blob: b59374b9b13e01037ea272d7b1284964ca69a8b4 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Ryan Hsuf75bd242015-12-17 12:22:02 -08002 * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
28/**
29 * DOC: wma_features.c
30 * This file contains different features related functions like WoW,
31 * Offloads, TDLS etc.
32 */
33
34/* Header files */
35
36#include "wma.h"
37#include "wma_api.h"
38#include "cds_api.h"
39#include "wmi_unified_api.h"
40#include "wlan_qct_sys.h"
41#include "wni_api.h"
42#include "ani_global.h"
43#include "wmi_unified.h"
44#include "wni_cfg.h"
45#include "cfg_api.h"
Manjunathappa Prakash3454fd62016-04-01 08:52:06 -070046#include "ol_txrx_ctrl_api.h"
47#include <cdp_txrx_tx_delay.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080048#include "wlan_tgt_def_config.h"
Manjunathappa Prakash3454fd62016-04-01 08:52:06 -070049#include <cdp_txrx_peer_ops.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080050
Nirav Shahcbc6d722016-03-01 16:24:53 +053051#include "qdf_nbuf.h"
Anurag Chouhan6d760662016-02-20 16:05:43 +053052#include "qdf_types.h"
Anurag Chouhan600c3a02016-03-01 10:33:54 +053053#include "qdf_mem.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080054#include "ol_txrx_peer_find.h"
55
56#include "wma_types.h"
57#include "lim_api.h"
58#include "lim_session_utils.h"
59
60#include "cds_utils.h"
61
62#if !defined(REMOVE_PKT_LOG)
63#include "pktlog_ac.h"
64#endif /* REMOVE_PKT_LOG */
65
66#include "dbglog_host.h"
67#include "csr_api.h"
68#include "ol_fw.h"
69
70#include "dfs.h"
71#include "radar_filters.h"
72#include "wma_internal.h"
73
74#ifndef ARRAY_LENGTH
75#define ARRAY_LENGTH(a) (sizeof(a) / sizeof((a)[0]))
76#endif
77
78#define WMA_WOW_STA_WAKE_UP_EVENTS ((1 << WOW_CSA_IE_EVENT) |\
79 (1 << WOW_CLIENT_KICKOUT_EVENT) |\
80 (1 << WOW_PATTERN_MATCH_EVENT) |\
81 (1 << WOW_MAGIC_PKT_RECVD_EVENT) |\
82 (1 << WOW_DEAUTH_RECVD_EVENT) |\
83 (1 << WOW_DISASSOC_RECVD_EVENT) |\
84 (1 << WOW_BMISS_EVENT) |\
85 (1 << WOW_GTK_ERR_EVENT) |\
86 (1 << WOW_BETTER_AP_EVENT) |\
87 (1 << WOW_HTT_EVENT) |\
88 (1 << WOW_RA_MATCH_EVENT) |\
89 (1 << WOW_NLO_DETECTED_EVENT) |\
90 (1 << WOW_EXTSCAN_EVENT))\
91
92#define WMA_WOW_SAP_WAKE_UP_EVENTS ((1 << WOW_PROBE_REQ_WPS_IE_EVENT) |\
93 (1 << WOW_PATTERN_MATCH_EVENT) |\
94 (1 << WOW_AUTH_REQ_EVENT) |\
95 (1 << WOW_ASSOC_REQ_EVENT) |\
96 (1 << WOW_DEAUTH_RECVD_EVENT) |\
97 (1 << WOW_DISASSOC_RECVD_EVENT) |\
98 (1 << WOW_HTT_EVENT))\
99
100static const uint8_t arp_ptrn[] = {0x08, 0x06};
101static const uint8_t arp_mask[] = {0xff, 0xff};
102static const uint8_t ns_ptrn[] = {0x86, 0xDD};
103static const uint8_t discvr_ptrn[] = {0xe0, 0x00, 0x00, 0xf8};
104static const uint8_t discvr_mask[] = {0xf0, 0x00, 0x00, 0xf8};
105
106#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
107/**
108 * wma_post_auto_shutdown_msg() - to post auto shutdown event to sme
109 *
110 * Return: 0 for success or error code
111 */
112static int wma_post_auto_shutdown_msg(void)
113{
114 tSirAutoShutdownEvtParams *auto_sh_evt;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530115 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800116 cds_msg_t sme_msg = { 0 };
117
118 auto_sh_evt = (tSirAutoShutdownEvtParams *)
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530119 qdf_mem_malloc(sizeof(tSirAutoShutdownEvtParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800120 if (!auto_sh_evt) {
121 WMA_LOGE(FL("No Mem"));
122 return -ENOMEM;
123 }
124
125 auto_sh_evt->shutdown_reason =
126 WMI_HOST_AUTO_SHUTDOWN_REASON_TIMER_EXPIRY;
127 sme_msg.type = eWNI_SME_AUTO_SHUTDOWN_IND;
128 sme_msg.bodyptr = auto_sh_evt;
129 sme_msg.bodyval = 0;
130
Anurag Chouhan6d760662016-02-20 16:05:43 +0530131 qdf_status = cds_mq_post_message(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530132 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800133 WMA_LOGE("Fail to post eWNI_SME_AUTO_SHUTDOWN_IND msg to SME");
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530134 qdf_mem_free(auto_sh_evt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800135 return -EINVAL;
136 }
137
138 return 0;
139}
140#endif
141/**
142 * wma_send_snr_request() - send request to fw to get RSSI stats
143 * @wma_handle: wma handle
144 * @pGetRssiReq: get RSSI request
145 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530146 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800147 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530148QDF_STATUS wma_send_snr_request(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800149 void *pGetRssiReq)
150{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800151 tAniGetRssiReq *pRssiBkUp = NULL;
152
153 /* command is in progess */
154 if (NULL != wma_handle->pGetRssiReq)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530155 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800156
157 /* create a copy of csrRssiCallback to send rssi value
158 * after wmi event
159 */
160 if (pGetRssiReq) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530161 pRssiBkUp = qdf_mem_malloc(sizeof(tAniGetRssiReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800162 if (!pRssiBkUp) {
163 WMA_LOGE("Failed to allocate memory for tAniGetRssiReq");
164 wma_handle->pGetRssiReq = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530165 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800166 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530167 qdf_mem_set(pRssiBkUp, sizeof(tAniGetRssiReq), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800168 pRssiBkUp->sessionId =
169 ((tAniGetRssiReq *) pGetRssiReq)->sessionId;
170 pRssiBkUp->rssiCallback =
171 ((tAniGetRssiReq *) pGetRssiReq)->rssiCallback;
172 pRssiBkUp->pDevContext =
173 ((tAniGetRssiReq *) pGetRssiReq)->pDevContext;
174 wma_handle->pGetRssiReq = (void *)pRssiBkUp;
175 }
176
Govind Singhaa64c242016-03-08 11:31:49 +0530177 if (wmi_unified_snr_request_cmd(wma_handle->wmi_handle)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800178 WMA_LOGE("Failed to send host stats request to fw");
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530179 qdf_mem_free(pRssiBkUp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800180 wma_handle->pGetRssiReq = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530181 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800182 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530183 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800184}
185
186/**
187 * wma_get_snr() - get RSSI from fw
188 * @psnr_req: request params
189 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530190 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800191 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530192QDF_STATUS wma_get_snr(tAniGetSnrReq *psnr_req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800193{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800194 tAniGetSnrReq *psnr_req_bkp;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800195 tp_wma_handle wma_handle = NULL;
196 struct wma_txrx_node *intr;
197
Anurag Chouhan6d760662016-02-20 16:05:43 +0530198 wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800199
200 if (NULL == wma_handle) {
201 WMA_LOGE("%s : Failed to get wma_handle", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530202 return QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800203 }
204
205 intr = &wma_handle->interfaces[psnr_req->sessionId];
206 /* command is in progess */
207 if (NULL != intr->psnr_req) {
208 WMA_LOGE("%s : previous snr request is pending", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530209 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800210 }
211
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530212 psnr_req_bkp = qdf_mem_malloc(sizeof(tAniGetSnrReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800213 if (!psnr_req_bkp) {
214 WMA_LOGE("Failed to allocate memory for tAniGetSnrReq");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530215 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800216 }
217
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530218 qdf_mem_set(psnr_req_bkp, sizeof(tAniGetSnrReq), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800219 psnr_req_bkp->staId = psnr_req->staId;
220 psnr_req_bkp->pDevContext = psnr_req->pDevContext;
221 psnr_req_bkp->snrCallback = psnr_req->snrCallback;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800222 intr->psnr_req = (void *)psnr_req_bkp;
Govind Singhaa64c242016-03-08 11:31:49 +0530223
224 if (wmi_unified_snr_cmd(wma_handle->wmi_handle,
225 psnr_req->sessionId)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800226 WMA_LOGE("Failed to send host stats request to fw");
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530227 qdf_mem_free(psnr_req_bkp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800228 intr->psnr_req = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530229 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800230 }
231
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530232 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800233}
234
235/**
236 * wma_process_link_status_req() - process link status request from UMAC
237 * @wma: wma handle
238 * @pGetLinkStatus: get link params
239 *
240 * Return: none
241 */
242void wma_process_link_status_req(tp_wma_handle wma,
243 tAniGetLinkStatus *pGetLinkStatus)
244{
Govind Singhaa64c242016-03-08 11:31:49 +0530245 struct link_status_params cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800246 struct wma_txrx_node *iface =
247 &wma->interfaces[pGetLinkStatus->sessionId];
248
249 if (iface->plink_status_req) {
250 WMA_LOGE("%s:previous link status request is pending,deleting the new request",
251 __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530252 qdf_mem_free(pGetLinkStatus);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800253 return;
254 }
255
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800256 iface->plink_status_req = pGetLinkStatus;
Govind Singhaa64c242016-03-08 11:31:49 +0530257 cmd.session_id = pGetLinkStatus->sessionId;
258 if (wmi_unified_link_status_req_cmd(wma->wmi_handle, &cmd)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800259 WMA_LOGE("Failed to send WMI link status request to fw");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800260 iface->plink_status_req = NULL;
261 goto end;
262 }
263
264 return;
265
266end:
267 wma_post_link_status(pGetLinkStatus, LINK_STATUS_LEGACY);
268}
269
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700270#ifdef WLAN_FEATURE_TSF
271/**
272 * wma_vdev_tsf_handler() - handle tsf event indicated by FW
273 * @handle: wma context
274 * @data: event buffer
275 * @data len: length of event buffer
276 *
277 * Return: 0 on success
278 */
279int wma_vdev_tsf_handler(void *handle, uint8_t *data, uint32_t data_len)
280{
281 cds_msg_t tsf_msg = {0};
282 WMI_VDEV_TSF_REPORT_EVENTID_param_tlvs *param_buf;
283 wmi_vdev_tsf_report_event_fixed_param *tsf_event;
284 struct stsf *ptsf;
285
286 if (data == NULL) {
287 WMA_LOGE("%s: invalid pointer", __func__);
288 return -EINVAL;
289 }
290 ptsf = qdf_mem_malloc(sizeof(*ptsf));
291 if (NULL == ptsf) {
292 WMA_LOGE("%s: failed to allocate tsf data structure", __func__);
293 return -ENOMEM;
294 }
295
296 param_buf = (WMI_VDEV_TSF_REPORT_EVENTID_param_tlvs *)data;
297 tsf_event = param_buf->fixed_param;
298
299 ptsf->vdev_id = tsf_event->vdev_id;
300 ptsf->tsf_low = tsf_event->tsf_low;
301 ptsf->tsf_high = tsf_event->tsf_high;
Manikandan Mohan5356c2b2016-04-03 15:51:35 -0700302 ptsf->soc_timer_low = tsf_event->qtimer_low;
303 ptsf->soc_timer_high = tsf_event->qtimer_high;
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700304
305 WMA_LOGD("%s: receive WMI_VDEV_TSF_REPORT_EVENTID ", __func__);
306 WMA_LOGD("%s: vdev_id = %u,tsf_low =%u, tsf_high = %u", __func__,
307 ptsf->vdev_id, ptsf->tsf_low, ptsf->tsf_high);
308
309 tsf_msg.type = eWNI_SME_TSF_EVENT;
310 tsf_msg.bodyptr = ptsf;
311 tsf_msg.bodyval = 0;
312
313 if (QDF_STATUS_SUCCESS !=
314 cds_mq_post_message(CDS_MQ_ID_SME, &tsf_msg)) {
315
316 WMA_LOGP("%s: Failed to post eWNI_SME_TSF_EVENT", __func__);
317 qdf_mem_free(ptsf);
318 return -EINVAL;
319 }
320 return 0;
321}
322
Manikandan Mohan5356c2b2016-04-03 15:51:35 -0700323#ifdef QCA_WIFI_3_0
324#define TSF_FW_ACTION_CMD TSF_TSTAMP_QTIMER_CAPTURE_REQ
325#else
326#define TSF_FW_ACTION_CMD TSF_TSTAMP_CAPTURE_REQ
327#endif
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700328/**
329 * wma_capture_tsf() - send wmi to fw to capture tsf
330 * @wma_handle: wma handler
331 * @vdev_id: vdev id
332 *
333 * Return: wmi send state
334 */
335QDF_STATUS wma_capture_tsf(tp_wma_handle wma_handle, uint32_t vdev_id)
336{
337 QDF_STATUS status = QDF_STATUS_SUCCESS;
338 wmi_buf_t buf;
339 wmi_vdev_tsf_tstamp_action_cmd_fixed_param *cmd;
340 int ret;
341 int len = sizeof(*cmd);
342
343 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
344 if (!buf) {
345 WMA_LOGP("%s: failed to allocate memory for cap tsf cmd",
346 __func__);
347 return QDF_STATUS_E_NOMEM;
348 }
349
350 cmd = (wmi_vdev_tsf_tstamp_action_cmd_fixed_param *) wmi_buf_data(buf);
351 cmd->vdev_id = vdev_id;
Manikandan Mohan5356c2b2016-04-03 15:51:35 -0700352 cmd->tsf_action = TSF_FW_ACTION_CMD;
353 WMA_LOGD("%s :vdev_id %u, tsf_cmd: %d", __func__, cmd->vdev_id,
354 cmd->tsf_action);
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700355
356 WMITLV_SET_HDR(&cmd->tlv_header,
357 WMITLV_TAG_STRUC_wmi_vdev_tsf_tstamp_action_cmd_fixed_param,
358 WMITLV_GET_STRUCT_TLVLEN(
359 wmi_vdev_tsf_tstamp_action_cmd_fixed_param));
360
361 ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len,
362 WMI_VDEV_TSF_TSTAMP_ACTION_CMDID);
363 if (ret != EOK) {
364 WMA_LOGE("wmi_unified_cmd_send returned Error %d", status);
365 status = QDF_STATUS_E_FAILURE;
366 goto error;
367 }
368
369 return QDF_STATUS_SUCCESS;
370
371error:
372 if (buf)
373 wmi_buf_free(buf);
374 return status;
375}
376
377/**
378 * wma_reset_tsf_gpio() - send wmi to fw to reset GPIO
379 * @wma_handle: wma handler
380 * @vdev_id: vdev id
381 *
382 * Return: wmi send state
383 */
384QDF_STATUS wma_reset_tsf_gpio(tp_wma_handle wma_handle, uint32_t vdev_id)
385{
386 QDF_STATUS status = QDF_STATUS_SUCCESS;
387 wmi_buf_t buf;
388 wmi_vdev_tsf_tstamp_action_cmd_fixed_param *cmd;
389 int ret;
390 int len = sizeof(*cmd);
391 uint8_t *buf_ptr;
392
393 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
394 if (!buf) {
395 WMA_LOGP("%s: failed to allocate memory for reset tsf gpio",
396 __func__);
397 return QDF_STATUS_E_NOMEM;
398 }
399
400 buf_ptr = (uint8_t *) wmi_buf_data(buf);
401 cmd = (wmi_vdev_tsf_tstamp_action_cmd_fixed_param *) buf_ptr;
402 cmd->vdev_id = vdev_id;
403 cmd->tsf_action = TSF_TSTAMP_CAPTURE_RESET;
404
405 WMA_LOGD("%s :vdev_id %u, TSF_TSTAMP_CAPTURE_RESET", __func__,
406 cmd->vdev_id);
407
408 WMITLV_SET_HDR(&cmd->tlv_header,
409 WMITLV_TAG_STRUC_wmi_vdev_tsf_tstamp_action_cmd_fixed_param,
410 WMITLV_GET_STRUCT_TLVLEN(
411 wmi_vdev_tsf_tstamp_action_cmd_fixed_param));
412
413 ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len,
414 WMI_VDEV_TSF_TSTAMP_ACTION_CMDID);
415
416 if (ret != EOK) {
417 WMA_LOGE("wmi_unified_cmd_send returned Error %d", status);
418 status = QDF_STATUS_E_FAILURE;
419 goto error;
420 }
421 return QDF_STATUS_SUCCESS;
422
423error:
424 if (buf)
425 wmi_buf_free(buf);
426 return status;
427}
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700428
Manikandan Mohan976e7562016-03-15 16:33:31 -0700429/**
430 * wma_set_tsf_gpio_pin() - send wmi cmd to configure gpio pin
431 * @handle: wma handler
432 * @pin: GPIO pin id
433 *
434 * Return: QDF_STATUS
435 */
436QDF_STATUS wma_set_tsf_gpio_pin(WMA_HANDLE handle, uint32_t pin)
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700437{
Manikandan Mohan976e7562016-03-15 16:33:31 -0700438 tp_wma_handle wma = (tp_wma_handle)handle;
439 struct pdev_params pdev_param = {0};
440 int32_t ret;
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700441
Manikandan Mohan976e7562016-03-15 16:33:31 -0700442 if (!wma || !wma->wmi_handle) {
443 WMA_LOGE("%s: WMA is closed, can not set gpio", __func__);
444 return QDF_STATUS_E_INVAL;
445 }
446
447 WMA_LOGD("%s: set tsf gpio pin: %d", __func__, pin);
448
449 pdev_param.param_id = WMI_PDEV_PARAM_WNTS_CONFIG;
450 pdev_param.param_value = pin;
451 ret = wmi_unified_pdev_param_send(wma->wmi_handle,
452 &pdev_param,
453 WMA_WILDCARD_PDEV_ID);
454 if (ret) {
455 WMA_LOGE("%s: Failed to set tsf gpio pin (%d)", __func__, ret);
456 return QDF_STATUS_E_FAILURE;
457 }
458 return QDF_STATUS_SUCCESS;
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700459}
460#endif
461
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800462#ifdef FEATURE_WLAN_LPHB
463/**
464 * wma_lphb_conf_hbenable() - enable command of LPHB configuration requests
465 * @wma_handle: WMA handle
466 * @lphb_conf_req: configuration info
467 * @by_user: whether this call is from user or cached resent
468 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530469 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800470 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530471QDF_STATUS wma_lphb_conf_hbenable(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800472 tSirLPHBReq *lphb_conf_req, bool by_user)
473{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530474 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800475 int status = 0;
476 tSirLPHBEnableStruct *ts_lphb_enable;
Govind Singhaa64c242016-03-08 11:31:49 +0530477 wmi_hb_set_enable_cmd_fixed_param hb_enable_fp;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800478 int i;
479
480 if (lphb_conf_req == NULL) {
481 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530482 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800483 }
484
485 ts_lphb_enable = &(lphb_conf_req->params.lphbEnableReq);
486 WMA_LOGI("%s: WMA --> WMI_HB_SET_ENABLE enable=%d, item=%d, session=%d",
487 __func__,
488 ts_lphb_enable->enable,
489 ts_lphb_enable->item, ts_lphb_enable->session);
490
491 if ((ts_lphb_enable->item != 1) && (ts_lphb_enable->item != 2)) {
492 WMA_LOGE("%s : LPHB configuration wrong item %d",
493 __func__, ts_lphb_enable->item);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530494 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800495 }
496
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800497
498 /* fill in values */
Govind Singhaa64c242016-03-08 11:31:49 +0530499 hb_enable_fp.vdev_id = ts_lphb_enable->session;
500 hb_enable_fp.enable = ts_lphb_enable->enable;
501 hb_enable_fp.item = ts_lphb_enable->item;
502 hb_enable_fp.session = ts_lphb_enable->session;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800503
Govind Singhaa64c242016-03-08 11:31:49 +0530504 status = wmi_unified_lphb_config_hbenable_cmd(wma_handle->wmi_handle,
505 &hb_enable_fp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800506 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530507 qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800508 goto error;
509 }
510
511 if (by_user) {
512 /* target already configured, now cache command status */
513 if (ts_lphb_enable->enable) {
514 i = ts_lphb_enable->item - 1;
515 wma_handle->wow.lphb_cache[i].cmd
516 = LPHB_SET_EN_PARAMS_INDID;
517 wma_handle->wow.lphb_cache[i].params.lphbEnableReq.
518 enable = ts_lphb_enable->enable;
519 wma_handle->wow.lphb_cache[i].params.lphbEnableReq.
520 item = ts_lphb_enable->item;
521 wma_handle->wow.lphb_cache[i].params.lphbEnableReq.
522 session = ts_lphb_enable->session;
523
524 WMA_LOGI("%s: cached LPHB status in WMA context for item %d",
525 __func__, i);
526 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530527 qdf_mem_zero((void *)&wma_handle->wow.lphb_cache,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800528 sizeof(wma_handle->wow.lphb_cache));
529 WMA_LOGI("%s: cleared all cached LPHB status in WMA context",
530 __func__);
531 }
532 }
533
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530534 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800535error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530536 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800537}
538
539/**
540 * wma_lphb_conf_tcp_params() - set tcp params of LPHB configuration requests
541 * @wma_handle: wma handle
542 * @lphb_conf_req: lphb config request
543 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530544 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800545 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530546QDF_STATUS wma_lphb_conf_tcp_params(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800547 tSirLPHBReq *lphb_conf_req)
548{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530549 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800550 int status = 0;
551 tSirLPHBTcpParamStruct *ts_lphb_tcp_param;
Govind Singhaa64c242016-03-08 11:31:49 +0530552 wmi_hb_set_tcp_params_cmd_fixed_param hb_tcp_params_fp = {0};
553
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800554
555 if (lphb_conf_req == NULL) {
556 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530557 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800558 }
559
560 ts_lphb_tcp_param = &(lphb_conf_req->params.lphbTcpParamReq);
Srinivas Girigowda9dc32cf2015-11-19 14:47:04 -0800561 WMA_LOGI("%s: WMA --> WMI_HB_SET_TCP_PARAMS srv_ip=%08x, "
562 "dev_ip=%08x, src_port=%d, dst_port=%d, timeout=%d, "
563 "session=%d, gateway_mac="MAC_ADDRESS_STR", timePeriodSec=%d, "
564 "tcpSn=%d", __func__, ts_lphb_tcp_param->srv_ip,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800565 ts_lphb_tcp_param->dev_ip, ts_lphb_tcp_param->src_port,
566 ts_lphb_tcp_param->dst_port, ts_lphb_tcp_param->timeout,
Srinivas Girigowda9dc32cf2015-11-19 14:47:04 -0800567 ts_lphb_tcp_param->session,
568 MAC_ADDR_ARRAY(ts_lphb_tcp_param->gateway_mac.bytes),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800569 ts_lphb_tcp_param->timePeriodSec, ts_lphb_tcp_param->tcpSn);
570
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800571 /* fill in values */
Govind Singhaa64c242016-03-08 11:31:49 +0530572 hb_tcp_params_fp.vdev_id = ts_lphb_tcp_param->session;
573 hb_tcp_params_fp.srv_ip = ts_lphb_tcp_param->srv_ip;
574 hb_tcp_params_fp.dev_ip = ts_lphb_tcp_param->dev_ip;
575 hb_tcp_params_fp.seq = ts_lphb_tcp_param->tcpSn;
576 hb_tcp_params_fp.src_port = ts_lphb_tcp_param->src_port;
577 hb_tcp_params_fp.dst_port = ts_lphb_tcp_param->dst_port;
578 hb_tcp_params_fp.interval = ts_lphb_tcp_param->timePeriodSec;
579 hb_tcp_params_fp.timeout = ts_lphb_tcp_param->timeout;
580 hb_tcp_params_fp.session = ts_lphb_tcp_param->session;
Srinivas Girigowda9dc32cf2015-11-19 14:47:04 -0800581 WMI_CHAR_ARRAY_TO_MAC_ADDR(ts_lphb_tcp_param->gateway_mac.bytes,
Govind Singhaa64c242016-03-08 11:31:49 +0530582 &hb_tcp_params_fp.gateway_mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800583
Govind Singhaa64c242016-03-08 11:31:49 +0530584 status = wmi_unified_lphb_config_tcp_params_cmd(wma_handle->wmi_handle,
585 &hb_tcp_params_fp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800586 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530587 qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800588 goto error;
589 }
590
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530591 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800592error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530593 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800594}
595
596/**
597 * wma_lphb_conf_tcp_pkt_filter() - configure tcp packet filter command of LPHB
598 * @wma_handle: wma handle
599 * @lphb_conf_req: lphb config request
600 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530601 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800602 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530603QDF_STATUS wma_lphb_conf_tcp_pkt_filter(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800604 tSirLPHBReq *lphb_conf_req)
605{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530606 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800607 int status = 0;
608 tSirLPHBTcpFilterStruct *ts_lphb_tcp_filter;
Govind Singhaa64c242016-03-08 11:31:49 +0530609 wmi_hb_set_tcp_pkt_filter_cmd_fixed_param hb_tcp_filter_fp = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800610
611 if (lphb_conf_req == NULL) {
612 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530613 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800614 }
615
616 ts_lphb_tcp_filter = &(lphb_conf_req->params.lphbTcpFilterReq);
617 WMA_LOGI("%s: WMA --> WMI_HB_SET_TCP_PKT_FILTER length=%d, offset=%d, session=%d, "
618 "filter=%2x:%2x:%2x:%2x:%2x:%2x ...", __func__,
619 ts_lphb_tcp_filter->length, ts_lphb_tcp_filter->offset,
620 ts_lphb_tcp_filter->session, ts_lphb_tcp_filter->filter[0],
621 ts_lphb_tcp_filter->filter[1], ts_lphb_tcp_filter->filter[2],
622 ts_lphb_tcp_filter->filter[3], ts_lphb_tcp_filter->filter[4],
623 ts_lphb_tcp_filter->filter[5]);
624
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800625 /* fill in values */
Govind Singhaa64c242016-03-08 11:31:49 +0530626 hb_tcp_filter_fp.vdev_id = ts_lphb_tcp_filter->session;
627 hb_tcp_filter_fp.length = ts_lphb_tcp_filter->length;
628 hb_tcp_filter_fp.offset = ts_lphb_tcp_filter->offset;
629 hb_tcp_filter_fp.session = ts_lphb_tcp_filter->session;
630 memcpy((void *)&hb_tcp_filter_fp.filter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800631 (void *)&ts_lphb_tcp_filter->filter,
632 WMI_WLAN_HB_MAX_FILTER_SIZE);
633
Govind Singhaa64c242016-03-08 11:31:49 +0530634 status = wmi_unified_lphb_config_tcp_pkt_filter_cmd(wma_handle->wmi_handle,
635 &hb_tcp_filter_fp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800636 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530637 qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800638 goto error;
639 }
640
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530641 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800642error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530643 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800644}
645
646/**
647 * wma_lphb_conf_udp_params() - configure udp param command of LPHB
648 * @wma_handle: wma handle
649 * @lphb_conf_req: lphb config request
650 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530651 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800652 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530653QDF_STATUS wma_lphb_conf_udp_params(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800654 tSirLPHBReq *lphb_conf_req)
655{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530656 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800657 int status = 0;
658 tSirLPHBUdpParamStruct *ts_lphb_udp_param;
Govind Singhaa64c242016-03-08 11:31:49 +0530659 wmi_hb_set_udp_params_cmd_fixed_param hb_udp_params_fp = {0};
660
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800661
662 if (lphb_conf_req == NULL) {
663 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530664 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800665 }
666
667 ts_lphb_udp_param = &(lphb_conf_req->params.lphbUdpParamReq);
668 WMA_LOGI("%s: WMA --> WMI_HB_SET_UDP_PARAMS srv_ip=%d, dev_ip=%d, src_port=%d, "
669 "dst_port=%d, interval=%d, timeout=%d, session=%d, "
Srinivas Girigowda9eddfda2015-11-19 14:38:02 -0800670 "gateway_mac="MAC_ADDRESS_STR, __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800671 ts_lphb_udp_param->srv_ip, ts_lphb_udp_param->dev_ip,
672 ts_lphb_udp_param->src_port, ts_lphb_udp_param->dst_port,
673 ts_lphb_udp_param->interval, ts_lphb_udp_param->timeout,
Srinivas Girigowda9eddfda2015-11-19 14:38:02 -0800674 ts_lphb_udp_param->session,
675 MAC_ADDR_ARRAY(ts_lphb_udp_param->gateway_mac.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800676
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800677
678 /* fill in values */
Govind Singhaa64c242016-03-08 11:31:49 +0530679 hb_udp_params_fp.vdev_id = ts_lphb_udp_param->session;
680 hb_udp_params_fp.srv_ip = ts_lphb_udp_param->srv_ip;
681 hb_udp_params_fp.dev_ip = ts_lphb_udp_param->dev_ip;
682 hb_udp_params_fp.src_port = ts_lphb_udp_param->src_port;
683 hb_udp_params_fp.dst_port = ts_lphb_udp_param->dst_port;
684 hb_udp_params_fp.interval = ts_lphb_udp_param->interval;
685 hb_udp_params_fp.timeout = ts_lphb_udp_param->timeout;
686 hb_udp_params_fp.session = ts_lphb_udp_param->session;
Srinivas Girigowda9eddfda2015-11-19 14:38:02 -0800687 WMI_CHAR_ARRAY_TO_MAC_ADDR(ts_lphb_udp_param->gateway_mac.bytes,
Govind Singhaa64c242016-03-08 11:31:49 +0530688 &hb_udp_params_fp.gateway_mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800689
Govind Singhaa64c242016-03-08 11:31:49 +0530690 status = wmi_unified_lphb_config_udp_params_cmd(wma_handle->wmi_handle,
691 &hb_udp_params_fp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800692 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530693 qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800694 goto error;
695 }
696
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530697 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800698error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530699 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800700}
701
702/**
703 * wma_lphb_conf_udp_pkt_filter() - configure udp pkt filter command of LPHB
704 * @wma_handle: wma handle
705 * @lphb_conf_req: lphb config request
706 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530707 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800708 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530709QDF_STATUS wma_lphb_conf_udp_pkt_filter(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800710 tSirLPHBReq *lphb_conf_req)
711{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530712 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800713 int status = 0;
714 tSirLPHBUdpFilterStruct *ts_lphb_udp_filter;
Govind Singhaa64c242016-03-08 11:31:49 +0530715 wmi_hb_set_udp_pkt_filter_cmd_fixed_param hb_udp_filter_fp = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800716
717 if (lphb_conf_req == NULL) {
718 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530719 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800720 }
721
722 ts_lphb_udp_filter = &(lphb_conf_req->params.lphbUdpFilterReq);
723 WMA_LOGI("%s: WMA --> WMI_HB_SET_UDP_PKT_FILTER length=%d, offset=%d, session=%d, "
724 "filter=%2x:%2x:%2x:%2x:%2x:%2x ...", __func__,
725 ts_lphb_udp_filter->length, ts_lphb_udp_filter->offset,
726 ts_lphb_udp_filter->session, ts_lphb_udp_filter->filter[0],
727 ts_lphb_udp_filter->filter[1], ts_lphb_udp_filter->filter[2],
728 ts_lphb_udp_filter->filter[3], ts_lphb_udp_filter->filter[4],
729 ts_lphb_udp_filter->filter[5]);
730
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800731
732 /* fill in values */
Govind Singhaa64c242016-03-08 11:31:49 +0530733 hb_udp_filter_fp.vdev_id = ts_lphb_udp_filter->session;
734 hb_udp_filter_fp.length = ts_lphb_udp_filter->length;
735 hb_udp_filter_fp.offset = ts_lphb_udp_filter->offset;
736 hb_udp_filter_fp.session = ts_lphb_udp_filter->session;
737 memcpy((void *)&hb_udp_filter_fp.filter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800738 (void *)&ts_lphb_udp_filter->filter,
739 WMI_WLAN_HB_MAX_FILTER_SIZE);
740
Govind Singhaa64c242016-03-08 11:31:49 +0530741 status = wmi_unified_lphb_config_udp_pkt_filter_cmd(wma_handle->wmi_handle,
742 &hb_udp_filter_fp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800743 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530744 qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800745 goto error;
746 }
747
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530748 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800749error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530750 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800751}
752
753/**
754 * wma_process_lphb_conf_req() - handle LPHB configuration requests
755 * @wma_handle: wma handle
756 * @lphb_conf_req: lphb config request
757 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530758 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800759 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530760QDF_STATUS wma_process_lphb_conf_req(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800761 tSirLPHBReq *lphb_conf_req)
762{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530763 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800764
765 if (lphb_conf_req == NULL) {
766 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530767 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800768 }
769
770 WMA_LOGI("%s : LPHB configuration cmd id is %d", __func__,
771 lphb_conf_req->cmd);
772 switch (lphb_conf_req->cmd) {
773 case LPHB_SET_EN_PARAMS_INDID:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530774 qdf_status = wma_lphb_conf_hbenable(wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800775 lphb_conf_req, true);
776 break;
777
778 case LPHB_SET_TCP_PARAMS_INDID:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530779 qdf_status = wma_lphb_conf_tcp_params(wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800780 lphb_conf_req);
781 break;
782
783 case LPHB_SET_TCP_PKT_FILTER_INDID:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530784 qdf_status = wma_lphb_conf_tcp_pkt_filter(wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800785 lphb_conf_req);
786 break;
787
788 case LPHB_SET_UDP_PARAMS_INDID:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530789 qdf_status = wma_lphb_conf_udp_params(wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800790 lphb_conf_req);
791 break;
792
793 case LPHB_SET_UDP_PKT_FILTER_INDID:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530794 qdf_status = wma_lphb_conf_udp_pkt_filter(wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800795 lphb_conf_req);
796 break;
797
798 case LPHB_SET_NETWORK_INFO_INDID:
799 default:
800 break;
801 }
802
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530803 qdf_mem_free(lphb_conf_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530804 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800805}
806#endif /* FEATURE_WLAN_LPHB */
807
808/**
809 * wma_process_dhcp_ind() - process dhcp indication from SME
810 * @wma_handle: wma handle
811 * @ta_dhcp_ind: DHCP indication
812 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530813 * Return: QDF Status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800814 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530815QDF_STATUS wma_process_dhcp_ind(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800816 tAniDHCPInd *ta_dhcp_ind)
817{
818 uint8_t vdev_id;
819 int status = 0;
Govind Singhaa64c242016-03-08 11:31:49 +0530820 wmi_peer_set_param_cmd_fixed_param peer_set_param_fp = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800821
822 if (!ta_dhcp_ind) {
823 WMA_LOGE("%s : DHCP indication is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530824 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800825 }
826
Srinivas Girigowda296105a2015-09-24 16:31:16 -0700827 if (!wma_find_vdev_by_addr(wma_handle,
828 ta_dhcp_ind->adapterMacAddr.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800829 &vdev_id)) {
830 WMA_LOGE("%s: Failed to find vdev id for DHCP indication",
831 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530832 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800833 }
834
835 WMA_LOGI("%s: WMA --> WMI_PEER_SET_PARAM triggered by DHCP, "
836 "msgType=%s,"
837 "device_mode=%d, macAddr=" MAC_ADDRESS_STR,
838 __func__,
839 ta_dhcp_ind->msgType == WMA_DHCP_START_IND ?
840 "WMA_DHCP_START_IND" : "WMA_DHCP_STOP_IND",
841 ta_dhcp_ind->device_mode,
Srinivas Girigowda296105a2015-09-24 16:31:16 -0700842 MAC_ADDR_ARRAY(ta_dhcp_ind->peerMacAddr.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800843
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800844 /* fill in values */
Govind Singhaa64c242016-03-08 11:31:49 +0530845 peer_set_param_fp.vdev_id = vdev_id;
846 peer_set_param_fp.param_id = WMI_PEER_CRIT_PROTO_HINT_ENABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800847 if (WMA_DHCP_START_IND == ta_dhcp_ind->msgType)
Govind Singhaa64c242016-03-08 11:31:49 +0530848 peer_set_param_fp.param_value = 1;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800849 else
Govind Singhaa64c242016-03-08 11:31:49 +0530850 peer_set_param_fp.param_value = 0;
Srinivas Girigowda296105a2015-09-24 16:31:16 -0700851 WMI_CHAR_ARRAY_TO_MAC_ADDR(ta_dhcp_ind->peerMacAddr.bytes,
Govind Singhaa64c242016-03-08 11:31:49 +0530852 &peer_set_param_fp.peer_macaddr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800853
Govind Singhaa64c242016-03-08 11:31:49 +0530854 status = wmi_unified_process_dhcp_ind(wma_handle->wmi_handle,
855 &peer_set_param_fp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800856 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530857 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800858 }
859
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530860 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800861}
862
863/**
864 * wma_chan_to_mode() - convert channel to phy mode
865 * @chan: channel number
866 * @chan_width: channel width
867 * @vht_capable: vht capable
868 * @dot11_mode: 802.11 mode
869 *
870 * Return: return phy mode
871 */
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800872WLAN_PHY_MODE wma_chan_to_mode(u8 chan, enum phy_ch_width chan_width,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800873 u8 vht_capable, u8 dot11_mode)
874{
875 WLAN_PHY_MODE phymode = MODE_UNKNOWN;
876
877 /* 2.4 GHz band */
878 if ((chan >= WMA_11G_CHANNEL_BEGIN) && (chan <= WMA_11G_CHANNEL_END)) {
879 switch (chan_width) {
880 case CH_WIDTH_20MHZ:
881 /* In case of no channel bonding, use dot11_mode
882 * to set phy mode
883 */
884 switch (dot11_mode) {
885 case WNI_CFG_DOT11_MODE_11A:
886 phymode = MODE_11A;
887 break;
888 case WNI_CFG_DOT11_MODE_11B:
889 phymode = MODE_11B;
890 break;
891 case WNI_CFG_DOT11_MODE_11G:
892 phymode = MODE_11G;
893 break;
894 case WNI_CFG_DOT11_MODE_11G_ONLY:
895 phymode = MODE_11GONLY;
896 break;
897 default:
898 /* Configure MODE_11NG_HT20 for
899 * self vdev(for vht too)
900 */
901 phymode = MODE_11NG_HT20;
902 break;
903 }
904 break;
905 case CH_WIDTH_40MHZ:
906 phymode = vht_capable ? MODE_11AC_VHT40 :
907 MODE_11NG_HT40;
908 break;
909 default:
910 break;
911 }
912 }
913
914 /* 5 GHz band */
915 if ((chan >= WMA_11A_CHANNEL_BEGIN) && (chan <= WMA_11A_CHANNEL_END)) {
916 switch (chan_width) {
917 case CH_WIDTH_20MHZ:
918 phymode = vht_capable ? MODE_11AC_VHT20 :
919 MODE_11NA_HT20;
920 break;
921 case CH_WIDTH_40MHZ:
922 phymode = vht_capable ? MODE_11AC_VHT40 :
923 MODE_11NA_HT40;
924 break;
925 case CH_WIDTH_80MHZ:
926 phymode = MODE_11AC_VHT80;
927 break;
928#if CONFIG_160MHZ_SUPPORT != 0
929 case CH_WIDTH_160MHZ:
930 phymode = MODE_11AC_VHT160;
931 break;
932 case CH_WIDTH_80P80MHZ:
933 phymode = MODE_11AC_VHT80_80;
934 break;
935#endif
936
937 default:
938 break;
939 }
940 }
941
942 /* 5.9 GHz Band */
943 if ((chan >= WMA_11P_CHANNEL_BEGIN) && (chan <= WMA_11P_CHANNEL_END))
944 /* Only Legacy Modulation Schemes are supported */
945 phymode = MODE_11A;
946
947 WMA_LOGD("%s: phymode %d channel %d ch_width %d vht_capable %d "
948 "dot11_mode %d", __func__, phymode, chan,
949 chan_width, vht_capable, dot11_mode);
950
951 return phymode;
952}
953
954/**
955 * wma_get_link_speed() -send command to get linkspeed
956 * @handle: wma handle
957 * @pLinkSpeed: link speed info
958 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530959 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800960 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530961QDF_STATUS wma_get_link_speed(WMA_HANDLE handle, tSirLinkSpeedInfo *pLinkSpeed)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800962{
963 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Govind Singhaa64c242016-03-08 11:31:49 +0530964 wmi_mac_addr peer_macaddr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800965
966 if (!wma_handle || !wma_handle->wmi_handle) {
967 WMA_LOGE("%s: WMA is closed, can not issue get link speed cmd",
968 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530969 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800970 }
971 if (!WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap,
972 WMI_SERVICE_ESTIMATE_LINKSPEED)) {
973 WMA_LOGE("%s: Linkspeed feature bit not enabled"
974 " Sending value 0 as link speed.", __func__);
975 wma_send_link_speed(0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530976 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800977 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800978
979 /* Copy the peer macaddress to the wma buffer */
Srinivas Girigowdadccab9a2015-11-19 14:31:14 -0800980 WMI_CHAR_ARRAY_TO_MAC_ADDR(pLinkSpeed->peer_macaddr.bytes,
Govind Singhaa64c242016-03-08 11:31:49 +0530981 &peer_macaddr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800982
983 WMA_LOGD("%s: pLinkSpeed->peerMacAddr: %pM, "
984 "peer_macaddr.mac_addr31to0: 0x%x, peer_macaddr.mac_addr47to32: 0x%x",
Srinivas Girigowdadccab9a2015-11-19 14:31:14 -0800985 __func__, pLinkSpeed->peer_macaddr.bytes,
Govind Singhaa64c242016-03-08 11:31:49 +0530986 peer_macaddr.mac_addr31to0,
987 peer_macaddr.mac_addr47to32);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800988
Govind Singhaa64c242016-03-08 11:31:49 +0530989 if (wmi_unified_get_link_speed_cmd(wma_handle->wmi_handle,
990 peer_macaddr)) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530991 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800992 }
Govind Singhaa64c242016-03-08 11:31:49 +0530993
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530994 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800995}
996
Gupta, Kapil4cb1d7d2016-04-16 18:16:25 -0700997/**
998* wma_add_beacon_filter() - Issue WMI command to set beacon filter
999* @wma: wma handler
1000* @filter_params: beacon_filter_param to set
1001*
1002* Return: Return QDF_STATUS
1003*/
1004QDF_STATUS wma_add_beacon_filter(WMA_HANDLE handle,
1005 struct beacon_filter_param *filter_params)
1006{
1007 int i;
1008 wmi_buf_t wmi_buf;
1009 u_int8_t *buf;
1010 A_UINT32 *ie_map;
1011 int ret;
1012 tp_wma_handle wma = (tp_wma_handle) handle;
1013 wmi_add_bcn_filter_cmd_fixed_param *cmd;
1014 int len = sizeof(wmi_add_bcn_filter_cmd_fixed_param);
1015
1016 len += WMI_TLV_HDR_SIZE;
1017 len += BCN_FLT_MAX_ELEMS_IE_LIST*sizeof(A_UINT32);
1018
1019 if (!wma || !wma->wmi_handle) {
1020 WMA_LOGE("%s: WMA is closed, can not issue set beacon filter",
1021 __func__);
1022 return QDF_STATUS_E_INVAL;
1023 }
1024
1025 wmi_buf = wmi_buf_alloc(wma->wmi_handle, len);
1026 if (!wmi_buf) {
1027 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
1028 return QDF_STATUS_E_NOMEM;
1029 }
1030
1031 buf = (u_int8_t *) wmi_buf_data(wmi_buf);
1032
1033 cmd = (wmi_add_bcn_filter_cmd_fixed_param *)wmi_buf_data(wmi_buf);
1034 cmd->vdev_id = filter_params->vdev_id;
1035
1036 WMITLV_SET_HDR(&cmd->tlv_header,
1037 WMITLV_TAG_STRUC_wmi_add_bcn_filter_cmd_fixed_param,
1038 WMITLV_GET_STRUCT_TLVLEN(
1039 wmi_add_bcn_filter_cmd_fixed_param));
1040
1041 buf += sizeof(wmi_add_bcn_filter_cmd_fixed_param);
1042
1043 WMITLV_SET_HDR(buf, WMITLV_TAG_ARRAY_UINT32,
1044 (BCN_FLT_MAX_ELEMS_IE_LIST * sizeof(u_int32_t)));
1045
1046 ie_map = (A_UINT32 *)(buf + WMI_TLV_HDR_SIZE);
1047 for (i = 0; i < BCN_FLT_MAX_ELEMS_IE_LIST; i++) {
1048 ie_map[i] = filter_params->ie_map[i];
1049 WMA_LOGD("beacon filter ie map = %u", ie_map[i]);
1050 }
1051
1052 ret = wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len,
1053 WMI_ADD_BCN_FILTER_CMDID);
1054 if (ret) {
1055 WMA_LOGE("Failed to send wmi add beacon filter = %d",
1056 ret);
1057 wmi_buf_free(wmi_buf);
1058 return QDF_STATUS_E_FAILURE;
1059 }
1060 WMA_LOGD("added beacon filter = %d", ret);
1061
1062 return QDF_STATUS_SUCCESS;
1063}
1064
1065/**
1066* wma_remove_beacon_filter() - Issue WMI command to remove beacon filter
1067* @wma: wma handler
1068* @filter_params: beacon_filter_params
1069*
1070* Return: Return QDF_STATUS
1071*/
1072QDF_STATUS wma_remove_beacon_filter(WMA_HANDLE handle,
1073 struct beacon_filter_param *filter_params)
1074{
1075 wmi_buf_t buf;
1076 tp_wma_handle wma = (tp_wma_handle) handle;
1077 wmi_rmv_bcn_filter_cmd_fixed_param *cmd;
1078 int len = sizeof(wmi_rmv_bcn_filter_cmd_fixed_param);
1079 int ret;
1080
1081 if (!wma || !wma->wmi_handle) {
1082 WMA_LOGE("%s: WMA is closed, cannot issue remove beacon filter",
1083 __func__);
1084 return QDF_STATUS_E_INVAL;
1085 }
1086
1087 buf = wmi_buf_alloc(wma->wmi_handle, len);
1088 if (!buf) {
1089 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
1090 return QDF_STATUS_E_NOMEM;
1091 }
1092 cmd = (wmi_rmv_bcn_filter_cmd_fixed_param *)wmi_buf_data(buf);
1093 cmd->vdev_id = filter_params->vdev_id;
1094
1095 WMITLV_SET_HDR(&cmd->tlv_header,
1096 WMITLV_TAG_STRUC_wmi_rmv_bcn_filter_cmd_fixed_param,
1097 WMITLV_GET_STRUCT_TLVLEN(
1098 wmi_rmv_bcn_filter_cmd_fixed_param));
1099
1100 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
1101 WMI_RMV_BCN_FILTER_CMDID);
1102 if (ret) {
1103 WMA_LOGE("Failed to send wmi remove beacon filter = %d",
1104 ret);
1105 wmi_buf_free(buf);
1106 return QDF_STATUS_E_FAILURE;
1107 }
1108 WMA_LOGD("removed beacon filter = %d", ret);
1109
1110 return QDF_STATUS_SUCCESS;
1111}
1112
1113
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001114#ifdef FEATURE_GREEN_AP
1115
1116/**
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001117 * wma_egap_info_status_event() - egap info status event
1118 * @handle: pointer to wma handler
1119 * @event: pointer to event
1120 * @len: len of the event
1121 *
1122 * Return: 0 for success, otherwise appropriate error code
1123 */
1124static int wma_egap_info_status_event(void *handle, u_int8_t *event,
1125 uint32_t len)
1126{
1127 WMI_TX_PAUSE_EVENTID_param_tlvs *param_buf;
1128 wmi_ap_ps_egap_info_event_fixed_param *egap_info_event;
1129 wmi_ap_ps_egap_info_chainmask_list *chainmask_event;
1130 u_int8_t *buf_ptr;
1131
1132 param_buf = (WMI_TX_PAUSE_EVENTID_param_tlvs *)event;
1133 if (!param_buf) {
1134 WMA_LOGE("Invalid EGAP Info status event buffer");
1135 return -EINVAL;
1136 }
1137
1138 egap_info_event = (wmi_ap_ps_egap_info_event_fixed_param *)
1139 param_buf->fixed_param;
1140 buf_ptr = (uint8_t *)egap_info_event;
1141 buf_ptr += sizeof(wmi_ap_ps_egap_info_event_fixed_param);
1142 chainmask_event = (wmi_ap_ps_egap_info_chainmask_list *)buf_ptr;
1143
1144 WMA_LOGI("mac_id: %d, status: %d, tx_mask: %x, rx_mask: %d",
1145 chainmask_event->mac_id,
1146 egap_info_event->status,
1147 chainmask_event->tx_chainmask,
1148 chainmask_event->rx_chainmask);
1149 return 0;
1150}
1151
1152/**
1153 * wma_send_egap_conf_params() - send wmi cmd of egap configuration params
1154 * @wma_handle: wma handler
1155 * @egap_params: pointer to egap_params
1156 *
1157 * Return: 0 for success, otherwise appropriate error code
1158 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301159QDF_STATUS wma_send_egap_conf_params(WMA_HANDLE handle,
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001160 struct egap_conf_params *egap_params)
1161{
1162 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Govind Singhaa64c242016-03-08 11:31:49 +05301163 wmi_ap_ps_egap_param_cmd_fixed_param cmd = {0};
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001164 int32_t err;
1165
Govind Singhaa64c242016-03-08 11:31:49 +05301166 cmd.enable = egap_params->enable;
1167 cmd.inactivity_time = egap_params->inactivity_time;
1168 cmd.wait_time = egap_params->wait_time;
1169 cmd.flags = egap_params->flags;
1170 err = wmi_unified_egap_conf_params_cmd(wma_handle->wmi_handle, &cmd);
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001171 if (err) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301172 return QDF_STATUS_E_FAILURE;
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001173 }
Govind Singhaa64c242016-03-08 11:31:49 +05301174
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301175 return QDF_STATUS_SUCCESS;
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001176}
1177
1178/**
1179 * wma_setup_egap_support() - setup the EGAP support flag
1180 * @tgt_cfg: pointer to hdd target configuration
1181 * @egap_support: EGAP support flag
1182 *
1183 * Return: None
1184 */
1185void wma_setup_egap_support(struct wma_tgt_cfg *tgt_cfg, WMA_HANDLE handle)
1186{
1187 tp_wma_handle wma_handle = (tp_wma_handle) handle;
1188
1189 if (tgt_cfg && wma_handle)
1190 tgt_cfg->egap_support = wma_handle->egap_support;
1191}
1192
1193/**
1194 * wma_register_egap_event_handle() - register the EGAP event handle
1195 * @wma_handle: wma handler
1196 *
1197 * Return: None
1198 */
1199void wma_register_egap_event_handle(WMA_HANDLE handle)
1200{
1201 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Govind Singhd76a5b02016-03-08 15:12:14 +05301202 QDF_STATUS status;
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001203
1204 if (WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap,
1205 WMI_SERVICE_EGAP)) {
1206 status = wmi_unified_register_event_handler(
1207 wma_handle->wmi_handle,
1208 WMI_AP_PS_EGAP_INFO_EVENTID,
Govind Singhd76a5b02016-03-08 15:12:14 +05301209 wma_egap_info_status_event,
1210 WMA_RX_SERIALIZER_CTX);
1211 if (QDF_IS_STATUS_ERROR(status)) {
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001212 WMA_LOGE("Failed to register Enhance Green AP event");
1213 wma_handle->egap_support = false;
1214 } else {
1215 WMA_LOGI("Set the Enhance Green AP event handler");
1216 wma_handle->egap_support = true;
1217 }
1218 } else
1219 wma_handle->egap_support = false;
1220}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001221#endif /* FEATURE_GREEN_AP */
1222
Govind Singha471e5e2015-10-12 17:11:14 +05301223/**
Govind Singhaa64c242016-03-08 11:31:49 +05301224 * wma_unified_fw_profiling_cmd() - send FW profiling cmd to WLAN FW
Govind Singha471e5e2015-10-12 17:11:14 +05301225 * @wma: wma handle
1226 * @cmd: Profiling command index
1227 * @value1: parameter1 value
1228 * @value2: parameter2 value
1229 *
1230 * Return: 0 for success else error code
1231 */
Govind Singhaa64c242016-03-08 11:31:49 +05301232QDF_STATUS wma_unified_fw_profiling_cmd(wmi_unified_t wmi_handle,
Govind Singha471e5e2015-10-12 17:11:14 +05301233 uint32_t cmd, uint32_t value1, uint32_t value2)
1234{
Govind Singha471e5e2015-10-12 17:11:14 +05301235 int ret;
Govind Singha471e5e2015-10-12 17:11:14 +05301236
Govind Singhaa64c242016-03-08 11:31:49 +05301237 ret = wmi_unified_fw_profiling_data_cmd(wmi_handle, cmd,
1238 value1, value2);
1239 if (ret) {
1240 WMA_LOGE("enable cmd Failed for id %d value %d",
1241 value1, value2);
1242 return ret;
Govind Singha471e5e2015-10-12 17:11:14 +05301243 }
1244
Govind Singhaa64c242016-03-08 11:31:49 +05301245 return QDF_STATUS_SUCCESS;
Govind Singha471e5e2015-10-12 17:11:14 +05301246}
1247
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001248#ifdef FEATURE_WLAN_LPHB
1249/**
1250 * wma_lphb_handler() - send LPHB indication to SME
1251 * @wma: wma handle
1252 * @event: event handler
1253 *
1254 * Return: 0 for success or error code
1255 */
1256static int wma_lphb_handler(tp_wma_handle wma, uint8_t *event)
1257{
1258 wmi_hb_ind_event_fixed_param *hb_fp;
1259 tSirLPHBInd *slphb_indication;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301260 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001261 cds_msg_t sme_msg = { 0 };
1262
1263 hb_fp = (wmi_hb_ind_event_fixed_param *) event;
1264 if (!hb_fp) {
1265 WMA_LOGE("Invalid wmi_hb_ind_event_fixed_param buffer");
1266 return -EINVAL;
1267 }
1268
1269 WMA_LOGD("lphb indication received with vdev_id=%d, session=%d, reason=%d",
1270 hb_fp->vdev_id, hb_fp->session, hb_fp->reason);
1271
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301272 slphb_indication = (tSirLPHBInd *) qdf_mem_malloc(sizeof(tSirLPHBInd));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001273
1274 if (!slphb_indication) {
1275 WMA_LOGE("Invalid LPHB indication buffer");
1276 return -ENOMEM;
1277 }
1278
1279 slphb_indication->sessionIdx = hb_fp->session;
1280 slphb_indication->protocolType = hb_fp->reason;
1281 slphb_indication->eventReason = hb_fp->reason;
1282
1283 sme_msg.type = eWNI_SME_LPHB_IND;
1284 sme_msg.bodyptr = slphb_indication;
1285 sme_msg.bodyval = 0;
1286
Anurag Chouhan6d760662016-02-20 16:05:43 +05301287 qdf_status = cds_mq_post_message(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301288 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001289 WMA_LOGE("Fail to post eWNI_SME_LPHB_IND msg to SME");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301290 qdf_mem_free(slphb_indication);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001291 return -EINVAL;
1292 }
1293
1294 return 0;
1295}
1296#endif /* FEATURE_WLAN_LPHB */
1297
1298#ifdef FEATURE_WLAN_RA_FILTERING
1299/**
1300 * wma_wow_sta_ra_filter() - set RA filter pattern in fw
1301 * @wma: wma handle
1302 * @vdev_id: vdev id
1303 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05301304 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001305 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301306static QDF_STATUS wma_wow_sta_ra_filter(tp_wma_handle wma, uint8_t vdev_id)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001307{
1308
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001309 struct wma_txrx_node *iface;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001310 int ret;
Govind Singhaa64c242016-03-08 11:31:49 +05301311 uint8_t default_pattern;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001312
1313 iface = &wma->interfaces[vdev_id];
1314
Govind Singhaa64c242016-03-08 11:31:49 +05301315 default_pattern = iface->num_wow_default_patterns++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001316
1317 WMA_LOGD("%s: send RA rate limit [%d] to fw vdev = %d", __func__,
1318 wma->RArateLimitInterval, vdev_id);
1319
Govind Singhaa64c242016-03-08 11:31:49 +05301320 ret = wmi_unified_wow_sta_ra_filter_cmd(wma->wmi_handle, vdev_id,
1321 default_pattern, wma->RArateLimitInterval);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001322 if (ret) {
1323 WMA_LOGE("%s: Failed to send RA rate limit to fw", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001324 iface->num_wow_default_patterns--;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301325 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001326 }
1327
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301328 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001329
1330}
1331#endif /* FEATURE_WLAN_RA_FILTERING */
1332
1333/**
1334 * wmi_unified_nat_keepalive_enable() - enable NAT keepalive filter
1335 * @wma: wma handle
1336 * @vdev_id: vdev id
1337 *
1338 * Return: 0 for success or error code
1339 */
1340int wmi_unified_nat_keepalive_enable(tp_wma_handle wma, uint8_t vdev_id)
1341{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001342
Govind Singhaa64c242016-03-08 11:31:49 +05301343 if (wmi_unified_nat_keepalive_en_cmd(wma->wmi_handle, vdev_id))
1344 return QDF_STATUS_E_FAILURE;
1345
1346 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001347}
1348
1349/**
Govind Singhd76a5b02016-03-08 15:12:14 +05301350 * wma_unified_csa_offload_enable() - sen CSA offload enable command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001351 * @wma: wma handle
1352 * @vdev_id: vdev id
1353 *
1354 * Return: 0 for success or error code
1355 */
Govind Singhd76a5b02016-03-08 15:12:14 +05301356int wma_unified_csa_offload_enable(tp_wma_handle wma, uint8_t vdev_id)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001357{
Govind Singhaa64c242016-03-08 11:31:49 +05301358 if (wmi_unified_csa_offload_enable(wma->wmi_handle,
1359 vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001360 WMA_LOGP("%s: Failed to send CSA offload enable command",
1361 __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001362 return -EIO;
1363 }
Govind Singhaa64c242016-03-08 11:31:49 +05301364
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001365 return 0;
1366}
1367
1368#ifdef WLAN_FEATURE_NAN
1369/**
1370 * wma_nan_rsp_event_handler() - Function is used to handle nan response
1371 * @handle: wma handle
1372 * @event_buf: event buffer
1373 * @len: length of buffer
1374 *
1375 * Return: 0 for success or error code
1376 */
1377int wma_nan_rsp_event_handler(void *handle, uint8_t *event_buf,
1378 uint32_t len)
1379{
1380 WMI_NAN_EVENTID_param_tlvs *param_buf;
1381 tSirNanEvent *nan_rsp_event;
1382 wmi_nan_event_hdr *nan_rsp_event_hdr;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301383 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001384 cds_msg_t cds_msg;
1385 uint8_t *buf_ptr;
1386 uint32_t alloc_len;
1387
1388 /*
1389 * This is how received event_buf looks like
1390 *
1391 * <-------------------- event_buf ----------------------------------->
1392 *
1393 * <--wmi_nan_event_hdr--><---WMI_TLV_HDR_SIZE---><----- data -------->
1394 *
1395 * +-----------+---------+-----------------------+--------------------+
1396 * | tlv_header| data_len| WMITLV_TAG_ARRAY_BYTE | nan_rsp_event_data |
1397 * +-----------+---------+-----------------------+--------------------+
1398 */
1399
1400 WMA_LOGD("%s: Posting NaN response event to SME", __func__);
1401 param_buf = (WMI_NAN_EVENTID_param_tlvs *) event_buf;
1402 if (!param_buf) {
1403 WMA_LOGE("%s: Invalid nan response event buf", __func__);
1404 return -EINVAL;
1405 }
1406 nan_rsp_event_hdr = param_buf->fixed_param;
1407 buf_ptr = (uint8_t *) nan_rsp_event_hdr;
1408 alloc_len = sizeof(tSirNanEvent);
1409 alloc_len += nan_rsp_event_hdr->data_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301410 nan_rsp_event = (tSirNanEvent *) qdf_mem_malloc(alloc_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001411 if (NULL == nan_rsp_event) {
1412 WMA_LOGE("%s: Memory allocation failure", __func__);
1413 return -ENOMEM;
1414 }
1415
1416 nan_rsp_event->event_data_len = nan_rsp_event_hdr->data_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301417 qdf_mem_copy(nan_rsp_event->event_data, buf_ptr +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001418 sizeof(wmi_nan_event_hdr) + WMI_TLV_HDR_SIZE,
1419 nan_rsp_event->event_data_len);
1420 cds_msg.type = eWNI_SME_NAN_EVENT;
1421 cds_msg.bodyptr = (void *)nan_rsp_event;
1422 cds_msg.bodyval = 0;
1423
1424 status = cds_mq_post_message(CDS_MQ_ID_SME, &cds_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301425 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001426 WMA_LOGE("%s: Failed to post NaN response event to SME",
1427 __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301428 qdf_mem_free(nan_rsp_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001429 return -EFAULT;
1430 }
1431 WMA_LOGD("%s: NaN response event Posted to SME", __func__);
1432 return 0;
1433}
1434#endif /* WLAN_FEATURE_NAN */
1435
1436/**
1437 * wma_csa_offload_handler() - CSA event handler
1438 * @handle: wma handle
1439 * @event: event buffer
1440 * @len: buffer length
1441 *
1442 * This event is sent by firmware when it receives CSA IE.
1443 *
1444 * Return: 0 for success or error code
1445 */
1446int wma_csa_offload_handler(void *handle, uint8_t *event, uint32_t len)
1447{
1448 tp_wma_handle wma = (tp_wma_handle) handle;
1449 WMI_CSA_HANDLING_EVENTID_param_tlvs *param_buf;
1450 wmi_csa_event_fixed_param *csa_event;
1451 uint8_t bssid[IEEE80211_ADDR_LEN];
1452 uint8_t vdev_id = 0;
1453 uint8_t cur_chan = 0;
1454 struct ieee80211_channelswitch_ie *csa_ie;
Chandrasekaran, Manishekar5c19dc52016-02-04 14:58:26 +05301455 struct csa_offload_params *csa_offload_event;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001456 struct ieee80211_extendedchannelswitch_ie *xcsa_ie;
1457 struct ieee80211_ie_wide_bw_switch *wb_ie;
1458 struct wma_txrx_node *intr = wma->interfaces;
1459
1460 param_buf = (WMI_CSA_HANDLING_EVENTID_param_tlvs *) event;
1461
1462 WMA_LOGD("%s: Enter", __func__);
1463 if (!param_buf) {
1464 WMA_LOGE("Invalid csa event buffer");
1465 return -EINVAL;
1466 }
1467 csa_event = param_buf->fixed_param;
1468 WMI_MAC_ADDR_TO_CHAR_ARRAY(&csa_event->i_addr2, &bssid[0]);
1469
1470 if (wma_find_vdev_by_bssid(wma, bssid, &vdev_id) == NULL) {
1471 WMA_LOGE("Invalid bssid received %s:%d", __func__, __LINE__);
1472 return -EINVAL;
1473 }
1474
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301475 csa_offload_event = qdf_mem_malloc(sizeof(*csa_offload_event));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001476 if (!csa_offload_event) {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05301477 WMA_LOGE("QDF MEM Alloc Failed for csa_offload_event");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001478 return -EINVAL;
1479 }
1480
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301481 qdf_mem_zero(csa_offload_event, sizeof(*csa_offload_event));
1482 qdf_mem_copy(csa_offload_event->bssId, &bssid, IEEE80211_ADDR_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001483
1484 if (csa_event->ies_present_flag & WMI_CSA_IE_PRESENT) {
1485 csa_ie = (struct ieee80211_channelswitch_ie *)
1486 (&csa_event->csa_ie[0]);
1487 csa_offload_event->channel = csa_ie->newchannel;
Chandrasekaran, Manishekar5c19dc52016-02-04 14:58:26 +05301488 csa_offload_event->switch_mode = csa_ie->switchmode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001489 } else if (csa_event->ies_present_flag & WMI_XCSA_IE_PRESENT) {
1490 xcsa_ie = (struct ieee80211_extendedchannelswitch_ie *)
1491 (&csa_event->xcsa_ie[0]);
1492 csa_offload_event->channel = xcsa_ie->newchannel;
Chandrasekaran, Manishekar5c19dc52016-02-04 14:58:26 +05301493 csa_offload_event->switch_mode = xcsa_ie->switchmode;
Gupta, Kapil121bf212015-11-25 19:21:29 +05301494 csa_offload_event->new_op_class = xcsa_ie->newClass;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001495 } else {
1496 WMA_LOGE("CSA Event error: No CSA IE present");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301497 qdf_mem_free(csa_offload_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001498 return -EINVAL;
1499 }
1500
1501 if (csa_event->ies_present_flag & WMI_WBW_IE_PRESENT) {
1502 wb_ie = (struct ieee80211_ie_wide_bw_switch *)
1503 (&csa_event->wb_ie[0]);
1504 csa_offload_event->new_ch_width = wb_ie->new_ch_width;
1505 csa_offload_event->new_ch_freq_seg1 = wb_ie->new_ch_freq_seg1;
1506 csa_offload_event->new_ch_freq_seg2 = wb_ie->new_ch_freq_seg2;
1507 }
1508
1509 csa_offload_event->ies_present_flag = csa_event->ies_present_flag;
1510
1511 WMA_LOGD("CSA: New Channel = %d BSSID:%pM",
1512 csa_offload_event->channel, csa_offload_event->bssId);
1513
1514 cur_chan = cds_freq_to_chan(intr[vdev_id].mhz);
1515 /*
1516 * basic sanity check: requested channel should not be 0
1517 * and equal to home channel
1518 */
1519 if ((0 == csa_offload_event->channel) ||
1520 (cur_chan == csa_offload_event->channel)) {
1521 WMA_LOGE("CSA Event with channel %d. Ignore !!",
1522 csa_offload_event->channel);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301523 qdf_mem_free(csa_offload_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001524 return -EINVAL;
1525 }
1526 wma->interfaces[vdev_id].is_channel_switch = true;
1527 wma_send_msg(wma, WMA_CSA_OFFLOAD_EVENT, (void *)csa_offload_event, 0);
1528 return 0;
1529}
1530
1531#ifdef FEATURE_OEM_DATA_SUPPORT
1532
1533/**
1534 * wma_oem_capability_event_callback() - OEM capability event handler
1535 * @handle: wma handle
1536 * @datap: data ptr
1537 * @len: data length
1538 *
1539 * Return: 0 for success or error code
1540 */
1541int wma_oem_capability_event_callback(void *handle,
1542 uint8_t *datap, uint32_t len)
1543{
1544 tp_wma_handle wma = (tp_wma_handle) handle;
1545 WMI_OEM_CAPABILITY_EVENTID_param_tlvs *param_buf;
1546 uint8_t *data;
1547 uint32_t datalen;
1548 uint32_t *msg_subtype;
1549 tStartOemDataRsp *pStartOemDataRsp;
1550
1551 param_buf = (WMI_OEM_CAPABILITY_EVENTID_param_tlvs *) datap;
1552 if (!param_buf) {
1553 WMA_LOGE("%s: Received NULL buf ptr from FW", __func__);
1554 return -ENOMEM;
1555 }
1556
1557 data = param_buf->data;
1558 datalen = param_buf->num_data;
1559
1560 if (!data) {
1561 WMA_LOGE("%s: Received NULL data from FW", __func__);
1562 return -EINVAL;
1563 }
1564
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001565 /*
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001566 * wma puts 4 bytes prefix for msg subtype, so length
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001567 * of data received from target should be 4 bytes less
1568 * then max allowed
1569 */
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001570 if (datalen > (OEM_DATA_RSP_SIZE - OEM_MESSAGE_SUBTYPE_LEN)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001571 WMA_LOGE("%s: Received data len (%d) exceeds max value (%d)",
1572 __func__, datalen, (OEM_DATA_RSP_SIZE - 4));
1573 return -EINVAL;
1574 }
1575
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301576 pStartOemDataRsp = qdf_mem_malloc(sizeof(*pStartOemDataRsp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001577 if (!pStartOemDataRsp) {
1578 WMA_LOGE("%s: Failed to alloc pStartOemDataRsp", __func__);
1579 return -ENOMEM;
1580 }
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001581
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001582 pStartOemDataRsp->rsp_len = datalen + OEM_MESSAGE_SUBTYPE_LEN;
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001583 if (pStartOemDataRsp->rsp_len) {
1584 pStartOemDataRsp->oem_data_rsp =
1585 qdf_mem_malloc(pStartOemDataRsp->rsp_len);
1586 if (!pStartOemDataRsp->oem_data_rsp) {
1587 WMA_LOGE(FL("malloc failed for oem_data_rsp"));
1588 qdf_mem_free(pStartOemDataRsp);
1589 return -ENOMEM;
1590 }
1591 } else {
1592 WMA_LOGE(FL("Invalid rsp length: %d"),
1593 pStartOemDataRsp->rsp_len);
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001594 qdf_mem_free(pStartOemDataRsp);
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001595 return -EINVAL;
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001596 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001597
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001598 pStartOemDataRsp->target_rsp = true;
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001599 msg_subtype = (uint32_t *) pStartOemDataRsp->oem_data_rsp;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001600 *msg_subtype = WMI_OEM_CAPABILITY_RSP;
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001601 /* copy data after msg sub type */
1602 qdf_mem_copy(pStartOemDataRsp->oem_data_rsp + OEM_MESSAGE_SUBTYPE_LEN,
1603 data, datalen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001604
1605 WMA_LOGI("%s: Sending WMA_START_OEM_DATA_RSP, data len (%d)",
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001606 __func__, pStartOemDataRsp->rsp_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001607
1608 wma_send_msg(wma, WMA_START_OEM_DATA_RSP, (void *)pStartOemDataRsp, 0);
1609 return 0;
1610}
1611
1612/**
1613 * wma_oem_measurement_report_event_callback() - OEM measurement report handler
1614 * @handle: wma handle
1615 * @datap: data ptr
1616 * @len: data length
1617 *
1618 * Return: 0 for success or error code
1619 */
1620int wma_oem_measurement_report_event_callback(void *handle,
1621 uint8_t *datap,
1622 uint32_t len)
1623{
1624 tp_wma_handle wma = (tp_wma_handle) handle;
1625 WMI_OEM_MEASUREMENT_REPORT_EVENTID_param_tlvs *param_buf;
1626 uint8_t *data;
1627 uint32_t datalen;
1628 uint32_t *msg_subtype;
1629 tStartOemDataRsp *pStartOemDataRsp;
1630
1631 param_buf = (WMI_OEM_MEASUREMENT_REPORT_EVENTID_param_tlvs *) datap;
1632 if (!param_buf) {
1633 WMA_LOGE("%s: Received NULL buf ptr from FW", __func__);
1634 return -ENOMEM;
1635 }
1636
1637 data = param_buf->data;
1638 datalen = param_buf->num_data;
1639
1640 if (!data) {
1641 WMA_LOGE("%s: Received NULL data from FW", __func__);
1642 return -EINVAL;
1643 }
1644
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001645 /*
1646 * wma puts 4 bytes prefix for msg subtype, so length
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001647 * of data received from target should be 4 bytes less
1648 * then max allowed
1649 */
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001650 if (datalen > (OEM_DATA_RSP_SIZE - OEM_MESSAGE_SUBTYPE_LEN)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001651 WMA_LOGE("%s: Received data len (%d) exceeds max value (%d)",
1652 __func__, datalen, (OEM_DATA_RSP_SIZE - 4));
1653 return -EINVAL;
1654 }
1655
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301656 pStartOemDataRsp = qdf_mem_malloc(sizeof(*pStartOemDataRsp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001657 if (!pStartOemDataRsp) {
1658 WMA_LOGE("%s: Failed to alloc pStartOemDataRsp", __func__);
1659 return -ENOMEM;
1660 }
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001661
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001662 pStartOemDataRsp->rsp_len = datalen + OEM_MESSAGE_SUBTYPE_LEN;
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001663 if (pStartOemDataRsp->rsp_len) {
1664 pStartOemDataRsp->oem_data_rsp =
1665 qdf_mem_malloc(pStartOemDataRsp->rsp_len);
1666 if (!pStartOemDataRsp->oem_data_rsp) {
1667 WMA_LOGE(FL("malloc failed for oem_data_rsp"));
1668 qdf_mem_free(pStartOemDataRsp);
1669 return -ENOMEM;
1670 }
1671 } else {
1672 WMA_LOGE(FL("Invalid rsp length: %d"),
1673 pStartOemDataRsp->rsp_len);
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001674 qdf_mem_free(pStartOemDataRsp);
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001675 return -EINVAL;
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001676 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001677
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001678 pStartOemDataRsp->target_rsp = true;
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001679 msg_subtype = (uint32_t *) pStartOemDataRsp->oem_data_rsp;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001680 *msg_subtype = WMI_OEM_MEASUREMENT_RSP;
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001681 /* copy data after msg sub type */
1682 qdf_mem_copy(pStartOemDataRsp->oem_data_rsp + OEM_MESSAGE_SUBTYPE_LEN,
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001683 data, datalen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001684
1685 WMA_LOGI("%s: Sending WMA_START_OEM_DATA_RSP, data len (%d)",
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001686 __func__, pStartOemDataRsp->rsp_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001687
1688 wma_send_msg(wma, WMA_START_OEM_DATA_RSP, (void *)pStartOemDataRsp, 0);
1689 return 0;
1690}
1691
1692/**
1693 * wma_oem_error_report_event_callback() - OEM error report handler
1694 * @handle: wma handle
1695 * @datap: data ptr
1696 * @len: data length
1697 *
1698 * Return: 0 for success or error code
1699 */
1700int wma_oem_error_report_event_callback(void *handle,
1701 uint8_t *datap, uint32_t len)
1702{
1703 tp_wma_handle wma = (tp_wma_handle) handle;
1704 WMI_OEM_ERROR_REPORT_EVENTID_param_tlvs *param_buf;
1705 uint8_t *data;
1706 uint32_t datalen;
1707 uint32_t *msg_subtype;
1708 tStartOemDataRsp *pStartOemDataRsp;
1709
1710 param_buf = (WMI_OEM_ERROR_REPORT_EVENTID_param_tlvs *) datap;
1711 if (!param_buf) {
1712 WMA_LOGE("%s: Received NULL buf ptr from FW", __func__);
1713 return -ENOMEM;
1714 }
1715
1716 data = param_buf->data;
1717 datalen = param_buf->num_data;
1718
1719 if (!data) {
1720 WMA_LOGE("%s: Received NULL data from FW", __func__);
1721 return -EINVAL;
1722 }
1723
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001724 /*
1725 * wma puts 4 bytes prefix for msg subtype, so length
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001726 * of data received from target should be 4 bytes less
1727 * then max allowed
1728 */
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001729 if (datalen > (OEM_DATA_RSP_SIZE - OEM_MESSAGE_SUBTYPE_LEN)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001730 WMA_LOGE("%s: Received data len (%d) exceeds max value (%d)",
1731 __func__, datalen, (OEM_DATA_RSP_SIZE - 4));
1732 return -EINVAL;
1733 }
1734
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301735 pStartOemDataRsp = qdf_mem_malloc(sizeof(*pStartOemDataRsp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001736 if (!pStartOemDataRsp) {
1737 WMA_LOGE("%s: Failed to alloc pStartOemDataRsp", __func__);
1738 return -ENOMEM;
1739 }
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001740
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001741 pStartOemDataRsp->rsp_len = datalen + OEM_MESSAGE_SUBTYPE_LEN;
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001742 if (pStartOemDataRsp->rsp_len) {
1743 pStartOemDataRsp->oem_data_rsp =
1744 qdf_mem_malloc(pStartOemDataRsp->rsp_len);
1745 if (!pStartOemDataRsp->oem_data_rsp) {
1746 WMA_LOGE(FL("malloc failed for oem_data_rsp"));
1747 qdf_mem_free(pStartOemDataRsp);
1748 return -ENOMEM;
1749 }
1750 } else {
1751 WMA_LOGE(FL("Invalid rsp length: %d"),
1752 pStartOemDataRsp->rsp_len);
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001753 qdf_mem_free(pStartOemDataRsp);
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001754 return -EINVAL;
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001755 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001756
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001757 pStartOemDataRsp->target_rsp = true;
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001758 msg_subtype = (uint32_t *) pStartOemDataRsp->oem_data_rsp;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001759 *msg_subtype = WMI_OEM_ERROR_REPORT_RSP;
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001760 /* copy data after msg sub type */
1761 qdf_mem_copy(pStartOemDataRsp->oem_data_rsp + OEM_MESSAGE_SUBTYPE_LEN,
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001762 data, datalen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001763
1764 WMA_LOGI("%s: Sending WMA_START_OEM_DATA_RSP, data len (%d)",
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001765 __func__, pStartOemDataRsp->rsp_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001766
1767 wma_send_msg(wma, WMA_START_OEM_DATA_RSP, (void *)pStartOemDataRsp, 0);
1768 return 0;
1769}
1770
1771/**
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001772 * wma_oem_data_response_handler() - OEM data response event handler
1773 * @handle: wma handle
1774 * @datap: data ptr
1775 * @len: data length
1776 *
1777 * Return: 0 for success or error code
1778 */
1779int wma_oem_data_response_handler(void *handle,
1780 uint8_t *datap, uint32_t len)
1781{
1782 tp_wma_handle wma = (tp_wma_handle) handle;
1783 WMI_OEM_RESPONSE_EVENTID_param_tlvs *param_buf;
1784 uint8_t *data;
1785 uint32_t datalen;
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001786 tStartOemDataRsp *oem_rsp;
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001787
1788 param_buf = (WMI_OEM_RESPONSE_EVENTID_param_tlvs *) datap;
1789 if (!param_buf) {
1790 WMA_LOGE(FL("Received NULL buf ptr from FW"));
1791 return -ENOMEM;
1792 }
1793
1794 data = param_buf->data;
1795 datalen = param_buf->num_data;
1796
1797 if (!data) {
1798 WMA_LOGE(FL("Received NULL data from FW"));
1799 return -EINVAL;
1800 }
1801
1802 if (datalen > OEM_DATA_RSP_SIZE) {
1803 WMA_LOGE(FL("Received data len %d exceeds max value %d"),
1804 datalen, OEM_DATA_RSP_SIZE);
1805 return -EINVAL;
1806 }
1807
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001808 oem_rsp = qdf_mem_malloc(sizeof(*oem_rsp));
1809 if (!oem_rsp) {
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001810 WMA_LOGE(FL("Failed to alloc oem_data_rsp"));
1811 return -ENOMEM;
1812 }
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001813 oem_rsp->rsp_len = datalen;
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001814 if (oem_rsp->rsp_len) {
1815 oem_rsp->oem_data_rsp = qdf_mem_malloc(oem_rsp->rsp_len);
1816 if (!oem_rsp->oem_data_rsp) {
1817 WMA_LOGE(FL("malloc failed for oem_data_rsp"));
1818 qdf_mem_free(oem_rsp);
1819 return -ENOMEM;
1820 }
1821 } else {
1822 WMA_LOGE(FL("Invalid rsp length: %d"),
1823 oem_rsp->rsp_len);
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001824 qdf_mem_free(oem_rsp);
Krishna Kumaar Natarajana96ee0f2016-03-10 16:57:45 -08001825 return -EINVAL;
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001826 }
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001827
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001828 oem_rsp->target_rsp = true;
1829 qdf_mem_copy(oem_rsp->oem_data_rsp, data, datalen);
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001830
1831 WMA_LOGI(FL("Sending WMA_START_OEM_DATA_RSP, data len %d"), datalen);
1832
Krishna Kumaar Natarajan608291e2015-12-14 18:17:27 -08001833 wma_send_msg(wma, WMA_START_OEM_DATA_RSP, (void *)oem_rsp, 0);
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001834 return 0;
1835}
1836
1837/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001838 * wma_start_oem_data_req() - start OEM data request to target
1839 * @wma_handle: wma handle
1840 * @startOemDataReq: start request params
1841 *
1842 * Return: none
1843 */
1844void wma_start_oem_data_req(tp_wma_handle wma_handle,
1845 tStartOemDataReq *startOemDataReq)
1846{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001847 int ret = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001848 tStartOemDataRsp *pStartOemDataRsp;
1849
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001850 WMA_LOGD(FL("Send OEM Data Request to target"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001851
Sreelakshmi Konamki86d79202016-02-10 12:33:40 +05301852 if (!startOemDataReq || !startOemDataReq->data) {
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001853 WMA_LOGE(FL("startOemDataReq is null"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001854 goto out;
1855 }
1856
1857 if (!wma_handle || !wma_handle->wmi_handle) {
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001858 WMA_LOGE(FL("WMA - closed, can not send Oem data request cmd"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001859 return;
1860 }
1861
Govind Singhaa64c242016-03-08 11:31:49 +05301862 ret = wmi_unified_start_oem_data_cmd(wma_handle->wmi_handle,
1863 startOemDataReq->data_len,
1864 startOemDataReq->data);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001865
1866 if (ret != EOK) {
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001867 WMA_LOGE(FL(":wmi cmd send failed"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001868 }
1869
1870out:
1871 /* free oem data req buffer received from UMAC */
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001872 if (startOemDataReq) {
1873 if (startOemDataReq->data)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301874 qdf_mem_free(startOemDataReq->data);
1875 qdf_mem_free(startOemDataReq);
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001876 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001877
1878 /* Now send data resp back to PE/SME with message sub-type of
1879 * WMI_OEM_INTERNAL_RSP. This is required so that PE/SME clears
1880 * up pending active command. Later when desired oem response(s)
1881 * comes as wmi event from target then those shall be passed
1882 * to oem application
1883 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301884 pStartOemDataRsp = qdf_mem_malloc(sizeof(*pStartOemDataRsp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001885 if (!pStartOemDataRsp) {
1886 WMA_LOGE("%s:failed to allocate memory for OEM Data Resp to PE",
1887 __func__);
1888 return;
1889 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301890 qdf_mem_zero(pStartOemDataRsp, sizeof(tStartOemDataRsp));
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001891 pStartOemDataRsp->target_rsp = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001892
1893 WMA_LOGI("%s: Sending WMA_START_OEM_DATA_RSP to clear up PE/SME pending cmd",
1894 __func__);
1895
1896 wma_send_msg(wma_handle, WMA_START_OEM_DATA_RSP,
1897 (void *)pStartOemDataRsp, 0);
1898
1899 return;
1900}
1901#endif /* FEATURE_OEM_DATA_SUPPORT */
1902
1903
1904/**
1905 * wma_unified_dfs_radar_rx_event_handler() - dfs radar rx event handler
1906 * @handle: wma handle
1907 * @data: data buffer
1908 * @datalen: data length
1909 *
1910 * WMI handler for WMI_DFS_RADAR_EVENTID
1911 * This handler is registered for handling
1912 * filtered DFS Phyerror. This handler is
1913 * will be invoked only when DFS Phyerr
1914 * filtering offload is enabled.
1915 *
1916 * Return: 1 for Success and 0 for error
1917 */
1918static int wma_unified_dfs_radar_rx_event_handler(void *handle,
1919 uint8_t *data,
1920 uint32_t datalen)
1921{
1922 tp_wma_handle wma = (tp_wma_handle) handle;
1923 struct ieee80211com *ic;
1924 struct ath_dfs *dfs;
1925 struct dfs_event *event;
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05301926 struct dfs_ieee80211_channel *chan;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001927 int empty;
1928 int do_check_chirp = 0;
1929 int is_hw_chirp = 0;
1930 int is_sw_chirp = 0;
1931 int is_pri = 0;
Vishwajith Upendrabf673e72016-01-19 16:05:40 -08001932 bool is_ch_dfs = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001933
1934 WMI_DFS_RADAR_EVENTID_param_tlvs *param_tlvs;
1935 wmi_dfs_radar_event_fixed_param *radar_event;
1936
1937 ic = wma->dfs_ic;
1938 if (NULL == ic) {
1939 WMA_LOGE("%s: dfs_ic is NULL ", __func__);
1940 return 0;
1941 }
1942
1943 dfs = (struct ath_dfs *)ic->ic_dfs;
1944 param_tlvs = (WMI_DFS_RADAR_EVENTID_param_tlvs *) data;
1945
1946 if (NULL == dfs) {
1947 WMA_LOGE("%s: dfs is NULL ", __func__);
1948 return 0;
1949 }
1950 /*
1951 * This parameter holds the number
1952 * of phyerror interrupts to the host
1953 * after the phyerrors have passed through
1954 * false detect filters in the firmware.
1955 */
1956 dfs->dfs_phyerr_count++;
1957
1958 if (!param_tlvs) {
1959 WMA_LOGE("%s: Received NULL data from FW", __func__);
1960 return 0;
1961 }
1962
1963 radar_event = param_tlvs->fixed_param;
1964
Anurag Chouhana37b5b72016-02-21 14:53:42 +05301965 qdf_spin_lock_bh(&ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001966 chan = ic->ic_curchan;
Edhar, Mahesh Kumar35d9b2e2015-10-26 17:06:23 +05301967 if (ic->disable_phy_err_processing) {
1968 WMA_LOGD("%s: radar indication done,drop phyerror event",
1969 __func__);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05301970 qdf_spin_unlock_bh(&ic->chan_lock);
Edhar, Mahesh Kumar35d9b2e2015-10-26 17:06:23 +05301971 return 0;
1972 }
1973
Vishwajith Upendrabf673e72016-01-19 16:05:40 -08001974 if (IEEE80211_IS_CHAN_11AC_VHT160(chan)) {
1975 is_ch_dfs = true;
1976 } else if (IEEE80211_IS_CHAN_11AC_VHT80P80(chan)) {
1977 if (cds_get_channel_state(chan->ic_ieee) == CHANNEL_STATE_DFS ||
1978 cds_get_channel_state(chan->ic_ieee_ext -
1979 WMA_80MHZ_START_CENTER_CH_DIFF) ==
1980 CHANNEL_STATE_DFS)
1981 is_ch_dfs = true;
1982 } else {
1983 if (cds_get_channel_state(chan->ic_ieee) == CHANNEL_STATE_DFS)
1984 is_ch_dfs = true;
1985 }
1986 if (!is_ch_dfs) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001987 WMA_LOGE
1988 ("%s: Invalid DFS Phyerror event. Channel=%d is Non-DFS",
1989 __func__, chan->ic_ieee);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05301990 qdf_spin_unlock_bh(&ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001991 return 0;
1992 }
1993
Anurag Chouhana37b5b72016-02-21 14:53:42 +05301994 qdf_spin_unlock_bh(&ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001995 dfs->ath_dfs_stats.total_phy_errors++;
1996
1997 if (dfs->dfs_caps.ath_chip_is_bb_tlv) {
1998 do_check_chirp = 1;
1999 is_pri = 1;
2000 is_hw_chirp = radar_event->pulse_is_chirp;
2001
2002 if ((uint32_t) dfs->dfs_phyerr_freq_min >
2003 radar_event->pulse_center_freq) {
2004 dfs->dfs_phyerr_freq_min =
2005 (int)radar_event->pulse_center_freq;
2006 }
2007
2008 if (dfs->dfs_phyerr_freq_max <
2009 (int)radar_event->pulse_center_freq) {
2010 dfs->dfs_phyerr_freq_max =
2011 (int)radar_event->pulse_center_freq;
2012 }
2013 }
2014
2015 /*
2016 * Now, add the parsed, checked and filtered
2017 * radar phyerror event radar pulse event list.
2018 * This event will then be processed by
2019 * dfs_radar_processevent() to see if the pattern
2020 * of pulses in radar pulse list match any radar
2021 * singnature in the current regulatory domain.
2022 */
2023
2024 ATH_DFSEVENTQ_LOCK(dfs);
2025 empty = STAILQ_EMPTY(&(dfs->dfs_eventq));
2026 ATH_DFSEVENTQ_UNLOCK(dfs);
2027 if (empty) {
2028 return 0;
2029 }
2030 /*
2031 * Add the event to the list, if there's space.
2032 */
2033 ATH_DFSEVENTQ_LOCK(dfs);
2034 event = STAILQ_FIRST(&(dfs->dfs_eventq));
2035 if (event == NULL) {
2036 ATH_DFSEVENTQ_UNLOCK(dfs);
2037 WMA_LOGE("%s: No more space left for queuing DFS Phyerror events",
2038 __func__);
2039 return 0;
2040 }
2041 STAILQ_REMOVE_HEAD(&(dfs->dfs_eventq), re_list);
2042 ATH_DFSEVENTQ_UNLOCK(dfs);
2043 dfs->dfs_phyerr_queued_count++;
2044 dfs->dfs_phyerr_w53_counter++;
2045 event->re_dur = (uint8_t) radar_event->pulse_duration;
2046 event->re_rssi = radar_event->rssi;
2047 event->re_ts = radar_event->pulse_detect_ts & DFS_TSMASK;
2048 event->re_full_ts = (((uint64_t) radar_event->upload_fullts_high) << 32)
2049 | radar_event->upload_fullts_low;
2050
2051 /*
2052 * Index of peak magnitude
2053 */
2054 event->sidx = radar_event->peak_sidx;
2055
2056 /*
2057 * Handle chirp flags.
2058 */
2059 if (do_check_chirp) {
2060 event->re_flags |= DFS_EVENT_CHECKCHIRP;
2061 if (is_hw_chirp) {
2062 event->re_flags |= DFS_EVENT_HW_CHIRP;
2063 }
2064 if (is_sw_chirp) {
2065 event->re_flags |= DFS_EVENT_SW_CHIRP;
2066 }
2067 }
2068 /*
2069 * Correctly set which channel is being reported on
2070 */
2071 if (is_pri) {
2072 event->re_chanindex = (uint8_t) dfs->dfs_curchan_radindex;
2073 } else {
2074 if (dfs->dfs_extchan_radindex == -1) {
2075 WMA_LOGI("%s phyerr on ext channel", __func__);
2076 }
2077 event->re_chanindex = (uint8_t) dfs->dfs_extchan_radindex;
2078 WMA_LOGI("%s:New extension channel event is added to queue",
2079 __func__);
2080 }
2081
2082 ATH_DFSQ_LOCK(dfs);
2083
2084 STAILQ_INSERT_TAIL(&(dfs->dfs_radarq), event, re_list);
2085
2086 empty = STAILQ_EMPTY(&dfs->dfs_radarq);
2087
2088 ATH_DFSQ_UNLOCK(dfs);
2089
2090 if (!empty && !dfs->ath_radar_tasksched) {
2091 dfs->ath_radar_tasksched = 1;
2092 OS_SET_TIMER(&dfs->ath_dfs_task_timer, 0);
2093 }
2094
2095 return 1;
2096
2097}
2098
2099/**
2100 * wma_unified_phyerr_rx_event_handler() - phyerr event handler
2101 * @handle: wma handle
2102 * @data: data buffer
2103 * @datalen: buffer length
2104 *
2105 * WMI Handler for WMI_PHYERR_EVENTID event from firmware.
2106 * This handler is currently handling only DFS phy errors.
2107 * This handler will be invoked only when the DFS phyerror
2108 * filtering offload is disabled.
2109 *
2110 * Return: 1:Success, 0:Failure
2111 */
2112static int wma_unified_phyerr_rx_event_handler(void *handle,
2113 uint8_t *data, uint32_t datalen)
2114{
2115 tp_wma_handle wma = (tp_wma_handle) handle;
2116 WMI_PHYERR_EVENTID_param_tlvs *param_tlvs;
2117 wmi_comb_phyerr_rx_hdr *pe_hdr;
2118 uint8_t *bufp;
2119 wmi_single_phyerr_rx_event *ev;
2120 struct ieee80211com *ic = wma->dfs_ic;
Anurag Chouhan6d760662016-02-20 16:05:43 +05302121 qdf_size_t n;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002122 A_UINT64 tsf64 = 0;
2123 int phy_err_code = 0;
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08002124 A_UINT32 phy_err_mask = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002125 int error = 0;
2126 tpAniSirGlobal mac_ctx =
Anurag Chouhan6d760662016-02-20 16:05:43 +05302127 (tpAniSirGlobal)cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002128 bool enable_log = false;
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08002129 int max_dfs_buf_length = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002130
2131 if (NULL == mac_ctx) {
2132 WMA_LOGE("%s: mac_ctx is NULL", __func__);
2133 return 0;
2134 }
2135 enable_log = mac_ctx->sap.enable_dfs_phy_error_logs;
2136
2137 param_tlvs = (WMI_PHYERR_EVENTID_param_tlvs *) data;
2138
2139 if (!param_tlvs) {
2140 WMA_LOGE("%s: Received NULL data from FW", __func__);
2141 return 0;
2142 }
2143
2144 pe_hdr = param_tlvs->hdr;
2145 if (pe_hdr == NULL) {
2146 WMA_LOGE("%s: Received Data PE Header is NULL", __func__);
2147 return 0;
2148 }
2149
2150 /* Ensure it's at least the size of the header */
2151 if (datalen < sizeof(*pe_hdr)) {
2152 WMA_LOGE("%s: Expected minimum size %zu, received %d",
2153 __func__, sizeof(*pe_hdr), datalen);
2154 return 0;
2155 }
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08002156 /*
2157 * The max buffer lenght is larger for DFS-3 than DFS-2.
2158 * So, accordingly use the correct max buffer size.
2159 */
2160 if (wma->hw_bd_id != WMI_HWBD_QCA6174)
2161 max_dfs_buf_length = DFS3_MAX_BUF_LENGTH;
2162 else
2163 max_dfs_buf_length = DFS_MAX_BUF_LENGTH;
2164
2165 if (pe_hdr->buf_len > max_dfs_buf_length) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002166 WMA_LOGE("%s: Received Invalid Phyerror event buffer length = %d"
2167 "Maximum allowed buf length = %d", __func__,
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08002168 pe_hdr->buf_len, max_dfs_buf_length);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002169
2170 return 0;
2171 }
2172
2173 /*
2174 * Reconstruct the 64 bit event TSF. This isn't from the MAC, it's
2175 * at the time the event was sent to us, the TSF value will be
2176 * in the future.
2177 */
2178 tsf64 = pe_hdr->tsf_l32;
2179 tsf64 |= (((uint64_t) pe_hdr->tsf_u32) << 32);
2180
2181 /*
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08002182 * Check the HW board ID to figure out
2183 * if DFS-3 is supported. In DFS-3
2184 * phyerror mask indicates the type of
2185 * phyerror, whereas in DFS-2 phyerrorcode
2186 * indicates the type of phyerror. If the
2187 * board is NOT WMI_HWBD_QCA6174, for now
2188 * assume that it supports DFS-3.
2189 */
2190 if (wma->hw_bd_id != WMI_HWBD_QCA6174) {
2191 phy_err_mask = pe_hdr->rsPhyErrMask0;
2192 WMA_LOGD("%s: DFS-3 phyerror mask = 0x%x",
2193 __func__, phy_err_mask);
2194 }
2195
2196 /*
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002197 * Loop over the bufp, extracting out phyerrors
2198 * wmi_unified_comb_phyerr_rx_event.bufp is a char pointer,
2199 * which isn't correct here - what we have received here
2200 * is an array of TLV-style PHY errors.
2201 */
2202 n = 0; /* Start just after the header */
2203 bufp = param_tlvs->bufp;
2204 while (n < pe_hdr->buf_len) {
2205 /* ensure there's at least space for the header */
2206 if ((pe_hdr->buf_len - n) < sizeof(ev->hdr)) {
2207 WMA_LOGE("%s: Not enough space.(datalen=%d, n=%zu, hdr=%zu bytes",
2208 __func__, pe_hdr->buf_len, n, sizeof(ev->hdr));
2209 error = 1;
2210 break;
2211 }
2212 /*
2213 * Obtain a pointer to the beginning of the current event.
2214 * data[0] is the beginning of the WMI payload.
2215 */
2216 ev = (wmi_single_phyerr_rx_event *) &bufp[n];
2217
2218 /*
2219 * Sanity check the buffer length of the event against
2220 * what we currently have.
2221 * Since buf_len is 32 bits, we check if it overflows
2222 * a large 32 bit value. It's not 0x7fffffff because
2223 * we increase n by (buf_len + sizeof(hdr)), which would
2224 * in itself cause n to overflow.
2225 * If "int" is 64 bits then this becomes a moot point.
2226 */
2227 if (ev->hdr.buf_len > 0x7f000000) {
2228 WMA_LOGE("%s:buf_len is garbage (0x%x)", __func__,
2229 ev->hdr.buf_len);
2230 error = 1;
2231 break;
2232 }
2233 if (n + ev->hdr.buf_len > pe_hdr->buf_len) {
2234 WMA_LOGE("%s: buf_len exceeds available space n=%zu,"
2235 "buf_len=%d, datalen=%d",
2236 __func__, n, ev->hdr.buf_len, pe_hdr->buf_len);
2237 error = 1;
2238 break;
2239 }
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08002240 /*
2241 * If the board id is WMI_HWBD_QCA6174
2242 * then it supports only DFS-2. So, fetch
2243 * phyerror code in order to know the type
2244 * of phyerror.
2245 */
2246 if (wma->hw_bd_id == WMI_HWBD_QCA6174) {
2247 phy_err_code = WMI_UNIFIED_PHYERRCODE_GET(&ev->hdr);
2248 WMA_LOGD("%s: DFS-2 phyerror code = 0x%x",
2249 __func__, phy_err_code);
2250 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002251
2252 /*
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08002253 * phy_err_code is set for DFS-2 and phy_err_mask
2254 * is set for DFS-3. Checking both to support
2255 * compatability for older platforms.
2256 * If the phyerror or phyerrmask category matches,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002257 * pass radar events to the dfs pattern matching code.
2258 * Don't pass radar events with no buffer payload.
2259 */
Rakesh Sunki8641f8a2015-12-10 15:11:19 -08002260 if (((phy_err_mask & WMI_PHY_ERROR_MASK0_RADAR) ||
2261 (phy_err_mask & WMI_PHY_ERROR_MASK0_FALSE_RADAR_EXT)) ||
2262 (phy_err_code == WMA_DFS2_PHYERROR_CODE ||
2263 phy_err_code == WMA_DFS2_FALSE_RADAR_EXT)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002264 if (ev->hdr.buf_len > 0) {
2265 /* Calling in to the DFS module to process the phyerr */
2266 dfs_process_phyerr(ic, &ev->bufp[0],
2267 ev->hdr.buf_len,
2268 WMI_UNIFIED_RSSI_COMB_GET
2269 (&ev->hdr) & 0xff,
2270 /* Extension RSSI */
2271 WMI_UNIFIED_RSSI_COMB_GET
2272 (&ev->hdr) & 0xff,
2273 ev->hdr.tsf_timestamp,
2274 tsf64, enable_log);
2275 }
2276 }
2277
2278 /*
2279 * Advance the buffer pointer to the next PHY error.
2280 * buflen is the length of this payload, so we need to
2281 * advance past the current header _AND_ the payload.
2282 */
2283 n += sizeof(*ev) + ev->hdr.buf_len;
2284
2285 } /*end while() */
2286 if (error)
2287 return 0;
2288 else
2289 return 1;
2290}
2291
2292/**
2293 * wma_register_dfs_event_handler() - register dfs event handler
2294 * @wma_handle: wma handle
2295 *
2296 * Register appropriate dfs phyerror event handler
2297 * based on phyerror filtering offload is enabled
2298 * or disabled.
2299 *
2300 * Return: none
2301 */
2302void wma_register_dfs_event_handler(tp_wma_handle wma_handle)
2303{
2304 if (NULL == wma_handle) {
2305 WMA_LOGE("%s:wma_handle is NULL", __func__);
2306 return;
2307 }
2308
2309 if (false == wma_handle->dfs_phyerr_filter_offload) {
2310 /*
2311 * Register the wma_unified_phyerr_rx_event_handler
2312 * for filtering offload disabled case to handle
2313 * the DFS phyerrors.
2314 */
2315 WMA_LOGD("%s:Phyerror Filtering offload is Disabled in ini",
2316 __func__);
2317 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Govind Singhd76a5b02016-03-08 15:12:14 +05302318 WMI_PHYERR_EVENTID,
2319 wma_unified_phyerr_rx_event_handler,
2320 WMA_RX_WORK_CTX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002321 WMA_LOGD("%s: WMI_PHYERR_EVENTID event handler registered",
2322 __func__);
2323 } else {
2324 WMA_LOGD("%s:Phyerror Filtering offload is Enabled in ini",
2325 __func__);
2326 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Govind Singhd76a5b02016-03-08 15:12:14 +05302327 WMI_DFS_RADAR_EVENTID,
2328 wma_unified_dfs_radar_rx_event_handler,
2329 WMA_RX_WORK_CTX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002330 WMA_LOGD("%s:WMI_DFS_RADAR_EVENTID event handler registered",
2331 __func__);
2332 }
2333
2334 return;
2335}
2336
2337
2338/**
2339 * wma_unified_dfs_phyerr_filter_offload_enable() - enable dfs phyerr filter
2340 * @wma_handle: wma handle
2341 *
2342 * Send WMI_DFS_PHYERR_FILTER_ENA_CMDID or
2343 * WMI_DFS_PHYERR_FILTER_DIS_CMDID command
2344 * to firmware based on phyerr filtering
2345 * offload status.
2346 *
2347 * Return: 1 success, 0 failure
2348 */
2349int
2350wma_unified_dfs_phyerr_filter_offload_enable(tp_wma_handle wma_handle)
2351{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002352 int ret;
2353
2354 if (NULL == wma_handle) {
2355 WMA_LOGE("%s:wma_handle is NULL", __func__);
2356 return 0;
2357 }
2358
Govind Singhaa64c242016-03-08 11:31:49 +05302359 ret = wmi_unified_dfs_phyerr_filter_offload_en_cmd(wma_handle->wmi_handle,
2360 wma_handle->dfs_phyerr_filter_offload);
2361 if (ret)
2362 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002363
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002364
Govind Singhaa64c242016-03-08 11:31:49 +05302365 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002366}
2367
2368#if !defined(REMOVE_PKT_LOG)
2369/**
2370 * wma_pktlog_wmi_send_cmd() - send pktlog enable/disable command to target
2371 * @handle: wma handle
2372 * @params: pktlog params
2373 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302374 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002375 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302376QDF_STATUS wma_pktlog_wmi_send_cmd(WMA_HANDLE handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002377 struct ath_pktlog_wmi_params *params)
2378{
2379 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Govind Singhaa64c242016-03-08 11:31:49 +05302380 int ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002381
2382 /*Check if packet log is enabled in cfg.ini */
2383 if (!cds_is_packet_log_enabled()) {
2384 WMA_LOGE("%s:pkt log is not enabled in cfg.ini", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302385 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002386 }
2387
Govind Singhaa64c242016-03-08 11:31:49 +05302388 ret = wmi_unified_pktlog_wmi_send_cmd(wma_handle->wmi_handle,
2389 params->pktlog_event,
2390 params->cmd_id);
2391 if (ret)
2392 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002393
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002394
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302395 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002396}
2397#endif /* REMOVE_PKT_LOG */
2398
2399static void wma_send_status_to_suspend_ind(tp_wma_handle wma, bool suspended)
2400{
2401 tSirReadyToSuspendInd *ready_to_suspend;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302402 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002403 cds_msg_t cds_msg;
2404 uint8_t len;
2405
2406 WMA_LOGD("Posting ready to suspend indication to umac");
2407
2408 len = sizeof(tSirReadyToSuspendInd);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302409 ready_to_suspend = (tSirReadyToSuspendInd *) qdf_mem_malloc(len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002410
2411 if (NULL == ready_to_suspend) {
2412 WMA_LOGE("%s: Memory allocation failure", __func__);
2413 return;
2414 }
2415
2416 ready_to_suspend->mesgType = eWNI_SME_READY_TO_SUSPEND_IND;
2417 ready_to_suspend->mesgLen = len;
2418 ready_to_suspend->suspended = suspended;
2419
2420 cds_msg.type = eWNI_SME_READY_TO_SUSPEND_IND;
2421 cds_msg.bodyptr = (void *)ready_to_suspend;
2422 cds_msg.bodyval = 0;
2423
2424 status = cds_mq_post_message(CDS_MQ_ID_SME, &cds_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302425 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002426 WMA_LOGE("Failed to post ready to suspend");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302427 qdf_mem_free(ready_to_suspend);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002428 }
2429}
2430
2431/**
2432 * wma_wow_wake_reason_str() - Converts wow wakeup reason code to text format
2433 * @wake_reason - WOW wake reason
2434 *
2435 * Return: reason code in string format
2436 */
2437static const u8 *wma_wow_wake_reason_str(A_INT32 wake_reason)
2438{
2439 switch (wake_reason) {
2440 case WOW_REASON_UNSPECIFIED:
2441 return "UNSPECIFIED";
2442 case WOW_REASON_NLOD:
2443 return "NLOD";
2444 case WOW_REASON_AP_ASSOC_LOST:
2445 return "AP_ASSOC_LOST";
2446 case WOW_REASON_LOW_RSSI:
2447 return "LOW_RSSI";
2448 case WOW_REASON_DEAUTH_RECVD:
2449 return "DEAUTH_RECVD";
2450 case WOW_REASON_DISASSOC_RECVD:
2451 return "DISASSOC_RECVD";
2452 case WOW_REASON_GTK_HS_ERR:
2453 return "GTK_HS_ERR";
2454 case WOW_REASON_EAP_REQ:
2455 return "EAP_REQ";
2456 case WOW_REASON_FOURWAY_HS_RECV:
2457 return "FOURWAY_HS_RECV";
2458 case WOW_REASON_TIMER_INTR_RECV:
2459 return "TIMER_INTR_RECV";
2460 case WOW_REASON_PATTERN_MATCH_FOUND:
2461 return "PATTERN_MATCH_FOUND";
2462 case WOW_REASON_RECV_MAGIC_PATTERN:
2463 return "RECV_MAGIC_PATTERN";
2464 case WOW_REASON_P2P_DISC:
2465 return "P2P_DISC";
2466#ifdef FEATURE_WLAN_LPHB
2467 case WOW_REASON_WLAN_HB:
2468 return "WLAN_HB";
2469#endif /* FEATURE_WLAN_LPHB */
2470
2471 case WOW_REASON_CSA_EVENT:
2472 return "CSA_EVENT";
2473 case WOW_REASON_PROBE_REQ_WPS_IE_RECV:
2474 return "PROBE_REQ_RECV";
2475 case WOW_REASON_AUTH_REQ_RECV:
2476 return "AUTH_REQ_RECV";
2477 case WOW_REASON_ASSOC_REQ_RECV:
2478 return "ASSOC_REQ_RECV";
2479 case WOW_REASON_HTT_EVENT:
2480 return "WOW_REASON_HTT_EVENT";
2481#ifdef FEATURE_WLAN_RA_FILTERING
2482 case WOW_REASON_RA_MATCH:
2483 return "WOW_REASON_RA_MATCH";
2484#endif /* FEATURE_WLAN_RA_FILTERING */
2485 case WOW_REASON_BEACON_RECV:
2486 return "WOW_REASON_IBSS_BEACON_RECV";
2487#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
2488 case WOW_REASON_HOST_AUTO_SHUTDOWN:
2489 return "WOW_REASON_HOST_AUTO_SHUTDOWN";
2490#endif /* FEATURE_WLAN_AUTO_SHUTDOWN */
2491#ifdef WLAN_FEATURE_ROAM_OFFLOAD
2492 case WOW_REASON_ROAM_HO:
2493 return "WOW_REASON_ROAM_HO";
2494#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
2495#ifdef FEATURE_WLAN_EXTSCAN
2496 case WOW_REASON_EXTSCAN:
2497 return "WOW_REASON_EXTSCAN";
2498#endif
2499 case WOW_REASON_RSSI_BREACH_EVENT:
2500 return "WOW_REASON_RSSI_BREACH_EVENT";
Srinivas Girigowdae80cea92015-11-23 11:33:57 -08002501 case WOW_REASON_NLO_SCAN_COMPLETE:
2502 return "WOW_REASON_NLO_SCAN_COMPLETE";
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002503 }
2504 return "unknown";
2505}
2506
2507/**
2508 * wma_wow_wake_up_stats_display() - display wow wake up stats
2509 * @wma: Pointer to wma handle
2510 *
2511 * Return: none
2512 */
2513static void wma_wow_wake_up_stats_display(tp_wma_handle wma)
2514{
2515 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",
2516 wma->wow_ucast_wake_up_count,
2517 wma->wow_bcast_wake_up_count,
2518 wma->wow_ipv4_mcast_wake_up_count,
2519 wma->wow_ipv6_mcast_wake_up_count,
2520 wma->wow_ipv6_mcast_ra_stats,
2521 wma->wow_ipv6_mcast_ns_stats,
2522 wma->wow_ipv6_mcast_na_stats,
2523 wma->wow_pno_match_wake_up_count,
2524 wma->wow_pno_complete_wake_up_count,
2525 wma->wow_gscan_wake_up_count,
2526 wma->wow_low_rssi_wake_up_count,
2527 wma->wow_rssi_breach_wake_up_count);
2528
2529 return;
2530}
2531
2532/**
2533 * wma_wow_ipv6_mcast_stats() - ipv6 mcast wake up stats
2534 * @wma: Pointer to wma handle
2535 * @data: Pointer to pattern match data
2536 *
2537 * Return: none
2538 */
2539static void wma_wow_ipv6_mcast_stats(tp_wma_handle wma, uint8_t *data)
2540{
2541 static const uint8_t ipv6_mcast[] = {0x86, 0xDD};
2542
2543 if (!memcmp(ipv6_mcast, (data + WMA_ETHER_TYPE_OFFSET),
2544 sizeof(ipv6_mcast))) {
2545 if (WMA_ICMP_V6_HEADER_TYPE ==
2546 *(data + WMA_ICMP_V6_HEADER_OFFSET)) {
2547 if (WMA_ICMP_V6_RA_TYPE ==
2548 *(data + WMA_ICMP_V6_TYPE_OFFSET))
2549 wma->wow_ipv6_mcast_ra_stats++;
2550 else if (WMA_ICMP_V6_NS_TYPE ==
2551 *(data + WMA_ICMP_V6_TYPE_OFFSET))
2552 wma->wow_ipv6_mcast_ns_stats++;
2553 else if (WMA_ICMP_V6_NA_TYPE ==
2554 *(data + WMA_ICMP_V6_TYPE_OFFSET))
2555 wma->wow_ipv6_mcast_na_stats++;
2556 else
2557 WMA_LOGA("ICMP V6 type : 0x%x",
2558 *(data + WMA_ICMP_V6_TYPE_OFFSET));
2559 } else {
2560 WMA_LOGA("ICMP_V6 header 0x%x",
2561 *(data + WMA_ICMP_V6_HEADER_OFFSET));
2562 }
2563 } else {
2564 WMA_LOGA("Ethertype x%x:0x%x",
2565 *(data + WMA_ETHER_TYPE_OFFSET),
2566 *(data + WMA_ETHER_TYPE_OFFSET + 1));
2567 }
2568
2569 return;
2570}
2571
2572/**
2573 * wma_wow_wake_up_stats() - maintain wow pattern match wake up stats
2574 * @wma: Pointer to wma handle
2575 * @data: Pointer to pattern match data
2576 * @len: Pattern match data length
2577 * @event: Wake up event
2578 *
2579 * Return: none
2580 */
2581static void wma_wow_wake_up_stats(tp_wma_handle wma, uint8_t *data,
2582 int32_t len, WOW_WAKE_REASON_TYPE event)
2583{
2584 switch (event) {
2585
2586 case WOW_REASON_PATTERN_MATCH_FOUND:
2587 if (WMA_BCAST_MAC_ADDR == *data) {
2588 wma->wow_bcast_wake_up_count++;
2589 } else if (WMA_MCAST_IPV4_MAC_ADDR == *data) {
2590 wma->wow_ipv4_mcast_wake_up_count++;
2591 } else if (WMA_MCAST_IPV6_MAC_ADDR == *data) {
2592 wma->wow_ipv6_mcast_wake_up_count++;
2593 if (len > WMA_ICMP_V6_TYPE_OFFSET)
2594 wma_wow_ipv6_mcast_stats(wma, data);
2595 else
2596 WMA_LOGA("ICMP_V6 data len %d", len);
2597 } else {
2598 wma->wow_ucast_wake_up_count++;
2599 }
2600 break;
2601
2602 case WOW_REASON_RA_MATCH:
2603 wma->wow_ipv6_mcast_ra_stats++;
2604 break;
2605
2606 case WOW_REASON_NLOD:
2607 wma->wow_pno_match_wake_up_count++;
2608 break;
2609
2610 case WOW_REASON_NLO_SCAN_COMPLETE:
2611 wma->wow_pno_complete_wake_up_count++;
2612 break;
2613
2614 case WOW_REASON_LOW_RSSI:
2615 wma->wow_low_rssi_wake_up_count++;
2616 break;
2617
2618 case WOW_REASON_EXTSCAN:
2619 wma->wow_gscan_wake_up_count++;
2620 break;
2621
2622 case WOW_REASON_RSSI_BREACH_EVENT:
2623 wma->wow_rssi_breach_wake_up_count++;
2624 break;
2625
2626 default:
2627 WMA_LOGE("Unknown wake up reason");
2628 break;
2629 }
2630
2631 wma_wow_wake_up_stats_display(wma);
2632 return;
2633}
2634
2635/**
2636 * wma_wow_wakeup_host_event() - wakeup host event handler
2637 * @handle: wma handle
2638 * @event: event data
2639 * @len: buffer length
2640 *
2641 * Handler to catch wow wakeup host event. This event will have
2642 * reason why the firmware has woken the host.
2643 *
2644 * Return: 0 for success or error
2645 */
2646int wma_wow_wakeup_host_event(void *handle, uint8_t *event,
2647 uint32_t len)
2648{
2649 tp_wma_handle wma = (tp_wma_handle) handle;
2650 WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs *param_buf;
2651 WOW_EVENT_INFO_fixed_param *wake_info;
2652#ifdef FEATURE_WLAN_SCAN_PNO
2653 struct wma_txrx_node *node;
2654#endif /* FEATURE_WLAN_SCAN_PNO */
2655 uint32_t wake_lock_duration = 0;
2656 uint32_t wow_buf_pkt_len = 0;
2657
2658 param_buf = (WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs *) event;
2659 if (!param_buf) {
2660 WMA_LOGE("Invalid wow wakeup host event buf");
2661 return -EINVAL;
2662 }
2663
2664 wake_info = param_buf->fixed_param;
2665
2666 WMA_LOGA("WOW wakeup host event received (reason: %s(%d)) for vdev %d",
2667 wma_wow_wake_reason_str(wake_info->wake_reason),
2668 wake_info->wake_reason, wake_info->vdev_id);
2669
Anurag Chouhance0dc992016-02-16 18:18:03 +05302670 qdf_event_set(&wma->wma_resume_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002671
2672 switch (wake_info->wake_reason) {
2673 case WOW_REASON_AUTH_REQ_RECV:
2674 wake_lock_duration = WMA_AUTH_REQ_RECV_WAKE_LOCK_TIMEOUT;
2675 break;
2676
2677 case WOW_REASON_ASSOC_REQ_RECV:
2678 wake_lock_duration = WMA_ASSOC_REQ_RECV_WAKE_LOCK_DURATION;
2679 break;
2680
2681 case WOW_REASON_DEAUTH_RECVD:
2682 wake_lock_duration = WMA_DEAUTH_RECV_WAKE_LOCK_DURATION;
2683 break;
2684
2685 case WOW_REASON_DISASSOC_RECVD:
2686 wake_lock_duration = WMA_DISASSOC_RECV_WAKE_LOCK_DURATION;
2687 break;
2688
2689 case WOW_REASON_AP_ASSOC_LOST:
2690 wake_lock_duration = WMA_BMISS_EVENT_WAKE_LOCK_DURATION;
2691 WMA_LOGA("Beacon miss indication on vdev %x",
2692 wake_info->vdev_id);
2693 wma_beacon_miss_handler(wma, wake_info->vdev_id);
2694 break;
2695#ifdef FEATURE_WLAN_RA_FILTERING
2696 case WOW_REASON_RA_MATCH:
2697 wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_RA_MATCH);
2698 break;
2699#endif /* FEATURE_WLAN_RA_FILTERING */
2700#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
2701 case WOW_REASON_HOST_AUTO_SHUTDOWN:
2702 wake_lock_duration = WMA_AUTO_SHUTDOWN_WAKE_LOCK_DURATION;
2703 WMA_LOGA("Received WOW Auto Shutdown trigger in suspend");
2704 if (wma_post_auto_shutdown_msg())
2705 return -EINVAL;
2706 break;
2707#endif /* FEATURE_WLAN_AUTO_SHUTDOWN */
2708#ifdef FEATURE_WLAN_SCAN_PNO
2709 case WOW_REASON_NLOD:
2710 wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_NLOD);
2711 node = &wma->interfaces[wake_info->vdev_id];
2712 if (node) {
2713 WMA_LOGD("NLO match happened");
2714 node->nlo_match_evt_received = true;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302715 qdf_wake_lock_timeout_acquire(&wma->pno_wake_lock,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002716 WMA_PNO_MATCH_WAKE_LOCK_TIMEOUT,
2717 WIFI_POWER_EVENT_WAKELOCK_PNO);
Srinivas Girigowdae80cea92015-11-23 11:33:57 -08002718 }
2719 break;
2720
2721 case WOW_REASON_NLO_SCAN_COMPLETE:
2722 {
2723 WMI_NLO_SCAN_COMPLETE_EVENTID_param_tlvs param;
2724
2725 WMA_LOGD("Host woken up due to pno scan complete reason");
2726
2727 /* First 4-bytes of wow_packet_buffer is the length */
2728 if (param_buf->wow_packet_buffer) {
2729 param.fixed_param = (wmi_nlo_event *)
2730 (param_buf->wow_packet_buffer + 4);
2731 wma_nlo_scan_cmp_evt_handler(handle,
2732 (u_int8_t *)&param, sizeof(param));
2733 } else
2734 WMA_LOGD("No wow_packet_buffer present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002735 }
2736 break;
2737#endif /* FEATURE_WLAN_SCAN_PNO */
2738
2739 case WOW_REASON_CSA_EVENT:
2740 {
2741 WMI_CSA_HANDLING_EVENTID_param_tlvs param;
2742 WMA_LOGD("Host woken up because of CSA IE");
2743 param.fixed_param = (wmi_csa_event_fixed_param *)
2744 (((uint8_t *) wake_info)
2745 + sizeof(WOW_EVENT_INFO_fixed_param)
2746 + WOW_CSA_EVENT_OFFSET);
2747 wma_csa_offload_handler(handle, (uint8_t *) &param,
2748 sizeof(param));
2749 }
2750 break;
2751
2752#ifdef FEATURE_WLAN_LPHB
2753 case WOW_REASON_WLAN_HB:
2754 wma_lphb_handler(wma, (uint8_t *) param_buf->hb_indevt);
2755 break;
2756#endif /* FEATURE_WLAN_LPHB */
2757
2758 case WOW_REASON_HTT_EVENT:
2759 break;
2760 case WOW_REASON_PATTERN_MATCH_FOUND:
2761 wma_wow_wake_up_stats_display(wma);
2762 WMA_LOGD("Wake up for Rx packet, dump starting from ethernet hdr");
2763 if (param_buf->wow_packet_buffer) {
2764 /* First 4-bytes of wow_packet_buffer is the length */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302765 qdf_mem_copy((uint8_t *) &wow_buf_pkt_len,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002766 param_buf->wow_packet_buffer, 4);
2767 wma_wow_wake_up_stats(wma,
2768 param_buf->wow_packet_buffer + 4,
2769 wow_buf_pkt_len,
2770 WOW_REASON_PATTERN_MATCH_FOUND);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302771 qdf_trace_hex_dump(QDF_MODULE_ID_WMA,
2772 QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002773 param_buf->wow_packet_buffer + 4,
2774 wow_buf_pkt_len);
2775 } else {
2776 WMA_LOGE("No wow packet buffer present");
2777 }
2778 break;
2779
2780 case WOW_REASON_LOW_RSSI:
2781 {
2782 /* WOW_REASON_LOW_RSSI is used for all roaming events.
2783 * WMI_ROAM_REASON_BETTER_AP, WMI_ROAM_REASON_BMISS,
2784 * WMI_ROAM_REASON_SUITABLE_AP will be handled by
2785 * wma_roam_event_callback().
2786 */
2787 WMI_ROAM_EVENTID_param_tlvs param;
2788 wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_LOW_RSSI);
2789 if (param_buf->wow_packet_buffer) {
2790 /* Roam event is embedded in wow_packet_buffer */
2791 WMA_LOGD("Host woken up because of roam event");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302792 qdf_mem_copy((uint8_t *) &wow_buf_pkt_len,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002793 param_buf->wow_packet_buffer, 4);
2794 WMA_LOGD("wow_packet_buffer dump");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302795 qdf_trace_hex_dump(QDF_MODULE_ID_WMA,
2796 QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002797 param_buf->wow_packet_buffer,
2798 wow_buf_pkt_len);
2799 if (wow_buf_pkt_len >= sizeof(param)) {
2800 param.fixed_param =
2801 (wmi_roam_event_fixed_param *)
2802 (param_buf->wow_packet_buffer + 4);
2803 wma_roam_event_callback(handle,
2804 (uint8_t *) &
2805 param,
2806 sizeof(param));
2807 } else {
2808 WMA_LOGE("Wrong length for roam event = %d bytes",
2809 wow_buf_pkt_len);
2810 }
2811 } else {
2812 /* No wow_packet_buffer means a better AP beacon
2813 * will follow in a later event.
2814 */
2815 WMA_LOGD("Host woken up because of better AP beacon");
2816 }
2817 break;
2818 }
2819 case WOW_REASON_CLIENT_KICKOUT_EVENT:
2820 {
2821 WMI_PEER_STA_KICKOUT_EVENTID_param_tlvs param;
2822 if (param_buf->wow_packet_buffer) {
2823 /* station kickout event embedded in wow_packet_buffer */
2824 WMA_LOGD("Host woken up because of sta_kickout event");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302825 qdf_mem_copy((u_int8_t *) &wow_buf_pkt_len,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002826 param_buf->wow_packet_buffer, 4);
2827 WMA_LOGD("wow_packet_buffer dump");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302828 qdf_trace_hex_dump(QDF_MODULE_ID_WMA,
2829 QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002830 param_buf->wow_packet_buffer, wow_buf_pkt_len);
2831 if (wow_buf_pkt_len >= sizeof(param)) {
2832 param.fixed_param = (wmi_peer_sta_kickout_event_fixed_param *)
2833 (param_buf->wow_packet_buffer + 4);
2834 wma_peer_sta_kickout_event_handler(handle,
2835 (u_int8_t *)&param, sizeof(param));
2836 } else {
2837 WMA_LOGE("Wrong length for sta_kickout event = %d bytes",
2838 wow_buf_pkt_len);
2839 }
2840 } else {
2841 WMA_LOGD("No wow_packet_buffer present");
2842 }
2843 break;
2844 }
2845#ifdef FEATURE_WLAN_EXTSCAN
2846 case WOW_REASON_EXTSCAN:
2847 WMA_LOGD("Host woken up because of extscan reason");
2848 wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_EXTSCAN);
2849 if (param_buf->wow_packet_buffer) {
2850 wow_buf_pkt_len =
2851 *(uint32_t *)param_buf->wow_packet_buffer;
2852 wma_extscan_wow_event_callback(handle,
2853 (u_int8_t *)(param_buf->wow_packet_buffer + 4),
2854 wow_buf_pkt_len);
2855 } else
2856 WMA_LOGE("wow_packet_buffer is empty");
2857 break;
2858#endif
2859 case WOW_REASON_RSSI_BREACH_EVENT:
2860 {
2861 WMI_RSSI_BREACH_EVENTID_param_tlvs param;
2862
2863 wma_wow_wake_up_stats(wma, NULL, 0,
2864 WOW_REASON_RSSI_BREACH_EVENT);
2865 WMA_LOGD("Host woken up because of rssi breach reason");
2866 /* rssi breach event is embedded in wow_packet_buffer */
2867 if (param_buf->wow_packet_buffer) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302868 qdf_mem_copy((u_int8_t *) &wow_buf_pkt_len,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002869 param_buf->wow_packet_buffer, 4);
2870 if (wow_buf_pkt_len >= sizeof(param)) {
2871 param.fixed_param =
2872 (wmi_rssi_breach_event_fixed_param *)
2873 (param_buf->wow_packet_buffer + 4);
2874 wma_rssi_breached_event_handler(handle,
2875 (u_int8_t *)&param,
2876 sizeof(param));
2877 } else {
2878 WMA_LOGE("%s: Wrong length: %d bytes",
2879 __func__, wow_buf_pkt_len);
2880 }
2881 } else
2882 WMA_LOGD("No wow_packet_buffer present");
2883 }
2884 break;
2885 default:
2886 break;
2887 }
2888
2889 if (wake_lock_duration) {
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302890 qdf_wake_lock_timeout_acquire(&wma->wow_wake_lock,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002891 wake_lock_duration,
2892 WIFI_POWER_EVENT_WAKELOCK_WOW);
2893 WMA_LOGA("Holding %d msec wake_lock", wake_lock_duration);
2894 }
2895
2896 return 0;
2897}
2898
2899/**
2900 * wma_pdev_resume_event_handler() - PDEV resume event handler
2901 * @handle: wma handle
2902 * @event: event data
2903 * @len: buffer length
2904 *
2905 * Return: 0 for success or error
2906 */
2907int wma_pdev_resume_event_handler(void *handle, uint8_t *event, uint32_t len)
2908{
2909 tp_wma_handle wma = (tp_wma_handle) handle;
2910
2911 WMA_LOGA("Received PDEV resume event");
2912
Anurag Chouhance0dc992016-02-16 18:18:03 +05302913 qdf_event_set(&wma->wma_resume_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002914
2915 return 0;
2916}
2917/**
2918 * wma_set_wow_bus_suspend() - set suspend flag
2919 * @wma: wma handle
2920 * @val: value
2921 *
2922 * Return: none
2923 */
2924static inline void wma_set_wow_bus_suspend(tp_wma_handle wma, int val)
2925{
2926
Anurag Chouhan8e0ccd32016-02-19 15:30:20 +05302927 qdf_atomic_set(&wma->is_wow_bus_suspended, val);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002928}
2929
2930
2931
2932/**
2933 * wma_add_wow_wakeup_event() - Configures wow wakeup events.
2934 * @wma: wma handle
2935 * @vdev_id: vdev id
2936 * @bitmap: Event bitmap
2937 * @enable: enable/disable
2938 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302939 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002940 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302941static QDF_STATUS wma_add_wow_wakeup_event(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002942 uint32_t vdev_id,
2943 uint32_t bitmap,
2944 bool enable)
2945{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002946 int ret;
2947
Govind Singhaa64c242016-03-08 11:31:49 +05302948 ret = wmi_unified_add_wow_wakeup_event_cmd(wma->wmi_handle, vdev_id,
2949 enable, bitmap);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002950 if (ret) {
2951 WMA_LOGE("Failed to config wow wakeup event");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302952 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002953 }
2954
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302955 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002956}
2957
2958/**
2959 * wma_send_wow_patterns_to_fw() - Sends WOW patterns to FW.
2960 * @wma: wma handle
2961 * @vdev_id: vdev id
2962 * @ptrn_id: pattern id
2963 * @ptrn: pattern
2964 * @ptrn_len: pattern length
2965 * @ptrn_offset: pattern offset
2966 * @mask: mask
2967 * @mask_len: mask length
2968 * @user: true for user configured pattern and false for default pattern
2969 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302970 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002971 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302972static QDF_STATUS wma_send_wow_patterns_to_fw(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002973 uint8_t vdev_id, uint8_t ptrn_id,
2974 const uint8_t *ptrn, uint8_t ptrn_len,
2975 uint8_t ptrn_offset, const uint8_t *mask,
2976 uint8_t mask_len, bool user)
2977{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002978 struct wma_txrx_node *iface;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002979 int ret;
Govind Singhaa64c242016-03-08 11:31:49 +05302980 uint8_t default_patterns;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002981
2982 iface = &wma->interfaces[vdev_id];
Govind Singhaa64c242016-03-08 11:31:49 +05302983 default_patterns = iface->num_wow_default_patterns++;
2984 ret = wmi_unified_wow_patterns_to_fw_cmd(wma->wmi_handle,
2985 vdev_id, ptrn_id, ptrn,
2986 ptrn_len, ptrn_offset, mask,
2987 mask_len, user, default_patterns);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002988 if (ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002989 if (!user)
2990 iface->num_wow_default_patterns--;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302991 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002992 }
2993
2994 if (user)
2995 iface->num_wow_user_patterns++;
2996
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302997 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002998}
2999
3000/**
3001 * wma_wow_ap() - set WOW patterns in ap mode
3002 * @wma: wma handle
3003 * @vdev_id: vdev id
3004 *
3005 * Configures default WOW pattern for the given vdev_id which is in AP mode.
3006 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303007 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003008 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303009static QDF_STATUS wma_wow_ap(tp_wma_handle wma, uint8_t vdev_id)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003010{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303011 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003012 uint8_t arp_offset = 20;
3013 uint8_t mac_mask[IEEE80211_ADDR_LEN];
3014
3015 /* Setup unicast pkt pattern */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303016 qdf_mem_set(&mac_mask, IEEE80211_ADDR_LEN, 0xFF);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003017 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
3018 wma->interfaces[vdev_id].addr,
3019 IEEE80211_ADDR_LEN, 0, mac_mask,
3020 IEEE80211_ADDR_LEN, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303021 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003022 WMA_LOGE("Failed to add WOW unicast pattern ret %d", ret);
3023 return ret;
3024 }
3025
3026 /*
3027 * Setup all ARP pkt pattern. This is dummy pattern hence the length
3028 * is zero
3029 */
3030 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
3031 arp_ptrn, 0, arp_offset, arp_mask, 0, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303032 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003033 WMA_LOGE("Failed to add WOW ARP pattern ret %d", ret);
3034 return ret;
3035 }
3036
3037 return ret;
3038}
3039
3040/**
3041 * wma_wow_sta() - set WOW patterns in sta mode
3042 * @wma: wma handle
3043 * @vdev_id: vdev id
3044 *
3045 * Configures default WOW pattern for the given vdev_id which is in sta mode.
3046 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303047 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003048 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303049static QDF_STATUS wma_wow_sta(tp_wma_handle wma, uint8_t vdev_id)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003050{
3051 uint8_t arp_offset = 12;
3052 uint8_t discvr_offset = 30;
3053 uint8_t mac_mask[IEEE80211_ADDR_LEN];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303054 QDF_STATUS ret = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003055
3056 /* Setup unicast pkt pattern */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303057 qdf_mem_set(&mac_mask, IEEE80211_ADDR_LEN, 0xFF);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003058 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
3059 wma->interfaces[vdev_id].addr,
3060 IEEE80211_ADDR_LEN, 0, mac_mask,
3061 IEEE80211_ADDR_LEN, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303062 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003063 WMA_LOGE("Failed to add WOW unicast pattern ret %d", ret);
3064 return ret;
3065 }
3066
3067 /*
3068 * Setup multicast pattern for mDNS 224.0.0.251,
3069 * SSDP 239.255.255.250 and LLMNR 224.0.0.252
3070 */
3071 if (wma->ssdp) {
3072 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
3073 discvr_ptrn, sizeof(discvr_ptrn), discvr_offset,
3074 discvr_mask, sizeof(discvr_ptrn), false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303075 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003076 WMA_LOGE("Failed to add WOW mDNS/SSDP/LLMNR pattern");
3077 return ret;
3078 }
3079 } else
3080 WMA_LOGD("mDNS, SSDP, LLMNR patterns are disabled from ini");
3081
3082 /* when arp offload or ns offloaded is disabled
3083 * from ini file, configure broad cast arp pattern
3084 * to fw, so that host can wake up
3085 */
3086 if (!(wma->ol_ini_info & 0x1)) {
3087 /* Setup all ARP pkt pattern */
3088 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
3089 arp_ptrn, sizeof(arp_ptrn), arp_offset,
3090 arp_mask, sizeof(arp_mask), false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303091 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003092 WMA_LOGE("Failed to add WOW ARP pattern");
3093 return ret;
3094 }
3095 }
3096
3097 /* for NS or NDP offload packets */
3098 if (!(wma->ol_ini_info & 0x2)) {
3099 /* Setup all NS pkt pattern */
3100 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
3101 ns_ptrn, sizeof(arp_ptrn), arp_offset,
3102 arp_mask, sizeof(arp_mask), false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303103 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003104 WMA_LOGE("Failed to add WOW NS pattern");
3105 return ret;
3106 }
3107 }
3108
3109 return ret;
3110}
3111
3112/**
3113 * wma_register_wow_default_patterns() - register default wow patterns with fw
3114 * @handle: Pointer to wma handle
3115 * @vdev_id: vdev id
3116 *
3117 * WoW default wake up pattern rule is:
3118 * - For STA & P2P CLI mode register for same STA specific wow patterns
3119 * - For SAP/P2P GO & IBSS mode register for same SAP specific wow patterns
3120 *
3121 * Return: none
3122 */
3123void wma_register_wow_default_patterns(WMA_HANDLE handle, uint8_t vdev_id)
3124{
3125 tp_wma_handle wma = handle;
3126 struct wma_txrx_node *iface;
3127
3128 if (vdev_id > wma->max_bssid) {
3129 WMA_LOGE("Invalid vdev id %d", vdev_id);
3130 return;
3131 }
3132 iface = &wma->interfaces[vdev_id];
3133
3134 if (iface->ptrn_match_enable) {
Houston Hoffman79b4af22015-10-06 12:01:08 -07003135 if (wma_is_vdev_in_beaconning_mode(wma, vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003136 /* Configure SAP/GO/IBSS mode default wow patterns */
3137 WMA_LOGI("Config SAP specific default wow patterns vdev_id %d",
3138 vdev_id);
3139 wma_wow_ap(wma, vdev_id);
3140 } else {
3141 /* Configure STA/P2P CLI mode default wow patterns */
3142 WMA_LOGI("Config STA specific default wow patterns vdev_id %d",
3143 vdev_id);
3144 wma_wow_sta(wma, vdev_id);
3145 if (wma->IsRArateLimitEnabled) {
3146 WMA_LOGI("Config STA RA limit wow patterns vdev_id %d",
3147 vdev_id);
3148 wma_wow_sta_ra_filter(wma, vdev_id);
3149 }
3150 }
3151 }
3152
3153 return;
3154}
3155
3156/**
3157 * wma_register_wow_wakeup_events() - register vdev specific wake events with fw
3158 * @handle: Pointer to wma handle
3159 * @vdev_id: vdev Id
3160 * @vdev_type: vdev type
3161 * @vdev_subtype: vdev sub type
3162 *
3163 * WoW wake up event rule is following:
3164 * 1) STA mode and P2P CLI mode wake up events are same
3165 * 2) SAP mode and P2P GO mode wake up events are same
3166 * 3) IBSS mode wake events are same as STA mode plus WOW_BEACON_EVENT
3167 *
3168 * Return: none
3169 */
3170void wma_register_wow_wakeup_events(WMA_HANDLE handle,
3171 uint8_t vdev_id,
3172 uint8_t vdev_type,
3173 uint8_t vdev_subtype)
3174{
3175 tp_wma_handle wma = handle;
3176 uint32_t event_bitmap;
3177
3178 WMA_LOGI("vdev_type %d vdev_subtype %d vdev_id %d", vdev_type,
3179 vdev_subtype, vdev_id);
3180
3181 if ((WMI_VDEV_TYPE_STA == vdev_type) ||
3182 ((WMI_VDEV_TYPE_AP == vdev_type) &&
3183 (WMI_UNIFIED_VDEV_SUBTYPE_P2P_DEVICE == vdev_subtype))) {
3184 /* Configure STA/P2P CLI mode specific default wake up events */
3185 event_bitmap = WMA_WOW_STA_WAKE_UP_EVENTS;
3186 WMA_LOGI("STA specific default wake up event 0x%x vdev id %d",
3187 event_bitmap, vdev_id);
3188 } else if (WMI_VDEV_TYPE_IBSS == vdev_type) {
3189 /* Configure IBSS mode specific default wake up events */
3190 event_bitmap = (WMA_WOW_STA_WAKE_UP_EVENTS |
3191 (1 << WOW_BEACON_EVENT));
3192 WMA_LOGI("IBSS specific default wake up event 0x%x vdev id %d",
3193 event_bitmap, vdev_id);
3194 } else if (WMI_VDEV_TYPE_AP == vdev_type) {
3195 /* Configure SAP/GO mode specific default wake up events */
3196 event_bitmap = WMA_WOW_SAP_WAKE_UP_EVENTS;
3197 WMA_LOGI("SAP specific default wake up event 0x%x vdev id %d",
3198 event_bitmap, vdev_id);
3199 } else {
3200 WMA_LOGE("unknown type %d subtype %d", vdev_type, vdev_subtype);
3201 return;
3202 }
3203
3204 wma_add_wow_wakeup_event(wma, vdev_id, event_bitmap, true);
3205
3206 return;
3207}
3208
3209/**
3210 * wma_enable_disable_wakeup_event() - Configures wow wakeup events
3211 * @wma: wma handle
3212 * @vdev_id: vdev id
3213 * @bitmap: Event bitmap
3214 * @enable: enable/disable
3215 *
3216 * Return: none
3217 */
3218void wma_enable_disable_wakeup_event(WMA_HANDLE handle,
3219 uint32_t vdev_id,
3220 uint32_t bitmap,
3221 bool enable)
3222{
3223 tp_wma_handle wma = handle;
3224
3225 WMA_LOGI("vdev_id %d wake up event 0x%x enable %d",
3226 vdev_id, bitmap, enable);
3227 wma_add_wow_wakeup_event(wma, vdev_id, bitmap, enable);
3228}
3229
3230/**
3231 * wma_enable_wow_in_fw() - wnable wow in fw
3232 * @wma: wma handle
3233 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303234 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003235 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303236QDF_STATUS wma_enable_wow_in_fw(WMA_HANDLE handle)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003237{
3238 tp_wma_handle wma = handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003239 int ret;
Komal Seelam3d202862016-02-24 18:43:24 +05303240 struct hif_opaque_softc *scn;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003241 int host_credits;
3242 int wmi_pending_cmds;
Govind Singhd76a5b02016-03-08 15:12:14 +05303243 struct wow_cmd_params param = {0};
3244
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003245#ifdef CONFIG_CNSS
Anurag Chouhan6d760662016-02-20 16:05:43 +05303246 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003247
3248 if (NULL == pMac) {
3249 WMA_LOGE("%s: Unable to get PE context", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303250 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003251 }
3252#endif /* CONFIG_CNSS */
3253
Anurag Chouhance0dc992016-02-16 18:18:03 +05303254 qdf_event_reset(&wma->target_suspend);
Houston Hoffmana769ed32016-04-14 17:02:51 -07003255 wma->wow_nack = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003256
3257 host_credits = wmi_get_host_credits(wma->wmi_handle);
3258 wmi_pending_cmds = wmi_get_pending_cmds(wma->wmi_handle);
3259
3260 WMA_LOGD("Credits:%d; Pending_Cmds: %d",
3261 host_credits, wmi_pending_cmds);
3262
3263 if (host_credits < WMI_WOW_REQUIRED_CREDITS) {
3264 WMA_LOGE("%s: Host Doesn't have enough credits to Post WMI_WOW_ENABLE_CMDID! "
3265 "Credits:%d, pending_cmds:%d\n", __func__, host_credits,
3266 wmi_pending_cmds);
3267#ifndef QCA_WIFI_3_0_EMU
3268 goto error;
3269#endif
3270 }
3271
Govind Singhd76a5b02016-03-08 15:12:14 +05303272 param.enable = true;
3273 param.can_suspend_link = hif_can_suspend_link(wma->htc_handle);
3274 ret = wmi_unified_wow_enable_send(wma->wmi_handle, &param,
3275 WMA_WILDCARD_PDEV_ID);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003276 if (ret) {
3277 WMA_LOGE("Failed to enable wow in fw");
3278 goto error;
3279 }
3280
3281 wmi_set_target_suspend(wma->wmi_handle, true);
3282
Anurag Chouhance0dc992016-02-16 18:18:03 +05303283 if (qdf_wait_single_event(&wma->target_suspend,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003284 WMA_TGT_SUSPEND_COMPLETE_TIMEOUT)
Anurag Chouhance0dc992016-02-16 18:18:03 +05303285 != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003286 WMA_LOGE("Failed to receive WoW Enable Ack from FW");
3287 WMA_LOGE("Credits:%d; Pending_Cmds: %d",
3288 wmi_get_host_credits(wma->wmi_handle),
3289 wmi_get_pending_cmds(wma->wmi_handle));
Prashanth Bhatta9e143052015-12-04 11:56:47 -08003290 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003291#ifdef CONFIG_CNSS
Yue Ma455aff62015-10-20 18:29:16 -07003292 if (pMac->sme.enableSelfRecovery) {
3293 cds_trigger_recovery();
3294 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303295 QDF_BUG(0);
Yue Ma455aff62015-10-20 18:29:16 -07003296 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003297#else
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303298 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003299#endif /* CONFIG_CNSS */
Yue Ma455aff62015-10-20 18:29:16 -07003300 } else {
3301 WMA_LOGE("%s: LOGP is in progress, ignore!", __func__);
3302 }
3303
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003304 wmi_set_target_suspend(wma->wmi_handle, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303305 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003306 }
3307
3308 if (wma->wow_nack) {
3309 WMA_LOGE("FW not ready to WOW");
3310 wmi_set_target_suspend(wma->wmi_handle, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303311 return QDF_STATUS_E_AGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003312 }
3313
3314 host_credits = wmi_get_host_credits(wma->wmi_handle);
3315 wmi_pending_cmds = wmi_get_pending_cmds(wma->wmi_handle);
3316
3317 if (host_credits < WMI_WOW_REQUIRED_CREDITS) {
3318 WMA_LOGE("%s: No Credits after HTC ACK:%d, pending_cmds:%d, "
3319 "cannot resume back", __func__, host_credits,
3320 wmi_pending_cmds);
3321 htc_dump_counter_info(wma->htc_handle);
Prashanth Bhatta9e143052015-12-04 11:56:47 -08003322 if (!cds_is_driver_recovering())
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303323 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003324 else
3325 WMA_LOGE("%s: SSR in progress, ignore no credit issue",
3326 __func__);
3327 }
3328
3329 WMA_LOGD("WOW enabled successfully in fw: credits:%d"
3330 "pending_cmds: %d", host_credits, wmi_pending_cmds);
3331
Anurag Chouhan6d760662016-02-20 16:05:43 +05303332 scn = cds_get_context(QDF_MODULE_ID_HIF);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003333
3334 if (scn == NULL) {
3335 WMA_LOGE("%s: Failed to get HIF context", __func__);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303336 QDF_ASSERT(0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303337 return QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003338 }
3339
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003340 wma->wow.wow_enable_cmd_sent = true;
3341
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303342 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003343
3344error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303345 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003346}
3347
3348/**
3349 * wma_resume_req() - clear configured wow patterns in fw
3350 * @wma: wma handle
Houston Hoffmana76591b2015-11-10 16:52:05 -08003351 * @type: type of suspend
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003352 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303353 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003354 */
Anurag Chouhan6d760662016-02-20 16:05:43 +05303355QDF_STATUS wma_resume_req(tp_wma_handle wma, enum qdf_suspend_type type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003356{
Anurag Chouhan6d760662016-02-20 16:05:43 +05303357 if (type == QDF_SYSTEM_SUSPEND) {
Houston Hoffmana76591b2015-11-10 16:52:05 -08003358 wma->no_of_resume_ind++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003359
Houston Hoffmana76591b2015-11-10 16:52:05 -08003360 if (wma->no_of_resume_ind < wma_get_vdev_count(wma))
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303361 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003362
Houston Hoffmana76591b2015-11-10 16:52:05 -08003363 wma->no_of_resume_ind = 0;
3364 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003365
3366 /* Reset the DTIM Parameters */
3367 wma_set_resume_dtim(wma);
3368 /* need to reset if hif_pci_suspend_fails */
3369 wma_set_wow_bus_suspend(wma, 0);
3370 /* unpause the vdev if left paused and hif_pci_suspend fails */
3371 wma_unpause_vdev(wma);
3372
Houston Hoffman1460fa32015-11-18 02:36:30 -08003373 wmi_set_runtime_pm_inprogress(wma->wmi_handle, false);
3374
Houston Hoffmanc45db892015-11-13 19:59:25 -08003375 if (type == QDF_RUNTIME_SUSPEND)
3376 qdf_runtime_pm_allow_suspend(wma->wma_runtime_resume_lock);
3377
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303378 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003379}
3380
3381/**
3382 * wma_wow_delete_pattern() - delete wow pattern in target
3383 * @wma: wma handle
3384 * @ptrn_id: pattern id
3385 * @vdev_id: vdev id
3386 * @user: true for user pattern and false for default pattern
3387 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303388 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003389 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303390static QDF_STATUS wma_wow_delete_pattern(tp_wma_handle wma, uint8_t ptrn_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003391 uint8_t vdev_id, bool user)
3392{
Govind Singhaa64c242016-03-08 11:31:49 +05303393
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003394 struct wma_txrx_node *iface;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003395 int ret;
3396
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003397 iface = &wma->interfaces[vdev_id];
Govind Singhaa64c242016-03-08 11:31:49 +05303398 ret = wmi_unified_wow_delete_pattern_cmd(wma->wmi_handle, ptrn_id,
3399 vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003400 if (ret) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303401 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003402 }
3403
3404 if (user)
3405 iface->num_wow_user_patterns--;
3406
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303407 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003408}
3409
3410/**
3411 * wma_wow_add_pattern() - add wow pattern in target
3412 * @wma: wma handle
3413 * @ptrn: wow pattern
3414 *
3415 * This function does following:
3416 * 1) Delete all default patterns of the vdev
3417 * 2) Add received wow patterns for given vdev in target.
3418 *
3419 * Target is responsible for caching wow patterns accross multiple
3420 * suspend/resumes until the pattern is deleted by user
3421 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303422 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003423 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303424QDF_STATUS wma_wow_add_pattern(tp_wma_handle wma, struct wow_add_pattern *ptrn)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003425{
3426 uint8_t id;
3427 uint8_t bit_to_check, pos;
3428 struct wma_txrx_node *iface;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303429 QDF_STATUS ret = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003430 uint8_t new_mask[SIR_WOWL_BCAST_PATTERN_MAX_SIZE];
3431
3432 if (ptrn->session_id > wma->max_bssid) {
3433 WMA_LOGE("Invalid vdev id (%d)", ptrn->session_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303434 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003435 }
3436
3437 iface = &wma->interfaces[ptrn->session_id];
3438
3439 /* clear all default patterns cofigured by wma */
3440 for (id = 0; id < iface->num_wow_default_patterns; id++)
3441 wma_wow_delete_pattern(wma, id, ptrn->session_id, false);
3442
3443 iface->num_wow_default_patterns = 0;
3444
3445 WMA_LOGI("Add user passed wow pattern id %d vdev id %d",
3446 ptrn->pattern_id, ptrn->session_id);
3447 /*
3448 * Convert received pattern mask value from bit representation
3449 * to byte representation.
3450 *
3451 * For example, received value from umac,
3452 *
3453 * Mask value : A1 (equivalent binary is "1010 0001")
3454 * Pattern value : 12:00:13:00:00:00:00:44
3455 *
3456 * The value which goes to FW after the conversion from this
3457 * function (1 in mask value will become FF and 0 will
3458 * become 00),
3459 *
3460 * Mask value : FF:00:FF:00:0:00:00:FF
3461 * Pattern value : 12:00:13:00:00:00:00:44
3462 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303463 qdf_mem_zero(new_mask, sizeof(new_mask));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003464 for (pos = 0; pos < ptrn->pattern_size; pos++) {
3465 bit_to_check = (WMA_NUM_BITS_IN_BYTE - 1) -
3466 (pos % WMA_NUM_BITS_IN_BYTE);
3467 bit_to_check = 0x1 << bit_to_check;
3468 if (ptrn->pattern_mask[pos / WMA_NUM_BITS_IN_BYTE] &
3469 bit_to_check)
3470 new_mask[pos] = WMA_WOW_PTRN_MASK_VALID;
3471 }
3472
3473 ret = wma_send_wow_patterns_to_fw(wma, ptrn->session_id,
3474 ptrn->pattern_id,
3475 ptrn->pattern, ptrn->pattern_size,
3476 ptrn->pattern_byte_offset, new_mask,
3477 ptrn->pattern_size, true);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303478 if (ret != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003479 WMA_LOGE("Failed to add wow pattern %d", ptrn->pattern_id);
3480
3481 return ret;
3482}
3483
3484/**
3485 * wma_wow_delete_user_pattern() - delete user configured wow pattern in target
3486 * @wma: wma handle
3487 * @ptrn: wow pattern
3488 *
3489 * This function does following:
3490 * 1) Deletes a particular user configured wow pattern in target
3491 * 2) After deleting all user wow patterns add default wow patterns
3492 * specific to that vdev.
3493 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303494 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003495 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303496QDF_STATUS wma_wow_delete_user_pattern(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003497 struct wow_delete_pattern *pattern)
3498{
3499 struct wma_txrx_node *iface;
3500
3501 if (pattern->session_id > wma->max_bssid) {
3502 WMA_LOGE("Invalid vdev id %d", pattern->session_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303503 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003504 }
3505
3506 iface = &wma->interfaces[pattern->session_id];
3507 if (iface->num_wow_user_patterns <= 0) {
3508 WMA_LOGE("No valid user pattern. Num user pattern %u vdev %d",
3509 iface->num_wow_user_patterns, pattern->session_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303510 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003511 }
3512
3513 WMA_LOGI("Delete user passed wow pattern id %d total user pattern %d",
3514 pattern->pattern_id, iface->num_wow_user_patterns);
3515
3516 wma_wow_delete_pattern(wma, pattern->pattern_id,
3517 pattern->session_id, true);
3518
3519 /* configure default patterns once all user patterns are deleted */
3520 if (!iface->num_wow_user_patterns)
3521 wma_register_wow_default_patterns(wma, pattern->session_id);
3522
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303523 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003524}
3525
3526/**
3527 * wma_wow_enter() - store enable/disable status for pattern
3528 * @wma: wma handle
3529 * @info: wow parameters
3530 *
3531 * Records pattern enable/disable status locally. This choice will
3532 * take effect when the driver enter into suspend state.
3533 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303534 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003535 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303536QDF_STATUS wma_wow_enter(tp_wma_handle wma, tpSirHalWowlEnterParams info)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003537{
3538 struct wma_txrx_node *iface;
3539
3540 WMA_LOGD("wow enable req received for vdev id: %d", info->sessionId);
3541
3542 if (info->sessionId > wma->max_bssid) {
3543 WMA_LOGE("Invalid vdev id (%d)", info->sessionId);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303544 qdf_mem_free(info);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303545 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003546 }
3547
3548 iface = &wma->interfaces[info->sessionId];
3549 iface->ptrn_match_enable = info->ucPatternFilteringEnable ?
3550 true : false;
3551 wma->wow.magic_ptrn_enable = info->ucMagicPktEnable ? true : false;
3552 wma->wow.deauth_enable = info->ucWowDeauthRcv ? true : false;
3553 wma->wow.disassoc_enable = info->ucWowDeauthRcv ? true : false;
3554 wma->wow.bmiss_enable = info->ucWowMaxMissedBeacons ? true : false;
3555
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303556 qdf_mem_free(info);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003557
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303558 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003559}
3560
3561/**
3562 * wma_wow_exit() - clear all wma states
3563 * @wma: wma handle
3564 * @info: wow params
3565 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303566 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003567 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303568QDF_STATUS wma_wow_exit(tp_wma_handle wma, tpSirHalWowlExitParams info)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003569{
3570 struct wma_txrx_node *iface;
3571
3572 WMA_LOGD("wow disable req received for vdev id: %d", info->sessionId);
3573
3574 if (info->sessionId > wma->max_bssid) {
3575 WMA_LOGE("Invalid vdev id (%d)", info->sessionId);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303576 qdf_mem_free(info);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303577 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003578 }
3579
3580 iface = &wma->interfaces[info->sessionId];
3581 iface->ptrn_match_enable = false;
3582 wma->wow.magic_ptrn_enable = false;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303583 qdf_mem_free(info);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003584
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303585 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003586}
3587
3588/**
Houston Hoffmana76591b2015-11-10 16:52:05 -08003589 * wma_calculate_and_update_conn_state(): calculate each interfaces conn state
3590 * @wma: validated wma handle
3591 *
3592 * Identifies any vdev that is up and not in ap mode as connected.
3593 * stores this in the interfaces conn_state varible.
3594 */
3595void wma_calculate_and_update_conn_state(tp_wma_handle wma)
3596{
3597 int i;
3598 for (i = 0; i < wma->max_bssid; i++) {
3599 wma->interfaces[i].conn_state =
3600 !!(wma->interfaces[i].vdev_up &&
3601 !wma_is_vdev_in_ap_mode(wma, i));
3602 }
3603}
3604
3605/**
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003606 * wma_update_conn_state(): synchronize wma & hdd
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003607 * @wma: wma handle
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003608 * @conn_state: boolean array to populate
3609 * @len: validation parameter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003610 *
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003611 * populate interfaces conn_state with true if the interface
3612 * is a connected client and wow will configure a pattern.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003613 */
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003614void wma_update_conn_state(tp_wma_handle wma, uint32_t conn_mask)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003615{
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003616 int i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003617 for (i = 0; i < wma->max_bssid; i++) {
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003618 if (conn_mask & (1 << i))
3619 wma->interfaces[i].conn_state = true;
3620 else
3621 wma->interfaces[i].conn_state = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003622 }
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003623
3624 if (wma->wow.magic_ptrn_enable)
3625 return;
3626
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003627 for (i = 0; i < wma->max_bssid; i++) {
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003628 if (!wma->interfaces[i].ptrn_match_enable)
3629 wma->interfaces[i].conn_state = false;
3630 }
3631}
3632
3633/**
3634 * wma_is_beaconning_vdev_up(): check if a beaconning vdev is up
3635 * @wma: wma handle
3636 *
3637 * Return TRUE if beaconning vdev is up
3638 */
3639static inline
3640bool wma_is_beaconning_vdev_up(tp_wma_handle wma)
3641{
3642 int i;
3643 for (i = 0; i < wma->max_bssid; i++) {
3644 if (wma_is_vdev_in_beaconning_mode(wma, i)
3645 && wma->interfaces[i].vdev_up)
3646 return true;
3647 }
3648 return false;
3649}
3650
3651/**
3652 * wma_support_wow_for_beaconing: wow query for beaconning
3653 * @wma: wma handle
3654 *
3655 * Need to configure wow to enable beaconning offload when
3656 * a beaconing vdev is up and beaonning offload is configured.
3657 *
3658 * Return: true if we need to enable wow for beaconning offload
3659 */
3660static inline
3661bool wma_support_wow_for_beaconing(tp_wma_handle wma)
3662{
3663 if (WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
3664 WMI_SERVICE_BEACON_OFFLOAD)) {
3665 if (wma_is_beaconning_vdev_up(wma))
3666 return true;
3667 }
3668 return false;
3669}
3670
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003671#ifdef FEATURE_WLAN_SCAN_PNO
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003672/**
3673 * wma_is_pnoscan_in_progress(): check if a pnoscan is in progress
3674 * @wma: wma handle
3675 * @vdev_id: vdev_id
3676 *
3677 * Return: TRUE/FALSE
3678 */
3679static inline
3680bool wma_is_pnoscan_in_progress(tp_wma_handle wma, int vdev_id)
3681{
3682 return wma->interfaces[vdev_id].pno_in_progress;
3683}
Houston Hoffman345fa402015-12-16 11:28:51 -08003684
3685/**
3686 * wma_is_pnoscan_match_found(): check if a scan match was found
3687 * @wma: wma handle
3688 * @vdev_id: vdev_id
3689 *
3690 * Return: TRUE/FALSE
3691 */
3692static inline
3693bool wma_is_pnoscan_match_found(tp_wma_handle wma, int vdev_id)
3694{
3695 return wma->interfaces[vdev_id].nlo_match_evt_received;
3696}
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003697#else
3698/**
3699 * wma_is_pnoscan_in_progress(): dummy
3700 *
Houston Hoffman345fa402015-12-16 11:28:51 -08003701 * Return: False since no pnoscan cannot be in progress
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003702 * when feature flag is not defined.
3703 */
3704bool wma_is_pnoscan_in_progress(tp_wma_handle wma, int vdev_id)
3705{
3706 return FALSE;
3707}
Houston Hoffman345fa402015-12-16 11:28:51 -08003708
3709/**
3710 * wma_is_pnoscan_match_found(): dummy
3711 * @wma: wma handle
3712 * @vdev_id: vdev_id
3713 *
3714 * Return: False since no pnoscan cannot occur
3715 * when feature flag is not defined.
3716 */
3717static inline
3718bool wma_is_pnoscan_match_found(tp_wma_handle wma, int vdev_id)
3719{
3720 return FALSE;
3721}
Houston Hoffman61667962015-12-15 20:15:41 -08003722#endif
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003723
3724#ifdef FEATURE_WLAN_EXTSCAN
3725static inline
3726/**
3727 * wma_is_extscan_in_progress(): check if an extscan is in progress
3728 * @wma: wma handle
3729 * @vdev_id: vdev_id
3730 *
3731 * Return: TRUE/FALSvE
3732 */
3733bool wma_is_extscan_in_progress(tp_wma_handle wma, int vdev_id)
3734{
3735 return wma->interfaces[vdev_id].extscan_in_progress;
3736}
3737#else
3738/**
3739 * wma_is_extscan_in_progress(): dummy
3740 *
3741 * Return: False since no extscan can be in progress
3742 * when feature flag is not defined.
3743 */
3744bool wma_is_extscan_in_progress(tp_wma_handle wma, int vdev_id)
3745{
3746 return false;
3747}
3748#endif
3749
3750/**
3751 * wma_is_wow_applicable(): should enable wow
3752 * @wma: wma handle
3753 *
3754 * Enable WOW if any one of the condition meets,
3755 * 1) Is any one of vdev in beaconning mode (in AP mode) ?
3756 * 2) Is any one of vdev in connected state (in STA mode) ?
3757 * 3) Is PNO in progress in any one of vdev ?
3758 * 4) Is Extscan in progress in any one of vdev ?
Rajeev Kumaraea89632016-02-02 18:02:32 -08003759 * If none of above conditions is true then return false
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003760 *
Rajeev Kumaraea89632016-02-02 18:02:32 -08003761 * Return: true if wma needs to configure wow false otherwise.
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003762 */
3763bool wma_is_wow_applicable(tp_wma_handle wma)
3764{
3765 int vdev_id;
3766 if (wma_support_wow_for_beaconing(wma)) {
3767 WMA_LOGD("vdev is in beaconning mode, enabling wow");
3768 return true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003769 }
3770
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003771 for (vdev_id = 0; vdev_id < wma->max_bssid; vdev_id++) {
3772 if (wma->interfaces[vdev_id].conn_state) {
3773 WMA_LOGD("STA is connected, enabling wow");
3774 return true;
3775 } else if (wma_is_pnoscan_in_progress(wma, vdev_id)) {
3776 WMA_LOGD("PNO is in progress, enabling wow");
3777 return true;
3778 } else if (wma_is_extscan_in_progress(wma, vdev_id)) {
3779 WMA_LOGD("EXT is in progress, enabling wow");
3780 return true;
3781 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003782 }
3783
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003784 WMA_LOGD("All vdev are in disconnected state and pno/extscan is not in progress, skipping wow");
Rajeev Kumaraea89632016-02-02 18:02:32 -08003785 return false;
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003786}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003787
Houston Hoffman345fa402015-12-16 11:28:51 -08003788/**
3789 * wma_configure_dynamic_wake_events(): configure dyanmic wake events
3790 * @wma: wma handle
3791 *
3792 * Some wake events need to be enabled dynamically. Controll those here.
3793 *
3794 * Return: none
3795 */
3796void wma_configure_dynamic_wake_events(tp_wma_handle wma)
3797{
3798 int vdev_id;
3799 int enable_mask;
3800 int disable_mask;
3801
3802 for (vdev_id = 0; vdev_id < wma->max_bssid; vdev_id++) {
3803 enable_mask = 0;
3804 disable_mask = 0;
3805
3806 if (wma_is_pnoscan_in_progress(wma, vdev_id)) {
3807 if (wma_is_pnoscan_match_found(wma, vdev_id))
3808 enable_mask |=
3809 (1 << WOW_NLO_SCAN_COMPLETE_EVENT);
3810 else
3811 disable_mask |=
3812 (1 << WOW_NLO_SCAN_COMPLETE_EVENT);
3813 }
3814
3815 if (enable_mask != 0)
3816 wma_enable_disable_wakeup_event(wma, vdev_id,
3817 enable_mask, true);
3818 if (disable_mask != 0)
3819 wma_enable_disable_wakeup_event(wma, vdev_id,
3820 disable_mask, false);
3821 }
3822}
3823
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003824#ifdef FEATURE_WLAN_LPHB
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003825/**
3826 * wma_apply_lphb(): apply cached LPHB settings
3827 * @wma: wma handle
3828 *
3829 * LPHB cache, if any item was enabled, should be
3830 * applied.
3831 */
3832static inline
3833void wma_apply_lphb(tp_wma_handle wma)
3834{
3835 int i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003836 WMA_LOGD("%s: checking LPHB cache", __func__);
3837 for (i = 0; i < 2; i++) {
3838 if (wma->wow.lphb_cache[i].params.lphbEnableReq.enable) {
3839 WMA_LOGD("%s: LPHB cache for item %d is marked as enable",
3840 __func__, i + 1);
3841 wma_lphb_conf_hbenable(wma, &(wma->wow.lphb_cache[i]),
3842 false);
3843 }
3844 }
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003845}
3846#else
3847void wma_apply_lphb(tp_wma_handle wma) {}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003848#endif /* FEATURE_WLAN_LPHB */
3849
Houston Hoffmana76591b2015-11-10 16:52:05 -08003850static void wma_notify_suspend_req_procesed(tp_wma_handle wma,
Anurag Chouhan6d760662016-02-20 16:05:43 +05303851 enum qdf_suspend_type type)
Houston Hoffmana76591b2015-11-10 16:52:05 -08003852{
Anurag Chouhan6d760662016-02-20 16:05:43 +05303853 if (type == QDF_SYSTEM_SUSPEND)
Houston Hoffmana76591b2015-11-10 16:52:05 -08003854 wma_send_status_to_suspend_ind(wma, true);
Anurag Chouhan6d760662016-02-20 16:05:43 +05303855 else if (type == QDF_RUNTIME_SUSPEND)
Anurag Chouhance0dc992016-02-16 18:18:03 +05303856 qdf_event_set(&wma->runtime_suspend);
Houston Hoffmana76591b2015-11-10 16:52:05 -08003857}
3858
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003859/**
3860 * wma_suspend_req() - Handles suspend indication request received from umac.
3861 * @wma: wma handle
Houston Hoffmana76591b2015-11-10 16:52:05 -08003862 * @type: type of suspend
3863 *
3864 * The type controlls how we notify the indicator that the indication has
3865 * been processed
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003866 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303867 * Return: QDF status
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003868 */
Anurag Chouhan6d760662016-02-20 16:05:43 +05303869QDF_STATUS wma_suspend_req(tp_wma_handle wma, enum qdf_suspend_type type)
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003870{
Anurag Chouhan6d760662016-02-20 16:05:43 +05303871 if (type == QDF_RUNTIME_SUSPEND)
Houston Hoffman1460fa32015-11-18 02:36:30 -08003872 wmi_set_runtime_pm_inprogress(wma->wmi_handle, true);
3873
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003874 if (wma_is_wow_applicable(wma)) {
3875 WMA_LOGE("WOW Suspend");
3876 wma_apply_lphb(wma);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003877
Houston Hoffman345fa402015-12-16 11:28:51 -08003878 wma_configure_dynamic_wake_events(wma);
3879
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003880 wma->wow.wow_enable = true;
3881 wma->wow.wow_enable_cmd_sent = false;
3882 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003883
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003884 /* Set the Suspend DTIM Parameters */
3885 wma_set_suspend_dtim(wma);
Houston Hoffmana76591b2015-11-10 16:52:05 -08003886
3887 wma_notify_suspend_req_procesed(wma, type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003888
3889 /* to handle race between hif_pci_suspend and
3890 * unpause/pause tx handler
3891 */
3892 wma_set_wow_bus_suspend(wma, 1);
3893
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303894 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003895}
3896
3897/**
3898 * wma_send_host_wakeup_ind_to_fw() - send wakeup ind to fw
3899 * @wma: wma handle
3900 *
3901 * Sends host wakeup indication to FW. On receiving this indication,
3902 * FW will come out of WOW.
3903 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303904 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003905 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303906static QDF_STATUS wma_send_host_wakeup_ind_to_fw(tp_wma_handle wma)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003907{
Anurag Chouhance0dc992016-02-16 18:18:03 +05303908 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003909 int ret;
3910#ifdef CONFIG_CNSS
Anurag Chouhan6d760662016-02-20 16:05:43 +05303911 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003912 if (NULL == pMac) {
3913 WMA_LOGE("%s: Unable to get PE context", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303914 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003915 }
3916#endif /* CONFIG_CNSS */
3917
Anurag Chouhance0dc992016-02-16 18:18:03 +05303918 qdf_event_reset(&wma->wma_resume_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003919
Govind Singhaa64c242016-03-08 11:31:49 +05303920 ret = wmi_unified_host_wakeup_ind_to_fw_cmd(wma->wmi_handle);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003921 if (ret) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303922 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003923 }
3924
3925 WMA_LOGD("Host wakeup indication sent to fw");
3926
Anurag Chouhance0dc992016-02-16 18:18:03 +05303927 qdf_status = qdf_wait_single_event(&(wma->wma_resume_event),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003928 WMA_RESUME_TIMEOUT);
Anurag Chouhance0dc992016-02-16 18:18:03 +05303929 if (QDF_STATUS_SUCCESS != qdf_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003930 WMA_LOGP("%s: Timeout waiting for resume event from FW",
3931 __func__);
3932 WMA_LOGP("%s: Pending commands %d credits %d", __func__,
3933 wmi_get_pending_cmds(wma->wmi_handle),
3934 wmi_get_host_credits(wma->wmi_handle));
Prashanth Bhatta9e143052015-12-04 11:56:47 -08003935 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003936#ifdef CONFIG_CNSS
3937 if (pMac->sme.enableSelfRecovery) {
3938 cds_trigger_recovery();
3939 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303940 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003941 }
3942#else
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303943 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003944#endif /* CONFIG_CNSS */
3945 } else {
3946 WMA_LOGE("%s: SSR in progress, ignore resume timeout",
3947 __func__);
3948 }
3949 } else {
3950 WMA_LOGD("Host wakeup received");
3951 }
3952
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303953 if (QDF_STATUS_SUCCESS == qdf_status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003954 wmi_set_target_suspend(wma->wmi_handle, false);
3955
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303956 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003957}
3958
3959/**
3960 * wma_disable_wow_in_fw() - Disable wow in PCIe resume context.
3961 * @handle: wma handle
3962 *
3963 * Return: 0 for success or error code
3964 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303965QDF_STATUS wma_disable_wow_in_fw(WMA_HANDLE handle)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003966{
3967 tp_wma_handle wma = handle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303968 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003969
3970 if (!wma->wow.wow_enable || !wma->wow.wow_enable_cmd_sent)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303971 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003972
3973 ret = wma_send_host_wakeup_ind_to_fw(wma);
3974
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303975 if (ret != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003976 return ret;
3977
3978 wma->wow.wow_enable = false;
3979 wma->wow.wow_enable_cmd_sent = false;
3980
3981 /* To allow the tx pause/unpause events */
3982 wma_set_wow_bus_suspend(wma, 0);
3983 /* Unpause the vdev as we are resuming */
3984 wma_unpause_vdev(wma);
3985
3986 return ret;
3987}
3988
3989#ifdef WLAN_FEATURE_LPSS
3990/**
3991 * wma_is_lpass_enabled() - check if lpass is enabled
3992 * @handle: Pointer to wma handle
3993 *
3994 * WoW is needed if LPASS or NaN feature is enabled in INI because
3995 * target can't wake up itself if its put in PDEV suspend when LPASS
3996 * or NaN features are supported
3997 *
3998 * Return: true if lpass is enabled else false
3999 */
4000bool static wma_is_lpass_enabled(tp_wma_handle wma)
4001{
4002 if (wma->is_lpass_enabled)
4003 return true;
4004 else
4005 return false;
4006}
4007#else
4008bool static wma_is_lpass_enabled(tp_wma_handle wma)
4009{
4010 return false;
4011}
4012#endif
4013
4014#ifdef WLAN_FEATURE_NAN
4015/**
4016 * wma_is_nan_enabled() - check if NaN is enabled
4017 * @handle: Pointer to wma handle
4018 *
4019 * WoW is needed if LPASS or NaN feature is enabled in INI because
4020 * target can't wake up itself if its put in PDEV suspend when LPASS
4021 * or NaN features are supported
4022 *
4023 * Return: true if NaN is enabled else false
4024 */
4025bool static wma_is_nan_enabled(tp_wma_handle wma)
4026{
4027 if (wma->is_nan_enabled)
4028 return true;
4029 else
4030 return false;
4031}
4032#else
4033bool static wma_is_nan_enabled(tp_wma_handle wma)
4034{
4035 return false;
4036}
4037#endif
4038
4039/**
4040 * wma_is_wow_mode_selected() - check if wow needs to be enabled in fw
4041 * @handle: Pointer to wma handle
4042 *
4043 * If lpass is enabled then always do wow else check wow_enable config
4044 *
4045 * Return: true is wow mode is needed else false
4046 */
Houston Hoffmana76591b2015-11-10 16:52:05 -08004047bool wma_is_wow_mode_selected(WMA_HANDLE handle)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004048{
4049 tp_wma_handle wma = (tp_wma_handle) handle;
4050
4051 if (wma_is_lpass_enabled(wma)) {
4052 WMA_LOGD("LPASS is enabled select WoW");
4053 return true;
4054 } else if (wma_is_nan_enabled(wma)) {
4055 WMA_LOGD("NAN is enabled select WoW");
4056 return true;
4057 } else {
4058 WMA_LOGD("WoW enable %d", wma->wow.wow_enable);
4059 return wma->wow.wow_enable;
4060 }
4061}
4062
4063/**
4064 * wma_del_ts_req() - send DELTS request to fw
4065 * @wma: wma handle
4066 * @msg: delts params
4067 *
4068 * Return: none
4069 */
4070void wma_del_ts_req(tp_wma_handle wma, tDelTsParams *msg)
4071{
Govind Singhaa64c242016-03-08 11:31:49 +05304072 if (wmi_unified_del_ts_cmd(wma->wmi_handle,
4073 msg->sessionId,
4074 TID_TO_WME_AC(msg->userPrio))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004075 WMA_LOGP("%s: Failed to send vdev DELTS command", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004076 }
Govind Singhaa64c242016-03-08 11:31:49 +05304077
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004078#ifdef WLAN_FEATURE_ROAM_OFFLOAD
4079 if (msg->setRICparams == true)
4080 wma_set_ric_req(wma, msg, false);
4081#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
4082
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304083 qdf_mem_free(msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004084}
4085
4086/**
4087 * wma_aggr_qos_req() - send aggr qos request to fw
4088 * @wma: handle to wma
4089 * @pAggrQosRspMsg - combined struct for all ADD_TS requests.
4090 *
4091 * A function to handle WMA_AGGR_QOS_REQ. This will send out
4092 * ADD_TS requestes to firmware in loop for all the ACs with
4093 * active flow.
4094 *
4095 * Return: none
4096 */
4097void wma_aggr_qos_req(tp_wma_handle wma,
4098 tAggrAddTsParams *pAggrQosRspMsg)
4099{
Govind Singhaa64c242016-03-08 11:31:49 +05304100 wmi_unified_aggr_qos_cmd(wma->wmi_handle,
4101 (struct aggr_add_ts_param *)pAggrQosRspMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004102 /* send reponse to upper layers from here only. */
4103 wma_send_msg(wma, WMA_AGGR_QOS_RSP, pAggrQosRspMsg, 0);
4104}
4105
4106/**
4107 * wma_add_ts_req() - send ADDTS request to fw
4108 * @wma: wma handle
4109 * @msg: ADDTS params
4110 *
4111 * Return: none
4112 */
4113void wma_add_ts_req(tp_wma_handle wma, tAddTsParams *msg)
4114{
Govind Singhaa64c242016-03-08 11:31:49 +05304115 struct add_ts_param cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004116
4117#ifdef FEATURE_WLAN_ESE
4118 /*
4119 * msmt_interval is in unit called TU (1 TU = 1024 us)
4120 * max value of msmt_interval cannot make resulting
4121 * interval_miliseconds overflow 32 bit
4122 */
4123 uint32_t intervalMiliseconds;
Anurag Chouhan6d760662016-02-20 16:05:43 +05304124 ol_txrx_pdev_handle pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004125 if (NULL == pdev) {
4126 WMA_LOGE("%s: Failed to get pdev", __func__);
4127 goto err;
4128 }
4129
4130 intervalMiliseconds = (msg->tsm_interval * 1024) / 1000;
4131
4132 ol_tx_set_compute_interval(pdev, intervalMiliseconds);
4133#endif /* FEATURE_WLAN_ESE */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304134 msg->status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004135
Govind Singhaa64c242016-03-08 11:31:49 +05304136
4137 cmd.sme_session_id = msg->sme_session_id;
4138 cmd.tspec.tsinfo.traffic.userPrio =
4139 TID_TO_WME_AC(msg->tspec.tsinfo.traffic.userPrio);
4140 cmd.tspec.mediumTime = msg->tspec.mediumTime;
4141 if (wmi_unified_add_ts_cmd(wma->wmi_handle, &cmd))
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304142 msg->status = QDF_STATUS_E_FAILURE;
Govind Singhaa64c242016-03-08 11:31:49 +05304143
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004144#ifdef WLAN_FEATURE_ROAM_OFFLOAD
4145 if (msg->setRICparams == true)
4146 wma_set_ric_req(wma, msg, true);
4147#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
4148
4149err:
4150 wma_send_msg(wma, WMA_ADD_TS_RSP, msg, 0);
4151}
4152
4153/**
4154 * wma_enable_disable_packet_filter() - enable/disable packet filter in target
4155 * @wma: Pointer to wma handle
4156 * @vdev_id: vdev id
4157 * @enable: Flag to enable/disable packet filter
4158 *
4159 * Return: 0 for success or error code
4160 */
4161static int wma_enable_disable_packet_filter(tp_wma_handle wma,
4162 uint8_t vdev_id, bool enable)
4163{
Govind Singhaa64c242016-03-08 11:31:49 +05304164 int ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004165
Govind Singhaa64c242016-03-08 11:31:49 +05304166 ret = wmi_unified_enable_disable_packet_filter_cmd(wma->wmi_handle,
4167 vdev_id, enable);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004168 if (ret)
4169 WMA_LOGE("Failed to send packet filter wmi cmd to fw");
4170
4171 return ret;
4172}
4173
4174/**
4175 * wma_config_packet_filter() - configure packet filter in target
4176 * @wma: Pointer to wma handle
4177 * @vdev_id: vdev id
4178 * @rcv_filter_param: Packet filter parameters
4179 * @filter_id: Filter id
4180 * @enable: Flag to add/delete packet filter configuration
4181 *
4182 * Return: 0 for success or error code
4183 */
4184static int wma_config_packet_filter(tp_wma_handle wma,
4185 uint8_t vdev_id, tSirRcvPktFilterCfgType *rcv_filter_param,
4186 uint8_t filter_id, bool enable)
4187{
Govind Singhaa64c242016-03-08 11:31:49 +05304188 int err;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004189
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004190 /* send the command along with data */
Govind Singhaa64c242016-03-08 11:31:49 +05304191 err = wmi_unified_config_packet_filter_cmd(wma->wmi_handle,
4192 vdev_id, (struct rcv_pkt_filter_config *)rcv_filter_param,
4193 filter_id, enable);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004194 if (err) {
4195 WMA_LOGE("Failed to send pkt_filter cmd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004196 return -EIO;
4197 }
4198
4199 /* Enable packet filter */
4200 if (enable)
4201 wma_enable_disable_packet_filter(wma, vdev_id, true);
4202
4203 return 0;
4204}
4205
4206/**
4207 * wma_process_receive_filter_set_filter_req() - enable packet filter
4208 * @wma_handle: wma handle
4209 * @rcv_filter_param: filter params
4210 *
4211 * Return: 0 for success or error code
4212 */
4213int wma_process_receive_filter_set_filter_req(tp_wma_handle wma,
4214 tSirRcvPktFilterCfgType *rcv_filter_param)
4215{
4216 int ret = 0;
4217 uint8_t vdev_id;
4218
4219 /* Get the vdev id */
Srinivas Girigowda98530492015-11-20 17:39:24 -08004220 if (!wma_find_vdev_by_bssid(wma,
4221 rcv_filter_param->bssid.bytes, &vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004222 WMA_LOGE("vdev handle is invalid for %pM",
Srinivas Girigowda98530492015-11-20 17:39:24 -08004223 rcv_filter_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004224 return -EINVAL;
4225 }
4226
4227 ret = wma_config_packet_filter(wma, vdev_id, rcv_filter_param,
4228 rcv_filter_param->filterId, true);
4229
4230 return ret;
4231}
4232
4233/**
4234 * wma_process_receive_filter_clear_filter_req() - disable packet filter
4235 * @wma_handle: wma handle
4236 * @rcv_clear_param: filter params
4237 *
4238 * Return: 0 for success or error code
4239 */
4240int wma_process_receive_filter_clear_filter_req(tp_wma_handle wma,
4241 tSirRcvFltPktClearParam *rcv_clear_param)
4242{
4243 int ret = 0;
4244 uint8_t vdev_id;
4245
4246 /* Get the vdev id */
Srinivas Girigowda98530492015-11-20 17:39:24 -08004247 if (!wma_find_vdev_by_bssid(wma,
4248 rcv_clear_param->bssid.bytes, &vdev_id)) {
4249 WMA_LOGE("vdev handle is invalid for %pM",
4250 rcv_clear_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004251 return -EINVAL;
4252 }
4253
4254 ret = wma_config_packet_filter(wma, vdev_id, NULL,
4255 rcv_clear_param->filterId, false);
4256
4257 return ret;
4258}
4259
4260#ifdef FEATURE_WLAN_ESE
4261
4262#define TSM_DELAY_HISTROGRAM_BINS 4
4263/**
4264 * wma_process_tsm_stats_req() - process tsm stats request
4265 * @wma_handler - handle to wma
4266 * @pTsmStatsMsg - TSM stats struct that needs to be populated and
4267 * passed in message.
4268 *
4269 * A parallel function to WMA_ProcessTsmStatsReq for pronto. This
4270 * function fetches stats from data path APIs and post
4271 * WMA_TSM_STATS_RSP msg back to LIM.
4272 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304273 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004274 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304275QDF_STATUS wma_process_tsm_stats_req(tp_wma_handle wma_handler,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004276 void *pTsmStatsMsg)
4277{
4278 uint8_t counter;
4279 uint32_t queue_delay_microsec = 0;
4280 uint32_t tx_delay_microsec = 0;
4281 uint16_t packet_count = 0;
4282 uint16_t packet_loss_count = 0;
4283 tpAniTrafStrmMetrics pTsmMetric = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004284 tpAniGetTsmStatsReq pStats = (tpAniGetTsmStatsReq) pTsmStatsMsg;
4285 tpAniGetTsmStatsRsp pTsmRspParams = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004286 int tid = pStats->tid;
4287 /*
4288 * The number of histrogram bin report by data path api are different
4289 * than required by TSM, hence different (6) size array used
4290 */
4291 uint16_t bin_values[QCA_TX_DELAY_HIST_REPORT_BINS] = { 0, };
4292
Anurag Chouhan6d760662016-02-20 16:05:43 +05304293 ol_txrx_pdev_handle pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004294
4295 if (NULL == pdev) {
4296 WMA_LOGE("%s: Failed to get pdev", __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304297 qdf_mem_free(pTsmStatsMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304298 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004299 }
4300
4301 /* get required values from data path APIs */
4302 ol_tx_delay(pdev, &queue_delay_microsec, &tx_delay_microsec, tid);
4303 ol_tx_delay_hist(pdev, bin_values, tid);
4304 ol_tx_packet_count(pdev, &packet_count, &packet_loss_count, tid);
4305
Srinivas Girigowda515a9ef2015-12-11 11:00:48 -08004306 pTsmRspParams = qdf_mem_malloc(sizeof(*pTsmRspParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004307 if (NULL == pTsmRspParams) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304308 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304309 "%s: QDF MEM Alloc Failure", __func__);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304310 QDF_ASSERT(0);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304311 qdf_mem_free(pTsmStatsMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304312 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004313 }
4314 pTsmRspParams->staId = pStats->staId;
4315 pTsmRspParams->rc = eSIR_FAILURE;
4316 pTsmRspParams->tsmStatsReq = pStats;
4317 pTsmMetric = &pTsmRspParams->tsmMetrics;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004318 /* populate pTsmMetric */
4319 pTsmMetric->UplinkPktQueueDly = queue_delay_microsec;
4320 /* store only required number of bin values */
4321 for (counter = 0; counter < TSM_DELAY_HISTROGRAM_BINS; counter++) {
4322 pTsmMetric->UplinkPktQueueDlyHist[counter] =
4323 bin_values[counter];
4324 }
4325 pTsmMetric->UplinkPktTxDly = tx_delay_microsec;
4326 pTsmMetric->UplinkPktLoss = packet_loss_count;
4327 pTsmMetric->UplinkPktCount = packet_count;
4328
4329 /*
4330 * No need to populate roaming delay and roaming count as they are
4331 * being populated just before sending IAPP frame out
4332 */
4333 /* post this message to LIM/PE */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004334 wma_send_msg(wma_handler, WMA_TSM_STATS_RSP, (void *)pTsmRspParams, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304335 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004336}
4337
4338#endif /* FEATURE_WLAN_ESE */
4339
4340/**
4341 * wma_add_clear_mcbc_filter() - set mcast filter command to fw
4342 * @wma_handle: wma handle
4343 * @vdev_id: vdev id
4344 * @multicastAddr: mcast address
4345 * @clearList: clear list flag
4346 *
4347 * Return: 0 for success or error code
4348 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05304349static QDF_STATUS wma_add_clear_mcbc_filter(tp_wma_handle wma_handle,
4350 uint8_t vdev_id,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304351 struct qdf_mac_addr multicast_addr,
Srinivas Girigowda98530492015-11-20 17:39:24 -08004352 bool clearList)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004353{
Himanshu Agarwal44195412016-03-09 13:03:54 +05304354 return wmi_unified_add_clear_mcbc_filter_cmd(wma_handle->wmi_handle,
4355 vdev_id, multicast_addr, clearList);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004356}
4357
4358/**
Rajeev Kumaref96e152016-04-15 18:10:33 -07004359 * wma_config_enhance_multicast_offload() - config enhance multicast offload
4360 * @wma_handle: wma handle
4361 * @vdev_id: vdev id
4362 * @action: enable or disable enhance multicast offload
4363 *
4364 * Return: none
4365 */
4366static void wma_config_enhance_multicast_offload(tp_wma_handle wma_handle,
4367 uint8_t vdev_id,
4368 uint8_t action)
4369{
4370 int status;
4371 wmi_buf_t buf;
4372 wmi_config_enhanced_mcast_filter_cmd_fixed_param *cmd;
4373
4374 buf = wmi_buf_alloc(wma_handle->wmi_handle, sizeof(*cmd));
4375 if (!buf) {
4376 WMA_LOGE("Failed to allocate buffer to send set key cmd");
4377 return;
4378 }
4379
4380 cmd = (wmi_config_enhanced_mcast_filter_cmd_fixed_param *)
4381 wmi_buf_data(buf);
4382
4383 WMITLV_SET_HDR(&cmd->tlv_header,
4384 WMITLV_TAG_STRUC_wmi_config_enhanced_mcast_filter_fixed_param,
4385 WMITLV_GET_STRUCT_TLVLEN(wmi_config_enhanced_mcast_filter_cmd_fixed_param));
4386
4387 cmd->vdev_id = vdev_id;
4388 cmd->enable = ((0 == action) ? ENHANCED_MCAST_FILTER_DISABLED :
4389 ENHANCED_MCAST_FILTER_ENABLED);
4390
4391 WMA_LOGD("%s: config enhance multicast offload action %d for vdev %d",
4392 __func__, action, vdev_id);
4393
4394 status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf,
4395 sizeof(*cmd), WMI_CONFIG_ENHANCED_MCAST_FILTER_CMDID);
4396 if (status) {
4397 qdf_nbuf_free(buf);
4398 WMA_LOGE("%s:Failed to send WMI_CONFIG_ENHANCED_MCAST_FILTER_CMDID",
4399 __func__);
4400 }
4401
4402 return;
4403}
4404
4405/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004406 * wma_process_mcbc_set_filter_req() - process mcbc set filter request
4407 * @wma_handle: wma handle
4408 * @mcbc_param: mcbc params
4409 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304410 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004411 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304412QDF_STATUS wma_process_mcbc_set_filter_req(tp_wma_handle wma_handle,
Anurag Chouhance0dc992016-02-16 18:18:03 +05304413 tSirRcvFltMcAddrList *mcbc_param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004414{
4415 uint8_t vdev_id = 0;
4416 int i;
4417
4418 if (mcbc_param->ulMulticastAddrCnt <= 0) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004419 WMA_LOGW("Number of multicast addresses is 0");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304420 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004421 }
4422
Srinivas Girigowda98530492015-11-20 17:39:24 -08004423 if (!wma_find_vdev_by_addr(wma_handle,
4424 mcbc_param->self_macaddr.bytes, &vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004425 WMA_LOGE("%s: Failed to find vdev id for %pM", __func__,
Srinivas Girigowda98530492015-11-20 17:39:24 -08004426 mcbc_param->bssid.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304427 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004428 }
Rajeev Kumaref96e152016-04-15 18:10:33 -07004429
4430 /*
4431 * Configure enhance multicast offload feature for filtering out
4432 * multicast IP data packets transmitted using unicast MAC address
4433 */
4434 if (WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap,
4435 WMI_SERVICE_ENHANCED_MCAST_FILTER)) {
4436 WMA_LOGD("%s: FW supports enhance multicast offload", __func__);
4437 wma_config_enhance_multicast_offload(wma_handle, vdev_id,
4438 mcbc_param->action);
4439 } else {
4440 WMA_LOGD("%s: FW does not support enhance multicast offload",
4441 __func__);
4442 }
4443
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004444 /* set mcbc_param->action to clear MCList and reset
4445 * to configure the MCList in FW
4446 */
4447
4448 for (i = 0; i < mcbc_param->ulMulticastAddrCnt; i++) {
4449 wma_add_clear_mcbc_filter(wma_handle, vdev_id,
4450 mcbc_param->multicastAddr[i],
4451 (mcbc_param->action == 0));
4452 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304453 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004454}
4455
4456#ifdef WLAN_FEATURE_GTK_OFFLOAD
4457#define GTK_OFFLOAD_ENABLE 0
4458#define GTK_OFFLOAD_DISABLE 1
4459
4460/**
4461 * wma_gtk_offload_status_event() - GTK offload status event handler
4462 * @handle: wma handle
4463 * @event: event buffer
4464 * @len: buffer length
4465 *
4466 * Return: 0 for success or error code
4467 */
4468int wma_gtk_offload_status_event(void *handle, uint8_t *event,
4469 uint32_t len)
4470{
4471 tp_wma_handle wma = (tp_wma_handle) handle;
4472 WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param *status;
4473 WMI_GTK_OFFLOAD_STATUS_EVENTID_param_tlvs *param_buf;
4474 tpSirGtkOffloadGetInfoRspParams resp;
4475 cds_msg_t cds_msg;
4476 uint8_t *bssid;
4477
4478 WMA_LOGD("%s Enter", __func__);
4479
4480 param_buf = (WMI_GTK_OFFLOAD_STATUS_EVENTID_param_tlvs *) event;
4481 if (!param_buf) {
4482 WMA_LOGE("param_buf is NULL");
4483 return -EINVAL;
4484 }
4485
4486 status = (WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param *) param_buf->fixed_param;
4487
4488 if (len < sizeof(WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param)) {
4489 WMA_LOGE("Invalid length for GTK status");
4490 return -EINVAL;
4491 }
4492 bssid = wma_find_bssid_by_vdev_id(wma, status->vdev_id);
4493 if (!bssid) {
4494 WMA_LOGE("invalid bssid for vdev id %d", status->vdev_id);
4495 return -ENOENT;
4496 }
4497
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304498 resp = qdf_mem_malloc(sizeof(*resp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004499 if (!resp) {
4500 WMA_LOGE("%s: Failed to alloc response", __func__);
4501 return -ENOMEM;
4502 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304503 qdf_mem_zero(resp, sizeof(*resp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004504 resp->mesgType = eWNI_PMC_GTK_OFFLOAD_GETINFO_RSP;
4505 resp->mesgLen = sizeof(*resp);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304506 resp->ulStatus = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004507 resp->ulTotalRekeyCount = status->refresh_cnt;
4508 /* TODO: Is the total rekey count and GTK rekey count same? */
4509 resp->ulGTKRekeyCount = status->refresh_cnt;
4510
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304511 qdf_mem_copy(&resp->ullKeyReplayCounter, &status->replay_counter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004512 GTK_REPLAY_COUNTER_BYTES);
4513
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304514 qdf_mem_copy(resp->bssid.bytes, bssid, IEEE80211_ADDR_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004515
4516#ifdef IGTK_OFFLOAD
4517 /* TODO: Is the refresh count same for GTK and IGTK? */
4518 resp->ulIGTKRekeyCount = status->refresh_cnt;
4519#endif /* IGTK_OFFLOAD */
4520
4521 cds_msg.type = eWNI_PMC_GTK_OFFLOAD_GETINFO_RSP;
4522 cds_msg.bodyptr = (void *)resp;
4523 cds_msg.bodyval = 0;
4524
4525 if (cds_mq_post_message(CDS_MQ_ID_SME, (cds_msg_t *) &cds_msg)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304526 != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004527 WMA_LOGE("Failed to post GTK response to SME");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304528 qdf_mem_free(resp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004529 return -EINVAL;
4530 }
4531
4532 WMA_LOGD("GTK: got target status with replay counter "
4533 "%02x%02x%02x%02x%02x%02x%02x%02x. vdev %d "
4534 "Refresh GTK %d times exchanges since last set operation",
4535 status->replay_counter[0],
4536 status->replay_counter[1],
4537 status->replay_counter[2],
4538 status->replay_counter[3],
4539 status->replay_counter[4],
4540 status->replay_counter[5],
4541 status->replay_counter[6],
4542 status->replay_counter[7],
4543 status->vdev_id, status->refresh_cnt);
4544
4545 WMA_LOGD("%s Exit", __func__);
4546
4547 return 0;
4548}
4549
4550/**
4551 * wma_send_gtk_offload_req() - send GTK offload command to fw
4552 * @wma: wma handle
4553 * @vdev_id: vdev id
4554 * @params: GTK offload parameters
4555 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304556 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004557 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304558static QDF_STATUS wma_send_gtk_offload_req(tp_wma_handle wma, uint8_t vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004559 tpSirGtkOffloadParams params)
4560{
Himanshu Agarwal44195412016-03-09 13:03:54 +05304561 struct gtk_offload_params offload_params = {0};
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304562 QDF_STATUS status = QDF_STATUS_SUCCESS;
Himanshu Agarwal44195412016-03-09 13:03:54 +05304563 bool enable_offload;
4564 uint32_t gtk_offload_opcode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004565
4566 WMA_LOGD("%s Enter", __func__);
4567
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004568 /* Request target to enable GTK offload */
4569 if (params->ulFlags == GTK_OFFLOAD_ENABLE) {
Himanshu Agarwal44195412016-03-09 13:03:54 +05304570 gtk_offload_opcode = GTK_OFFLOAD_ENABLE_OPCODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004571 wma->wow.gtk_err_enable[vdev_id] = true;
4572
4573 /* Copy the keys and replay counter */
Himanshu Agarwal44195412016-03-09 13:03:54 +05304574 qdf_mem_copy(offload_params.aKCK, params->aKCK,
4575 GTK_OFFLOAD_KCK_BYTES);
4576 qdf_mem_copy(offload_params.aKEK, params->aKEK,
4577 GTK_OFFLOAD_KEK_BYTES);
4578 qdf_mem_copy(&offload_params.ullKeyReplayCounter,
4579 &params->ullKeyReplayCounter, GTK_REPLAY_COUNTER_BYTES);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004580 } else {
4581 wma->wow.gtk_err_enable[vdev_id] = false;
Himanshu Agarwal44195412016-03-09 13:03:54 +05304582 gtk_offload_opcode = GTK_OFFLOAD_DISABLE_OPCODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004583 }
4584
Himanshu Agarwal44195412016-03-09 13:03:54 +05304585 enable_offload = params->ulFlags;
4586
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004587 /* send the wmi command */
Himanshu Agarwal44195412016-03-09 13:03:54 +05304588 status = wmi_unified_send_gtk_offload_cmd(wma->wmi_handle,
4589 vdev_id, &offload_params,
4590 enable_offload,
4591 gtk_offload_opcode);
4592 if (QDF_IS_STATUS_ERROR(status))
4593 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004594
Himanshu Agarwal44195412016-03-09 13:03:54 +05304595 WMA_LOGD("VDEVID: %d, GTK_FLAGS: x%x", vdev_id, gtk_offload_opcode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004596out:
4597 WMA_LOGD("%s Exit", __func__);
4598 return status;
4599}
4600
4601/**
4602 * wma_process_gtk_offload_req() - process GTK offload req from umac
4603 * @handle: wma handle
4604 * @params: GTK offload params
4605 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304606 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004607 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304608QDF_STATUS wma_process_gtk_offload_req(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004609 tpSirGtkOffloadParams params)
4610{
4611 uint8_t vdev_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304612 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004613
4614 WMA_LOGD("%s Enter", __func__);
4615
4616 /* Get the vdev id */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -08004617 if (!wma_find_vdev_by_bssid(wma, params->bssid.bytes, &vdev_id)) {
4618 WMA_LOGE("vdev handle is invalid for %pM", params->bssid.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304619 status = QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004620 goto out;
4621 }
4622
4623 /* Validate vdev id */
4624 if (vdev_id >= wma->max_bssid) {
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -08004625 WMA_LOGE("invalid vdev_id %d for %pM", vdev_id,
4626 params->bssid.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304627 status = QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004628 goto out;
4629 }
4630
4631 if ((params->ulFlags == GTK_OFFLOAD_ENABLE) &&
4632 (wma->wow.gtk_err_enable[vdev_id] == true)) {
4633 WMA_LOGE("%s GTK Offload already enabled. Disable it first "
4634 "vdev_id %d", __func__, vdev_id);
4635 params->ulFlags = GTK_OFFLOAD_DISABLE;
4636 status = wma_send_gtk_offload_req(wma, vdev_id, params);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304637 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004638 WMA_LOGE("%s Failed to disable GTK Offload", __func__);
4639 goto out;
4640 }
4641 WMA_LOGD("%s Enable GTK Offload again with updated inputs",
4642 __func__);
4643 params->ulFlags = GTK_OFFLOAD_ENABLE;
4644 }
4645 status = wma_send_gtk_offload_req(wma, vdev_id, params);
4646out:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304647 qdf_mem_free(params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004648 WMA_LOGD("%s Exit", __func__);
4649 return status;
4650}
4651
4652/**
4653 * wma_process_gtk_offload_getinfo_req() - send GTK offload cmd to fw
4654 * @wma: wma handle
4655 * @params: GTK offload params
4656 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304657 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004658 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304659QDF_STATUS wma_process_gtk_offload_getinfo_req(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004660 tpSirGtkOffloadGetInfoRspParams params)
4661{
4662 uint8_t vdev_id;
Himanshu Agarwal44195412016-03-09 13:03:54 +05304663 uint64_t offload_req_opcode;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304664 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004665
4666 WMA_LOGD("%s Enter", __func__);
4667
4668 /* Get the vdev id */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -08004669 if (!wma_find_vdev_by_bssid(wma, params->bssid.bytes, &vdev_id)) {
4670 WMA_LOGE("vdev handle is invalid for %pM", params->bssid.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304671 status = QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004672 goto out;
4673 }
4674
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004675 /* Request for GTK offload status */
Himanshu Agarwal44195412016-03-09 13:03:54 +05304676 offload_req_opcode = GTK_OFFLOAD_REQUEST_STATUS_OPCODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004677
4678 /* send the wmi command */
Himanshu Agarwal44195412016-03-09 13:03:54 +05304679 status = wmi_unified_process_gtk_offload_getinfo_cmd(wma->wmi_handle,
4680 vdev_id, offload_req_opcode);
4681
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004682out:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304683 qdf_mem_free(params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004684 WMA_LOGD("%s Exit", __func__);
4685 return status;
4686}
4687#endif /* WLAN_FEATURE_GTK_OFFLOAD */
4688
4689/**
4690 * wma_enable_arp_ns_offload() - enable ARP NS offload
4691 * @wma: wma handle
4692 * @tpSirHostOffloadReq: offload request
Govind Singhaa64c242016-03-08 11:31:49 +05304693 * @arp_only: flag
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004694 *
4695 * To configure ARP NS off load data to firmware
4696 * when target goes to wow mode.
4697 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304698 * Return: QDF Status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004699 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304700QDF_STATUS wma_enable_arp_ns_offload(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004701 tpSirHostOffloadReq
Govind Singhaa64c242016-03-08 11:31:49 +05304702 pHostOffloadParams, bool arp_only)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004703{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004704 int32_t res;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004705 uint8_t vdev_id;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004706
4707 /* Get the vdev id */
Srinivas Girigowdab084b552015-11-24 12:39:12 -08004708 if (!wma_find_vdev_by_bssid(wma, pHostOffloadParams->bssid.bytes,
4709 &vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004710 WMA_LOGE("vdev handle is invalid for %pM",
Srinivas Girigowdab084b552015-11-24 12:39:12 -08004711 pHostOffloadParams->bssid.bytes);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304712 qdf_mem_free(pHostOffloadParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304713 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004714 }
4715
4716 if (!wma->interfaces[vdev_id].vdev_up) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004717 WMA_LOGE("vdev %d is not up skipping arp/ns offload", vdev_id);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304718 qdf_mem_free(pHostOffloadParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304719 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004720 }
4721
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004722
Govind Singhaa64c242016-03-08 11:31:49 +05304723 res = wmi_unified_enable_arp_ns_offload_cmd(wma->wmi_handle,
4724 (struct host_offload_req_param *)pHostOffloadParams,
4725 arp_only,
4726 vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004727 if (res) {
4728 WMA_LOGE("Failed to enable ARP NDP/NSffload");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304729 qdf_mem_free(pHostOffloadParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304730 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004731 }
4732
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304733 qdf_mem_free(pHostOffloadParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304734 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004735}
4736
4737/**
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08004738 * wma_process_cesium_enable_ind() - enables cesium functionality in target
4739 * @wma: wma handle
4740 *
4741 * Return: QDF status
4742 */
4743QDF_STATUS wma_process_cesium_enable_ind(tp_wma_handle wma)
4744{
4745 QDF_STATUS ret;
4746 int32_t vdev_id;
4747
4748 vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
4749 if (vdev_id < 0) {
4750 WMA_LOGE("%s: IBSS vdev does not exist could not enable cesium",
4751 __func__);
4752 return QDF_STATUS_E_FAILURE;
4753 }
4754
4755 /* Send enable cesium command to target */
4756 WMA_LOGE("Enable cesium in target for vdevId %d ", vdev_id);
4757 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
4758 WMI_VDEV_PARAM_ENABLE_RMC, 1);
4759 if (ret) {
4760 WMA_LOGE("Enable cesium failed for vdevId %d", vdev_id);
4761 return QDF_STATUS_E_FAILURE;
4762 }
4763 return QDF_STATUS_SUCCESS;
4764}
4765
4766/**
4767 * wma_process_get_peer_info_req() - sends get peer info cmd to target
4768 * @wma: wma handle
4769 * @preq: get peer info request
4770 *
4771 * Return: QDF status
4772 */
4773QDF_STATUS wma_process_get_peer_info_req
4774 (tp_wma_handle wma, tSirIbssGetPeerInfoReqParams *pReq)
4775{
4776 int32_t ret;
4777 uint8_t *p;
4778 uint16_t len;
4779 wmi_buf_t buf;
4780 int32_t vdev_id;
4781 ol_txrx_pdev_handle pdev;
4782 struct ol_txrx_peer_t *peer;
4783 uint8_t peer_mac[IEEE80211_ADDR_LEN];
4784 wmi_peer_info_req_cmd_fixed_param *p_get_peer_info_cmd;
4785 uint8_t bcast_mac[IEEE80211_ADDR_LEN] = { 0xff, 0xff, 0xff,
4786 0xff, 0xff, 0xff };
4787
4788 vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
4789 if (vdev_id < 0) {
4790 WMA_LOGE("%s: IBSS vdev does not exist could not get peer info",
4791 __func__);
4792 return QDF_STATUS_E_FAILURE;
4793 }
4794
4795 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
4796 if (NULL == pdev) {
4797 WMA_LOGE("%s: Failed to get pdev context", __func__);
4798 return QDF_STATUS_E_FAILURE;
4799 }
4800
4801 if (0xFF == pReq->staIdx) {
4802 /*get info for all peers */
4803 qdf_mem_copy(peer_mac, bcast_mac, IEEE80211_ADDR_LEN);
4804 } else {
4805 /*get info for a single peer */
4806 peer = ol_txrx_peer_find_by_local_id(pdev, pReq->staIdx);
4807 if (!peer) {
4808 WMA_LOGE("%s: Failed to get peer handle using peer id %d",
4809 __func__, pReq->staIdx);
4810 return QDF_STATUS_E_FAILURE;
4811 }
4812 WMA_LOGE("%s: staIdx %d peer mac: 0x%2x:0x%2x:0x%2x:0x%2x:0x%2x:0x%2x",
4813 __func__, pReq->staIdx, peer->mac_addr.raw[0],
4814 peer->mac_addr.raw[1], peer->mac_addr.raw[2],
4815 peer->mac_addr.raw[3], peer->mac_addr.raw[4],
4816 peer->mac_addr.raw[5]);
4817 qdf_mem_copy(peer_mac, peer->mac_addr.raw, IEEE80211_ADDR_LEN);
4818 }
4819
4820 len = sizeof(wmi_peer_info_req_cmd_fixed_param);
4821 buf = wmi_buf_alloc(wma->wmi_handle, len);
4822 if (!buf) {
4823 WMA_LOGE("%s %d: No WMI resource!", __func__, __LINE__);
4824 return QDF_STATUS_E_FAILURE;
4825 }
4826
4827 p = (uint8_t *) wmi_buf_data(buf);
4828 qdf_mem_zero(p, len);
4829 p_get_peer_info_cmd = (wmi_peer_info_req_cmd_fixed_param *) p;
4830
4831 WMITLV_SET_HDR(&p_get_peer_info_cmd->tlv_header,
4832 WMITLV_TAG_STRUC_wmi_peer_info_req_cmd_fixed_param,
4833 WMITLV_GET_STRUCT_TLVLEN
4834 (wmi_peer_info_req_cmd_fixed_param));
4835
4836 p_get_peer_info_cmd->vdev_id = vdev_id;
4837 WMI_CHAR_ARRAY_TO_MAC_ADDR(peer_mac,
4838 &p_get_peer_info_cmd->peer_mac_address);
4839
4840 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
4841 WMI_PEER_INFO_REQ_CMDID);
4842
4843 WMA_LOGE("IBSS get peer info cmd sent len: %d, vdev %d"
4844 " command id: %d, status: %d", len,
4845 p_get_peer_info_cmd->vdev_id, WMI_PEER_INFO_REQ_CMDID, ret);
4846
4847 return QDF_STATUS_SUCCESS;
4848}
4849
4850/**
4851 * wma_process_tx_fail_monitor_ind() - sends tx fail monitor cmd to target
4852 * @wma: wma handle
4853 * @pReq: tx fail monitor command params
4854 *
4855 * Return: QDF status
4856 */
4857QDF_STATUS wma_process_tx_fail_monitor_ind
4858 (tp_wma_handle wma, tAniTXFailMonitorInd *pReq)
4859{
4860 QDF_STATUS ret;
4861 int32_t vdev_id;
4862
4863 vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
4864 if (vdev_id < 0) {
4865 WMA_LOGE("%s: IBSS vdev does not exist could not send fast tx fail"
4866 " monitor indication message to target", __func__);
4867 return QDF_STATUS_E_FAILURE;
4868 }
4869
4870 /* Send enable cesium command to target */
4871 WMA_LOGE("send fast tx fail monitor ind cmd target for vdevId %d val %d",
4872 vdev_id, pReq->tx_fail_count);
4873
4874 if (0 == pReq->tx_fail_count) {
4875 wma->hddTxFailCb = NULL;
4876 } else {
4877 wma->hddTxFailCb = pReq->txFailIndCallback;
4878 }
4879 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
4880 WMI_VDEV_PARAM_SET_IBSS_TX_FAIL_CNT_THR,
4881 pReq->tx_fail_count);
4882 if (ret) {
4883 WMA_LOGE("tx fail monitor failed for vdevId %d", vdev_id);
4884 return QDF_STATUS_E_FAILURE;
4885 }
4886
4887 return QDF_STATUS_SUCCESS;
4888}
4889
4890/**
4891 * wma_process_rmc_enable_ind() - enables RMC functionality in target
4892 * @wma: wma handle
4893 *
4894 * Return: QDF status
4895 */
4896QDF_STATUS wma_process_rmc_enable_ind(tp_wma_handle wma)
4897{
4898 int ret;
4899 uint8_t *p;
4900 uint16_t len;
4901 wmi_buf_t buf;
4902 int32_t vdev_id;
4903 wmi_rmc_set_mode_cmd_fixed_param *p_rmc_enable_cmd;
4904
4905 vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
4906 if (vdev_id < 0) {
4907 WMA_LOGE("%s: IBSS vdev does not exist could not enable RMC",
4908 __func__);
4909 return QDF_STATUS_E_FAILURE;
4910 }
4911
4912 len = sizeof(wmi_rmc_set_mode_cmd_fixed_param);
4913 buf = wmi_buf_alloc(wma->wmi_handle, len);
4914 if (!buf) {
4915 WMA_LOGE("%s %d: No WMI resource!", __func__, __LINE__);
4916 return QDF_STATUS_E_FAILURE;
4917 }
4918
4919 p = (uint8_t *) wmi_buf_data(buf);
4920 qdf_mem_zero(p, len);
4921 p_rmc_enable_cmd = (wmi_rmc_set_mode_cmd_fixed_param *) p;
4922
4923 WMITLV_SET_HDR(&p_rmc_enable_cmd->tlv_header,
4924 WMITLV_TAG_STRUC_wmi_rmc_set_mode_cmd_fixed_param,
4925 WMITLV_GET_STRUCT_TLVLEN
4926 (wmi_rmc_set_mode_cmd_fixed_param));
4927
4928 p_rmc_enable_cmd->vdev_id = vdev_id;
4929 p_rmc_enable_cmd->enable_rmc = WMI_RMC_MODE_ENABLED;
4930
4931 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
4932 WMI_RMC_SET_MODE_CMDID);
4933
4934 WMA_LOGE("Enable RMC cmd sent len: %d, vdev %d" " command id: %d,"
4935 " status: %d", len, p_rmc_enable_cmd->vdev_id,
4936 WMI_RMC_SET_MODE_CMDID, ret);
4937
4938 return QDF_STATUS_SUCCESS;
4939}
4940
4941/**
4942 * wma_process_rmc_disable_ind() - disables rmc functionality in target
4943 * @wma: wma handle
4944 *
4945 * Return: QDF status
4946 */
4947QDF_STATUS wma_process_rmc_disable_ind(tp_wma_handle wma)
4948{
4949 int ret;
4950 uint8_t *p;
4951 uint16_t len;
4952 wmi_buf_t buf;
4953 int32_t vdev_id;
4954 wmi_rmc_set_mode_cmd_fixed_param *p_rmc_disable_cmd;
4955
4956 vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
4957 if (vdev_id < 0) {
4958 WMA_LOGE("%s: IBSS vdev does not exist could not disable RMC",
4959 __func__);
4960 return QDF_STATUS_E_FAILURE;
4961 }
4962
4963 len = sizeof(wmi_rmc_set_mode_cmd_fixed_param);
4964 buf = wmi_buf_alloc(wma->wmi_handle, len);
4965 if (!buf) {
4966 WMA_LOGE("%s %d: No WMI resource!", __func__, __LINE__);
4967 return QDF_STATUS_E_FAILURE;
4968 }
4969
4970 p = (uint8_t *) wmi_buf_data(buf);
4971 qdf_mem_zero(p, len);
4972 p_rmc_disable_cmd = (wmi_rmc_set_mode_cmd_fixed_param *) p;
4973
4974 WMITLV_SET_HDR(&p_rmc_disable_cmd->tlv_header,
4975 WMITLV_TAG_STRUC_wmi_rmc_set_mode_cmd_fixed_param,
4976 WMITLV_GET_STRUCT_TLVLEN
4977 (wmi_rmc_set_mode_cmd_fixed_param));
4978
4979 p_rmc_disable_cmd->vdev_id = vdev_id;
4980 p_rmc_disable_cmd->enable_rmc = WMI_RMC_MODE_DISABLED;
4981
4982 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
4983 WMI_RMC_SET_MODE_CMDID);
4984
4985 WMA_LOGE("Disable RMC cmd sent len: %d, vdev %d" " command id: %d,"
4986 " status: %d", len, p_rmc_disable_cmd->vdev_id,
4987 WMI_RMC_SET_MODE_CMDID, ret);
4988
4989 return QDF_STATUS_SUCCESS;
4990}
4991
4992/**
4993 * wma_process_rmc_action_period_ind() - sends RMC action period to target
4994 * @wma: wma handle
4995 *
4996 * Return: QDF status
4997 */
4998QDF_STATUS wma_process_rmc_action_period_ind(tp_wma_handle wma)
4999{
5000 int ret;
5001 uint8_t *p;
5002 uint16_t len;
5003 uint32_t val;
5004 wmi_buf_t buf;
5005 int32_t vdev_id;
5006 wmi_rmc_set_action_period_cmd_fixed_param *p_rmc_cmd;
5007 struct sAniSirGlobal *mac = cds_get_context(QDF_MODULE_ID_PE);
5008
5009 if (NULL == mac) {
5010 WMA_LOGE("%s: MAC mac does not exist", __func__);
5011 return QDF_STATUS_E_FAILURE;
5012 }
5013
5014 vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
5015 if (vdev_id < 0) {
5016 WMA_LOGE("%s: IBSS vdev does not exist could not send"
5017 " RMC action period to target", __func__);
5018 return QDF_STATUS_E_FAILURE;
5019 }
5020
5021 len = sizeof(wmi_rmc_set_action_period_cmd_fixed_param);
5022 buf = wmi_buf_alloc(wma->wmi_handle, len);
5023 if (!buf) {
5024 WMA_LOGE("%s %d: No WMI resource!", __func__, __LINE__);
5025 return QDF_STATUS_E_FAILURE;
5026 }
5027
5028 p = (uint8_t *) wmi_buf_data(buf);
5029 qdf_mem_zero(p, len);
5030 p_rmc_cmd = (wmi_rmc_set_action_period_cmd_fixed_param *) p;
5031
5032 WMITLV_SET_HDR(&p_rmc_cmd->tlv_header,
5033 WMITLV_TAG_STRUC_wmi_rmc_set_action_period_cmd_fixed_param,
5034 WMITLV_GET_STRUCT_TLVLEN
5035 (wmi_rmc_set_action_period_cmd_fixed_param));
5036
5037 if (wlan_cfg_get_int(mac, WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY, &val)
5038 != eSIR_SUCCESS) {
5039 WMA_LOGE("Failed to get value for RMC action period using default");
5040 val = WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY_STADEF;
5041 }
5042
5043 p_rmc_cmd->vdev_id = vdev_id;
5044 p_rmc_cmd->periodicity_msec = val;
5045
5046 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
5047 WMI_RMC_SET_ACTION_PERIOD_CMDID);
5048
5049 WMA_LOGE("RMC action period %d cmd sent len: %d, vdev %d"
5050 " command id: %d, status: %d", p_rmc_cmd->periodicity_msec,
5051 len, p_rmc_cmd->vdev_id, WMI_RMC_SET_ACTION_PERIOD_CMDID, ret);
5052
5053 return QDF_STATUS_SUCCESS;
5054}
5055
5056/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005057 * wma_process_add_periodic_tx_ptrn_ind - add periodic tx ptrn
5058 * @handle: wma handle
5059 * @pAddPeriodicTxPtrnParams: tx ptrn params
5060 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305061 * Retrun: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005062 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305063QDF_STATUS wma_process_add_periodic_tx_ptrn_ind(WMA_HANDLE handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005064 tSirAddPeriodicTxPtrn *
5065 pAddPeriodicTxPtrnParams)
5066{
5067 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Himanshu Agarwal44195412016-03-09 13:03:54 +05305068 struct periodic_tx_pattern params;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005069 uint8_t vdev_id;
Himanshu Agarwal44195412016-03-09 13:03:54 +05305070
5071 qdf_mem_set(&params, sizeof(struct periodic_tx_pattern), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005072
5073 if (!wma_handle || !wma_handle->wmi_handle) {
5074 WMA_LOGE("%s: WMA is closed, can not issue fw add pattern cmd",
5075 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305076 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005077 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005078
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005079 if (!wma_find_vdev_by_addr(wma_handle,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005080 pAddPeriodicTxPtrnParams->mac_address.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005081 &vdev_id)) {
5082 WMA_LOGE("%s: Failed to find vdev id for %pM", __func__,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005083 pAddPeriodicTxPtrnParams->mac_address.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305084 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005085 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005086
Himanshu Agarwal44195412016-03-09 13:03:54 +05305087 params.ucPtrnId = pAddPeriodicTxPtrnParams->ucPtrnId;
5088 params.ucPtrnSize = pAddPeriodicTxPtrnParams->ucPtrnSize;
5089 params.usPtrnIntervalMs = pAddPeriodicTxPtrnParams->usPtrnIntervalMs;
5090 qdf_mem_copy(&params.mac_address,
5091 &pAddPeriodicTxPtrnParams->mac_address,
5092 sizeof(struct qdf_mac_addr));
5093 qdf_mem_copy(params.ucPattern, pAddPeriodicTxPtrnParams->ucPattern,
5094 params.ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005095
Himanshu Agarwal44195412016-03-09 13:03:54 +05305096 return wmi_unified_process_add_periodic_tx_ptrn_cmd(
5097 wma_handle->wmi_handle, &params, vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005098}
5099
5100/**
5101 * wma_process_del_periodic_tx_ptrn_ind - del periodic tx ptrn
5102 * @handle: wma handle
5103 * @pDelPeriodicTxPtrnParams: tx ptrn params
5104 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305105 * Retrun: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005106 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305107QDF_STATUS wma_process_del_periodic_tx_ptrn_ind(WMA_HANDLE handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005108 tSirDelPeriodicTxPtrn *
5109 pDelPeriodicTxPtrnParams)
5110{
5111 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005112 uint8_t vdev_id;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005113
5114 if (!wma_handle || !wma_handle->wmi_handle) {
5115 WMA_LOGE("%s: WMA is closed, can not issue Del Pattern cmd",
5116 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305117 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005118 }
Himanshu Agarwal44195412016-03-09 13:03:54 +05305119
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005120 if (!wma_find_vdev_by_addr(wma_handle,
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08005121 pDelPeriodicTxPtrnParams->mac_address.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005122 &vdev_id)) {
5123 WMA_LOGE("%s: Failed to find vdev id for %pM", __func__,
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08005124 pDelPeriodicTxPtrnParams->mac_address.bytes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305125 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005126 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005127
Himanshu Agarwal44195412016-03-09 13:03:54 +05305128 return wmi_unified_process_del_periodic_tx_ptrn_cmd(
5129 wma_handle->wmi_handle, vdev_id,
5130 pDelPeriodicTxPtrnParams->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005131}
5132
5133#ifdef WLAN_FEATURE_STATS_EXT
5134/**
5135 * wma_stats_ext_req() - request ext stats from fw
5136 * @wma_ptr: wma handle
5137 * @preq: stats ext params
5138 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305139 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005140 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305141QDF_STATUS wma_stats_ext_req(void *wma_ptr, tpStatsExtRequest preq)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005142{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005143 tp_wma_handle wma = (tp_wma_handle) wma_ptr;
Himanshu Agarwal44195412016-03-09 13:03:54 +05305144 struct stats_ext_params params = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005145
Himanshu Agarwal44195412016-03-09 13:03:54 +05305146 if (!wma) {
5147 WMA_LOGE("%s: wma handle is NULL", __func__);
5148 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005149 }
5150
Himanshu Agarwal44195412016-03-09 13:03:54 +05305151 params.vdev_id = preq->vdev_id;
5152 params.request_data_len = preq->request_data_len;
5153 qdf_mem_copy(params.request_data, preq->request_data,
5154 params.request_data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005155
Himanshu Agarwal44195412016-03-09 13:03:54 +05305156 return wmi_unified_stats_ext_req_cmd(wma->wmi_handle,
5157 &params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005158}
5159
5160#endif /* WLAN_FEATURE_STATS_EXT */
5161
5162#ifdef WLAN_FEATURE_EXTWOW_SUPPORT
5163/**
5164 * wma_send_status_of_ext_wow() - send ext wow status to SME
5165 * @wma: wma handle
5166 * @status: status
5167 *
5168 * Return: none
5169 */
5170static void wma_send_status_of_ext_wow(tp_wma_handle wma, bool status)
5171{
5172 tSirReadyToExtWoWInd *ready_to_extwow;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305173 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005174 cds_msg_t cds_msg;
5175 uint8_t len;
5176
5177 WMA_LOGD("Posting ready to suspend indication to umac");
5178
5179 len = sizeof(tSirReadyToExtWoWInd);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305180 ready_to_extwow = (tSirReadyToExtWoWInd *) qdf_mem_malloc(len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005181
5182 if (NULL == ready_to_extwow) {
5183 WMA_LOGE("%s: Memory allocation failure", __func__);
5184 return;
5185 }
5186
5187 ready_to_extwow->mesgType = eWNI_SME_READY_TO_EXTWOW_IND;
5188 ready_to_extwow->mesgLen = len;
5189 ready_to_extwow->status = status;
5190
5191 cds_msg.type = eWNI_SME_READY_TO_EXTWOW_IND;
5192 cds_msg.bodyptr = (void *)ready_to_extwow;
5193 cds_msg.bodyval = 0;
5194
5195 vstatus = cds_mq_post_message(CDS_MQ_ID_SME, &cds_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305196 if (vstatus != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005197 WMA_LOGE("Failed to post ready to suspend");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305198 qdf_mem_free(ready_to_extwow);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005199 }
5200}
5201
5202/**
5203 * wma_enable_ext_wow() - enable ext wow in fw
5204 * @wma: wma handle
5205 * @params: ext wow params
5206 *
5207 * Return:0 for success or error code
5208 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05305209QDF_STATUS wma_enable_ext_wow(tp_wma_handle wma, tpSirExtWoWParams params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005210{
Himanshu Agarwal44195412016-03-09 13:03:54 +05305211 struct ext_wow_params wow_params = {0};
5212 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005213
Himanshu Agarwal44195412016-03-09 13:03:54 +05305214 if (!wma) {
5215 WMA_LOGE("%s: wma handle is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305216 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005217 }
5218
Himanshu Agarwal44195412016-03-09 13:03:54 +05305219 wow_params.vdev_id = params->vdev_id;
5220 wow_params.type = (enum wmi_ext_wow_type) params->type;
5221 wow_params.wakeup_pin_num = params->wakeup_pin_num;
5222
5223 status = wmi_unified_enable_ext_wow_cmd(wma->wmi_handle,
5224 &wow_params);
5225 if (QDF_IS_STATUS_ERROR(status))
5226 return status;
5227
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005228 wma_send_status_of_ext_wow(wma, true);
Himanshu Agarwal44195412016-03-09 13:03:54 +05305229 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005230
5231}
5232
5233/**
5234 * wma_set_app_type1_params_in_fw() - set app type1 params in fw
5235 * @wma: wma handle
5236 * @appType1Params: app type1 params
5237 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305238 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005239 */
5240int wma_set_app_type1_params_in_fw(tp_wma_handle wma,
5241 tpSirAppType1Params appType1Params)
5242{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005243 int ret;
5244
Govind Singhaa64c242016-03-08 11:31:49 +05305245 ret = wmi_unified_app_type1_params_in_fw_cmd(wma->wmi_handle,
5246 (struct app_type1_params *)appType1Params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005247 if (ret) {
5248 WMA_LOGE("%s: Failed to set APP TYPE1 PARAMS", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305249 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005250 }
5251
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305252 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005253}
5254
5255/**
5256 * wma_set_app_type2_params_in_fw() - set app type2 params in fw
5257 * @wma: wma handle
5258 * @appType2Params: app type2 params
5259 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305260 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005261 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05305262QDF_STATUS wma_set_app_type2_params_in_fw(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005263 tpSirAppType2Params appType2Params)
5264{
Himanshu Agarwal44195412016-03-09 13:03:54 +05305265 struct app_type2_params params = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005266
Himanshu Agarwal44195412016-03-09 13:03:54 +05305267 if (!wma) {
5268 WMA_LOGE("%s: wma handle is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305269 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005270 }
5271
Himanshu Agarwal44195412016-03-09 13:03:54 +05305272 params.vdev_id = appType2Params->vdev_id;
5273 params.rc4_key_len = appType2Params->rc4_key_len;
5274 qdf_mem_copy(params.rc4_key, appType2Params->rc4_key, 16);
5275 params.ip_id = appType2Params->ip_id;
5276 params.ip_device_ip = appType2Params->ip_device_ip;
5277 params.ip_server_ip = appType2Params->ip_server_ip;
5278 params.tcp_src_port = appType2Params->tcp_src_port;
5279 params.tcp_dst_port = appType2Params->tcp_dst_port;
5280 params.tcp_seq = appType2Params->tcp_seq;
5281 params.tcp_ack_seq = appType2Params->tcp_ack_seq;
5282 params.keepalive_init = appType2Params->keepalive_init;
5283 params.keepalive_min = appType2Params->keepalive_min;
5284 params.keepalive_max = appType2Params->keepalive_max;
5285 params.keepalive_inc = appType2Params->keepalive_inc;
5286 params.tcp_tx_timeout_val = appType2Params->tcp_tx_timeout_val;
5287 params.tcp_rx_timeout_val = appType2Params->tcp_rx_timeout_val;
5288 qdf_mem_copy(&params.gateway_mac, &appType2Params->gateway_mac,
5289 sizeof(struct qdf_mac_addr));
5290
5291 return wmi_unified_set_app_type2_params_in_fw_cmd(wma->wmi_handle,
5292 &params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005293
5294}
5295#endif /* WLAN_FEATURE_EXTWOW_SUPPORT */
5296
5297#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
5298/**
5299 * wma_auto_shutdown_event_handler() - process auto shutdown timer trigger
5300 * @handle: wma handle
5301 * @event: event buffer
5302 * @len: buffer length
5303 *
5304 * Return: 0 for success or error code
5305 */
5306int wma_auto_shutdown_event_handler(void *handle, uint8_t *event,
5307 uint32_t len)
5308{
5309 wmi_host_auto_shutdown_event_fixed_param *wmi_auto_sh_evt;
5310 WMI_HOST_AUTO_SHUTDOWN_EVENTID_param_tlvs *param_buf =
5311 (WMI_HOST_AUTO_SHUTDOWN_EVENTID_param_tlvs *)
5312 event;
5313
5314 if (!param_buf || !param_buf->fixed_param) {
5315 WMA_LOGE("%s:%d: Invalid Auto shutdown timer evt", __func__,
5316 __LINE__);
5317 return -EINVAL;
5318 }
5319
5320 wmi_auto_sh_evt = param_buf->fixed_param;
5321
5322 if (wmi_auto_sh_evt->shutdown_reason
5323 != WMI_HOST_AUTO_SHUTDOWN_REASON_TIMER_EXPIRY) {
5324 WMA_LOGE("%s:%d: Invalid Auto shutdown timer evt", __func__,
5325 __LINE__);
5326 return -EINVAL;
5327 }
5328
5329 WMA_LOGD("%s:%d: Auto Shutdown Evt: %d", __func__, __LINE__,
5330 wmi_auto_sh_evt->shutdown_reason);
5331 return wma_post_auto_shutdown_msg();
5332}
5333
5334/**
5335 * wma_set_auto_shutdown_timer_req() - sets auto shutdown timer in firmware
5336 * @wma: wma handle
5337 * @auto_sh_cmd: auto shutdown timer value
5338 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305339 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005340 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305341QDF_STATUS wma_set_auto_shutdown_timer_req(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005342 tSirAutoShutdownCmdParams *
5343 auto_sh_cmd)
5344{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005345 if (auto_sh_cmd == NULL) {
5346 WMA_LOGE("%s : Invalid Autoshutdown cfg cmd", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305347 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005348 }
5349
Himanshu Agarwal44195412016-03-09 13:03:54 +05305350 return wmi_unified_set_auto_shutdown_timer_cmd(wma_handle->wmi_handle,
5351 auto_sh_cmd->timer_val);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005352}
5353#endif /* FEATURE_WLAN_AUTO_SHUTDOWN */
5354
5355#ifdef WLAN_FEATURE_NAN
5356/**
5357 * wma_nan_req() - to send nan request to target
5358 * @wma: wma_handle
5359 * @nan_req: request data which will be non-null
5360 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305361 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005362 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305363QDF_STATUS wma_nan_req(void *wma_ptr, tpNanRequest nan_req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005364{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005365 tp_wma_handle wma_handle = (tp_wma_handle) wma_ptr;
Himanshu Agarwal44195412016-03-09 13:03:54 +05305366 struct nan_req_params params = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005367
Himanshu Agarwal44195412016-03-09 13:03:54 +05305368 if (!wma_handle) {
5369 WMA_LOGE("%s: wma handle is NULL", __func__);
5370 return QDF_STATUS_E_FAILURE;
5371 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005372 if (!nan_req) {
5373 WMA_LOGE("%s:nan req is not valid", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305374 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005375 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005376
Himanshu Agarwal44195412016-03-09 13:03:54 +05305377 params.request_data_len = nan_req->request_data_len;
5378 qdf_mem_copy(params.request_data, nan_req->request_data,
5379 params.request_data_len);
5380
5381 return wmi_unified_nan_req_cmd(wma_handle->wmi_handle,
5382 &params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005383}
5384#endif /* WLAN_FEATURE_NAN */
5385
5386#ifdef DHCP_SERVER_OFFLOAD
5387/**
5388 * wma_process_dhcpserver_offload() - enable DHCP server offload
5389 * @wma_handle: wma handle
5390 * @pDhcpSrvOffloadInfo: DHCP server offload info
5391 *
5392 * Return: 0 for success or error code
5393 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05305394QDF_STATUS wma_process_dhcpserver_offload(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005395 tSirDhcpSrvOffloadInfo *
5396 pDhcpSrvOffloadInfo)
5397{
Himanshu Agarwal44195412016-03-09 13:03:54 +05305398 struct dhcp_offload_info_params params = {0};
5399 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005400
Himanshu Agarwal44195412016-03-09 13:03:54 +05305401 if (!wma_handle) {
5402 WMA_LOGE("%s: wma handle is NULL", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005403 return -EIO;
5404 }
Himanshu Agarwal44195412016-03-09 13:03:54 +05305405
5406 params.vdev_id = pDhcpSrvOffloadInfo->vdev_id;
5407 params.dhcpSrvOffloadEnabled =
5408 pDhcpSrvOffloadInfo->dhcpSrvOffloadEnabled;
5409 params.dhcpClientNum = pDhcpSrvOffloadInfo->dhcpClientNum;
5410 params.dhcpSrvIP = pDhcpSrvOffloadInfo->;
5411
5412 status = wmi_unified_process_dhcpserver_offload_cmd(
5413 wma_handle->wmi_handle, &params);
5414 if (QDF_IS_STATUS_ERROR(status))
5415 return status;
5416
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005417 WMA_LOGD("Set dhcp server offload to vdevId %d",
5418 pDhcpSrvOffloadInfo->vdev_id);
Himanshu Agarwal44195412016-03-09 13:03:54 +05305419 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005420}
5421#endif /* DHCP_SERVER_OFFLOAD */
5422
5423#ifdef WLAN_FEATURE_GPIO_LED_FLASHING
5424/**
5425 * wma_set_led_flashing() - set led flashing in fw
5426 * @wma_handle: wma handle
5427 * @flashing: flashing request
5428 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305429 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005430 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305431QDF_STATUS wma_set_led_flashing(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005432 tSirLedFlashingReq *flashing)
5433{
Govind Singhaa64c242016-03-08 11:31:49 +05305434 struct flashing_req_params cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005435
5436 if (!wma_handle || !wma_handle->wmi_handle) {
5437 WMA_LOGE(FL("WMA is closed, can not issue cmd"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305438 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005439 }
5440 if (!flashing) {
5441 WMA_LOGE(FL("invalid parameter: flashing"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305442 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005443 }
Govind Singhaa64c242016-03-08 11:31:49 +05305444 cmd.req_id = flashing->reqId;
5445 cmd.pattern_id = flashing->pattern_id;
5446 cmd.led_x0 = flashing->led_x0;
5447 cmd.led_x1 = flashing->led_x1;
5448 status = wmi_unified_set_led_flashing_cmd(wma_handle->wmi_handle,
5449 &cmd);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005450 if (status != EOK) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305451 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005452 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305453 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005454}
5455#endif /* WLAN_FEATURE_GPIO_LED_FLASHING */
5456
5457#ifdef FEATURE_WLAN_CH_AVOID
5458/**
5459 * wma_channel_avoid_evt_handler() - process channel to avoid event from FW.
5460 * @handle: wma handle
5461 * @event: event buffer
5462 * @len: buffer length
5463 *
5464 * Return: 0 for success or error code
5465 */
5466int wma_channel_avoid_evt_handler(void *handle, uint8_t *event,
5467 uint32_t len)
5468{
5469 wmi_avoid_freq_ranges_event_fixed_param *afr_fixed_param;
5470 wmi_avoid_freq_range_desc *afr_desc;
5471 uint32_t num_freq_ranges, freq_range_idx;
5472 tSirChAvoidIndType *sca_indication;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305473 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005474 cds_msg_t sme_msg = { 0 };
5475 WMI_WLAN_FREQ_AVOID_EVENTID_param_tlvs *param_buf =
5476 (WMI_WLAN_FREQ_AVOID_EVENTID_param_tlvs *) event;
5477
5478 if (!param_buf) {
5479 WMA_LOGE("Invalid channel avoid event buffer");
5480 return -EINVAL;
5481 }
5482
5483 afr_fixed_param = param_buf->fixed_param;
5484 if (!afr_fixed_param) {
5485 WMA_LOGE("Invalid channel avoid event fixed param buffer");
5486 return -EINVAL;
5487 }
5488
5489 num_freq_ranges =
5490 (afr_fixed_param->num_freq_ranges >
5491 SIR_CH_AVOID_MAX_RANGE) ? SIR_CH_AVOID_MAX_RANGE :
5492 afr_fixed_param->num_freq_ranges;
5493
5494 WMA_LOGD("Channel avoid event received with %d ranges",
5495 num_freq_ranges);
5496 for (freq_range_idx = 0; freq_range_idx < num_freq_ranges;
5497 freq_range_idx++) {
5498 afr_desc = (wmi_avoid_freq_range_desc *)
5499 ((void *)param_buf->avd_freq_range +
5500 freq_range_idx * sizeof(wmi_avoid_freq_range_desc));
5501
5502 WMA_LOGD("range %d: tlv id = %u, start freq = %u, end freq = %u",
5503 freq_range_idx, afr_desc->tlv_header, afr_desc->start_freq,
5504 afr_desc->end_freq);
5505 }
5506
5507 sca_indication = (tSirChAvoidIndType *)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305508 qdf_mem_malloc(sizeof(tSirChAvoidIndType));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005509 if (!sca_indication) {
5510 WMA_LOGE("Invalid channel avoid indication buffer");
5511 return -EINVAL;
5512 }
5513
5514 sca_indication->avoid_range_count = num_freq_ranges;
5515 for (freq_range_idx = 0; freq_range_idx < num_freq_ranges;
5516 freq_range_idx++) {
5517 afr_desc = (wmi_avoid_freq_range_desc *)
5518 ((void *)param_buf->avd_freq_range +
5519 freq_range_idx * sizeof(wmi_avoid_freq_range_desc));
5520 sca_indication->avoid_freq_range[freq_range_idx].start_freq =
5521 afr_desc->start_freq;
5522 sca_indication->avoid_freq_range[freq_range_idx].end_freq =
5523 afr_desc->end_freq;
5524 }
5525
5526 sme_msg.type = eWNI_SME_CH_AVOID_IND;
5527 sme_msg.bodyptr = sca_indication;
5528 sme_msg.bodyval = 0;
5529
Anurag Chouhan6d760662016-02-20 16:05:43 +05305530 qdf_status = cds_mq_post_message(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305531 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005532 WMA_LOGE("Fail to post eWNI_SME_CH_AVOID_IND msg to SME");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305533 qdf_mem_free(sca_indication);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005534 return -EINVAL;
5535 }
5536
5537 return 0;
5538}
5539
5540/**
5541 * wma_process_ch_avoid_update_req() - handles channel avoid update request
5542 * @wma_handle: wma handle
5543 * @ch_avoid_update_req: channel avoid update params
5544 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305545 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005546 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305547QDF_STATUS wma_process_ch_avoid_update_req(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005548 tSirChAvoidUpdateReq *
5549 ch_avoid_update_req)
5550{
Himanshu Agarwal44195412016-03-09 13:03:54 +05305551 QDF_STATUS status;
5552 if (!wma_handle) {
5553 WMA_LOGE("%s: wma handle is NULL", __func__);
5554 return QDF_STATUS_E_FAILURE;
5555 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005556 if (ch_avoid_update_req == NULL) {
5557 WMA_LOGE("%s : ch_avoid_update_req is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305558 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005559 }
5560
5561 WMA_LOGI("%s: WMA --> WMI_CHAN_AVOID_UPDATE", __func__);
5562
Himanshu Agarwal44195412016-03-09 13:03:54 +05305563 status = wmi_unified_process_ch_avoid_update_cmd(
5564 wma_handle->wmi_handle);
5565 if (QDF_IS_STATUS_ERROR(status))
5566 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005567
5568 WMA_LOGI("%s: WMA --> WMI_CHAN_AVOID_UPDATE sent through WMI",
5569 __func__);
Himanshu Agarwal44195412016-03-09 13:03:54 +05305570 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005571}
5572#endif /* FEATURE_WLAN_CH_AVOID */
5573
5574/**
5575 * wma_set_reg_domain() - set reg domain
5576 * @clientCtxt: client context
5577 * @regId: reg id
5578 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305579 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005580 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305581QDF_STATUS wma_set_reg_domain(void *clientCtxt, v_REGDOMAIN_t regId)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005582{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305583 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005584 cds_set_reg_domain(clientCtxt, regId))
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305585 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005586
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305587 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005588}
5589
5590/**
5591 * wma_send_regdomain_info_to_fw() - send regdomain info to fw
5592 * @reg_dmn: reg domain
5593 * @regdmn2G: 2G reg domain
5594 * @regdmn5G: 5G reg domain
5595 * @ctl2G: 2G test limit
5596 * @ctl5G: 5G test limit
5597 *
5598 * Return: none
5599 */
5600void wma_send_regdomain_info_to_fw(uint32_t reg_dmn, uint16_t regdmn2G,
5601 uint16_t regdmn5G, int8_t ctl2G,
5602 int8_t ctl5G)
5603{
Anurag Chouhan6d760662016-02-20 16:05:43 +05305604 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005605 int32_t cck_mask_val = 0;
Govind Singhd76a5b02016-03-08 15:12:14 +05305606 struct pdev_params pdev_param = {0};
Himanshu Agarwal44195412016-03-09 13:03:54 +05305607 QDF_STATUS ret = QDF_STATUS_SUCCESS;
5608 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005609
5610 if (NULL == wma) {
5611 WMA_LOGE("%s: wma context is NULL", __func__);
5612 return;
5613 }
5614
Himanshu Agarwal44195412016-03-09 13:03:54 +05305615 status = wmi_unified_send_regdomain_info_to_fw_cmd(wma->wmi_handle,
5616 reg_dmn, regdmn2G, regdmn5G, ctl2G, ctl5G);
5617 if (status == QDF_STATUS_E_NOMEM)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005618 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005619
Amar Singhal76b41322015-12-09 14:39:17 -08005620 if ((((reg_dmn & ~COUNTRY_ERD_FLAG) == CTRY_JAPAN14) ||
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005621 ((reg_dmn & ~COUNTRY_ERD_FLAG) == CTRY_KOREA_ROC)) &&
5622 (true == wma->tx_chain_mask_cck))
5623 cck_mask_val = 1;
5624
5625 cck_mask_val |= (wma->self_gen_frm_pwr << 16);
Govind Singhd76a5b02016-03-08 15:12:14 +05305626 pdev_param.param_id = WMI_PDEV_PARAM_TX_CHAIN_MASK_CCK;
5627 pdev_param.param_value = cck_mask_val;
5628 ret = wmi_unified_pdev_param_send(wma->wmi_handle,
5629 &pdev_param,
5630 WMA_WILDCARD_PDEV_ID);
5631
Himanshu Agarwal44195412016-03-09 13:03:54 +05305632 if (QDF_IS_STATUS_ERROR(ret))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005633 WMA_LOGE("failed to set PDEV tx_chain_mask_cck %d",
5634 ret);
5635
5636 return;
5637}
5638
5639/**
Houston Hoffmana76591b2015-11-10 16:52:05 -08005640 * wma_post_runtime_resume_msg() - post the resume request
5641 * @handle: validated wma handle
5642 *
5643 * request the MC thread unpaus the vdev and set resume dtim
5644 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305645 * Return: qdf status of the mq post
Houston Hoffmana76591b2015-11-10 16:52:05 -08005646 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305647static QDF_STATUS wma_post_runtime_resume_msg(WMA_HANDLE handle)
Houston Hoffmana76591b2015-11-10 16:52:05 -08005648{
5649 cds_msg_t resume_msg;
Houston Hoffmanc45db892015-11-13 19:59:25 -08005650 QDF_STATUS status;
5651 tp_wma_handle wma = (tp_wma_handle) handle;
5652
5653 qdf_runtime_pm_prevent_suspend(wma->wma_runtime_resume_lock);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005654
5655 resume_msg.bodyptr = NULL;
5656 resume_msg.type = WMA_RUNTIME_PM_RESUME_IND;
Houston Hoffmanc45db892015-11-13 19:59:25 -08005657
5658 status = cds_mq_post_message(QDF_MODULE_ID_WMA, &resume_msg);
5659
5660 if (!QDF_IS_STATUS_SUCCESS(status)) {
5661 WMA_LOGE("Failed to post Runtime PM Resume IND to VOS");
5662 qdf_runtime_pm_allow_suspend(wma->wma_runtime_resume_lock);
5663 }
5664
5665 return status;
Houston Hoffmana76591b2015-11-10 16:52:05 -08005666}
5667
5668/**
5669 * wma_post_runtime_suspend_msg() - post the suspend request
5670 * @handle: validated wma handle
5671 *
5672 * Requests for offloads to be configured for runtime suspend
5673 * on the MC thread
5674 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305675 * Return QDF_STATUS_E_AGAIN in case of timeout or QDF_STATUS_SUCCESS
Houston Hoffmana76591b2015-11-10 16:52:05 -08005676 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305677static QDF_STATUS wma_post_runtime_suspend_msg(WMA_HANDLE handle)
Houston Hoffmana76591b2015-11-10 16:52:05 -08005678{
5679 cds_msg_t cds_msg;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305680 QDF_STATUS qdf_status;
Houston Hoffmana76591b2015-11-10 16:52:05 -08005681 tp_wma_handle wma = (tp_wma_handle) handle;
5682
Anurag Chouhance0dc992016-02-16 18:18:03 +05305683 qdf_event_reset(&wma->runtime_suspend);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005684
5685 cds_msg.bodyptr = NULL;
5686 cds_msg.type = WMA_RUNTIME_PM_SUSPEND_IND;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305687 qdf_status = cds_mq_post_message(QDF_MODULE_ID_WMA, &cds_msg);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005688
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305689 if (qdf_status != QDF_STATUS_SUCCESS)
Houston Hoffmana76591b2015-11-10 16:52:05 -08005690 goto failure;
5691
Anurag Chouhance0dc992016-02-16 18:18:03 +05305692 if (qdf_wait_single_event(&wma->runtime_suspend,
Houston Hoffmana76591b2015-11-10 16:52:05 -08005693 WMA_TGT_SUSPEND_COMPLETE_TIMEOUT) !=
Anurag Chouhance0dc992016-02-16 18:18:03 +05305694 QDF_STATUS_SUCCESS) {
Houston Hoffmana76591b2015-11-10 16:52:05 -08005695 WMA_LOGE("Failed to get runtime suspend event");
Houston Hoffmanc45db892015-11-13 19:59:25 -08005696 goto msg_timed_out;
Houston Hoffmana76591b2015-11-10 16:52:05 -08005697 }
5698
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305699 return QDF_STATUS_SUCCESS;
Houston Hoffmana76591b2015-11-10 16:52:05 -08005700
Houston Hoffmanc45db892015-11-13 19:59:25 -08005701msg_timed_out:
5702 wma_post_runtime_resume_msg(wma);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005703failure:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305704 return QDF_STATUS_E_AGAIN;
Houston Hoffmana76591b2015-11-10 16:52:05 -08005705}
5706
5707/**
5708 * __wma_bus_suspend(): handles bus suspend for wma
5709 * @type: is this suspend part of runtime suspend or system suspend?
5710 *
5711 * Bails if a scan is in progress.
5712 * Calls the appropriate handlers based on configuration and event.
5713 *
5714 * Return: 0 for success or error code
5715 */
Anurag Chouhan6d760662016-02-20 16:05:43 +05305716static int __wma_bus_suspend(enum qdf_suspend_type type)
Houston Hoffmana76591b2015-11-10 16:52:05 -08005717{
Anurag Chouhan6d760662016-02-20 16:05:43 +05305718 WMA_HANDLE handle = cds_get_context(QDF_MODULE_ID_WMA);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005719 if (NULL == handle) {
5720 WMA_LOGE("%s: wma context is NULL", __func__);
5721 return -EFAULT;
5722 }
5723
5724 if (wma_check_scan_in_progress(handle)) {
5725 WMA_LOGE("%s: Scan in progress. Aborting suspend", __func__);
5726 return -EBUSY;
5727 }
5728
Anurag Chouhan6d760662016-02-20 16:05:43 +05305729 if (type == QDF_RUNTIME_SUSPEND) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305730 QDF_STATUS status = wma_post_runtime_suspend_msg(handle);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005731 if (status)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305732 return qdf_status_to_os_return(status);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005733 }
5734
Anurag Chouhan6d760662016-02-20 16:05:43 +05305735 if (type == QDF_SYSTEM_SUSPEND)
Houston Hoffmana76591b2015-11-10 16:52:05 -08005736 WMA_LOGE("%s: wow mode selected %d", __func__,
5737 wma_is_wow_mode_selected(handle));
5738
5739 if (wma_is_wow_mode_selected(handle)) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305740 QDF_STATUS status = wma_enable_wow_in_fw(handle);
5741 return qdf_status_to_os_return(status);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005742 }
5743
5744 return wma_suspend_target(handle, 0);
5745}
5746
5747/**
5748 * wma_runtime_suspend() - handles runtime suspend request from hdd
5749 *
5750 * Calls the appropriate handler based on configuration and event.
5751 * Last busy marking should prevent race conditions between processing
5752 * of asyncronous fw events and the running of runtime suspend.
5753 * (eg. last busy marking should guarantee that any auth requests have
5754 * been processed)
5755 * Events comming from the host are not protected, but aren't expected
5756 * to be an issue.
5757 *
5758 * Return: 0 for success or error code
5759 */
5760int wma_runtime_suspend(void)
5761{
Anurag Chouhan6d760662016-02-20 16:05:43 +05305762 return __wma_bus_suspend(QDF_RUNTIME_SUSPEND);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005763}
5764
5765/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005766 * wma_bus_suspend() - handles bus suspend request from hdd
5767 *
5768 * Calls the appropriate handler based on configuration and event
5769 *
5770 * Return: 0 for success or error code
5771 */
5772int wma_bus_suspend(void)
5773{
Houston Hoffmana76591b2015-11-10 16:52:05 -08005774
Anurag Chouhan6d760662016-02-20 16:05:43 +05305775 return __wma_bus_suspend(QDF_SYSTEM_SUSPEND);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005776}
5777
5778/**
5779 * __wma_bus_resume() - bus resume for wma
5780 *
5781 * does the part of the bus resume common to bus and system suspend
5782 *
5783 * Return: os error code.
5784 */
5785int __wma_bus_resume(WMA_HANDLE handle)
5786{
5787 bool wow_mode = wma_is_wow_mode_selected(handle);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305788 QDF_STATUS status;
Houston Hoffmana76591b2015-11-10 16:52:05 -08005789
5790 WMA_LOGE("%s: wow mode %d", __func__, wow_mode);
5791
5792 if (!wow_mode)
Rajeev Kumar9be537e2016-04-25 17:35:33 -07005793 return qdf_status_to_os_return(wma_resume_target(handle));
Houston Hoffmana76591b2015-11-10 16:52:05 -08005794
5795 status = wma_disable_wow_in_fw(handle);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305796 return qdf_status_to_os_return(status);
Houston Hoffmana76591b2015-11-10 16:52:05 -08005797}
5798
5799/**
5800 * wma_runtime_resume() - do the runtime resume operation for wma
5801 *
5802 * Return: os error code.
5803 */
5804int wma_runtime_resume(void)
5805{
5806 int ret;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305807 QDF_STATUS status;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305808 WMA_HANDLE handle = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005809 if (NULL == handle) {
5810 WMA_LOGE("%s: wma context is NULL", __func__);
5811 return -EFAULT;
5812 }
5813
Houston Hoffmana76591b2015-11-10 16:52:05 -08005814 ret = __wma_bus_resume(handle);
5815 if (ret)
5816 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005817
Houston Hoffmana76591b2015-11-10 16:52:05 -08005818 status = wma_post_runtime_resume_msg(handle);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305819 return qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005820}
5821
5822/**
5823 * wma_bus_resume() - handles bus resume request from hdd
5824 * @handle: valid wma handle
5825 *
5826 * Calls the appropriate handler based on configuration
5827 *
5828 * Return: 0 for success or error code
5829 */
5830int wma_bus_resume(void)
5831{
Anurag Chouhan6d760662016-02-20 16:05:43 +05305832 WMA_HANDLE handle = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005833 if (NULL == handle) {
5834 WMA_LOGE("%s: wma context is NULL", __func__);
5835 return -EFAULT;
5836 }
5837
Houston Hoffmana76591b2015-11-10 16:52:05 -08005838 return __wma_bus_resume(handle);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005839}
5840
5841/**
Manjunathappa Prakash7b67e622016-04-12 15:18:45 +05305842 * wma_suspend_target_timeout() - Handles the target suspend timeout
5843 * @is_self_recovery_enabled: Is self recovery enabled or not
5844 *
5845 * Return: NONE
5846 */
5847#ifdef QCA_WIFI_3_0_ADRASTEA
5848static inline void wma_suspend_target_timeout(bool is_self_recovery_enabled)
5849{
5850 if (cds_is_driver_recovering()) {
5851 WMA_LOGE("%s: recovery is in progress, ignore!", __func__);
5852 } else {
5853 if (is_self_recovery_enabled) {
5854 cds_trigger_recovery();
5855 } else {
5856 QDF_BUG(0);
5857 }
5858 }
5859}
5860#else /* ROME chipset */
5861static inline void wma_suspend_target_timeout(bool is_self_recovery_enabled)
5862{
5863 if (cds_is_load_or_unload_in_progress() || cds_is_driver_recovering()) {
5864 WMA_LOGE("%s: Unloading/Loading/recovery is in progress, Ignore!",
5865 __func__);
5866 } else {
5867 if (is_self_recovery_enabled) {
5868 cds_trigger_recovery();
5869 } else {
5870 QDF_BUG(0);
5871 }
5872 }
5873}
5874#endif
5875
5876/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005877 * wma_suspend_target() - suspend target
5878 * @handle: wma handle
5879 * @disable_target_intr: disable target interrupt
5880 *
Govind Singhd76a5b02016-03-08 15:12:14 +05305881 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005882 */
Govind Singhd76a5b02016-03-08 15:12:14 +05305883QDF_STATUS wma_suspend_target(WMA_HANDLE handle, int disable_target_intr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005884{
5885 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Komal Seelam3d202862016-02-24 18:43:24 +05305886 struct hif_opaque_softc *scn;
Govind Singhd76a5b02016-03-08 15:12:14 +05305887 QDF_STATUS status;
5888 struct suspend_params param = {0};
5889
Anurag Chouhan6d760662016-02-20 16:05:43 +05305890 tpAniSirGlobal pmac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005891
5892 if (!wma_handle || !wma_handle->wmi_handle) {
5893 WMA_LOGE("WMA is closed. can not issue suspend cmd");
Govind Singhd76a5b02016-03-08 15:12:14 +05305894 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005895 }
Yue Mae1a85f32015-10-20 18:12:45 -07005896
Yue Mae1a85f32015-10-20 18:12:45 -07005897 if (NULL == pmac) {
5898 WMA_LOGE("%s: Unable to get PE context", __func__);
Govind Singhd76a5b02016-03-08 15:12:14 +05305899 return QDF_STATUS_E_INVAL;
Yue Mae1a85f32015-10-20 18:12:45 -07005900 }
Houston Hoffman52ec6692016-04-21 16:36:45 -07005901
Anurag Chouhance0dc992016-02-16 18:18:03 +05305902 qdf_event_reset(&wma_handle->target_suspend);
Govind Singhd76a5b02016-03-08 15:12:14 +05305903 param.disable_target_intr = disable_target_intr;
5904 status = wmi_unified_suspend_send(wma_handle->wmi_handle,
5905 &param,
5906 WMA_WILDCARD_PDEV_ID);
5907 if (QDF_IS_STATUS_ERROR(status))
5908 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005909
5910 wmi_set_target_suspend(wma_handle->wmi_handle, true);
5911
Anurag Chouhance0dc992016-02-16 18:18:03 +05305912 if (qdf_wait_single_event(&wma_handle->target_suspend,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005913 WMA_TGT_SUSPEND_COMPLETE_TIMEOUT)
Anurag Chouhance0dc992016-02-16 18:18:03 +05305914 != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005915 WMA_LOGE("Failed to get ACK from firmware for pdev suspend");
5916 wmi_set_target_suspend(wma_handle->wmi_handle, false);
Manjunathappa Prakash7b67e622016-04-12 15:18:45 +05305917 wma_suspend_target_timeout(pmac->sme.enableSelfRecovery);
Govind Singhd76a5b02016-03-08 15:12:14 +05305918 return QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005919 }
5920
Anurag Chouhan6d760662016-02-20 16:05:43 +05305921 scn = cds_get_context(QDF_MODULE_ID_HIF);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005922
5923 if (scn == NULL) {
5924 WMA_LOGE("%s: Failed to get HIF context", __func__);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305925 QDF_ASSERT(0);
Govind Singhd76a5b02016-03-08 15:12:14 +05305926 return QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005927 }
5928
Govind Singhd76a5b02016-03-08 15:12:14 +05305929 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005930}
5931
5932/**
5933 * wma_target_suspend_acknowledge() - update target susspend status
Houston Hoffmana769ed32016-04-14 17:02:51 -07005934 * @context: HTC_INIT_INFO->context
5935 * @wow_nack: true when wow is rejected
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005936 *
5937 * Return: none
5938 */
Houston Hoffmana769ed32016-04-14 17:02:51 -07005939void wma_target_suspend_acknowledge(void *context, bool wow_nack)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005940{
Anurag Chouhan6d760662016-02-20 16:05:43 +05305941 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005942
5943 if (NULL == wma) {
5944 WMA_LOGE("%s: wma is NULL", __func__);
5945 return;
5946 }
5947
5948 wma->wow_nack = wow_nack;
Anurag Chouhance0dc992016-02-16 18:18:03 +05305949 qdf_event_set(&wma->target_suspend);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005950 if (wow_nack)
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305951 qdf_wake_lock_timeout_acquire(&wma->wow_wake_lock,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005952 WMA_WAKE_LOCK_TIMEOUT,
5953 WIFI_POWER_EVENT_WAKELOCK_WOW);
5954}
5955
5956/**
5957 * wma_resume_target() - resume target
5958 * @handle: wma handle
5959 *
Govind Singhd76a5b02016-03-08 15:12:14 +05305960 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005961 */
Govind Singhd76a5b02016-03-08 15:12:14 +05305962QDF_STATUS wma_resume_target(WMA_HANDLE handle)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005963{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005964 tp_wma_handle wma = (tp_wma_handle) handle;
Anurag Chouhance0dc992016-02-16 18:18:03 +05305965 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005966#ifdef CONFIG_CNSS
Anurag Chouhan6d760662016-02-20 16:05:43 +05305967 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005968 if (NULL == pMac) {
5969 WMA_LOGE("%s: Unable to get PE context", __func__);
Govind Singhd76a5b02016-03-08 15:12:14 +05305970 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005971 }
5972#endif /* CONFIG_CNSS */
5973
Anurag Chouhance0dc992016-02-16 18:18:03 +05305974 qdf_event_reset(&wma->wma_resume_event);
Govind Singhd76a5b02016-03-08 15:12:14 +05305975 qdf_status = wmi_unified_resume_send(wma->wmi_handle,
5976 WMA_WILDCARD_PDEV_ID);
5977 if (QDF_IS_STATUS_ERROR(qdf_status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005978 WMA_LOGE("Failed to send WMI_PDEV_RESUME_CMDID command");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005979
Anurag Chouhance0dc992016-02-16 18:18:03 +05305980 qdf_status = qdf_wait_single_event(&(wma->wma_resume_event),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005981 WMA_RESUME_TIMEOUT);
Anurag Chouhance0dc992016-02-16 18:18:03 +05305982 if (QDF_STATUS_SUCCESS != qdf_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005983 WMA_LOGP("%s: Timeout waiting for resume event from FW",
5984 __func__);
5985 WMA_LOGP("%s: Pending commands %d credits %d", __func__,
5986 wmi_get_pending_cmds(wma->wmi_handle),
5987 wmi_get_host_credits(wma->wmi_handle));
Prashanth Bhatta9e143052015-12-04 11:56:47 -08005988 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005989#ifdef CONFIG_CNSS
5990 if (pMac->sme.enableSelfRecovery) {
5991 cds_trigger_recovery();
5992 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305993 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005994 }
5995#else
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305996 QDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005997#endif /* CONFIG_CNSS */
5998 } else {
5999 WMA_LOGE("%s: SSR in progress, ignore resume timeout",
6000 __func__);
6001 }
6002 } else {
6003 WMA_LOGD("Host wakeup received");
6004 }
6005
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306006 if (QDF_STATUS_SUCCESS == qdf_status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006007 wmi_set_target_suspend(wma->wmi_handle, false);
6008
Houston Hoffman52ec6692016-04-21 16:36:45 -07006009 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006010}
6011
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006012#ifdef FEATURE_WLAN_TDLS
6013/**
6014 * wma_tdls_event_handler() - handle TDLS event
6015 * @handle: wma handle
6016 * @event: event buffer
6017 * @len: buffer length
6018 *
6019 * Return: 0 for success or error code
6020 */
6021int wma_tdls_event_handler(void *handle, uint8_t *event, uint32_t len)
6022{
6023 tp_wma_handle wma = (tp_wma_handle) handle;
6024 WMI_TDLS_PEER_EVENTID_param_tlvs *param_buf = NULL;
6025 wmi_tdls_peer_event_fixed_param *peer_event = NULL;
6026 tSirTdlsEventnotify *tdls_event;
6027
6028 if (!event) {
6029 WMA_LOGE("%s: event param null", __func__);
6030 return -EINVAL;
6031 }
6032
6033 param_buf = (WMI_TDLS_PEER_EVENTID_param_tlvs *) event;
6034 if (!param_buf) {
6035 WMA_LOGE("%s: received null buf from target", __func__);
6036 return -EINVAL;
6037 }
6038
6039 peer_event = param_buf->fixed_param;
6040 if (!peer_event) {
6041 WMA_LOGE("%s: received null event data from target", __func__);
6042 return -EINVAL;
6043 }
6044
6045 tdls_event = (tSirTdlsEventnotify *)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306046 qdf_mem_malloc(sizeof(*tdls_event));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006047 if (!tdls_event) {
6048 WMA_LOGE("%s: failed to allocate memory for tdls_event",
6049 __func__);
6050 return -ENOMEM;
6051 }
6052
6053 tdls_event->sessionId = peer_event->vdev_id;
6054 WMI_MAC_ADDR_TO_CHAR_ARRAY(&peer_event->peer_macaddr,
Srinivas Girigowda4f593792015-11-19 15:33:42 -08006055 tdls_event->peermac.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006056
6057 switch (peer_event->peer_status) {
6058 case WMI_TDLS_SHOULD_DISCOVER:
6059 tdls_event->messageType = WMA_TDLS_SHOULD_DISCOVER_CMD;
6060 break;
6061 case WMI_TDLS_SHOULD_TEARDOWN:
6062 tdls_event->messageType = WMA_TDLS_SHOULD_TEARDOWN_CMD;
6063 break;
6064 case WMI_TDLS_PEER_DISCONNECTED:
6065 tdls_event->messageType = WMA_TDLS_PEER_DISCONNECTED_CMD;
6066 break;
6067 default:
6068 WMA_LOGE("%s: Discarding unknown tdls event(%d) from target",
6069 __func__, peer_event->peer_status);
6070 return -EINVAL;
6071 }
6072
6073 switch (peer_event->peer_reason) {
6074 case WMI_TDLS_TEARDOWN_REASON_TX:
6075 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_TX;
6076 break;
6077 case WMI_TDLS_TEARDOWN_REASON_RSSI:
6078 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_RSSI;
6079 break;
6080 case WMI_TDLS_TEARDOWN_REASON_SCAN:
6081 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_SCAN;
6082 break;
6083 case WMI_TDLS_DISCONNECTED_REASON_PEER_DELETE:
6084 tdls_event->peer_reason =
6085 eWNI_TDLS_DISCONNECTED_REASON_PEER_DELETE;
6086 break;
6087 case WMI_TDLS_TEARDOWN_REASON_PTR_TIMEOUT:
6088 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_PTR_TIMEOUT;
6089 break;
6090 case WMI_TDLS_TEARDOWN_REASON_BAD_PTR:
6091 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_BAD_PTR;
6092 break;
6093 case WMI_TDLS_TEARDOWN_REASON_NO_RESPONSE:
6094 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_NO_RESPONSE;
6095 break;
6096 default:
6097 WMA_LOGE("%s: unknown reason(%d) in tdls event(%d) from target",
6098 __func__, peer_event->peer_reason,
6099 peer_event->peer_status);
6100 return -EINVAL;
6101 }
6102
6103 WMA_LOGD("%s: sending msg to umac, messageType: 0x%x, "
6104 "for peer: %pM, reason: %d, smesessionId: %d",
Srinivas Girigowda4f593792015-11-19 15:33:42 -08006105 __func__, tdls_event->messageType, tdls_event->peermac.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006106 tdls_event->peer_reason, tdls_event->sessionId);
6107
6108 wma_send_msg(wma, tdls_event->messageType, (void *)tdls_event, 0);
6109 return 0;
6110}
6111
6112/**
6113 * wma_set_tdls_offchan_mode() - set tdls off channel mode
6114 * @handle: wma handle
6115 * @chan_switch_params: Pointer to tdls channel switch parameter structure
6116 *
6117 * This function sets tdls off channel mode
6118 *
6119 * Return: 0 on success; Negative errno otherwise
6120 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05306121QDF_STATUS wma_set_tdls_offchan_mode(WMA_HANDLE handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006122 tdls_chan_switch_params *chan_switch_params)
6123{
6124 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Himanshu Agarwal44195412016-03-09 13:03:54 +05306125 struct tdls_channel_switch_params params = {0};
6126 QDF_STATUS ret = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006127
6128 if (!wma_handle || !wma_handle->wmi_handle) {
6129 WMA_LOGE(FL(
6130 "WMA is closed, can not issue tdls off channel cmd"
6131 ));
6132 ret = -EINVAL;
6133 goto end;
6134 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006135
Himanshu Agarwal44195412016-03-09 13:03:54 +05306136 params.vdev_id = chan_switch_params->vdev_id;
6137 params.tdls_off_ch_bw_offset =
6138 chan_switch_params->tdls_off_ch_bw_offset;
6139 params.tdls_off_ch = chan_switch_params->tdls_off_ch;
6140 params.tdls_sw_mode = chan_switch_params->tdls_sw_mode;
6141 params.oper_class = chan_switch_params->oper_class;
6142 params.is_responder = chan_switch_params->is_responder;
6143 qdf_mem_copy(params.peer_mac_addr, chan_switch_params->peer_mac_addr,
Krunal Soniab793342016-04-22 18:43:20 -07006144 IEEE80211_ADDR_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006145
Himanshu Agarwal44195412016-03-09 13:03:54 +05306146 ret = wmi_unified_set_tdls_offchan_mode_cmd(wma_handle->wmi_handle,
6147 &params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006148
6149end:
6150 if (chan_switch_params)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306151 qdf_mem_free(chan_switch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006152 return ret;
6153}
6154
6155/**
6156 * wma_update_fw_tdls_state() - send enable/disable tdls for a vdev
6157 * @wma: wma handle
6158 * @pwmaTdlsparams: TDLS params
6159 *
6160 * Return: 0 for sucess or error code
6161 */
Himanshu Agarwal44195412016-03-09 13:03:54 +05306162QDF_STATUS wma_update_fw_tdls_state(WMA_HANDLE handle, void *pwmaTdlsparams)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006163{
6164 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006165 t_wma_tdls_mode tdls_mode;
6166 t_wma_tdls_params *wma_tdls = (t_wma_tdls_params *) pwmaTdlsparams;
Himanshu Agarwal44195412016-03-09 13:03:54 +05306167 struct wmi_tdls_params params = {0};
6168 QDF_STATUS ret = QDF_STATUS_SUCCESS;
6169 uint8_t tdls_state;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006170
6171 if (!wma_handle || !wma_handle->wmi_handle) {
6172 WMA_LOGE("%s: WMA is closed, can not issue fw tdls state cmd",
6173 __func__);
6174 ret = -EINVAL;
6175 goto end_fw_tdls_state;
6176 }
6177
Himanshu Agarwal44195412016-03-09 13:03:54 +05306178 params.tdls_state = wma_tdls->tdls_state;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006179 tdls_mode = wma_tdls->tdls_state;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006180
6181 if (WMA_TDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY == tdls_mode) {
Himanshu Agarwal44195412016-03-09 13:03:54 +05306182 tdls_state = WMI_TDLS_ENABLE_PASSIVE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006183 } else if (WMA_TDLS_SUPPORT_ENABLED == tdls_mode) {
Himanshu Agarwal44195412016-03-09 13:03:54 +05306184 tdls_state = WMI_TDLS_ENABLE_ACTIVE;
Kabilan Kannan421714b2015-11-23 04:44:59 -08006185 } else if (WMA_TDLS_SUPPORT_ACTIVE_EXTERNAL_CONTROL == tdls_mode) {
Himanshu Agarwal44195412016-03-09 13:03:54 +05306186 tdls_state = WMI_TDLS_ENABLE_ACTIVE_EXTERNAL_CONTROL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006187 } else {
Himanshu Agarwal44195412016-03-09 13:03:54 +05306188 tdls_state = WMI_TDLS_DISABLE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006189 }
6190
Himanshu Agarwal44195412016-03-09 13:03:54 +05306191 params.vdev_id = wma_tdls->vdev_id;
6192 params.notification_interval_ms = wma_tdls->notification_interval_ms;
6193 params.tx_discovery_threshold = wma_tdls->tx_discovery_threshold;
6194 params.tx_teardown_threshold = wma_tdls->tx_teardown_threshold;
6195 params.rssi_teardown_threshold = wma_tdls->rssi_teardown_threshold;
6196 params.rssi_delta = wma_tdls->rssi_delta;
6197 params.tdls_options = wma_tdls->tdls_options;
6198 params.peer_traffic_ind_window = wma_tdls->peer_traffic_ind_window;
6199 params.peer_traffic_response_timeout =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006200 wma_tdls->peer_traffic_response_timeout;
Himanshu Agarwal44195412016-03-09 13:03:54 +05306201 params.puapsd_mask = wma_tdls->puapsd_mask;
6202 params.puapsd_inactivity_time = wma_tdls->puapsd_inactivity_time;
6203 params.puapsd_rx_frame_threshold =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006204 wma_tdls->puapsd_rx_frame_threshold;
Himanshu Agarwal44195412016-03-09 13:03:54 +05306205 params.teardown_notification_ms =
Kabilan Kannanca670be2015-11-23 01:56:12 -08006206 wma_tdls->teardown_notification_ms;
Himanshu Agarwal44195412016-03-09 13:03:54 +05306207 params.tdls_peer_kickout_threshold =
Kabilan Kannan421714b2015-11-23 04:44:59 -08006208 wma_tdls->tdls_peer_kickout_threshold;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006209
Himanshu Agarwal44195412016-03-09 13:03:54 +05306210 ret = wmi_unified_update_fw_tdls_state_cmd(wma_handle->wmi_handle,
6211 &params, tdls_state);
6212 if (QDF_IS_STATUS_ERROR(ret))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006213 goto end_fw_tdls_state;
Himanshu Agarwal44195412016-03-09 13:03:54 +05306214
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006215 WMA_LOGD("%s: vdev_id %d", __func__, wma_tdls->vdev_id);
6216
6217end_fw_tdls_state:
6218 if (pwmaTdlsparams)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306219 qdf_mem_free(pwmaTdlsparams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006220 return ret;
6221}
6222
6223/**
6224 * wma_update_tdls_peer_state() - update TDLS peer state
6225 * @handle: wma handle
6226 * @peerStateParams: TDLS peer state params
6227 *
6228 * Return: 0 for success or error code
6229 */
6230int wma_update_tdls_peer_state(WMA_HANDLE handle,
6231 tTdlsPeerStateParams *peerStateParams)
6232{
6233 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006234 uint32_t i;
6235 ol_txrx_pdev_handle pdev;
6236 uint8_t peer_id;
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07006237 ol_txrx_peer_handle peer;
6238 uint8_t *peer_mac_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006239 int ret = 0;
Govind Singhaa64c242016-03-08 11:31:49 +05306240 uint32_t *ch_mhz;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006241
6242 if (!wma_handle || !wma_handle->wmi_handle) {
6243 WMA_LOGE("%s: WMA is closed, can not issue cmd", __func__);
6244 ret = -EINVAL;
6245 goto end_tdls_peer_state;
6246 }
6247
6248 /* peer capability info is valid only when peer state is connected */
6249 if (WMA_TDLS_PEER_STATE_CONNECTED != peerStateParams->peerState) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306250 qdf_mem_zero(&peerStateParams->peerCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006251 sizeof(tTdlsPeerCapParams));
6252 }
6253
Govind Singhaa64c242016-03-08 11:31:49 +05306254 ch_mhz = qdf_mem_malloc(sizeof(uint32_t) *
6255 peerStateParams->peerCap.peerChanLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006256 for (i = 0; i < peerStateParams->peerCap.peerChanLen; ++i) {
Govind Singhaa64c242016-03-08 11:31:49 +05306257 ch_mhz[i] =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006258 cds_chan_to_freq(peerStateParams->peerCap.peerChan[i].
6259 chanId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006260 }
6261
Govind Singhaa64c242016-03-08 11:31:49 +05306262 if (wmi_unified_update_tdls_peer_state_cmd(wma_handle->wmi_handle,
6263 (struct tdls_peer_state_params *)peerStateParams,
6264 ch_mhz)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006265 WMA_LOGE("%s: failed to send tdls peer update state command",
6266 __func__);
Govind Singhaa64c242016-03-08 11:31:49 +05306267 qdf_mem_free(ch_mhz);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006268 ret = -EIO;
6269 goto end_tdls_peer_state;
6270 }
6271
Govind Singhaa64c242016-03-08 11:31:49 +05306272 qdf_mem_free(ch_mhz);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006273 /* in case of teardown, remove peer from fw */
6274 if (WMA_TDLS_PEER_STATE_TEARDOWN == peerStateParams->peerState) {
Anurag Chouhan6d760662016-02-20 16:05:43 +05306275 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006276 if (!pdev) {
6277 WMA_LOGE("%s: Failed to find pdev", __func__);
6278 ret = -EIO;
6279 goto end_tdls_peer_state;
6280 }
6281
6282 peer = ol_txrx_find_peer_by_addr(pdev,
6283 peerStateParams->peerMacAddr,
6284 &peer_id);
6285 if (!peer) {
6286 WMA_LOGE("%s: Failed to get peer handle using peer mac %pM",
6287 __func__, peerStateParams->peerMacAddr);
6288 ret = -EIO;
6289 goto end_tdls_peer_state;
6290 }
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07006291 peer_mac_addr = ol_txrx_peer_get_peer_mac_addr(peer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006292
6293 WMA_LOGD("%s: calling wma_remove_peer for peer " MAC_ADDRESS_STR
6294 " vdevId: %d", __func__,
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07006295 MAC_ADDR_ARRAY(peer_mac_addr),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006296 peerStateParams->vdevId);
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07006297 wma_remove_peer(wma_handle, peer_mac_addr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006298 peerStateParams->vdevId, peer, false);
6299 }
6300
6301end_tdls_peer_state:
6302 if (peerStateParams)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306303 qdf_mem_free(peerStateParams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006304 return ret;
6305}
6306#endif /* FEATURE_WLAN_TDLS */
6307
6308
6309/**
6310 * wma_dfs_attach() - Attach DFS methods to the umac state.
6311 * @dfs_ic: ieee80211com ptr
6312 *
6313 * Return: Return ieee80211com ptr with updated info
6314 */
6315struct ieee80211com *wma_dfs_attach(struct ieee80211com *dfs_ic)
6316{
6317 /*Allocate memory for dfs_ic before passing it up to dfs_attach() */
6318 dfs_ic = (struct ieee80211com *)
6319 os_malloc(NULL, sizeof(struct ieee80211com), GFP_ATOMIC);
6320 if (dfs_ic == NULL) {
6321 WMA_LOGE("%s:Allocation of dfs_ic failed %zu",
6322 __func__, sizeof(struct ieee80211com));
6323 return NULL;
6324 }
6325 OS_MEMZERO(dfs_ic, sizeof(struct ieee80211com));
6326 /* DFS pattern matching hooks */
6327 dfs_ic->ic_dfs_attach = ol_if_dfs_attach;
6328 dfs_ic->ic_dfs_disable = ol_if_dfs_disable;
6329 dfs_ic->ic_find_channel = ieee80211_find_channel;
6330 dfs_ic->ic_dfs_enable = ol_if_dfs_enable;
6331 dfs_ic->ic_ieee2mhz = ieee80211_ieee2mhz;
6332
6333 /* Hardware facing hooks */
6334 dfs_ic->ic_get_ext_busy = ol_if_dfs_get_ext_busy;
6335 dfs_ic->ic_get_mib_cycle_counts_pct =
6336 ol_if_dfs_get_mib_cycle_counts_pct;
6337 dfs_ic->ic_get_TSF64 = ol_if_get_tsf64;
6338
6339 /* NOL related hooks */
6340 dfs_ic->ic_dfs_usenol = ol_if_dfs_usenol;
6341 /*
6342 * Hooks from wma/dfs/ back
6343 * into the PE/SME
6344 * and shared DFS code
6345 */
6346 dfs_ic->ic_dfs_notify_radar = ieee80211_mark_dfs;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306347 qdf_spinlock_create(&dfs_ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006348 /* Initializes DFS Data Structures and queues */
6349 dfs_attach(dfs_ic);
6350
6351 return dfs_ic;
6352}
6353
6354/**
6355 * wma_dfs_detach() - Detach DFS methods
6356 * @dfs_ic: ieee80211com ptr
6357 *
6358 * Return: none
6359 */
6360void wma_dfs_detach(struct ieee80211com *dfs_ic)
6361{
6362 dfs_detach(dfs_ic);
6363
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306364 qdf_spinlock_destroy(&dfs_ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006365 if (NULL != dfs_ic->ic_curchan) {
6366 OS_FREE(dfs_ic->ic_curchan);
6367 dfs_ic->ic_curchan = NULL;
6368 }
6369
6370 OS_FREE(dfs_ic);
6371}
6372
6373/**
6374 * wma_dfs_configure() - configure dfs
6375 * @ic: ieee80211com ptr
6376 *
6377 * Configures Radar Filters during
6378 * vdev start/channel change/regulatory domain
6379 * change.This Configuration enables to program
6380 * the DFS pattern matching module.
6381 *
6382 * Return: none
6383 */
6384void wma_dfs_configure(struct ieee80211com *ic)
6385{
6386 struct ath_dfs_radar_tab_info rinfo;
6387 int dfsdomain;
6388 int radar_enabled_status = 0;
6389 if (ic == NULL) {
6390 WMA_LOGE("%s: DFS ic is Invalid", __func__);
6391 return;
6392 }
6393
6394 dfsdomain = ic->current_dfs_regdomain;
6395
6396 /* Fetch current radar patterns from the lmac */
6397 OS_MEMZERO(&rinfo, sizeof(rinfo));
6398
6399 /*
6400 * Look up the current DFS
6401 * regulatory domain and decide
6402 * which radar pulses to use.
6403 */
6404 switch (dfsdomain) {
Amar Singhala7bb01b2016-01-27 11:31:59 -08006405 case DFS_FCC_REGION:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006406 WMA_LOGI("%s: DFS-FCC domain", __func__);
Amar Singhala7bb01b2016-01-27 11:31:59 -08006407 rinfo.dfsdomain = DFS_FCC_REGION;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006408 rinfo.dfs_radars = dfs_fcc_radars;
Anurag Chouhan6d760662016-02-20 16:05:43 +05306409 rinfo.numradars = QDF_ARRAY_SIZE(dfs_fcc_radars);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006410 rinfo.b5pulses = dfs_fcc_bin5pulses;
Anurag Chouhan6d760662016-02-20 16:05:43 +05306411 rinfo.numb5radars = QDF_ARRAY_SIZE(dfs_fcc_bin5pulses);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006412 break;
Amar Singhala7bb01b2016-01-27 11:31:59 -08006413 case DFS_ETSI_REGION:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006414 WMA_LOGI("%s: DFS-ETSI domain", __func__);
Amar Singhala7bb01b2016-01-27 11:31:59 -08006415 rinfo.dfsdomain = DFS_ETSI_REGION;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006416 rinfo.dfs_radars = dfs_etsi_radars;
Anurag Chouhan6d760662016-02-20 16:05:43 +05306417 rinfo.numradars = QDF_ARRAY_SIZE(dfs_etsi_radars);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006418 rinfo.b5pulses = NULL;
6419 rinfo.numb5radars = 0;
6420 break;
Amar Singhala7bb01b2016-01-27 11:31:59 -08006421 case DFS_MKK_REGION:
6422 WMA_LOGI("%s: DFS-MKK domain", __func__);
6423 rinfo.dfsdomain = DFS_MKK_REGION;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006424 rinfo.dfs_radars = dfs_mkk4_radars;
Anurag Chouhan6d760662016-02-20 16:05:43 +05306425 rinfo.numradars = QDF_ARRAY_SIZE(dfs_mkk4_radars);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006426 rinfo.b5pulses = dfs_jpn_bin5pulses;
Anurag Chouhan6d760662016-02-20 16:05:43 +05306427 rinfo.numb5radars = QDF_ARRAY_SIZE(dfs_jpn_bin5pulses);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006428 break;
6429 default:
6430 WMA_LOGI("%s: DFS-UNINT domain", __func__);
Amar Singhala7bb01b2016-01-27 11:31:59 -08006431 rinfo.dfsdomain = DFS_UNINIT_REGION;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006432 rinfo.dfs_radars = NULL;
6433 rinfo.numradars = 0;
6434 rinfo.b5pulses = NULL;
6435 rinfo.numb5radars = 0;
6436 break;
6437 }
6438
6439 rinfo.dfs_pri_multiplier = ic->dfs_pri_multiplier;
6440
6441 /*
6442 * Set the regulatory domain,
6443 * radar pulse table and enable
6444 * radar events if required.
6445 * dfs_radar_enable() returns
6446 * 0 on success and non-zero
6447 * failure.
6448 */
6449 radar_enabled_status = dfs_radar_enable(ic, &rinfo);
6450 if (radar_enabled_status != DFS_STATUS_SUCCESS) {
6451 WMA_LOGE("%s[%d]: DFS- Radar Detection Enabling Failed",
6452 __func__, __LINE__);
6453 }
6454}
6455
6456/**
6457 * wma_dfs_configure_channel() - configure DFS channel
6458 * @dfs_ic: ieee80211com ptr
Siddarth Poddar17dc4712016-03-09 16:30:27 +05306459 * @band_center_freq1: center frequency 1
6460 * @band_center_freq2: center frequency 2
6461 * (valid only for 11ac vht 80plus80 mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006462 * @ req: vdev start request
6463 *
6464 * Set the Channel parameters in to DFS module
6465 * Also,configure the DFS radar filters for
6466 * matching the DFS phyerrors.
6467 *
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306468 * Return: dfs_ieee80211_channel / NULL for error
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006469 */
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306470struct dfs_ieee80211_channel *wma_dfs_configure_channel(
6471 struct ieee80211com *dfs_ic,
Siddarth Poddar17dc4712016-03-09 16:30:27 +05306472 uint32_t band_center_freq1,
6473 uint32_t band_center_freq2,
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306474 struct wma_vdev_start_req
6475 *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006476{
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006477 uint8_t ext_channel;
6478
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006479 if (dfs_ic == NULL) {
6480 WMA_LOGE("%s: DFS ic is Invalid", __func__);
6481 return NULL;
6482 }
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05306483
6484 if (!dfs_ic->ic_curchan) {
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306485 dfs_ic->ic_curchan = (struct dfs_ieee80211_channel *)os_malloc(
6486 NULL,
6487 sizeof(struct dfs_ieee80211_channel),
6488 GFP_ATOMIC);
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05306489 if (dfs_ic->ic_curchan == NULL) {
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306490 WMA_LOGE(
6491 "%s: allocation of dfs_ic->ic_curchan failed %zu",
6492 __func__, sizeof(struct dfs_ieee80211_channel));
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05306493 return NULL;
6494 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006495 }
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05306496
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306497 OS_MEMZERO(dfs_ic->ic_curchan, sizeof(struct dfs_ieee80211_channel));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006498
6499 dfs_ic->ic_curchan->ic_ieee = req->chan;
Siddarth Poddar17dc4712016-03-09 16:30:27 +05306500 dfs_ic->ic_curchan->ic_freq = cds_chan_to_freq(req->chan);
6501 dfs_ic->ic_curchan->ic_vhtop_ch_freq_seg1 = band_center_freq1;
6502 dfs_ic->ic_curchan->ic_vhtop_ch_freq_seg2 = band_center_freq2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006503 dfs_ic->ic_curchan->ic_pri_freq_center_freq_mhz_separation =
6504 dfs_ic->ic_curchan->ic_freq -
6505 dfs_ic->ic_curchan->ic_vhtop_ch_freq_seg1;
6506
6507 if ((dfs_ic->ic_curchan->ic_ieee >= WMA_11A_CHANNEL_BEGIN) &&
6508 (dfs_ic->ic_curchan->ic_ieee <= WMA_11A_CHANNEL_END)) {
6509 dfs_ic->ic_curchan->ic_flags |= IEEE80211_CHAN_5GHZ;
6510 }
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006511
6512 switch (req->chan_width) {
6513 case CH_WIDTH_20MHZ:
6514 dfs_ic->ic_curchan->ic_flags |=
6515 (req->vht_capable ? IEEE80211_CHAN_VHT20 :
6516 IEEE80211_CHAN_HT20);
6517 break;
6518 case CH_WIDTH_40MHZ:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006519 if (req->chan < req->ch_center_freq_seg0)
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006520 dfs_ic->ic_curchan->ic_flags |=
6521 (req->vht_capable ?
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006522 IEEE80211_CHAN_VHT40PLUS :
6523 IEEE80211_CHAN_HT40PLUS);
6524 else
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006525 dfs_ic->ic_curchan->ic_flags |=
6526 (req->vht_capable ?
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006527 IEEE80211_CHAN_VHT40MINUS :
6528 IEEE80211_CHAN_HT40MINUS);
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006529 break;
6530 case CH_WIDTH_80MHZ:
6531 dfs_ic->ic_curchan->ic_flags |= IEEE80211_CHAN_VHT80;
6532 break;
6533 case CH_WIDTH_80P80MHZ:
Siddarth Poddar17dc4712016-03-09 16:30:27 +05306534 ext_channel = cds_freq_to_chan(band_center_freq2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006535 dfs_ic->ic_curchan->ic_flags |=
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006536 IEEE80211_CHAN_VHT80P80;
6537 dfs_ic->ic_curchan->ic_freq_ext =
Siddarth Poddar17dc4712016-03-09 16:30:27 +05306538 band_center_freq2;
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006539 dfs_ic->ic_curchan->ic_ieee_ext = ext_channel;
6540
6541 /* verify both the 80MHz are DFS bands or not */
Rajeev Kumara3f6c2d2016-04-15 12:47:41 -07006542 if ((CHANNEL_STATE_DFS ==
6543 cds_get_5g_bonded_channel_state(req->chan ,
6544 CH_WIDTH_80MHZ)) &&
6545 (CHANNEL_STATE_DFS == cds_get_5g_bonded_channel_state(
6546 ext_channel - WMA_80MHZ_START_CENTER_CH_DIFF,
6547 CH_WIDTH_80MHZ)))
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006548 dfs_ic->ic_curchan->ic_80p80_both_dfs = true;
6549 break;
6550 case CH_WIDTH_160MHZ:
6551 dfs_ic->ic_curchan->ic_flags |=
6552 IEEE80211_CHAN_VHT160;
6553 break;
6554 default:
6555 WMA_LOGE(
6556 "%s: Recieved a wrong channel width %d",
6557 __func__, req->chan_width);
6558 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006559 }
Sandeep Puligillae2c9a952015-12-14 16:37:38 -08006560
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006561 dfs_ic->ic_curchan->ic_flagext |= IEEE80211_CHAN_DFS;
6562
6563 if (req->oper_mode == BSS_OPERATIONAL_MODE_AP) {
6564 dfs_ic->ic_opmode = IEEE80211_M_HOSTAP;
6565 dfs_ic->vdev_id = req->vdev_id;
6566 }
6567
6568 dfs_ic->dfs_pri_multiplier = req->dfs_pri_multiplier;
6569
6570 /*
6571 * Configuring the DFS with current channel and the radar filters
6572 */
6573 wma_dfs_configure(dfs_ic);
6574 WMA_LOGI("%s: DFS- CHANNEL CONFIGURED", __func__);
6575 return dfs_ic->ic_curchan;
6576}
6577
6578
6579/**
6580 * wma_set_dfs_region() - set DFS region
6581 * @wma: wma handle
6582 *
6583 * Configure the DFS region for DFS radar filter initialization
6584 *
6585 * Return: none
6586 */
6587void wma_set_dfs_region(tp_wma_handle wma, uint8_t dfs_region)
6588{
6589 /* dfs information is passed */
Amar Singhala7bb01b2016-01-27 11:31:59 -08006590 if (dfs_region > DFS_MKK_REGION || dfs_region == DFS_UNINIT_REGION)
6591 /* assign DFS_FCC_REGION as default region*/
6592 wma->dfs_ic->current_dfs_regdomain = DFS_FCC_REGION;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006593 else
6594 wma->dfs_ic->current_dfs_regdomain = dfs_region;
6595
6596 WMA_LOGI("%s: DFS Region Domain: %d", __func__,
6597 wma->dfs_ic->current_dfs_regdomain);
6598}
6599
6600/**
6601 * wma_get_channels() - prepare dfs radar channel list
6602 * @ichan: channel
6603 * @chan_list: return channel list
6604 *
6605 * Return: return number of channels
6606 */
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306607int wma_get_channels(struct dfs_ieee80211_channel *ichan,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006608 struct wma_dfs_radar_channel_list *chan_list)
6609{
6610 uint8_t center_chan = cds_freq_to_chan(ichan->ic_vhtop_ch_freq_seg1);
Vishwajith Upendrabf673e72016-01-19 16:05:40 -08006611 int count = 0;
6612 int start_channel = 0;
6613 int loop;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006614
6615 chan_list->nchannels = 0;
6616
Vishwajith Upendrabf673e72016-01-19 16:05:40 -08006617 if (IEEE80211_IS_CHAN_11AC_VHT160(ichan)) {
6618 /*
6619 * In 160MHz channel width, need to
6620 * check if each of the 8 20MHz channel
6621 * is DFS before adding to the NOL list.
6622 * As it is possible that part of the
6623 * 160MHz can be Non-DFS channels.
6624 */
6625 start_channel = center_chan - WMA_160MHZ_START_CENTER_CH_DIFF;
6626 for (loop = 0; loop < WMA_DFS_MAX_20M_SUB_CH; loop++) {
6627 if (cds_get_channel_state(start_channel +
6628 (loop * WMA_NEXT_20MHZ_START_CH_DIFF)) ==
6629 CHANNEL_STATE_DFS) {
6630 chan_list->channels[count] = start_channel +
6631 (loop * WMA_NEXT_20MHZ_START_CH_DIFF);
6632 count++;
6633 }
6634 }
6635 chan_list->nchannels = count;
6636 } else if (IEEE80211_IS_CHAN_11AC_VHT80P80(ichan)) {
6637 chan_list->nchannels = 4;
6638 /*
6639 * If SAP is operating in 80p80 mode, either
6640 * one of the two 80 segments or both the 80
6641 * segments can be DFS channels, so need to
6642 * identify on which 80 segment radar has
6643 * been detected and only add those channels
6644 * to the NOL list. center frequency should be
6645 * based on the segment id passed as part of
6646 * channel information in radar indication.
6647 */
6648 if (ichan->ic_radar_found_segid == DFS_80P80_SEG1)
6649 center_chan =
6650 cds_freq_to_chan(ichan->ic_vhtop_ch_freq_seg2);
6651 chan_list->channels[0] = center_chan - 6;
6652 chan_list->channels[1] = center_chan - 2;
6653 chan_list->channels[2] = center_chan + 2;
6654 chan_list->channels[3] = center_chan + 6;
6655 } else if (IEEE80211_IS_CHAN_11AC_VHT80(ichan)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006656 chan_list->nchannels = 4;
6657 chan_list->channels[0] = center_chan - 6;
6658 chan_list->channels[1] = center_chan - 2;
6659 chan_list->channels[2] = center_chan + 2;
6660 chan_list->channels[3] = center_chan + 6;
6661 } else if (IEEE80211_IS_CHAN_11N_HT40(ichan) ||
6662 IEEE80211_IS_CHAN_11AC_VHT40(ichan)) {
6663 chan_list->nchannels = 2;
6664 chan_list->channels[0] = center_chan - 2;
6665 chan_list->channels[1] = center_chan + 2;
6666 } else {
6667 chan_list->nchannels = 1;
6668 chan_list->channels[0] = center_chan;
6669 }
6670
6671 return chan_list->nchannels;
6672}
6673
6674
6675/**
6676 * wma_dfs_indicate_radar() - Indicate Radar to SAP/HDD
6677 * @ic: ieee80211com ptr
6678 * @ichan: ieee 80211 channel
6679 *
6680 * Return: 0 for success or error code
6681 */
6682int wma_dfs_indicate_radar(struct ieee80211com *ic,
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306683 struct dfs_ieee80211_channel *ichan)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006684{
6685 tp_wma_handle wma;
6686 void *hdd_ctx;
6687 struct wma_dfs_radar_indication *radar_event;
6688 struct wma_dfs_radar_ind wma_radar_event;
6689 tpAniSirGlobal pmac = NULL;
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05306690 bool indication_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006691
Anurag Chouhan6d760662016-02-20 16:05:43 +05306692 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006693 if (wma == NULL) {
6694 WMA_LOGE("%s: DFS- Invalid wma", __func__);
6695 return -ENOENT;
6696 }
6697
Anurag Chouhan6d760662016-02-20 16:05:43 +05306698 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006699 pmac = (tpAniSirGlobal)
Anurag Chouhan6d760662016-02-20 16:05:43 +05306700 cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006701
6702 if (!pmac) {
6703 WMA_LOGE("%s: Invalid MAC handle", __func__);
6704 return -ENOENT;
6705 }
6706
6707 if (wma->dfs_ic != ic) {
6708 WMA_LOGE("%s:DFS- Invalid WMA handle", __func__);
6709 return -ENOENT;
6710 }
6711 radar_event = (struct wma_dfs_radar_indication *)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306712 qdf_mem_malloc(sizeof(struct wma_dfs_radar_indication));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006713 if (radar_event == NULL) {
6714 WMA_LOGE("%s:DFS- Invalid radar_event", __func__);
6715 return -ENOMEM;
6716 }
6717
6718 /*
6719 * Do not post multiple Radar events on the same channel.
6720 * But, when DFS test mode is enabled, allow multiple dfs
6721 * radar events to be posted on the same channel.
6722 */
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306723 qdf_spin_lock_bh(&ic->chan_lock);
Edhar, Mahesh Kumar35d9b2e2015-10-26 17:06:23 +05306724 if (!pmac->sap.SapDfsInfo.disable_dfs_ch_switch)
6725 wma->dfs_ic->disable_phy_err_processing = true;
6726
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006727 if ((ichan->ic_ieee != (wma->dfs_ic->last_radar_found_chan)) ||
6728 (pmac->sap.SapDfsInfo.disable_dfs_ch_switch == true)) {
6729 wma->dfs_ic->last_radar_found_chan = ichan->ic_ieee;
6730 /* Indicate the radar event to HDD to stop the netif Tx queues */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006731 wma_radar_event.chan_freq = ichan->ic_freq;
6732 wma_radar_event.dfs_radar_status = WMA_DFS_RADAR_FOUND;
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05306733 indication_status =
6734 wma->dfs_radar_indication_cb(hdd_ctx, &wma_radar_event);
6735 if (indication_status == false) {
6736 WMA_LOGE("%s:Application triggered channel switch in progress!.. drop radar event indiaction to SAP",
6737 __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306738 qdf_mem_free(radar_event);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306739 qdf_spin_unlock_bh(&ic->chan_lock);
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05306740 return 0;
6741 }
6742
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006743 WMA_LOGE("%s:DFS- RADAR INDICATED TO HDD", __func__);
6744
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05306745 wma_radar_event.ieee_chan_number = ichan->ic_ieee;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006746 /*
6747 * Indicate to the radar event to SAP to
6748 * select a new channel and set CSA IE
6749 */
6750 radar_event->vdev_id = ic->vdev_id;
6751 wma_get_channels(ichan, &radar_event->chan_list);
6752 radar_event->dfs_radar_status = WMA_DFS_RADAR_FOUND;
6753 radar_event->use_nol = ic->ic_dfs_usenol(ic);
6754 wma_send_msg(wma, WMA_DFS_RADAR_IND, (void *)radar_event, 0);
6755 WMA_LOGE("%s:DFS- WMA_DFS_RADAR_IND Message Posted", __func__);
6756 }
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306757 qdf_spin_unlock_bh(&ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006758
6759 return 0;
6760}
6761
6762#ifdef WLAN_FEATURE_MEMDUMP
6763/*
6764 * wma_process_fw_mem_dump_req() - Function to request fw memory dump from
6765 * firmware
6766 * @wma: Pointer to WMA handle
6767 * @mem_dump_req: Pointer for mem_dump_req
6768 *
6769 * This function sends memory dump request to firmware
6770 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306771 * Return: QDF_STATUS_SUCCESS for success otherwise failure
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006772 *
6773 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306774QDF_STATUS wma_process_fw_mem_dump_req(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006775 struct fw_dump_req *mem_dump_req)
6776{
Govind Singhaa64c242016-03-08 11:31:49 +05306777 int ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006778
6779 if (!mem_dump_req || !wma) {
6780 WMA_LOGE(FL("input pointer is NULL"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306781 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006782 }
6783
Govind Singhaa64c242016-03-08 11:31:49 +05306784 ret = wmi_unified_process_fw_mem_dump_cmd(wma->wmi_handle,
6785 (struct fw_dump_req_param *) mem_dump_req);
6786 if (ret)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306787 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006788
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306789 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006790}
6791
6792/**
6793 * wma_fw_mem_dump_rsp() - send fw mem dump response to SME
6794 *
6795 * @req_id - request id.
6796 * @status - copy status from the firmware.
6797 *
6798 * This function is called by the memory dump response handler to
6799 * indicate SME that firmware dump copy is complete
6800 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306801 * Return: QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006802 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306803static QDF_STATUS wma_fw_mem_dump_rsp(uint32_t req_id, uint32_t status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006804{
6805 struct fw_dump_rsp *dump_rsp;
6806 cds_msg_t sme_msg = {0};
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306807 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006808
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306809 dump_rsp = qdf_mem_malloc(sizeof(*dump_rsp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006810
6811 if (!dump_rsp) {
6812 WMA_LOGE(FL("Memory allocation failed."));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306813 qdf_status = QDF_STATUS_E_NOMEM;
6814 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006815 }
6816
6817 WMA_LOGI(FL("FW memory dump copy complete status: %d for request: %d"),
6818 status, req_id);
6819
6820 dump_rsp->request_id = req_id;
6821 dump_rsp->dump_complete = status;
6822
6823 sme_msg.type = eWNI_SME_FW_DUMP_IND;
6824 sme_msg.bodyptr = dump_rsp;
6825 sme_msg.bodyval = 0;
6826
Anurag Chouhan6d760662016-02-20 16:05:43 +05306827 qdf_status = cds_mq_post_message(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306828 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006829 WMA_LOGE(FL("Fail to post fw mem dump ind msg"));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306830 qdf_mem_free(dump_rsp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006831 }
6832
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306833 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006834}
6835
6836/**
6837 * wma_fw_mem_dump_event_handler() - handles fw memory dump event
6838 *
6839 * @handle: pointer to wma handle.
6840 * @cmd_param_info: pointer to TLV info received in the event.
6841 * @len: length of data in @cmd_param_info
6842 *
6843 * This function is a handler for firmware memory dump event.
6844 *
6845 * Return: integer (0 for success and error code otherwise)
6846 */
6847int wma_fw_mem_dump_event_handler(void *handle, u_int8_t *cmd_param_info,
6848 u_int32_t len)
6849{
6850 WMI_UPDATE_FW_MEM_DUMP_EVENTID_param_tlvs *param_buf;
6851 wmi_update_fw_mem_dump_fixed_param *event;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306852 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006853
6854 param_buf =
6855 (WMI_UPDATE_FW_MEM_DUMP_EVENTID_param_tlvs *) cmd_param_info;
6856 if (!param_buf) {
6857 WMA_LOGA("%s: Invalid stats event", __func__);
6858 return -EINVAL;
6859 }
6860
6861 event = param_buf->fixed_param;
6862
6863 status = wma_fw_mem_dump_rsp(event->request_id,
6864 event->fw_mem_dump_complete);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306865 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006866 WMA_LOGE("Error posting FW MEM DUMP RSP.");
6867 return -EINVAL;
6868 }
6869
6870 WMA_LOGI("FW MEM DUMP RSP posted successfully");
6871 return 0;
6872}
6873#endif /* WLAN_FEATURE_MEMDUMP */
6874
6875/*
6876 * wma_process_set_ie_info() - Function to send IE info to firmware
6877 * @wma: Pointer to WMA handle
6878 * @ie_data: Pointer for ie data
6879 *
6880 * This function sends IE information to firmware
6881 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306882 * Return: QDF_STATUS_SUCCESS for success otherwise failure
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006883 *
6884 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306885QDF_STATUS wma_process_set_ie_info(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006886 struct vdev_ie_info *ie_info)
6887{
Govind Singhaa64c242016-03-08 11:31:49 +05306888 struct vdev_ie_info_param cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006889 int ret;
6890
6891 if (!ie_info || !wma) {
6892 WMA_LOGE(FL("input pointer is NULL"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306893 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006894 }
6895
6896 /* Validate the input */
6897 if (ie_info->length <= 0) {
6898 WMA_LOGE(FL("Invalid IE length"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306899 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006900 }
6901
Govind Singhaa64c242016-03-08 11:31:49 +05306902 cmd.vdev_id = ie_info->vdev_id;
6903 cmd.ie_id = ie_info->ie_id;
6904 cmd.length = ie_info->length;
6905 cmd.data = ie_info->data;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006906
Govind Singhaa64c242016-03-08 11:31:49 +05306907 ret = wmi_unified_process_set_ie_info_cmd(wma->wmi_handle,
6908 &cmd);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006909
6910 return ret;
6911}
6912
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306913/**
6914 * wma_get_bpf_caps_event_handler() - Event handler for get bpf capability
6915 * @handle: WMA global handle
6916 * @cmd_param_info: command event data
6917 * @len: Length of @cmd_param_info
6918 *
6919 * Return: 0 on Success or Errno on failure
6920 */
6921int wma_get_bpf_caps_event_handler(void *handle,
6922 u_int8_t *cmd_param_info,
6923 u_int32_t len)
6924{
6925 WMI_BPF_CAPABILIY_INFO_EVENTID_param_tlvs *param_buf;
6926 wmi_bpf_capability_info_evt_fixed_param *event;
6927 struct sir_bpf_get_offload *bpf_get_offload;
6928 tpAniSirGlobal pmac = (tpAniSirGlobal)cds_get_context(
6929 QDF_MODULE_ID_PE);
6930
6931 if (!pmac) {
6932 WMA_LOGE("%s: Invalid pmac", __func__);
6933 return -EINVAL;
6934 }
6935 if (!pmac->sme.pbpf_get_offload_cb) {
6936 WMA_LOGE("%s: Callback not registered", __func__);
6937 return -EINVAL;
6938 }
6939
6940 param_buf = (WMI_BPF_CAPABILIY_INFO_EVENTID_param_tlvs *)cmd_param_info;
6941 event = param_buf->fixed_param;
6942 bpf_get_offload = qdf_mem_malloc(sizeof(*bpf_get_offload));
6943
6944 if (!bpf_get_offload) {
6945 WMA_LOGP("%s: Memory allocation failed.", __func__);
6946 return -ENOMEM;
6947 }
6948
6949 bpf_get_offload->bpf_version = event->bpf_version;
6950 bpf_get_offload->max_bpf_filters = event->max_bpf_filters;
6951 bpf_get_offload->max_bytes_for_bpf_inst =
6952 event->max_bytes_for_bpf_inst;
6953 WMA_LOGD("%s: BPF capabilities version: %d max bpf filter size: %d",
6954 __func__, bpf_get_offload->bpf_version,
6955 bpf_get_offload->max_bytes_for_bpf_inst);
6956
6957 WMA_LOGD("%s: sending bpf capabilities event to hdd", __func__);
6958 pmac->sme.pbpf_get_offload_cb(pmac->hHdd, bpf_get_offload);
6959 qdf_mem_free(bpf_get_offload);
6960 return 0;
6961}
6962
6963/**
6964 * wma_get_bpf_capabilities - Send get bpf capability to firmware
6965 * @wma_handle: wma handle
6966 *
6967 * Return: QDF_STATUS enumeration.
6968 */
6969QDF_STATUS wma_get_bpf_capabilities(tp_wma_handle wma)
6970{
6971 QDF_STATUS status = QDF_STATUS_SUCCESS;
6972 wmi_bpf_get_capability_cmd_fixed_param *cmd;
6973 wmi_buf_t wmi_buf;
6974 uint32_t len;
6975 u_int8_t *buf_ptr;
6976
6977 if (!wma || !wma->wmi_handle) {
6978 WMA_LOGE(FL("WMA is closed, can not issue get BPF capab"));
6979 return QDF_STATUS_E_INVAL;
6980 }
6981
6982 if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
6983 WMI_SERVICE_BPF_OFFLOAD)) {
6984 WMA_LOGE(FL("BPF cababilities feature bit not enabled"));
6985 return QDF_STATUS_E_FAILURE;
6986 }
6987
6988 len = sizeof(*cmd);
6989 wmi_buf = wmi_buf_alloc(wma->wmi_handle, len);
6990 if (!wmi_buf) {
6991 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
6992 return QDF_STATUS_E_NOMEM;
6993 }
6994
6995 buf_ptr = (u_int8_t *) wmi_buf_data(wmi_buf);
6996 cmd = (wmi_bpf_get_capability_cmd_fixed_param *) buf_ptr;
6997 WMITLV_SET_HDR(&cmd->tlv_header,
6998 WMITLV_TAG_STRUC_wmi_bpf_get_capability_cmd_fixed_param,
6999 WMITLV_GET_STRUCT_TLVLEN(
7000 wmi_bpf_get_capability_cmd_fixed_param));
7001
7002 if (wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len,
7003 WMI_BPF_GET_CAPABILITY_CMDID)) {
7004 WMA_LOGE(FL("Failed to send BPF capability command"));
7005 wmi_buf_free(wmi_buf);
7006 return QDF_STATUS_E_FAILURE;
7007 }
7008 return status;
7009}
7010
7011/**
7012 * wma_set_bpf_instructions - Set bpf instructions to firmware
7013 * @wma: wma handle
7014 * @bpf_set_offload: Bpf offload information to set to firmware
7015 *
7016 * Return: QDF_STATUS enumeration
7017 */
7018QDF_STATUS wma_set_bpf_instructions(tp_wma_handle wma,
7019 struct sir_bpf_set_offload *bpf_set_offload)
7020{
7021 wmi_bpf_set_vdev_instructions_cmd_fixed_param *cmd;
7022 wmi_buf_t wmi_buf;
7023 uint32_t len = 0, len_aligned = 0;
7024 u_int8_t *buf_ptr;
7025
7026 if (!wma || !wma->wmi_handle) {
7027 WMA_LOGE("%s: WMA is closed, can not issue set BPF capability",
7028 __func__);
7029 return QDF_STATUS_E_INVAL;
7030 }
7031
7032 if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
7033 WMI_SERVICE_BPF_OFFLOAD)) {
7034 WMA_LOGE(FL("BPF offload feature Disabled"));
7035 return QDF_STATUS_E_NOSUPPORT;
7036 }
7037
7038 if (bpf_set_offload->total_length) {
7039 len_aligned = roundup(bpf_set_offload->current_length,
7040 sizeof(A_UINT32));
7041 len = len_aligned + WMI_TLV_HDR_SIZE;
7042 }
7043
7044 len += sizeof(*cmd);
7045 wmi_buf = wmi_buf_alloc(wma->wmi_handle, len);
7046 if (!wmi_buf) {
7047 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
7048 return QDF_STATUS_E_NOMEM;
7049 }
7050
7051 buf_ptr = (u_int8_t *) wmi_buf_data(wmi_buf);
7052 cmd = (wmi_bpf_set_vdev_instructions_cmd_fixed_param *) buf_ptr;
7053
7054 WMITLV_SET_HDR(&cmd->tlv_header,
7055 WMITLV_TAG_STRUC_wmi_bpf_set_vdev_instructions_cmd_fixed_param,
7056 WMITLV_GET_STRUCT_TLVLEN(
7057 wmi_bpf_set_vdev_instructions_cmd_fixed_param));
7058 cmd->vdev_id = bpf_set_offload->session_id;
7059 cmd->filter_id = bpf_set_offload->filter_id;
7060 cmd->total_length = bpf_set_offload->total_length;
7061 cmd->current_offset = bpf_set_offload->current_offset;
7062 cmd->current_length = bpf_set_offload->current_length;
7063
7064 if (bpf_set_offload->total_length) {
7065 buf_ptr +=
7066 sizeof(wmi_bpf_set_vdev_instructions_cmd_fixed_param);
7067 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, len_aligned);
7068 buf_ptr += WMI_TLV_HDR_SIZE;
7069 qdf_mem_copy(buf_ptr, bpf_set_offload->program,
7070 bpf_set_offload->current_length);
7071 qdf_mem_free(bpf_set_offload->program);
7072 }
7073
7074 if (wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len,
7075 WMI_BPF_SET_VDEV_INSTRUCTIONS_CMDID)) {
7076 WMA_LOGE(FL("Failed to send config bpf instructions command"));
7077 wmi_buf_free(wmi_buf);
7078 return QDF_STATUS_E_FAILURE;
7079 }
7080 return QDF_STATUS_SUCCESS;
7081}