blob: 71514c7aa004de1b37c9f9c8ea44c8d84ec662b2 [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"
46#include "ol_txrx_ctrl_api.h"
47#include "wlan_tgt_def_config.h"
48
Nirav Shahcbc6d722016-03-01 16:24:53 +053049#include "qdf_nbuf.h"
Anurag Chouhan6d760662016-02-20 16:05:43 +053050#include "qdf_types.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080051#include "ol_txrx_api.h"
Anurag Chouhan600c3a02016-03-01 10:33:54 +053052#include "qdf_mem.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080053#include "ol_txrx_types.h"
54#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 */
680WLAN_PHY_MODE wma_chan_to_mode(u8 chan, phy_ch_width chan_width,
681 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;
1146 tpCSAOffloadParams csa_offload_event;
1147 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;
1179 csa_offload_event->switchmode = csa_ie->switchmode;
1180 } 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;
1184 csa_offload_event->switchmode = 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
1256 /* wma puts 4 bytes prefix for msg subtype, so length
1257 * of data received from target should be 4 bytes less
1258 * then max allowed
1259 */
1260 if (datalen > (OEM_DATA_RSP_SIZE - 4)) {
1261 WMA_LOGE("%s: Received data len (%d) exceeds max value (%d)",
1262 __func__, datalen, (OEM_DATA_RSP_SIZE - 4));
1263 return -EINVAL;
1264 }
1265
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301266 pStartOemDataRsp = qdf_mem_malloc(sizeof(*pStartOemDataRsp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001267 if (!pStartOemDataRsp) {
1268 WMA_LOGE("%s: Failed to alloc pStartOemDataRsp", __func__);
1269 return -ENOMEM;
1270 }
1271
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301272 qdf_mem_zero(pStartOemDataRsp, sizeof(tStartOemDataRsp));
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001273 pStartOemDataRsp->target_rsp = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001274 msg_subtype = (uint32_t *) (&pStartOemDataRsp->oemDataRsp[0]);
1275 *msg_subtype = WMI_OEM_CAPABILITY_RSP;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301276 qdf_mem_copy(&pStartOemDataRsp->oemDataRsp[4], data, datalen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001277
1278 WMA_LOGI("%s: Sending WMA_START_OEM_DATA_RSP, data len (%d)",
1279 __func__, datalen);
1280
1281 wma_send_msg(wma, WMA_START_OEM_DATA_RSP, (void *)pStartOemDataRsp, 0);
1282 return 0;
1283}
1284
1285/**
1286 * wma_oem_measurement_report_event_callback() - OEM measurement report handler
1287 * @handle: wma handle
1288 * @datap: data ptr
1289 * @len: data length
1290 *
1291 * Return: 0 for success or error code
1292 */
1293int wma_oem_measurement_report_event_callback(void *handle,
1294 uint8_t *datap,
1295 uint32_t len)
1296{
1297 tp_wma_handle wma = (tp_wma_handle) handle;
1298 WMI_OEM_MEASUREMENT_REPORT_EVENTID_param_tlvs *param_buf;
1299 uint8_t *data;
1300 uint32_t datalen;
1301 uint32_t *msg_subtype;
1302 tStartOemDataRsp *pStartOemDataRsp;
1303
1304 param_buf = (WMI_OEM_MEASUREMENT_REPORT_EVENTID_param_tlvs *) datap;
1305 if (!param_buf) {
1306 WMA_LOGE("%s: Received NULL buf ptr from FW", __func__);
1307 return -ENOMEM;
1308 }
1309
1310 data = param_buf->data;
1311 datalen = param_buf->num_data;
1312
1313 if (!data) {
1314 WMA_LOGE("%s: Received NULL data from FW", __func__);
1315 return -EINVAL;
1316 }
1317
1318 /* wma puts 4 bytes prefix for msg subtype, so length
1319 * of data received from target should be 4 bytes less
1320 * then max allowed
1321 */
1322 if (datalen > (OEM_DATA_RSP_SIZE - 4)) {
1323 WMA_LOGE("%s: Received data len (%d) exceeds max value (%d)",
1324 __func__, datalen, (OEM_DATA_RSP_SIZE - 4));
1325 return -EINVAL;
1326 }
1327
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301328 pStartOemDataRsp = qdf_mem_malloc(sizeof(*pStartOemDataRsp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001329 if (!pStartOemDataRsp) {
1330 WMA_LOGE("%s: Failed to alloc pStartOemDataRsp", __func__);
1331 return -ENOMEM;
1332 }
1333
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301334 qdf_mem_zero(pStartOemDataRsp, sizeof(tStartOemDataRsp));
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001335 pStartOemDataRsp->target_rsp = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001336 msg_subtype = (uint32_t *) (&pStartOemDataRsp->oemDataRsp[0]);
1337 *msg_subtype = WMI_OEM_MEASUREMENT_RSP;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301338 qdf_mem_copy(&pStartOemDataRsp->oemDataRsp[4], data, datalen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001339
1340 WMA_LOGI("%s: Sending WMA_START_OEM_DATA_RSP, data len (%d)",
1341 __func__, datalen);
1342
1343 wma_send_msg(wma, WMA_START_OEM_DATA_RSP, (void *)pStartOemDataRsp, 0);
1344 return 0;
1345}
1346
1347/**
1348 * wma_oem_error_report_event_callback() - OEM error report handler
1349 * @handle: wma handle
1350 * @datap: data ptr
1351 * @len: data length
1352 *
1353 * Return: 0 for success or error code
1354 */
1355int wma_oem_error_report_event_callback(void *handle,
1356 uint8_t *datap, uint32_t len)
1357{
1358 tp_wma_handle wma = (tp_wma_handle) handle;
1359 WMI_OEM_ERROR_REPORT_EVENTID_param_tlvs *param_buf;
1360 uint8_t *data;
1361 uint32_t datalen;
1362 uint32_t *msg_subtype;
1363 tStartOemDataRsp *pStartOemDataRsp;
1364
1365 param_buf = (WMI_OEM_ERROR_REPORT_EVENTID_param_tlvs *) datap;
1366 if (!param_buf) {
1367 WMA_LOGE("%s: Received NULL buf ptr from FW", __func__);
1368 return -ENOMEM;
1369 }
1370
1371 data = param_buf->data;
1372 datalen = param_buf->num_data;
1373
1374 if (!data) {
1375 WMA_LOGE("%s: Received NULL data from FW", __func__);
1376 return -EINVAL;
1377 }
1378
1379 /* wma puts 4 bytes prefix for msg subtype, so length
1380 * of data received from target should be 4 bytes less
1381 * then max allowed
1382 */
1383 if (datalen > (OEM_DATA_RSP_SIZE - 4)) {
1384 WMA_LOGE("%s: Received data len (%d) exceeds max value (%d)",
1385 __func__, datalen, (OEM_DATA_RSP_SIZE - 4));
1386 return -EINVAL;
1387 }
1388
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301389 pStartOemDataRsp = qdf_mem_malloc(sizeof(*pStartOemDataRsp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001390 if (!pStartOemDataRsp) {
1391 WMA_LOGE("%s: Failed to alloc pStartOemDataRsp", __func__);
1392 return -ENOMEM;
1393 }
1394
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301395 qdf_mem_zero(pStartOemDataRsp, sizeof(tStartOemDataRsp));
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001396 pStartOemDataRsp->target_rsp = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001397 msg_subtype = (uint32_t *) (&pStartOemDataRsp->oemDataRsp[0]);
1398 *msg_subtype = WMI_OEM_ERROR_REPORT_RSP;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301399 qdf_mem_copy(&pStartOemDataRsp->oemDataRsp[4], data, datalen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001400
1401 WMA_LOGI("%s: Sending WMA_START_OEM_DATA_RSP, data len (%d)",
1402 __func__, datalen);
1403
1404 wma_send_msg(wma, WMA_START_OEM_DATA_RSP, (void *)pStartOemDataRsp, 0);
1405 return 0;
1406}
1407
1408/**
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001409 * wma_oem_data_response_handler() - OEM data response event handler
1410 * @handle: wma handle
1411 * @datap: data ptr
1412 * @len: data length
1413 *
1414 * Return: 0 for success or error code
1415 */
1416int wma_oem_data_response_handler(void *handle,
1417 uint8_t *datap, uint32_t len)
1418{
1419 tp_wma_handle wma = (tp_wma_handle) handle;
1420 WMI_OEM_RESPONSE_EVENTID_param_tlvs *param_buf;
1421 uint8_t *data;
1422 uint32_t datalen;
1423 tStartOemDataRsp *oem_data_rsp;
1424
1425 param_buf = (WMI_OEM_RESPONSE_EVENTID_param_tlvs *) datap;
1426 if (!param_buf) {
1427 WMA_LOGE(FL("Received NULL buf ptr from FW"));
1428 return -ENOMEM;
1429 }
1430
1431 data = param_buf->data;
1432 datalen = param_buf->num_data;
1433
1434 if (!data) {
1435 WMA_LOGE(FL("Received NULL data from FW"));
1436 return -EINVAL;
1437 }
1438
1439 if (datalen > OEM_DATA_RSP_SIZE) {
1440 WMA_LOGE(FL("Received data len %d exceeds max value %d"),
1441 datalen, OEM_DATA_RSP_SIZE);
1442 return -EINVAL;
1443 }
1444
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301445 oem_data_rsp = qdf_mem_malloc(sizeof(*oem_data_rsp));
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001446 if (!oem_data_rsp) {
1447 WMA_LOGE(FL("Failed to alloc oem_data_rsp"));
1448 return -ENOMEM;
1449 }
1450
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301451 qdf_mem_zero(oem_data_rsp, sizeof(tStartOemDataRsp));
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001452 oem_data_rsp->target_rsp = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301453 qdf_mem_copy(&oem_data_rsp->oemDataRsp[0], data, datalen);
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001454
1455 WMA_LOGI(FL("Sending WMA_START_OEM_DATA_RSP, data len %d"), datalen);
1456
1457 wma_send_msg(wma, WMA_START_OEM_DATA_RSP, (void *)oem_data_rsp, 0);
1458 return 0;
1459}
1460
1461/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001462 * wma_start_oem_data_req() - start OEM data request to target
1463 * @wma_handle: wma handle
1464 * @startOemDataReq: start request params
1465 *
1466 * Return: none
1467 */
1468void wma_start_oem_data_req(tp_wma_handle wma_handle,
1469 tStartOemDataReq *startOemDataReq)
1470{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001471 int ret = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001472 tStartOemDataRsp *pStartOemDataRsp;
1473
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001474 WMA_LOGD(FL("Send OEM Data Request to target"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001475
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001476 if (!startOemDataReq && !startOemDataReq->data) {
1477 WMA_LOGE(FL("startOemDataReq is null"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001478 goto out;
1479 }
1480
1481 if (!wma_handle || !wma_handle->wmi_handle) {
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001482 WMA_LOGE(FL("WMA - closed, can not send Oem data request cmd"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001483 return;
1484 }
1485
Govind Singhaa64c242016-03-08 11:31:49 +05301486 ret = wmi_unified_start_oem_data_cmd(wma_handle->wmi_handle,
1487 startOemDataReq->data_len,
1488 startOemDataReq->data);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001489
1490 if (ret != EOK) {
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001491 WMA_LOGE(FL(":wmi cmd send failed"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001492 }
1493
1494out:
1495 /* free oem data req buffer received from UMAC */
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001496 if (startOemDataReq) {
1497 if (startOemDataReq->data)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301498 qdf_mem_free(startOemDataReq->data);
1499 qdf_mem_free(startOemDataReq);
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001500 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001501
1502 /* Now send data resp back to PE/SME with message sub-type of
1503 * WMI_OEM_INTERNAL_RSP. This is required so that PE/SME clears
1504 * up pending active command. Later when desired oem response(s)
1505 * comes as wmi event from target then those shall be passed
1506 * to oem application
1507 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301508 pStartOemDataRsp = qdf_mem_malloc(sizeof(*pStartOemDataRsp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001509 if (!pStartOemDataRsp) {
1510 WMA_LOGE("%s:failed to allocate memory for OEM Data Resp to PE",
1511 __func__);
1512 return;
1513 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301514 qdf_mem_zero(pStartOemDataRsp, sizeof(tStartOemDataRsp));
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001515 pStartOemDataRsp->target_rsp = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001516
1517 WMA_LOGI("%s: Sending WMA_START_OEM_DATA_RSP to clear up PE/SME pending cmd",
1518 __func__);
1519
1520 wma_send_msg(wma_handle, WMA_START_OEM_DATA_RSP,
1521 (void *)pStartOemDataRsp, 0);
1522
1523 return;
1524}
1525#endif /* FEATURE_OEM_DATA_SUPPORT */
1526
1527
1528/**
1529 * wma_unified_dfs_radar_rx_event_handler() - dfs radar rx event handler
1530 * @handle: wma handle
1531 * @data: data buffer
1532 * @datalen: data length
1533 *
1534 * WMI handler for WMI_DFS_RADAR_EVENTID
1535 * This handler is registered for handling
1536 * filtered DFS Phyerror. This handler is
1537 * will be invoked only when DFS Phyerr
1538 * filtering offload is enabled.
1539 *
1540 * Return: 1 for Success and 0 for error
1541 */
1542static int wma_unified_dfs_radar_rx_event_handler(void *handle,
1543 uint8_t *data,
1544 uint32_t datalen)
1545{
1546 tp_wma_handle wma = (tp_wma_handle) handle;
1547 struct ieee80211com *ic;
1548 struct ath_dfs *dfs;
1549 struct dfs_event *event;
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05301550 struct dfs_ieee80211_channel *chan;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001551 int empty;
1552 int do_check_chirp = 0;
1553 int is_hw_chirp = 0;
1554 int is_sw_chirp = 0;
1555 int is_pri = 0;
1556
1557 WMI_DFS_RADAR_EVENTID_param_tlvs *param_tlvs;
1558 wmi_dfs_radar_event_fixed_param *radar_event;
1559
1560 ic = wma->dfs_ic;
1561 if (NULL == ic) {
1562 WMA_LOGE("%s: dfs_ic is NULL ", __func__);
1563 return 0;
1564 }
1565
1566 dfs = (struct ath_dfs *)ic->ic_dfs;
1567 param_tlvs = (WMI_DFS_RADAR_EVENTID_param_tlvs *) data;
1568
1569 if (NULL == dfs) {
1570 WMA_LOGE("%s: dfs is NULL ", __func__);
1571 return 0;
1572 }
1573 /*
1574 * This parameter holds the number
1575 * of phyerror interrupts to the host
1576 * after the phyerrors have passed through
1577 * false detect filters in the firmware.
1578 */
1579 dfs->dfs_phyerr_count++;
1580
1581 if (!param_tlvs) {
1582 WMA_LOGE("%s: Received NULL data from FW", __func__);
1583 return 0;
1584 }
1585
1586 radar_event = param_tlvs->fixed_param;
1587
Anurag Chouhana37b5b72016-02-21 14:53:42 +05301588 qdf_spin_lock_bh(&ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001589 chan = ic->ic_curchan;
Edhar, Mahesh Kumar35d9b2e2015-10-26 17:06:23 +05301590 if (ic->disable_phy_err_processing) {
1591 WMA_LOGD("%s: radar indication done,drop phyerror event",
1592 __func__);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05301593 qdf_spin_unlock_bh(&ic->chan_lock);
Edhar, Mahesh Kumar35d9b2e2015-10-26 17:06:23 +05301594 return 0;
1595 }
1596
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001597 if (CHANNEL_STATE_DFS != cds_get_channel_state(chan->ic_ieee)) {
1598 WMA_LOGE
1599 ("%s: Invalid DFS Phyerror event. Channel=%d is Non-DFS",
1600 __func__, chan->ic_ieee);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05301601 qdf_spin_unlock_bh(&ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001602 return 0;
1603 }
1604
Anurag Chouhana37b5b72016-02-21 14:53:42 +05301605 qdf_spin_unlock_bh(&ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001606 dfs->ath_dfs_stats.total_phy_errors++;
1607
1608 if (dfs->dfs_caps.ath_chip_is_bb_tlv) {
1609 do_check_chirp = 1;
1610 is_pri = 1;
1611 is_hw_chirp = radar_event->pulse_is_chirp;
1612
1613 if ((uint32_t) dfs->dfs_phyerr_freq_min >
1614 radar_event->pulse_center_freq) {
1615 dfs->dfs_phyerr_freq_min =
1616 (int)radar_event->pulse_center_freq;
1617 }
1618
1619 if (dfs->dfs_phyerr_freq_max <
1620 (int)radar_event->pulse_center_freq) {
1621 dfs->dfs_phyerr_freq_max =
1622 (int)radar_event->pulse_center_freq;
1623 }
1624 }
1625
1626 /*
1627 * Now, add the parsed, checked and filtered
1628 * radar phyerror event radar pulse event list.
1629 * This event will then be processed by
1630 * dfs_radar_processevent() to see if the pattern
1631 * of pulses in radar pulse list match any radar
1632 * singnature in the current regulatory domain.
1633 */
1634
1635 ATH_DFSEVENTQ_LOCK(dfs);
1636 empty = STAILQ_EMPTY(&(dfs->dfs_eventq));
1637 ATH_DFSEVENTQ_UNLOCK(dfs);
1638 if (empty) {
1639 return 0;
1640 }
1641 /*
1642 * Add the event to the list, if there's space.
1643 */
1644 ATH_DFSEVENTQ_LOCK(dfs);
1645 event = STAILQ_FIRST(&(dfs->dfs_eventq));
1646 if (event == NULL) {
1647 ATH_DFSEVENTQ_UNLOCK(dfs);
1648 WMA_LOGE("%s: No more space left for queuing DFS Phyerror events",
1649 __func__);
1650 return 0;
1651 }
1652 STAILQ_REMOVE_HEAD(&(dfs->dfs_eventq), re_list);
1653 ATH_DFSEVENTQ_UNLOCK(dfs);
1654 dfs->dfs_phyerr_queued_count++;
1655 dfs->dfs_phyerr_w53_counter++;
1656 event->re_dur = (uint8_t) radar_event->pulse_duration;
1657 event->re_rssi = radar_event->rssi;
1658 event->re_ts = radar_event->pulse_detect_ts & DFS_TSMASK;
1659 event->re_full_ts = (((uint64_t) radar_event->upload_fullts_high) << 32)
1660 | radar_event->upload_fullts_low;
1661
1662 /*
1663 * Index of peak magnitude
1664 */
1665 event->sidx = radar_event->peak_sidx;
1666
1667 /*
1668 * Handle chirp flags.
1669 */
1670 if (do_check_chirp) {
1671 event->re_flags |= DFS_EVENT_CHECKCHIRP;
1672 if (is_hw_chirp) {
1673 event->re_flags |= DFS_EVENT_HW_CHIRP;
1674 }
1675 if (is_sw_chirp) {
1676 event->re_flags |= DFS_EVENT_SW_CHIRP;
1677 }
1678 }
1679 /*
1680 * Correctly set which channel is being reported on
1681 */
1682 if (is_pri) {
1683 event->re_chanindex = (uint8_t) dfs->dfs_curchan_radindex;
1684 } else {
1685 if (dfs->dfs_extchan_radindex == -1) {
1686 WMA_LOGI("%s phyerr on ext channel", __func__);
1687 }
1688 event->re_chanindex = (uint8_t) dfs->dfs_extchan_radindex;
1689 WMA_LOGI("%s:New extension channel event is added to queue",
1690 __func__);
1691 }
1692
1693 ATH_DFSQ_LOCK(dfs);
1694
1695 STAILQ_INSERT_TAIL(&(dfs->dfs_radarq), event, re_list);
1696
1697 empty = STAILQ_EMPTY(&dfs->dfs_radarq);
1698
1699 ATH_DFSQ_UNLOCK(dfs);
1700
1701 if (!empty && !dfs->ath_radar_tasksched) {
1702 dfs->ath_radar_tasksched = 1;
1703 OS_SET_TIMER(&dfs->ath_dfs_task_timer, 0);
1704 }
1705
1706 return 1;
1707
1708}
1709
1710/**
1711 * wma_unified_phyerr_rx_event_handler() - phyerr event handler
1712 * @handle: wma handle
1713 * @data: data buffer
1714 * @datalen: buffer length
1715 *
1716 * WMI Handler for WMI_PHYERR_EVENTID event from firmware.
1717 * This handler is currently handling only DFS phy errors.
1718 * This handler will be invoked only when the DFS phyerror
1719 * filtering offload is disabled.
1720 *
1721 * Return: 1:Success, 0:Failure
1722 */
1723static int wma_unified_phyerr_rx_event_handler(void *handle,
1724 uint8_t *data, uint32_t datalen)
1725{
1726 tp_wma_handle wma = (tp_wma_handle) handle;
1727 WMI_PHYERR_EVENTID_param_tlvs *param_tlvs;
1728 wmi_comb_phyerr_rx_hdr *pe_hdr;
1729 uint8_t *bufp;
1730 wmi_single_phyerr_rx_event *ev;
1731 struct ieee80211com *ic = wma->dfs_ic;
Anurag Chouhan6d760662016-02-20 16:05:43 +05301732 qdf_size_t n;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001733 A_UINT64 tsf64 = 0;
1734 int phy_err_code = 0;
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08001735 A_UINT32 phy_err_mask = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001736 int error = 0;
1737 tpAniSirGlobal mac_ctx =
Anurag Chouhan6d760662016-02-20 16:05:43 +05301738 (tpAniSirGlobal)cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001739 bool enable_log = false;
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08001740 int max_dfs_buf_length = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001741
1742 if (NULL == mac_ctx) {
1743 WMA_LOGE("%s: mac_ctx is NULL", __func__);
1744 return 0;
1745 }
1746 enable_log = mac_ctx->sap.enable_dfs_phy_error_logs;
1747
1748 param_tlvs = (WMI_PHYERR_EVENTID_param_tlvs *) data;
1749
1750 if (!param_tlvs) {
1751 WMA_LOGE("%s: Received NULL data from FW", __func__);
1752 return 0;
1753 }
1754
1755 pe_hdr = param_tlvs->hdr;
1756 if (pe_hdr == NULL) {
1757 WMA_LOGE("%s: Received Data PE Header is NULL", __func__);
1758 return 0;
1759 }
1760
1761 /* Ensure it's at least the size of the header */
1762 if (datalen < sizeof(*pe_hdr)) {
1763 WMA_LOGE("%s: Expected minimum size %zu, received %d",
1764 __func__, sizeof(*pe_hdr), datalen);
1765 return 0;
1766 }
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08001767 /*
1768 * The max buffer lenght is larger for DFS-3 than DFS-2.
1769 * So, accordingly use the correct max buffer size.
1770 */
1771 if (wma->hw_bd_id != WMI_HWBD_QCA6174)
1772 max_dfs_buf_length = DFS3_MAX_BUF_LENGTH;
1773 else
1774 max_dfs_buf_length = DFS_MAX_BUF_LENGTH;
1775
1776 if (pe_hdr->buf_len > max_dfs_buf_length) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001777 WMA_LOGE("%s: Received Invalid Phyerror event buffer length = %d"
1778 "Maximum allowed buf length = %d", __func__,
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08001779 pe_hdr->buf_len, max_dfs_buf_length);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001780
1781 return 0;
1782 }
1783
1784 /*
1785 * Reconstruct the 64 bit event TSF. This isn't from the MAC, it's
1786 * at the time the event was sent to us, the TSF value will be
1787 * in the future.
1788 */
1789 tsf64 = pe_hdr->tsf_l32;
1790 tsf64 |= (((uint64_t) pe_hdr->tsf_u32) << 32);
1791
1792 /*
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08001793 * Check the HW board ID to figure out
1794 * if DFS-3 is supported. In DFS-3
1795 * phyerror mask indicates the type of
1796 * phyerror, whereas in DFS-2 phyerrorcode
1797 * indicates the type of phyerror. If the
1798 * board is NOT WMI_HWBD_QCA6174, for now
1799 * assume that it supports DFS-3.
1800 */
1801 if (wma->hw_bd_id != WMI_HWBD_QCA6174) {
1802 phy_err_mask = pe_hdr->rsPhyErrMask0;
1803 WMA_LOGD("%s: DFS-3 phyerror mask = 0x%x",
1804 __func__, phy_err_mask);
1805 }
1806
1807 /*
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001808 * Loop over the bufp, extracting out phyerrors
1809 * wmi_unified_comb_phyerr_rx_event.bufp is a char pointer,
1810 * which isn't correct here - what we have received here
1811 * is an array of TLV-style PHY errors.
1812 */
1813 n = 0; /* Start just after the header */
1814 bufp = param_tlvs->bufp;
1815 while (n < pe_hdr->buf_len) {
1816 /* ensure there's at least space for the header */
1817 if ((pe_hdr->buf_len - n) < sizeof(ev->hdr)) {
1818 WMA_LOGE("%s: Not enough space.(datalen=%d, n=%zu, hdr=%zu bytes",
1819 __func__, pe_hdr->buf_len, n, sizeof(ev->hdr));
1820 error = 1;
1821 break;
1822 }
1823 /*
1824 * Obtain a pointer to the beginning of the current event.
1825 * data[0] is the beginning of the WMI payload.
1826 */
1827 ev = (wmi_single_phyerr_rx_event *) &bufp[n];
1828
1829 /*
1830 * Sanity check the buffer length of the event against
1831 * what we currently have.
1832 * Since buf_len is 32 bits, we check if it overflows
1833 * a large 32 bit value. It's not 0x7fffffff because
1834 * we increase n by (buf_len + sizeof(hdr)), which would
1835 * in itself cause n to overflow.
1836 * If "int" is 64 bits then this becomes a moot point.
1837 */
1838 if (ev->hdr.buf_len > 0x7f000000) {
1839 WMA_LOGE("%s:buf_len is garbage (0x%x)", __func__,
1840 ev->hdr.buf_len);
1841 error = 1;
1842 break;
1843 }
1844 if (n + ev->hdr.buf_len > pe_hdr->buf_len) {
1845 WMA_LOGE("%s: buf_len exceeds available space n=%zu,"
1846 "buf_len=%d, datalen=%d",
1847 __func__, n, ev->hdr.buf_len, pe_hdr->buf_len);
1848 error = 1;
1849 break;
1850 }
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08001851 /*
1852 * If the board id is WMI_HWBD_QCA6174
1853 * then it supports only DFS-2. So, fetch
1854 * phyerror code in order to know the type
1855 * of phyerror.
1856 */
1857 if (wma->hw_bd_id == WMI_HWBD_QCA6174) {
1858 phy_err_code = WMI_UNIFIED_PHYERRCODE_GET(&ev->hdr);
1859 WMA_LOGD("%s: DFS-2 phyerror code = 0x%x",
1860 __func__, phy_err_code);
1861 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001862
1863 /*
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08001864 * phy_err_code is set for DFS-2 and phy_err_mask
1865 * is set for DFS-3. Checking both to support
1866 * compatability for older platforms.
1867 * If the phyerror or phyerrmask category matches,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001868 * pass radar events to the dfs pattern matching code.
1869 * Don't pass radar events with no buffer payload.
1870 */
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08001871 if (((phy_err_mask & WMI_PHY_ERROR_MASK0_RADAR) ||
1872 (phy_err_mask & WMI_PHY_ERROR_MASK0_FALSE_RADAR_EXT)) ||
1873 (phy_err_code == WMA_DFS2_PHYERROR_CODE ||
1874 phy_err_code == WMA_DFS2_FALSE_RADAR_EXT)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001875 if (ev->hdr.buf_len > 0) {
1876 /* Calling in to the DFS module to process the phyerr */
1877 dfs_process_phyerr(ic, &ev->bufp[0],
1878 ev->hdr.buf_len,
1879 WMI_UNIFIED_RSSI_COMB_GET
1880 (&ev->hdr) & 0xff,
1881 /* Extension RSSI */
1882 WMI_UNIFIED_RSSI_COMB_GET
1883 (&ev->hdr) & 0xff,
1884 ev->hdr.tsf_timestamp,
1885 tsf64, enable_log);
1886 }
1887 }
1888
1889 /*
1890 * Advance the buffer pointer to the next PHY error.
1891 * buflen is the length of this payload, so we need to
1892 * advance past the current header _AND_ the payload.
1893 */
1894 n += sizeof(*ev) + ev->hdr.buf_len;
1895
1896 } /*end while() */
1897 if (error)
1898 return 0;
1899 else
1900 return 1;
1901}
1902
1903/**
1904 * wma_register_dfs_event_handler() - register dfs event handler
1905 * @wma_handle: wma handle
1906 *
1907 * Register appropriate dfs phyerror event handler
1908 * based on phyerror filtering offload is enabled
1909 * or disabled.
1910 *
1911 * Return: none
1912 */
1913void wma_register_dfs_event_handler(tp_wma_handle wma_handle)
1914{
1915 if (NULL == wma_handle) {
1916 WMA_LOGE("%s:wma_handle is NULL", __func__);
1917 return;
1918 }
1919
1920 if (false == wma_handle->dfs_phyerr_filter_offload) {
1921 /*
1922 * Register the wma_unified_phyerr_rx_event_handler
1923 * for filtering offload disabled case to handle
1924 * the DFS phyerrors.
1925 */
1926 WMA_LOGD("%s:Phyerror Filtering offload is Disabled in ini",
1927 __func__);
1928 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Govind Singhd76a5b02016-03-08 15:12:14 +05301929 WMI_PHYERR_EVENTID,
1930 wma_unified_phyerr_rx_event_handler,
1931 WMA_RX_WORK_CTX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001932 WMA_LOGD("%s: WMI_PHYERR_EVENTID event handler registered",
1933 __func__);
1934 } else {
1935 WMA_LOGD("%s:Phyerror Filtering offload is Enabled in ini",
1936 __func__);
1937 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Govind Singhd76a5b02016-03-08 15:12:14 +05301938 WMI_DFS_RADAR_EVENTID,
1939 wma_unified_dfs_radar_rx_event_handler,
1940 WMA_RX_WORK_CTX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001941 WMA_LOGD("%s:WMI_DFS_RADAR_EVENTID event handler registered",
1942 __func__);
1943 }
1944
1945 return;
1946}
1947
1948
1949/**
1950 * wma_unified_dfs_phyerr_filter_offload_enable() - enable dfs phyerr filter
1951 * @wma_handle: wma handle
1952 *
1953 * Send WMI_DFS_PHYERR_FILTER_ENA_CMDID or
1954 * WMI_DFS_PHYERR_FILTER_DIS_CMDID command
1955 * to firmware based on phyerr filtering
1956 * offload status.
1957 *
1958 * Return: 1 success, 0 failure
1959 */
1960int
1961wma_unified_dfs_phyerr_filter_offload_enable(tp_wma_handle wma_handle)
1962{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001963 int ret;
1964
1965 if (NULL == wma_handle) {
1966 WMA_LOGE("%s:wma_handle is NULL", __func__);
1967 return 0;
1968 }
1969
Govind Singhaa64c242016-03-08 11:31:49 +05301970 ret = wmi_unified_dfs_phyerr_filter_offload_en_cmd(wma_handle->wmi_handle,
1971 wma_handle->dfs_phyerr_filter_offload);
1972 if (ret)
1973 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001974
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001975
Govind Singhaa64c242016-03-08 11:31:49 +05301976 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001977}
1978
1979#if !defined(REMOVE_PKT_LOG)
1980/**
1981 * wma_pktlog_wmi_send_cmd() - send pktlog enable/disable command to target
1982 * @handle: wma handle
1983 * @params: pktlog params
1984 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05301985 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001986 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301987QDF_STATUS wma_pktlog_wmi_send_cmd(WMA_HANDLE handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001988 struct ath_pktlog_wmi_params *params)
1989{
1990 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Govind Singhaa64c242016-03-08 11:31:49 +05301991 int ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001992
1993 /*Check if packet log is enabled in cfg.ini */
1994 if (!cds_is_packet_log_enabled()) {
1995 WMA_LOGE("%s:pkt log is not enabled in cfg.ini", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301996 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001997 }
1998
Govind Singhaa64c242016-03-08 11:31:49 +05301999 ret = wmi_unified_pktlog_wmi_send_cmd(wma_handle->wmi_handle,
2000 params->pktlog_event,
2001 params->cmd_id);
2002 if (ret)
2003 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002004
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002005
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302006 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002007}
2008#endif /* REMOVE_PKT_LOG */
2009
2010static void wma_send_status_to_suspend_ind(tp_wma_handle wma, bool suspended)
2011{
2012 tSirReadyToSuspendInd *ready_to_suspend;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302013 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002014 cds_msg_t cds_msg;
2015 uint8_t len;
2016
2017 WMA_LOGD("Posting ready to suspend indication to umac");
2018
2019 len = sizeof(tSirReadyToSuspendInd);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302020 ready_to_suspend = (tSirReadyToSuspendInd *) qdf_mem_malloc(len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002021
2022 if (NULL == ready_to_suspend) {
2023 WMA_LOGE("%s: Memory allocation failure", __func__);
2024 return;
2025 }
2026
2027 ready_to_suspend->mesgType = eWNI_SME_READY_TO_SUSPEND_IND;
2028 ready_to_suspend->mesgLen = len;
2029 ready_to_suspend->suspended = suspended;
2030
2031 cds_msg.type = eWNI_SME_READY_TO_SUSPEND_IND;
2032 cds_msg.bodyptr = (void *)ready_to_suspend;
2033 cds_msg.bodyval = 0;
2034
2035 status = cds_mq_post_message(CDS_MQ_ID_SME, &cds_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302036 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002037 WMA_LOGE("Failed to post ready to suspend");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302038 qdf_mem_free(ready_to_suspend);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002039 }
2040}
2041
2042/**
2043 * wma_wow_wake_reason_str() - Converts wow wakeup reason code to text format
2044 * @wake_reason - WOW wake reason
2045 *
2046 * Return: reason code in string format
2047 */
2048static const u8 *wma_wow_wake_reason_str(A_INT32 wake_reason)
2049{
2050 switch (wake_reason) {
2051 case WOW_REASON_UNSPECIFIED:
2052 return "UNSPECIFIED";
2053 case WOW_REASON_NLOD:
2054 return "NLOD";
2055 case WOW_REASON_AP_ASSOC_LOST:
2056 return "AP_ASSOC_LOST";
2057 case WOW_REASON_LOW_RSSI:
2058 return "LOW_RSSI";
2059 case WOW_REASON_DEAUTH_RECVD:
2060 return "DEAUTH_RECVD";
2061 case WOW_REASON_DISASSOC_RECVD:
2062 return "DISASSOC_RECVD";
2063 case WOW_REASON_GTK_HS_ERR:
2064 return "GTK_HS_ERR";
2065 case WOW_REASON_EAP_REQ:
2066 return "EAP_REQ";
2067 case WOW_REASON_FOURWAY_HS_RECV:
2068 return "FOURWAY_HS_RECV";
2069 case WOW_REASON_TIMER_INTR_RECV:
2070 return "TIMER_INTR_RECV";
2071 case WOW_REASON_PATTERN_MATCH_FOUND:
2072 return "PATTERN_MATCH_FOUND";
2073 case WOW_REASON_RECV_MAGIC_PATTERN:
2074 return "RECV_MAGIC_PATTERN";
2075 case WOW_REASON_P2P_DISC:
2076 return "P2P_DISC";
2077#ifdef FEATURE_WLAN_LPHB
2078 case WOW_REASON_WLAN_HB:
2079 return "WLAN_HB";
2080#endif /* FEATURE_WLAN_LPHB */
2081
2082 case WOW_REASON_CSA_EVENT:
2083 return "CSA_EVENT";
2084 case WOW_REASON_PROBE_REQ_WPS_IE_RECV:
2085 return "PROBE_REQ_RECV";
2086 case WOW_REASON_AUTH_REQ_RECV:
2087 return "AUTH_REQ_RECV";
2088 case WOW_REASON_ASSOC_REQ_RECV:
2089 return "ASSOC_REQ_RECV";
2090 case WOW_REASON_HTT_EVENT:
2091 return "WOW_REASON_HTT_EVENT";
2092#ifdef FEATURE_WLAN_RA_FILTERING
2093 case WOW_REASON_RA_MATCH:
2094 return "WOW_REASON_RA_MATCH";
2095#endif /* FEATURE_WLAN_RA_FILTERING */
2096 case WOW_REASON_BEACON_RECV:
2097 return "WOW_REASON_IBSS_BEACON_RECV";
2098#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
2099 case WOW_REASON_HOST_AUTO_SHUTDOWN:
2100 return "WOW_REASON_HOST_AUTO_SHUTDOWN";
2101#endif /* FEATURE_WLAN_AUTO_SHUTDOWN */
2102#ifdef WLAN_FEATURE_ROAM_OFFLOAD
2103 case WOW_REASON_ROAM_HO:
2104 return "WOW_REASON_ROAM_HO";
2105#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
2106#ifdef FEATURE_WLAN_EXTSCAN
2107 case WOW_REASON_EXTSCAN:
2108 return "WOW_REASON_EXTSCAN";
2109#endif
2110 case WOW_REASON_RSSI_BREACH_EVENT:
2111 return "WOW_REASON_RSSI_BREACH_EVENT";
Srinivas Girigowdae80cea92015-11-23 11:33:57 -08002112 case WOW_REASON_NLO_SCAN_COMPLETE:
2113 return "WOW_REASON_NLO_SCAN_COMPLETE";
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002114 }
2115 return "unknown";
2116}
2117
2118/**
2119 * wma_wow_wake_up_stats_display() - display wow wake up stats
2120 * @wma: Pointer to wma handle
2121 *
2122 * Return: none
2123 */
2124static void wma_wow_wake_up_stats_display(tp_wma_handle wma)
2125{
2126 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",
2127 wma->wow_ucast_wake_up_count,
2128 wma->wow_bcast_wake_up_count,
2129 wma->wow_ipv4_mcast_wake_up_count,
2130 wma->wow_ipv6_mcast_wake_up_count,
2131 wma->wow_ipv6_mcast_ra_stats,
2132 wma->wow_ipv6_mcast_ns_stats,
2133 wma->wow_ipv6_mcast_na_stats,
2134 wma->wow_pno_match_wake_up_count,
2135 wma->wow_pno_complete_wake_up_count,
2136 wma->wow_gscan_wake_up_count,
2137 wma->wow_low_rssi_wake_up_count,
2138 wma->wow_rssi_breach_wake_up_count);
2139
2140 return;
2141}
2142
2143/**
2144 * wma_wow_ipv6_mcast_stats() - ipv6 mcast wake up stats
2145 * @wma: Pointer to wma handle
2146 * @data: Pointer to pattern match data
2147 *
2148 * Return: none
2149 */
2150static void wma_wow_ipv6_mcast_stats(tp_wma_handle wma, uint8_t *data)
2151{
2152 static const uint8_t ipv6_mcast[] = {0x86, 0xDD};
2153
2154 if (!memcmp(ipv6_mcast, (data + WMA_ETHER_TYPE_OFFSET),
2155 sizeof(ipv6_mcast))) {
2156 if (WMA_ICMP_V6_HEADER_TYPE ==
2157 *(data + WMA_ICMP_V6_HEADER_OFFSET)) {
2158 if (WMA_ICMP_V6_RA_TYPE ==
2159 *(data + WMA_ICMP_V6_TYPE_OFFSET))
2160 wma->wow_ipv6_mcast_ra_stats++;
2161 else if (WMA_ICMP_V6_NS_TYPE ==
2162 *(data + WMA_ICMP_V6_TYPE_OFFSET))
2163 wma->wow_ipv6_mcast_ns_stats++;
2164 else if (WMA_ICMP_V6_NA_TYPE ==
2165 *(data + WMA_ICMP_V6_TYPE_OFFSET))
2166 wma->wow_ipv6_mcast_na_stats++;
2167 else
2168 WMA_LOGA("ICMP V6 type : 0x%x",
2169 *(data + WMA_ICMP_V6_TYPE_OFFSET));
2170 } else {
2171 WMA_LOGA("ICMP_V6 header 0x%x",
2172 *(data + WMA_ICMP_V6_HEADER_OFFSET));
2173 }
2174 } else {
2175 WMA_LOGA("Ethertype x%x:0x%x",
2176 *(data + WMA_ETHER_TYPE_OFFSET),
2177 *(data + WMA_ETHER_TYPE_OFFSET + 1));
2178 }
2179
2180 return;
2181}
2182
2183/**
2184 * wma_wow_wake_up_stats() - maintain wow pattern match wake up stats
2185 * @wma: Pointer to wma handle
2186 * @data: Pointer to pattern match data
2187 * @len: Pattern match data length
2188 * @event: Wake up event
2189 *
2190 * Return: none
2191 */
2192static void wma_wow_wake_up_stats(tp_wma_handle wma, uint8_t *data,
2193 int32_t len, WOW_WAKE_REASON_TYPE event)
2194{
2195 switch (event) {
2196
2197 case WOW_REASON_PATTERN_MATCH_FOUND:
2198 if (WMA_BCAST_MAC_ADDR == *data) {
2199 wma->wow_bcast_wake_up_count++;
2200 } else if (WMA_MCAST_IPV4_MAC_ADDR == *data) {
2201 wma->wow_ipv4_mcast_wake_up_count++;
2202 } else if (WMA_MCAST_IPV6_MAC_ADDR == *data) {
2203 wma->wow_ipv6_mcast_wake_up_count++;
2204 if (len > WMA_ICMP_V6_TYPE_OFFSET)
2205 wma_wow_ipv6_mcast_stats(wma, data);
2206 else
2207 WMA_LOGA("ICMP_V6 data len %d", len);
2208 } else {
2209 wma->wow_ucast_wake_up_count++;
2210 }
2211 break;
2212
2213 case WOW_REASON_RA_MATCH:
2214 wma->wow_ipv6_mcast_ra_stats++;
2215 break;
2216
2217 case WOW_REASON_NLOD:
2218 wma->wow_pno_match_wake_up_count++;
2219 break;
2220
2221 case WOW_REASON_NLO_SCAN_COMPLETE:
2222 wma->wow_pno_complete_wake_up_count++;
2223 break;
2224
2225 case WOW_REASON_LOW_RSSI:
2226 wma->wow_low_rssi_wake_up_count++;
2227 break;
2228
2229 case WOW_REASON_EXTSCAN:
2230 wma->wow_gscan_wake_up_count++;
2231 break;
2232
2233 case WOW_REASON_RSSI_BREACH_EVENT:
2234 wma->wow_rssi_breach_wake_up_count++;
2235 break;
2236
2237 default:
2238 WMA_LOGE("Unknown wake up reason");
2239 break;
2240 }
2241
2242 wma_wow_wake_up_stats_display(wma);
2243 return;
2244}
2245
2246/**
2247 * wma_wow_wakeup_host_event() - wakeup host event handler
2248 * @handle: wma handle
2249 * @event: event data
2250 * @len: buffer length
2251 *
2252 * Handler to catch wow wakeup host event. This event will have
2253 * reason why the firmware has woken the host.
2254 *
2255 * Return: 0 for success or error
2256 */
2257int wma_wow_wakeup_host_event(void *handle, uint8_t *event,
2258 uint32_t len)
2259{
2260 tp_wma_handle wma = (tp_wma_handle) handle;
2261 WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs *param_buf;
2262 WOW_EVENT_INFO_fixed_param *wake_info;
2263#ifdef FEATURE_WLAN_SCAN_PNO
2264 struct wma_txrx_node *node;
2265#endif /* FEATURE_WLAN_SCAN_PNO */
2266 uint32_t wake_lock_duration = 0;
2267 uint32_t wow_buf_pkt_len = 0;
2268
2269 param_buf = (WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs *) event;
2270 if (!param_buf) {
2271 WMA_LOGE("Invalid wow wakeup host event buf");
2272 return -EINVAL;
2273 }
2274
2275 wake_info = param_buf->fixed_param;
2276
2277 WMA_LOGA("WOW wakeup host event received (reason: %s(%d)) for vdev %d",
2278 wma_wow_wake_reason_str(wake_info->wake_reason),
2279 wake_info->wake_reason, wake_info->vdev_id);
2280
Anurag Chouhance0dc992016-02-16 18:18:03 +05302281 qdf_event_set(&wma->wma_resume_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002282
2283 switch (wake_info->wake_reason) {
2284 case WOW_REASON_AUTH_REQ_RECV:
2285 wake_lock_duration = WMA_AUTH_REQ_RECV_WAKE_LOCK_TIMEOUT;
2286 break;
2287
2288 case WOW_REASON_ASSOC_REQ_RECV:
2289 wake_lock_duration = WMA_ASSOC_REQ_RECV_WAKE_LOCK_DURATION;
2290 break;
2291
2292 case WOW_REASON_DEAUTH_RECVD:
2293 wake_lock_duration = WMA_DEAUTH_RECV_WAKE_LOCK_DURATION;
2294 break;
2295
2296 case WOW_REASON_DISASSOC_RECVD:
2297 wake_lock_duration = WMA_DISASSOC_RECV_WAKE_LOCK_DURATION;
2298 break;
2299
2300 case WOW_REASON_AP_ASSOC_LOST:
2301 wake_lock_duration = WMA_BMISS_EVENT_WAKE_LOCK_DURATION;
2302 WMA_LOGA("Beacon miss indication on vdev %x",
2303 wake_info->vdev_id);
2304 wma_beacon_miss_handler(wma, wake_info->vdev_id);
2305 break;
2306#ifdef FEATURE_WLAN_RA_FILTERING
2307 case WOW_REASON_RA_MATCH:
2308 wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_RA_MATCH);
2309 break;
2310#endif /* FEATURE_WLAN_RA_FILTERING */
2311#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
2312 case WOW_REASON_HOST_AUTO_SHUTDOWN:
2313 wake_lock_duration = WMA_AUTO_SHUTDOWN_WAKE_LOCK_DURATION;
2314 WMA_LOGA("Received WOW Auto Shutdown trigger in suspend");
2315 if (wma_post_auto_shutdown_msg())
2316 return -EINVAL;
2317 break;
2318#endif /* FEATURE_WLAN_AUTO_SHUTDOWN */
2319#ifdef FEATURE_WLAN_SCAN_PNO
2320 case WOW_REASON_NLOD:
2321 wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_NLOD);
2322 node = &wma->interfaces[wake_info->vdev_id];
2323 if (node) {
2324 WMA_LOGD("NLO match happened");
2325 node->nlo_match_evt_received = true;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302326 qdf_wake_lock_timeout_acquire(&wma->pno_wake_lock,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002327 WMA_PNO_MATCH_WAKE_LOCK_TIMEOUT,
2328 WIFI_POWER_EVENT_WAKELOCK_PNO);
Srinivas Girigowdae80cea92015-11-23 11:33:57 -08002329 }
2330 break;
2331
2332 case WOW_REASON_NLO_SCAN_COMPLETE:
2333 {
2334 WMI_NLO_SCAN_COMPLETE_EVENTID_param_tlvs param;
2335
2336 WMA_LOGD("Host woken up due to pno scan complete reason");
2337
2338 /* First 4-bytes of wow_packet_buffer is the length */
2339 if (param_buf->wow_packet_buffer) {
2340 param.fixed_param = (wmi_nlo_event *)
2341 (param_buf->wow_packet_buffer + 4);
2342 wma_nlo_scan_cmp_evt_handler(handle,
2343 (u_int8_t *)&param, sizeof(param));
2344 } else
2345 WMA_LOGD("No wow_packet_buffer present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002346 }
2347 break;
2348#endif /* FEATURE_WLAN_SCAN_PNO */
2349
2350 case WOW_REASON_CSA_EVENT:
2351 {
2352 WMI_CSA_HANDLING_EVENTID_param_tlvs param;
2353 WMA_LOGD("Host woken up because of CSA IE");
2354 param.fixed_param = (wmi_csa_event_fixed_param *)
2355 (((uint8_t *) wake_info)
2356 + sizeof(WOW_EVENT_INFO_fixed_param)
2357 + WOW_CSA_EVENT_OFFSET);
2358 wma_csa_offload_handler(handle, (uint8_t *) &param,
2359 sizeof(param));
2360 }
2361 break;
2362
2363#ifdef FEATURE_WLAN_LPHB
2364 case WOW_REASON_WLAN_HB:
2365 wma_lphb_handler(wma, (uint8_t *) param_buf->hb_indevt);
2366 break;
2367#endif /* FEATURE_WLAN_LPHB */
2368
2369 case WOW_REASON_HTT_EVENT:
2370 break;
2371 case WOW_REASON_PATTERN_MATCH_FOUND:
2372 wma_wow_wake_up_stats_display(wma);
2373 WMA_LOGD("Wake up for Rx packet, dump starting from ethernet hdr");
2374 if (param_buf->wow_packet_buffer) {
2375 /* First 4-bytes of wow_packet_buffer is the length */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302376 qdf_mem_copy((uint8_t *) &wow_buf_pkt_len,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002377 param_buf->wow_packet_buffer, 4);
2378 wma_wow_wake_up_stats(wma,
2379 param_buf->wow_packet_buffer + 4,
2380 wow_buf_pkt_len,
2381 WOW_REASON_PATTERN_MATCH_FOUND);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302382 qdf_trace_hex_dump(QDF_MODULE_ID_WMA,
2383 QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002384 param_buf->wow_packet_buffer + 4,
2385 wow_buf_pkt_len);
2386 } else {
2387 WMA_LOGE("No wow packet buffer present");
2388 }
2389 break;
2390
2391 case WOW_REASON_LOW_RSSI:
2392 {
2393 /* WOW_REASON_LOW_RSSI is used for all roaming events.
2394 * WMI_ROAM_REASON_BETTER_AP, WMI_ROAM_REASON_BMISS,
2395 * WMI_ROAM_REASON_SUITABLE_AP will be handled by
2396 * wma_roam_event_callback().
2397 */
2398 WMI_ROAM_EVENTID_param_tlvs param;
2399 wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_LOW_RSSI);
2400 if (param_buf->wow_packet_buffer) {
2401 /* Roam event is embedded in wow_packet_buffer */
2402 WMA_LOGD("Host woken up because of roam event");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302403 qdf_mem_copy((uint8_t *) &wow_buf_pkt_len,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002404 param_buf->wow_packet_buffer, 4);
2405 WMA_LOGD("wow_packet_buffer dump");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302406 qdf_trace_hex_dump(QDF_MODULE_ID_WMA,
2407 QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002408 param_buf->wow_packet_buffer,
2409 wow_buf_pkt_len);
2410 if (wow_buf_pkt_len >= sizeof(param)) {
2411 param.fixed_param =
2412 (wmi_roam_event_fixed_param *)
2413 (param_buf->wow_packet_buffer + 4);
2414 wma_roam_event_callback(handle,
2415 (uint8_t *) &
2416 param,
2417 sizeof(param));
2418 } else {
2419 WMA_LOGE("Wrong length for roam event = %d bytes",
2420 wow_buf_pkt_len);
2421 }
2422 } else {
2423 /* No wow_packet_buffer means a better AP beacon
2424 * will follow in a later event.
2425 */
2426 WMA_LOGD("Host woken up because of better AP beacon");
2427 }
2428 break;
2429 }
2430 case WOW_REASON_CLIENT_KICKOUT_EVENT:
2431 {
2432 WMI_PEER_STA_KICKOUT_EVENTID_param_tlvs param;
2433 if (param_buf->wow_packet_buffer) {
2434 /* station kickout event embedded in wow_packet_buffer */
2435 WMA_LOGD("Host woken up because of sta_kickout event");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302436 qdf_mem_copy((u_int8_t *) &wow_buf_pkt_len,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002437 param_buf->wow_packet_buffer, 4);
2438 WMA_LOGD("wow_packet_buffer dump");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302439 qdf_trace_hex_dump(QDF_MODULE_ID_WMA,
2440 QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002441 param_buf->wow_packet_buffer, wow_buf_pkt_len);
2442 if (wow_buf_pkt_len >= sizeof(param)) {
2443 param.fixed_param = (wmi_peer_sta_kickout_event_fixed_param *)
2444 (param_buf->wow_packet_buffer + 4);
2445 wma_peer_sta_kickout_event_handler(handle,
2446 (u_int8_t *)&param, sizeof(param));
2447 } else {
2448 WMA_LOGE("Wrong length for sta_kickout event = %d bytes",
2449 wow_buf_pkt_len);
2450 }
2451 } else {
2452 WMA_LOGD("No wow_packet_buffer present");
2453 }
2454 break;
2455 }
2456#ifdef FEATURE_WLAN_EXTSCAN
2457 case WOW_REASON_EXTSCAN:
2458 WMA_LOGD("Host woken up because of extscan reason");
2459 wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_EXTSCAN);
2460 if (param_buf->wow_packet_buffer) {
2461 wow_buf_pkt_len =
2462 *(uint32_t *)param_buf->wow_packet_buffer;
2463 wma_extscan_wow_event_callback(handle,
2464 (u_int8_t *)(param_buf->wow_packet_buffer + 4),
2465 wow_buf_pkt_len);
2466 } else
2467 WMA_LOGE("wow_packet_buffer is empty");
2468 break;
2469#endif
2470 case WOW_REASON_RSSI_BREACH_EVENT:
2471 {
2472 WMI_RSSI_BREACH_EVENTID_param_tlvs param;
2473
2474 wma_wow_wake_up_stats(wma, NULL, 0,
2475 WOW_REASON_RSSI_BREACH_EVENT);
2476 WMA_LOGD("Host woken up because of rssi breach reason");
2477 /* rssi breach event is embedded in wow_packet_buffer */
2478 if (param_buf->wow_packet_buffer) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302479 qdf_mem_copy((u_int8_t *) &wow_buf_pkt_len,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002480 param_buf->wow_packet_buffer, 4);
2481 if (wow_buf_pkt_len >= sizeof(param)) {
2482 param.fixed_param =
2483 (wmi_rssi_breach_event_fixed_param *)
2484 (param_buf->wow_packet_buffer + 4);
2485 wma_rssi_breached_event_handler(handle,
2486 (u_int8_t *)&param,
2487 sizeof(param));
2488 } else {
2489 WMA_LOGE("%s: Wrong length: %d bytes",
2490 __func__, wow_buf_pkt_len);
2491 }
2492 } else
2493 WMA_LOGD("No wow_packet_buffer present");
2494 }
2495 break;
2496 default:
2497 break;
2498 }
2499
2500 if (wake_lock_duration) {
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302501 qdf_wake_lock_timeout_acquire(&wma->wow_wake_lock,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002502 wake_lock_duration,
2503 WIFI_POWER_EVENT_WAKELOCK_WOW);
2504 WMA_LOGA("Holding %d msec wake_lock", wake_lock_duration);
2505 }
2506
2507 return 0;
2508}
2509
2510/**
2511 * wma_pdev_resume_event_handler() - PDEV resume event handler
2512 * @handle: wma handle
2513 * @event: event data
2514 * @len: buffer length
2515 *
2516 * Return: 0 for success or error
2517 */
2518int wma_pdev_resume_event_handler(void *handle, uint8_t *event, uint32_t len)
2519{
2520 tp_wma_handle wma = (tp_wma_handle) handle;
2521
2522 WMA_LOGA("Received PDEV resume event");
2523
Anurag Chouhance0dc992016-02-16 18:18:03 +05302524 qdf_event_set(&wma->wma_resume_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002525
2526 return 0;
2527}
2528/**
2529 * wma_set_wow_bus_suspend() - set suspend flag
2530 * @wma: wma handle
2531 * @val: value
2532 *
2533 * Return: none
2534 */
2535static inline void wma_set_wow_bus_suspend(tp_wma_handle wma, int val)
2536{
2537
Anurag Chouhan8e0ccd32016-02-19 15:30:20 +05302538 qdf_atomic_set(&wma->is_wow_bus_suspended, val);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002539}
2540
2541
2542
2543/**
2544 * wma_add_wow_wakeup_event() - Configures wow wakeup events.
2545 * @wma: wma handle
2546 * @vdev_id: vdev id
2547 * @bitmap: Event bitmap
2548 * @enable: enable/disable
2549 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302550 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002551 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302552static QDF_STATUS wma_add_wow_wakeup_event(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002553 uint32_t vdev_id,
2554 uint32_t bitmap,
2555 bool enable)
2556{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002557 int ret;
2558
Govind Singhaa64c242016-03-08 11:31:49 +05302559 ret = wmi_unified_add_wow_wakeup_event_cmd(wma->wmi_handle, vdev_id,
2560 enable, bitmap);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002561 if (ret) {
2562 WMA_LOGE("Failed to config wow wakeup event");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302563 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002564 }
2565
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302566 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002567}
2568
2569/**
2570 * wma_send_wow_patterns_to_fw() - Sends WOW patterns to FW.
2571 * @wma: wma handle
2572 * @vdev_id: vdev id
2573 * @ptrn_id: pattern id
2574 * @ptrn: pattern
2575 * @ptrn_len: pattern length
2576 * @ptrn_offset: pattern offset
2577 * @mask: mask
2578 * @mask_len: mask length
2579 * @user: true for user configured pattern and false for default pattern
2580 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302581 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002582 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302583static QDF_STATUS wma_send_wow_patterns_to_fw(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002584 uint8_t vdev_id, uint8_t ptrn_id,
2585 const uint8_t *ptrn, uint8_t ptrn_len,
2586 uint8_t ptrn_offset, const uint8_t *mask,
2587 uint8_t mask_len, bool user)
2588{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002589 struct wma_txrx_node *iface;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002590 int ret;
Govind Singhaa64c242016-03-08 11:31:49 +05302591 uint8_t default_patterns;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002592
2593 iface = &wma->interfaces[vdev_id];
Govind Singhaa64c242016-03-08 11:31:49 +05302594 default_patterns = iface->num_wow_default_patterns++;
2595 ret = wmi_unified_wow_patterns_to_fw_cmd(wma->wmi_handle,
2596 vdev_id, ptrn_id, ptrn,
2597 ptrn_len, ptrn_offset, mask,
2598 mask_len, user, default_patterns);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002599 if (ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002600 if (!user)
2601 iface->num_wow_default_patterns--;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302602 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002603 }
2604
2605 if (user)
2606 iface->num_wow_user_patterns++;
2607
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302608 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002609}
2610
2611/**
2612 * wma_wow_ap() - set WOW patterns in ap mode
2613 * @wma: wma handle
2614 * @vdev_id: vdev id
2615 *
2616 * Configures default WOW pattern for the given vdev_id which is in AP mode.
2617 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302618 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002619 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302620static QDF_STATUS wma_wow_ap(tp_wma_handle wma, uint8_t vdev_id)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002621{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302622 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002623 uint8_t arp_offset = 20;
2624 uint8_t mac_mask[IEEE80211_ADDR_LEN];
2625
2626 /* Setup unicast pkt pattern */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302627 qdf_mem_set(&mac_mask, IEEE80211_ADDR_LEN, 0xFF);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002628 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
2629 wma->interfaces[vdev_id].addr,
2630 IEEE80211_ADDR_LEN, 0, mac_mask,
2631 IEEE80211_ADDR_LEN, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302632 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002633 WMA_LOGE("Failed to add WOW unicast pattern ret %d", ret);
2634 return ret;
2635 }
2636
2637 /*
2638 * Setup all ARP pkt pattern. This is dummy pattern hence the length
2639 * is zero
2640 */
2641 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
2642 arp_ptrn, 0, arp_offset, arp_mask, 0, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302643 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002644 WMA_LOGE("Failed to add WOW ARP pattern ret %d", ret);
2645 return ret;
2646 }
2647
2648 return ret;
2649}
2650
2651/**
2652 * wma_wow_sta() - set WOW patterns in sta mode
2653 * @wma: wma handle
2654 * @vdev_id: vdev id
2655 *
2656 * Configures default WOW pattern for the given vdev_id which is in sta mode.
2657 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302658 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002659 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302660static QDF_STATUS wma_wow_sta(tp_wma_handle wma, uint8_t vdev_id)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002661{
2662 uint8_t arp_offset = 12;
2663 uint8_t discvr_offset = 30;
2664 uint8_t mac_mask[IEEE80211_ADDR_LEN];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302665 QDF_STATUS ret = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002666
2667 /* Setup unicast pkt pattern */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302668 qdf_mem_set(&mac_mask, IEEE80211_ADDR_LEN, 0xFF);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002669 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
2670 wma->interfaces[vdev_id].addr,
2671 IEEE80211_ADDR_LEN, 0, mac_mask,
2672 IEEE80211_ADDR_LEN, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302673 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002674 WMA_LOGE("Failed to add WOW unicast pattern ret %d", ret);
2675 return ret;
2676 }
2677
2678 /*
2679 * Setup multicast pattern for mDNS 224.0.0.251,
2680 * SSDP 239.255.255.250 and LLMNR 224.0.0.252
2681 */
2682 if (wma->ssdp) {
2683 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
2684 discvr_ptrn, sizeof(discvr_ptrn), discvr_offset,
2685 discvr_mask, sizeof(discvr_ptrn), false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302686 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002687 WMA_LOGE("Failed to add WOW mDNS/SSDP/LLMNR pattern");
2688 return ret;
2689 }
2690 } else
2691 WMA_LOGD("mDNS, SSDP, LLMNR patterns are disabled from ini");
2692
2693 /* when arp offload or ns offloaded is disabled
2694 * from ini file, configure broad cast arp pattern
2695 * to fw, so that host can wake up
2696 */
2697 if (!(wma->ol_ini_info & 0x1)) {
2698 /* Setup all ARP pkt pattern */
2699 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
2700 arp_ptrn, sizeof(arp_ptrn), arp_offset,
2701 arp_mask, sizeof(arp_mask), false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302702 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002703 WMA_LOGE("Failed to add WOW ARP pattern");
2704 return ret;
2705 }
2706 }
2707
2708 /* for NS or NDP offload packets */
2709 if (!(wma->ol_ini_info & 0x2)) {
2710 /* Setup all NS pkt pattern */
2711 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
2712 ns_ptrn, sizeof(arp_ptrn), arp_offset,
2713 arp_mask, sizeof(arp_mask), false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302714 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002715 WMA_LOGE("Failed to add WOW NS pattern");
2716 return ret;
2717 }
2718 }
2719
2720 return ret;
2721}
2722
2723/**
2724 * wma_register_wow_default_patterns() - register default wow patterns with fw
2725 * @handle: Pointer to wma handle
2726 * @vdev_id: vdev id
2727 *
2728 * WoW default wake up pattern rule is:
2729 * - For STA & P2P CLI mode register for same STA specific wow patterns
2730 * - For SAP/P2P GO & IBSS mode register for same SAP specific wow patterns
2731 *
2732 * Return: none
2733 */
2734void wma_register_wow_default_patterns(WMA_HANDLE handle, uint8_t vdev_id)
2735{
2736 tp_wma_handle wma = handle;
2737 struct wma_txrx_node *iface;
2738
2739 if (vdev_id > wma->max_bssid) {
2740 WMA_LOGE("Invalid vdev id %d", vdev_id);
2741 return;
2742 }
2743 iface = &wma->interfaces[vdev_id];
2744
2745 if (iface->ptrn_match_enable) {
Houston Hoffman79b4af22015-10-06 12:01:08 -07002746 if (wma_is_vdev_in_beaconning_mode(wma, vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002747 /* Configure SAP/GO/IBSS mode default wow patterns */
2748 WMA_LOGI("Config SAP specific default wow patterns vdev_id %d",
2749 vdev_id);
2750 wma_wow_ap(wma, vdev_id);
2751 } else {
2752 /* Configure STA/P2P CLI mode default wow patterns */
2753 WMA_LOGI("Config STA specific default wow patterns vdev_id %d",
2754 vdev_id);
2755 wma_wow_sta(wma, vdev_id);
2756 if (wma->IsRArateLimitEnabled) {
2757 WMA_LOGI("Config STA RA limit wow patterns vdev_id %d",
2758 vdev_id);
2759 wma_wow_sta_ra_filter(wma, vdev_id);
2760 }
2761 }
2762 }
2763
2764 return;
2765}
2766
2767/**
2768 * wma_register_wow_wakeup_events() - register vdev specific wake events with fw
2769 * @handle: Pointer to wma handle
2770 * @vdev_id: vdev Id
2771 * @vdev_type: vdev type
2772 * @vdev_subtype: vdev sub type
2773 *
2774 * WoW wake up event rule is following:
2775 * 1) STA mode and P2P CLI mode wake up events are same
2776 * 2) SAP mode and P2P GO mode wake up events are same
2777 * 3) IBSS mode wake events are same as STA mode plus WOW_BEACON_EVENT
2778 *
2779 * Return: none
2780 */
2781void wma_register_wow_wakeup_events(WMA_HANDLE handle,
2782 uint8_t vdev_id,
2783 uint8_t vdev_type,
2784 uint8_t vdev_subtype)
2785{
2786 tp_wma_handle wma = handle;
2787 uint32_t event_bitmap;
2788
2789 WMA_LOGI("vdev_type %d vdev_subtype %d vdev_id %d", vdev_type,
2790 vdev_subtype, vdev_id);
2791
2792 if ((WMI_VDEV_TYPE_STA == vdev_type) ||
2793 ((WMI_VDEV_TYPE_AP == vdev_type) &&
2794 (WMI_UNIFIED_VDEV_SUBTYPE_P2P_DEVICE == vdev_subtype))) {
2795 /* Configure STA/P2P CLI mode specific default wake up events */
2796 event_bitmap = WMA_WOW_STA_WAKE_UP_EVENTS;
2797 WMA_LOGI("STA specific default wake up event 0x%x vdev id %d",
2798 event_bitmap, vdev_id);
2799 } else if (WMI_VDEV_TYPE_IBSS == vdev_type) {
2800 /* Configure IBSS mode specific default wake up events */
2801 event_bitmap = (WMA_WOW_STA_WAKE_UP_EVENTS |
2802 (1 << WOW_BEACON_EVENT));
2803 WMA_LOGI("IBSS specific default wake up event 0x%x vdev id %d",
2804 event_bitmap, vdev_id);
2805 } else if (WMI_VDEV_TYPE_AP == vdev_type) {
2806 /* Configure SAP/GO mode specific default wake up events */
2807 event_bitmap = WMA_WOW_SAP_WAKE_UP_EVENTS;
2808 WMA_LOGI("SAP specific default wake up event 0x%x vdev id %d",
2809 event_bitmap, vdev_id);
2810 } else {
2811 WMA_LOGE("unknown type %d subtype %d", vdev_type, vdev_subtype);
2812 return;
2813 }
2814
2815 wma_add_wow_wakeup_event(wma, vdev_id, event_bitmap, true);
2816
2817 return;
2818}
2819
2820/**
2821 * wma_enable_disable_wakeup_event() - Configures wow wakeup events
2822 * @wma: wma handle
2823 * @vdev_id: vdev id
2824 * @bitmap: Event bitmap
2825 * @enable: enable/disable
2826 *
2827 * Return: none
2828 */
2829void wma_enable_disable_wakeup_event(WMA_HANDLE handle,
2830 uint32_t vdev_id,
2831 uint32_t bitmap,
2832 bool enable)
2833{
2834 tp_wma_handle wma = handle;
2835
2836 WMA_LOGI("vdev_id %d wake up event 0x%x enable %d",
2837 vdev_id, bitmap, enable);
2838 wma_add_wow_wakeup_event(wma, vdev_id, bitmap, enable);
2839}
2840
2841/**
2842 * wma_enable_wow_in_fw() - wnable wow in fw
2843 * @wma: wma handle
2844 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302845 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002846 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302847QDF_STATUS wma_enable_wow_in_fw(WMA_HANDLE handle)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002848{
2849 tp_wma_handle wma = handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002850 int ret;
Komal Seelam3d202862016-02-24 18:43:24 +05302851 struct hif_opaque_softc *scn;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002852 int host_credits;
2853 int wmi_pending_cmds;
Govind Singhd76a5b02016-03-08 15:12:14 +05302854 struct wow_cmd_params param = {0};
2855
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002856#ifdef CONFIG_CNSS
Anurag Chouhan6d760662016-02-20 16:05:43 +05302857 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002858
2859 if (NULL == pMac) {
2860 WMA_LOGE("%s: Unable to get PE context", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302861 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002862 }
2863#endif /* CONFIG_CNSS */
2864
Anurag Chouhance0dc992016-02-16 18:18:03 +05302865 qdf_event_reset(&wma->target_suspend);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002866 wma->wow_nack = 0;
2867
2868 host_credits = wmi_get_host_credits(wma->wmi_handle);
2869 wmi_pending_cmds = wmi_get_pending_cmds(wma->wmi_handle);
2870
2871 WMA_LOGD("Credits:%d; Pending_Cmds: %d",
2872 host_credits, wmi_pending_cmds);
2873
2874 if (host_credits < WMI_WOW_REQUIRED_CREDITS) {
2875 WMA_LOGE("%s: Host Doesn't have enough credits to Post WMI_WOW_ENABLE_CMDID! "
2876 "Credits:%d, pending_cmds:%d\n", __func__, host_credits,
2877 wmi_pending_cmds);
2878#ifndef QCA_WIFI_3_0_EMU
2879 goto error;
2880#endif
2881 }
2882
Govind Singhd76a5b02016-03-08 15:12:14 +05302883 param.enable = true;
2884 param.can_suspend_link = hif_can_suspend_link(wma->htc_handle);
2885 ret = wmi_unified_wow_enable_send(wma->wmi_handle, &param,
2886 WMA_WILDCARD_PDEV_ID);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002887 if (ret) {
2888 WMA_LOGE("Failed to enable wow in fw");
2889 goto error;
2890 }
2891
2892 wmi_set_target_suspend(wma->wmi_handle, true);
2893
Anurag Chouhance0dc992016-02-16 18:18:03 +05302894 if (qdf_wait_single_event(&wma->target_suspend,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002895 WMA_TGT_SUSPEND_COMPLETE_TIMEOUT)
Anurag Chouhance0dc992016-02-16 18:18:03 +05302896 != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002897 WMA_LOGE("Failed to receive WoW Enable Ack from FW");
2898 WMA_LOGE("Credits:%d; Pending_Cmds: %d",
2899 wmi_get_host_credits(wma->wmi_handle),
2900 wmi_get_pending_cmds(wma->wmi_handle));
Prashanth Bhatta9e143052015-12-04 11:56:47 -08002901 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002902#ifdef CONFIG_CNSS
Yue Ma455aff62015-10-20 18:29:16 -07002903 if (pMac->sme.enableSelfRecovery) {
2904 cds_trigger_recovery();
2905 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302906 QDF_BUG(0);
Yue Ma455aff62015-10-20 18:29:16 -07002907 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002908#else
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302909 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002910#endif /* CONFIG_CNSS */
Yue Ma455aff62015-10-20 18:29:16 -07002911 } else {
2912 WMA_LOGE("%s: LOGP is in progress, ignore!", __func__);
2913 }
2914
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002915 wmi_set_target_suspend(wma->wmi_handle, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302916 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002917 }
2918
2919 if (wma->wow_nack) {
2920 WMA_LOGE("FW not ready to WOW");
2921 wmi_set_target_suspend(wma->wmi_handle, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302922 return QDF_STATUS_E_AGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002923 }
2924
2925 host_credits = wmi_get_host_credits(wma->wmi_handle);
2926 wmi_pending_cmds = wmi_get_pending_cmds(wma->wmi_handle);
2927
2928 if (host_credits < WMI_WOW_REQUIRED_CREDITS) {
2929 WMA_LOGE("%s: No Credits after HTC ACK:%d, pending_cmds:%d, "
2930 "cannot resume back", __func__, host_credits,
2931 wmi_pending_cmds);
2932 htc_dump_counter_info(wma->htc_handle);
Prashanth Bhatta9e143052015-12-04 11:56:47 -08002933 if (!cds_is_driver_recovering())
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302934 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002935 else
2936 WMA_LOGE("%s: SSR in progress, ignore no credit issue",
2937 __func__);
2938 }
2939
2940 WMA_LOGD("WOW enabled successfully in fw: credits:%d"
2941 "pending_cmds: %d", host_credits, wmi_pending_cmds);
2942
Anurag Chouhan6d760662016-02-20 16:05:43 +05302943 scn = cds_get_context(QDF_MODULE_ID_HIF);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002944
2945 if (scn == NULL) {
2946 WMA_LOGE("%s: Failed to get HIF context", __func__);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302947 QDF_ASSERT(0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302948 return QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002949 }
2950
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002951 wma->wow.wow_enable_cmd_sent = true;
2952
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302953 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002954
2955error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302956 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002957}
2958
2959/**
2960 * wma_resume_req() - clear configured wow patterns in fw
2961 * @wma: wma handle
Houston Hoffmana76591b2015-11-10 16:52:05 -08002962 * @type: type of suspend
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002963 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302964 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002965 */
Anurag Chouhan6d760662016-02-20 16:05:43 +05302966QDF_STATUS wma_resume_req(tp_wma_handle wma, enum qdf_suspend_type type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002967{
Anurag Chouhan6d760662016-02-20 16:05:43 +05302968 if (type == QDF_SYSTEM_SUSPEND) {
Houston Hoffmana76591b2015-11-10 16:52:05 -08002969 wma->no_of_resume_ind++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002970
Houston Hoffmana76591b2015-11-10 16:52:05 -08002971 if (wma->no_of_resume_ind < wma_get_vdev_count(wma))
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302972 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002973
Houston Hoffmana76591b2015-11-10 16:52:05 -08002974 wma->no_of_resume_ind = 0;
2975 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002976
2977 /* Reset the DTIM Parameters */
2978 wma_set_resume_dtim(wma);
2979 /* need to reset if hif_pci_suspend_fails */
2980 wma_set_wow_bus_suspend(wma, 0);
2981 /* unpause the vdev if left paused and hif_pci_suspend fails */
2982 wma_unpause_vdev(wma);
2983
Houston Hoffman1460fa32015-11-18 02:36:30 -08002984 wmi_set_runtime_pm_inprogress(wma->wmi_handle, false);
2985
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302986 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002987}
2988
2989/**
2990 * wma_wow_delete_pattern() - delete wow pattern in target
2991 * @wma: wma handle
2992 * @ptrn_id: pattern id
2993 * @vdev_id: vdev id
2994 * @user: true for user pattern and false for default pattern
2995 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302996 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002997 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302998static QDF_STATUS wma_wow_delete_pattern(tp_wma_handle wma, uint8_t ptrn_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002999 uint8_t vdev_id, bool user)
3000{
Govind Singhaa64c242016-03-08 11:31:49 +05303001
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003002 struct wma_txrx_node *iface;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003003 int ret;
3004
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003005 iface = &wma->interfaces[vdev_id];
Govind Singhaa64c242016-03-08 11:31:49 +05303006 ret = wmi_unified_wow_delete_pattern_cmd(wma->wmi_handle, ptrn_id,
3007 vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003008 if (ret) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303009 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003010 }
3011
3012 if (user)
3013 iface->num_wow_user_patterns--;
3014
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303015 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003016}
3017
3018/**
3019 * wma_wow_add_pattern() - add wow pattern in target
3020 * @wma: wma handle
3021 * @ptrn: wow pattern
3022 *
3023 * This function does following:
3024 * 1) Delete all default patterns of the vdev
3025 * 2) Add received wow patterns for given vdev in target.
3026 *
3027 * Target is responsible for caching wow patterns accross multiple
3028 * suspend/resumes until the pattern is deleted by user
3029 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303030 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003031 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303032QDF_STATUS wma_wow_add_pattern(tp_wma_handle wma, struct wow_add_pattern *ptrn)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003033{
3034 uint8_t id;
3035 uint8_t bit_to_check, pos;
3036 struct wma_txrx_node *iface;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303037 QDF_STATUS ret = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003038 uint8_t new_mask[SIR_WOWL_BCAST_PATTERN_MAX_SIZE];
3039
3040 if (ptrn->session_id > wma->max_bssid) {
3041 WMA_LOGE("Invalid vdev id (%d)", ptrn->session_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303042 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003043 }
3044
3045 iface = &wma->interfaces[ptrn->session_id];
3046
3047 /* clear all default patterns cofigured by wma */
3048 for (id = 0; id < iface->num_wow_default_patterns; id++)
3049 wma_wow_delete_pattern(wma, id, ptrn->session_id, false);
3050
3051 iface->num_wow_default_patterns = 0;
3052
3053 WMA_LOGI("Add user passed wow pattern id %d vdev id %d",
3054 ptrn->pattern_id, ptrn->session_id);
3055 /*
3056 * Convert received pattern mask value from bit representation
3057 * to byte representation.
3058 *
3059 * For example, received value from umac,
3060 *
3061 * Mask value : A1 (equivalent binary is "1010 0001")
3062 * Pattern value : 12:00:13:00:00:00:00:44
3063 *
3064 * The value which goes to FW after the conversion from this
3065 * function (1 in mask value will become FF and 0 will
3066 * become 00),
3067 *
3068 * Mask value : FF:00:FF:00:0:00:00:FF
3069 * Pattern value : 12:00:13:00:00:00:00:44
3070 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303071 qdf_mem_zero(new_mask, sizeof(new_mask));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003072 for (pos = 0; pos < ptrn->pattern_size; pos++) {
3073 bit_to_check = (WMA_NUM_BITS_IN_BYTE - 1) -
3074 (pos % WMA_NUM_BITS_IN_BYTE);
3075 bit_to_check = 0x1 << bit_to_check;
3076 if (ptrn->pattern_mask[pos / WMA_NUM_BITS_IN_BYTE] &
3077 bit_to_check)
3078 new_mask[pos] = WMA_WOW_PTRN_MASK_VALID;
3079 }
3080
3081 ret = wma_send_wow_patterns_to_fw(wma, ptrn->session_id,
3082 ptrn->pattern_id,
3083 ptrn->pattern, ptrn->pattern_size,
3084 ptrn->pattern_byte_offset, new_mask,
3085 ptrn->pattern_size, true);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303086 if (ret != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003087 WMA_LOGE("Failed to add wow pattern %d", ptrn->pattern_id);
3088
3089 return ret;
3090}
3091
3092/**
3093 * wma_wow_delete_user_pattern() - delete user configured wow pattern in target
3094 * @wma: wma handle
3095 * @ptrn: wow pattern
3096 *
3097 * This function does following:
3098 * 1) Deletes a particular user configured wow pattern in target
3099 * 2) After deleting all user wow patterns add default wow patterns
3100 * specific to that vdev.
3101 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303102 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003103 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303104QDF_STATUS wma_wow_delete_user_pattern(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003105 struct wow_delete_pattern *pattern)
3106{
3107 struct wma_txrx_node *iface;
3108
3109 if (pattern->session_id > wma->max_bssid) {
3110 WMA_LOGE("Invalid vdev id %d", pattern->session_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303111 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003112 }
3113
3114 iface = &wma->interfaces[pattern->session_id];
3115 if (iface->num_wow_user_patterns <= 0) {
3116 WMA_LOGE("No valid user pattern. Num user pattern %u vdev %d",
3117 iface->num_wow_user_patterns, pattern->session_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303118 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003119 }
3120
3121 WMA_LOGI("Delete user passed wow pattern id %d total user pattern %d",
3122 pattern->pattern_id, iface->num_wow_user_patterns);
3123
3124 wma_wow_delete_pattern(wma, pattern->pattern_id,
3125 pattern->session_id, true);
3126
3127 /* configure default patterns once all user patterns are deleted */
3128 if (!iface->num_wow_user_patterns)
3129 wma_register_wow_default_patterns(wma, pattern->session_id);
3130
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303131 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003132}
3133
3134/**
3135 * wma_wow_enter() - store enable/disable status for pattern
3136 * @wma: wma handle
3137 * @info: wow parameters
3138 *
3139 * Records pattern enable/disable status locally. This choice will
3140 * take effect when the driver enter into suspend state.
3141 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303142 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003143 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303144QDF_STATUS wma_wow_enter(tp_wma_handle wma, tpSirHalWowlEnterParams info)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003145{
3146 struct wma_txrx_node *iface;
3147
3148 WMA_LOGD("wow enable req received for vdev id: %d", info->sessionId);
3149
3150 if (info->sessionId > wma->max_bssid) {
3151 WMA_LOGE("Invalid vdev id (%d)", info->sessionId);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303152 qdf_mem_free(info);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303153 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003154 }
3155
3156 iface = &wma->interfaces[info->sessionId];
3157 iface->ptrn_match_enable = info->ucPatternFilteringEnable ?
3158 true : false;
3159 wma->wow.magic_ptrn_enable = info->ucMagicPktEnable ? true : false;
3160 wma->wow.deauth_enable = info->ucWowDeauthRcv ? true : false;
3161 wma->wow.disassoc_enable = info->ucWowDeauthRcv ? true : false;
3162 wma->wow.bmiss_enable = info->ucWowMaxMissedBeacons ? true : false;
3163
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303164 qdf_mem_free(info);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003165
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303166 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003167}
3168
3169/**
3170 * wma_wow_exit() - clear all wma states
3171 * @wma: wma handle
3172 * @info: wow params
3173 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303174 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003175 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303176QDF_STATUS wma_wow_exit(tp_wma_handle wma, tpSirHalWowlExitParams info)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003177{
3178 struct wma_txrx_node *iface;
3179
3180 WMA_LOGD("wow disable req received for vdev id: %d", info->sessionId);
3181
3182 if (info->sessionId > wma->max_bssid) {
3183 WMA_LOGE("Invalid vdev id (%d)", info->sessionId);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303184 qdf_mem_free(info);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303185 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003186 }
3187
3188 iface = &wma->interfaces[info->sessionId];
3189 iface->ptrn_match_enable = false;
3190 wma->wow.magic_ptrn_enable = false;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303191 qdf_mem_free(info);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003192
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303193 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003194}
3195
3196/**
Houston Hoffmana76591b2015-11-10 16:52:05 -08003197 * wma_calculate_and_update_conn_state(): calculate each interfaces conn state
3198 * @wma: validated wma handle
3199 *
3200 * Identifies any vdev that is up and not in ap mode as connected.
3201 * stores this in the interfaces conn_state varible.
3202 */
3203void wma_calculate_and_update_conn_state(tp_wma_handle wma)
3204{
3205 int i;
3206 for (i = 0; i < wma->max_bssid; i++) {
3207 wma->interfaces[i].conn_state =
3208 !!(wma->interfaces[i].vdev_up &&
3209 !wma_is_vdev_in_ap_mode(wma, i));
3210 }
3211}
3212
3213/**
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003214 * wma_update_conn_state(): synchronize wma & hdd
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003215 * @wma: wma handle
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003216 * @conn_state: boolean array to populate
3217 * @len: validation parameter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003218 *
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003219 * populate interfaces conn_state with true if the interface
3220 * is a connected client and wow will configure a pattern.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003221 */
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003222void wma_update_conn_state(tp_wma_handle wma, uint32_t conn_mask)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003223{
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003224 int i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003225 for (i = 0; i < wma->max_bssid; i++) {
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003226 if (conn_mask & (1 << i))
3227 wma->interfaces[i].conn_state = true;
3228 else
3229 wma->interfaces[i].conn_state = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003230 }
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003231
3232 if (wma->wow.magic_ptrn_enable)
3233 return;
3234
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003235 for (i = 0; i < wma->max_bssid; i++) {
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003236 if (!wma->interfaces[i].ptrn_match_enable)
3237 wma->interfaces[i].conn_state = false;
3238 }
3239}
3240
3241/**
3242 * wma_is_beaconning_vdev_up(): check if a beaconning vdev is up
3243 * @wma: wma handle
3244 *
3245 * Return TRUE if beaconning vdev is up
3246 */
3247static inline
3248bool wma_is_beaconning_vdev_up(tp_wma_handle wma)
3249{
3250 int i;
3251 for (i = 0; i < wma->max_bssid; i++) {
3252 if (wma_is_vdev_in_beaconning_mode(wma, i)
3253 && wma->interfaces[i].vdev_up)
3254 return true;
3255 }
3256 return false;
3257}
3258
3259/**
3260 * wma_support_wow_for_beaconing: wow query for beaconning
3261 * @wma: wma handle
3262 *
3263 * Need to configure wow to enable beaconning offload when
3264 * a beaconing vdev is up and beaonning offload is configured.
3265 *
3266 * Return: true if we need to enable wow for beaconning offload
3267 */
3268static inline
3269bool wma_support_wow_for_beaconing(tp_wma_handle wma)
3270{
3271 if (WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
3272 WMI_SERVICE_BEACON_OFFLOAD)) {
3273 if (wma_is_beaconning_vdev_up(wma))
3274 return true;
3275 }
3276 return false;
3277}
3278
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003279#ifdef FEATURE_WLAN_SCAN_PNO
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003280/**
3281 * wma_is_pnoscan_in_progress(): check if a pnoscan is in progress
3282 * @wma: wma handle
3283 * @vdev_id: vdev_id
3284 *
3285 * Return: TRUE/FALSE
3286 */
3287static inline
3288bool wma_is_pnoscan_in_progress(tp_wma_handle wma, int vdev_id)
3289{
3290 return wma->interfaces[vdev_id].pno_in_progress;
3291}
Houston Hoffman345fa402015-12-16 11:28:51 -08003292
3293/**
3294 * wma_is_pnoscan_match_found(): check if a scan match was found
3295 * @wma: wma handle
3296 * @vdev_id: vdev_id
3297 *
3298 * Return: TRUE/FALSE
3299 */
3300static inline
3301bool wma_is_pnoscan_match_found(tp_wma_handle wma, int vdev_id)
3302{
3303 return wma->interfaces[vdev_id].nlo_match_evt_received;
3304}
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003305#else
3306/**
3307 * wma_is_pnoscan_in_progress(): dummy
3308 *
Houston Hoffman345fa402015-12-16 11:28:51 -08003309 * Return: False since no pnoscan cannot be in progress
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003310 * when feature flag is not defined.
3311 */
3312bool wma_is_pnoscan_in_progress(tp_wma_handle wma, int vdev_id)
3313{
3314 return FALSE;
3315}
Houston Hoffman345fa402015-12-16 11:28:51 -08003316
3317/**
3318 * wma_is_pnoscan_match_found(): dummy
3319 * @wma: wma handle
3320 * @vdev_id: vdev_id
3321 *
3322 * Return: False since no pnoscan cannot occur
3323 * when feature flag is not defined.
3324 */
3325static inline
3326bool wma_is_pnoscan_match_found(tp_wma_handle wma, int vdev_id)
3327{
3328 return FALSE;
3329}
Houston Hoffman61667962015-12-15 20:15:41 -08003330#endif
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003331
3332#ifdef FEATURE_WLAN_EXTSCAN
3333static inline
3334/**
3335 * wma_is_extscan_in_progress(): check if an extscan is in progress
3336 * @wma: wma handle
3337 * @vdev_id: vdev_id
3338 *
3339 * Return: TRUE/FALSvE
3340 */
3341bool wma_is_extscan_in_progress(tp_wma_handle wma, int vdev_id)
3342{
3343 return wma->interfaces[vdev_id].extscan_in_progress;
3344}
3345#else
3346/**
3347 * wma_is_extscan_in_progress(): dummy
3348 *
3349 * Return: False since no extscan can be in progress
3350 * when feature flag is not defined.
3351 */
3352bool wma_is_extscan_in_progress(tp_wma_handle wma, int vdev_id)
3353{
3354 return false;
3355}
3356#endif
3357
3358/**
3359 * wma_is_wow_applicable(): should enable wow
3360 * @wma: wma handle
3361 *
3362 * Enable WOW if any one of the condition meets,
3363 * 1) Is any one of vdev in beaconning mode (in AP mode) ?
3364 * 2) Is any one of vdev in connected state (in STA mode) ?
3365 * 3) Is PNO in progress in any one of vdev ?
3366 * 4) Is Extscan in progress in any one of vdev ?
3367 *
3368 * Return: true if wma needs to configure wow.
3369 */
3370bool wma_is_wow_applicable(tp_wma_handle wma)
3371{
3372 int vdev_id;
3373 if (wma_support_wow_for_beaconing(wma)) {
3374 WMA_LOGD("vdev is in beaconning mode, enabling wow");
3375 return true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003376 }
3377
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003378 for (vdev_id = 0; vdev_id < wma->max_bssid; vdev_id++) {
3379 if (wma->interfaces[vdev_id].conn_state) {
3380 WMA_LOGD("STA is connected, enabling wow");
3381 return true;
3382 } else if (wma_is_pnoscan_in_progress(wma, vdev_id)) {
3383 WMA_LOGD("PNO is in progress, enabling wow");
3384 return true;
3385 } else if (wma_is_extscan_in_progress(wma, vdev_id)) {
3386 WMA_LOGD("EXT is in progress, enabling wow");
3387 return true;
3388 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003389 }
3390
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003391 WMA_LOGD("All vdev are in disconnected state and pno/extscan is not in progress, skipping wow");
3392 return true;
3393}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003394
Houston Hoffman345fa402015-12-16 11:28:51 -08003395/**
3396 * wma_configure_dynamic_wake_events(): configure dyanmic wake events
3397 * @wma: wma handle
3398 *
3399 * Some wake events need to be enabled dynamically. Controll those here.
3400 *
3401 * Return: none
3402 */
3403void wma_configure_dynamic_wake_events(tp_wma_handle wma)
3404{
3405 int vdev_id;
3406 int enable_mask;
3407 int disable_mask;
3408
3409 for (vdev_id = 0; vdev_id < wma->max_bssid; vdev_id++) {
3410 enable_mask = 0;
3411 disable_mask = 0;
3412
3413 if (wma_is_pnoscan_in_progress(wma, vdev_id)) {
3414 if (wma_is_pnoscan_match_found(wma, vdev_id))
3415 enable_mask |=
3416 (1 << WOW_NLO_SCAN_COMPLETE_EVENT);
3417 else
3418 disable_mask |=
3419 (1 << WOW_NLO_SCAN_COMPLETE_EVENT);
3420 }
3421
3422 if (enable_mask != 0)
3423 wma_enable_disable_wakeup_event(wma, vdev_id,
3424 enable_mask, true);
3425 if (disable_mask != 0)
3426 wma_enable_disable_wakeup_event(wma, vdev_id,
3427 disable_mask, false);
3428 }
3429}
3430
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003431#ifdef FEATURE_WLAN_LPHB
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003432/**
3433 * wma_apply_lphb(): apply cached LPHB settings
3434 * @wma: wma handle
3435 *
3436 * LPHB cache, if any item was enabled, should be
3437 * applied.
3438 */
3439static inline
3440void wma_apply_lphb(tp_wma_handle wma)
3441{
3442 int i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003443 WMA_LOGD("%s: checking LPHB cache", __func__);
3444 for (i = 0; i < 2; i++) {
3445 if (wma->wow.lphb_cache[i].params.lphbEnableReq.enable) {
3446 WMA_LOGD("%s: LPHB cache for item %d is marked as enable",
3447 __func__, i + 1);
3448 wma_lphb_conf_hbenable(wma, &(wma->wow.lphb_cache[i]),
3449 false);
3450 }
3451 }
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003452}
3453#else
3454void wma_apply_lphb(tp_wma_handle wma) {}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003455#endif /* FEATURE_WLAN_LPHB */
3456
Houston Hoffmana76591b2015-11-10 16:52:05 -08003457static void wma_notify_suspend_req_procesed(tp_wma_handle wma,
Anurag Chouhan6d760662016-02-20 16:05:43 +05303458 enum qdf_suspend_type type)
Houston Hoffmana76591b2015-11-10 16:52:05 -08003459{
Anurag Chouhan6d760662016-02-20 16:05:43 +05303460 if (type == QDF_SYSTEM_SUSPEND)
Houston Hoffmana76591b2015-11-10 16:52:05 -08003461 wma_send_status_to_suspend_ind(wma, true);
Anurag Chouhan6d760662016-02-20 16:05:43 +05303462 else if (type == QDF_RUNTIME_SUSPEND)
Anurag Chouhance0dc992016-02-16 18:18:03 +05303463 qdf_event_set(&wma->runtime_suspend);
Houston Hoffmana76591b2015-11-10 16:52:05 -08003464}
3465
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003466/**
3467 * wma_suspend_req() - Handles suspend indication request received from umac.
3468 * @wma: wma handle
Houston Hoffmana76591b2015-11-10 16:52:05 -08003469 * @type: type of suspend
3470 *
3471 * The type controlls how we notify the indicator that the indication has
3472 * been processed
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003473 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303474 * Return: QDF status
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003475 */
Anurag Chouhan6d760662016-02-20 16:05:43 +05303476QDF_STATUS wma_suspend_req(tp_wma_handle wma, enum qdf_suspend_type type)
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003477{
Anurag Chouhan6d760662016-02-20 16:05:43 +05303478 if (type == QDF_RUNTIME_SUSPEND)
Houston Hoffman1460fa32015-11-18 02:36:30 -08003479 wmi_set_runtime_pm_inprogress(wma->wmi_handle, true);
3480
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003481 if (wma_is_wow_applicable(wma)) {
3482 WMA_LOGE("WOW Suspend");
3483 wma_apply_lphb(wma);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003484
Houston Hoffman345fa402015-12-16 11:28:51 -08003485 wma_configure_dynamic_wake_events(wma);
3486
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003487 wma->wow.wow_enable = true;
3488 wma->wow.wow_enable_cmd_sent = false;
3489 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003490
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003491 /* Set the Suspend DTIM Parameters */
3492 wma_set_suspend_dtim(wma);
Houston Hoffmana76591b2015-11-10 16:52:05 -08003493
3494 wma_notify_suspend_req_procesed(wma, type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003495
3496 /* to handle race between hif_pci_suspend and
3497 * unpause/pause tx handler
3498 */
3499 wma_set_wow_bus_suspend(wma, 1);
3500
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303501 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003502}
3503
3504/**
3505 * wma_send_host_wakeup_ind_to_fw() - send wakeup ind to fw
3506 * @wma: wma handle
3507 *
3508 * Sends host wakeup indication to FW. On receiving this indication,
3509 * FW will come out of WOW.
3510 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303511 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003512 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303513static QDF_STATUS wma_send_host_wakeup_ind_to_fw(tp_wma_handle wma)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003514{
Anurag Chouhance0dc992016-02-16 18:18:03 +05303515 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003516 int ret;
3517#ifdef CONFIG_CNSS
Anurag Chouhan6d760662016-02-20 16:05:43 +05303518 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003519 if (NULL == pMac) {
3520 WMA_LOGE("%s: Unable to get PE context", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303521 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003522 }
3523#endif /* CONFIG_CNSS */
3524
Anurag Chouhance0dc992016-02-16 18:18:03 +05303525 qdf_event_reset(&wma->wma_resume_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003526
Govind Singhaa64c242016-03-08 11:31:49 +05303527 ret = wmi_unified_host_wakeup_ind_to_fw_cmd(wma->wmi_handle);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003528 if (ret) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303529 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003530 }
3531
3532 WMA_LOGD("Host wakeup indication sent to fw");
3533
Anurag Chouhance0dc992016-02-16 18:18:03 +05303534 qdf_status = qdf_wait_single_event(&(wma->wma_resume_event),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003535 WMA_RESUME_TIMEOUT);
Anurag Chouhance0dc992016-02-16 18:18:03 +05303536 if (QDF_STATUS_SUCCESS != qdf_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003537 WMA_LOGP("%s: Timeout waiting for resume event from FW",
3538 __func__);
3539 WMA_LOGP("%s: Pending commands %d credits %d", __func__,
3540 wmi_get_pending_cmds(wma->wmi_handle),
3541 wmi_get_host_credits(wma->wmi_handle));
Prashanth Bhatta9e143052015-12-04 11:56:47 -08003542 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003543#ifdef CONFIG_CNSS
3544 if (pMac->sme.enableSelfRecovery) {
3545 cds_trigger_recovery();
3546 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303547 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003548 }
3549#else
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303550 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003551#endif /* CONFIG_CNSS */
3552 } else {
3553 WMA_LOGE("%s: SSR in progress, ignore resume timeout",
3554 __func__);
3555 }
3556 } else {
3557 WMA_LOGD("Host wakeup received");
3558 }
3559
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303560 if (QDF_STATUS_SUCCESS == qdf_status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003561 wmi_set_target_suspend(wma->wmi_handle, false);
3562
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303563 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003564}
3565
3566/**
3567 * wma_disable_wow_in_fw() - Disable wow in PCIe resume context.
3568 * @handle: wma handle
3569 *
3570 * Return: 0 for success or error code
3571 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303572QDF_STATUS wma_disable_wow_in_fw(WMA_HANDLE handle)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003573{
3574 tp_wma_handle wma = handle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303575 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003576
3577 if (!wma->wow.wow_enable || !wma->wow.wow_enable_cmd_sent)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303578 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003579
3580 ret = wma_send_host_wakeup_ind_to_fw(wma);
3581
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303582 if (ret != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003583 return ret;
3584
3585 wma->wow.wow_enable = false;
3586 wma->wow.wow_enable_cmd_sent = false;
3587
3588 /* To allow the tx pause/unpause events */
3589 wma_set_wow_bus_suspend(wma, 0);
3590 /* Unpause the vdev as we are resuming */
3591 wma_unpause_vdev(wma);
3592
3593 return ret;
3594}
3595
3596#ifdef WLAN_FEATURE_LPSS
3597/**
3598 * wma_is_lpass_enabled() - check if lpass is enabled
3599 * @handle: Pointer to wma handle
3600 *
3601 * WoW is needed if LPASS or NaN feature is enabled in INI because
3602 * target can't wake up itself if its put in PDEV suspend when LPASS
3603 * or NaN features are supported
3604 *
3605 * Return: true if lpass is enabled else false
3606 */
3607bool static wma_is_lpass_enabled(tp_wma_handle wma)
3608{
3609 if (wma->is_lpass_enabled)
3610 return true;
3611 else
3612 return false;
3613}
3614#else
3615bool static wma_is_lpass_enabled(tp_wma_handle wma)
3616{
3617 return false;
3618}
3619#endif
3620
3621#ifdef WLAN_FEATURE_NAN
3622/**
3623 * wma_is_nan_enabled() - check if NaN is enabled
3624 * @handle: Pointer to wma handle
3625 *
3626 * WoW is needed if LPASS or NaN feature is enabled in INI because
3627 * target can't wake up itself if its put in PDEV suspend when LPASS
3628 * or NaN features are supported
3629 *
3630 * Return: true if NaN is enabled else false
3631 */
3632bool static wma_is_nan_enabled(tp_wma_handle wma)
3633{
3634 if (wma->is_nan_enabled)
3635 return true;
3636 else
3637 return false;
3638}
3639#else
3640bool static wma_is_nan_enabled(tp_wma_handle wma)
3641{
3642 return false;
3643}
3644#endif
3645
3646/**
3647 * wma_is_wow_mode_selected() - check if wow needs to be enabled in fw
3648 * @handle: Pointer to wma handle
3649 *
3650 * If lpass is enabled then always do wow else check wow_enable config
3651 *
3652 * Return: true is wow mode is needed else false
3653 */
Houston Hoffmana76591b2015-11-10 16:52:05 -08003654bool wma_is_wow_mode_selected(WMA_HANDLE handle)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003655{
3656 tp_wma_handle wma = (tp_wma_handle) handle;
3657
3658 if (wma_is_lpass_enabled(wma)) {
3659 WMA_LOGD("LPASS is enabled select WoW");
3660 return true;
3661 } else if (wma_is_nan_enabled(wma)) {
3662 WMA_LOGD("NAN is enabled select WoW");
3663 return true;
3664 } else {
3665 WMA_LOGD("WoW enable %d", wma->wow.wow_enable);
3666 return wma->wow.wow_enable;
3667 }
3668}
3669
3670/**
3671 * wma_del_ts_req() - send DELTS request to fw
3672 * @wma: wma handle
3673 * @msg: delts params
3674 *
3675 * Return: none
3676 */
3677void wma_del_ts_req(tp_wma_handle wma, tDelTsParams *msg)
3678{
Govind Singhaa64c242016-03-08 11:31:49 +05303679 if (wmi_unified_del_ts_cmd(wma->wmi_handle,
3680 msg->sessionId,
3681 TID_TO_WME_AC(msg->userPrio))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003682 WMA_LOGP("%s: Failed to send vdev DELTS command", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003683 }
Govind Singhaa64c242016-03-08 11:31:49 +05303684
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003685#ifdef WLAN_FEATURE_ROAM_OFFLOAD
3686 if (msg->setRICparams == true)
3687 wma_set_ric_req(wma, msg, false);
3688#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
3689
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303690 qdf_mem_free(msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003691}
3692
3693/**
3694 * wma_aggr_qos_req() - send aggr qos request to fw
3695 * @wma: handle to wma
3696 * @pAggrQosRspMsg - combined struct for all ADD_TS requests.
3697 *
3698 * A function to handle WMA_AGGR_QOS_REQ. This will send out
3699 * ADD_TS requestes to firmware in loop for all the ACs with
3700 * active flow.
3701 *
3702 * Return: none
3703 */
3704void wma_aggr_qos_req(tp_wma_handle wma,
3705 tAggrAddTsParams *pAggrQosRspMsg)
3706{
Govind Singhaa64c242016-03-08 11:31:49 +05303707 wmi_unified_aggr_qos_cmd(wma->wmi_handle,
3708 (struct aggr_add_ts_param *)pAggrQosRspMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003709 /* send reponse to upper layers from here only. */
3710 wma_send_msg(wma, WMA_AGGR_QOS_RSP, pAggrQosRspMsg, 0);
3711}
3712
3713/**
3714 * wma_add_ts_req() - send ADDTS request to fw
3715 * @wma: wma handle
3716 * @msg: ADDTS params
3717 *
3718 * Return: none
3719 */
3720void wma_add_ts_req(tp_wma_handle wma, tAddTsParams *msg)
3721{
Govind Singhaa64c242016-03-08 11:31:49 +05303722 struct add_ts_param cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003723
3724#ifdef FEATURE_WLAN_ESE
3725 /*
3726 * msmt_interval is in unit called TU (1 TU = 1024 us)
3727 * max value of msmt_interval cannot make resulting
3728 * interval_miliseconds overflow 32 bit
3729 */
3730 uint32_t intervalMiliseconds;
Anurag Chouhan6d760662016-02-20 16:05:43 +05303731 ol_txrx_pdev_handle pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003732 if (NULL == pdev) {
3733 WMA_LOGE("%s: Failed to get pdev", __func__);
3734 goto err;
3735 }
3736
3737 intervalMiliseconds = (msg->tsm_interval * 1024) / 1000;
3738
3739 ol_tx_set_compute_interval(pdev, intervalMiliseconds);
3740#endif /* FEATURE_WLAN_ESE */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303741 msg->status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003742
Govind Singhaa64c242016-03-08 11:31:49 +05303743
3744 cmd.sme_session_id = msg->sme_session_id;
3745 cmd.tspec.tsinfo.traffic.userPrio =
3746 TID_TO_WME_AC(msg->tspec.tsinfo.traffic.userPrio);
3747 cmd.tspec.mediumTime = msg->tspec.mediumTime;
3748 if (wmi_unified_add_ts_cmd(wma->wmi_handle, &cmd))
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303749 msg->status = QDF_STATUS_E_FAILURE;
Govind Singhaa64c242016-03-08 11:31:49 +05303750
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003751#ifdef WLAN_FEATURE_ROAM_OFFLOAD
3752 if (msg->setRICparams == true)
3753 wma_set_ric_req(wma, msg, true);
3754#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
3755
3756err:
3757 wma_send_msg(wma, WMA_ADD_TS_RSP, msg, 0);
3758}
3759
3760/**
3761 * wma_enable_disable_packet_filter() - enable/disable packet filter in target
3762 * @wma: Pointer to wma handle
3763 * @vdev_id: vdev id
3764 * @enable: Flag to enable/disable packet filter
3765 *
3766 * Return: 0 for success or error code
3767 */
3768static int wma_enable_disable_packet_filter(tp_wma_handle wma,
3769 uint8_t vdev_id, bool enable)
3770{
Govind Singhaa64c242016-03-08 11:31:49 +05303771 int ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003772
Govind Singhaa64c242016-03-08 11:31:49 +05303773 ret = wmi_unified_enable_disable_packet_filter_cmd(wma->wmi_handle,
3774 vdev_id, enable);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003775 if (ret)
3776 WMA_LOGE("Failed to send packet filter wmi cmd to fw");
3777
3778 return ret;
3779}
3780
3781/**
3782 * wma_config_packet_filter() - configure packet filter in target
3783 * @wma: Pointer to wma handle
3784 * @vdev_id: vdev id
3785 * @rcv_filter_param: Packet filter parameters
3786 * @filter_id: Filter id
3787 * @enable: Flag to add/delete packet filter configuration
3788 *
3789 * Return: 0 for success or error code
3790 */
3791static int wma_config_packet_filter(tp_wma_handle wma,
3792 uint8_t vdev_id, tSirRcvPktFilterCfgType *rcv_filter_param,
3793 uint8_t filter_id, bool enable)
3794{
Govind Singhaa64c242016-03-08 11:31:49 +05303795 int err;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003796
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003797 /* send the command along with data */
Govind Singhaa64c242016-03-08 11:31:49 +05303798 err = wmi_unified_config_packet_filter_cmd(wma->wmi_handle,
3799 vdev_id, (struct rcv_pkt_filter_config *)rcv_filter_param,
3800 filter_id, enable);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003801 if (err) {
3802 WMA_LOGE("Failed to send pkt_filter cmd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003803 return -EIO;
3804 }
3805
3806 /* Enable packet filter */
3807 if (enable)
3808 wma_enable_disable_packet_filter(wma, vdev_id, true);
3809
3810 return 0;
3811}
3812
3813/**
3814 * wma_process_receive_filter_set_filter_req() - enable packet filter
3815 * @wma_handle: wma handle
3816 * @rcv_filter_param: filter params
3817 *
3818 * Return: 0 for success or error code
3819 */
3820int wma_process_receive_filter_set_filter_req(tp_wma_handle wma,
3821 tSirRcvPktFilterCfgType *rcv_filter_param)
3822{
3823 int ret = 0;
3824 uint8_t vdev_id;
3825
3826 /* Get the vdev id */
Srinivas Girigowda98530492015-11-20 17:39:24 -08003827 if (!wma_find_vdev_by_bssid(wma,
3828 rcv_filter_param->bssid.bytes, &vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003829 WMA_LOGE("vdev handle is invalid for %pM",
Srinivas Girigowda98530492015-11-20 17:39:24 -08003830 rcv_filter_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003831 return -EINVAL;
3832 }
3833
3834 ret = wma_config_packet_filter(wma, vdev_id, rcv_filter_param,
3835 rcv_filter_param->filterId, true);
3836
3837 return ret;
3838}
3839
3840/**
3841 * wma_process_receive_filter_clear_filter_req() - disable packet filter
3842 * @wma_handle: wma handle
3843 * @rcv_clear_param: filter params
3844 *
3845 * Return: 0 for success or error code
3846 */
3847int wma_process_receive_filter_clear_filter_req(tp_wma_handle wma,
3848 tSirRcvFltPktClearParam *rcv_clear_param)
3849{
3850 int ret = 0;
3851 uint8_t vdev_id;
3852
3853 /* Get the vdev id */
Srinivas Girigowda98530492015-11-20 17:39:24 -08003854 if (!wma_find_vdev_by_bssid(wma,
3855 rcv_clear_param->bssid.bytes, &vdev_id)) {
3856 WMA_LOGE("vdev handle is invalid for %pM",
3857 rcv_clear_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003858 return -EINVAL;
3859 }
3860
3861 ret = wma_config_packet_filter(wma, vdev_id, NULL,
3862 rcv_clear_param->filterId, false);
3863
3864 return ret;
3865}
3866
3867#ifdef FEATURE_WLAN_ESE
3868
3869#define TSM_DELAY_HISTROGRAM_BINS 4
3870/**
3871 * wma_process_tsm_stats_req() - process tsm stats request
3872 * @wma_handler - handle to wma
3873 * @pTsmStatsMsg - TSM stats struct that needs to be populated and
3874 * passed in message.
3875 *
3876 * A parallel function to WMA_ProcessTsmStatsReq for pronto. This
3877 * function fetches stats from data path APIs and post
3878 * WMA_TSM_STATS_RSP msg back to LIM.
3879 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303880 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003881 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303882QDF_STATUS wma_process_tsm_stats_req(tp_wma_handle wma_handler,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003883 void *pTsmStatsMsg)
3884{
3885 uint8_t counter;
3886 uint32_t queue_delay_microsec = 0;
3887 uint32_t tx_delay_microsec = 0;
3888 uint16_t packet_count = 0;
3889 uint16_t packet_loss_count = 0;
3890 tpAniTrafStrmMetrics pTsmMetric = NULL;
3891#ifdef FEATURE_WLAN_ESE_UPLOAD
3892 tpAniGetTsmStatsReq pStats = (tpAniGetTsmStatsReq) pTsmStatsMsg;
3893 tpAniGetTsmStatsRsp pTsmRspParams = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003894#endif /* FEATURE_WLAN_ESE_UPLOAD */
3895 int tid = pStats->tid;
3896 /*
3897 * The number of histrogram bin report by data path api are different
3898 * than required by TSM, hence different (6) size array used
3899 */
3900 uint16_t bin_values[QCA_TX_DELAY_HIST_REPORT_BINS] = { 0, };
3901
Anurag Chouhan6d760662016-02-20 16:05:43 +05303902 ol_txrx_pdev_handle pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003903
3904 if (NULL == pdev) {
3905 WMA_LOGE("%s: Failed to get pdev", __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303906 qdf_mem_free(pTsmStatsMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303907 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003908 }
3909
3910 /* get required values from data path APIs */
3911 ol_tx_delay(pdev, &queue_delay_microsec, &tx_delay_microsec, tid);
3912 ol_tx_delay_hist(pdev, bin_values, tid);
3913 ol_tx_packet_count(pdev, &packet_count, &packet_loss_count, tid);
3914
3915#ifdef FEATURE_WLAN_ESE_UPLOAD
3916 pTsmRspParams =
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303917 (tpAniGetTsmStatsRsp) qdf_mem_malloc(sizeof(tAniGetTsmStatsRsp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003918 if (NULL == pTsmRspParams) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303919 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303920 "%s: QDF MEM Alloc Failure", __func__);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303921 QDF_ASSERT(0);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303922 qdf_mem_free(pTsmStatsMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303923 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003924 }
3925 pTsmRspParams->staId = pStats->staId;
3926 pTsmRspParams->rc = eSIR_FAILURE;
3927 pTsmRspParams->tsmStatsReq = pStats;
3928 pTsmMetric = &pTsmRspParams->tsmMetrics;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003929#endif /* FEATURE_WLAN_ESE_UPLOAD */
3930 /* populate pTsmMetric */
3931 pTsmMetric->UplinkPktQueueDly = queue_delay_microsec;
3932 /* store only required number of bin values */
3933 for (counter = 0; counter < TSM_DELAY_HISTROGRAM_BINS; counter++) {
3934 pTsmMetric->UplinkPktQueueDlyHist[counter] =
3935 bin_values[counter];
3936 }
3937 pTsmMetric->UplinkPktTxDly = tx_delay_microsec;
3938 pTsmMetric->UplinkPktLoss = packet_loss_count;
3939 pTsmMetric->UplinkPktCount = packet_count;
3940
3941 /*
3942 * No need to populate roaming delay and roaming count as they are
3943 * being populated just before sending IAPP frame out
3944 */
3945 /* post this message to LIM/PE */
3946#ifdef FEATURE_WLAN_ESE_UPLOAD
3947 wma_send_msg(wma_handler, WMA_TSM_STATS_RSP, (void *)pTsmRspParams, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003948#endif /* FEATURE_WLAN_ESE_UPLOAD */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303949 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003950}
3951
3952#endif /* FEATURE_WLAN_ESE */
3953
3954/**
3955 * wma_add_clear_mcbc_filter() - set mcast filter command to fw
3956 * @wma_handle: wma handle
3957 * @vdev_id: vdev id
3958 * @multicastAddr: mcast address
3959 * @clearList: clear list flag
3960 *
3961 * Return: 0 for success or error code
3962 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05303963static QDF_STATUS wma_add_clear_mcbc_filter(tp_wma_handle wma_handle,
3964 uint8_t vdev_id,
Anurag Chouhan6d760662016-02-20 16:05:43 +05303965 struct qdf_mac_addr multicast_addr,
Srinivas Girigowda98530492015-11-20 17:39:24 -08003966 bool clearList)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003967{
Himanshu Agarwal44195412016-03-09 13:03:54 +05303968 return wmi_unified_add_clear_mcbc_filter_cmd(wma_handle->wmi_handle,
3969 vdev_id, multicast_addr, clearList);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003970}
3971
3972/**
3973 * wma_process_mcbc_set_filter_req() - process mcbc set filter request
3974 * @wma_handle: wma handle
3975 * @mcbc_param: mcbc params
3976 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303977 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003978 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303979QDF_STATUS wma_process_mcbc_set_filter_req(tp_wma_handle wma_handle,
Anurag Chouhance0dc992016-02-16 18:18:03 +05303980 tSirRcvFltMcAddrList *mcbc_param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003981{
3982 uint8_t vdev_id = 0;
3983 int i;
3984
3985 if (mcbc_param->ulMulticastAddrCnt <= 0) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08003986 WMA_LOGW("Number of multicast addresses is 0");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303987 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003988 }
3989
Srinivas Girigowda98530492015-11-20 17:39:24 -08003990 if (!wma_find_vdev_by_addr(wma_handle,
3991 mcbc_param->self_macaddr.bytes, &vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003992 WMA_LOGE("%s: Failed to find vdev id for %pM", __func__,
Srinivas Girigowda98530492015-11-20 17:39:24 -08003993 mcbc_param->bssid.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303994 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003995 }
3996 /* set mcbc_param->action to clear MCList and reset
3997 * to configure the MCList in FW
3998 */
3999
4000 for (i = 0; i < mcbc_param->ulMulticastAddrCnt; i++) {
4001 wma_add_clear_mcbc_filter(wma_handle, vdev_id,
4002 mcbc_param->multicastAddr[i],
4003 (mcbc_param->action == 0));
4004 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304005 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004006}
4007
4008#ifdef WLAN_FEATURE_GTK_OFFLOAD
4009#define GTK_OFFLOAD_ENABLE 0
4010#define GTK_OFFLOAD_DISABLE 1
4011
4012/**
4013 * wma_gtk_offload_status_event() - GTK offload status event handler
4014 * @handle: wma handle
4015 * @event: event buffer
4016 * @len: buffer length
4017 *
4018 * Return: 0 for success or error code
4019 */
4020int wma_gtk_offload_status_event(void *handle, uint8_t *event,
4021 uint32_t len)
4022{
4023 tp_wma_handle wma = (tp_wma_handle) handle;
4024 WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param *status;
4025 WMI_GTK_OFFLOAD_STATUS_EVENTID_param_tlvs *param_buf;
4026 tpSirGtkOffloadGetInfoRspParams resp;
4027 cds_msg_t cds_msg;
4028 uint8_t *bssid;
4029
4030 WMA_LOGD("%s Enter", __func__);
4031
4032 param_buf = (WMI_GTK_OFFLOAD_STATUS_EVENTID_param_tlvs *) event;
4033 if (!param_buf) {
4034 WMA_LOGE("param_buf is NULL");
4035 return -EINVAL;
4036 }
4037
4038 status = (WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param *) param_buf->fixed_param;
4039
4040 if (len < sizeof(WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param)) {
4041 WMA_LOGE("Invalid length for GTK status");
4042 return -EINVAL;
4043 }
4044 bssid = wma_find_bssid_by_vdev_id(wma, status->vdev_id);
4045 if (!bssid) {
4046 WMA_LOGE("invalid bssid for vdev id %d", status->vdev_id);
4047 return -ENOENT;
4048 }
4049
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304050 resp = qdf_mem_malloc(sizeof(*resp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004051 if (!resp) {
4052 WMA_LOGE("%s: Failed to alloc response", __func__);
4053 return -ENOMEM;
4054 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304055 qdf_mem_zero(resp, sizeof(*resp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004056 resp->mesgType = eWNI_PMC_GTK_OFFLOAD_GETINFO_RSP;
4057 resp->mesgLen = sizeof(*resp);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304058 resp->ulStatus = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004059 resp->ulTotalRekeyCount = status->refresh_cnt;
4060 /* TODO: Is the total rekey count and GTK rekey count same? */
4061 resp->ulGTKRekeyCount = status->refresh_cnt;
4062
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304063 qdf_mem_copy(&resp->ullKeyReplayCounter, &status->replay_counter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004064 GTK_REPLAY_COUNTER_BYTES);
4065
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304066 qdf_mem_copy(resp->bssid.bytes, bssid, IEEE80211_ADDR_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004067
4068#ifdef IGTK_OFFLOAD
4069 /* TODO: Is the refresh count same for GTK and IGTK? */
4070 resp->ulIGTKRekeyCount = status->refresh_cnt;
4071#endif /* IGTK_OFFLOAD */
4072
4073 cds_msg.type = eWNI_PMC_GTK_OFFLOAD_GETINFO_RSP;
4074 cds_msg.bodyptr = (void *)resp;
4075 cds_msg.bodyval = 0;
4076
4077 if (cds_mq_post_message(CDS_MQ_ID_SME, (cds_msg_t *) &cds_msg)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304078 != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004079 WMA_LOGE("Failed to post GTK response to SME");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304080 qdf_mem_free(resp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004081 return -EINVAL;
4082 }
4083
4084 WMA_LOGD("GTK: got target status with replay counter "
4085 "%02x%02x%02x%02x%02x%02x%02x%02x. vdev %d "
4086 "Refresh GTK %d times exchanges since last set operation",
4087 status->replay_counter[0],
4088 status->replay_counter[1],
4089 status->replay_counter[2],
4090 status->replay_counter[3],
4091 status->replay_counter[4],
4092 status->replay_counter[5],
4093 status->replay_counter[6],
4094 status->replay_counter[7],
4095 status->vdev_id, status->refresh_cnt);
4096
4097 WMA_LOGD("%s Exit", __func__);
4098
4099 return 0;
4100}
4101
4102/**
4103 * wma_send_gtk_offload_req() - send GTK offload command to fw
4104 * @wma: wma handle
4105 * @vdev_id: vdev id
4106 * @params: GTK offload parameters
4107 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304108 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004109 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304110static QDF_STATUS wma_send_gtk_offload_req(tp_wma_handle wma, uint8_t vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004111 tpSirGtkOffloadParams params)
4112{
Himanshu Agarwal44195412016-03-09 13:03:54 +05304113 struct gtk_offload_params offload_params = {0};
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304114 QDF_STATUS status = QDF_STATUS_SUCCESS;
Himanshu Agarwal44195412016-03-09 13:03:54 +05304115 bool enable_offload;
4116 uint32_t gtk_offload_opcode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004117
4118 WMA_LOGD("%s Enter", __func__);
4119
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004120 /* Request target to enable GTK offload */
4121 if (params->ulFlags == GTK_OFFLOAD_ENABLE) {
Himanshu Agarwal44195412016-03-09 13:03:54 +05304122 gtk_offload_opcode = GTK_OFFLOAD_ENABLE_OPCODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004123 wma->wow.gtk_err_enable[vdev_id] = true;
4124
4125 /* Copy the keys and replay counter */
Himanshu Agarwal44195412016-03-09 13:03:54 +05304126 qdf_mem_copy(offload_params.aKCK, params->aKCK,
4127 GTK_OFFLOAD_KCK_BYTES);
4128 qdf_mem_copy(offload_params.aKEK, params->aKEK,
4129 GTK_OFFLOAD_KEK_BYTES);
4130 qdf_mem_copy(&offload_params.ullKeyReplayCounter,
4131 &params->ullKeyReplayCounter, GTK_REPLAY_COUNTER_BYTES);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004132 } else {
4133 wma->wow.gtk_err_enable[vdev_id] = false;
Himanshu Agarwal44195412016-03-09 13:03:54 +05304134 gtk_offload_opcode = GTK_OFFLOAD_DISABLE_OPCODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004135 }
4136
Himanshu Agarwal44195412016-03-09 13:03:54 +05304137 enable_offload = params->ulFlags;
4138
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004139 /* send the wmi command */
Himanshu Agarwal44195412016-03-09 13:03:54 +05304140 status = wmi_unified_send_gtk_offload_cmd(wma->wmi_handle,
4141 vdev_id, &offload_params,
4142 enable_offload,
4143 gtk_offload_opcode);
4144 if (QDF_IS_STATUS_ERROR(status))
4145 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004146
Himanshu Agarwal44195412016-03-09 13:03:54 +05304147 WMA_LOGD("VDEVID: %d, GTK_FLAGS: x%x", vdev_id, gtk_offload_opcode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004148out:
4149 WMA_LOGD("%s Exit", __func__);
4150 return status;
4151}
4152
4153/**
4154 * wma_process_gtk_offload_req() - process GTK offload req from umac
4155 * @handle: wma handle
4156 * @params: GTK offload params
4157 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304158 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004159 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304160QDF_STATUS wma_process_gtk_offload_req(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004161 tpSirGtkOffloadParams params)
4162{
4163 uint8_t vdev_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304164 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004165
4166 WMA_LOGD("%s Enter", __func__);
4167
4168 /* Get the vdev id */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -08004169 if (!wma_find_vdev_by_bssid(wma, params->bssid.bytes, &vdev_id)) {
4170 WMA_LOGE("vdev handle is invalid for %pM", params->bssid.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304171 status = QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004172 goto out;
4173 }
4174
4175 /* Validate vdev id */
4176 if (vdev_id >= wma->max_bssid) {
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -08004177 WMA_LOGE("invalid vdev_id %d for %pM", vdev_id,
4178 params->bssid.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304179 status = QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004180 goto out;
4181 }
4182
4183 if ((params->ulFlags == GTK_OFFLOAD_ENABLE) &&
4184 (wma->wow.gtk_err_enable[vdev_id] == true)) {
4185 WMA_LOGE("%s GTK Offload already enabled. Disable it first "
4186 "vdev_id %d", __func__, vdev_id);
4187 params->ulFlags = GTK_OFFLOAD_DISABLE;
4188 status = wma_send_gtk_offload_req(wma, vdev_id, params);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304189 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004190 WMA_LOGE("%s Failed to disable GTK Offload", __func__);
4191 goto out;
4192 }
4193 WMA_LOGD("%s Enable GTK Offload again with updated inputs",
4194 __func__);
4195 params->ulFlags = GTK_OFFLOAD_ENABLE;
4196 }
4197 status = wma_send_gtk_offload_req(wma, vdev_id, params);
4198out:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304199 qdf_mem_free(params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004200 WMA_LOGD("%s Exit", __func__);
4201 return status;
4202}
4203
4204/**
4205 * wma_process_gtk_offload_getinfo_req() - send GTK offload cmd to fw
4206 * @wma: wma handle
4207 * @params: GTK offload params
4208 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304209 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004210 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304211QDF_STATUS wma_process_gtk_offload_getinfo_req(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004212 tpSirGtkOffloadGetInfoRspParams params)
4213{
4214 uint8_t vdev_id;
Himanshu Agarwal44195412016-03-09 13:03:54 +05304215 uint64_t offload_req_opcode;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304216 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004217
4218 WMA_LOGD("%s Enter", __func__);
4219
4220 /* Get the vdev id */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -08004221 if (!wma_find_vdev_by_bssid(wma, params->bssid.bytes, &vdev_id)) {
4222 WMA_LOGE("vdev handle is invalid for %pM", params->bssid.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304223 status = QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004224 goto out;
4225 }
4226
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004227 /* Request for GTK offload status */
Himanshu Agarwal44195412016-03-09 13:03:54 +05304228 offload_req_opcode = GTK_OFFLOAD_REQUEST_STATUS_OPCODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004229
4230 /* send the wmi command */
Himanshu Agarwal44195412016-03-09 13:03:54 +05304231 status = wmi_unified_process_gtk_offload_getinfo_cmd(wma->wmi_handle,
4232 vdev_id, offload_req_opcode);
4233
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004234out:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304235 qdf_mem_free(params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004236 WMA_LOGD("%s Exit", __func__);
4237 return status;
4238}
4239#endif /* WLAN_FEATURE_GTK_OFFLOAD */
4240
4241/**
4242 * wma_enable_arp_ns_offload() - enable ARP NS offload
4243 * @wma: wma handle
4244 * @tpSirHostOffloadReq: offload request
Govind Singhaa64c242016-03-08 11:31:49 +05304245 * @arp_only: flag
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004246 *
4247 * To configure ARP NS off load data to firmware
4248 * when target goes to wow mode.
4249 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304250 * Return: QDF Status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004251 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304252QDF_STATUS wma_enable_arp_ns_offload(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004253 tpSirHostOffloadReq
Govind Singhaa64c242016-03-08 11:31:49 +05304254 pHostOffloadParams, bool arp_only)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004255{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004256 int32_t res;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004257 uint8_t vdev_id;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004258
4259 /* Get the vdev id */
Srinivas Girigowdab084b552015-11-24 12:39:12 -08004260 if (!wma_find_vdev_by_bssid(wma, pHostOffloadParams->bssid.bytes,
4261 &vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004262 WMA_LOGE("vdev handle is invalid for %pM",
Srinivas Girigowdab084b552015-11-24 12:39:12 -08004263 pHostOffloadParams->bssid.bytes);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304264 qdf_mem_free(pHostOffloadParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304265 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004266 }
4267
4268 if (!wma->interfaces[vdev_id].vdev_up) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004269 WMA_LOGE("vdev %d is not up skipping arp/ns offload", vdev_id);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304270 qdf_mem_free(pHostOffloadParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304271 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004272 }
4273
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004274
Govind Singhaa64c242016-03-08 11:31:49 +05304275 res = wmi_unified_enable_arp_ns_offload_cmd(wma->wmi_handle,
4276 (struct host_offload_req_param *)pHostOffloadParams,
4277 arp_only,
4278 vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004279 if (res) {
4280 WMA_LOGE("Failed to enable ARP NDP/NSffload");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304281 qdf_mem_free(pHostOffloadParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304282 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004283 }
4284
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304285 qdf_mem_free(pHostOffloadParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304286 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004287}
4288
4289/**
4290 * wma_process_add_periodic_tx_ptrn_ind - add periodic tx ptrn
4291 * @handle: wma handle
4292 * @pAddPeriodicTxPtrnParams: tx ptrn params
4293 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304294 * Retrun: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004295 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304296QDF_STATUS wma_process_add_periodic_tx_ptrn_ind(WMA_HANDLE handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004297 tSirAddPeriodicTxPtrn *
4298 pAddPeriodicTxPtrnParams)
4299{
4300 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Himanshu Agarwal44195412016-03-09 13:03:54 +05304301 struct periodic_tx_pattern params;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004302 uint8_t vdev_id;
Himanshu Agarwal44195412016-03-09 13:03:54 +05304303
4304 qdf_mem_set(&params, sizeof(struct periodic_tx_pattern), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004305
4306 if (!wma_handle || !wma_handle->wmi_handle) {
4307 WMA_LOGE("%s: WMA is closed, can not issue fw add pattern cmd",
4308 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304309 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004310 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004311
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004312 if (!wma_find_vdev_by_addr(wma_handle,
Srinivas Girigowda31896552015-11-18 22:59:52 -08004313 pAddPeriodicTxPtrnParams->mac_address.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004314 &vdev_id)) {
4315 WMA_LOGE("%s: Failed to find vdev id for %pM", __func__,
Srinivas Girigowda31896552015-11-18 22:59:52 -08004316 pAddPeriodicTxPtrnParams->mac_address.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304317 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004318 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004319
Himanshu Agarwal44195412016-03-09 13:03:54 +05304320 params.ucPtrnId = pAddPeriodicTxPtrnParams->ucPtrnId;
4321 params.ucPtrnSize = pAddPeriodicTxPtrnParams->ucPtrnSize;
4322 params.usPtrnIntervalMs = pAddPeriodicTxPtrnParams->usPtrnIntervalMs;
4323 qdf_mem_copy(&params.mac_address,
4324 &pAddPeriodicTxPtrnParams->mac_address,
4325 sizeof(struct qdf_mac_addr));
4326 qdf_mem_copy(params.ucPattern, pAddPeriodicTxPtrnParams->ucPattern,
4327 params.ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004328
Himanshu Agarwal44195412016-03-09 13:03:54 +05304329 return wmi_unified_process_add_periodic_tx_ptrn_cmd(
4330 wma_handle->wmi_handle, &params, vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004331}
4332
4333/**
4334 * wma_process_del_periodic_tx_ptrn_ind - del periodic tx ptrn
4335 * @handle: wma handle
4336 * @pDelPeriodicTxPtrnParams: tx ptrn params
4337 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304338 * Retrun: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004339 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304340QDF_STATUS wma_process_del_periodic_tx_ptrn_ind(WMA_HANDLE handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004341 tSirDelPeriodicTxPtrn *
4342 pDelPeriodicTxPtrnParams)
4343{
4344 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004345 uint8_t vdev_id;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004346
4347 if (!wma_handle || !wma_handle->wmi_handle) {
4348 WMA_LOGE("%s: WMA is closed, can not issue Del Pattern cmd",
4349 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304350 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004351 }
Himanshu Agarwal44195412016-03-09 13:03:54 +05304352
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004353 if (!wma_find_vdev_by_addr(wma_handle,
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08004354 pDelPeriodicTxPtrnParams->mac_address.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004355 &vdev_id)) {
4356 WMA_LOGE("%s: Failed to find vdev id for %pM", __func__,
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08004357 pDelPeriodicTxPtrnParams->mac_address.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304358 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004359 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004360
Himanshu Agarwal44195412016-03-09 13:03:54 +05304361 return wmi_unified_process_del_periodic_tx_ptrn_cmd(
4362 wma_handle->wmi_handle, vdev_id,
4363 pDelPeriodicTxPtrnParams->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004364}
4365
4366#ifdef WLAN_FEATURE_STATS_EXT
4367/**
4368 * wma_stats_ext_req() - request ext stats from fw
4369 * @wma_ptr: wma handle
4370 * @preq: stats ext params
4371 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304372 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004373 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304374QDF_STATUS wma_stats_ext_req(void *wma_ptr, tpStatsExtRequest preq)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004375{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004376 tp_wma_handle wma = (tp_wma_handle) wma_ptr;
Himanshu Agarwal44195412016-03-09 13:03:54 +05304377 struct stats_ext_params params = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004378
Himanshu Agarwal44195412016-03-09 13:03:54 +05304379 if (!wma) {
4380 WMA_LOGE("%s: wma handle is NULL", __func__);
4381 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004382 }
4383
Himanshu Agarwal44195412016-03-09 13:03:54 +05304384 params.vdev_id = preq->vdev_id;
4385 params.request_data_len = preq->request_data_len;
4386 qdf_mem_copy(params.request_data, preq->request_data,
4387 params.request_data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004388
Himanshu Agarwal44195412016-03-09 13:03:54 +05304389 return wmi_unified_stats_ext_req_cmd(wma->wmi_handle,
4390 &params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004391}
4392
4393#endif /* WLAN_FEATURE_STATS_EXT */
4394
4395#ifdef WLAN_FEATURE_EXTWOW_SUPPORT
4396/**
4397 * wma_send_status_of_ext_wow() - send ext wow status to SME
4398 * @wma: wma handle
4399 * @status: status
4400 *
4401 * Return: none
4402 */
4403static void wma_send_status_of_ext_wow(tp_wma_handle wma, bool status)
4404{
4405 tSirReadyToExtWoWInd *ready_to_extwow;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304406 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004407 cds_msg_t cds_msg;
4408 uint8_t len;
4409
4410 WMA_LOGD("Posting ready to suspend indication to umac");
4411
4412 len = sizeof(tSirReadyToExtWoWInd);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304413 ready_to_extwow = (tSirReadyToExtWoWInd *) qdf_mem_malloc(len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004414
4415 if (NULL == ready_to_extwow) {
4416 WMA_LOGE("%s: Memory allocation failure", __func__);
4417 return;
4418 }
4419
4420 ready_to_extwow->mesgType = eWNI_SME_READY_TO_EXTWOW_IND;
4421 ready_to_extwow->mesgLen = len;
4422 ready_to_extwow->status = status;
4423
4424 cds_msg.type = eWNI_SME_READY_TO_EXTWOW_IND;
4425 cds_msg.bodyptr = (void *)ready_to_extwow;
4426 cds_msg.bodyval = 0;
4427
4428 vstatus = cds_mq_post_message(CDS_MQ_ID_SME, &cds_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304429 if (vstatus != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004430 WMA_LOGE("Failed to post ready to suspend");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304431 qdf_mem_free(ready_to_extwow);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004432 }
4433}
4434
4435/**
4436 * wma_enable_ext_wow() - enable ext wow in fw
4437 * @wma: wma handle
4438 * @params: ext wow params
4439 *
4440 * Return:0 for success or error code
4441 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05304442QDF_STATUS wma_enable_ext_wow(tp_wma_handle wma, tpSirExtWoWParams params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004443{
Himanshu Agarwal44195412016-03-09 13:03:54 +05304444 struct ext_wow_params wow_params = {0};
4445 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004446
Himanshu Agarwal44195412016-03-09 13:03:54 +05304447 if (!wma) {
4448 WMA_LOGE("%s: wma handle is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304449 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004450 }
4451
Himanshu Agarwal44195412016-03-09 13:03:54 +05304452 wow_params.vdev_id = params->vdev_id;
4453 wow_params.type = (enum wmi_ext_wow_type) params->type;
4454 wow_params.wakeup_pin_num = params->wakeup_pin_num;
4455
4456 status = wmi_unified_enable_ext_wow_cmd(wma->wmi_handle,
4457 &wow_params);
4458 if (QDF_IS_STATUS_ERROR(status))
4459 return status;
4460
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004461 wma_send_status_of_ext_wow(wma, true);
Himanshu Agarwal44195412016-03-09 13:03:54 +05304462 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004463
4464}
4465
4466/**
4467 * wma_set_app_type1_params_in_fw() - set app type1 params in fw
4468 * @wma: wma handle
4469 * @appType1Params: app type1 params
4470 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304471 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004472 */
4473int wma_set_app_type1_params_in_fw(tp_wma_handle wma,
4474 tpSirAppType1Params appType1Params)
4475{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004476 int ret;
4477
Govind Singhaa64c242016-03-08 11:31:49 +05304478 ret = wmi_unified_app_type1_params_in_fw_cmd(wma->wmi_handle,
4479 (struct app_type1_params *)appType1Params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004480 if (ret) {
4481 WMA_LOGE("%s: Failed to set APP TYPE1 PARAMS", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304482 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004483 }
4484
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304485 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004486}
4487
4488/**
4489 * wma_set_app_type2_params_in_fw() - set app type2 params in fw
4490 * @wma: wma handle
4491 * @appType2Params: app type2 params
4492 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304493 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004494 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05304495QDF_STATUS wma_set_app_type2_params_in_fw(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004496 tpSirAppType2Params appType2Params)
4497{
Himanshu Agarwal44195412016-03-09 13:03:54 +05304498 struct app_type2_params params = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004499
Himanshu Agarwal44195412016-03-09 13:03:54 +05304500 if (!wma) {
4501 WMA_LOGE("%s: wma handle is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304502 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004503 }
4504
Himanshu Agarwal44195412016-03-09 13:03:54 +05304505 params.vdev_id = appType2Params->vdev_id;
4506 params.rc4_key_len = appType2Params->rc4_key_len;
4507 qdf_mem_copy(params.rc4_key, appType2Params->rc4_key, 16);
4508 params.ip_id = appType2Params->ip_id;
4509 params.ip_device_ip = appType2Params->ip_device_ip;
4510 params.ip_server_ip = appType2Params->ip_server_ip;
4511 params.tcp_src_port = appType2Params->tcp_src_port;
4512 params.tcp_dst_port = appType2Params->tcp_dst_port;
4513 params.tcp_seq = appType2Params->tcp_seq;
4514 params.tcp_ack_seq = appType2Params->tcp_ack_seq;
4515 params.keepalive_init = appType2Params->keepalive_init;
4516 params.keepalive_min = appType2Params->keepalive_min;
4517 params.keepalive_max = appType2Params->keepalive_max;
4518 params.keepalive_inc = appType2Params->keepalive_inc;
4519 params.tcp_tx_timeout_val = appType2Params->tcp_tx_timeout_val;
4520 params.tcp_rx_timeout_val = appType2Params->tcp_rx_timeout_val;
4521 qdf_mem_copy(&params.gateway_mac, &appType2Params->gateway_mac,
4522 sizeof(struct qdf_mac_addr));
4523
4524 return wmi_unified_set_app_type2_params_in_fw_cmd(wma->wmi_handle,
4525 &params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004526
4527}
4528#endif /* WLAN_FEATURE_EXTWOW_SUPPORT */
4529
4530#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
4531/**
4532 * wma_auto_shutdown_event_handler() - process auto shutdown timer trigger
4533 * @handle: wma handle
4534 * @event: event buffer
4535 * @len: buffer length
4536 *
4537 * Return: 0 for success or error code
4538 */
4539int wma_auto_shutdown_event_handler(void *handle, uint8_t *event,
4540 uint32_t len)
4541{
4542 wmi_host_auto_shutdown_event_fixed_param *wmi_auto_sh_evt;
4543 WMI_HOST_AUTO_SHUTDOWN_EVENTID_param_tlvs *param_buf =
4544 (WMI_HOST_AUTO_SHUTDOWN_EVENTID_param_tlvs *)
4545 event;
4546
4547 if (!param_buf || !param_buf->fixed_param) {
4548 WMA_LOGE("%s:%d: Invalid Auto shutdown timer evt", __func__,
4549 __LINE__);
4550 return -EINVAL;
4551 }
4552
4553 wmi_auto_sh_evt = param_buf->fixed_param;
4554
4555 if (wmi_auto_sh_evt->shutdown_reason
4556 != WMI_HOST_AUTO_SHUTDOWN_REASON_TIMER_EXPIRY) {
4557 WMA_LOGE("%s:%d: Invalid Auto shutdown timer evt", __func__,
4558 __LINE__);
4559 return -EINVAL;
4560 }
4561
4562 WMA_LOGD("%s:%d: Auto Shutdown Evt: %d", __func__, __LINE__,
4563 wmi_auto_sh_evt->shutdown_reason);
4564 return wma_post_auto_shutdown_msg();
4565}
4566
4567/**
4568 * wma_set_auto_shutdown_timer_req() - sets auto shutdown timer in firmware
4569 * @wma: wma handle
4570 * @auto_sh_cmd: auto shutdown timer value
4571 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304572 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004573 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304574QDF_STATUS wma_set_auto_shutdown_timer_req(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004575 tSirAutoShutdownCmdParams *
4576 auto_sh_cmd)
4577{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004578 if (auto_sh_cmd == NULL) {
4579 WMA_LOGE("%s : Invalid Autoshutdown cfg cmd", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304580 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004581 }
4582
Himanshu Agarwal44195412016-03-09 13:03:54 +05304583 return wmi_unified_set_auto_shutdown_timer_cmd(wma_handle->wmi_handle,
4584 auto_sh_cmd->timer_val);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004585}
4586#endif /* FEATURE_WLAN_AUTO_SHUTDOWN */
4587
4588#ifdef WLAN_FEATURE_NAN
4589/**
4590 * wma_nan_req() - to send nan request to target
4591 * @wma: wma_handle
4592 * @nan_req: request data which will be non-null
4593 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304594 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004595 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304596QDF_STATUS wma_nan_req(void *wma_ptr, tpNanRequest nan_req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004597{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004598 tp_wma_handle wma_handle = (tp_wma_handle) wma_ptr;
Himanshu Agarwal44195412016-03-09 13:03:54 +05304599 struct nan_req_params params = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004600
Himanshu Agarwal44195412016-03-09 13:03:54 +05304601 if (!wma_handle) {
4602 WMA_LOGE("%s: wma handle is NULL", __func__);
4603 return QDF_STATUS_E_FAILURE;
4604 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004605 if (!nan_req) {
4606 WMA_LOGE("%s:nan req is not valid", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304607 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004608 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004609
Himanshu Agarwal44195412016-03-09 13:03:54 +05304610 params.request_data_len = nan_req->request_data_len;
4611 qdf_mem_copy(params.request_data, nan_req->request_data,
4612 params.request_data_len);
4613
4614 return wmi_unified_nan_req_cmd(wma_handle->wmi_handle,
4615 &params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004616}
4617#endif /* WLAN_FEATURE_NAN */
4618
4619#ifdef DHCP_SERVER_OFFLOAD
4620/**
4621 * wma_process_dhcpserver_offload() - enable DHCP server offload
4622 * @wma_handle: wma handle
4623 * @pDhcpSrvOffloadInfo: DHCP server offload info
4624 *
4625 * Return: 0 for success or error code
4626 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05304627QDF_STATUS wma_process_dhcpserver_offload(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004628 tSirDhcpSrvOffloadInfo *
4629 pDhcpSrvOffloadInfo)
4630{
Himanshu Agarwal44195412016-03-09 13:03:54 +05304631 struct dhcp_offload_info_params params = {0};
4632 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004633
Himanshu Agarwal44195412016-03-09 13:03:54 +05304634 if (!wma_handle) {
4635 WMA_LOGE("%s: wma handle is NULL", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004636 return -EIO;
4637 }
Himanshu Agarwal44195412016-03-09 13:03:54 +05304638
4639 params.vdev_id = pDhcpSrvOffloadInfo->vdev_id;
4640 params.dhcpSrvOffloadEnabled =
4641 pDhcpSrvOffloadInfo->dhcpSrvOffloadEnabled;
4642 params.dhcpClientNum = pDhcpSrvOffloadInfo->dhcpClientNum;
4643 params.dhcpSrvIP = pDhcpSrvOffloadInfo->;
4644
4645 status = wmi_unified_process_dhcpserver_offload_cmd(
4646 wma_handle->wmi_handle, &params);
4647 if (QDF_IS_STATUS_ERROR(status))
4648 return status;
4649
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004650 WMA_LOGD("Set dhcp server offload to vdevId %d",
4651 pDhcpSrvOffloadInfo->vdev_id);
Himanshu Agarwal44195412016-03-09 13:03:54 +05304652 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004653}
4654#endif /* DHCP_SERVER_OFFLOAD */
4655
4656#ifdef WLAN_FEATURE_GPIO_LED_FLASHING
4657/**
4658 * wma_set_led_flashing() - set led flashing in fw
4659 * @wma_handle: wma handle
4660 * @flashing: flashing request
4661 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304662 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004663 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304664QDF_STATUS wma_set_led_flashing(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004665 tSirLedFlashingReq *flashing)
4666{
Govind Singhaa64c242016-03-08 11:31:49 +05304667 struct flashing_req_params cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004668
4669 if (!wma_handle || !wma_handle->wmi_handle) {
4670 WMA_LOGE(FL("WMA is closed, can not issue cmd"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304671 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004672 }
4673 if (!flashing) {
4674 WMA_LOGE(FL("invalid parameter: flashing"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304675 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004676 }
Govind Singhaa64c242016-03-08 11:31:49 +05304677 cmd.req_id = flashing->reqId;
4678 cmd.pattern_id = flashing->pattern_id;
4679 cmd.led_x0 = flashing->led_x0;
4680 cmd.led_x1 = flashing->led_x1;
4681 status = wmi_unified_set_led_flashing_cmd(wma_handle->wmi_handle,
4682 &cmd);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004683 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304684 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004685 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304686 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004687}
4688#endif /* WLAN_FEATURE_GPIO_LED_FLASHING */
4689
4690#ifdef FEATURE_WLAN_CH_AVOID
4691/**
4692 * wma_channel_avoid_evt_handler() - process channel to avoid event from FW.
4693 * @handle: wma handle
4694 * @event: event buffer
4695 * @len: buffer length
4696 *
4697 * Return: 0 for success or error code
4698 */
4699int wma_channel_avoid_evt_handler(void *handle, uint8_t *event,
4700 uint32_t len)
4701{
4702 wmi_avoid_freq_ranges_event_fixed_param *afr_fixed_param;
4703 wmi_avoid_freq_range_desc *afr_desc;
4704 uint32_t num_freq_ranges, freq_range_idx;
4705 tSirChAvoidIndType *sca_indication;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304706 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004707 cds_msg_t sme_msg = { 0 };
4708 WMI_WLAN_FREQ_AVOID_EVENTID_param_tlvs *param_buf =
4709 (WMI_WLAN_FREQ_AVOID_EVENTID_param_tlvs *) event;
4710
4711 if (!param_buf) {
4712 WMA_LOGE("Invalid channel avoid event buffer");
4713 return -EINVAL;
4714 }
4715
4716 afr_fixed_param = param_buf->fixed_param;
4717 if (!afr_fixed_param) {
4718 WMA_LOGE("Invalid channel avoid event fixed param buffer");
4719 return -EINVAL;
4720 }
4721
4722 num_freq_ranges =
4723 (afr_fixed_param->num_freq_ranges >
4724 SIR_CH_AVOID_MAX_RANGE) ? SIR_CH_AVOID_MAX_RANGE :
4725 afr_fixed_param->num_freq_ranges;
4726
4727 WMA_LOGD("Channel avoid event received with %d ranges",
4728 num_freq_ranges);
4729 for (freq_range_idx = 0; freq_range_idx < num_freq_ranges;
4730 freq_range_idx++) {
4731 afr_desc = (wmi_avoid_freq_range_desc *)
4732 ((void *)param_buf->avd_freq_range +
4733 freq_range_idx * sizeof(wmi_avoid_freq_range_desc));
4734
4735 WMA_LOGD("range %d: tlv id = %u, start freq = %u, end freq = %u",
4736 freq_range_idx, afr_desc->tlv_header, afr_desc->start_freq,
4737 afr_desc->end_freq);
4738 }
4739
4740 sca_indication = (tSirChAvoidIndType *)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304741 qdf_mem_malloc(sizeof(tSirChAvoidIndType));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004742 if (!sca_indication) {
4743 WMA_LOGE("Invalid channel avoid indication buffer");
4744 return -EINVAL;
4745 }
4746
4747 sca_indication->avoid_range_count = num_freq_ranges;
4748 for (freq_range_idx = 0; freq_range_idx < num_freq_ranges;
4749 freq_range_idx++) {
4750 afr_desc = (wmi_avoid_freq_range_desc *)
4751 ((void *)param_buf->avd_freq_range +
4752 freq_range_idx * sizeof(wmi_avoid_freq_range_desc));
4753 sca_indication->avoid_freq_range[freq_range_idx].start_freq =
4754 afr_desc->start_freq;
4755 sca_indication->avoid_freq_range[freq_range_idx].end_freq =
4756 afr_desc->end_freq;
4757 }
4758
4759 sme_msg.type = eWNI_SME_CH_AVOID_IND;
4760 sme_msg.bodyptr = sca_indication;
4761 sme_msg.bodyval = 0;
4762
Anurag Chouhan6d760662016-02-20 16:05:43 +05304763 qdf_status = cds_mq_post_message(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304764 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004765 WMA_LOGE("Fail to post eWNI_SME_CH_AVOID_IND msg to SME");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304766 qdf_mem_free(sca_indication);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004767 return -EINVAL;
4768 }
4769
4770 return 0;
4771}
4772
4773/**
4774 * wma_process_ch_avoid_update_req() - handles channel avoid update request
4775 * @wma_handle: wma handle
4776 * @ch_avoid_update_req: channel avoid update params
4777 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304778 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004779 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304780QDF_STATUS wma_process_ch_avoid_update_req(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004781 tSirChAvoidUpdateReq *
4782 ch_avoid_update_req)
4783{
Himanshu Agarwal44195412016-03-09 13:03:54 +05304784 QDF_STATUS status;
4785 if (!wma_handle) {
4786 WMA_LOGE("%s: wma handle is NULL", __func__);
4787 return QDF_STATUS_E_FAILURE;
4788 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004789 if (ch_avoid_update_req == NULL) {
4790 WMA_LOGE("%s : ch_avoid_update_req is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304791 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004792 }
4793
4794 WMA_LOGI("%s: WMA --> WMI_CHAN_AVOID_UPDATE", __func__);
4795
Himanshu Agarwal44195412016-03-09 13:03:54 +05304796 status = wmi_unified_process_ch_avoid_update_cmd(
4797 wma_handle->wmi_handle);
4798 if (QDF_IS_STATUS_ERROR(status))
4799 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004800
4801 WMA_LOGI("%s: WMA --> WMI_CHAN_AVOID_UPDATE sent through WMI",
4802 __func__);
Himanshu Agarwal44195412016-03-09 13:03:54 +05304803 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004804}
4805#endif /* FEATURE_WLAN_CH_AVOID */
4806
4807/**
4808 * wma_set_reg_domain() - set reg domain
4809 * @clientCtxt: client context
4810 * @regId: reg id
4811 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304812 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004813 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304814QDF_STATUS wma_set_reg_domain(void *clientCtxt, v_REGDOMAIN_t regId)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004815{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304816 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004817 cds_set_reg_domain(clientCtxt, regId))
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304818 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004819
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304820 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004821}
4822
4823/**
4824 * wma_send_regdomain_info_to_fw() - send regdomain info to fw
4825 * @reg_dmn: reg domain
4826 * @regdmn2G: 2G reg domain
4827 * @regdmn5G: 5G reg domain
4828 * @ctl2G: 2G test limit
4829 * @ctl5G: 5G test limit
4830 *
4831 * Return: none
4832 */
4833void wma_send_regdomain_info_to_fw(uint32_t reg_dmn, uint16_t regdmn2G,
4834 uint16_t regdmn5G, int8_t ctl2G,
4835 int8_t ctl5G)
4836{
Anurag Chouhan6d760662016-02-20 16:05:43 +05304837 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004838 int32_t cck_mask_val = 0;
Govind Singhd76a5b02016-03-08 15:12:14 +05304839 struct pdev_params pdev_param = {0};
Himanshu Agarwal44195412016-03-09 13:03:54 +05304840 QDF_STATUS ret = QDF_STATUS_SUCCESS;
4841 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004842
4843 if (NULL == wma) {
4844 WMA_LOGE("%s: wma context is NULL", __func__);
4845 return;
4846 }
4847
Himanshu Agarwal44195412016-03-09 13:03:54 +05304848 status = wmi_unified_send_regdomain_info_to_fw_cmd(wma->wmi_handle,
4849 reg_dmn, regdmn2G, regdmn5G, ctl2G, ctl5G);
4850 if (status == QDF_STATUS_E_NOMEM)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004851 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004852
4853 if ((((reg_dmn & ~COUNTRY_ERD_FLAG) == CTRY_JAPAN) ||
4854 ((reg_dmn & ~COUNTRY_ERD_FLAG) == CTRY_KOREA_ROC)) &&
4855 (true == wma->tx_chain_mask_cck))
4856 cck_mask_val = 1;
4857
4858 cck_mask_val |= (wma->self_gen_frm_pwr << 16);
Govind Singhd76a5b02016-03-08 15:12:14 +05304859 pdev_param.param_id = WMI_PDEV_PARAM_TX_CHAIN_MASK_CCK;
4860 pdev_param.param_value = cck_mask_val;
4861 ret = wmi_unified_pdev_param_send(wma->wmi_handle,
4862 &pdev_param,
4863 WMA_WILDCARD_PDEV_ID);
4864
Himanshu Agarwal44195412016-03-09 13:03:54 +05304865 if (QDF_IS_STATUS_ERROR(ret))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004866 WMA_LOGE("failed to set PDEV tx_chain_mask_cck %d",
4867 ret);
4868
4869 return;
4870}
4871
4872/**
Houston Hoffmana76591b2015-11-10 16:52:05 -08004873 * wma_post_runtime_resume_msg() - post the resume request
4874 * @handle: validated wma handle
4875 *
4876 * request the MC thread unpaus the vdev and set resume dtim
4877 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304878 * Return: qdf status of the mq post
Houston Hoffmana76591b2015-11-10 16:52:05 -08004879 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304880static QDF_STATUS wma_post_runtime_resume_msg(WMA_HANDLE handle)
Houston Hoffmana76591b2015-11-10 16:52:05 -08004881{
4882 cds_msg_t resume_msg;
4883
4884 resume_msg.bodyptr = NULL;
4885 resume_msg.type = WMA_RUNTIME_PM_RESUME_IND;
Anurag Chouhan6d760662016-02-20 16:05:43 +05304886 return cds_mq_post_message(QDF_MODULE_ID_WMA, &resume_msg);
Houston Hoffmana76591b2015-11-10 16:52:05 -08004887}
4888
4889/**
4890 * wma_post_runtime_suspend_msg() - post the suspend request
4891 * @handle: validated wma handle
4892 *
4893 * Requests for offloads to be configured for runtime suspend
4894 * on the MC thread
4895 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304896 * Return QDF_STATUS_E_AGAIN in case of timeout or QDF_STATUS_SUCCESS
Houston Hoffmana76591b2015-11-10 16:52:05 -08004897 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304898static QDF_STATUS wma_post_runtime_suspend_msg(WMA_HANDLE handle)
Houston Hoffmana76591b2015-11-10 16:52:05 -08004899{
4900 cds_msg_t cds_msg;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304901 QDF_STATUS qdf_status;
Houston Hoffmana76591b2015-11-10 16:52:05 -08004902 tp_wma_handle wma = (tp_wma_handle) handle;
4903
Anurag Chouhance0dc992016-02-16 18:18:03 +05304904 qdf_event_reset(&wma->runtime_suspend);
Houston Hoffmana76591b2015-11-10 16:52:05 -08004905
4906 cds_msg.bodyptr = NULL;
4907 cds_msg.type = WMA_RUNTIME_PM_SUSPEND_IND;
Anurag Chouhan6d760662016-02-20 16:05:43 +05304908 qdf_status = cds_mq_post_message(QDF_MODULE_ID_WMA, &cds_msg);
Houston Hoffmana76591b2015-11-10 16:52:05 -08004909
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304910 if (qdf_status != QDF_STATUS_SUCCESS)
Houston Hoffmana76591b2015-11-10 16:52:05 -08004911 goto failure;
4912
Anurag Chouhance0dc992016-02-16 18:18:03 +05304913 if (qdf_wait_single_event(&wma->runtime_suspend,
Houston Hoffmana76591b2015-11-10 16:52:05 -08004914 WMA_TGT_SUSPEND_COMPLETE_TIMEOUT) !=
Anurag Chouhance0dc992016-02-16 18:18:03 +05304915 QDF_STATUS_SUCCESS) {
Houston Hoffmana76591b2015-11-10 16:52:05 -08004916 WMA_LOGE("Failed to get runtime suspend event");
4917 goto failure;
4918 }
4919
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304920 return QDF_STATUS_SUCCESS;
Houston Hoffmana76591b2015-11-10 16:52:05 -08004921
4922failure:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304923 return QDF_STATUS_E_AGAIN;
Houston Hoffmana76591b2015-11-10 16:52:05 -08004924}
4925
4926/**
4927 * __wma_bus_suspend(): handles bus suspend for wma
4928 * @type: is this suspend part of runtime suspend or system suspend?
4929 *
4930 * Bails if a scan is in progress.
4931 * Calls the appropriate handlers based on configuration and event.
4932 *
4933 * Return: 0 for success or error code
4934 */
Anurag Chouhan6d760662016-02-20 16:05:43 +05304935static int __wma_bus_suspend(enum qdf_suspend_type type)
Houston Hoffmana76591b2015-11-10 16:52:05 -08004936{
Anurag Chouhan6d760662016-02-20 16:05:43 +05304937 WMA_HANDLE handle = cds_get_context(QDF_MODULE_ID_WMA);
Houston Hoffmana76591b2015-11-10 16:52:05 -08004938 if (NULL == handle) {
4939 WMA_LOGE("%s: wma context is NULL", __func__);
4940 return -EFAULT;
4941 }
4942
4943 if (wma_check_scan_in_progress(handle)) {
4944 WMA_LOGE("%s: Scan in progress. Aborting suspend", __func__);
4945 return -EBUSY;
4946 }
4947
Anurag Chouhan6d760662016-02-20 16:05:43 +05304948 if (type == QDF_RUNTIME_SUSPEND) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304949 QDF_STATUS status = wma_post_runtime_suspend_msg(handle);
Houston Hoffmana76591b2015-11-10 16:52:05 -08004950 if (status)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304951 return qdf_status_to_os_return(status);
Houston Hoffmana76591b2015-11-10 16:52:05 -08004952 }
4953
Anurag Chouhan6d760662016-02-20 16:05:43 +05304954 if (type == QDF_SYSTEM_SUSPEND)
Houston Hoffmana76591b2015-11-10 16:52:05 -08004955 WMA_LOGE("%s: wow mode selected %d", __func__,
4956 wma_is_wow_mode_selected(handle));
4957
4958 if (wma_is_wow_mode_selected(handle)) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304959 QDF_STATUS status = wma_enable_wow_in_fw(handle);
4960 return qdf_status_to_os_return(status);
Houston Hoffmana76591b2015-11-10 16:52:05 -08004961 }
4962
4963 return wma_suspend_target(handle, 0);
4964}
4965
4966/**
4967 * wma_runtime_suspend() - handles runtime suspend request from hdd
4968 *
4969 * Calls the appropriate handler based on configuration and event.
4970 * Last busy marking should prevent race conditions between processing
4971 * of asyncronous fw events and the running of runtime suspend.
4972 * (eg. last busy marking should guarantee that any auth requests have
4973 * been processed)
4974 * Events comming from the host are not protected, but aren't expected
4975 * to be an issue.
4976 *
4977 * Return: 0 for success or error code
4978 */
4979int wma_runtime_suspend(void)
4980{
Anurag Chouhan6d760662016-02-20 16:05:43 +05304981 return __wma_bus_suspend(QDF_RUNTIME_SUSPEND);
Houston Hoffmana76591b2015-11-10 16:52:05 -08004982}
4983
4984/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004985 * wma_bus_suspend() - handles bus suspend request from hdd
4986 *
4987 * Calls the appropriate handler based on configuration and event
4988 *
4989 * Return: 0 for success or error code
4990 */
4991int wma_bus_suspend(void)
4992{
Houston Hoffmana76591b2015-11-10 16:52:05 -08004993
Anurag Chouhan6d760662016-02-20 16:05:43 +05304994 return __wma_bus_suspend(QDF_SYSTEM_SUSPEND);
Houston Hoffmana76591b2015-11-10 16:52:05 -08004995}
4996
4997/**
4998 * __wma_bus_resume() - bus resume for wma
4999 *
5000 * does the part of the bus resume common to bus and system suspend
5001 *
5002 * Return: os error code.
5003 */
5004int __wma_bus_resume(WMA_HANDLE handle)
5005{
5006 bool wow_mode = wma_is_wow_mode_selected(handle);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305007 QDF_STATUS status;
Houston Hoffmana76591b2015-11-10 16:52:05 -08005008
5009 WMA_LOGE("%s: wow mode %d", __func__, wow_mode);
5010
5011 if (!wow_mode)
5012 return wma_resume_target(handle);
5013
5014 status = wma_disable_wow_in_fw(handle);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305015 return qdf_status_to_os_return(status);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005016}
5017
5018/**
5019 * wma_runtime_resume() - do the runtime resume operation for wma
5020 *
5021 * Return: os error code.
5022 */
5023int wma_runtime_resume(void)
5024{
5025 int ret;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305026 QDF_STATUS status;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305027 WMA_HANDLE handle = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005028 if (NULL == handle) {
5029 WMA_LOGE("%s: wma context is NULL", __func__);
5030 return -EFAULT;
5031 }
5032
Houston Hoffmana76591b2015-11-10 16:52:05 -08005033 ret = __wma_bus_resume(handle);
5034 if (ret)
5035 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005036
Houston Hoffmana76591b2015-11-10 16:52:05 -08005037 status = wma_post_runtime_resume_msg(handle);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305038 return qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005039}
5040
5041/**
5042 * wma_bus_resume() - handles bus resume request from hdd
5043 * @handle: valid wma handle
5044 *
5045 * Calls the appropriate handler based on configuration
5046 *
5047 * Return: 0 for success or error code
5048 */
5049int wma_bus_resume(void)
5050{
Anurag Chouhan6d760662016-02-20 16:05:43 +05305051 WMA_HANDLE handle = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005052 if (NULL == handle) {
5053 WMA_LOGE("%s: wma context is NULL", __func__);
5054 return -EFAULT;
5055 }
5056
Houston Hoffmana76591b2015-11-10 16:52:05 -08005057 return __wma_bus_resume(handle);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005058}
5059
5060/**
5061 * wma_suspend_target() - suspend target
5062 * @handle: wma handle
5063 * @disable_target_intr: disable target interrupt
5064 *
Govind Singhd76a5b02016-03-08 15:12:14 +05305065 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005066 */
Govind Singhd76a5b02016-03-08 15:12:14 +05305067QDF_STATUS wma_suspend_target(WMA_HANDLE handle, int disable_target_intr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005068{
5069 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Komal Seelam3d202862016-02-24 18:43:24 +05305070 struct hif_opaque_softc *scn;
Govind Singhd76a5b02016-03-08 15:12:14 +05305071 QDF_STATUS status;
5072 struct suspend_params param = {0};
5073
Yue Mae1a85f32015-10-20 18:12:45 -07005074#ifdef CONFIG_CNSS
Anurag Chouhan6d760662016-02-20 16:05:43 +05305075 tpAniSirGlobal pmac = cds_get_context(QDF_MODULE_ID_PE);
Yue Mae1a85f32015-10-20 18:12:45 -07005076#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005077
5078 if (!wma_handle || !wma_handle->wmi_handle) {
5079 WMA_LOGE("WMA is closed. can not issue suspend cmd");
Govind Singhd76a5b02016-03-08 15:12:14 +05305080 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005081 }
Yue Mae1a85f32015-10-20 18:12:45 -07005082
5083#ifdef CONFIG_CNSS
5084 if (NULL == pmac) {
5085 WMA_LOGE("%s: Unable to get PE context", __func__);
Govind Singhd76a5b02016-03-08 15:12:14 +05305086 return QDF_STATUS_E_INVAL;
Yue Mae1a85f32015-10-20 18:12:45 -07005087 }
5088#endif
Anurag Chouhance0dc992016-02-16 18:18:03 +05305089 qdf_event_reset(&wma_handle->target_suspend);
Govind Singhd76a5b02016-03-08 15:12:14 +05305090 param.disable_target_intr = disable_target_intr;
5091 status = wmi_unified_suspend_send(wma_handle->wmi_handle,
5092 &param,
5093 WMA_WILDCARD_PDEV_ID);
5094 if (QDF_IS_STATUS_ERROR(status))
5095 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005096
5097 wmi_set_target_suspend(wma_handle->wmi_handle, true);
5098
Anurag Chouhance0dc992016-02-16 18:18:03 +05305099 if (qdf_wait_single_event(&wma_handle->target_suspend,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005100 WMA_TGT_SUSPEND_COMPLETE_TIMEOUT)
Anurag Chouhance0dc992016-02-16 18:18:03 +05305101 != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005102 WMA_LOGE("Failed to get ACK from firmware for pdev suspend");
5103 wmi_set_target_suspend(wma_handle->wmi_handle, false);
Yue Mae1a85f32015-10-20 18:12:45 -07005104#ifdef CONFIG_CNSS
Prashanth Bhatta9e143052015-12-04 11:56:47 -08005105 if (!cds_is_driver_recovering()) {
Yue Ma455aff62015-10-20 18:29:16 -07005106 if (pmac->sme.enableSelfRecovery) {
5107 cds_trigger_recovery();
5108 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305109 QDF_BUG(0);
Yue Ma455aff62015-10-20 18:29:16 -07005110 }
Yue Mae1a85f32015-10-20 18:12:45 -07005111 } else {
Yue Ma455aff62015-10-20 18:29:16 -07005112 WMA_LOGE("%s: LOGP is in progress, ignore!", __func__);
Yue Mae1a85f32015-10-20 18:12:45 -07005113 }
5114#endif
Govind Singhd76a5b02016-03-08 15:12:14 +05305115 return QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005116 }
5117
Anurag Chouhan6d760662016-02-20 16:05:43 +05305118 scn = cds_get_context(QDF_MODULE_ID_HIF);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005119
5120 if (scn == NULL) {
5121 WMA_LOGE("%s: Failed to get HIF context", __func__);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305122 QDF_ASSERT(0);
Govind Singhd76a5b02016-03-08 15:12:14 +05305123 return QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005124 }
5125
Govind Singhd76a5b02016-03-08 15:12:14 +05305126 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005127}
5128
5129/**
5130 * wma_target_suspend_acknowledge() - update target susspend status
5131 * @context: wma context
5132 *
5133 * Return: none
5134 */
5135void wma_target_suspend_acknowledge(void *context)
5136{
Anurag Chouhan6d760662016-02-20 16:05:43 +05305137 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005138 int wow_nack = *((int *)context);
5139
5140 if (NULL == wma) {
5141 WMA_LOGE("%s: wma is NULL", __func__);
5142 return;
5143 }
5144
5145 wma->wow_nack = wow_nack;
Anurag Chouhance0dc992016-02-16 18:18:03 +05305146 qdf_event_set(&wma->target_suspend);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005147 if (wow_nack)
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305148 qdf_wake_lock_timeout_acquire(&wma->wow_wake_lock,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005149 WMA_WAKE_LOCK_TIMEOUT,
5150 WIFI_POWER_EVENT_WAKELOCK_WOW);
5151}
5152
5153/**
5154 * wma_resume_target() - resume target
5155 * @handle: wma handle
5156 *
Govind Singhd76a5b02016-03-08 15:12:14 +05305157 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005158 */
Govind Singhd76a5b02016-03-08 15:12:14 +05305159QDF_STATUS wma_resume_target(WMA_HANDLE handle)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005160{
5161 int ret;
5162 tp_wma_handle wma = (tp_wma_handle) handle;
Anurag Chouhance0dc992016-02-16 18:18:03 +05305163 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005164#ifdef CONFIG_CNSS
Anurag Chouhan6d760662016-02-20 16:05:43 +05305165 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005166 if (NULL == pMac) {
5167 WMA_LOGE("%s: Unable to get PE context", __func__);
Govind Singhd76a5b02016-03-08 15:12:14 +05305168 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005169 }
5170#endif /* CONFIG_CNSS */
5171
Anurag Chouhance0dc992016-02-16 18:18:03 +05305172 qdf_event_reset(&wma->wma_resume_event);
Govind Singhd76a5b02016-03-08 15:12:14 +05305173 qdf_status = wmi_unified_resume_send(wma->wmi_handle,
5174 WMA_WILDCARD_PDEV_ID);
5175 if (QDF_IS_STATUS_ERROR(qdf_status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005176 WMA_LOGE("Failed to send WMI_PDEV_RESUME_CMDID command");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005177
Anurag Chouhance0dc992016-02-16 18:18:03 +05305178 qdf_status = qdf_wait_single_event(&(wma->wma_resume_event),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005179 WMA_RESUME_TIMEOUT);
Anurag Chouhance0dc992016-02-16 18:18:03 +05305180 if (QDF_STATUS_SUCCESS != qdf_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005181 WMA_LOGP("%s: Timeout waiting for resume event from FW",
5182 __func__);
5183 WMA_LOGP("%s: Pending commands %d credits %d", __func__,
5184 wmi_get_pending_cmds(wma->wmi_handle),
5185 wmi_get_host_credits(wma->wmi_handle));
Prashanth Bhatta9e143052015-12-04 11:56:47 -08005186 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005187#ifdef CONFIG_CNSS
5188 if (pMac->sme.enableSelfRecovery) {
5189 cds_trigger_recovery();
5190 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305191 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005192 }
5193#else
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305194 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005195#endif /* CONFIG_CNSS */
5196 } else {
5197 WMA_LOGE("%s: SSR in progress, ignore resume timeout",
5198 __func__);
5199 }
5200 } else {
5201 WMA_LOGD("Host wakeup received");
5202 }
5203
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305204 if (QDF_STATUS_SUCCESS == qdf_status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005205 wmi_set_target_suspend(wma->wmi_handle, false);
5206
5207 return ret;
5208}
5209
5210/**
5211 * wma_get_modeselect() - get modeSelect flag based on phy_capability
5212 * @wma: wma handle
5213 * @modeSelect: mode Select
5214 *
5215 * Return: none
5216 */
5217void wma_get_modeselect(tp_wma_handle wma, uint32_t *modeSelect)
5218{
5219
5220 switch (wma->phy_capability) {
5221 case WMI_11G_CAPABILITY:
5222 case WMI_11NG_CAPABILITY:
5223 *modeSelect &= ~(REGDMN_MODE_11A | REGDMN_MODE_TURBO |
5224 REGDMN_MODE_108A | REGDMN_MODE_11A_HALF_RATE |
5225 REGDMN_MODE_11A_QUARTER_RATE |
5226 REGDMN_MODE_11NA_HT20 |
5227 REGDMN_MODE_11NA_HT40PLUS |
5228 REGDMN_MODE_11NA_HT40MINUS |
5229 REGDMN_MODE_11AC_VHT20 |
5230 REGDMN_MODE_11AC_VHT40PLUS |
5231 REGDMN_MODE_11AC_VHT40MINUS |
5232 REGDMN_MODE_11AC_VHT80);
5233 break;
5234 case WMI_11A_CAPABILITY:
5235 case WMI_11NA_CAPABILITY:
5236 case WMI_11AC_CAPABILITY:
5237 *modeSelect &= ~(REGDMN_MODE_11B | REGDMN_MODE_11G |
5238 REGDMN_MODE_108G | REGDMN_MODE_11NG_HT20 |
5239 REGDMN_MODE_11NG_HT40PLUS |
5240 REGDMN_MODE_11NG_HT40MINUS |
5241 REGDMN_MODE_11AC_VHT20_2G |
5242 REGDMN_MODE_11AC_VHT40_2G |
5243 REGDMN_MODE_11AC_VHT80_2G);
5244 break;
5245 }
5246}
5247
5248
5249#ifdef FEATURE_WLAN_TDLS
5250/**
5251 * wma_tdls_event_handler() - handle TDLS event
5252 * @handle: wma handle
5253 * @event: event buffer
5254 * @len: buffer length
5255 *
5256 * Return: 0 for success or error code
5257 */
5258int wma_tdls_event_handler(void *handle, uint8_t *event, uint32_t len)
5259{
5260 tp_wma_handle wma = (tp_wma_handle) handle;
5261 WMI_TDLS_PEER_EVENTID_param_tlvs *param_buf = NULL;
5262 wmi_tdls_peer_event_fixed_param *peer_event = NULL;
5263 tSirTdlsEventnotify *tdls_event;
5264
5265 if (!event) {
5266 WMA_LOGE("%s: event param null", __func__);
5267 return -EINVAL;
5268 }
5269
5270 param_buf = (WMI_TDLS_PEER_EVENTID_param_tlvs *) event;
5271 if (!param_buf) {
5272 WMA_LOGE("%s: received null buf from target", __func__);
5273 return -EINVAL;
5274 }
5275
5276 peer_event = param_buf->fixed_param;
5277 if (!peer_event) {
5278 WMA_LOGE("%s: received null event data from target", __func__);
5279 return -EINVAL;
5280 }
5281
5282 tdls_event = (tSirTdlsEventnotify *)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305283 qdf_mem_malloc(sizeof(*tdls_event));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005284 if (!tdls_event) {
5285 WMA_LOGE("%s: failed to allocate memory for tdls_event",
5286 __func__);
5287 return -ENOMEM;
5288 }
5289
5290 tdls_event->sessionId = peer_event->vdev_id;
5291 WMI_MAC_ADDR_TO_CHAR_ARRAY(&peer_event->peer_macaddr,
Srinivas Girigowda4f593792015-11-19 15:33:42 -08005292 tdls_event->peermac.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005293
5294 switch (peer_event->peer_status) {
5295 case WMI_TDLS_SHOULD_DISCOVER:
5296 tdls_event->messageType = WMA_TDLS_SHOULD_DISCOVER_CMD;
5297 break;
5298 case WMI_TDLS_SHOULD_TEARDOWN:
5299 tdls_event->messageType = WMA_TDLS_SHOULD_TEARDOWN_CMD;
5300 break;
5301 case WMI_TDLS_PEER_DISCONNECTED:
5302 tdls_event->messageType = WMA_TDLS_PEER_DISCONNECTED_CMD;
5303 break;
5304 default:
5305 WMA_LOGE("%s: Discarding unknown tdls event(%d) from target",
5306 __func__, peer_event->peer_status);
5307 return -EINVAL;
5308 }
5309
5310 switch (peer_event->peer_reason) {
5311 case WMI_TDLS_TEARDOWN_REASON_TX:
5312 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_TX;
5313 break;
5314 case WMI_TDLS_TEARDOWN_REASON_RSSI:
5315 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_RSSI;
5316 break;
5317 case WMI_TDLS_TEARDOWN_REASON_SCAN:
5318 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_SCAN;
5319 break;
5320 case WMI_TDLS_DISCONNECTED_REASON_PEER_DELETE:
5321 tdls_event->peer_reason =
5322 eWNI_TDLS_DISCONNECTED_REASON_PEER_DELETE;
5323 break;
5324 case WMI_TDLS_TEARDOWN_REASON_PTR_TIMEOUT:
5325 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_PTR_TIMEOUT;
5326 break;
5327 case WMI_TDLS_TEARDOWN_REASON_BAD_PTR:
5328 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_BAD_PTR;
5329 break;
5330 case WMI_TDLS_TEARDOWN_REASON_NO_RESPONSE:
5331 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_NO_RESPONSE;
5332 break;
5333 default:
5334 WMA_LOGE("%s: unknown reason(%d) in tdls event(%d) from target",
5335 __func__, peer_event->peer_reason,
5336 peer_event->peer_status);
5337 return -EINVAL;
5338 }
5339
5340 WMA_LOGD("%s: sending msg to umac, messageType: 0x%x, "
5341 "for peer: %pM, reason: %d, smesessionId: %d",
Srinivas Girigowda4f593792015-11-19 15:33:42 -08005342 __func__, tdls_event->messageType, tdls_event->peermac.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005343 tdls_event->peer_reason, tdls_event->sessionId);
5344
5345 wma_send_msg(wma, tdls_event->messageType, (void *)tdls_event, 0);
5346 return 0;
5347}
5348
5349/**
5350 * wma_set_tdls_offchan_mode() - set tdls off channel mode
5351 * @handle: wma handle
5352 * @chan_switch_params: Pointer to tdls channel switch parameter structure
5353 *
5354 * This function sets tdls off channel mode
5355 *
5356 * Return: 0 on success; Negative errno otherwise
5357 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05305358QDF_STATUS wma_set_tdls_offchan_mode(WMA_HANDLE handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005359 tdls_chan_switch_params *chan_switch_params)
5360{
5361 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Himanshu Agarwal44195412016-03-09 13:03:54 +05305362 struct tdls_channel_switch_params params = {0};
5363 QDF_STATUS ret = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005364
5365 if (!wma_handle || !wma_handle->wmi_handle) {
5366 WMA_LOGE(FL(
5367 "WMA is closed, can not issue tdls off channel cmd"
5368 ));
5369 ret = -EINVAL;
5370 goto end;
5371 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005372
Himanshu Agarwal44195412016-03-09 13:03:54 +05305373 params.vdev_id = chan_switch_params->vdev_id;
5374 params.tdls_off_ch_bw_offset =
5375 chan_switch_params->tdls_off_ch_bw_offset;
5376 params.tdls_off_ch = chan_switch_params->tdls_off_ch;
5377 params.tdls_sw_mode = chan_switch_params->tdls_sw_mode;
5378 params.oper_class = chan_switch_params->oper_class;
5379 params.is_responder = chan_switch_params->is_responder;
5380 qdf_mem_copy(params.peer_mac_addr, chan_switch_params->peer_mac_addr,
5381 WMI_ETH_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005382
Himanshu Agarwal44195412016-03-09 13:03:54 +05305383 ret = wmi_unified_set_tdls_offchan_mode_cmd(wma_handle->wmi_handle,
5384 &params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005385
5386end:
5387 if (chan_switch_params)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305388 qdf_mem_free(chan_switch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005389 return ret;
5390}
5391
5392/**
5393 * wma_update_fw_tdls_state() - send enable/disable tdls for a vdev
5394 * @wma: wma handle
5395 * @pwmaTdlsparams: TDLS params
5396 *
5397 * Return: 0 for sucess or error code
5398 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05305399QDF_STATUS wma_update_fw_tdls_state(WMA_HANDLE handle, void *pwmaTdlsparams)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005400{
5401 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005402 t_wma_tdls_mode tdls_mode;
5403 t_wma_tdls_params *wma_tdls = (t_wma_tdls_params *) pwmaTdlsparams;
Himanshu Agarwal44195412016-03-09 13:03:54 +05305404 struct wmi_tdls_params params = {0};
5405 QDF_STATUS ret = QDF_STATUS_SUCCESS;
5406 uint8_t tdls_state;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005407
5408 if (!wma_handle || !wma_handle->wmi_handle) {
5409 WMA_LOGE("%s: WMA is closed, can not issue fw tdls state cmd",
5410 __func__);
5411 ret = -EINVAL;
5412 goto end_fw_tdls_state;
5413 }
5414
Himanshu Agarwal44195412016-03-09 13:03:54 +05305415 params.tdls_state = wma_tdls->tdls_state;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005416 tdls_mode = wma_tdls->tdls_state;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005417
5418 if (WMA_TDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY == tdls_mode) {
Himanshu Agarwal44195412016-03-09 13:03:54 +05305419 tdls_state = WMI_TDLS_ENABLE_PASSIVE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005420 } else if (WMA_TDLS_SUPPORT_ENABLED == tdls_mode) {
Himanshu Agarwal44195412016-03-09 13:03:54 +05305421 tdls_state = WMI_TDLS_ENABLE_ACTIVE;
Kabilan Kannan421714b2015-11-23 04:44:59 -08005422 } else if (WMA_TDLS_SUPPORT_ACTIVE_EXTERNAL_CONTROL == tdls_mode) {
Himanshu Agarwal44195412016-03-09 13:03:54 +05305423 tdls_state = WMI_TDLS_ENABLE_ACTIVE_EXTERNAL_CONTROL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005424 } else {
Himanshu Agarwal44195412016-03-09 13:03:54 +05305425 tdls_state = WMI_TDLS_DISABLE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005426 }
5427
Himanshu Agarwal44195412016-03-09 13:03:54 +05305428 params.vdev_id = wma_tdls->vdev_id;
5429 params.notification_interval_ms = wma_tdls->notification_interval_ms;
5430 params.tx_discovery_threshold = wma_tdls->tx_discovery_threshold;
5431 params.tx_teardown_threshold = wma_tdls->tx_teardown_threshold;
5432 params.rssi_teardown_threshold = wma_tdls->rssi_teardown_threshold;
5433 params.rssi_delta = wma_tdls->rssi_delta;
5434 params.tdls_options = wma_tdls->tdls_options;
5435 params.peer_traffic_ind_window = wma_tdls->peer_traffic_ind_window;
5436 params.peer_traffic_response_timeout =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005437 wma_tdls->peer_traffic_response_timeout;
Himanshu Agarwal44195412016-03-09 13:03:54 +05305438 params.puapsd_mask = wma_tdls->puapsd_mask;
5439 params.puapsd_inactivity_time = wma_tdls->puapsd_inactivity_time;
5440 params.puapsd_rx_frame_threshold =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005441 wma_tdls->puapsd_rx_frame_threshold;
Himanshu Agarwal44195412016-03-09 13:03:54 +05305442 params.teardown_notification_ms =
Kabilan Kannanca670be2015-11-23 01:56:12 -08005443 wma_tdls->teardown_notification_ms;
Himanshu Agarwal44195412016-03-09 13:03:54 +05305444 params.tdls_peer_kickout_threshold =
Kabilan Kannan421714b2015-11-23 04:44:59 -08005445 wma_tdls->tdls_peer_kickout_threshold;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005446
Himanshu Agarwal44195412016-03-09 13:03:54 +05305447 ret = wmi_unified_update_fw_tdls_state_cmd(wma_handle->wmi_handle,
5448 &params, tdls_state);
5449 if (QDF_IS_STATUS_ERROR(ret))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005450 goto end_fw_tdls_state;
Himanshu Agarwal44195412016-03-09 13:03:54 +05305451
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005452 WMA_LOGD("%s: vdev_id %d", __func__, wma_tdls->vdev_id);
5453
5454end_fw_tdls_state:
5455 if (pwmaTdlsparams)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305456 qdf_mem_free(pwmaTdlsparams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005457 return ret;
5458}
5459
5460/**
5461 * wma_update_tdls_peer_state() - update TDLS peer state
5462 * @handle: wma handle
5463 * @peerStateParams: TDLS peer state params
5464 *
5465 * Return: 0 for success or error code
5466 */
5467int wma_update_tdls_peer_state(WMA_HANDLE handle,
5468 tTdlsPeerStateParams *peerStateParams)
5469{
5470 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005471 uint32_t i;
5472 ol_txrx_pdev_handle pdev;
5473 uint8_t peer_id;
5474 struct ol_txrx_peer_t *peer;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005475 int ret = 0;
Govind Singhaa64c242016-03-08 11:31:49 +05305476 uint32_t *ch_mhz;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005477
5478 if (!wma_handle || !wma_handle->wmi_handle) {
5479 WMA_LOGE("%s: WMA is closed, can not issue cmd", __func__);
5480 ret = -EINVAL;
5481 goto end_tdls_peer_state;
5482 }
5483
5484 /* peer capability info is valid only when peer state is connected */
5485 if (WMA_TDLS_PEER_STATE_CONNECTED != peerStateParams->peerState) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305486 qdf_mem_zero(&peerStateParams->peerCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005487 sizeof(tTdlsPeerCapParams));
5488 }
5489
Govind Singhaa64c242016-03-08 11:31:49 +05305490 ch_mhz = qdf_mem_malloc(sizeof(uint32_t) *
5491 peerStateParams->peerCap.peerChanLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005492 for (i = 0; i < peerStateParams->peerCap.peerChanLen; ++i) {
Govind Singhaa64c242016-03-08 11:31:49 +05305493 ch_mhz[i] =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005494 cds_chan_to_freq(peerStateParams->peerCap.peerChan[i].
5495 chanId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005496 }
5497
Govind Singhaa64c242016-03-08 11:31:49 +05305498 if (wmi_unified_update_tdls_peer_state_cmd(wma_handle->wmi_handle,
5499 (struct tdls_peer_state_params *)peerStateParams,
5500 ch_mhz)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005501 WMA_LOGE("%s: failed to send tdls peer update state command",
5502 __func__);
Govind Singhaa64c242016-03-08 11:31:49 +05305503 qdf_mem_free(ch_mhz);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005504 ret = -EIO;
5505 goto end_tdls_peer_state;
5506 }
5507
Govind Singhaa64c242016-03-08 11:31:49 +05305508 qdf_mem_free(ch_mhz);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005509 /* in case of teardown, remove peer from fw */
5510 if (WMA_TDLS_PEER_STATE_TEARDOWN == peerStateParams->peerState) {
Anurag Chouhan6d760662016-02-20 16:05:43 +05305511 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005512 if (!pdev) {
5513 WMA_LOGE("%s: Failed to find pdev", __func__);
5514 ret = -EIO;
5515 goto end_tdls_peer_state;
5516 }
5517
5518 peer = ol_txrx_find_peer_by_addr(pdev,
5519 peerStateParams->peerMacAddr,
5520 &peer_id);
5521 if (!peer) {
5522 WMA_LOGE("%s: Failed to get peer handle using peer mac %pM",
5523 __func__, peerStateParams->peerMacAddr);
5524 ret = -EIO;
5525 goto end_tdls_peer_state;
5526 }
5527
5528 WMA_LOGD("%s: calling wma_remove_peer for peer " MAC_ADDRESS_STR
5529 " vdevId: %d", __func__,
5530 MAC_ADDR_ARRAY(peer->mac_addr.raw),
5531 peerStateParams->vdevId);
5532 wma_remove_peer(wma_handle, peer->mac_addr.raw,
5533 peerStateParams->vdevId, peer, false);
5534 }
5535
5536end_tdls_peer_state:
5537 if (peerStateParams)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305538 qdf_mem_free(peerStateParams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005539 return ret;
5540}
5541#endif /* FEATURE_WLAN_TDLS */
5542
5543
5544/**
5545 * wma_dfs_attach() - Attach DFS methods to the umac state.
5546 * @dfs_ic: ieee80211com ptr
5547 *
5548 * Return: Return ieee80211com ptr with updated info
5549 */
5550struct ieee80211com *wma_dfs_attach(struct ieee80211com *dfs_ic)
5551{
5552 /*Allocate memory for dfs_ic before passing it up to dfs_attach() */
5553 dfs_ic = (struct ieee80211com *)
5554 os_malloc(NULL, sizeof(struct ieee80211com), GFP_ATOMIC);
5555 if (dfs_ic == NULL) {
5556 WMA_LOGE("%s:Allocation of dfs_ic failed %zu",
5557 __func__, sizeof(struct ieee80211com));
5558 return NULL;
5559 }
5560 OS_MEMZERO(dfs_ic, sizeof(struct ieee80211com));
5561 /* DFS pattern matching hooks */
5562 dfs_ic->ic_dfs_attach = ol_if_dfs_attach;
5563 dfs_ic->ic_dfs_disable = ol_if_dfs_disable;
5564 dfs_ic->ic_find_channel = ieee80211_find_channel;
5565 dfs_ic->ic_dfs_enable = ol_if_dfs_enable;
5566 dfs_ic->ic_ieee2mhz = ieee80211_ieee2mhz;
5567
5568 /* Hardware facing hooks */
5569 dfs_ic->ic_get_ext_busy = ol_if_dfs_get_ext_busy;
5570 dfs_ic->ic_get_mib_cycle_counts_pct =
5571 ol_if_dfs_get_mib_cycle_counts_pct;
5572 dfs_ic->ic_get_TSF64 = ol_if_get_tsf64;
5573
5574 /* NOL related hooks */
5575 dfs_ic->ic_dfs_usenol = ol_if_dfs_usenol;
5576 /*
5577 * Hooks from wma/dfs/ back
5578 * into the PE/SME
5579 * and shared DFS code
5580 */
5581 dfs_ic->ic_dfs_notify_radar = ieee80211_mark_dfs;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305582 qdf_spinlock_create(&dfs_ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005583 /* Initializes DFS Data Structures and queues */
5584 dfs_attach(dfs_ic);
5585
5586 return dfs_ic;
5587}
5588
5589/**
5590 * wma_dfs_detach() - Detach DFS methods
5591 * @dfs_ic: ieee80211com ptr
5592 *
5593 * Return: none
5594 */
5595void wma_dfs_detach(struct ieee80211com *dfs_ic)
5596{
5597 dfs_detach(dfs_ic);
5598
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305599 qdf_spinlock_destroy(&dfs_ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005600 if (NULL != dfs_ic->ic_curchan) {
5601 OS_FREE(dfs_ic->ic_curchan);
5602 dfs_ic->ic_curchan = NULL;
5603 }
5604
5605 OS_FREE(dfs_ic);
5606}
5607
5608/**
5609 * wma_dfs_configure() - configure dfs
5610 * @ic: ieee80211com ptr
5611 *
5612 * Configures Radar Filters during
5613 * vdev start/channel change/regulatory domain
5614 * change.This Configuration enables to program
5615 * the DFS pattern matching module.
5616 *
5617 * Return: none
5618 */
5619void wma_dfs_configure(struct ieee80211com *ic)
5620{
5621 struct ath_dfs_radar_tab_info rinfo;
5622 int dfsdomain;
5623 int radar_enabled_status = 0;
5624 if (ic == NULL) {
5625 WMA_LOGE("%s: DFS ic is Invalid", __func__);
5626 return;
5627 }
5628
5629 dfsdomain = ic->current_dfs_regdomain;
5630
5631 /* Fetch current radar patterns from the lmac */
5632 OS_MEMZERO(&rinfo, sizeof(rinfo));
5633
5634 /*
5635 * Look up the current DFS
5636 * regulatory domain and decide
5637 * which radar pulses to use.
5638 */
5639 switch (dfsdomain) {
5640 case DFS_FCC_DOMAIN:
5641 WMA_LOGI("%s: DFS-FCC domain", __func__);
5642 rinfo.dfsdomain = DFS_FCC_DOMAIN;
5643 rinfo.dfs_radars = dfs_fcc_radars;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305644 rinfo.numradars = QDF_ARRAY_SIZE(dfs_fcc_radars);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005645 rinfo.b5pulses = dfs_fcc_bin5pulses;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305646 rinfo.numb5radars = QDF_ARRAY_SIZE(dfs_fcc_bin5pulses);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005647 break;
5648 case DFS_ETSI_DOMAIN:
5649 WMA_LOGI("%s: DFS-ETSI domain", __func__);
5650 rinfo.dfsdomain = DFS_ETSI_DOMAIN;
5651 rinfo.dfs_radars = dfs_etsi_radars;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305652 rinfo.numradars = QDF_ARRAY_SIZE(dfs_etsi_radars);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005653 rinfo.b5pulses = NULL;
5654 rinfo.numb5radars = 0;
5655 break;
5656 case DFS_MKK4_DOMAIN:
5657 WMA_LOGI("%s: DFS-MKK4 domain", __func__);
5658 rinfo.dfsdomain = DFS_MKK4_DOMAIN;
5659 rinfo.dfs_radars = dfs_mkk4_radars;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305660 rinfo.numradars = QDF_ARRAY_SIZE(dfs_mkk4_radars);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005661 rinfo.b5pulses = dfs_jpn_bin5pulses;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305662 rinfo.numb5radars = QDF_ARRAY_SIZE(dfs_jpn_bin5pulses);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005663 break;
5664 default:
5665 WMA_LOGI("%s: DFS-UNINT domain", __func__);
5666 rinfo.dfsdomain = DFS_UNINIT_DOMAIN;
5667 rinfo.dfs_radars = NULL;
5668 rinfo.numradars = 0;
5669 rinfo.b5pulses = NULL;
5670 rinfo.numb5radars = 0;
5671 break;
5672 }
5673
5674 rinfo.dfs_pri_multiplier = ic->dfs_pri_multiplier;
5675
5676 /*
5677 * Set the regulatory domain,
5678 * radar pulse table and enable
5679 * radar events if required.
5680 * dfs_radar_enable() returns
5681 * 0 on success and non-zero
5682 * failure.
5683 */
5684 radar_enabled_status = dfs_radar_enable(ic, &rinfo);
5685 if (radar_enabled_status != DFS_STATUS_SUCCESS) {
5686 WMA_LOGE("%s[%d]: DFS- Radar Detection Enabling Failed",
5687 __func__, __LINE__);
5688 }
5689}
5690
5691/**
5692 * wma_dfs_configure_channel() - configure DFS channel
5693 * @dfs_ic: ieee80211com ptr
Siddarth Poddar17dc4712016-03-09 16:30:27 +05305694 * @band_center_freq1: center frequency 1
5695 * @band_center_freq2: center frequency 2
5696 * (valid only for 11ac vht 80plus80 mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005697 * @ req: vdev start request
5698 *
5699 * Set the Channel parameters in to DFS module
5700 * Also,configure the DFS radar filters for
5701 * matching the DFS phyerrors.
5702 *
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05305703 * Return: dfs_ieee80211_channel / NULL for error
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005704 */
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05305705struct dfs_ieee80211_channel *wma_dfs_configure_channel(
5706 struct ieee80211com *dfs_ic,
Siddarth Poddar17dc4712016-03-09 16:30:27 +05305707 uint32_t band_center_freq1,
5708 uint32_t band_center_freq2,
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05305709 struct wma_vdev_start_req
5710 *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005711{
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08005712 uint8_t ext_channel;
5713
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005714 if (dfs_ic == NULL) {
5715 WMA_LOGE("%s: DFS ic is Invalid", __func__);
5716 return NULL;
5717 }
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05305718
5719 if (!dfs_ic->ic_curchan) {
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05305720 dfs_ic->ic_curchan = (struct dfs_ieee80211_channel *)os_malloc(
5721 NULL,
5722 sizeof(struct dfs_ieee80211_channel),
5723 GFP_ATOMIC);
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05305724 if (dfs_ic->ic_curchan == NULL) {
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05305725 WMA_LOGE(
5726 "%s: allocation of dfs_ic->ic_curchan failed %zu",
5727 __func__, sizeof(struct dfs_ieee80211_channel));
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05305728 return NULL;
5729 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005730 }
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05305731
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05305732 OS_MEMZERO(dfs_ic->ic_curchan, sizeof(struct dfs_ieee80211_channel));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005733
5734 dfs_ic->ic_curchan->ic_ieee = req->chan;
Siddarth Poddar17dc4712016-03-09 16:30:27 +05305735 dfs_ic->ic_curchan->ic_freq = cds_chan_to_freq(req->chan);
5736 dfs_ic->ic_curchan->ic_vhtop_ch_freq_seg1 = band_center_freq1;
5737 dfs_ic->ic_curchan->ic_vhtop_ch_freq_seg2 = band_center_freq2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005738 dfs_ic->ic_curchan->ic_pri_freq_center_freq_mhz_separation =
5739 dfs_ic->ic_curchan->ic_freq -
5740 dfs_ic->ic_curchan->ic_vhtop_ch_freq_seg1;
5741
5742 if ((dfs_ic->ic_curchan->ic_ieee >= WMA_11A_CHANNEL_BEGIN) &&
5743 (dfs_ic->ic_curchan->ic_ieee <= WMA_11A_CHANNEL_END)) {
5744 dfs_ic->ic_curchan->ic_flags |= IEEE80211_CHAN_5GHZ;
5745 }
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08005746
5747 switch (req->chan_width) {
5748 case CH_WIDTH_20MHZ:
5749 dfs_ic->ic_curchan->ic_flags |=
5750 (req->vht_capable ? IEEE80211_CHAN_VHT20 :
5751 IEEE80211_CHAN_HT20);
5752 break;
5753 case CH_WIDTH_40MHZ:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005754 if (req->chan < req->ch_center_freq_seg0)
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08005755 dfs_ic->ic_curchan->ic_flags |=
5756 (req->vht_capable ?
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005757 IEEE80211_CHAN_VHT40PLUS :
5758 IEEE80211_CHAN_HT40PLUS);
5759 else
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08005760 dfs_ic->ic_curchan->ic_flags |=
5761 (req->vht_capable ?
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005762 IEEE80211_CHAN_VHT40MINUS :
5763 IEEE80211_CHAN_HT40MINUS);
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08005764 break;
5765 case CH_WIDTH_80MHZ:
5766 dfs_ic->ic_curchan->ic_flags |= IEEE80211_CHAN_VHT80;
5767 break;
5768 case CH_WIDTH_80P80MHZ:
Siddarth Poddar17dc4712016-03-09 16:30:27 +05305769 ext_channel = cds_freq_to_chan(band_center_freq2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005770 dfs_ic->ic_curchan->ic_flags |=
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08005771 IEEE80211_CHAN_VHT80P80;
5772 dfs_ic->ic_curchan->ic_freq_ext =
Siddarth Poddar17dc4712016-03-09 16:30:27 +05305773 band_center_freq2;
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08005774 dfs_ic->ic_curchan->ic_ieee_ext = ext_channel;
5775
5776 /* verify both the 80MHz are DFS bands or not */
5777 if ((CHANNEL_STATE_DFS ==
5778 cds_get_bonded_channel_state(req->chan ,
5779 CH_WIDTH_80MHZ)) &&
5780 (CHANNEL_STATE_DFS ==
5781 cds_get_bonded_channel_state(
5782 ext_channel - 6 ,
5783 CH_WIDTH_80MHZ)))
5784 dfs_ic->ic_curchan->ic_80p80_both_dfs = true;
5785 break;
5786 case CH_WIDTH_160MHZ:
5787 dfs_ic->ic_curchan->ic_flags |=
5788 IEEE80211_CHAN_VHT160;
5789 break;
5790 default:
5791 WMA_LOGE(
5792 "%s: Recieved a wrong channel width %d",
5793 __func__, req->chan_width);
5794 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005795 }
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08005796
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005797 dfs_ic->ic_curchan->ic_flagext |= IEEE80211_CHAN_DFS;
5798
5799 if (req->oper_mode == BSS_OPERATIONAL_MODE_AP) {
5800 dfs_ic->ic_opmode = IEEE80211_M_HOSTAP;
5801 dfs_ic->vdev_id = req->vdev_id;
5802 }
5803
5804 dfs_ic->dfs_pri_multiplier = req->dfs_pri_multiplier;
5805
5806 /*
5807 * Configuring the DFS with current channel and the radar filters
5808 */
5809 wma_dfs_configure(dfs_ic);
5810 WMA_LOGI("%s: DFS- CHANNEL CONFIGURED", __func__);
5811 return dfs_ic->ic_curchan;
5812}
5813
5814
5815/**
5816 * wma_set_dfs_region() - set DFS region
5817 * @wma: wma handle
5818 *
5819 * Configure the DFS region for DFS radar filter initialization
5820 *
5821 * Return: none
5822 */
5823void wma_set_dfs_region(tp_wma_handle wma, uint8_t dfs_region)
5824{
5825 /* dfs information is passed */
5826 if (dfs_region > DFS_MKK4_DOMAIN || dfs_region == DFS_UNINIT_DOMAIN)
5827 /* assign DFS_FCC_DOMAIN as default domain*/
5828 wma->dfs_ic->current_dfs_regdomain = DFS_FCC_DOMAIN;
5829 else
5830 wma->dfs_ic->current_dfs_regdomain = dfs_region;
5831
5832 WMA_LOGI("%s: DFS Region Domain: %d", __func__,
5833 wma->dfs_ic->current_dfs_regdomain);
5834}
5835
5836/**
5837 * wma_get_channels() - prepare dfs radar channel list
5838 * @ichan: channel
5839 * @chan_list: return channel list
5840 *
5841 * Return: return number of channels
5842 */
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05305843int wma_get_channels(struct dfs_ieee80211_channel *ichan,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005844 struct wma_dfs_radar_channel_list *chan_list)
5845{
5846 uint8_t center_chan = cds_freq_to_chan(ichan->ic_vhtop_ch_freq_seg1);
5847
5848 chan_list->nchannels = 0;
5849
5850 if (IEEE80211_IS_CHAN_11AC_VHT80(ichan)) {
5851 chan_list->nchannels = 4;
5852 chan_list->channels[0] = center_chan - 6;
5853 chan_list->channels[1] = center_chan - 2;
5854 chan_list->channels[2] = center_chan + 2;
5855 chan_list->channels[3] = center_chan + 6;
5856 } else if (IEEE80211_IS_CHAN_11N_HT40(ichan) ||
5857 IEEE80211_IS_CHAN_11AC_VHT40(ichan)) {
5858 chan_list->nchannels = 2;
5859 chan_list->channels[0] = center_chan - 2;
5860 chan_list->channels[1] = center_chan + 2;
5861 } else {
5862 chan_list->nchannels = 1;
5863 chan_list->channels[0] = center_chan;
5864 }
5865
5866 return chan_list->nchannels;
5867}
5868
5869
5870/**
5871 * wma_dfs_indicate_radar() - Indicate Radar to SAP/HDD
5872 * @ic: ieee80211com ptr
5873 * @ichan: ieee 80211 channel
5874 *
5875 * Return: 0 for success or error code
5876 */
5877int wma_dfs_indicate_radar(struct ieee80211com *ic,
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05305878 struct dfs_ieee80211_channel *ichan)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005879{
5880 tp_wma_handle wma;
5881 void *hdd_ctx;
5882 struct wma_dfs_radar_indication *radar_event;
5883 struct wma_dfs_radar_ind wma_radar_event;
5884 tpAniSirGlobal pmac = NULL;
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05305885 bool indication_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005886
Anurag Chouhan6d760662016-02-20 16:05:43 +05305887 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005888 if (wma == NULL) {
5889 WMA_LOGE("%s: DFS- Invalid wma", __func__);
5890 return -ENOENT;
5891 }
5892
Anurag Chouhan6d760662016-02-20 16:05:43 +05305893 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005894 pmac = (tpAniSirGlobal)
Anurag Chouhan6d760662016-02-20 16:05:43 +05305895 cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005896
5897 if (!pmac) {
5898 WMA_LOGE("%s: Invalid MAC handle", __func__);
5899 return -ENOENT;
5900 }
5901
5902 if (wma->dfs_ic != ic) {
5903 WMA_LOGE("%s:DFS- Invalid WMA handle", __func__);
5904 return -ENOENT;
5905 }
5906 radar_event = (struct wma_dfs_radar_indication *)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305907 qdf_mem_malloc(sizeof(struct wma_dfs_radar_indication));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005908 if (radar_event == NULL) {
5909 WMA_LOGE("%s:DFS- Invalid radar_event", __func__);
5910 return -ENOMEM;
5911 }
5912
5913 /*
5914 * Do not post multiple Radar events on the same channel.
5915 * But, when DFS test mode is enabled, allow multiple dfs
5916 * radar events to be posted on the same channel.
5917 */
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305918 qdf_spin_lock_bh(&ic->chan_lock);
Edhar, Mahesh Kumar35d9b2e2015-10-26 17:06:23 +05305919 if (!pmac->sap.SapDfsInfo.disable_dfs_ch_switch)
5920 wma->dfs_ic->disable_phy_err_processing = true;
5921
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005922 if ((ichan->ic_ieee != (wma->dfs_ic->last_radar_found_chan)) ||
5923 (pmac->sap.SapDfsInfo.disable_dfs_ch_switch == true)) {
5924 wma->dfs_ic->last_radar_found_chan = ichan->ic_ieee;
5925 /* Indicate the radar event to HDD to stop the netif Tx queues */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005926 wma_radar_event.chan_freq = ichan->ic_freq;
5927 wma_radar_event.dfs_radar_status = WMA_DFS_RADAR_FOUND;
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05305928 indication_status =
5929 wma->dfs_radar_indication_cb(hdd_ctx, &wma_radar_event);
5930 if (indication_status == false) {
5931 WMA_LOGE("%s:Application triggered channel switch in progress!.. drop radar event indiaction to SAP",
5932 __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305933 qdf_mem_free(radar_event);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305934 qdf_spin_unlock_bh(&ic->chan_lock);
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05305935 return 0;
5936 }
5937
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005938 WMA_LOGE("%s:DFS- RADAR INDICATED TO HDD", __func__);
5939
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05305940 wma_radar_event.ieee_chan_number = ichan->ic_ieee;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005941 /*
5942 * Indicate to the radar event to SAP to
5943 * select a new channel and set CSA IE
5944 */
5945 radar_event->vdev_id = ic->vdev_id;
5946 wma_get_channels(ichan, &radar_event->chan_list);
5947 radar_event->dfs_radar_status = WMA_DFS_RADAR_FOUND;
5948 radar_event->use_nol = ic->ic_dfs_usenol(ic);
5949 wma_send_msg(wma, WMA_DFS_RADAR_IND, (void *)radar_event, 0);
5950 WMA_LOGE("%s:DFS- WMA_DFS_RADAR_IND Message Posted", __func__);
5951 }
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305952 qdf_spin_unlock_bh(&ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005953
5954 return 0;
5955}
5956
5957#ifdef WLAN_FEATURE_MEMDUMP
5958/*
5959 * wma_process_fw_mem_dump_req() - Function to request fw memory dump from
5960 * firmware
5961 * @wma: Pointer to WMA handle
5962 * @mem_dump_req: Pointer for mem_dump_req
5963 *
5964 * This function sends memory dump request to firmware
5965 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305966 * Return: QDF_STATUS_SUCCESS for success otherwise failure
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005967 *
5968 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305969QDF_STATUS wma_process_fw_mem_dump_req(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005970 struct fw_dump_req *mem_dump_req)
5971{
Govind Singhaa64c242016-03-08 11:31:49 +05305972 int ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005973
5974 if (!mem_dump_req || !wma) {
5975 WMA_LOGE(FL("input pointer is NULL"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305976 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005977 }
5978
Govind Singhaa64c242016-03-08 11:31:49 +05305979 ret = wmi_unified_process_fw_mem_dump_cmd(wma->wmi_handle,
5980 (struct fw_dump_req_param *) mem_dump_req);
5981 if (ret)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305982 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005983
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305984 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005985}
5986
5987/**
5988 * wma_fw_mem_dump_rsp() - send fw mem dump response to SME
5989 *
5990 * @req_id - request id.
5991 * @status - copy status from the firmware.
5992 *
5993 * This function is called by the memory dump response handler to
5994 * indicate SME that firmware dump copy is complete
5995 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305996 * Return: QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005997 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305998static QDF_STATUS wma_fw_mem_dump_rsp(uint32_t req_id, uint32_t status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005999{
6000 struct fw_dump_rsp *dump_rsp;
6001 cds_msg_t sme_msg = {0};
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306002 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006003
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306004 dump_rsp = qdf_mem_malloc(sizeof(*dump_rsp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006005
6006 if (!dump_rsp) {
6007 WMA_LOGE(FL("Memory allocation failed."));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306008 qdf_status = QDF_STATUS_E_NOMEM;
6009 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006010 }
6011
6012 WMA_LOGI(FL("FW memory dump copy complete status: %d for request: %d"),
6013 status, req_id);
6014
6015 dump_rsp->request_id = req_id;
6016 dump_rsp->dump_complete = status;
6017
6018 sme_msg.type = eWNI_SME_FW_DUMP_IND;
6019 sme_msg.bodyptr = dump_rsp;
6020 sme_msg.bodyval = 0;
6021
Anurag Chouhan6d760662016-02-20 16:05:43 +05306022 qdf_status = cds_mq_post_message(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306023 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006024 WMA_LOGE(FL("Fail to post fw mem dump ind msg"));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306025 qdf_mem_free(dump_rsp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006026 }
6027
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306028 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006029}
6030
6031/**
6032 * wma_fw_mem_dump_event_handler() - handles fw memory dump event
6033 *
6034 * @handle: pointer to wma handle.
6035 * @cmd_param_info: pointer to TLV info received in the event.
6036 * @len: length of data in @cmd_param_info
6037 *
6038 * This function is a handler for firmware memory dump event.
6039 *
6040 * Return: integer (0 for success and error code otherwise)
6041 */
6042int wma_fw_mem_dump_event_handler(void *handle, u_int8_t *cmd_param_info,
6043 u_int32_t len)
6044{
6045 WMI_UPDATE_FW_MEM_DUMP_EVENTID_param_tlvs *param_buf;
6046 wmi_update_fw_mem_dump_fixed_param *event;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306047 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006048
6049 param_buf =
6050 (WMI_UPDATE_FW_MEM_DUMP_EVENTID_param_tlvs *) cmd_param_info;
6051 if (!param_buf) {
6052 WMA_LOGA("%s: Invalid stats event", __func__);
6053 return -EINVAL;
6054 }
6055
6056 event = param_buf->fixed_param;
6057
6058 status = wma_fw_mem_dump_rsp(event->request_id,
6059 event->fw_mem_dump_complete);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306060 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006061 WMA_LOGE("Error posting FW MEM DUMP RSP.");
6062 return -EINVAL;
6063 }
6064
6065 WMA_LOGI("FW MEM DUMP RSP posted successfully");
6066 return 0;
6067}
6068#endif /* WLAN_FEATURE_MEMDUMP */
6069
6070/*
6071 * wma_process_set_ie_info() - Function to send IE info to firmware
6072 * @wma: Pointer to WMA handle
6073 * @ie_data: Pointer for ie data
6074 *
6075 * This function sends IE information to firmware
6076 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306077 * Return: QDF_STATUS_SUCCESS for success otherwise failure
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006078 *
6079 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306080QDF_STATUS wma_process_set_ie_info(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006081 struct vdev_ie_info *ie_info)
6082{
Govind Singhaa64c242016-03-08 11:31:49 +05306083 struct vdev_ie_info_param cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006084 int ret;
6085
6086 if (!ie_info || !wma) {
6087 WMA_LOGE(FL("input pointer is NULL"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306088 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006089 }
6090
6091 /* Validate the input */
6092 if (ie_info->length <= 0) {
6093 WMA_LOGE(FL("Invalid IE length"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306094 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006095 }
6096
Govind Singhaa64c242016-03-08 11:31:49 +05306097 cmd.vdev_id = ie_info->vdev_id;
6098 cmd.ie_id = ie_info->ie_id;
6099 cmd.length = ie_info->length;
6100 cmd.data = ie_info->data;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006101
Govind Singhaa64c242016-03-08 11:31:49 +05306102 ret = wmi_unified_process_set_ie_info_cmd(wma->wmi_handle,
6103 &cmd);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006104
6105 return ret;
6106}
6107