blob: 42f86d0a21ec7c412723a9c55b8bf8a6b7fa63c9 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Ryan Hsuf75bd242015-12-17 12:22:02 -08002 * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
28/**
29 * DOC: wma_features.c
30 * This file contains different features related functions like WoW,
31 * Offloads, TDLS etc.
32 */
33
34/* Header files */
35
36#include "wma.h"
37#include "wma_api.h"
38#include "cds_api.h"
39#include "wmi_unified_api.h"
40#include "wlan_qct_sys.h"
41#include "wni_api.h"
42#include "ani_global.h"
43#include "wmi_unified.h"
44#include "wni_cfg.h"
45#include "cfg_api.h"
46#include "ol_txrx_ctrl_api.h"
47#include "wlan_tgt_def_config.h"
48
49#include "cdf_nbuf.h"
50#include "cdf_types.h"
51#include "ol_txrx_api.h"
52#include "cdf_memory.h"
53#include "ol_txrx_types.h"
54#include "ol_txrx_peer_find.h"
55
56#include "wma_types.h"
57#include "lim_api.h"
58#include "lim_session_utils.h"
59
60#include "cds_utils.h"
61
62#if !defined(REMOVE_PKT_LOG)
63#include "pktlog_ac.h"
64#endif /* REMOVE_PKT_LOG */
65
66#include "dbglog_host.h"
67#include "csr_api.h"
68#include "ol_fw.h"
69
70#include "dfs.h"
71#include "radar_filters.h"
72#include "wma_internal.h"
73
74#ifndef ARRAY_LENGTH
75#define ARRAY_LENGTH(a) (sizeof(a) / sizeof((a)[0]))
76#endif
77
78#define WMA_WOW_STA_WAKE_UP_EVENTS ((1 << WOW_CSA_IE_EVENT) |\
79 (1 << WOW_CLIENT_KICKOUT_EVENT) |\
80 (1 << WOW_PATTERN_MATCH_EVENT) |\
81 (1 << WOW_MAGIC_PKT_RECVD_EVENT) |\
82 (1 << WOW_DEAUTH_RECVD_EVENT) |\
83 (1 << WOW_DISASSOC_RECVD_EVENT) |\
84 (1 << WOW_BMISS_EVENT) |\
85 (1 << WOW_GTK_ERR_EVENT) |\
86 (1 << WOW_BETTER_AP_EVENT) |\
87 (1 << WOW_HTT_EVENT) |\
88 (1 << WOW_RA_MATCH_EVENT) |\
89 (1 << WOW_NLO_DETECTED_EVENT) |\
90 (1 << WOW_EXTSCAN_EVENT))\
91
92#define WMA_WOW_SAP_WAKE_UP_EVENTS ((1 << WOW_PROBE_REQ_WPS_IE_EVENT) |\
93 (1 << WOW_PATTERN_MATCH_EVENT) |\
94 (1 << WOW_AUTH_REQ_EVENT) |\
95 (1 << WOW_ASSOC_REQ_EVENT) |\
96 (1 << WOW_DEAUTH_RECVD_EVENT) |\
97 (1 << WOW_DISASSOC_RECVD_EVENT) |\
98 (1 << WOW_HTT_EVENT))\
99
100static const uint8_t arp_ptrn[] = {0x08, 0x06};
101static const uint8_t arp_mask[] = {0xff, 0xff};
102static const uint8_t ns_ptrn[] = {0x86, 0xDD};
103static const uint8_t discvr_ptrn[] = {0xe0, 0x00, 0x00, 0xf8};
104static const uint8_t discvr_mask[] = {0xf0, 0x00, 0x00, 0xf8};
105
106#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
107/**
108 * wma_post_auto_shutdown_msg() - to post auto shutdown event to sme
109 *
110 * Return: 0 for success or error code
111 */
112static int wma_post_auto_shutdown_msg(void)
113{
114 tSirAutoShutdownEvtParams *auto_sh_evt;
115 CDF_STATUS cdf_status;
116 cds_msg_t sme_msg = { 0 };
117
118 auto_sh_evt = (tSirAutoShutdownEvtParams *)
119 cdf_mem_malloc(sizeof(tSirAutoShutdownEvtParams));
120 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
131 cdf_status = cds_mq_post_message(CDF_MODULE_ID_SME, &sme_msg);
132 if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
133 WMA_LOGE("Fail to post eWNI_SME_AUTO_SHUTDOWN_IND msg to SME");
134 cdf_mem_free(auto_sh_evt);
135 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 *
146 * Return: CDF status
147 */
148CDF_STATUS wma_send_snr_request(tp_wma_handle wma_handle,
149 void *pGetRssiReq)
150{
151 wmi_buf_t buf;
152 wmi_request_stats_cmd_fixed_param *cmd;
153 uint8_t len = sizeof(wmi_request_stats_cmd_fixed_param);
154 tAniGetRssiReq *pRssiBkUp = NULL;
155
156 /* command is in progess */
157 if (NULL != wma_handle->pGetRssiReq)
158 return CDF_STATUS_SUCCESS;
159
160 /* create a copy of csrRssiCallback to send rssi value
161 * after wmi event
162 */
163 if (pGetRssiReq) {
164 pRssiBkUp = cdf_mem_malloc(sizeof(tAniGetRssiReq));
165 if (!pRssiBkUp) {
166 WMA_LOGE("Failed to allocate memory for tAniGetRssiReq");
167 wma_handle->pGetRssiReq = NULL;
168 return CDF_STATUS_E_NOMEM;
169 }
170 cdf_mem_set(pRssiBkUp, sizeof(tAniGetRssiReq), 0);
171 pRssiBkUp->sessionId =
172 ((tAniGetRssiReq *) pGetRssiReq)->sessionId;
173 pRssiBkUp->rssiCallback =
174 ((tAniGetRssiReq *) pGetRssiReq)->rssiCallback;
175 pRssiBkUp->pDevContext =
176 ((tAniGetRssiReq *) pGetRssiReq)->pDevContext;
177 wma_handle->pGetRssiReq = (void *)pRssiBkUp;
178 }
179
180 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
181 if (!buf) {
182 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
183 cdf_mem_free(pRssiBkUp);
184 wma_handle->pGetRssiReq = NULL;
185 return CDF_STATUS_E_FAILURE;
186 }
187
188 cmd = (wmi_request_stats_cmd_fixed_param *) wmi_buf_data(buf);
189 WMITLV_SET_HDR(&cmd->tlv_header,
190 WMITLV_TAG_STRUC_wmi_request_stats_cmd_fixed_param,
191 WMITLV_GET_STRUCT_TLVLEN
192 (wmi_request_stats_cmd_fixed_param));
193 cmd->stats_id = WMI_REQUEST_VDEV_STAT;
194 if (wmi_unified_cmd_send
195 (wma_handle->wmi_handle, buf, len, WMI_REQUEST_STATS_CMDID)) {
196 WMA_LOGE("Failed to send host stats request to fw");
197 wmi_buf_free(buf);
198 cdf_mem_free(pRssiBkUp);
199 wma_handle->pGetRssiReq = NULL;
200 return CDF_STATUS_E_FAILURE;
201 }
202 return CDF_STATUS_SUCCESS;
203}
204
205/**
206 * wma_get_snr() - get RSSI from fw
207 * @psnr_req: request params
208 *
209 * Return: CDF status
210 */
211CDF_STATUS wma_get_snr(tAniGetSnrReq *psnr_req)
212{
213 wmi_buf_t buf;
214 wmi_request_stats_cmd_fixed_param *cmd;
215 tAniGetSnrReq *psnr_req_bkp;
216 uint8_t len = sizeof(wmi_request_stats_cmd_fixed_param);
217 tp_wma_handle wma_handle = NULL;
218 struct wma_txrx_node *intr;
219
220 wma_handle = cds_get_context(CDF_MODULE_ID_WMA);
221
222 if (NULL == wma_handle) {
223 WMA_LOGE("%s : Failed to get wma_handle", __func__);
224 return CDF_STATUS_E_FAULT;
225 }
226
227 intr = &wma_handle->interfaces[psnr_req->sessionId];
228 /* command is in progess */
229 if (NULL != intr->psnr_req) {
230 WMA_LOGE("%s : previous snr request is pending", __func__);
231 return CDF_STATUS_SUCCESS;
232 }
233
234 psnr_req_bkp = cdf_mem_malloc(sizeof(tAniGetSnrReq));
235 if (!psnr_req_bkp) {
236 WMA_LOGE("Failed to allocate memory for tAniGetSnrReq");
237 return CDF_STATUS_E_NOMEM;
238 }
239
240 cdf_mem_set(psnr_req_bkp, sizeof(tAniGetSnrReq), 0);
241 psnr_req_bkp->staId = psnr_req->staId;
242 psnr_req_bkp->pDevContext = psnr_req->pDevContext;
243 psnr_req_bkp->snrCallback = psnr_req->snrCallback;
244 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
245 if (!buf) {
246 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
247 cdf_mem_free(psnr_req_bkp);
248 return CDF_STATUS_E_FAILURE;
249 }
250
251 cmd = (wmi_request_stats_cmd_fixed_param *) wmi_buf_data(buf);
252 cmd->vdev_id = psnr_req->sessionId;
253
254 WMITLV_SET_HDR(&cmd->tlv_header,
255 WMITLV_TAG_STRUC_wmi_request_stats_cmd_fixed_param,
256 WMITLV_GET_STRUCT_TLVLEN
257 (wmi_request_stats_cmd_fixed_param));
258 cmd->stats_id = WMI_REQUEST_VDEV_STAT;
259 intr->psnr_req = (void *)psnr_req_bkp;
260 if (wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len,
261 WMI_REQUEST_STATS_CMDID)) {
262 WMA_LOGE("Failed to send host stats request to fw");
263 wmi_buf_free(buf);
264 cdf_mem_free(psnr_req_bkp);
265 intr->psnr_req = NULL;
266 return CDF_STATUS_E_FAILURE;
267 }
268
269 return CDF_STATUS_SUCCESS;
270}
271
272/**
273 * wma_process_link_status_req() - process link status request from UMAC
274 * @wma: wma handle
275 * @pGetLinkStatus: get link params
276 *
277 * Return: none
278 */
279void wma_process_link_status_req(tp_wma_handle wma,
280 tAniGetLinkStatus *pGetLinkStatus)
281{
282 wmi_buf_t buf;
283 wmi_request_stats_cmd_fixed_param *cmd;
284 uint8_t len = sizeof(wmi_request_stats_cmd_fixed_param);
285 struct wma_txrx_node *iface =
286 &wma->interfaces[pGetLinkStatus->sessionId];
287
288 if (iface->plink_status_req) {
289 WMA_LOGE("%s:previous link status request is pending,deleting the new request",
290 __func__);
291 cdf_mem_free(pGetLinkStatus);
292 return;
293 }
294
295 buf = wmi_buf_alloc(wma->wmi_handle, len);
296 if (!buf) {
297 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
298 goto end;
299 }
300
301 iface->plink_status_req = pGetLinkStatus;
302 cmd = (wmi_request_stats_cmd_fixed_param *) wmi_buf_data(buf);
303 WMITLV_SET_HDR(&cmd->tlv_header,
304 WMITLV_TAG_STRUC_wmi_request_stats_cmd_fixed_param,
305 WMITLV_GET_STRUCT_TLVLEN
306 (wmi_request_stats_cmd_fixed_param));
307 cmd->stats_id = WMI_REQUEST_VDEV_RATE_STAT;
308 cmd->vdev_id = pGetLinkStatus->sessionId;
309 if (wmi_unified_cmd_send(wma->wmi_handle, buf, len,
310 WMI_REQUEST_STATS_CMDID)) {
311 WMA_LOGE("Failed to send WMI link status request to fw");
312 wmi_buf_free(buf);
313 iface->plink_status_req = NULL;
314 goto end;
315 }
316
317 return;
318
319end:
320 wma_post_link_status(pGetLinkStatus, LINK_STATUS_LEGACY);
321}
322
323#ifdef FEATURE_WLAN_LPHB
324/**
325 * wma_lphb_conf_hbenable() - enable command of LPHB configuration requests
326 * @wma_handle: WMA handle
327 * @lphb_conf_req: configuration info
328 * @by_user: whether this call is from user or cached resent
329 *
330 * Return: CDF status
331 */
332CDF_STATUS wma_lphb_conf_hbenable(tp_wma_handle wma_handle,
333 tSirLPHBReq *lphb_conf_req, bool by_user)
334{
335 CDF_STATUS cdf_status = CDF_STATUS_SUCCESS;
336 int status = 0;
337 tSirLPHBEnableStruct *ts_lphb_enable;
338 wmi_buf_t buf = NULL;
339 uint8_t *buf_ptr;
340 wmi_hb_set_enable_cmd_fixed_param *hb_enable_fp;
341 int len = sizeof(wmi_hb_set_enable_cmd_fixed_param);
342 int i;
343
344 if (lphb_conf_req == NULL) {
345 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
346 return CDF_STATUS_E_FAILURE;
347 }
348
349 ts_lphb_enable = &(lphb_conf_req->params.lphbEnableReq);
350 WMA_LOGI("%s: WMA --> WMI_HB_SET_ENABLE enable=%d, item=%d, session=%d",
351 __func__,
352 ts_lphb_enable->enable,
353 ts_lphb_enable->item, ts_lphb_enable->session);
354
355 if ((ts_lphb_enable->item != 1) && (ts_lphb_enable->item != 2)) {
356 WMA_LOGE("%s : LPHB configuration wrong item %d",
357 __func__, ts_lphb_enable->item);
358 return CDF_STATUS_E_FAILURE;
359 }
360
361 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
362 if (!buf) {
363 WMA_LOGE("%s : wmi_buf_alloc failed", __func__);
364 return CDF_STATUS_E_NOMEM;
365 }
366
367 buf_ptr = (uint8_t *) wmi_buf_data(buf);
368 hb_enable_fp = (wmi_hb_set_enable_cmd_fixed_param *) buf_ptr;
369 WMITLV_SET_HDR(&hb_enable_fp->tlv_header,
370 WMITLV_TAG_STRUC_wmi_hb_set_enable_cmd_fixed_param,
371 WMITLV_GET_STRUCT_TLVLEN
372 (wmi_hb_set_enable_cmd_fixed_param));
373
374 /* fill in values */
375 hb_enable_fp->vdev_id = ts_lphb_enable->session;
376 hb_enable_fp->enable = ts_lphb_enable->enable;
377 hb_enable_fp->item = ts_lphb_enable->item;
378 hb_enable_fp->session = ts_lphb_enable->session;
379
380 status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf,
381 len, WMI_HB_SET_ENABLE_CMDID);
382 if (status != EOK) {
383 WMA_LOGE("wmi_unified_cmd_send WMI_HB_SET_ENABLE returned Error %d",
384 status);
385 cdf_status = CDF_STATUS_E_FAILURE;
386 goto error;
387 }
388
389 if (by_user) {
390 /* target already configured, now cache command status */
391 if (ts_lphb_enable->enable) {
392 i = ts_lphb_enable->item - 1;
393 wma_handle->wow.lphb_cache[i].cmd
394 = LPHB_SET_EN_PARAMS_INDID;
395 wma_handle->wow.lphb_cache[i].params.lphbEnableReq.
396 enable = ts_lphb_enable->enable;
397 wma_handle->wow.lphb_cache[i].params.lphbEnableReq.
398 item = ts_lphb_enable->item;
399 wma_handle->wow.lphb_cache[i].params.lphbEnableReq.
400 session = ts_lphb_enable->session;
401
402 WMA_LOGI("%s: cached LPHB status in WMA context for item %d",
403 __func__, i);
404 } else {
405 cdf_mem_zero((void *)&wma_handle->wow.lphb_cache,
406 sizeof(wma_handle->wow.lphb_cache));
407 WMA_LOGI("%s: cleared all cached LPHB status in WMA context",
408 __func__);
409 }
410 }
411
412 return CDF_STATUS_SUCCESS;
413error:
414 return cdf_status;
415}
416
417/**
418 * wma_lphb_conf_tcp_params() - set tcp params of LPHB configuration requests
419 * @wma_handle: wma handle
420 * @lphb_conf_req: lphb config request
421 *
422 * Return: CDF status
423 */
424CDF_STATUS wma_lphb_conf_tcp_params(tp_wma_handle wma_handle,
425 tSirLPHBReq *lphb_conf_req)
426{
427 CDF_STATUS cdf_status = CDF_STATUS_SUCCESS;
428 int status = 0;
429 tSirLPHBTcpParamStruct *ts_lphb_tcp_param;
430 wmi_buf_t buf = NULL;
431 uint8_t *buf_ptr;
432 wmi_hb_set_tcp_params_cmd_fixed_param *hb_tcp_params_fp;
433 int len = sizeof(wmi_hb_set_tcp_params_cmd_fixed_param);
434
435 if (lphb_conf_req == NULL) {
436 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
437 return CDF_STATUS_E_FAILURE;
438 }
439
440 ts_lphb_tcp_param = &(lphb_conf_req->params.lphbTcpParamReq);
Srinivas Girigowda9dc32cf2015-11-19 14:47:04 -0800441 WMA_LOGI("%s: WMA --> WMI_HB_SET_TCP_PARAMS srv_ip=%08x, "
442 "dev_ip=%08x, src_port=%d, dst_port=%d, timeout=%d, "
443 "session=%d, gateway_mac="MAC_ADDRESS_STR", timePeriodSec=%d, "
444 "tcpSn=%d", __func__, ts_lphb_tcp_param->srv_ip,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800445 ts_lphb_tcp_param->dev_ip, ts_lphb_tcp_param->src_port,
446 ts_lphb_tcp_param->dst_port, ts_lphb_tcp_param->timeout,
Srinivas Girigowda9dc32cf2015-11-19 14:47:04 -0800447 ts_lphb_tcp_param->session,
448 MAC_ADDR_ARRAY(ts_lphb_tcp_param->gateway_mac.bytes),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800449 ts_lphb_tcp_param->timePeriodSec, ts_lphb_tcp_param->tcpSn);
450
451 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
452 if (!buf) {
453 WMA_LOGE("%s : wmi_buf_alloc failed", __func__);
454 return CDF_STATUS_E_NOMEM;
455 }
456
457 buf_ptr = (uint8_t *) wmi_buf_data(buf);
458 hb_tcp_params_fp = (wmi_hb_set_tcp_params_cmd_fixed_param *) buf_ptr;
459 WMITLV_SET_HDR(&hb_tcp_params_fp->tlv_header,
460 WMITLV_TAG_STRUC_wmi_hb_set_tcp_params_cmd_fixed_param,
461 WMITLV_GET_STRUCT_TLVLEN
462 (wmi_hb_set_tcp_params_cmd_fixed_param));
463
464 /* fill in values */
465 hb_tcp_params_fp->vdev_id = ts_lphb_tcp_param->session;
466 hb_tcp_params_fp->srv_ip = ts_lphb_tcp_param->srv_ip;
467 hb_tcp_params_fp->dev_ip = ts_lphb_tcp_param->dev_ip;
468 hb_tcp_params_fp->seq = ts_lphb_tcp_param->tcpSn;
469 hb_tcp_params_fp->src_port = ts_lphb_tcp_param->src_port;
470 hb_tcp_params_fp->dst_port = ts_lphb_tcp_param->dst_port;
471 hb_tcp_params_fp->interval = ts_lphb_tcp_param->timePeriodSec;
472 hb_tcp_params_fp->timeout = ts_lphb_tcp_param->timeout;
473 hb_tcp_params_fp->session = ts_lphb_tcp_param->session;
Srinivas Girigowda9dc32cf2015-11-19 14:47:04 -0800474 WMI_CHAR_ARRAY_TO_MAC_ADDR(ts_lphb_tcp_param->gateway_mac.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800475 &hb_tcp_params_fp->gateway_mac);
476
477 status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf,
478 len, WMI_HB_SET_TCP_PARAMS_CMDID);
479 if (status != EOK) {
480 WMA_LOGE("wmi_unified_cmd_send WMI_HB_SET_TCP_PARAMS returned Error %d",
481 status);
482 cdf_status = CDF_STATUS_E_FAILURE;
483 goto error;
484 }
485
486 return CDF_STATUS_SUCCESS;
487error:
488 return cdf_status;
489}
490
491/**
492 * wma_lphb_conf_tcp_pkt_filter() - configure tcp packet filter command of LPHB
493 * @wma_handle: wma handle
494 * @lphb_conf_req: lphb config request
495 *
496 * Return: CDF status
497 */
498CDF_STATUS wma_lphb_conf_tcp_pkt_filter(tp_wma_handle wma_handle,
499 tSirLPHBReq *lphb_conf_req)
500{
501 CDF_STATUS cdf_status = CDF_STATUS_SUCCESS;
502 int status = 0;
503 tSirLPHBTcpFilterStruct *ts_lphb_tcp_filter;
504 wmi_buf_t buf = NULL;
505 uint8_t *buf_ptr;
506 wmi_hb_set_tcp_pkt_filter_cmd_fixed_param *hb_tcp_filter_fp;
507 int len = sizeof(wmi_hb_set_tcp_pkt_filter_cmd_fixed_param);
508
509 if (lphb_conf_req == NULL) {
510 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
511 return CDF_STATUS_E_FAILURE;
512 }
513
514 ts_lphb_tcp_filter = &(lphb_conf_req->params.lphbTcpFilterReq);
515 WMA_LOGI("%s: WMA --> WMI_HB_SET_TCP_PKT_FILTER length=%d, offset=%d, session=%d, "
516 "filter=%2x:%2x:%2x:%2x:%2x:%2x ...", __func__,
517 ts_lphb_tcp_filter->length, ts_lphb_tcp_filter->offset,
518 ts_lphb_tcp_filter->session, ts_lphb_tcp_filter->filter[0],
519 ts_lphb_tcp_filter->filter[1], ts_lphb_tcp_filter->filter[2],
520 ts_lphb_tcp_filter->filter[3], ts_lphb_tcp_filter->filter[4],
521 ts_lphb_tcp_filter->filter[5]);
522
523 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
524 if (!buf) {
525 WMA_LOGE("%s : wmi_buf_alloc failed", __func__);
526 return CDF_STATUS_E_NOMEM;
527 }
528
529 buf_ptr = (uint8_t *) wmi_buf_data(buf);
530 hb_tcp_filter_fp =
531 (wmi_hb_set_tcp_pkt_filter_cmd_fixed_param *) buf_ptr;
532 WMITLV_SET_HDR(&hb_tcp_filter_fp->tlv_header,
533 WMITLV_TAG_STRUC_wmi_hb_set_tcp_pkt_filter_cmd_fixed_param,
534 WMITLV_GET_STRUCT_TLVLEN
535 (wmi_hb_set_tcp_pkt_filter_cmd_fixed_param));
536
537 /* fill in values */
538 hb_tcp_filter_fp->vdev_id = ts_lphb_tcp_filter->session;
539 hb_tcp_filter_fp->length = ts_lphb_tcp_filter->length;
540 hb_tcp_filter_fp->offset = ts_lphb_tcp_filter->offset;
541 hb_tcp_filter_fp->session = ts_lphb_tcp_filter->session;
542 memcpy((void *)&hb_tcp_filter_fp->filter,
543 (void *)&ts_lphb_tcp_filter->filter,
544 WMI_WLAN_HB_MAX_FILTER_SIZE);
545
546 status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf,
547 len, WMI_HB_SET_TCP_PKT_FILTER_CMDID);
548 if (status != EOK) {
549 WMA_LOGE("wmi_unified_cmd_send WMI_HB_SET_TCP_PKT_FILTER returned Error %d",
550 status);
551 cdf_status = CDF_STATUS_E_FAILURE;
552 goto error;
553 }
554
555 return CDF_STATUS_SUCCESS;
556error:
557 return cdf_status;
558}
559
560/**
561 * wma_lphb_conf_udp_params() - configure udp param command of LPHB
562 * @wma_handle: wma handle
563 * @lphb_conf_req: lphb config request
564 *
565 * Return: CDF status
566 */
567CDF_STATUS wma_lphb_conf_udp_params(tp_wma_handle wma_handle,
568 tSirLPHBReq *lphb_conf_req)
569{
570 CDF_STATUS cdf_status = CDF_STATUS_SUCCESS;
571 int status = 0;
572 tSirLPHBUdpParamStruct *ts_lphb_udp_param;
573 wmi_buf_t buf = NULL;
574 uint8_t *buf_ptr;
575 wmi_hb_set_udp_params_cmd_fixed_param *hb_udp_params_fp;
576 int len = sizeof(wmi_hb_set_udp_params_cmd_fixed_param);
577
578 if (lphb_conf_req == NULL) {
579 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
580 return CDF_STATUS_E_FAILURE;
581 }
582
583 ts_lphb_udp_param = &(lphb_conf_req->params.lphbUdpParamReq);
584 WMA_LOGI("%s: WMA --> WMI_HB_SET_UDP_PARAMS srv_ip=%d, dev_ip=%d, src_port=%d, "
585 "dst_port=%d, interval=%d, timeout=%d, session=%d, "
Srinivas Girigowda9eddfda2015-11-19 14:38:02 -0800586 "gateway_mac="MAC_ADDRESS_STR, __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800587 ts_lphb_udp_param->srv_ip, ts_lphb_udp_param->dev_ip,
588 ts_lphb_udp_param->src_port, ts_lphb_udp_param->dst_port,
589 ts_lphb_udp_param->interval, ts_lphb_udp_param->timeout,
Srinivas Girigowda9eddfda2015-11-19 14:38:02 -0800590 ts_lphb_udp_param->session,
591 MAC_ADDR_ARRAY(ts_lphb_udp_param->gateway_mac.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800592
593 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
594 if (!buf) {
595 WMA_LOGE("%s : wmi_buf_alloc failed", __func__);
596 return CDF_STATUS_E_NOMEM;
597 }
598
599 buf_ptr = (uint8_t *) wmi_buf_data(buf);
600 hb_udp_params_fp = (wmi_hb_set_udp_params_cmd_fixed_param *) buf_ptr;
601 WMITLV_SET_HDR(&hb_udp_params_fp->tlv_header,
602 WMITLV_TAG_STRUC_wmi_hb_set_udp_params_cmd_fixed_param,
603 WMITLV_GET_STRUCT_TLVLEN
604 (wmi_hb_set_udp_params_cmd_fixed_param));
605
606 /* fill in values */
607 hb_udp_params_fp->vdev_id = ts_lphb_udp_param->session;
608 hb_udp_params_fp->srv_ip = ts_lphb_udp_param->srv_ip;
609 hb_udp_params_fp->dev_ip = ts_lphb_udp_param->dev_ip;
610 hb_udp_params_fp->src_port = ts_lphb_udp_param->src_port;
611 hb_udp_params_fp->dst_port = ts_lphb_udp_param->dst_port;
612 hb_udp_params_fp->interval = ts_lphb_udp_param->interval;
613 hb_udp_params_fp->timeout = ts_lphb_udp_param->timeout;
614 hb_udp_params_fp->session = ts_lphb_udp_param->session;
Srinivas Girigowda9eddfda2015-11-19 14:38:02 -0800615 WMI_CHAR_ARRAY_TO_MAC_ADDR(ts_lphb_udp_param->gateway_mac.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800616 &hb_udp_params_fp->gateway_mac);
617
618 status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf,
619 len, WMI_HB_SET_UDP_PARAMS_CMDID);
620 if (status != EOK) {
621 WMA_LOGE("wmi_unified_cmd_send WMI_HB_SET_UDP_PARAMS returned Error %d",
622 status);
623 cdf_status = CDF_STATUS_E_FAILURE;
624 goto error;
625 }
626
627 return CDF_STATUS_SUCCESS;
628error:
629 return cdf_status;
630}
631
632/**
633 * wma_lphb_conf_udp_pkt_filter() - configure udp pkt filter command of LPHB
634 * @wma_handle: wma handle
635 * @lphb_conf_req: lphb config request
636 *
637 * Return: CDF status
638 */
639CDF_STATUS wma_lphb_conf_udp_pkt_filter(tp_wma_handle wma_handle,
640 tSirLPHBReq *lphb_conf_req)
641{
642 CDF_STATUS cdf_status = CDF_STATUS_SUCCESS;
643 int status = 0;
644 tSirLPHBUdpFilterStruct *ts_lphb_udp_filter;
645 wmi_buf_t buf = NULL;
646 uint8_t *buf_ptr;
647 wmi_hb_set_udp_pkt_filter_cmd_fixed_param *hb_udp_filter_fp;
648 int len = sizeof(wmi_hb_set_udp_pkt_filter_cmd_fixed_param);
649
650 if (lphb_conf_req == NULL) {
651 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
652 return CDF_STATUS_E_FAILURE;
653 }
654
655 ts_lphb_udp_filter = &(lphb_conf_req->params.lphbUdpFilterReq);
656 WMA_LOGI("%s: WMA --> WMI_HB_SET_UDP_PKT_FILTER length=%d, offset=%d, session=%d, "
657 "filter=%2x:%2x:%2x:%2x:%2x:%2x ...", __func__,
658 ts_lphb_udp_filter->length, ts_lphb_udp_filter->offset,
659 ts_lphb_udp_filter->session, ts_lphb_udp_filter->filter[0],
660 ts_lphb_udp_filter->filter[1], ts_lphb_udp_filter->filter[2],
661 ts_lphb_udp_filter->filter[3], ts_lphb_udp_filter->filter[4],
662 ts_lphb_udp_filter->filter[5]);
663
664 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
665 if (!buf) {
666 WMA_LOGE("%s : wmi_buf_alloc failed", __func__);
667 return CDF_STATUS_E_NOMEM;
668 }
669
670 buf_ptr = (uint8_t *) wmi_buf_data(buf);
671 hb_udp_filter_fp =
672 (wmi_hb_set_udp_pkt_filter_cmd_fixed_param *) buf_ptr;
673 WMITLV_SET_HDR(&hb_udp_filter_fp->tlv_header,
674 WMITLV_TAG_STRUC_wmi_hb_set_udp_pkt_filter_cmd_fixed_param,
675 WMITLV_GET_STRUCT_TLVLEN
676 (wmi_hb_set_udp_pkt_filter_cmd_fixed_param));
677
678 /* fill in values */
679 hb_udp_filter_fp->vdev_id = ts_lphb_udp_filter->session;
680 hb_udp_filter_fp->length = ts_lphb_udp_filter->length;
681 hb_udp_filter_fp->offset = ts_lphb_udp_filter->offset;
682 hb_udp_filter_fp->session = ts_lphb_udp_filter->session;
683 memcpy((void *)&hb_udp_filter_fp->filter,
684 (void *)&ts_lphb_udp_filter->filter,
685 WMI_WLAN_HB_MAX_FILTER_SIZE);
686
687 status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf,
688 len, WMI_HB_SET_UDP_PKT_FILTER_CMDID);
689 if (status != EOK) {
690 WMA_LOGE("wmi_unified_cmd_send WMI_HB_SET_UDP_PKT_FILTER returned Error %d",
691 status);
692 cdf_status = CDF_STATUS_E_FAILURE;
693 goto error;
694 }
695
696 return CDF_STATUS_SUCCESS;
697error:
698 return cdf_status;
699}
700
701/**
702 * wma_process_lphb_conf_req() - handle LPHB configuration requests
703 * @wma_handle: wma handle
704 * @lphb_conf_req: lphb config request
705 *
706 * Return: CDF status
707 */
708CDF_STATUS wma_process_lphb_conf_req(tp_wma_handle wma_handle,
709 tSirLPHBReq *lphb_conf_req)
710{
711 CDF_STATUS cdf_status = CDF_STATUS_SUCCESS;
712
713 if (lphb_conf_req == NULL) {
714 WMA_LOGE("%s : LPHB configuration is NULL", __func__);
715 return CDF_STATUS_E_FAILURE;
716 }
717
718 WMA_LOGI("%s : LPHB configuration cmd id is %d", __func__,
719 lphb_conf_req->cmd);
720 switch (lphb_conf_req->cmd) {
721 case LPHB_SET_EN_PARAMS_INDID:
722 cdf_status = wma_lphb_conf_hbenable(wma_handle,
723 lphb_conf_req, true);
724 break;
725
726 case LPHB_SET_TCP_PARAMS_INDID:
727 cdf_status = wma_lphb_conf_tcp_params(wma_handle,
728 lphb_conf_req);
729 break;
730
731 case LPHB_SET_TCP_PKT_FILTER_INDID:
732 cdf_status = wma_lphb_conf_tcp_pkt_filter(wma_handle,
733 lphb_conf_req);
734 break;
735
736 case LPHB_SET_UDP_PARAMS_INDID:
737 cdf_status = wma_lphb_conf_udp_params(wma_handle,
738 lphb_conf_req);
739 break;
740
741 case LPHB_SET_UDP_PKT_FILTER_INDID:
742 cdf_status = wma_lphb_conf_udp_pkt_filter(wma_handle,
743 lphb_conf_req);
744 break;
745
746 case LPHB_SET_NETWORK_INFO_INDID:
747 default:
748 break;
749 }
750
751 cdf_mem_free(lphb_conf_req);
752 return cdf_status;
753}
754#endif /* FEATURE_WLAN_LPHB */
755
756/**
757 * wma_process_dhcp_ind() - process dhcp indication from SME
758 * @wma_handle: wma handle
759 * @ta_dhcp_ind: DHCP indication
760 *
761 * Return: CDF Status
762 */
763CDF_STATUS wma_process_dhcp_ind(tp_wma_handle wma_handle,
764 tAniDHCPInd *ta_dhcp_ind)
765{
766 uint8_t vdev_id;
767 int status = 0;
768 wmi_buf_t buf = NULL;
769 uint8_t *buf_ptr;
770 wmi_peer_set_param_cmd_fixed_param *peer_set_param_fp;
771 int len = sizeof(wmi_peer_set_param_cmd_fixed_param);
772
773 if (!ta_dhcp_ind) {
774 WMA_LOGE("%s : DHCP indication is NULL", __func__);
775 return CDF_STATUS_E_FAILURE;
776 }
777
Srinivas Girigowda296105a2015-09-24 16:31:16 -0700778 if (!wma_find_vdev_by_addr(wma_handle,
779 ta_dhcp_ind->adapterMacAddr.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800780 &vdev_id)) {
781 WMA_LOGE("%s: Failed to find vdev id for DHCP indication",
782 __func__);
783 return CDF_STATUS_E_FAILURE;
784 }
785
786 WMA_LOGI("%s: WMA --> WMI_PEER_SET_PARAM triggered by DHCP, "
787 "msgType=%s,"
788 "device_mode=%d, macAddr=" MAC_ADDRESS_STR,
789 __func__,
790 ta_dhcp_ind->msgType == WMA_DHCP_START_IND ?
791 "WMA_DHCP_START_IND" : "WMA_DHCP_STOP_IND",
792 ta_dhcp_ind->device_mode,
Srinivas Girigowda296105a2015-09-24 16:31:16 -0700793 MAC_ADDR_ARRAY(ta_dhcp_ind->peerMacAddr.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800794
795 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
796 if (!buf) {
797 WMA_LOGE("%s : wmi_buf_alloc failed", __func__);
798 return CDF_STATUS_E_NOMEM;
799 }
800
801 buf_ptr = (uint8_t *) wmi_buf_data(buf);
802 peer_set_param_fp = (wmi_peer_set_param_cmd_fixed_param *) buf_ptr;
803 WMITLV_SET_HDR(&peer_set_param_fp->tlv_header,
804 WMITLV_TAG_STRUC_wmi_peer_set_param_cmd_fixed_param,
805 WMITLV_GET_STRUCT_TLVLEN
806 (wmi_peer_set_param_cmd_fixed_param));
807
808 /* fill in values */
809 peer_set_param_fp->vdev_id = vdev_id;
810 peer_set_param_fp->param_id = WMI_PEER_CRIT_PROTO_HINT_ENABLED;
811 if (WMA_DHCP_START_IND == ta_dhcp_ind->msgType)
812 peer_set_param_fp->param_value = 1;
813 else
814 peer_set_param_fp->param_value = 0;
Srinivas Girigowda296105a2015-09-24 16:31:16 -0700815 WMI_CHAR_ARRAY_TO_MAC_ADDR(ta_dhcp_ind->peerMacAddr.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800816 &peer_set_param_fp->peer_macaddr);
817
818 status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf,
819 len, WMI_PEER_SET_PARAM_CMDID);
820 if (status != EOK) {
821 WMA_LOGE("%s: wmi_unified_cmd_send WMI_PEER_SET_PARAM_CMD"
822 " returned Error %d", __func__, status);
823 return CDF_STATUS_E_FAILURE;
824 }
825
826 return CDF_STATUS_SUCCESS;
827}
828
829/**
830 * wma_chan_to_mode() - convert channel to phy mode
831 * @chan: channel number
832 * @chan_width: channel width
833 * @vht_capable: vht capable
834 * @dot11_mode: 802.11 mode
835 *
836 * Return: return phy mode
837 */
838WLAN_PHY_MODE wma_chan_to_mode(u8 chan, phy_ch_width chan_width,
839 u8 vht_capable, u8 dot11_mode)
840{
841 WLAN_PHY_MODE phymode = MODE_UNKNOWN;
842
843 /* 2.4 GHz band */
844 if ((chan >= WMA_11G_CHANNEL_BEGIN) && (chan <= WMA_11G_CHANNEL_END)) {
845 switch (chan_width) {
846 case CH_WIDTH_20MHZ:
847 /* In case of no channel bonding, use dot11_mode
848 * to set phy mode
849 */
850 switch (dot11_mode) {
851 case WNI_CFG_DOT11_MODE_11A:
852 phymode = MODE_11A;
853 break;
854 case WNI_CFG_DOT11_MODE_11B:
855 phymode = MODE_11B;
856 break;
857 case WNI_CFG_DOT11_MODE_11G:
858 phymode = MODE_11G;
859 break;
860 case WNI_CFG_DOT11_MODE_11G_ONLY:
861 phymode = MODE_11GONLY;
862 break;
863 default:
864 /* Configure MODE_11NG_HT20 for
865 * self vdev(for vht too)
866 */
867 phymode = MODE_11NG_HT20;
868 break;
869 }
870 break;
871 case CH_WIDTH_40MHZ:
872 phymode = vht_capable ? MODE_11AC_VHT40 :
873 MODE_11NG_HT40;
874 break;
875 default:
876 break;
877 }
878 }
879
880 /* 5 GHz band */
881 if ((chan >= WMA_11A_CHANNEL_BEGIN) && (chan <= WMA_11A_CHANNEL_END)) {
882 switch (chan_width) {
883 case CH_WIDTH_20MHZ:
884 phymode = vht_capable ? MODE_11AC_VHT20 :
885 MODE_11NA_HT20;
886 break;
887 case CH_WIDTH_40MHZ:
888 phymode = vht_capable ? MODE_11AC_VHT40 :
889 MODE_11NA_HT40;
890 break;
891 case CH_WIDTH_80MHZ:
892 phymode = MODE_11AC_VHT80;
893 break;
894#if CONFIG_160MHZ_SUPPORT != 0
895 case CH_WIDTH_160MHZ:
896 phymode = MODE_11AC_VHT160;
897 break;
898 case CH_WIDTH_80P80MHZ:
899 phymode = MODE_11AC_VHT80_80;
900 break;
901#endif
902
903 default:
904 break;
905 }
906 }
907
908 /* 5.9 GHz Band */
909 if ((chan >= WMA_11P_CHANNEL_BEGIN) && (chan <= WMA_11P_CHANNEL_END))
910 /* Only Legacy Modulation Schemes are supported */
911 phymode = MODE_11A;
912
913 WMA_LOGD("%s: phymode %d channel %d ch_width %d vht_capable %d "
914 "dot11_mode %d", __func__, phymode, chan,
915 chan_width, vht_capable, dot11_mode);
916
917 return phymode;
918}
919
920/**
921 * wma_get_link_speed() -send command to get linkspeed
922 * @handle: wma handle
923 * @pLinkSpeed: link speed info
924 *
925 * Return: CDF status
926 */
927CDF_STATUS wma_get_link_speed(WMA_HANDLE handle, tSirLinkSpeedInfo *pLinkSpeed)
928{
929 tp_wma_handle wma_handle = (tp_wma_handle) handle;
930 wmi_peer_get_estimated_linkspeed_cmd_fixed_param *cmd;
931 wmi_buf_t wmi_buf;
932 uint32_t len;
933 uint8_t *buf_ptr;
934
935 if (!wma_handle || !wma_handle->wmi_handle) {
936 WMA_LOGE("%s: WMA is closed, can not issue get link speed cmd",
937 __func__);
938 return CDF_STATUS_E_INVAL;
939 }
940 if (!WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap,
941 WMI_SERVICE_ESTIMATE_LINKSPEED)) {
942 WMA_LOGE("%s: Linkspeed feature bit not enabled"
943 " Sending value 0 as link speed.", __func__);
944 wma_send_link_speed(0);
945 return CDF_STATUS_E_FAILURE;
946 }
947 len = sizeof(wmi_peer_get_estimated_linkspeed_cmd_fixed_param);
948 wmi_buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
949 if (!wmi_buf) {
950 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
951 return CDF_STATUS_E_NOMEM;
952 }
953 buf_ptr = (uint8_t *) wmi_buf_data(wmi_buf);
954
955 cmd = (wmi_peer_get_estimated_linkspeed_cmd_fixed_param *) buf_ptr;
956 WMITLV_SET_HDR(&cmd->tlv_header,
957 WMITLV_TAG_STRUC_wmi_peer_get_estimated_linkspeed_cmd_fixed_param,
958 WMITLV_GET_STRUCT_TLVLEN
959 (wmi_peer_get_estimated_linkspeed_cmd_fixed_param));
960
961 /* Copy the peer macaddress to the wma buffer */
Srinivas Girigowdadccab9a2015-11-19 14:31:14 -0800962 WMI_CHAR_ARRAY_TO_MAC_ADDR(pLinkSpeed->peer_macaddr.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800963 &cmd->peer_macaddr);
964
965 WMA_LOGD("%s: pLinkSpeed->peerMacAddr: %pM, "
966 "peer_macaddr.mac_addr31to0: 0x%x, peer_macaddr.mac_addr47to32: 0x%x",
Srinivas Girigowdadccab9a2015-11-19 14:31:14 -0800967 __func__, pLinkSpeed->peer_macaddr.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800968 cmd->peer_macaddr.mac_addr31to0,
969 cmd->peer_macaddr.mac_addr47to32);
970
971 if (wmi_unified_cmd_send(wma_handle->wmi_handle, wmi_buf, len,
972 WMI_PEER_GET_ESTIMATED_LINKSPEED_CMDID)) {
973 WMA_LOGE("%s: failed to send link speed command", __func__);
974 cdf_nbuf_free(wmi_buf);
975 return CDF_STATUS_E_FAILURE;
976 }
977 return CDF_STATUS_SUCCESS;
978}
979
980#ifdef FEATURE_GREEN_AP
981
982/**
Ryan Hsu3c8f79f2015-12-02 16:45:09 -0800983 * wma_egap_info_status_event() - egap info status event
984 * @handle: pointer to wma handler
985 * @event: pointer to event
986 * @len: len of the event
987 *
988 * Return: 0 for success, otherwise appropriate error code
989 */
990static int wma_egap_info_status_event(void *handle, u_int8_t *event,
991 uint32_t len)
992{
993 WMI_TX_PAUSE_EVENTID_param_tlvs *param_buf;
994 wmi_ap_ps_egap_info_event_fixed_param *egap_info_event;
995 wmi_ap_ps_egap_info_chainmask_list *chainmask_event;
996 u_int8_t *buf_ptr;
997
998 param_buf = (WMI_TX_PAUSE_EVENTID_param_tlvs *)event;
999 if (!param_buf) {
1000 WMA_LOGE("Invalid EGAP Info status event buffer");
1001 return -EINVAL;
1002 }
1003
1004 egap_info_event = (wmi_ap_ps_egap_info_event_fixed_param *)
1005 param_buf->fixed_param;
1006 buf_ptr = (uint8_t *)egap_info_event;
1007 buf_ptr += sizeof(wmi_ap_ps_egap_info_event_fixed_param);
1008 chainmask_event = (wmi_ap_ps_egap_info_chainmask_list *)buf_ptr;
1009
1010 WMA_LOGI("mac_id: %d, status: %d, tx_mask: %x, rx_mask: %d",
1011 chainmask_event->mac_id,
1012 egap_info_event->status,
1013 chainmask_event->tx_chainmask,
1014 chainmask_event->rx_chainmask);
1015 return 0;
1016}
1017
1018/**
1019 * wma_send_egap_conf_params() - send wmi cmd of egap configuration params
1020 * @wma_handle: wma handler
1021 * @egap_params: pointer to egap_params
1022 *
1023 * Return: 0 for success, otherwise appropriate error code
1024 */
1025CDF_STATUS wma_send_egap_conf_params(WMA_HANDLE handle,
1026 struct egap_conf_params *egap_params)
1027{
1028 tp_wma_handle wma_handle = (tp_wma_handle) handle;
1029 wmi_ap_ps_egap_param_cmd_fixed_param *cmd;
1030 wmi_buf_t buf;
1031 int32_t err;
1032
1033 buf = wmi_buf_alloc(wma_handle->wmi_handle, sizeof(*cmd));
1034 if (!buf) {
1035 WMA_LOGE("Failed to allocate buffer to send ap_ps_egap cmd");
1036 return CDF_STATUS_E_NOMEM;
1037 }
1038 cmd = (wmi_ap_ps_egap_param_cmd_fixed_param *) wmi_buf_data(buf);
1039 WMITLV_SET_HDR(&cmd->tlv_header,
1040 WMITLV_TAG_STRUC_wmi_ap_ps_egap_param_cmd_fixed_param,
1041 WMITLV_GET_STRUCT_TLVLEN(
1042 wmi_ap_ps_egap_param_cmd_fixed_param));
1043
1044 cmd->enable = egap_params->enable;
1045 cmd->inactivity_time = egap_params->inactivity_time;
1046 cmd->wait_time = egap_params->wait_time;
1047 cmd->flags = egap_params->flags;
1048 err = wmi_unified_cmd_send(wma_handle->wmi_handle, buf,
1049 sizeof(*cmd), WMI_AP_PS_EGAP_PARAM_CMDID);
1050 if (err) {
1051 WMA_LOGE("Failed to send ap_ps_egap cmd");
1052 wmi_buf_free(buf);
1053 return CDF_STATUS_E_FAILURE;
1054 }
1055 return CDF_STATUS_SUCCESS;
1056}
1057
1058/**
1059 * wma_setup_egap_support() - setup the EGAP support flag
1060 * @tgt_cfg: pointer to hdd target configuration
1061 * @egap_support: EGAP support flag
1062 *
1063 * Return: None
1064 */
1065void wma_setup_egap_support(struct wma_tgt_cfg *tgt_cfg, WMA_HANDLE handle)
1066{
1067 tp_wma_handle wma_handle = (tp_wma_handle) handle;
1068
1069 if (tgt_cfg && wma_handle)
1070 tgt_cfg->egap_support = wma_handle->egap_support;
1071}
1072
1073/**
1074 * wma_register_egap_event_handle() - register the EGAP event handle
1075 * @wma_handle: wma handler
1076 *
1077 * Return: None
1078 */
1079void wma_register_egap_event_handle(WMA_HANDLE handle)
1080{
1081 tp_wma_handle wma_handle = (tp_wma_handle) handle;
1082 int status;
1083
1084 if (WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap,
1085 WMI_SERVICE_EGAP)) {
1086 status = wmi_unified_register_event_handler(
1087 wma_handle->wmi_handle,
1088 WMI_AP_PS_EGAP_INFO_EVENTID,
1089 wma_egap_info_status_event);
1090 if (status) {
1091 WMA_LOGE("Failed to register Enhance Green AP event");
1092 wma_handle->egap_support = false;
1093 } else {
1094 WMA_LOGI("Set the Enhance Green AP event handler");
1095 wma_handle->egap_support = true;
1096 }
1097 } else
1098 wma_handle->egap_support = false;
1099}
1100
1101/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001102 * wmi_unified_pdev_green_ap_ps_enable_cmd() - enable green ap powersave command
1103 * @wmi_handle: wmi handle
1104 * @value: value
1105 *
1106 * Return: 0 for success or error code
1107 */
1108int32_t wmi_unified_pdev_green_ap_ps_enable_cmd(wmi_unified_t wmi_handle,
1109 uint32_t value)
1110{
1111 wmi_pdev_green_ap_ps_enable_cmd_fixed_param *cmd;
1112 wmi_buf_t buf;
1113 int32_t len = sizeof(*cmd);
1114
1115 WMA_LOGD("Set Green AP PS val %d", value);
1116
1117 buf = wmi_buf_alloc(wmi_handle, len);
1118 if (!buf) {
1119 WMA_LOGP("%s: Green AP PS Mem Alloc Failed", __func__);
1120 return -ENOMEM;
1121 }
1122
1123 cmd = (wmi_pdev_green_ap_ps_enable_cmd_fixed_param *) wmi_buf_data(buf);
1124 WMITLV_SET_HDR(&cmd->tlv_header,
1125 WMITLV_TAG_STRUC_wmi_pdev_green_ap_ps_enable_cmd_fixed_param,
1126 WMITLV_GET_STRUCT_TLVLEN
1127 (wmi_pdev_green_ap_ps_enable_cmd_fixed_param));
1128 cmd->reserved0 = 0;
1129 cmd->enable = value;
1130
1131 if (wmi_unified_cmd_send(wmi_handle, buf, len,
1132 WMI_PDEV_GREEN_AP_PS_ENABLE_CMDID)) {
1133 WMA_LOGE("Set Green AP PS param Failed val %d", value);
1134 cdf_nbuf_free(buf);
1135 return -EIO;
1136 }
1137 return 0;
1138}
1139#endif /* FEATURE_GREEN_AP */
1140
Govind Singha471e5e2015-10-12 17:11:14 +05301141/**
1142 * wmi_unified_fw_profiling_cmd() - send FW profiling cmd to WLAN FW
1143 * @wma: wma handle
1144 * @cmd: Profiling command index
1145 * @value1: parameter1 value
1146 * @value2: parameter2 value
1147 *
1148 * Return: 0 for success else error code
1149 */
1150int32_t wmi_unified_fw_profiling_cmd(wmi_unified_t wmi_handle,
1151 uint32_t cmd, uint32_t value1, uint32_t value2)
1152{
1153 wmi_buf_t buf;
1154 int32_t len = 0;
1155 int ret;
1156 wmi_wlan_profile_trigger_cmd_fixed_param *prof_trig_cmd;
1157 wmi_wlan_profile_set_hist_intvl_cmd_fixed_param *hist_intvl_cmd;
1158 wmi_wlan_profile_enable_profile_id_cmd_fixed_param *profile_enable_cmd;
1159 wmi_wlan_profile_get_prof_data_cmd_fixed_param *profile_getdata_cmd;
1160
1161 switch (cmd) {
1162 case WMI_WLAN_PROFILE_TRIGGER_CMDID:
1163 len = sizeof(wmi_wlan_profile_trigger_cmd_fixed_param);
1164 buf = wmi_buf_alloc(wmi_handle, len);
1165 if (!buf) {
1166 WMA_LOGP("%s: wmi_buf_alloc Failed", __func__);
1167 return -ENOMEM;
1168 }
1169 prof_trig_cmd =
1170 (wmi_wlan_profile_trigger_cmd_fixed_param *)
1171 wmi_buf_data(buf);
1172 WMITLV_SET_HDR(&prof_trig_cmd->tlv_header,
1173 WMITLV_TAG_STRUC_wmi_wlan_profile_trigger_cmd_fixed_param,
1174 WMITLV_GET_STRUCT_TLVLEN
1175 (wmi_wlan_profile_trigger_cmd_fixed_param));
1176 prof_trig_cmd->enable = value1;
1177 ret = wmi_unified_cmd_send(wmi_handle, buf, len,
1178 WMI_WLAN_PROFILE_TRIGGER_CMDID);
1179 if (ret) {
1180 WMA_LOGE("PROFILE_TRIGGER cmd Failed with value %d",
1181 value1);
1182 cdf_nbuf_free(buf);
1183 return ret;
1184 }
1185 break;
1186
1187 case WMI_WLAN_PROFILE_GET_PROFILE_DATA_CMDID:
1188 len = sizeof(wmi_wlan_profile_get_prof_data_cmd_fixed_param);
1189 buf = wmi_buf_alloc(wmi_handle, len);
1190 if (!buf) {
1191 WMA_LOGP("%s: wmi_buf_alloc Failed", __func__);
1192 return -ENOMEM;
1193 }
1194 profile_getdata_cmd =
1195 (wmi_wlan_profile_get_prof_data_cmd_fixed_param *)
1196 wmi_buf_data(buf);
1197 WMITLV_SET_HDR(&profile_getdata_cmd->tlv_header,
1198 WMITLV_TAG_STRUC_wmi_wlan_profile_get_prof_data_cmd_fixed_param,
1199 WMITLV_GET_STRUCT_TLVLEN
1200 (wmi_wlan_profile_get_prof_data_cmd_fixed_param));
1201 ret = wmi_unified_cmd_send(wmi_handle, buf, len,
1202 WMI_WLAN_PROFILE_GET_PROFILE_DATA_CMDID);
1203 if (ret) {
1204 WMA_LOGE("PROFILE_DATA cmd Failed for id %d value %d",
1205 value1, value2);
1206 cdf_nbuf_free(buf);
1207 return ret;
1208 }
1209 break;
1210
1211 case WMI_WLAN_PROFILE_SET_HIST_INTVL_CMDID:
1212 len = sizeof(wmi_wlan_profile_set_hist_intvl_cmd_fixed_param);
1213 buf = wmi_buf_alloc(wmi_handle, len);
1214 if (!buf) {
1215 WMA_LOGP("%s: wmi_buf_alloc Failed", __func__);
1216 return -ENOMEM;
1217 }
1218 hist_intvl_cmd =
1219 (wmi_wlan_profile_set_hist_intvl_cmd_fixed_param *)
1220 wmi_buf_data(buf);
1221 WMITLV_SET_HDR(&hist_intvl_cmd->tlv_header,
1222 WMITLV_TAG_STRUC_wmi_wlan_profile_set_hist_intvl_cmd_fixed_param,
1223 WMITLV_GET_STRUCT_TLVLEN
1224 (wmi_wlan_profile_set_hist_intvl_cmd_fixed_param));
1225 hist_intvl_cmd->profile_id = value1;
1226 hist_intvl_cmd->value = value2;
1227 ret = wmi_unified_cmd_send(wmi_handle, buf, len,
1228 WMI_WLAN_PROFILE_SET_HIST_INTVL_CMDID);
1229 if (ret) {
1230 WMA_LOGE("HIST_INTVL cmd Failed for id %d value %d",
1231 value1, value2);
1232 cdf_nbuf_free(buf);
1233 return ret;
1234 }
1235 break;
1236
1237 case WMI_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID:
1238 len =
1239 sizeof(wmi_wlan_profile_enable_profile_id_cmd_fixed_param);
1240 buf = wmi_buf_alloc(wmi_handle, len);
1241 if (!buf) {
1242 WMA_LOGP("%s: wmi_buf_alloc Failed", __func__);
1243 return -ENOMEM;
1244 }
1245 profile_enable_cmd =
1246 (wmi_wlan_profile_enable_profile_id_cmd_fixed_param *)
1247 wmi_buf_data(buf);
1248 WMITLV_SET_HDR(&profile_enable_cmd->tlv_header,
1249 WMITLV_TAG_STRUC_wmi_wlan_profile_enable_profile_id_cmd_fixed_param,
1250 WMITLV_GET_STRUCT_TLVLEN
1251 (wmi_wlan_profile_enable_profile_id_cmd_fixed_param));
1252 profile_enable_cmd->profile_id = value1;
1253 profile_enable_cmd->enable = value2;
1254 ret = wmi_unified_cmd_send(wmi_handle, buf, len,
1255 WMI_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID);
1256 if (ret) {
1257 WMA_LOGE("enable cmd Failed for id %d value %d",
1258 value1, value2);
1259 cdf_nbuf_free(buf);
1260 return ret;
1261 }
1262 break;
1263
1264 default:
1265 WMA_LOGD("%s: invalid profiling command", __func__);
1266 break;
1267 }
1268
1269 return 0;
1270}
1271
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001272#ifdef FEATURE_WLAN_LPHB
1273/**
1274 * wma_lphb_handler() - send LPHB indication to SME
1275 * @wma: wma handle
1276 * @event: event handler
1277 *
1278 * Return: 0 for success or error code
1279 */
1280static int wma_lphb_handler(tp_wma_handle wma, uint8_t *event)
1281{
1282 wmi_hb_ind_event_fixed_param *hb_fp;
1283 tSirLPHBInd *slphb_indication;
1284 CDF_STATUS cdf_status;
1285 cds_msg_t sme_msg = { 0 };
1286
1287 hb_fp = (wmi_hb_ind_event_fixed_param *) event;
1288 if (!hb_fp) {
1289 WMA_LOGE("Invalid wmi_hb_ind_event_fixed_param buffer");
1290 return -EINVAL;
1291 }
1292
1293 WMA_LOGD("lphb indication received with vdev_id=%d, session=%d, reason=%d",
1294 hb_fp->vdev_id, hb_fp->session, hb_fp->reason);
1295
1296 slphb_indication = (tSirLPHBInd *) cdf_mem_malloc(sizeof(tSirLPHBInd));
1297
1298 if (!slphb_indication) {
1299 WMA_LOGE("Invalid LPHB indication buffer");
1300 return -ENOMEM;
1301 }
1302
1303 slphb_indication->sessionIdx = hb_fp->session;
1304 slphb_indication->protocolType = hb_fp->reason;
1305 slphb_indication->eventReason = hb_fp->reason;
1306
1307 sme_msg.type = eWNI_SME_LPHB_IND;
1308 sme_msg.bodyptr = slphb_indication;
1309 sme_msg.bodyval = 0;
1310
1311 cdf_status = cds_mq_post_message(CDF_MODULE_ID_SME, &sme_msg);
1312 if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
1313 WMA_LOGE("Fail to post eWNI_SME_LPHB_IND msg to SME");
1314 cdf_mem_free(slphb_indication);
1315 return -EINVAL;
1316 }
1317
1318 return 0;
1319}
1320#endif /* FEATURE_WLAN_LPHB */
1321
1322#ifdef FEATURE_WLAN_RA_FILTERING
1323/**
1324 * wma_wow_sta_ra_filter() - set RA filter pattern in fw
1325 * @wma: wma handle
1326 * @vdev_id: vdev id
1327 *
1328 * Return: CDF status
1329 */
1330static CDF_STATUS wma_wow_sta_ra_filter(tp_wma_handle wma, uint8_t vdev_id)
1331{
1332
1333 WMI_WOW_ADD_PATTERN_CMD_fixed_param *cmd;
1334 struct wma_txrx_node *iface;
1335 wmi_buf_t buf;
1336 uint8_t *buf_ptr;
1337 int32_t len;
1338 int ret;
1339
1340 iface = &wma->interfaces[vdev_id];
1341
1342 len = sizeof(WMI_WOW_ADD_PATTERN_CMD_fixed_param) +
1343 WMI_TLV_HDR_SIZE +
1344 0 * sizeof(WOW_BITMAP_PATTERN_T) +
1345 WMI_TLV_HDR_SIZE +
1346 0 * sizeof(WOW_IPV4_SYNC_PATTERN_T) +
1347 WMI_TLV_HDR_SIZE +
1348 0 * sizeof(WOW_IPV6_SYNC_PATTERN_T) +
1349 WMI_TLV_HDR_SIZE +
1350 0 * sizeof(WOW_MAGIC_PATTERN_CMD) +
1351 WMI_TLV_HDR_SIZE +
1352 0 * sizeof(A_UINT32) + WMI_TLV_HDR_SIZE + 1 * sizeof(A_UINT32);
1353
1354 buf = wmi_buf_alloc(wma->wmi_handle, len);
1355 if (!buf) {
1356 WMA_LOGE("%s: Failed allocate wmi buffer", __func__);
1357 return CDF_STATUS_E_NOMEM;
1358 }
1359
1360 cmd = (WMI_WOW_ADD_PATTERN_CMD_fixed_param *) wmi_buf_data(buf);
1361 buf_ptr = (uint8_t *) cmd;
1362
1363 WMITLV_SET_HDR(&cmd->tlv_header,
1364 WMITLV_TAG_STRUC_WMI_WOW_ADD_PATTERN_CMD_fixed_param,
1365 WMITLV_GET_STRUCT_TLVLEN
1366 (WMI_WOW_ADD_PATTERN_CMD_fixed_param));
1367 cmd->vdev_id = vdev_id;
1368 cmd->pattern_id = iface->num_wow_default_patterns++,
1369 cmd->pattern_type = WOW_IPV6_RA_PATTERN;
1370 buf_ptr += sizeof(WMI_WOW_ADD_PATTERN_CMD_fixed_param);
1371
1372 /* Fill TLV for WMITLV_TAG_STRUC_WOW_BITMAP_PATTERN_T but no data. */
1373 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
1374 buf_ptr += WMI_TLV_HDR_SIZE;
1375
1376 /* Fill TLV for WMITLV_TAG_STRUC_WOW_IPV4_SYNC_PATTERN_T but no data. */
1377 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
1378 buf_ptr += WMI_TLV_HDR_SIZE;
1379
1380 /* Fill TLV for WMITLV_TAG_STRUC_WOW_IPV6_SYNC_PATTERN_T but no data. */
1381 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
1382 buf_ptr += WMI_TLV_HDR_SIZE;
1383
1384 /* Fill TLV for WMITLV_TAG_STRUC_WOW_MAGIC_PATTERN_CMD but no data. */
1385 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
1386 buf_ptr += WMI_TLV_HDR_SIZE;
1387
1388 /* Fill TLV for pattern_info_timeout but no data. */
1389 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, 0);
1390 buf_ptr += WMI_TLV_HDR_SIZE;
1391
1392 /* Fill TLV for ra_ratelimit_interval. */
1393 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, sizeof(A_UINT32));
1394 buf_ptr += WMI_TLV_HDR_SIZE;
1395
1396 *((A_UINT32 *) buf_ptr) = wma->RArateLimitInterval;
1397
1398 WMA_LOGD("%s: send RA rate limit [%d] to fw vdev = %d", __func__,
1399 wma->RArateLimitInterval, vdev_id);
1400
1401 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
1402 WMI_WOW_ADD_WAKE_PATTERN_CMDID);
1403 if (ret) {
1404 WMA_LOGE("%s: Failed to send RA rate limit to fw", __func__);
1405 wmi_buf_free(buf);
1406 iface->num_wow_default_patterns--;
1407 return CDF_STATUS_E_FAILURE;
1408 }
1409
1410 return CDF_STATUS_SUCCESS;
1411
1412}
1413#endif /* FEATURE_WLAN_RA_FILTERING */
1414
1415/**
1416 * wmi_unified_nat_keepalive_enable() - enable NAT keepalive filter
1417 * @wma: wma handle
1418 * @vdev_id: vdev id
1419 *
1420 * Return: 0 for success or error code
1421 */
1422int wmi_unified_nat_keepalive_enable(tp_wma_handle wma, uint8_t vdev_id)
1423{
1424 WMI_VDEV_IPSEC_NATKEEPALIVE_FILTER_CMD_fixed_param *cmd;
1425 wmi_buf_t buf;
1426 int32_t len = sizeof(*cmd);
1427
1428 WMA_LOGD("%s: vdev_id %d", __func__, vdev_id);
1429 buf = wmi_buf_alloc(wma->wmi_handle, len);
1430 if (!buf) {
1431 WMA_LOGP("%s: wmi_buf_alloc failed", __func__);
1432 return -ENOMEM;
1433 }
1434 cmd = (WMI_VDEV_IPSEC_NATKEEPALIVE_FILTER_CMD_fixed_param *)
1435 wmi_buf_data(buf);
1436 WMITLV_SET_HDR(&cmd->tlv_header,
1437 WMITLV_TAG_STRUC_WMI_VDEV_IPSEC_NATKEEPALIVE_FILTER_CMD_fixed_param,
1438 WMITLV_GET_STRUCT_TLVLEN
1439 (WMI_VDEV_IPSEC_NATKEEPALIVE_FILTER_CMD_fixed_param));
1440 cmd->vdev_id = vdev_id;
1441 cmd->action = IPSEC_NATKEEPALIVE_FILTER_ENABLE;
1442 if (wmi_unified_cmd_send(wma->wmi_handle, buf, len,
1443 WMI_VDEV_IPSEC_NATKEEPALIVE_FILTER_CMDID)) {
1444 WMA_LOGP("%s: Failed to send NAT keepalive enable command",
1445 __func__);
1446 wmi_buf_free(buf);
1447 return -EIO;
1448 }
1449 return 0;
1450}
1451
1452/**
1453 * wmi_unified_csa_offload_enable() - sen CSA offload enable command
1454 * @wma: wma handle
1455 * @vdev_id: vdev id
1456 *
1457 * Return: 0 for success or error code
1458 */
1459int wmi_unified_csa_offload_enable(tp_wma_handle wma, uint8_t vdev_id)
1460{
1461 wmi_csa_offload_enable_cmd_fixed_param *cmd;
1462 wmi_buf_t buf;
1463 int32_t len = sizeof(*cmd);
1464
1465 WMA_LOGD("%s: vdev_id %d", __func__, vdev_id);
1466 buf = wmi_buf_alloc(wma->wmi_handle, len);
1467 if (!buf) {
1468 WMA_LOGP("%s: wmi_buf_alloc failed", __func__);
1469 return -ENOMEM;
1470 }
1471 cmd = (wmi_csa_offload_enable_cmd_fixed_param *) wmi_buf_data(buf);
1472 WMITLV_SET_HDR(&cmd->tlv_header,
1473 WMITLV_TAG_STRUC_wmi_csa_offload_enable_cmd_fixed_param,
1474 WMITLV_GET_STRUCT_TLVLEN
1475 (wmi_csa_offload_enable_cmd_fixed_param));
1476 cmd->vdev_id = vdev_id;
1477 cmd->csa_offload_enable = WMI_CSA_OFFLOAD_ENABLE;
1478 if (wmi_unified_cmd_send(wma->wmi_handle, buf, len,
1479 WMI_CSA_OFFLOAD_ENABLE_CMDID)) {
1480 WMA_LOGP("%s: Failed to send CSA offload enable command",
1481 __func__);
1482 wmi_buf_free(buf);
1483 return -EIO;
1484 }
1485 return 0;
1486}
1487
1488#ifdef WLAN_FEATURE_NAN
1489/**
1490 * wma_nan_rsp_event_handler() - Function is used to handle nan response
1491 * @handle: wma handle
1492 * @event_buf: event buffer
1493 * @len: length of buffer
1494 *
1495 * Return: 0 for success or error code
1496 */
1497int wma_nan_rsp_event_handler(void *handle, uint8_t *event_buf,
1498 uint32_t len)
1499{
1500 WMI_NAN_EVENTID_param_tlvs *param_buf;
1501 tSirNanEvent *nan_rsp_event;
1502 wmi_nan_event_hdr *nan_rsp_event_hdr;
1503 CDF_STATUS status;
1504 cds_msg_t cds_msg;
1505 uint8_t *buf_ptr;
1506 uint32_t alloc_len;
1507
1508 /*
1509 * This is how received event_buf looks like
1510 *
1511 * <-------------------- event_buf ----------------------------------->
1512 *
1513 * <--wmi_nan_event_hdr--><---WMI_TLV_HDR_SIZE---><----- data -------->
1514 *
1515 * +-----------+---------+-----------------------+--------------------+
1516 * | tlv_header| data_len| WMITLV_TAG_ARRAY_BYTE | nan_rsp_event_data |
1517 * +-----------+---------+-----------------------+--------------------+
1518 */
1519
1520 WMA_LOGD("%s: Posting NaN response event to SME", __func__);
1521 param_buf = (WMI_NAN_EVENTID_param_tlvs *) event_buf;
1522 if (!param_buf) {
1523 WMA_LOGE("%s: Invalid nan response event buf", __func__);
1524 return -EINVAL;
1525 }
1526 nan_rsp_event_hdr = param_buf->fixed_param;
1527 buf_ptr = (uint8_t *) nan_rsp_event_hdr;
1528 alloc_len = sizeof(tSirNanEvent);
1529 alloc_len += nan_rsp_event_hdr->data_len;
1530 nan_rsp_event = (tSirNanEvent *) cdf_mem_malloc(alloc_len);
1531 if (NULL == nan_rsp_event) {
1532 WMA_LOGE("%s: Memory allocation failure", __func__);
1533 return -ENOMEM;
1534 }
1535
1536 nan_rsp_event->event_data_len = nan_rsp_event_hdr->data_len;
1537 cdf_mem_copy(nan_rsp_event->event_data, buf_ptr +
1538 sizeof(wmi_nan_event_hdr) + WMI_TLV_HDR_SIZE,
1539 nan_rsp_event->event_data_len);
1540 cds_msg.type = eWNI_SME_NAN_EVENT;
1541 cds_msg.bodyptr = (void *)nan_rsp_event;
1542 cds_msg.bodyval = 0;
1543
1544 status = cds_mq_post_message(CDS_MQ_ID_SME, &cds_msg);
1545 if (status != CDF_STATUS_SUCCESS) {
1546 WMA_LOGE("%s: Failed to post NaN response event to SME",
1547 __func__);
1548 cdf_mem_free(nan_rsp_event);
1549 return -EFAULT;
1550 }
1551 WMA_LOGD("%s: NaN response event Posted to SME", __func__);
1552 return 0;
1553}
1554#endif /* WLAN_FEATURE_NAN */
1555
1556/**
1557 * wma_csa_offload_handler() - CSA event handler
1558 * @handle: wma handle
1559 * @event: event buffer
1560 * @len: buffer length
1561 *
1562 * This event is sent by firmware when it receives CSA IE.
1563 *
1564 * Return: 0 for success or error code
1565 */
1566int wma_csa_offload_handler(void *handle, uint8_t *event, uint32_t len)
1567{
1568 tp_wma_handle wma = (tp_wma_handle) handle;
1569 WMI_CSA_HANDLING_EVENTID_param_tlvs *param_buf;
1570 wmi_csa_event_fixed_param *csa_event;
1571 uint8_t bssid[IEEE80211_ADDR_LEN];
1572 uint8_t vdev_id = 0;
1573 uint8_t cur_chan = 0;
1574 struct ieee80211_channelswitch_ie *csa_ie;
1575 tpCSAOffloadParams csa_offload_event;
1576 struct ieee80211_extendedchannelswitch_ie *xcsa_ie;
1577 struct ieee80211_ie_wide_bw_switch *wb_ie;
1578 struct wma_txrx_node *intr = wma->interfaces;
1579
1580 param_buf = (WMI_CSA_HANDLING_EVENTID_param_tlvs *) event;
1581
1582 WMA_LOGD("%s: Enter", __func__);
1583 if (!param_buf) {
1584 WMA_LOGE("Invalid csa event buffer");
1585 return -EINVAL;
1586 }
1587 csa_event = param_buf->fixed_param;
1588 WMI_MAC_ADDR_TO_CHAR_ARRAY(&csa_event->i_addr2, &bssid[0]);
1589
1590 if (wma_find_vdev_by_bssid(wma, bssid, &vdev_id) == NULL) {
1591 WMA_LOGE("Invalid bssid received %s:%d", __func__, __LINE__);
1592 return -EINVAL;
1593 }
1594
1595 csa_offload_event = cdf_mem_malloc(sizeof(*csa_offload_event));
1596 if (!csa_offload_event) {
1597 WMA_LOGE("CDF MEM Alloc Failed for csa_offload_event");
1598 return -EINVAL;
1599 }
1600
1601 cdf_mem_zero(csa_offload_event, sizeof(*csa_offload_event));
1602 cdf_mem_copy(csa_offload_event->bssId, &bssid, IEEE80211_ADDR_LEN);
1603
1604 if (csa_event->ies_present_flag & WMI_CSA_IE_PRESENT) {
1605 csa_ie = (struct ieee80211_channelswitch_ie *)
1606 (&csa_event->csa_ie[0]);
1607 csa_offload_event->channel = csa_ie->newchannel;
1608 csa_offload_event->switchmode = csa_ie->switchmode;
1609 } else if (csa_event->ies_present_flag & WMI_XCSA_IE_PRESENT) {
1610 xcsa_ie = (struct ieee80211_extendedchannelswitch_ie *)
1611 (&csa_event->xcsa_ie[0]);
1612 csa_offload_event->channel = xcsa_ie->newchannel;
1613 csa_offload_event->switchmode = xcsa_ie->switchmode;
Gupta, Kapil121bf212015-11-25 19:21:29 +05301614 csa_offload_event->new_op_class = xcsa_ie->newClass;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001615 } else {
1616 WMA_LOGE("CSA Event error: No CSA IE present");
1617 cdf_mem_free(csa_offload_event);
1618 return -EINVAL;
1619 }
1620
1621 if (csa_event->ies_present_flag & WMI_WBW_IE_PRESENT) {
1622 wb_ie = (struct ieee80211_ie_wide_bw_switch *)
1623 (&csa_event->wb_ie[0]);
1624 csa_offload_event->new_ch_width = wb_ie->new_ch_width;
1625 csa_offload_event->new_ch_freq_seg1 = wb_ie->new_ch_freq_seg1;
1626 csa_offload_event->new_ch_freq_seg2 = wb_ie->new_ch_freq_seg2;
1627 }
1628
1629 csa_offload_event->ies_present_flag = csa_event->ies_present_flag;
1630
1631 WMA_LOGD("CSA: New Channel = %d BSSID:%pM",
1632 csa_offload_event->channel, csa_offload_event->bssId);
1633
1634 cur_chan = cds_freq_to_chan(intr[vdev_id].mhz);
1635 /*
1636 * basic sanity check: requested channel should not be 0
1637 * and equal to home channel
1638 */
1639 if ((0 == csa_offload_event->channel) ||
1640 (cur_chan == csa_offload_event->channel)) {
1641 WMA_LOGE("CSA Event with channel %d. Ignore !!",
1642 csa_offload_event->channel);
1643 cdf_mem_free(csa_offload_event);
1644 return -EINVAL;
1645 }
1646 wma->interfaces[vdev_id].is_channel_switch = true;
1647 wma_send_msg(wma, WMA_CSA_OFFLOAD_EVENT, (void *)csa_offload_event, 0);
1648 return 0;
1649}
1650
1651#ifdef FEATURE_OEM_DATA_SUPPORT
1652
1653/**
1654 * wma_oem_capability_event_callback() - OEM capability event handler
1655 * @handle: wma handle
1656 * @datap: data ptr
1657 * @len: data length
1658 *
1659 * Return: 0 for success or error code
1660 */
1661int wma_oem_capability_event_callback(void *handle,
1662 uint8_t *datap, uint32_t len)
1663{
1664 tp_wma_handle wma = (tp_wma_handle) handle;
1665 WMI_OEM_CAPABILITY_EVENTID_param_tlvs *param_buf;
1666 uint8_t *data;
1667 uint32_t datalen;
1668 uint32_t *msg_subtype;
1669 tStartOemDataRsp *pStartOemDataRsp;
1670
1671 param_buf = (WMI_OEM_CAPABILITY_EVENTID_param_tlvs *) datap;
1672 if (!param_buf) {
1673 WMA_LOGE("%s: Received NULL buf ptr from FW", __func__);
1674 return -ENOMEM;
1675 }
1676
1677 data = param_buf->data;
1678 datalen = param_buf->num_data;
1679
1680 if (!data) {
1681 WMA_LOGE("%s: Received NULL data from FW", __func__);
1682 return -EINVAL;
1683 }
1684
1685 /* wma puts 4 bytes prefix for msg subtype, so length
1686 * of data received from target should be 4 bytes less
1687 * then max allowed
1688 */
1689 if (datalen > (OEM_DATA_RSP_SIZE - 4)) {
1690 WMA_LOGE("%s: Received data len (%d) exceeds max value (%d)",
1691 __func__, datalen, (OEM_DATA_RSP_SIZE - 4));
1692 return -EINVAL;
1693 }
1694
1695 pStartOemDataRsp = cdf_mem_malloc(sizeof(*pStartOemDataRsp));
1696 if (!pStartOemDataRsp) {
1697 WMA_LOGE("%s: Failed to alloc pStartOemDataRsp", __func__);
1698 return -ENOMEM;
1699 }
1700
1701 cdf_mem_zero(pStartOemDataRsp, sizeof(tStartOemDataRsp));
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001702 pStartOemDataRsp->target_rsp = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001703 msg_subtype = (uint32_t *) (&pStartOemDataRsp->oemDataRsp[0]);
1704 *msg_subtype = WMI_OEM_CAPABILITY_RSP;
1705 cdf_mem_copy(&pStartOemDataRsp->oemDataRsp[4], data, datalen);
1706
1707 WMA_LOGI("%s: Sending WMA_START_OEM_DATA_RSP, data len (%d)",
1708 __func__, datalen);
1709
1710 wma_send_msg(wma, WMA_START_OEM_DATA_RSP, (void *)pStartOemDataRsp, 0);
1711 return 0;
1712}
1713
1714/**
1715 * wma_oem_measurement_report_event_callback() - OEM measurement report handler
1716 * @handle: wma handle
1717 * @datap: data ptr
1718 * @len: data length
1719 *
1720 * Return: 0 for success or error code
1721 */
1722int wma_oem_measurement_report_event_callback(void *handle,
1723 uint8_t *datap,
1724 uint32_t len)
1725{
1726 tp_wma_handle wma = (tp_wma_handle) handle;
1727 WMI_OEM_MEASUREMENT_REPORT_EVENTID_param_tlvs *param_buf;
1728 uint8_t *data;
1729 uint32_t datalen;
1730 uint32_t *msg_subtype;
1731 tStartOemDataRsp *pStartOemDataRsp;
1732
1733 param_buf = (WMI_OEM_MEASUREMENT_REPORT_EVENTID_param_tlvs *) datap;
1734 if (!param_buf) {
1735 WMA_LOGE("%s: Received NULL buf ptr from FW", __func__);
1736 return -ENOMEM;
1737 }
1738
1739 data = param_buf->data;
1740 datalen = param_buf->num_data;
1741
1742 if (!data) {
1743 WMA_LOGE("%s: Received NULL data from FW", __func__);
1744 return -EINVAL;
1745 }
1746
1747 /* wma puts 4 bytes prefix for msg subtype, so length
1748 * of data received from target should be 4 bytes less
1749 * then max allowed
1750 */
1751 if (datalen > (OEM_DATA_RSP_SIZE - 4)) {
1752 WMA_LOGE("%s: Received data len (%d) exceeds max value (%d)",
1753 __func__, datalen, (OEM_DATA_RSP_SIZE - 4));
1754 return -EINVAL;
1755 }
1756
1757 pStartOemDataRsp = cdf_mem_malloc(sizeof(*pStartOemDataRsp));
1758 if (!pStartOemDataRsp) {
1759 WMA_LOGE("%s: Failed to alloc pStartOemDataRsp", __func__);
1760 return -ENOMEM;
1761 }
1762
1763 cdf_mem_zero(pStartOemDataRsp, sizeof(tStartOemDataRsp));
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001764 pStartOemDataRsp->target_rsp = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001765 msg_subtype = (uint32_t *) (&pStartOemDataRsp->oemDataRsp[0]);
1766 *msg_subtype = WMI_OEM_MEASUREMENT_RSP;
1767 cdf_mem_copy(&pStartOemDataRsp->oemDataRsp[4], data, datalen);
1768
1769 WMA_LOGI("%s: Sending WMA_START_OEM_DATA_RSP, data len (%d)",
1770 __func__, datalen);
1771
1772 wma_send_msg(wma, WMA_START_OEM_DATA_RSP, (void *)pStartOemDataRsp, 0);
1773 return 0;
1774}
1775
1776/**
1777 * wma_oem_error_report_event_callback() - OEM error report handler
1778 * @handle: wma handle
1779 * @datap: data ptr
1780 * @len: data length
1781 *
1782 * Return: 0 for success or error code
1783 */
1784int wma_oem_error_report_event_callback(void *handle,
1785 uint8_t *datap, uint32_t len)
1786{
1787 tp_wma_handle wma = (tp_wma_handle) handle;
1788 WMI_OEM_ERROR_REPORT_EVENTID_param_tlvs *param_buf;
1789 uint8_t *data;
1790 uint32_t datalen;
1791 uint32_t *msg_subtype;
1792 tStartOemDataRsp *pStartOemDataRsp;
1793
1794 param_buf = (WMI_OEM_ERROR_REPORT_EVENTID_param_tlvs *) datap;
1795 if (!param_buf) {
1796 WMA_LOGE("%s: Received NULL buf ptr from FW", __func__);
1797 return -ENOMEM;
1798 }
1799
1800 data = param_buf->data;
1801 datalen = param_buf->num_data;
1802
1803 if (!data) {
1804 WMA_LOGE("%s: Received NULL data from FW", __func__);
1805 return -EINVAL;
1806 }
1807
1808 /* wma puts 4 bytes prefix for msg subtype, so length
1809 * of data received from target should be 4 bytes less
1810 * then max allowed
1811 */
1812 if (datalen > (OEM_DATA_RSP_SIZE - 4)) {
1813 WMA_LOGE("%s: Received data len (%d) exceeds max value (%d)",
1814 __func__, datalen, (OEM_DATA_RSP_SIZE - 4));
1815 return -EINVAL;
1816 }
1817
1818 pStartOemDataRsp = cdf_mem_malloc(sizeof(*pStartOemDataRsp));
1819 if (!pStartOemDataRsp) {
1820 WMA_LOGE("%s: Failed to alloc pStartOemDataRsp", __func__);
1821 return -ENOMEM;
1822 }
1823
1824 cdf_mem_zero(pStartOemDataRsp, sizeof(tStartOemDataRsp));
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001825 pStartOemDataRsp->target_rsp = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001826 msg_subtype = (uint32_t *) (&pStartOemDataRsp->oemDataRsp[0]);
1827 *msg_subtype = WMI_OEM_ERROR_REPORT_RSP;
1828 cdf_mem_copy(&pStartOemDataRsp->oemDataRsp[4], data, datalen);
1829
1830 WMA_LOGI("%s: Sending WMA_START_OEM_DATA_RSP, data len (%d)",
1831 __func__, datalen);
1832
1833 wma_send_msg(wma, WMA_START_OEM_DATA_RSP, (void *)pStartOemDataRsp, 0);
1834 return 0;
1835}
1836
1837/**
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001838 * wma_oem_data_response_handler() - OEM data response event handler
1839 * @handle: wma handle
1840 * @datap: data ptr
1841 * @len: data length
1842 *
1843 * Return: 0 for success or error code
1844 */
1845int wma_oem_data_response_handler(void *handle,
1846 uint8_t *datap, uint32_t len)
1847{
1848 tp_wma_handle wma = (tp_wma_handle) handle;
1849 WMI_OEM_RESPONSE_EVENTID_param_tlvs *param_buf;
1850 uint8_t *data;
1851 uint32_t datalen;
1852 tStartOemDataRsp *oem_data_rsp;
1853
1854 param_buf = (WMI_OEM_RESPONSE_EVENTID_param_tlvs *) datap;
1855 if (!param_buf) {
1856 WMA_LOGE(FL("Received NULL buf ptr from FW"));
1857 return -ENOMEM;
1858 }
1859
1860 data = param_buf->data;
1861 datalen = param_buf->num_data;
1862
1863 if (!data) {
1864 WMA_LOGE(FL("Received NULL data from FW"));
1865 return -EINVAL;
1866 }
1867
1868 if (datalen > OEM_DATA_RSP_SIZE) {
1869 WMA_LOGE(FL("Received data len %d exceeds max value %d"),
1870 datalen, OEM_DATA_RSP_SIZE);
1871 return -EINVAL;
1872 }
1873
1874 oem_data_rsp = cdf_mem_malloc(sizeof(*oem_data_rsp));
1875 if (!oem_data_rsp) {
1876 WMA_LOGE(FL("Failed to alloc oem_data_rsp"));
1877 return -ENOMEM;
1878 }
1879
1880 cdf_mem_zero(oem_data_rsp, sizeof(tStartOemDataRsp));
1881 oem_data_rsp->target_rsp = true;
1882 cdf_mem_copy(&oem_data_rsp->oemDataRsp[0], data, datalen);
1883
1884 WMA_LOGI(FL("Sending WMA_START_OEM_DATA_RSP, data len %d"), datalen);
1885
1886 wma_send_msg(wma, WMA_START_OEM_DATA_RSP, (void *)oem_data_rsp, 0);
1887 return 0;
1888}
1889
1890/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001891 * wma_start_oem_data_req() - start OEM data request to target
1892 * @wma_handle: wma handle
1893 * @startOemDataReq: start request params
1894 *
1895 * Return: none
1896 */
1897void wma_start_oem_data_req(tp_wma_handle wma_handle,
1898 tStartOemDataReq *startOemDataReq)
1899{
1900 wmi_buf_t buf;
1901 uint8_t *cmd;
1902 int ret = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001903 tStartOemDataRsp *pStartOemDataRsp;
1904
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001905 WMA_LOGD(FL("Send OEM Data Request to target"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001906
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001907 if (!startOemDataReq && !startOemDataReq->data) {
1908 WMA_LOGE(FL("startOemDataReq is null"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001909 goto out;
1910 }
1911
1912 if (!wma_handle || !wma_handle->wmi_handle) {
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001913 WMA_LOGE(FL("WMA - closed, can not send Oem data request cmd"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001914 return;
1915 }
1916
1917 buf = wmi_buf_alloc(wma_handle->wmi_handle,
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001918 (startOemDataReq->data_len + WMI_TLV_HDR_SIZE));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001919 if (!buf) {
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001920 WMA_LOGE(FL("wmi_buf_alloc failed"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001921 goto out;
1922 }
1923
1924 cmd = (uint8_t *) wmi_buf_data(buf);
1925
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001926 WMITLV_SET_HDR(cmd, WMITLV_TAG_ARRAY_BYTE, startOemDataReq->data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001927 cmd += WMI_TLV_HDR_SIZE;
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001928 cdf_mem_copy(cmd, startOemDataReq->data,
1929 startOemDataReq->data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001930
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001931 WMA_LOGI(FL("Sending OEM Data Request to target, data len %d"),
1932 startOemDataReq->data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001933
1934 ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf,
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001935 (startOemDataReq->data_len +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001936 WMI_TLV_HDR_SIZE), WMI_OEM_REQ_CMDID);
1937
1938 if (ret != EOK) {
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001939 WMA_LOGE(FL(":wmi cmd send failed"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001940 cdf_nbuf_free(buf);
1941 }
1942
1943out:
1944 /* free oem data req buffer received from UMAC */
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001945 if (startOemDataReq) {
1946 if (startOemDataReq->data)
1947 cdf_mem_free(startOemDataReq->data);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001948 cdf_mem_free(startOemDataReq);
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08001949 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001950
1951 /* Now send data resp back to PE/SME with message sub-type of
1952 * WMI_OEM_INTERNAL_RSP. This is required so that PE/SME clears
1953 * up pending active command. Later when desired oem response(s)
1954 * comes as wmi event from target then those shall be passed
1955 * to oem application
1956 */
1957 pStartOemDataRsp = cdf_mem_malloc(sizeof(*pStartOemDataRsp));
1958 if (!pStartOemDataRsp) {
1959 WMA_LOGE("%s:failed to allocate memory for OEM Data Resp to PE",
1960 __func__);
1961 return;
1962 }
1963 cdf_mem_zero(pStartOemDataRsp, sizeof(tStartOemDataRsp));
Krishna Kumaar Natarajan4e9cf392015-11-20 13:35:05 -08001964 pStartOemDataRsp->target_rsp = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001965
1966 WMA_LOGI("%s: Sending WMA_START_OEM_DATA_RSP to clear up PE/SME pending cmd",
1967 __func__);
1968
1969 wma_send_msg(wma_handle, WMA_START_OEM_DATA_RSP,
1970 (void *)pStartOemDataRsp, 0);
1971
1972 return;
1973}
1974#endif /* FEATURE_OEM_DATA_SUPPORT */
1975
1976
1977/**
1978 * wma_unified_dfs_radar_rx_event_handler() - dfs radar rx event handler
1979 * @handle: wma handle
1980 * @data: data buffer
1981 * @datalen: data length
1982 *
1983 * WMI handler for WMI_DFS_RADAR_EVENTID
1984 * This handler is registered for handling
1985 * filtered DFS Phyerror. This handler is
1986 * will be invoked only when DFS Phyerr
1987 * filtering offload is enabled.
1988 *
1989 * Return: 1 for Success and 0 for error
1990 */
1991static int wma_unified_dfs_radar_rx_event_handler(void *handle,
1992 uint8_t *data,
1993 uint32_t datalen)
1994{
1995 tp_wma_handle wma = (tp_wma_handle) handle;
1996 struct ieee80211com *ic;
1997 struct ath_dfs *dfs;
1998 struct dfs_event *event;
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05301999 struct dfs_ieee80211_channel *chan;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002000 int empty;
2001 int do_check_chirp = 0;
2002 int is_hw_chirp = 0;
2003 int is_sw_chirp = 0;
2004 int is_pri = 0;
2005
2006 WMI_DFS_RADAR_EVENTID_param_tlvs *param_tlvs;
2007 wmi_dfs_radar_event_fixed_param *radar_event;
2008
2009 ic = wma->dfs_ic;
2010 if (NULL == ic) {
2011 WMA_LOGE("%s: dfs_ic is NULL ", __func__);
2012 return 0;
2013 }
2014
2015 dfs = (struct ath_dfs *)ic->ic_dfs;
2016 param_tlvs = (WMI_DFS_RADAR_EVENTID_param_tlvs *) data;
2017
2018 if (NULL == dfs) {
2019 WMA_LOGE("%s: dfs is NULL ", __func__);
2020 return 0;
2021 }
2022 /*
2023 * This parameter holds the number
2024 * of phyerror interrupts to the host
2025 * after the phyerrors have passed through
2026 * false detect filters in the firmware.
2027 */
2028 dfs->dfs_phyerr_count++;
2029
2030 if (!param_tlvs) {
2031 WMA_LOGE("%s: Received NULL data from FW", __func__);
2032 return 0;
2033 }
2034
2035 radar_event = param_tlvs->fixed_param;
2036
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05302037 cdf_spin_lock_bh(&ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002038 chan = ic->ic_curchan;
Edhar, Mahesh Kumar35d9b2e2015-10-26 17:06:23 +05302039 if (ic->disable_phy_err_processing) {
2040 WMA_LOGD("%s: radar indication done,drop phyerror event",
2041 __func__);
2042 cdf_spin_unlock_bh(&ic->chan_lock);
2043 return 0;
2044 }
2045
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002046 if (CHANNEL_STATE_DFS != cds_get_channel_state(chan->ic_ieee)) {
2047 WMA_LOGE
2048 ("%s: Invalid DFS Phyerror event. Channel=%d is Non-DFS",
2049 __func__, chan->ic_ieee);
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05302050 cdf_spin_unlock_bh(&ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002051 return 0;
2052 }
2053
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05302054 cdf_spin_unlock_bh(&ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002055 dfs->ath_dfs_stats.total_phy_errors++;
2056
2057 if (dfs->dfs_caps.ath_chip_is_bb_tlv) {
2058 do_check_chirp = 1;
2059 is_pri = 1;
2060 is_hw_chirp = radar_event->pulse_is_chirp;
2061
2062 if ((uint32_t) dfs->dfs_phyerr_freq_min >
2063 radar_event->pulse_center_freq) {
2064 dfs->dfs_phyerr_freq_min =
2065 (int)radar_event->pulse_center_freq;
2066 }
2067
2068 if (dfs->dfs_phyerr_freq_max <
2069 (int)radar_event->pulse_center_freq) {
2070 dfs->dfs_phyerr_freq_max =
2071 (int)radar_event->pulse_center_freq;
2072 }
2073 }
2074
2075 /*
2076 * Now, add the parsed, checked and filtered
2077 * radar phyerror event radar pulse event list.
2078 * This event will then be processed by
2079 * dfs_radar_processevent() to see if the pattern
2080 * of pulses in radar pulse list match any radar
2081 * singnature in the current regulatory domain.
2082 */
2083
2084 ATH_DFSEVENTQ_LOCK(dfs);
2085 empty = STAILQ_EMPTY(&(dfs->dfs_eventq));
2086 ATH_DFSEVENTQ_UNLOCK(dfs);
2087 if (empty) {
2088 return 0;
2089 }
2090 /*
2091 * Add the event to the list, if there's space.
2092 */
2093 ATH_DFSEVENTQ_LOCK(dfs);
2094 event = STAILQ_FIRST(&(dfs->dfs_eventq));
2095 if (event == NULL) {
2096 ATH_DFSEVENTQ_UNLOCK(dfs);
2097 WMA_LOGE("%s: No more space left for queuing DFS Phyerror events",
2098 __func__);
2099 return 0;
2100 }
2101 STAILQ_REMOVE_HEAD(&(dfs->dfs_eventq), re_list);
2102 ATH_DFSEVENTQ_UNLOCK(dfs);
2103 dfs->dfs_phyerr_queued_count++;
2104 dfs->dfs_phyerr_w53_counter++;
2105 event->re_dur = (uint8_t) radar_event->pulse_duration;
2106 event->re_rssi = radar_event->rssi;
2107 event->re_ts = radar_event->pulse_detect_ts & DFS_TSMASK;
2108 event->re_full_ts = (((uint64_t) radar_event->upload_fullts_high) << 32)
2109 | radar_event->upload_fullts_low;
2110
2111 /*
2112 * Index of peak magnitude
2113 */
2114 event->sidx = radar_event->peak_sidx;
2115
2116 /*
2117 * Handle chirp flags.
2118 */
2119 if (do_check_chirp) {
2120 event->re_flags |= DFS_EVENT_CHECKCHIRP;
2121 if (is_hw_chirp) {
2122 event->re_flags |= DFS_EVENT_HW_CHIRP;
2123 }
2124 if (is_sw_chirp) {
2125 event->re_flags |= DFS_EVENT_SW_CHIRP;
2126 }
2127 }
2128 /*
2129 * Correctly set which channel is being reported on
2130 */
2131 if (is_pri) {
2132 event->re_chanindex = (uint8_t) dfs->dfs_curchan_radindex;
2133 } else {
2134 if (dfs->dfs_extchan_radindex == -1) {
2135 WMA_LOGI("%s phyerr on ext channel", __func__);
2136 }
2137 event->re_chanindex = (uint8_t) dfs->dfs_extchan_radindex;
2138 WMA_LOGI("%s:New extension channel event is added to queue",
2139 __func__);
2140 }
2141
2142 ATH_DFSQ_LOCK(dfs);
2143
2144 STAILQ_INSERT_TAIL(&(dfs->dfs_radarq), event, re_list);
2145
2146 empty = STAILQ_EMPTY(&dfs->dfs_radarq);
2147
2148 ATH_DFSQ_UNLOCK(dfs);
2149
2150 if (!empty && !dfs->ath_radar_tasksched) {
2151 dfs->ath_radar_tasksched = 1;
2152 OS_SET_TIMER(&dfs->ath_dfs_task_timer, 0);
2153 }
2154
2155 return 1;
2156
2157}
2158
2159/**
2160 * wma_unified_phyerr_rx_event_handler() - phyerr event handler
2161 * @handle: wma handle
2162 * @data: data buffer
2163 * @datalen: buffer length
2164 *
2165 * WMI Handler for WMI_PHYERR_EVENTID event from firmware.
2166 * This handler is currently handling only DFS phy errors.
2167 * This handler will be invoked only when the DFS phyerror
2168 * filtering offload is disabled.
2169 *
2170 * Return: 1:Success, 0:Failure
2171 */
2172static int wma_unified_phyerr_rx_event_handler(void *handle,
2173 uint8_t *data, uint32_t datalen)
2174{
2175 tp_wma_handle wma = (tp_wma_handle) handle;
2176 WMI_PHYERR_EVENTID_param_tlvs *param_tlvs;
2177 wmi_comb_phyerr_rx_hdr *pe_hdr;
2178 uint8_t *bufp;
2179 wmi_single_phyerr_rx_event *ev;
2180 struct ieee80211com *ic = wma->dfs_ic;
2181 cdf_size_t n;
2182 A_UINT64 tsf64 = 0;
2183 int phy_err_code = 0;
2184 int error = 0;
2185 tpAniSirGlobal mac_ctx =
2186 (tpAniSirGlobal)cds_get_context(CDF_MODULE_ID_PE);
2187 bool enable_log = false;
2188
2189 if (NULL == mac_ctx) {
2190 WMA_LOGE("%s: mac_ctx is NULL", __func__);
2191 return 0;
2192 }
2193 enable_log = mac_ctx->sap.enable_dfs_phy_error_logs;
2194
2195 param_tlvs = (WMI_PHYERR_EVENTID_param_tlvs *) data;
2196
2197 if (!param_tlvs) {
2198 WMA_LOGE("%s: Received NULL data from FW", __func__);
2199 return 0;
2200 }
2201
2202 pe_hdr = param_tlvs->hdr;
2203 if (pe_hdr == NULL) {
2204 WMA_LOGE("%s: Received Data PE Header is NULL", __func__);
2205 return 0;
2206 }
2207
2208 /* Ensure it's at least the size of the header */
2209 if (datalen < sizeof(*pe_hdr)) {
2210 WMA_LOGE("%s: Expected minimum size %zu, received %d",
2211 __func__, sizeof(*pe_hdr), datalen);
2212 return 0;
2213 }
2214 if (pe_hdr->buf_len > DFS_MAX_BUF_LENGHT) {
2215 WMA_LOGE("%s: Received Invalid Phyerror event buffer length = %d"
2216 "Maximum allowed buf length = %d", __func__,
2217 pe_hdr->buf_len, DFS_MAX_BUF_LENGHT);
2218
2219 return 0;
2220 }
2221
2222 /*
2223 * Reconstruct the 64 bit event TSF. This isn't from the MAC, it's
2224 * at the time the event was sent to us, the TSF value will be
2225 * in the future.
2226 */
2227 tsf64 = pe_hdr->tsf_l32;
2228 tsf64 |= (((uint64_t) pe_hdr->tsf_u32) << 32);
2229
2230 /*
2231 * Loop over the bufp, extracting out phyerrors
2232 * wmi_unified_comb_phyerr_rx_event.bufp is a char pointer,
2233 * which isn't correct here - what we have received here
2234 * is an array of TLV-style PHY errors.
2235 */
2236 n = 0; /* Start just after the header */
2237 bufp = param_tlvs->bufp;
2238 while (n < pe_hdr->buf_len) {
2239 /* ensure there's at least space for the header */
2240 if ((pe_hdr->buf_len - n) < sizeof(ev->hdr)) {
2241 WMA_LOGE("%s: Not enough space.(datalen=%d, n=%zu, hdr=%zu bytes",
2242 __func__, pe_hdr->buf_len, n, sizeof(ev->hdr));
2243 error = 1;
2244 break;
2245 }
2246 /*
2247 * Obtain a pointer to the beginning of the current event.
2248 * data[0] is the beginning of the WMI payload.
2249 */
2250 ev = (wmi_single_phyerr_rx_event *) &bufp[n];
2251
2252 /*
2253 * Sanity check the buffer length of the event against
2254 * what we currently have.
2255 * Since buf_len is 32 bits, we check if it overflows
2256 * a large 32 bit value. It's not 0x7fffffff because
2257 * we increase n by (buf_len + sizeof(hdr)), which would
2258 * in itself cause n to overflow.
2259 * If "int" is 64 bits then this becomes a moot point.
2260 */
2261 if (ev->hdr.buf_len > 0x7f000000) {
2262 WMA_LOGE("%s:buf_len is garbage (0x%x)", __func__,
2263 ev->hdr.buf_len);
2264 error = 1;
2265 break;
2266 }
2267 if (n + ev->hdr.buf_len > pe_hdr->buf_len) {
2268 WMA_LOGE("%s: buf_len exceeds available space n=%zu,"
2269 "buf_len=%d, datalen=%d",
2270 __func__, n, ev->hdr.buf_len, pe_hdr->buf_len);
2271 error = 1;
2272 break;
2273 }
2274 phy_err_code = WMI_UNIFIED_PHYERRCODE_GET(&ev->hdr);
2275
2276 /*
2277 * If the phyerror category matches,
2278 * pass radar events to the dfs pattern matching code.
2279 * Don't pass radar events with no buffer payload.
2280 */
2281 if (phy_err_code == 0x5 || phy_err_code == 0x24) {
2282 if (ev->hdr.buf_len > 0) {
2283 /* Calling in to the DFS module to process the phyerr */
2284 dfs_process_phyerr(ic, &ev->bufp[0],
2285 ev->hdr.buf_len,
2286 WMI_UNIFIED_RSSI_COMB_GET
2287 (&ev->hdr) & 0xff,
2288 /* Extension RSSI */
2289 WMI_UNIFIED_RSSI_COMB_GET
2290 (&ev->hdr) & 0xff,
2291 ev->hdr.tsf_timestamp,
2292 tsf64, enable_log);
2293 }
2294 }
2295
2296 /*
2297 * Advance the buffer pointer to the next PHY error.
2298 * buflen is the length of this payload, so we need to
2299 * advance past the current header _AND_ the payload.
2300 */
2301 n += sizeof(*ev) + ev->hdr.buf_len;
2302
2303 } /*end while() */
2304 if (error)
2305 return 0;
2306 else
2307 return 1;
2308}
2309
2310/**
2311 * wma_register_dfs_event_handler() - register dfs event handler
2312 * @wma_handle: wma handle
2313 *
2314 * Register appropriate dfs phyerror event handler
2315 * based on phyerror filtering offload is enabled
2316 * or disabled.
2317 *
2318 * Return: none
2319 */
2320void wma_register_dfs_event_handler(tp_wma_handle wma_handle)
2321{
2322 if (NULL == wma_handle) {
2323 WMA_LOGE("%s:wma_handle is NULL", __func__);
2324 return;
2325 }
2326
2327 if (false == wma_handle->dfs_phyerr_filter_offload) {
2328 /*
2329 * Register the wma_unified_phyerr_rx_event_handler
2330 * for filtering offload disabled case to handle
2331 * the DFS phyerrors.
2332 */
2333 WMA_LOGD("%s:Phyerror Filtering offload is Disabled in ini",
2334 __func__);
2335 wmi_unified_register_event_handler(wma_handle->wmi_handle,
2336 WMI_PHYERR_EVENTID,
2337 wma_unified_phyerr_rx_event_handler);
2338 WMA_LOGD("%s: WMI_PHYERR_EVENTID event handler registered",
2339 __func__);
2340 } else {
2341 WMA_LOGD("%s:Phyerror Filtering offload is Enabled in ini",
2342 __func__);
2343 wmi_unified_register_event_handler(wma_handle->wmi_handle,
2344 WMI_DFS_RADAR_EVENTID,
2345 wma_unified_dfs_radar_rx_event_handler);
2346 WMA_LOGD("%s:WMI_DFS_RADAR_EVENTID event handler registered",
2347 __func__);
2348 }
2349
2350 return;
2351}
2352
2353
2354/**
2355 * wma_unified_dfs_phyerr_filter_offload_enable() - enable dfs phyerr filter
2356 * @wma_handle: wma handle
2357 *
2358 * Send WMI_DFS_PHYERR_FILTER_ENA_CMDID or
2359 * WMI_DFS_PHYERR_FILTER_DIS_CMDID command
2360 * to firmware based on phyerr filtering
2361 * offload status.
2362 *
2363 * Return: 1 success, 0 failure
2364 */
2365int
2366wma_unified_dfs_phyerr_filter_offload_enable(tp_wma_handle wma_handle)
2367{
2368 wmi_dfs_phyerr_filter_ena_cmd_fixed_param *enable_phyerr_offload_cmd;
2369 wmi_dfs_phyerr_filter_dis_cmd_fixed_param *disable_phyerr_offload_cmd;
2370 wmi_buf_t buf;
2371 uint16_t len;
2372 int ret;
2373
2374 if (NULL == wma_handle) {
2375 WMA_LOGE("%s:wma_handle is NULL", __func__);
2376 return 0;
2377 }
2378
2379 if (false == wma_handle->dfs_phyerr_filter_offload) {
2380 WMA_LOGD("%s:Phyerror Filtering offload is Disabled in ini",
2381 __func__);
2382 len = sizeof(*disable_phyerr_offload_cmd);
2383 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
2384 if (!buf) {
2385 WMA_LOGE("%s:wmi_buf_alloc failed", __func__);
2386 return 0;
2387 }
2388 disable_phyerr_offload_cmd =
2389 (wmi_dfs_phyerr_filter_dis_cmd_fixed_param *)
2390 wmi_buf_data(buf);
2391
2392 WMITLV_SET_HDR(&disable_phyerr_offload_cmd->tlv_header,
2393 WMITLV_TAG_STRUC_wmi_dfs_phyerr_filter_dis_cmd_fixed_param,
2394 WMITLV_GET_STRUCT_TLVLEN
2395 (wmi_dfs_phyerr_filter_dis_cmd_fixed_param));
2396
2397 /*
2398 * Send WMI_DFS_PHYERR_FILTER_DIS_CMDID
2399 * to the firmware to disable the phyerror
2400 * filtering offload.
2401 */
2402 ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len,
2403 WMI_DFS_PHYERR_FILTER_DIS_CMDID);
2404 if (ret < 0) {
2405 WMA_LOGE("%s: Failed to send WMI_DFS_PHYERR_FILTER_DIS_CMDID ret=%d",
2406 __func__, ret);
2407 wmi_buf_free(buf);
2408 return 0;
2409 }
2410 WMA_LOGD("%s: WMI_DFS_PHYERR_FILTER_DIS_CMDID Send Success",
2411 __func__);
2412 } else {
2413 WMA_LOGD("%s:Phyerror Filtering offload is Enabled in ini",
2414 __func__);
2415
2416 len = sizeof(*enable_phyerr_offload_cmd);
2417 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
2418 if (!buf) {
2419 WMA_LOGE("%s:wmi_buf_alloc failed", __func__);
2420 return 0;
2421 }
2422
2423 enable_phyerr_offload_cmd =
2424 (wmi_dfs_phyerr_filter_ena_cmd_fixed_param *)
2425 wmi_buf_data(buf);
2426
2427 WMITLV_SET_HDR(&enable_phyerr_offload_cmd->tlv_header,
2428 WMITLV_TAG_STRUC_wmi_dfs_phyerr_filter_ena_cmd_fixed_param,
2429 WMITLV_GET_STRUCT_TLVLEN
2430 (wmi_dfs_phyerr_filter_ena_cmd_fixed_param));
2431
2432 /*
2433 * Send a WMI_DFS_PHYERR_FILTER_ENA_CMDID
2434 * to the firmware to enable the phyerror
2435 * filtering offload.
2436 */
2437 ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len,
2438 WMI_DFS_PHYERR_FILTER_ENA_CMDID);
2439
2440 if (ret < 0) {
2441 WMA_LOGE("%s: Failed to send WMI_DFS_PHYERR_FILTER_ENA_CMDID ret=%d",
2442 __func__, ret);
2443 wmi_buf_free(buf);
2444 return 0;
2445 }
2446 WMA_LOGD("%s: WMI_DFS_PHYERR_FILTER_ENA_CMDID Send Success",
2447 __func__);
2448 }
2449
2450 return 1;
2451}
2452
2453#if !defined(REMOVE_PKT_LOG)
2454/**
2455 * wma_pktlog_wmi_send_cmd() - send pktlog enable/disable command to target
2456 * @handle: wma handle
2457 * @params: pktlog params
2458 *
2459 * Return: CDF status
2460 */
2461CDF_STATUS wma_pktlog_wmi_send_cmd(WMA_HANDLE handle,
2462 struct ath_pktlog_wmi_params *params)
2463{
2464 tp_wma_handle wma_handle = (tp_wma_handle) handle;
2465 WMI_PKTLOG_EVENT PKTLOG_EVENT;
2466 WMI_CMD_ID CMD_ID;
2467 wmi_pdev_pktlog_enable_cmd_fixed_param *cmd;
2468 wmi_pdev_pktlog_disable_cmd_fixed_param *disable_cmd;
2469 int len = 0;
2470 wmi_buf_t buf;
2471
2472 /*Check if packet log is enabled in cfg.ini */
2473 if (!cds_is_packet_log_enabled()) {
2474 WMA_LOGE("%s:pkt log is not enabled in cfg.ini", __func__);
2475 return CDF_STATUS_E_FAILURE;
2476 }
2477
2478 PKTLOG_EVENT = params->pktlog_event;
2479 CMD_ID = params->cmd_id;
2480
2481 switch (CMD_ID) {
2482 case WMI_PDEV_PKTLOG_ENABLE_CMDID:
2483 len = sizeof(*cmd);
2484 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
2485 if (!buf) {
2486 WMA_LOGE("%s:wmi_buf_alloc failed", __func__);
2487 return CDF_STATUS_E_NOMEM;
2488 }
2489 cmd = (wmi_pdev_pktlog_enable_cmd_fixed_param *)
2490 wmi_buf_data(buf);
2491 WMITLV_SET_HDR(&cmd->tlv_header,
2492 WMITLV_TAG_STRUC_wmi_pdev_pktlog_enable_cmd_fixed_param,
2493 WMITLV_GET_STRUCT_TLVLEN
2494 (wmi_pdev_pktlog_enable_cmd_fixed_param));
2495 cmd->evlist = PKTLOG_EVENT;
2496 if (wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len,
2497 WMI_PDEV_PKTLOG_ENABLE_CMDID)) {
2498 WMA_LOGE("failed to send pktlog enable cmdid");
2499 goto wmi_send_failed;
2500 }
2501 break;
2502 case WMI_PDEV_PKTLOG_DISABLE_CMDID:
2503 len = sizeof(*disable_cmd);
2504 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
2505 if (!buf) {
2506 WMA_LOGE("%s:wmi_buf_alloc failed", __func__);
2507 return CDF_STATUS_E_NOMEM;
2508 }
2509 disable_cmd = (wmi_pdev_pktlog_disable_cmd_fixed_param *)
2510 wmi_buf_data(buf);
2511 WMITLV_SET_HDR(&disable_cmd->tlv_header,
2512 WMITLV_TAG_STRUC_wmi_pdev_pktlog_disable_cmd_fixed_param,
2513 WMITLV_GET_STRUCT_TLVLEN
2514 (wmi_pdev_pktlog_disable_cmd_fixed_param));
2515 disable_cmd->reserved0 = 0;
2516 if (wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len,
2517 WMI_PDEV_PKTLOG_DISABLE_CMDID)) {
2518 WMA_LOGE("failed to send pktlog disable cmdid");
2519 goto wmi_send_failed;
2520 }
2521 break;
2522 default:
2523 WMA_LOGD("%s: invalid PKTLOG command", __func__);
2524 break;
2525 }
2526
2527 return CDF_STATUS_SUCCESS;
2528
2529wmi_send_failed:
2530 wmi_buf_free(buf);
2531 return CDF_STATUS_E_FAILURE;
2532}
2533#endif /* REMOVE_PKT_LOG */
2534
2535static void wma_send_status_to_suspend_ind(tp_wma_handle wma, bool suspended)
2536{
2537 tSirReadyToSuspendInd *ready_to_suspend;
2538 CDF_STATUS status;
2539 cds_msg_t cds_msg;
2540 uint8_t len;
2541
2542 WMA_LOGD("Posting ready to suspend indication to umac");
2543
2544 len = sizeof(tSirReadyToSuspendInd);
2545 ready_to_suspend = (tSirReadyToSuspendInd *) cdf_mem_malloc(len);
2546
2547 if (NULL == ready_to_suspend) {
2548 WMA_LOGE("%s: Memory allocation failure", __func__);
2549 return;
2550 }
2551
2552 ready_to_suspend->mesgType = eWNI_SME_READY_TO_SUSPEND_IND;
2553 ready_to_suspend->mesgLen = len;
2554 ready_to_suspend->suspended = suspended;
2555
2556 cds_msg.type = eWNI_SME_READY_TO_SUSPEND_IND;
2557 cds_msg.bodyptr = (void *)ready_to_suspend;
2558 cds_msg.bodyval = 0;
2559
2560 status = cds_mq_post_message(CDS_MQ_ID_SME, &cds_msg);
2561 if (status != CDF_STATUS_SUCCESS) {
2562 WMA_LOGE("Failed to post ready to suspend");
2563 cdf_mem_free(ready_to_suspend);
2564 }
2565}
2566
2567/**
2568 * wma_wow_wake_reason_str() - Converts wow wakeup reason code to text format
2569 * @wake_reason - WOW wake reason
2570 *
2571 * Return: reason code in string format
2572 */
2573static const u8 *wma_wow_wake_reason_str(A_INT32 wake_reason)
2574{
2575 switch (wake_reason) {
2576 case WOW_REASON_UNSPECIFIED:
2577 return "UNSPECIFIED";
2578 case WOW_REASON_NLOD:
2579 return "NLOD";
2580 case WOW_REASON_AP_ASSOC_LOST:
2581 return "AP_ASSOC_LOST";
2582 case WOW_REASON_LOW_RSSI:
2583 return "LOW_RSSI";
2584 case WOW_REASON_DEAUTH_RECVD:
2585 return "DEAUTH_RECVD";
2586 case WOW_REASON_DISASSOC_RECVD:
2587 return "DISASSOC_RECVD";
2588 case WOW_REASON_GTK_HS_ERR:
2589 return "GTK_HS_ERR";
2590 case WOW_REASON_EAP_REQ:
2591 return "EAP_REQ";
2592 case WOW_REASON_FOURWAY_HS_RECV:
2593 return "FOURWAY_HS_RECV";
2594 case WOW_REASON_TIMER_INTR_RECV:
2595 return "TIMER_INTR_RECV";
2596 case WOW_REASON_PATTERN_MATCH_FOUND:
2597 return "PATTERN_MATCH_FOUND";
2598 case WOW_REASON_RECV_MAGIC_PATTERN:
2599 return "RECV_MAGIC_PATTERN";
2600 case WOW_REASON_P2P_DISC:
2601 return "P2P_DISC";
2602#ifdef FEATURE_WLAN_LPHB
2603 case WOW_REASON_WLAN_HB:
2604 return "WLAN_HB";
2605#endif /* FEATURE_WLAN_LPHB */
2606
2607 case WOW_REASON_CSA_EVENT:
2608 return "CSA_EVENT";
2609 case WOW_REASON_PROBE_REQ_WPS_IE_RECV:
2610 return "PROBE_REQ_RECV";
2611 case WOW_REASON_AUTH_REQ_RECV:
2612 return "AUTH_REQ_RECV";
2613 case WOW_REASON_ASSOC_REQ_RECV:
2614 return "ASSOC_REQ_RECV";
2615 case WOW_REASON_HTT_EVENT:
2616 return "WOW_REASON_HTT_EVENT";
2617#ifdef FEATURE_WLAN_RA_FILTERING
2618 case WOW_REASON_RA_MATCH:
2619 return "WOW_REASON_RA_MATCH";
2620#endif /* FEATURE_WLAN_RA_FILTERING */
2621 case WOW_REASON_BEACON_RECV:
2622 return "WOW_REASON_IBSS_BEACON_RECV";
2623#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
2624 case WOW_REASON_HOST_AUTO_SHUTDOWN:
2625 return "WOW_REASON_HOST_AUTO_SHUTDOWN";
2626#endif /* FEATURE_WLAN_AUTO_SHUTDOWN */
2627#ifdef WLAN_FEATURE_ROAM_OFFLOAD
2628 case WOW_REASON_ROAM_HO:
2629 return "WOW_REASON_ROAM_HO";
2630#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
2631#ifdef FEATURE_WLAN_EXTSCAN
2632 case WOW_REASON_EXTSCAN:
2633 return "WOW_REASON_EXTSCAN";
2634#endif
2635 case WOW_REASON_RSSI_BREACH_EVENT:
2636 return "WOW_REASON_RSSI_BREACH_EVENT";
Srinivas Girigowdae80cea92015-11-23 11:33:57 -08002637 case WOW_REASON_NLO_SCAN_COMPLETE:
2638 return "WOW_REASON_NLO_SCAN_COMPLETE";
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002639 }
2640 return "unknown";
2641}
2642
2643/**
2644 * wma_wow_wake_up_stats_display() - display wow wake up stats
2645 * @wma: Pointer to wma handle
2646 *
2647 * Return: none
2648 */
2649static void wma_wow_wake_up_stats_display(tp_wma_handle wma)
2650{
2651 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",
2652 wma->wow_ucast_wake_up_count,
2653 wma->wow_bcast_wake_up_count,
2654 wma->wow_ipv4_mcast_wake_up_count,
2655 wma->wow_ipv6_mcast_wake_up_count,
2656 wma->wow_ipv6_mcast_ra_stats,
2657 wma->wow_ipv6_mcast_ns_stats,
2658 wma->wow_ipv6_mcast_na_stats,
2659 wma->wow_pno_match_wake_up_count,
2660 wma->wow_pno_complete_wake_up_count,
2661 wma->wow_gscan_wake_up_count,
2662 wma->wow_low_rssi_wake_up_count,
2663 wma->wow_rssi_breach_wake_up_count);
2664
2665 return;
2666}
2667
2668/**
2669 * wma_wow_ipv6_mcast_stats() - ipv6 mcast wake up stats
2670 * @wma: Pointer to wma handle
2671 * @data: Pointer to pattern match data
2672 *
2673 * Return: none
2674 */
2675static void wma_wow_ipv6_mcast_stats(tp_wma_handle wma, uint8_t *data)
2676{
2677 static const uint8_t ipv6_mcast[] = {0x86, 0xDD};
2678
2679 if (!memcmp(ipv6_mcast, (data + WMA_ETHER_TYPE_OFFSET),
2680 sizeof(ipv6_mcast))) {
2681 if (WMA_ICMP_V6_HEADER_TYPE ==
2682 *(data + WMA_ICMP_V6_HEADER_OFFSET)) {
2683 if (WMA_ICMP_V6_RA_TYPE ==
2684 *(data + WMA_ICMP_V6_TYPE_OFFSET))
2685 wma->wow_ipv6_mcast_ra_stats++;
2686 else if (WMA_ICMP_V6_NS_TYPE ==
2687 *(data + WMA_ICMP_V6_TYPE_OFFSET))
2688 wma->wow_ipv6_mcast_ns_stats++;
2689 else if (WMA_ICMP_V6_NA_TYPE ==
2690 *(data + WMA_ICMP_V6_TYPE_OFFSET))
2691 wma->wow_ipv6_mcast_na_stats++;
2692 else
2693 WMA_LOGA("ICMP V6 type : 0x%x",
2694 *(data + WMA_ICMP_V6_TYPE_OFFSET));
2695 } else {
2696 WMA_LOGA("ICMP_V6 header 0x%x",
2697 *(data + WMA_ICMP_V6_HEADER_OFFSET));
2698 }
2699 } else {
2700 WMA_LOGA("Ethertype x%x:0x%x",
2701 *(data + WMA_ETHER_TYPE_OFFSET),
2702 *(data + WMA_ETHER_TYPE_OFFSET + 1));
2703 }
2704
2705 return;
2706}
2707
2708/**
2709 * wma_wow_wake_up_stats() - maintain wow pattern match wake up stats
2710 * @wma: Pointer to wma handle
2711 * @data: Pointer to pattern match data
2712 * @len: Pattern match data length
2713 * @event: Wake up event
2714 *
2715 * Return: none
2716 */
2717static void wma_wow_wake_up_stats(tp_wma_handle wma, uint8_t *data,
2718 int32_t len, WOW_WAKE_REASON_TYPE event)
2719{
2720 switch (event) {
2721
2722 case WOW_REASON_PATTERN_MATCH_FOUND:
2723 if (WMA_BCAST_MAC_ADDR == *data) {
2724 wma->wow_bcast_wake_up_count++;
2725 } else if (WMA_MCAST_IPV4_MAC_ADDR == *data) {
2726 wma->wow_ipv4_mcast_wake_up_count++;
2727 } else if (WMA_MCAST_IPV6_MAC_ADDR == *data) {
2728 wma->wow_ipv6_mcast_wake_up_count++;
2729 if (len > WMA_ICMP_V6_TYPE_OFFSET)
2730 wma_wow_ipv6_mcast_stats(wma, data);
2731 else
2732 WMA_LOGA("ICMP_V6 data len %d", len);
2733 } else {
2734 wma->wow_ucast_wake_up_count++;
2735 }
2736 break;
2737
2738 case WOW_REASON_RA_MATCH:
2739 wma->wow_ipv6_mcast_ra_stats++;
2740 break;
2741
2742 case WOW_REASON_NLOD:
2743 wma->wow_pno_match_wake_up_count++;
2744 break;
2745
2746 case WOW_REASON_NLO_SCAN_COMPLETE:
2747 wma->wow_pno_complete_wake_up_count++;
2748 break;
2749
2750 case WOW_REASON_LOW_RSSI:
2751 wma->wow_low_rssi_wake_up_count++;
2752 break;
2753
2754 case WOW_REASON_EXTSCAN:
2755 wma->wow_gscan_wake_up_count++;
2756 break;
2757
2758 case WOW_REASON_RSSI_BREACH_EVENT:
2759 wma->wow_rssi_breach_wake_up_count++;
2760 break;
2761
2762 default:
2763 WMA_LOGE("Unknown wake up reason");
2764 break;
2765 }
2766
2767 wma_wow_wake_up_stats_display(wma);
2768 return;
2769}
2770
2771/**
2772 * wma_wow_wakeup_host_event() - wakeup host event handler
2773 * @handle: wma handle
2774 * @event: event data
2775 * @len: buffer length
2776 *
2777 * Handler to catch wow wakeup host event. This event will have
2778 * reason why the firmware has woken the host.
2779 *
2780 * Return: 0 for success or error
2781 */
2782int wma_wow_wakeup_host_event(void *handle, uint8_t *event,
2783 uint32_t len)
2784{
2785 tp_wma_handle wma = (tp_wma_handle) handle;
2786 WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs *param_buf;
2787 WOW_EVENT_INFO_fixed_param *wake_info;
2788#ifdef FEATURE_WLAN_SCAN_PNO
2789 struct wma_txrx_node *node;
2790#endif /* FEATURE_WLAN_SCAN_PNO */
2791 uint32_t wake_lock_duration = 0;
2792 uint32_t wow_buf_pkt_len = 0;
2793
2794 param_buf = (WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs *) event;
2795 if (!param_buf) {
2796 WMA_LOGE("Invalid wow wakeup host event buf");
2797 return -EINVAL;
2798 }
2799
2800 wake_info = param_buf->fixed_param;
2801
2802 WMA_LOGA("WOW wakeup host event received (reason: %s(%d)) for vdev %d",
2803 wma_wow_wake_reason_str(wake_info->wake_reason),
2804 wake_info->wake_reason, wake_info->vdev_id);
2805
2806 cdf_event_set(&wma->wma_resume_event);
2807
2808 switch (wake_info->wake_reason) {
2809 case WOW_REASON_AUTH_REQ_RECV:
2810 wake_lock_duration = WMA_AUTH_REQ_RECV_WAKE_LOCK_TIMEOUT;
2811 break;
2812
2813 case WOW_REASON_ASSOC_REQ_RECV:
2814 wake_lock_duration = WMA_ASSOC_REQ_RECV_WAKE_LOCK_DURATION;
2815 break;
2816
2817 case WOW_REASON_DEAUTH_RECVD:
2818 wake_lock_duration = WMA_DEAUTH_RECV_WAKE_LOCK_DURATION;
2819 break;
2820
2821 case WOW_REASON_DISASSOC_RECVD:
2822 wake_lock_duration = WMA_DISASSOC_RECV_WAKE_LOCK_DURATION;
2823 break;
2824
2825 case WOW_REASON_AP_ASSOC_LOST:
2826 wake_lock_duration = WMA_BMISS_EVENT_WAKE_LOCK_DURATION;
2827 WMA_LOGA("Beacon miss indication on vdev %x",
2828 wake_info->vdev_id);
2829 wma_beacon_miss_handler(wma, wake_info->vdev_id);
2830 break;
2831#ifdef FEATURE_WLAN_RA_FILTERING
2832 case WOW_REASON_RA_MATCH:
2833 wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_RA_MATCH);
2834 break;
2835#endif /* FEATURE_WLAN_RA_FILTERING */
2836#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
2837 case WOW_REASON_HOST_AUTO_SHUTDOWN:
2838 wake_lock_duration = WMA_AUTO_SHUTDOWN_WAKE_LOCK_DURATION;
2839 WMA_LOGA("Received WOW Auto Shutdown trigger in suspend");
2840 if (wma_post_auto_shutdown_msg())
2841 return -EINVAL;
2842 break;
2843#endif /* FEATURE_WLAN_AUTO_SHUTDOWN */
2844#ifdef FEATURE_WLAN_SCAN_PNO
2845 case WOW_REASON_NLOD:
2846 wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_NLOD);
2847 node = &wma->interfaces[wake_info->vdev_id];
2848 if (node) {
2849 WMA_LOGD("NLO match happened");
2850 node->nlo_match_evt_received = true;
2851 cdf_wake_lock_timeout_acquire(&wma->pno_wake_lock,
2852 WMA_PNO_MATCH_WAKE_LOCK_TIMEOUT,
2853 WIFI_POWER_EVENT_WAKELOCK_PNO);
Srinivas Girigowdae80cea92015-11-23 11:33:57 -08002854 }
2855 break;
2856
2857 case WOW_REASON_NLO_SCAN_COMPLETE:
2858 {
2859 WMI_NLO_SCAN_COMPLETE_EVENTID_param_tlvs param;
2860
2861 WMA_LOGD("Host woken up due to pno scan complete reason");
2862
2863 /* First 4-bytes of wow_packet_buffer is the length */
2864 if (param_buf->wow_packet_buffer) {
2865 param.fixed_param = (wmi_nlo_event *)
2866 (param_buf->wow_packet_buffer + 4);
2867 wma_nlo_scan_cmp_evt_handler(handle,
2868 (u_int8_t *)&param, sizeof(param));
2869 } else
2870 WMA_LOGD("No wow_packet_buffer present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002871 }
2872 break;
2873#endif /* FEATURE_WLAN_SCAN_PNO */
2874
2875 case WOW_REASON_CSA_EVENT:
2876 {
2877 WMI_CSA_HANDLING_EVENTID_param_tlvs param;
2878 WMA_LOGD("Host woken up because of CSA IE");
2879 param.fixed_param = (wmi_csa_event_fixed_param *)
2880 (((uint8_t *) wake_info)
2881 + sizeof(WOW_EVENT_INFO_fixed_param)
2882 + WOW_CSA_EVENT_OFFSET);
2883 wma_csa_offload_handler(handle, (uint8_t *) &param,
2884 sizeof(param));
2885 }
2886 break;
2887
2888#ifdef FEATURE_WLAN_LPHB
2889 case WOW_REASON_WLAN_HB:
2890 wma_lphb_handler(wma, (uint8_t *) param_buf->hb_indevt);
2891 break;
2892#endif /* FEATURE_WLAN_LPHB */
2893
2894 case WOW_REASON_HTT_EVENT:
2895 break;
2896 case WOW_REASON_PATTERN_MATCH_FOUND:
2897 wma_wow_wake_up_stats_display(wma);
2898 WMA_LOGD("Wake up for Rx packet, dump starting from ethernet hdr");
2899 if (param_buf->wow_packet_buffer) {
2900 /* First 4-bytes of wow_packet_buffer is the length */
2901 cdf_mem_copy((uint8_t *) &wow_buf_pkt_len,
2902 param_buf->wow_packet_buffer, 4);
2903 wma_wow_wake_up_stats(wma,
2904 param_buf->wow_packet_buffer + 4,
2905 wow_buf_pkt_len,
2906 WOW_REASON_PATTERN_MATCH_FOUND);
2907 cdf_trace_hex_dump(CDF_MODULE_ID_WMA,
2908 CDF_TRACE_LEVEL_DEBUG,
2909 param_buf->wow_packet_buffer + 4,
2910 wow_buf_pkt_len);
2911 } else {
2912 WMA_LOGE("No wow packet buffer present");
2913 }
2914 break;
2915
2916 case WOW_REASON_LOW_RSSI:
2917 {
2918 /* WOW_REASON_LOW_RSSI is used for all roaming events.
2919 * WMI_ROAM_REASON_BETTER_AP, WMI_ROAM_REASON_BMISS,
2920 * WMI_ROAM_REASON_SUITABLE_AP will be handled by
2921 * wma_roam_event_callback().
2922 */
2923 WMI_ROAM_EVENTID_param_tlvs param;
2924 wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_LOW_RSSI);
2925 if (param_buf->wow_packet_buffer) {
2926 /* Roam event is embedded in wow_packet_buffer */
2927 WMA_LOGD("Host woken up because of roam event");
2928 cdf_mem_copy((uint8_t *) &wow_buf_pkt_len,
2929 param_buf->wow_packet_buffer, 4);
2930 WMA_LOGD("wow_packet_buffer dump");
2931 cdf_trace_hex_dump(CDF_MODULE_ID_WMA,
2932 CDF_TRACE_LEVEL_DEBUG,
2933 param_buf->wow_packet_buffer,
2934 wow_buf_pkt_len);
2935 if (wow_buf_pkt_len >= sizeof(param)) {
2936 param.fixed_param =
2937 (wmi_roam_event_fixed_param *)
2938 (param_buf->wow_packet_buffer + 4);
2939 wma_roam_event_callback(handle,
2940 (uint8_t *) &
2941 param,
2942 sizeof(param));
2943 } else {
2944 WMA_LOGE("Wrong length for roam event = %d bytes",
2945 wow_buf_pkt_len);
2946 }
2947 } else {
2948 /* No wow_packet_buffer means a better AP beacon
2949 * will follow in a later event.
2950 */
2951 WMA_LOGD("Host woken up because of better AP beacon");
2952 }
2953 break;
2954 }
2955 case WOW_REASON_CLIENT_KICKOUT_EVENT:
2956 {
2957 WMI_PEER_STA_KICKOUT_EVENTID_param_tlvs param;
2958 if (param_buf->wow_packet_buffer) {
2959 /* station kickout event embedded in wow_packet_buffer */
2960 WMA_LOGD("Host woken up because of sta_kickout event");
2961 cdf_mem_copy((u_int8_t *) &wow_buf_pkt_len,
2962 param_buf->wow_packet_buffer, 4);
2963 WMA_LOGD("wow_packet_buffer dump");
2964 cdf_trace_hex_dump(CDF_MODULE_ID_WMA,
2965 CDF_TRACE_LEVEL_DEBUG,
2966 param_buf->wow_packet_buffer, wow_buf_pkt_len);
2967 if (wow_buf_pkt_len >= sizeof(param)) {
2968 param.fixed_param = (wmi_peer_sta_kickout_event_fixed_param *)
2969 (param_buf->wow_packet_buffer + 4);
2970 wma_peer_sta_kickout_event_handler(handle,
2971 (u_int8_t *)&param, sizeof(param));
2972 } else {
2973 WMA_LOGE("Wrong length for sta_kickout event = %d bytes",
2974 wow_buf_pkt_len);
2975 }
2976 } else {
2977 WMA_LOGD("No wow_packet_buffer present");
2978 }
2979 break;
2980 }
2981#ifdef FEATURE_WLAN_EXTSCAN
2982 case WOW_REASON_EXTSCAN:
2983 WMA_LOGD("Host woken up because of extscan reason");
2984 wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_EXTSCAN);
2985 if (param_buf->wow_packet_buffer) {
2986 wow_buf_pkt_len =
2987 *(uint32_t *)param_buf->wow_packet_buffer;
2988 wma_extscan_wow_event_callback(handle,
2989 (u_int8_t *)(param_buf->wow_packet_buffer + 4),
2990 wow_buf_pkt_len);
2991 } else
2992 WMA_LOGE("wow_packet_buffer is empty");
2993 break;
2994#endif
2995 case WOW_REASON_RSSI_BREACH_EVENT:
2996 {
2997 WMI_RSSI_BREACH_EVENTID_param_tlvs param;
2998
2999 wma_wow_wake_up_stats(wma, NULL, 0,
3000 WOW_REASON_RSSI_BREACH_EVENT);
3001 WMA_LOGD("Host woken up because of rssi breach reason");
3002 /* rssi breach event is embedded in wow_packet_buffer */
3003 if (param_buf->wow_packet_buffer) {
3004 cdf_mem_copy((u_int8_t *) &wow_buf_pkt_len,
3005 param_buf->wow_packet_buffer, 4);
3006 if (wow_buf_pkt_len >= sizeof(param)) {
3007 param.fixed_param =
3008 (wmi_rssi_breach_event_fixed_param *)
3009 (param_buf->wow_packet_buffer + 4);
3010 wma_rssi_breached_event_handler(handle,
3011 (u_int8_t *)&param,
3012 sizeof(param));
3013 } else {
3014 WMA_LOGE("%s: Wrong length: %d bytes",
3015 __func__, wow_buf_pkt_len);
3016 }
3017 } else
3018 WMA_LOGD("No wow_packet_buffer present");
3019 }
3020 break;
3021 default:
3022 break;
3023 }
3024
3025 if (wake_lock_duration) {
3026 cdf_wake_lock_timeout_acquire(&wma->wow_wake_lock,
3027 wake_lock_duration,
3028 WIFI_POWER_EVENT_WAKELOCK_WOW);
3029 WMA_LOGA("Holding %d msec wake_lock", wake_lock_duration);
3030 }
3031
3032 return 0;
3033}
3034
3035/**
3036 * wma_pdev_resume_event_handler() - PDEV resume event handler
3037 * @handle: wma handle
3038 * @event: event data
3039 * @len: buffer length
3040 *
3041 * Return: 0 for success or error
3042 */
3043int wma_pdev_resume_event_handler(void *handle, uint8_t *event, uint32_t len)
3044{
3045 tp_wma_handle wma = (tp_wma_handle) handle;
3046
3047 WMA_LOGA("Received PDEV resume event");
3048
3049 cdf_event_set(&wma->wma_resume_event);
3050
3051 return 0;
3052}
3053/**
3054 * wma_set_wow_bus_suspend() - set suspend flag
3055 * @wma: wma handle
3056 * @val: value
3057 *
3058 * Return: none
3059 */
3060static inline void wma_set_wow_bus_suspend(tp_wma_handle wma, int val)
3061{
3062
3063 cdf_atomic_set(&wma->is_wow_bus_suspended, val);
3064}
3065
3066
3067
3068/**
3069 * wma_add_wow_wakeup_event() - Configures wow wakeup events.
3070 * @wma: wma handle
3071 * @vdev_id: vdev id
3072 * @bitmap: Event bitmap
3073 * @enable: enable/disable
3074 *
3075 * Return: CDF status
3076 */
3077static CDF_STATUS wma_add_wow_wakeup_event(tp_wma_handle wma,
3078 uint32_t vdev_id,
3079 uint32_t bitmap,
3080 bool enable)
3081{
3082 WMI_WOW_ADD_DEL_EVT_CMD_fixed_param *cmd;
3083 uint16_t len;
3084 wmi_buf_t buf;
3085 int ret;
3086
3087 len = sizeof(WMI_WOW_ADD_DEL_EVT_CMD_fixed_param);
3088 buf = wmi_buf_alloc(wma->wmi_handle, len);
3089 if (!buf) {
3090 WMA_LOGE("%s: Failed allocate wmi buffer", __func__);
3091 return CDF_STATUS_E_NOMEM;
3092 }
3093 cmd = (WMI_WOW_ADD_DEL_EVT_CMD_fixed_param *) wmi_buf_data(buf);
3094 WMITLV_SET_HDR(&cmd->tlv_header,
3095 WMITLV_TAG_STRUC_WMI_WOW_ADD_DEL_EVT_CMD_fixed_param,
3096 WMITLV_GET_STRUCT_TLVLEN
3097 (WMI_WOW_ADD_DEL_EVT_CMD_fixed_param));
3098 cmd->vdev_id = vdev_id;
3099 cmd->is_add = enable;
3100 cmd->event_bitmap = bitmap;
3101
3102 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
3103 WMI_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID);
3104 if (ret) {
3105 WMA_LOGE("Failed to config wow wakeup event");
3106 wmi_buf_free(buf);
3107 return CDF_STATUS_E_FAILURE;
3108 }
3109
3110 WMA_LOGD("Wakeup pattern 0x%x %s in fw", bitmap,
3111 enable ? "enabled" : "disabled");
3112
3113 return CDF_STATUS_SUCCESS;
3114}
3115
3116/**
3117 * wma_send_wow_patterns_to_fw() - Sends WOW patterns to FW.
3118 * @wma: wma handle
3119 * @vdev_id: vdev id
3120 * @ptrn_id: pattern id
3121 * @ptrn: pattern
3122 * @ptrn_len: pattern length
3123 * @ptrn_offset: pattern offset
3124 * @mask: mask
3125 * @mask_len: mask length
3126 * @user: true for user configured pattern and false for default pattern
3127 *
3128 * Return: CDF status
3129 */
3130static CDF_STATUS wma_send_wow_patterns_to_fw(tp_wma_handle wma,
3131 uint8_t vdev_id, uint8_t ptrn_id,
3132 const uint8_t *ptrn, uint8_t ptrn_len,
3133 uint8_t ptrn_offset, const uint8_t *mask,
3134 uint8_t mask_len, bool user)
3135{
3136 WMI_WOW_ADD_PATTERN_CMD_fixed_param *cmd;
3137 WOW_BITMAP_PATTERN_T *bitmap_pattern;
3138 struct wma_txrx_node *iface;
3139 wmi_buf_t buf;
3140 uint8_t *buf_ptr;
3141 int32_t len;
3142 int ret;
3143
3144 iface = &wma->interfaces[vdev_id];
3145
3146 len = sizeof(WMI_WOW_ADD_PATTERN_CMD_fixed_param) +
3147 WMI_TLV_HDR_SIZE +
3148 1 * sizeof(WOW_BITMAP_PATTERN_T) +
3149 WMI_TLV_HDR_SIZE +
3150 0 * sizeof(WOW_IPV4_SYNC_PATTERN_T) +
3151 WMI_TLV_HDR_SIZE +
3152 0 * sizeof(WOW_IPV6_SYNC_PATTERN_T) +
3153 WMI_TLV_HDR_SIZE +
3154 0 * sizeof(WOW_MAGIC_PATTERN_CMD) +
3155 WMI_TLV_HDR_SIZE +
3156 0 * sizeof(A_UINT32) + WMI_TLV_HDR_SIZE + 1 * sizeof(A_UINT32);
3157
3158 buf = wmi_buf_alloc(wma->wmi_handle, len);
3159 if (!buf) {
3160 WMA_LOGE("%s: Failed allocate wmi buffer", __func__);
3161 return CDF_STATUS_E_NOMEM;
3162 }
3163
3164 cmd = (WMI_WOW_ADD_PATTERN_CMD_fixed_param *) wmi_buf_data(buf);
3165 buf_ptr = (uint8_t *) cmd;
3166
3167 WMITLV_SET_HDR(&cmd->tlv_header,
3168 WMITLV_TAG_STRUC_WMI_WOW_ADD_PATTERN_CMD_fixed_param,
3169 WMITLV_GET_STRUCT_TLVLEN
3170 (WMI_WOW_ADD_PATTERN_CMD_fixed_param));
3171 cmd->vdev_id = vdev_id;
3172 /*
3173 * For user configured wow pattern use pattern id sent by HDD
3174 * and for default wow patterns generate pattern id internally
3175 */
3176 if (user)
3177 cmd->pattern_id = ptrn_id;
3178 else
3179 cmd->pattern_id = iface->num_wow_default_patterns++;
3180
3181 cmd->pattern_type = WOW_BITMAP_PATTERN;
3182 buf_ptr += sizeof(WMI_WOW_ADD_PATTERN_CMD_fixed_param);
3183
3184 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
3185 sizeof(WOW_BITMAP_PATTERN_T));
3186 buf_ptr += WMI_TLV_HDR_SIZE;
3187 bitmap_pattern = (WOW_BITMAP_PATTERN_T *) buf_ptr;
3188
3189 WMITLV_SET_HDR(&bitmap_pattern->tlv_header,
3190 WMITLV_TAG_STRUC_WOW_BITMAP_PATTERN_T,
3191 WMITLV_GET_STRUCT_TLVLEN(WOW_BITMAP_PATTERN_T));
3192
3193 cdf_mem_copy(&bitmap_pattern->patternbuf[0], ptrn, ptrn_len);
3194 cdf_mem_copy(&bitmap_pattern->bitmaskbuf[0], mask, mask_len);
3195
3196 bitmap_pattern->pattern_offset = ptrn_offset;
3197 bitmap_pattern->pattern_len = ptrn_len;
3198
3199 if (bitmap_pattern->pattern_len > WOW_DEFAULT_BITMAP_PATTERN_SIZE)
3200 bitmap_pattern->pattern_len = WOW_DEFAULT_BITMAP_PATTERN_SIZE;
3201
3202 if (bitmap_pattern->pattern_len > WOW_DEFAULT_BITMASK_SIZE)
3203 bitmap_pattern->pattern_len = WOW_DEFAULT_BITMASK_SIZE;
3204
3205 bitmap_pattern->bitmask_len = bitmap_pattern->pattern_len;
3206 bitmap_pattern->pattern_id = ptrn_id;
3207
3208 WMA_LOGI("vdev id : %d, ptrn id: %d, ptrn len: %d, ptrn offset: %d user %d",
3209 cmd->vdev_id, cmd->pattern_id, bitmap_pattern->pattern_len,
3210 bitmap_pattern->pattern_offset, user);
3211
3212 WMA_LOGI("Pattern : ");
3213 CDF_TRACE_HEX_DUMP(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_INFO,
3214 &bitmap_pattern->patternbuf[0], bitmap_pattern->pattern_len);
3215
3216 WMA_LOGI("Mask : ");
3217 CDF_TRACE_HEX_DUMP(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_INFO,
3218 &bitmap_pattern->bitmaskbuf[0], bitmap_pattern->pattern_len);
3219
3220 buf_ptr += sizeof(WOW_BITMAP_PATTERN_T);
3221
3222 /* Fill TLV for WMITLV_TAG_STRUC_WOW_IPV4_SYNC_PATTERN_T but no data. */
3223 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
3224 buf_ptr += WMI_TLV_HDR_SIZE;
3225
3226 /* Fill TLV for WMITLV_TAG_STRUC_WOW_IPV6_SYNC_PATTERN_T but no data. */
3227 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
3228 buf_ptr += WMI_TLV_HDR_SIZE;
3229
3230 /* Fill TLV for WMITLV_TAG_STRUC_WOW_MAGIC_PATTERN_CMD but no data. */
3231 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
3232 buf_ptr += WMI_TLV_HDR_SIZE;
3233
3234 /* Fill TLV for pattern_info_timeout but no data. */
3235 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, 0);
3236 buf_ptr += WMI_TLV_HDR_SIZE;
3237
3238 /* Fill TLV for ra_ratelimit_interval with dummy data as this fix elem */
3239 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, 1 * sizeof(A_UINT32));
3240 buf_ptr += WMI_TLV_HDR_SIZE;
3241 *(A_UINT32 *) buf_ptr = 0;
3242
3243 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
3244 WMI_WOW_ADD_WAKE_PATTERN_CMDID);
3245 if (ret) {
3246 WMA_LOGE("%s: Failed to send wow ptrn to fw", __func__);
3247 wmi_buf_free(buf);
3248 if (!user)
3249 iface->num_wow_default_patterns--;
3250 return CDF_STATUS_E_FAILURE;
3251 }
3252
3253 if (user)
3254 iface->num_wow_user_patterns++;
3255
3256 return CDF_STATUS_SUCCESS;
3257}
3258
3259/**
3260 * wma_wow_ap() - set WOW patterns in ap mode
3261 * @wma: wma handle
3262 * @vdev_id: vdev id
3263 *
3264 * Configures default WOW pattern for the given vdev_id which is in AP mode.
3265 *
3266 * Return: CDF status
3267 */
3268static CDF_STATUS wma_wow_ap(tp_wma_handle wma, uint8_t vdev_id)
3269{
3270 CDF_STATUS ret;
3271 uint8_t arp_offset = 20;
3272 uint8_t mac_mask[IEEE80211_ADDR_LEN];
3273
3274 /* Setup unicast pkt pattern */
3275 cdf_mem_set(&mac_mask, IEEE80211_ADDR_LEN, 0xFF);
3276 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
3277 wma->interfaces[vdev_id].addr,
3278 IEEE80211_ADDR_LEN, 0, mac_mask,
3279 IEEE80211_ADDR_LEN, false);
3280 if (ret != CDF_STATUS_SUCCESS) {
3281 WMA_LOGE("Failed to add WOW unicast pattern ret %d", ret);
3282 return ret;
3283 }
3284
3285 /*
3286 * Setup all ARP pkt pattern. This is dummy pattern hence the length
3287 * is zero
3288 */
3289 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
3290 arp_ptrn, 0, arp_offset, arp_mask, 0, false);
3291 if (ret != CDF_STATUS_SUCCESS) {
3292 WMA_LOGE("Failed to add WOW ARP pattern ret %d", ret);
3293 return ret;
3294 }
3295
3296 return ret;
3297}
3298
3299/**
3300 * wma_wow_sta() - set WOW patterns in sta mode
3301 * @wma: wma handle
3302 * @vdev_id: vdev id
3303 *
3304 * Configures default WOW pattern for the given vdev_id which is in sta mode.
3305 *
3306 * Return: CDF status
3307 */
3308static CDF_STATUS wma_wow_sta(tp_wma_handle wma, uint8_t vdev_id)
3309{
3310 uint8_t arp_offset = 12;
3311 uint8_t discvr_offset = 30;
3312 uint8_t mac_mask[IEEE80211_ADDR_LEN];
3313 CDF_STATUS ret = CDF_STATUS_SUCCESS;
3314
3315 /* Setup unicast pkt pattern */
3316 cdf_mem_set(&mac_mask, IEEE80211_ADDR_LEN, 0xFF);
3317 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
3318 wma->interfaces[vdev_id].addr,
3319 IEEE80211_ADDR_LEN, 0, mac_mask,
3320 IEEE80211_ADDR_LEN, false);
3321 if (ret != CDF_STATUS_SUCCESS) {
3322 WMA_LOGE("Failed to add WOW unicast pattern ret %d", ret);
3323 return ret;
3324 }
3325
3326 /*
3327 * Setup multicast pattern for mDNS 224.0.0.251,
3328 * SSDP 239.255.255.250 and LLMNR 224.0.0.252
3329 */
3330 if (wma->ssdp) {
3331 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
3332 discvr_ptrn, sizeof(discvr_ptrn), discvr_offset,
3333 discvr_mask, sizeof(discvr_ptrn), false);
3334 if (ret != CDF_STATUS_SUCCESS) {
3335 WMA_LOGE("Failed to add WOW mDNS/SSDP/LLMNR pattern");
3336 return ret;
3337 }
3338 } else
3339 WMA_LOGD("mDNS, SSDP, LLMNR patterns are disabled from ini");
3340
3341 /* when arp offload or ns offloaded is disabled
3342 * from ini file, configure broad cast arp pattern
3343 * to fw, so that host can wake up
3344 */
3345 if (!(wma->ol_ini_info & 0x1)) {
3346 /* Setup all ARP pkt pattern */
3347 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
3348 arp_ptrn, sizeof(arp_ptrn), arp_offset,
3349 arp_mask, sizeof(arp_mask), false);
3350 if (ret != CDF_STATUS_SUCCESS) {
3351 WMA_LOGE("Failed to add WOW ARP pattern");
3352 return ret;
3353 }
3354 }
3355
3356 /* for NS or NDP offload packets */
3357 if (!(wma->ol_ini_info & 0x2)) {
3358 /* Setup all NS pkt pattern */
3359 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
3360 ns_ptrn, sizeof(arp_ptrn), arp_offset,
3361 arp_mask, sizeof(arp_mask), false);
3362 if (ret != CDF_STATUS_SUCCESS) {
3363 WMA_LOGE("Failed to add WOW NS pattern");
3364 return ret;
3365 }
3366 }
3367
3368 return ret;
3369}
3370
3371/**
3372 * wma_register_wow_default_patterns() - register default wow patterns with fw
3373 * @handle: Pointer to wma handle
3374 * @vdev_id: vdev id
3375 *
3376 * WoW default wake up pattern rule is:
3377 * - For STA & P2P CLI mode register for same STA specific wow patterns
3378 * - For SAP/P2P GO & IBSS mode register for same SAP specific wow patterns
3379 *
3380 * Return: none
3381 */
3382void wma_register_wow_default_patterns(WMA_HANDLE handle, uint8_t vdev_id)
3383{
3384 tp_wma_handle wma = handle;
3385 struct wma_txrx_node *iface;
3386
3387 if (vdev_id > wma->max_bssid) {
3388 WMA_LOGE("Invalid vdev id %d", vdev_id);
3389 return;
3390 }
3391 iface = &wma->interfaces[vdev_id];
3392
3393 if (iface->ptrn_match_enable) {
3394 if (wma_is_vdev_in_ap_mode(wma, vdev_id)
3395#ifdef QCA_IBSS_SUPPORT
3396 ||
3397 wma_is_vdev_in_ibss_mode(wma, vdev_id)
3398#endif
3399 ) {
3400 /* Configure SAP/GO/IBSS mode default wow patterns */
3401 WMA_LOGI("Config SAP specific default wow patterns vdev_id %d",
3402 vdev_id);
3403 wma_wow_ap(wma, vdev_id);
3404 } else {
3405 /* Configure STA/P2P CLI mode default wow patterns */
3406 WMA_LOGI("Config STA specific default wow patterns vdev_id %d",
3407 vdev_id);
3408 wma_wow_sta(wma, vdev_id);
3409 if (wma->IsRArateLimitEnabled) {
3410 WMA_LOGI("Config STA RA limit wow patterns vdev_id %d",
3411 vdev_id);
3412 wma_wow_sta_ra_filter(wma, vdev_id);
3413 }
3414 }
3415 }
3416
3417 return;
3418}
3419
3420/**
3421 * wma_register_wow_wakeup_events() - register vdev specific wake events with fw
3422 * @handle: Pointer to wma handle
3423 * @vdev_id: vdev Id
3424 * @vdev_type: vdev type
3425 * @vdev_subtype: vdev sub type
3426 *
3427 * WoW wake up event rule is following:
3428 * 1) STA mode and P2P CLI mode wake up events are same
3429 * 2) SAP mode and P2P GO mode wake up events are same
3430 * 3) IBSS mode wake events are same as STA mode plus WOW_BEACON_EVENT
3431 *
3432 * Return: none
3433 */
3434void wma_register_wow_wakeup_events(WMA_HANDLE handle,
3435 uint8_t vdev_id,
3436 uint8_t vdev_type,
3437 uint8_t vdev_subtype)
3438{
3439 tp_wma_handle wma = handle;
3440 uint32_t event_bitmap;
3441
3442 WMA_LOGI("vdev_type %d vdev_subtype %d vdev_id %d", vdev_type,
3443 vdev_subtype, vdev_id);
3444
3445 if ((WMI_VDEV_TYPE_STA == vdev_type) ||
3446 ((WMI_VDEV_TYPE_AP == vdev_type) &&
3447 (WMI_UNIFIED_VDEV_SUBTYPE_P2P_DEVICE == vdev_subtype))) {
3448 /* Configure STA/P2P CLI mode specific default wake up events */
3449 event_bitmap = WMA_WOW_STA_WAKE_UP_EVENTS;
3450 WMA_LOGI("STA specific default wake up event 0x%x vdev id %d",
3451 event_bitmap, vdev_id);
3452 } else if (WMI_VDEV_TYPE_IBSS == vdev_type) {
3453 /* Configure IBSS mode specific default wake up events */
3454 event_bitmap = (WMA_WOW_STA_WAKE_UP_EVENTS |
3455 (1 << WOW_BEACON_EVENT));
3456 WMA_LOGI("IBSS specific default wake up event 0x%x vdev id %d",
3457 event_bitmap, vdev_id);
3458 } else if (WMI_VDEV_TYPE_AP == vdev_type) {
3459 /* Configure SAP/GO mode specific default wake up events */
3460 event_bitmap = WMA_WOW_SAP_WAKE_UP_EVENTS;
3461 WMA_LOGI("SAP specific default wake up event 0x%x vdev id %d",
3462 event_bitmap, vdev_id);
3463 } else {
3464 WMA_LOGE("unknown type %d subtype %d", vdev_type, vdev_subtype);
3465 return;
3466 }
3467
3468 wma_add_wow_wakeup_event(wma, vdev_id, event_bitmap, true);
3469
3470 return;
3471}
3472
3473/**
3474 * wma_enable_disable_wakeup_event() - Configures wow wakeup events
3475 * @wma: wma handle
3476 * @vdev_id: vdev id
3477 * @bitmap: Event bitmap
3478 * @enable: enable/disable
3479 *
3480 * Return: none
3481 */
3482void wma_enable_disable_wakeup_event(WMA_HANDLE handle,
3483 uint32_t vdev_id,
3484 uint32_t bitmap,
3485 bool enable)
3486{
3487 tp_wma_handle wma = handle;
3488
3489 WMA_LOGI("vdev_id %d wake up event 0x%x enable %d",
3490 vdev_id, bitmap, enable);
3491 wma_add_wow_wakeup_event(wma, vdev_id, bitmap, enable);
3492}
3493
3494/**
3495 * wma_enable_wow_in_fw() - wnable wow in fw
3496 * @wma: wma handle
3497 *
3498 * Return: CDF status
3499 */
3500CDF_STATUS wma_enable_wow_in_fw(WMA_HANDLE handle)
3501{
3502 tp_wma_handle wma = handle;
3503 wmi_wow_enable_cmd_fixed_param *cmd;
3504 wmi_buf_t buf;
3505 int32_t len;
3506 int ret;
3507 struct ol_softc *scn;
3508 int host_credits;
3509 int wmi_pending_cmds;
3510#ifdef CONFIG_CNSS
3511 tpAniSirGlobal pMac = cds_get_context(CDF_MODULE_ID_PE);
3512
3513 if (NULL == pMac) {
3514 WMA_LOGE("%s: Unable to get PE context", __func__);
3515 return CDF_STATUS_E_FAILURE;
3516 }
3517#endif /* CONFIG_CNSS */
3518
3519 len = sizeof(wmi_wow_enable_cmd_fixed_param);
3520
3521 buf = wmi_buf_alloc(wma->wmi_handle, len);
3522 if (!buf) {
3523 WMA_LOGE("%s: Failed allocate wmi buffer", __func__);
3524 return CDF_STATUS_E_NOMEM;
3525 }
3526
3527 cmd = (wmi_wow_enable_cmd_fixed_param *) wmi_buf_data(buf);
3528 WMITLV_SET_HDR(&cmd->tlv_header,
3529 WMITLV_TAG_STRUC_wmi_wow_enable_cmd_fixed_param,
3530 WMITLV_GET_STRUCT_TLVLEN
3531 (wmi_wow_enable_cmd_fixed_param));
3532 cmd->enable = true;
3533 if (hif_can_suspend_link())
3534 cmd->pause_iface_config = WOW_IFACE_PAUSE_ENABLED;
3535 else
3536 cmd->pause_iface_config = WOW_IFACE_PAUSE_DISABLED;
3537
3538 WMA_LOGI("suspend type: %s",
3539 cmd->pause_iface_config == WOW_IFACE_PAUSE_ENABLED ?
3540 "WOW_IFACE_PAUSE_ENABLED" : "WOW_IFACE_PAUSE_DISABLED");
3541
3542 cdf_event_reset(&wma->target_suspend);
3543 wma->wow_nack = 0;
3544
3545 host_credits = wmi_get_host_credits(wma->wmi_handle);
3546 wmi_pending_cmds = wmi_get_pending_cmds(wma->wmi_handle);
3547
3548 WMA_LOGD("Credits:%d; Pending_Cmds: %d",
3549 host_credits, wmi_pending_cmds);
3550
3551 if (host_credits < WMI_WOW_REQUIRED_CREDITS) {
3552 WMA_LOGE("%s: Host Doesn't have enough credits to Post WMI_WOW_ENABLE_CMDID! "
3553 "Credits:%d, pending_cmds:%d\n", __func__, host_credits,
3554 wmi_pending_cmds);
3555#ifndef QCA_WIFI_3_0_EMU
3556 goto error;
3557#endif
3558 }
3559
3560 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
3561 WMI_WOW_ENABLE_CMDID);
3562 if (ret) {
3563 WMA_LOGE("Failed to enable wow in fw");
3564 goto error;
3565 }
3566
3567 wmi_set_target_suspend(wma->wmi_handle, true);
3568
3569 if (cdf_wait_single_event(&wma->target_suspend,
3570 WMA_TGT_SUSPEND_COMPLETE_TIMEOUT)
3571 != CDF_STATUS_SUCCESS) {
3572 WMA_LOGE("Failed to receive WoW Enable Ack from FW");
3573 WMA_LOGE("Credits:%d; Pending_Cmds: %d",
3574 wmi_get_host_credits(wma->wmi_handle),
3575 wmi_get_pending_cmds(wma->wmi_handle));
Prashanth Bhatta9e143052015-12-04 11:56:47 -08003576 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003577#ifdef CONFIG_CNSS
Yue Ma455aff62015-10-20 18:29:16 -07003578 if (pMac->sme.enableSelfRecovery) {
3579 cds_trigger_recovery();
3580 } else {
3581 CDF_BUG(0);
3582 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003583#else
Yue Ma455aff62015-10-20 18:29:16 -07003584 CDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003585#endif /* CONFIG_CNSS */
Yue Ma455aff62015-10-20 18:29:16 -07003586 } else {
3587 WMA_LOGE("%s: LOGP is in progress, ignore!", __func__);
3588 }
3589
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003590 wmi_set_target_suspend(wma->wmi_handle, false);
3591 return CDF_STATUS_E_FAILURE;
3592 }
3593
3594 if (wma->wow_nack) {
3595 WMA_LOGE("FW not ready to WOW");
3596 wmi_set_target_suspend(wma->wmi_handle, false);
3597 return CDF_STATUS_E_AGAIN;
3598 }
3599
3600 host_credits = wmi_get_host_credits(wma->wmi_handle);
3601 wmi_pending_cmds = wmi_get_pending_cmds(wma->wmi_handle);
3602
3603 if (host_credits < WMI_WOW_REQUIRED_CREDITS) {
3604 WMA_LOGE("%s: No Credits after HTC ACK:%d, pending_cmds:%d, "
3605 "cannot resume back", __func__, host_credits,
3606 wmi_pending_cmds);
3607 htc_dump_counter_info(wma->htc_handle);
Prashanth Bhatta9e143052015-12-04 11:56:47 -08003608 if (!cds_is_driver_recovering())
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003609 CDF_BUG(0);
3610 else
3611 WMA_LOGE("%s: SSR in progress, ignore no credit issue",
3612 __func__);
3613 }
3614
3615 WMA_LOGD("WOW enabled successfully in fw: credits:%d"
3616 "pending_cmds: %d", host_credits, wmi_pending_cmds);
3617
3618 scn = cds_get_context(CDF_MODULE_ID_HIF);
3619
3620 if (scn == NULL) {
3621 WMA_LOGE("%s: Failed to get HIF context", __func__);
3622 CDF_ASSERT(0);
3623 return CDF_STATUS_E_FAULT;
3624 }
3625
3626 htc_cancel_deferred_target_sleep(scn);
3627
3628 wma->wow.wow_enable_cmd_sent = true;
3629
3630 return CDF_STATUS_SUCCESS;
3631
3632error:
3633 wmi_buf_free(buf);
3634 return CDF_STATUS_E_FAILURE;
3635}
3636
3637/**
3638 * wma_resume_req() - clear configured wow patterns in fw
3639 * @wma: wma handle
3640 *
3641 * Return: CDF status
3642 */
3643CDF_STATUS wma_resume_req(tp_wma_handle wma)
3644{
3645 wma->no_of_resume_ind++;
3646
3647 if (wma->no_of_resume_ind < wma_get_vdev_count(wma))
3648 return CDF_STATUS_SUCCESS;
3649
3650 wma->no_of_resume_ind = 0;
3651
3652 /* Reset the DTIM Parameters */
3653 wma_set_resume_dtim(wma);
3654 /* need to reset if hif_pci_suspend_fails */
3655 wma_set_wow_bus_suspend(wma, 0);
3656 /* unpause the vdev if left paused and hif_pci_suspend fails */
3657 wma_unpause_vdev(wma);
3658
3659 return CDF_STATUS_SUCCESS;
3660}
3661
3662/**
3663 * wma_wow_delete_pattern() - delete wow pattern in target
3664 * @wma: wma handle
3665 * @ptrn_id: pattern id
3666 * @vdev_id: vdev id
3667 * @user: true for user pattern and false for default pattern
3668 *
3669 * Return: CDF status
3670 */
3671static CDF_STATUS wma_wow_delete_pattern(tp_wma_handle wma, uint8_t ptrn_id,
3672 uint8_t vdev_id, bool user)
3673{
3674 WMI_WOW_DEL_PATTERN_CMD_fixed_param *cmd;
3675 struct wma_txrx_node *iface;
3676 wmi_buf_t buf;
3677 int32_t len;
3678 int ret;
3679
3680 len = sizeof(WMI_WOW_DEL_PATTERN_CMD_fixed_param);
3681
3682 iface = &wma->interfaces[vdev_id];
3683
3684 buf = wmi_buf_alloc(wma->wmi_handle, len);
3685 if (!buf) {
3686 WMA_LOGE("%s: Failed allocate wmi buffer", __func__);
3687 return CDF_STATUS_E_NOMEM;
3688 }
3689
3690 cmd = (WMI_WOW_DEL_PATTERN_CMD_fixed_param *) wmi_buf_data(buf);
3691
3692 WMITLV_SET_HDR(&cmd->tlv_header,
3693 WMITLV_TAG_STRUC_WMI_WOW_DEL_PATTERN_CMD_fixed_param,
3694 WMITLV_GET_STRUCT_TLVLEN(
3695 WMI_WOW_DEL_PATTERN_CMD_fixed_param));
3696 cmd->vdev_id = vdev_id;
3697 cmd->pattern_id = ptrn_id;
3698 cmd->pattern_type = WOW_BITMAP_PATTERN;
3699
3700 WMA_LOGI("Deleting pattern id: %d vdev id %d in fw",
3701 cmd->pattern_id, vdev_id);
3702
3703 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
3704 WMI_WOW_DEL_WAKE_PATTERN_CMDID);
3705 if (ret) {
3706 WMA_LOGE("%s: Failed to delete wow ptrn from fw", __func__);
3707 wmi_buf_free(buf);
3708 return CDF_STATUS_E_FAILURE;
3709 }
3710
3711 if (user)
3712 iface->num_wow_user_patterns--;
3713
3714 return CDF_STATUS_SUCCESS;
3715}
3716
3717/**
3718 * wma_wow_add_pattern() - add wow pattern in target
3719 * @wma: wma handle
3720 * @ptrn: wow pattern
3721 *
3722 * This function does following:
3723 * 1) Delete all default patterns of the vdev
3724 * 2) Add received wow patterns for given vdev in target.
3725 *
3726 * Target is responsible for caching wow patterns accross multiple
3727 * suspend/resumes until the pattern is deleted by user
3728 *
3729 * Return: CDF status
3730 */
3731CDF_STATUS wma_wow_add_pattern(tp_wma_handle wma, struct wow_add_pattern *ptrn)
3732{
3733 uint8_t id;
3734 uint8_t bit_to_check, pos;
3735 struct wma_txrx_node *iface;
3736 CDF_STATUS ret = CDF_STATUS_SUCCESS;
3737 uint8_t new_mask[SIR_WOWL_BCAST_PATTERN_MAX_SIZE];
3738
3739 if (ptrn->session_id > wma->max_bssid) {
3740 WMA_LOGE("Invalid vdev id (%d)", ptrn->session_id);
3741 return CDF_STATUS_E_INVAL;
3742 }
3743
3744 iface = &wma->interfaces[ptrn->session_id];
3745
3746 /* clear all default patterns cofigured by wma */
3747 for (id = 0; id < iface->num_wow_default_patterns; id++)
3748 wma_wow_delete_pattern(wma, id, ptrn->session_id, false);
3749
3750 iface->num_wow_default_patterns = 0;
3751
3752 WMA_LOGI("Add user passed wow pattern id %d vdev id %d",
3753 ptrn->pattern_id, ptrn->session_id);
3754 /*
3755 * Convert received pattern mask value from bit representation
3756 * to byte representation.
3757 *
3758 * For example, received value from umac,
3759 *
3760 * Mask value : A1 (equivalent binary is "1010 0001")
3761 * Pattern value : 12:00:13:00:00:00:00:44
3762 *
3763 * The value which goes to FW after the conversion from this
3764 * function (1 in mask value will become FF and 0 will
3765 * become 00),
3766 *
3767 * Mask value : FF:00:FF:00:0:00:00:FF
3768 * Pattern value : 12:00:13:00:00:00:00:44
3769 */
3770 cdf_mem_zero(new_mask, sizeof(new_mask));
3771 for (pos = 0; pos < ptrn->pattern_size; pos++) {
3772 bit_to_check = (WMA_NUM_BITS_IN_BYTE - 1) -
3773 (pos % WMA_NUM_BITS_IN_BYTE);
3774 bit_to_check = 0x1 << bit_to_check;
3775 if (ptrn->pattern_mask[pos / WMA_NUM_BITS_IN_BYTE] &
3776 bit_to_check)
3777 new_mask[pos] = WMA_WOW_PTRN_MASK_VALID;
3778 }
3779
3780 ret = wma_send_wow_patterns_to_fw(wma, ptrn->session_id,
3781 ptrn->pattern_id,
3782 ptrn->pattern, ptrn->pattern_size,
3783 ptrn->pattern_byte_offset, new_mask,
3784 ptrn->pattern_size, true);
3785 if (ret != CDF_STATUS_SUCCESS)
3786 WMA_LOGE("Failed to add wow pattern %d", ptrn->pattern_id);
3787
3788 return ret;
3789}
3790
3791/**
3792 * wma_wow_delete_user_pattern() - delete user configured wow pattern in target
3793 * @wma: wma handle
3794 * @ptrn: wow pattern
3795 *
3796 * This function does following:
3797 * 1) Deletes a particular user configured wow pattern in target
3798 * 2) After deleting all user wow patterns add default wow patterns
3799 * specific to that vdev.
3800 *
3801 * Return: CDF status
3802 */
3803CDF_STATUS wma_wow_delete_user_pattern(tp_wma_handle wma,
3804 struct wow_delete_pattern *pattern)
3805{
3806 struct wma_txrx_node *iface;
3807
3808 if (pattern->session_id > wma->max_bssid) {
3809 WMA_LOGE("Invalid vdev id %d", pattern->session_id);
3810 return CDF_STATUS_E_INVAL;
3811 }
3812
3813 iface = &wma->interfaces[pattern->session_id];
3814 if (iface->num_wow_user_patterns <= 0) {
3815 WMA_LOGE("No valid user pattern. Num user pattern %u vdev %d",
3816 iface->num_wow_user_patterns, pattern->session_id);
3817 return CDF_STATUS_E_INVAL;
3818 }
3819
3820 WMA_LOGI("Delete user passed wow pattern id %d total user pattern %d",
3821 pattern->pattern_id, iface->num_wow_user_patterns);
3822
3823 wma_wow_delete_pattern(wma, pattern->pattern_id,
3824 pattern->session_id, true);
3825
3826 /* configure default patterns once all user patterns are deleted */
3827 if (!iface->num_wow_user_patterns)
3828 wma_register_wow_default_patterns(wma, pattern->session_id);
3829
3830 return CDF_STATUS_SUCCESS;
3831}
3832
3833/**
3834 * wma_wow_enter() - store enable/disable status for pattern
3835 * @wma: wma handle
3836 * @info: wow parameters
3837 *
3838 * Records pattern enable/disable status locally. This choice will
3839 * take effect when the driver enter into suspend state.
3840 *
3841 * Return: CDF status
3842 */
3843CDF_STATUS wma_wow_enter(tp_wma_handle wma, tpSirHalWowlEnterParams info)
3844{
3845 struct wma_txrx_node *iface;
3846
3847 WMA_LOGD("wow enable req received for vdev id: %d", info->sessionId);
3848
3849 if (info->sessionId > wma->max_bssid) {
3850 WMA_LOGE("Invalid vdev id (%d)", info->sessionId);
3851 cdf_mem_free(info);
3852 return CDF_STATUS_E_INVAL;
3853 }
3854
3855 iface = &wma->interfaces[info->sessionId];
3856 iface->ptrn_match_enable = info->ucPatternFilteringEnable ?
3857 true : false;
3858 wma->wow.magic_ptrn_enable = info->ucMagicPktEnable ? true : false;
3859 wma->wow.deauth_enable = info->ucWowDeauthRcv ? true : false;
3860 wma->wow.disassoc_enable = info->ucWowDeauthRcv ? true : false;
3861 wma->wow.bmiss_enable = info->ucWowMaxMissedBeacons ? true : false;
3862
3863 cdf_mem_free(info);
3864
3865 return CDF_STATUS_SUCCESS;
3866}
3867
3868/**
3869 * wma_wow_exit() - clear all wma states
3870 * @wma: wma handle
3871 * @info: wow params
3872 *
3873 * Return: CDF status
3874 */
3875CDF_STATUS wma_wow_exit(tp_wma_handle wma, tpSirHalWowlExitParams info)
3876{
3877 struct wma_txrx_node *iface;
3878
3879 WMA_LOGD("wow disable req received for vdev id: %d", info->sessionId);
3880
3881 if (info->sessionId > wma->max_bssid) {
3882 WMA_LOGE("Invalid vdev id (%d)", info->sessionId);
3883 cdf_mem_free(info);
3884 return CDF_STATUS_E_INVAL;
3885 }
3886
3887 iface = &wma->interfaces[info->sessionId];
3888 iface->ptrn_match_enable = false;
3889 wma->wow.magic_ptrn_enable = false;
3890 cdf_mem_free(info);
3891
3892 return CDF_STATUS_SUCCESS;
3893}
3894
Srinivas Girigowda0f09f992015-11-23 11:43:10 -08003895#ifdef FEATURE_WLAN_EXTSCAN
3896/**
3897 * wma_is_extscan_in_progress(): check if extscan is in progress
3898 * @wma: wma handle
3899 *
3900 * Return: true is extscan in progress, false otherwise.
3901 */
3902static bool wma_is_extscan_in_progress(tp_wma_handle wma)
3903{
3904 int i;
3905
3906 for (i = 0; i < wma->max_bssid; i++) {
3907 if (wma->interfaces[i].extscan_in_progress) {
3908 WMA_LOGD("Extscan is in progress, enabling wow");
3909 return true;
3910 }
3911 }
3912
3913 return false;
3914}
3915#else
3916static bool wma_is_extscan_in_progress(tp_wma_handle wma)
3917{
3918 return false;
3919}
3920#endif
3921
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003922/**
3923 * wma_suspend_req() - Handles suspend indication request received from umac.
3924 * @wma: wma handle
3925 * @info: suspend params
3926 *
3927 * Return: CDF status
3928 */
3929CDF_STATUS wma_suspend_req(tp_wma_handle wma, tpSirWlanSuspendParam info)
3930{
3931 struct wma_txrx_node *iface;
Ryan Hsu04aec8e2015-10-09 10:15:46 -07003932 bool pno_in_progress = false;
Srinivas Girigowdaa4db76f2015-11-23 11:39:24 -08003933 uint8_t i, vdev_id = 0;
3934 bool extscan_in_progress = false, pno_matched = false;
Ryan Hsu04aec8e2015-10-09 10:15:46 -07003935 bool enable_wow = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003936
3937 wma->no_of_suspend_ind++;
3938
3939 if (info->sessionId > wma->max_bssid) {
3940 WMA_LOGE("Invalid vdev id (%d)", info->sessionId);
3941 cdf_mem_free(info);
3942 return CDF_STATUS_E_INVAL;
3943 }
3944
3945 iface = &wma->interfaces[info->sessionId];
3946 if (!iface) {
3947 WMA_LOGD("vdev %d node is not found", info->sessionId);
3948 cdf_mem_free(info);
3949 return CDF_STATUS_SUCCESS;
3950 }
3951
3952 if (!wma->wow.magic_ptrn_enable && !iface->ptrn_match_enable) {
3953 cdf_mem_free(info);
3954
3955 if (wma->no_of_suspend_ind == wma_get_vdev_count(wma)) {
3956 WMA_LOGD("Both magic and pattern byte match are disabled");
3957 wma->no_of_suspend_ind = 0;
3958 goto send_ready_to_suspend;
3959 }
3960
3961 return CDF_STATUS_SUCCESS;
3962 }
3963
3964 iface->conn_state = (info->connectedState) ? true : false;
3965
3966 /*
3967 * Once WOW is enabled in FW, host can't send anymore
3968 * data to fw. umac sends suspend indication on each
3969 * vdev during platform suspend. WMA has to wait until
3970 * suspend indication received on last vdev before
3971 * enabling wow in fw.
3972 */
3973 if (wma->no_of_suspend_ind < wma_get_vdev_count(wma)) {
3974 cdf_mem_free(info);
3975 return CDF_STATUS_SUCCESS;
3976 }
3977
3978 wma->no_of_suspend_ind = 0;
3979 wma->wow.gtk_pdev_enable = 0;
3980 /*
3981 * Enable WOW if any one of the condition meets,
3982 * 1) Is any one of vdev in beaconning mode (in AP mode) ?
3983 * 2) Is any one of vdev in connected state (in STA mode) ?
3984 * 3) Is PNO in progress in any one of vdev ?
3985 * 4) Is Extscan in progress in any one of vdev ?
3986 */
3987 for (i = 0; i < wma->max_bssid; i++) {
3988 if ((wma_is_vdev_in_ap_mode(wma, i)
3989#ifdef QCA_IBSS_SUPPORT
3990 || wma_is_vdev_in_ibss_mode(wma, i)
3991#endif /* QCA_IBSS_SUPPORT */
3992 ) && wma->interfaces[i].vdev_up &&
3993 WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
3994 WMI_SERVICE_BEACON_OFFLOAD)) {
3995 WMA_LOGD("vdev %d is in beaconning mode, enabling wow",
3996 i);
Ryan Hsu04aec8e2015-10-09 10:15:46 -07003997 enable_wow = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003998 }
3999 }
4000 for (i = 0; i < wma->max_bssid; i++) {
Ryan Hsu04aec8e2015-10-09 10:15:46 -07004001 if (wma->interfaces[i].conn_state)
4002 enable_wow = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004003#ifdef FEATURE_WLAN_SCAN_PNO
4004 if (wma->interfaces[i].pno_in_progress) {
4005 WMA_LOGD("PNO is in progress, enabling wow");
Ryan Hsu04aec8e2015-10-09 10:15:46 -07004006 enable_wow = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004007 pno_in_progress = true;
Srinivas Girigowdaa4db76f2015-11-23 11:39:24 -08004008 vdev_id = i;
4009 if (wma->interfaces[i].nlo_match_evt_received)
4010 pno_matched = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004011 break;
4012 }
4013#endif /* FEATURE_WLAN_SCAN_PNO */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004014 }
Srinivas Girigowda0f09f992015-11-23 11:43:10 -08004015 extscan_in_progress = wma_is_extscan_in_progress(wma);
Ryan Hsu04aec8e2015-10-09 10:15:46 -07004016 if (extscan_in_progress)
4017 enable_wow = true;
Srinivas Girigowda0f09f992015-11-23 11:43:10 -08004018
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004019 for (i = 0; i < wma->max_bssid; i++) {
4020 wma->wow.gtk_pdev_enable |= wma->wow.gtk_err_enable[i];
4021 WMA_LOGD("VDEV_ID:%d, gtk_err_enable[%d]:%d, gtk_pdev_enable:%d", i,
4022 i, wma->wow.gtk_err_enable[i], wma->wow.gtk_pdev_enable);
4023 }
4024
Ryan Hsuf75bd242015-12-17 12:22:02 -08004025 if (!enable_wow && !pno_in_progress && !extscan_in_progress) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004026 WMA_LOGD("All vdev are in disconnected state and pno/extscan is not in progress, skipping wow");
4027 cdf_mem_free(info);
4028 goto send_ready_to_suspend;
4029 }
4030
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004031 WMA_LOGE("WOW Suspend");
4032
4033 /*
4034 * At this point, suspend indication is received on
4035 * last vdev. It's the time to enable wow in fw.
4036 */
4037#ifdef FEATURE_WLAN_LPHB
4038 /* LPHB cache, if any item was enabled, should be
4039 * applied.
4040 */
4041 WMA_LOGD("%s: checking LPHB cache", __func__);
4042 for (i = 0; i < 2; i++) {
4043 if (wma->wow.lphb_cache[i].params.lphbEnableReq.enable) {
4044 WMA_LOGD("%s: LPHB cache for item %d is marked as enable",
4045 __func__, i + 1);
4046 wma_lphb_conf_hbenable(wma, &(wma->wow.lphb_cache[i]),
4047 false);
4048 }
4049 }
4050#endif /* FEATURE_WLAN_LPHB */
4051
Srinivas Girigowdaa4db76f2015-11-23 11:39:24 -08004052 if (pno_matched)
4053 wma_enable_disable_wakeup_event(wma, vdev_id,
4054 (1 << WOW_NLO_SCAN_COMPLETE_EVENT),
4055 pno_matched);
4056
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004057 wma->wow.wow_enable = true;
4058 wma->wow.wow_enable_cmd_sent = false;
4059
4060 cdf_mem_free(info);
4061
4062send_ready_to_suspend:
4063 /* Set the Suspend DTIM Parameters */
4064 wma_set_suspend_dtim(wma);
4065 wma_send_status_to_suspend_ind(wma, true);
4066
4067 /* to handle race between hif_pci_suspend and
4068 * unpause/pause tx handler
4069 */
4070 wma_set_wow_bus_suspend(wma, 1);
4071
4072 return CDF_STATUS_SUCCESS;
4073}
4074
4075/**
4076 * wma_send_host_wakeup_ind_to_fw() - send wakeup ind to fw
4077 * @wma: wma handle
4078 *
4079 * Sends host wakeup indication to FW. On receiving this indication,
4080 * FW will come out of WOW.
4081 *
4082 * Return: CDF status
4083 */
4084static CDF_STATUS wma_send_host_wakeup_ind_to_fw(tp_wma_handle wma)
4085{
4086 wmi_wow_hostwakeup_from_sleep_cmd_fixed_param *cmd;
4087 wmi_buf_t buf;
4088 CDF_STATUS cdf_status = CDF_STATUS_SUCCESS;
4089 int32_t len;
4090 int ret;
4091#ifdef CONFIG_CNSS
4092 tpAniSirGlobal pMac = cds_get_context(CDF_MODULE_ID_PE);
4093 if (NULL == pMac) {
4094 WMA_LOGE("%s: Unable to get PE context", __func__);
4095 return CDF_STATUS_E_FAILURE;
4096 }
4097#endif /* CONFIG_CNSS */
4098
4099 len = sizeof(wmi_wow_hostwakeup_from_sleep_cmd_fixed_param);
4100
4101 buf = wmi_buf_alloc(wma->wmi_handle, len);
4102 if (!buf) {
4103 WMA_LOGE("%s: Failed allocate wmi buffer", __func__);
4104 return CDF_STATUS_E_NOMEM;
4105 }
4106
4107 cmd = (wmi_wow_hostwakeup_from_sleep_cmd_fixed_param *)
4108 wmi_buf_data(buf);
4109 WMITLV_SET_HDR(&cmd->tlv_header,
4110 WMITLV_TAG_STRUC_wmi_wow_hostwakeup_from_sleep_cmd_fixed_param,
4111 WMITLV_GET_STRUCT_TLVLEN
4112 (wmi_wow_hostwakeup_from_sleep_cmd_fixed_param));
4113
4114 cdf_event_reset(&wma->wma_resume_event);
4115
4116 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
4117 WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID);
4118 if (ret) {
4119 WMA_LOGE("Failed to send host wakeup indication to fw");
4120 wmi_buf_free(buf);
4121 return CDF_STATUS_E_FAILURE;
4122 }
4123
4124 WMA_LOGD("Host wakeup indication sent to fw");
4125
4126 cdf_status = cdf_wait_single_event(&(wma->wma_resume_event),
4127 WMA_RESUME_TIMEOUT);
4128 if (CDF_STATUS_SUCCESS != cdf_status) {
4129 WMA_LOGP("%s: Timeout waiting for resume event from FW",
4130 __func__);
4131 WMA_LOGP("%s: Pending commands %d credits %d", __func__,
4132 wmi_get_pending_cmds(wma->wmi_handle),
4133 wmi_get_host_credits(wma->wmi_handle));
Prashanth Bhatta9e143052015-12-04 11:56:47 -08004134 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004135#ifdef CONFIG_CNSS
4136 if (pMac->sme.enableSelfRecovery) {
4137 cds_trigger_recovery();
4138 } else {
4139 CDF_BUG(0);
4140 }
4141#else
4142 CDF_BUG(0);
4143#endif /* CONFIG_CNSS */
4144 } else {
4145 WMA_LOGE("%s: SSR in progress, ignore resume timeout",
4146 __func__);
4147 }
4148 } else {
4149 WMA_LOGD("Host wakeup received");
4150 }
4151
4152 if (CDF_STATUS_SUCCESS == cdf_status)
4153 wmi_set_target_suspend(wma->wmi_handle, false);
4154
4155 return cdf_status;
4156}
4157
4158/**
4159 * wma_disable_wow_in_fw() - Disable wow in PCIe resume context.
4160 * @handle: wma handle
4161 *
4162 * Return: 0 for success or error code
4163 */
4164CDF_STATUS wma_disable_wow_in_fw(WMA_HANDLE handle)
4165{
4166 tp_wma_handle wma = handle;
4167 CDF_STATUS ret;
4168
4169 if (!wma->wow.wow_enable || !wma->wow.wow_enable_cmd_sent)
4170 return CDF_STATUS_SUCCESS;
4171
4172 ret = wma_send_host_wakeup_ind_to_fw(wma);
4173
4174 if (ret != CDF_STATUS_SUCCESS)
4175 return ret;
4176
4177 wma->wow.wow_enable = false;
4178 wma->wow.wow_enable_cmd_sent = false;
4179
4180 /* To allow the tx pause/unpause events */
4181 wma_set_wow_bus_suspend(wma, 0);
4182 /* Unpause the vdev as we are resuming */
4183 wma_unpause_vdev(wma);
4184
4185 return ret;
4186}
4187
4188#ifdef WLAN_FEATURE_LPSS
4189/**
4190 * wma_is_lpass_enabled() - check if lpass is enabled
4191 * @handle: Pointer to wma handle
4192 *
4193 * WoW is needed if LPASS or NaN feature is enabled in INI because
4194 * target can't wake up itself if its put in PDEV suspend when LPASS
4195 * or NaN features are supported
4196 *
4197 * Return: true if lpass is enabled else false
4198 */
4199bool static wma_is_lpass_enabled(tp_wma_handle wma)
4200{
4201 if (wma->is_lpass_enabled)
4202 return true;
4203 else
4204 return false;
4205}
4206#else
4207bool static wma_is_lpass_enabled(tp_wma_handle wma)
4208{
4209 return false;
4210}
4211#endif
4212
4213#ifdef WLAN_FEATURE_NAN
4214/**
4215 * wma_is_nan_enabled() - check if NaN is enabled
4216 * @handle: Pointer to wma handle
4217 *
4218 * WoW is needed if LPASS or NaN feature is enabled in INI because
4219 * target can't wake up itself if its put in PDEV suspend when LPASS
4220 * or NaN features are supported
4221 *
4222 * Return: true if NaN is enabled else false
4223 */
4224bool static wma_is_nan_enabled(tp_wma_handle wma)
4225{
4226 if (wma->is_nan_enabled)
4227 return true;
4228 else
4229 return false;
4230}
4231#else
4232bool static wma_is_nan_enabled(tp_wma_handle wma)
4233{
4234 return false;
4235}
4236#endif
4237
4238/**
4239 * wma_is_wow_mode_selected() - check if wow needs to be enabled in fw
4240 * @handle: Pointer to wma handle
4241 *
4242 * If lpass is enabled then always do wow else check wow_enable config
4243 *
4244 * Return: true is wow mode is needed else false
4245 */
4246int wma_is_wow_mode_selected(WMA_HANDLE handle)
4247{
4248 tp_wma_handle wma = (tp_wma_handle) handle;
4249
4250 if (wma_is_lpass_enabled(wma)) {
4251 WMA_LOGD("LPASS is enabled select WoW");
4252 return true;
4253 } else if (wma_is_nan_enabled(wma)) {
4254 WMA_LOGD("NAN is enabled select WoW");
4255 return true;
4256 } else {
4257 WMA_LOGD("WoW enable %d", wma->wow.wow_enable);
4258 return wma->wow.wow_enable;
4259 }
4260}
4261
4262/**
4263 * wma_del_ts_req() - send DELTS request to fw
4264 * @wma: wma handle
4265 * @msg: delts params
4266 *
4267 * Return: none
4268 */
4269void wma_del_ts_req(tp_wma_handle wma, tDelTsParams *msg)
4270{
4271 wmi_vdev_wmm_delts_cmd_fixed_param *cmd;
4272 wmi_buf_t buf;
4273 int32_t len = sizeof(*cmd);
4274
4275 buf = wmi_buf_alloc(wma->wmi_handle, len);
4276 if (!buf) {
4277 WMA_LOGP("%s: wmi_buf_alloc failed", __func__);
4278 goto err;
4279 }
4280 cmd = (wmi_vdev_wmm_delts_cmd_fixed_param *) wmi_buf_data(buf);
4281 WMITLV_SET_HDR(&cmd->tlv_header,
4282 WMITLV_TAG_STRUC_wmi_vdev_wmm_delts_cmd_fixed_param,
4283 WMITLV_GET_STRUCT_TLVLEN
4284 (wmi_vdev_wmm_delts_cmd_fixed_param));
4285 cmd->vdev_id = msg->sessionId;
4286 cmd->ac = TID_TO_WME_AC(msg->userPrio);
4287
4288 WMA_LOGD("Delts vdev:%d, ac:%d, %s:%d",
4289 cmd->vdev_id, cmd->ac, __FUNCTION__, __LINE__);
4290 if (wmi_unified_cmd_send(wma->wmi_handle, buf, len,
4291 WMI_VDEV_WMM_DELTS_CMDID)) {
4292 WMA_LOGP("%s: Failed to send vdev DELTS command", __func__);
4293 cdf_nbuf_free(buf);
4294 }
4295#ifdef WLAN_FEATURE_ROAM_OFFLOAD
4296 if (msg->setRICparams == true)
4297 wma_set_ric_req(wma, msg, false);
4298#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
4299
4300err:
4301 cdf_mem_free(msg);
4302}
4303
4304/**
4305 * wma_aggr_qos_req() - send aggr qos request to fw
4306 * @wma: handle to wma
4307 * @pAggrQosRspMsg - combined struct for all ADD_TS requests.
4308 *
4309 * A function to handle WMA_AGGR_QOS_REQ. This will send out
4310 * ADD_TS requestes to firmware in loop for all the ACs with
4311 * active flow.
4312 *
4313 * Return: none
4314 */
4315void wma_aggr_qos_req(tp_wma_handle wma,
4316 tAggrAddTsParams *pAggrQosRspMsg)
4317{
4318 int i = 0;
4319 wmi_vdev_wmm_addts_cmd_fixed_param *cmd;
4320 wmi_buf_t buf;
4321 int32_t len = sizeof(*cmd);
4322
4323 for (i = 0; i < HAL_QOS_NUM_AC_MAX; i++) {
4324 /* if flow in this AC is active */
4325 if (((1 << i) & pAggrQosRspMsg->tspecIdx)) {
4326 /*
4327 * as per implementation of wma_add_ts_req() we
4328 * are not waiting any response from firmware so
4329 * apart from sending ADDTS to firmware just send
4330 * success to upper layers
4331 */
4332 pAggrQosRspMsg->status[i] = CDF_STATUS_SUCCESS;
4333
4334 buf = wmi_buf_alloc(wma->wmi_handle, len);
4335 if (!buf) {
4336 WMA_LOGP("%s: wmi_buf_alloc failed", __func__);
4337 goto aggr_qos_exit;
4338 }
4339 cmd = (wmi_vdev_wmm_addts_cmd_fixed_param *)
4340 wmi_buf_data(buf);
4341 WMITLV_SET_HDR(&cmd->tlv_header,
4342 WMITLV_TAG_STRUC_wmi_vdev_wmm_addts_cmd_fixed_param,
4343 WMITLV_GET_STRUCT_TLVLEN
4344 (wmi_vdev_wmm_addts_cmd_fixed_param));
4345 cmd->vdev_id = pAggrQosRspMsg->sessionId;
4346 cmd->ac =
4347 TID_TO_WME_AC(pAggrQosRspMsg->tspec[i].tsinfo.
4348 traffic.userPrio);
4349 cmd->medium_time_us =
4350 pAggrQosRspMsg->tspec[i].mediumTime * 32;
4351 cmd->downgrade_type = WMM_AC_DOWNGRADE_DEPRIO;
4352 WMA_LOGD("%s:%d: Addts vdev:%d, ac:%d, mediumTime:%d downgrade_type:%d",
4353 __func__, __LINE__, cmd->vdev_id, cmd->ac,
4354 cmd->medium_time_us, cmd->downgrade_type);
4355 if (wmi_unified_cmd_send
4356 (wma->wmi_handle, buf, len,
4357 WMI_VDEV_WMM_ADDTS_CMDID)) {
4358 WMA_LOGP("%s: Failed to send vdev ADDTS command",
4359 __func__);
4360 pAggrQosRspMsg->status[i] =
4361 CDF_STATUS_E_FAILURE;
4362 cdf_nbuf_free(buf);
4363 }
4364 }
4365 }
4366
4367aggr_qos_exit:
4368 /* send reponse to upper layers from here only. */
4369 wma_send_msg(wma, WMA_AGGR_QOS_RSP, pAggrQosRspMsg, 0);
4370}
4371
4372/**
4373 * wma_add_ts_req() - send ADDTS request to fw
4374 * @wma: wma handle
4375 * @msg: ADDTS params
4376 *
4377 * Return: none
4378 */
4379void wma_add_ts_req(tp_wma_handle wma, tAddTsParams *msg)
4380{
4381 wmi_vdev_wmm_addts_cmd_fixed_param *cmd;
4382 wmi_buf_t buf;
4383 int32_t len = sizeof(*cmd);
4384
4385#ifdef FEATURE_WLAN_ESE
4386 /*
4387 * msmt_interval is in unit called TU (1 TU = 1024 us)
4388 * max value of msmt_interval cannot make resulting
4389 * interval_miliseconds overflow 32 bit
4390 */
4391 uint32_t intervalMiliseconds;
4392 ol_txrx_pdev_handle pdev = cds_get_context(CDF_MODULE_ID_TXRX);
4393 if (NULL == pdev) {
4394 WMA_LOGE("%s: Failed to get pdev", __func__);
4395 goto err;
4396 }
4397
4398 intervalMiliseconds = (msg->tsm_interval * 1024) / 1000;
4399
4400 ol_tx_set_compute_interval(pdev, intervalMiliseconds);
4401#endif /* FEATURE_WLAN_ESE */
4402 msg->status = CDF_STATUS_SUCCESS;
4403
4404 buf = wmi_buf_alloc(wma->wmi_handle, len);
4405 if (!buf) {
4406 WMA_LOGP("%s: wmi_buf_alloc failed", __func__);
4407 goto err;
4408 }
4409 cmd = (wmi_vdev_wmm_addts_cmd_fixed_param *) wmi_buf_data(buf);
4410 WMITLV_SET_HDR(&cmd->tlv_header,
4411 WMITLV_TAG_STRUC_wmi_vdev_wmm_addts_cmd_fixed_param,
4412 WMITLV_GET_STRUCT_TLVLEN
4413 (wmi_vdev_wmm_addts_cmd_fixed_param));
4414 cmd->vdev_id = msg->sme_session_id;
4415 cmd->ac = TID_TO_WME_AC(msg->tspec.tsinfo.traffic.userPrio);
4416 cmd->medium_time_us = msg->tspec.mediumTime * 32;
4417 cmd->downgrade_type = WMM_AC_DOWNGRADE_DROP;
4418 WMA_LOGD("Addts vdev:%d, ac:%d, mediumTime:%d, downgrade_type:%d %s:%d",
4419 cmd->vdev_id, cmd->ac, cmd->medium_time_us,
4420 cmd->downgrade_type, __func__, __LINE__);
4421 if (wmi_unified_cmd_send(wma->wmi_handle, buf, len,
4422 WMI_VDEV_WMM_ADDTS_CMDID)) {
4423 WMA_LOGP("%s: Failed to send vdev ADDTS command", __func__);
4424 msg->status = CDF_STATUS_E_FAILURE;
4425 cdf_nbuf_free(buf);
4426 }
4427#ifdef WLAN_FEATURE_ROAM_OFFLOAD
4428 if (msg->setRICparams == true)
4429 wma_set_ric_req(wma, msg, true);
4430#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
4431
4432err:
4433 wma_send_msg(wma, WMA_ADD_TS_RSP, msg, 0);
4434}
4435
4436/**
4437 * wma_enable_disable_packet_filter() - enable/disable packet filter in target
4438 * @wma: Pointer to wma handle
4439 * @vdev_id: vdev id
4440 * @enable: Flag to enable/disable packet filter
4441 *
4442 * Return: 0 for success or error code
4443 */
4444static int wma_enable_disable_packet_filter(tp_wma_handle wma,
4445 uint8_t vdev_id, bool enable)
4446{
4447 int32_t len;
4448 int ret = 0;
4449 wmi_buf_t buf;
4450 WMI_PACKET_FILTER_ENABLE_CMD_fixed_param *cmd;
4451
4452 len = sizeof(WMI_PACKET_FILTER_ENABLE_CMD_fixed_param);
4453
4454 buf = wmi_buf_alloc(wma->wmi_handle, len);
4455 if (!buf) {
4456 WMA_LOGE("%s: Failed allocate wmi buffer", __func__);
4457 return -ENOMEM;
4458 }
4459
4460 cmd = (WMI_PACKET_FILTER_ENABLE_CMD_fixed_param *) wmi_buf_data(buf);
4461 WMITLV_SET_HDR(&cmd->tlv_header,
4462 WMITLV_TAG_STRUC_wmi_packet_filter_enable_fixed_param,
4463 WMITLV_GET_STRUCT_TLVLEN(
4464 WMI_PACKET_FILTER_ENABLE_CMD_fixed_param));
4465
4466 cmd->vdev_id = vdev_id;
4467 if (enable)
4468 cmd->enable = PACKET_FILTER_SET_ENABLE;
4469 else
4470 cmd->enable = PACKET_FILTER_SET_DISABLE;
4471
4472 WMA_LOGE("%s: Packet filter enable %d for vdev_id %d",
4473 __func__, cmd->enable, vdev_id);
4474
4475 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
4476 WMI_PACKET_FILTER_ENABLE_CMDID);
4477 if (ret)
4478 WMA_LOGE("Failed to send packet filter wmi cmd to fw");
4479
4480 return ret;
4481}
4482
4483/**
4484 * wma_config_packet_filter() - configure packet filter in target
4485 * @wma: Pointer to wma handle
4486 * @vdev_id: vdev id
4487 * @rcv_filter_param: Packet filter parameters
4488 * @filter_id: Filter id
4489 * @enable: Flag to add/delete packet filter configuration
4490 *
4491 * Return: 0 for success or error code
4492 */
4493static int wma_config_packet_filter(tp_wma_handle wma,
4494 uint8_t vdev_id, tSirRcvPktFilterCfgType *rcv_filter_param,
4495 uint8_t filter_id, bool enable)
4496{
4497 int len, i;
4498 int err = 0;
4499 wmi_buf_t buf;
4500 WMI_PACKET_FILTER_CONFIG_CMD_fixed_param *cmd;
4501
4502
4503 /* allocate the memory */
4504 len = sizeof(*cmd);
4505 buf = wmi_buf_alloc(wma->wmi_handle, len);
4506 if (!buf) {
4507 WMA_LOGE("Failed to allocate buffer to send set_param cmd");
4508 return -ENOMEM;
4509 }
4510
4511 cmd = (WMI_PACKET_FILTER_CONFIG_CMD_fixed_param *)wmi_buf_data(buf);
4512 WMITLV_SET_HDR(&cmd->tlv_header,
4513 WMITLV_TAG_STRUC_wmi_packet_filter_config_fixed_param,
4514 WMITLV_GET_STRUCT_TLVLEN
4515 (WMI_PACKET_FILTER_CONFIG_CMD_fixed_param));
4516
4517 cmd->vdev_id = vdev_id;
4518 cmd->filter_id = filter_id;
4519 if (enable)
4520 cmd->filter_action = PACKET_FILTER_SET_ACTIVE;
4521 else
4522 cmd->filter_action = PACKET_FILTER_SET_INACTIVE;
4523
4524 if (enable) {
4525 cmd->num_params = CDF_MIN(
4526 WMI_PACKET_FILTER_MAX_CMP_PER_PACKET_FILTER,
4527 rcv_filter_param->numFieldParams);
4528 cmd->filter_type = rcv_filter_param->filterType;
4529 cmd->coalesce_time = rcv_filter_param->coalesceTime;
4530
4531 for (i = 0; i < cmd->num_params; i++) {
4532 cmd->paramsData[i].proto_type =
4533 rcv_filter_param->paramsData[i].protocolLayer;
4534 cmd->paramsData[i].cmp_type =
4535 rcv_filter_param->paramsData[i].cmpFlag;
4536 cmd->paramsData[i].data_length =
4537 rcv_filter_param->paramsData[i].dataLength;
4538 cmd->paramsData[i].data_offset =
4539 rcv_filter_param->paramsData[i].dataOffset;
4540 memcpy(&cmd->paramsData[i].compareData,
4541 rcv_filter_param->paramsData[i].compareData,
4542 sizeof(cmd->paramsData[i].compareData));
4543 memcpy(&cmd->paramsData[i].dataMask,
4544 rcv_filter_param->paramsData[i].dataMask,
4545 sizeof(cmd->paramsData[i].dataMask));
4546 }
4547 }
4548
4549 WMA_LOGE("Packet filter action %d filter with id: %d, num_params=%d",
4550 cmd->filter_action, cmd->filter_id, cmd->num_params);
4551 /* send the command along with data */
4552 err = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
4553 WMI_PACKET_FILTER_CONFIG_CMDID);
4554 if (err) {
4555 WMA_LOGE("Failed to send pkt_filter cmd");
4556 wmi_buf_free(buf);
4557 return -EIO;
4558 }
4559
4560 /* Enable packet filter */
4561 if (enable)
4562 wma_enable_disable_packet_filter(wma, vdev_id, true);
4563
4564 return 0;
4565}
4566
4567/**
4568 * wma_process_receive_filter_set_filter_req() - enable packet filter
4569 * @wma_handle: wma handle
4570 * @rcv_filter_param: filter params
4571 *
4572 * Return: 0 for success or error code
4573 */
4574int wma_process_receive_filter_set_filter_req(tp_wma_handle wma,
4575 tSirRcvPktFilterCfgType *rcv_filter_param)
4576{
4577 int ret = 0;
4578 uint8_t vdev_id;
4579
4580 /* Get the vdev id */
Srinivas Girigowda98530492015-11-20 17:39:24 -08004581 if (!wma_find_vdev_by_bssid(wma,
4582 rcv_filter_param->bssid.bytes, &vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004583 WMA_LOGE("vdev handle is invalid for %pM",
Srinivas Girigowda98530492015-11-20 17:39:24 -08004584 rcv_filter_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004585 return -EINVAL;
4586 }
4587
4588 ret = wma_config_packet_filter(wma, vdev_id, rcv_filter_param,
4589 rcv_filter_param->filterId, true);
4590
4591 return ret;
4592}
4593
4594/**
4595 * wma_process_receive_filter_clear_filter_req() - disable packet filter
4596 * @wma_handle: wma handle
4597 * @rcv_clear_param: filter params
4598 *
4599 * Return: 0 for success or error code
4600 */
4601int wma_process_receive_filter_clear_filter_req(tp_wma_handle wma,
4602 tSirRcvFltPktClearParam *rcv_clear_param)
4603{
4604 int ret = 0;
4605 uint8_t vdev_id;
4606
4607 /* Get the vdev id */
Srinivas Girigowda98530492015-11-20 17:39:24 -08004608 if (!wma_find_vdev_by_bssid(wma,
4609 rcv_clear_param->bssid.bytes, &vdev_id)) {
4610 WMA_LOGE("vdev handle is invalid for %pM",
4611 rcv_clear_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004612 return -EINVAL;
4613 }
4614
4615 ret = wma_config_packet_filter(wma, vdev_id, NULL,
4616 rcv_clear_param->filterId, false);
4617
4618 return ret;
4619}
4620
4621#ifdef FEATURE_WLAN_ESE
4622
4623#define TSM_DELAY_HISTROGRAM_BINS 4
4624/**
4625 * wma_process_tsm_stats_req() - process tsm stats request
4626 * @wma_handler - handle to wma
4627 * @pTsmStatsMsg - TSM stats struct that needs to be populated and
4628 * passed in message.
4629 *
4630 * A parallel function to WMA_ProcessTsmStatsReq for pronto. This
4631 * function fetches stats from data path APIs and post
4632 * WMA_TSM_STATS_RSP msg back to LIM.
4633 *
4634 * Return: CDF status
4635 */
4636CDF_STATUS wma_process_tsm_stats_req(tp_wma_handle wma_handler,
4637 void *pTsmStatsMsg)
4638{
4639 uint8_t counter;
4640 uint32_t queue_delay_microsec = 0;
4641 uint32_t tx_delay_microsec = 0;
4642 uint16_t packet_count = 0;
4643 uint16_t packet_loss_count = 0;
4644 tpAniTrafStrmMetrics pTsmMetric = NULL;
4645#ifdef FEATURE_WLAN_ESE_UPLOAD
4646 tpAniGetTsmStatsReq pStats = (tpAniGetTsmStatsReq) pTsmStatsMsg;
4647 tpAniGetTsmStatsRsp pTsmRspParams = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004648#endif /* FEATURE_WLAN_ESE_UPLOAD */
4649 int tid = pStats->tid;
4650 /*
4651 * The number of histrogram bin report by data path api are different
4652 * than required by TSM, hence different (6) size array used
4653 */
4654 uint16_t bin_values[QCA_TX_DELAY_HIST_REPORT_BINS] = { 0, };
4655
4656 ol_txrx_pdev_handle pdev = cds_get_context(CDF_MODULE_ID_TXRX);
4657
4658 if (NULL == pdev) {
4659 WMA_LOGE("%s: Failed to get pdev", __func__);
4660 cdf_mem_free(pTsmStatsMsg);
4661 return CDF_STATUS_E_INVAL;
4662 }
4663
4664 /* get required values from data path APIs */
4665 ol_tx_delay(pdev, &queue_delay_microsec, &tx_delay_microsec, tid);
4666 ol_tx_delay_hist(pdev, bin_values, tid);
4667 ol_tx_packet_count(pdev, &packet_count, &packet_loss_count, tid);
4668
4669#ifdef FEATURE_WLAN_ESE_UPLOAD
4670 pTsmRspParams =
4671 (tpAniGetTsmStatsRsp) cdf_mem_malloc(sizeof(tAniGetTsmStatsRsp));
4672 if (NULL == pTsmRspParams) {
4673 CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_ERROR,
4674 "%s: CDF MEM Alloc Failure", __func__);
4675 CDF_ASSERT(0);
4676 cdf_mem_free(pTsmStatsMsg);
4677 return CDF_STATUS_E_NOMEM;
4678 }
4679 pTsmRspParams->staId = pStats->staId;
4680 pTsmRspParams->rc = eSIR_FAILURE;
4681 pTsmRspParams->tsmStatsReq = pStats;
4682 pTsmMetric = &pTsmRspParams->tsmMetrics;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004683#endif /* FEATURE_WLAN_ESE_UPLOAD */
4684 /* populate pTsmMetric */
4685 pTsmMetric->UplinkPktQueueDly = queue_delay_microsec;
4686 /* store only required number of bin values */
4687 for (counter = 0; counter < TSM_DELAY_HISTROGRAM_BINS; counter++) {
4688 pTsmMetric->UplinkPktQueueDlyHist[counter] =
4689 bin_values[counter];
4690 }
4691 pTsmMetric->UplinkPktTxDly = tx_delay_microsec;
4692 pTsmMetric->UplinkPktLoss = packet_loss_count;
4693 pTsmMetric->UplinkPktCount = packet_count;
4694
4695 /*
4696 * No need to populate roaming delay and roaming count as they are
4697 * being populated just before sending IAPP frame out
4698 */
4699 /* post this message to LIM/PE */
4700#ifdef FEATURE_WLAN_ESE_UPLOAD
4701 wma_send_msg(wma_handler, WMA_TSM_STATS_RSP, (void *)pTsmRspParams, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004702#endif /* FEATURE_WLAN_ESE_UPLOAD */
4703 return CDF_STATUS_SUCCESS;
4704}
4705
4706#endif /* FEATURE_WLAN_ESE */
4707
4708/**
4709 * wma_add_clear_mcbc_filter() - set mcast filter command to fw
4710 * @wma_handle: wma handle
4711 * @vdev_id: vdev id
4712 * @multicastAddr: mcast address
4713 * @clearList: clear list flag
4714 *
4715 * Return: 0 for success or error code
4716 */
4717static int wma_add_clear_mcbc_filter(tp_wma_handle wma_handle, uint8_t vdev_id,
Srinivas Girigowda98530492015-11-20 17:39:24 -08004718 struct cdf_mac_addr multicast_addr,
4719 bool clearList)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004720{
4721 WMI_SET_MCASTBCAST_FILTER_CMD_fixed_param *cmd;
4722 wmi_buf_t buf;
4723 int err;
4724
4725 buf = wmi_buf_alloc(wma_handle->wmi_handle, sizeof(*cmd));
4726 if (!buf) {
4727 WMA_LOGE("Failed to allocate buffer to send set_param cmd");
4728 return -ENOMEM;
4729 }
4730
4731 cmd = (WMI_SET_MCASTBCAST_FILTER_CMD_fixed_param *) wmi_buf_data(buf);
4732 cdf_mem_zero(cmd, sizeof(*cmd));
4733
4734 WMITLV_SET_HDR(&cmd->tlv_header,
4735 WMITLV_TAG_STRUC_WMI_SET_MCASTBCAST_FILTER_CMD_fixed_param,
4736 WMITLV_GET_STRUCT_TLVLEN
4737 (WMI_SET_MCASTBCAST_FILTER_CMD_fixed_param));
4738 cmd->action =
4739 (clearList ? WMI_MCAST_FILTER_DELETE : WMI_MCAST_FILTER_SET);
4740 cmd->vdev_id = vdev_id;
Srinivas Girigowda98530492015-11-20 17:39:24 -08004741 WMI_CHAR_ARRAY_TO_MAC_ADDR(multicast_addr.bytes, &cmd->mcastbdcastaddr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004742 err = wmi_unified_cmd_send(wma_handle->wmi_handle, buf,
4743 sizeof(*cmd),
4744 WMI_SET_MCASTBCAST_FILTER_CMDID);
4745 if (err) {
4746 WMA_LOGE("Failed to send set_param cmd");
4747 cdf_mem_free(buf);
4748 return -EIO;
4749 }
Srinivas Girigowda98530492015-11-20 17:39:24 -08004750 WMA_LOGD("Action:%d; vdev_id:%d; clearList:%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004751 cmd->action, vdev_id, clearList);
Srinivas Girigowda98530492015-11-20 17:39:24 -08004752 WMA_LOGD("MCBC MAC Addr: "MAC_ADDRESS_STR,
4753 MAC_ADDR_ARRAY(multicast_addr.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004754 return 0;
4755}
4756
4757/**
4758 * wma_process_mcbc_set_filter_req() - process mcbc set filter request
4759 * @wma_handle: wma handle
4760 * @mcbc_param: mcbc params
4761 *
4762 * Return: CDF status
4763 */
4764CDF_STATUS wma_process_mcbc_set_filter_req(tp_wma_handle wma_handle,
4765 tSirRcvFltMcAddrList * mcbc_param)
4766{
4767 uint8_t vdev_id = 0;
4768 int i;
4769
4770 if (mcbc_param->ulMulticastAddrCnt <= 0) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004771 WMA_LOGW("Number of multicast addresses is 0");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004772 return CDF_STATUS_E_FAILURE;
4773 }
4774
Srinivas Girigowda98530492015-11-20 17:39:24 -08004775 if (!wma_find_vdev_by_addr(wma_handle,
4776 mcbc_param->self_macaddr.bytes, &vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004777 WMA_LOGE("%s: Failed to find vdev id for %pM", __func__,
Srinivas Girigowda98530492015-11-20 17:39:24 -08004778 mcbc_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004779 return CDF_STATUS_E_FAILURE;
4780 }
4781 /* set mcbc_param->action to clear MCList and reset
4782 * to configure the MCList in FW
4783 */
4784
4785 for (i = 0; i < mcbc_param->ulMulticastAddrCnt; i++) {
4786 wma_add_clear_mcbc_filter(wma_handle, vdev_id,
4787 mcbc_param->multicastAddr[i],
4788 (mcbc_param->action == 0));
4789 }
4790 return CDF_STATUS_SUCCESS;
4791}
4792
4793#ifdef WLAN_FEATURE_GTK_OFFLOAD
4794#define GTK_OFFLOAD_ENABLE 0
4795#define GTK_OFFLOAD_DISABLE 1
4796
4797/**
4798 * wma_gtk_offload_status_event() - GTK offload status event handler
4799 * @handle: wma handle
4800 * @event: event buffer
4801 * @len: buffer length
4802 *
4803 * Return: 0 for success or error code
4804 */
4805int wma_gtk_offload_status_event(void *handle, uint8_t *event,
4806 uint32_t len)
4807{
4808 tp_wma_handle wma = (tp_wma_handle) handle;
4809 WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param *status;
4810 WMI_GTK_OFFLOAD_STATUS_EVENTID_param_tlvs *param_buf;
4811 tpSirGtkOffloadGetInfoRspParams resp;
4812 cds_msg_t cds_msg;
4813 uint8_t *bssid;
4814
4815 WMA_LOGD("%s Enter", __func__);
4816
4817 param_buf = (WMI_GTK_OFFLOAD_STATUS_EVENTID_param_tlvs *) event;
4818 if (!param_buf) {
4819 WMA_LOGE("param_buf is NULL");
4820 return -EINVAL;
4821 }
4822
4823 status = (WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param *) param_buf->fixed_param;
4824
4825 if (len < sizeof(WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param)) {
4826 WMA_LOGE("Invalid length for GTK status");
4827 return -EINVAL;
4828 }
4829 bssid = wma_find_bssid_by_vdev_id(wma, status->vdev_id);
4830 if (!bssid) {
4831 WMA_LOGE("invalid bssid for vdev id %d", status->vdev_id);
4832 return -ENOENT;
4833 }
4834
4835 resp = cdf_mem_malloc(sizeof(*resp));
4836 if (!resp) {
4837 WMA_LOGE("%s: Failed to alloc response", __func__);
4838 return -ENOMEM;
4839 }
4840 cdf_mem_zero(resp, sizeof(*resp));
4841 resp->mesgType = eWNI_PMC_GTK_OFFLOAD_GETINFO_RSP;
4842 resp->mesgLen = sizeof(*resp);
4843 resp->ulStatus = CDF_STATUS_SUCCESS;
4844 resp->ulTotalRekeyCount = status->refresh_cnt;
4845 /* TODO: Is the total rekey count and GTK rekey count same? */
4846 resp->ulGTKRekeyCount = status->refresh_cnt;
4847
4848 cdf_mem_copy(&resp->ullKeyReplayCounter, &status->replay_counter,
4849 GTK_REPLAY_COUNTER_BYTES);
4850
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -08004851 cdf_mem_copy(resp->bssid.bytes, bssid, IEEE80211_ADDR_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004852
4853#ifdef IGTK_OFFLOAD
4854 /* TODO: Is the refresh count same for GTK and IGTK? */
4855 resp->ulIGTKRekeyCount = status->refresh_cnt;
4856#endif /* IGTK_OFFLOAD */
4857
4858 cds_msg.type = eWNI_PMC_GTK_OFFLOAD_GETINFO_RSP;
4859 cds_msg.bodyptr = (void *)resp;
4860 cds_msg.bodyval = 0;
4861
4862 if (cds_mq_post_message(CDS_MQ_ID_SME, (cds_msg_t *) &cds_msg)
4863 != CDF_STATUS_SUCCESS) {
4864 WMA_LOGE("Failed to post GTK response to SME");
4865 cdf_mem_free(resp);
4866 return -EINVAL;
4867 }
4868
4869 WMA_LOGD("GTK: got target status with replay counter "
4870 "%02x%02x%02x%02x%02x%02x%02x%02x. vdev %d "
4871 "Refresh GTK %d times exchanges since last set operation",
4872 status->replay_counter[0],
4873 status->replay_counter[1],
4874 status->replay_counter[2],
4875 status->replay_counter[3],
4876 status->replay_counter[4],
4877 status->replay_counter[5],
4878 status->replay_counter[6],
4879 status->replay_counter[7],
4880 status->vdev_id, status->refresh_cnt);
4881
4882 WMA_LOGD("%s Exit", __func__);
4883
4884 return 0;
4885}
4886
4887/**
4888 * wma_send_gtk_offload_req() - send GTK offload command to fw
4889 * @wma: wma handle
4890 * @vdev_id: vdev id
4891 * @params: GTK offload parameters
4892 *
4893 * Return: CDF status
4894 */
4895static CDF_STATUS wma_send_gtk_offload_req(tp_wma_handle wma, uint8_t vdev_id,
4896 tpSirGtkOffloadParams params)
4897{
4898 int len;
4899 wmi_buf_t buf;
4900 WMI_GTK_OFFLOAD_CMD_fixed_param *cmd;
4901 CDF_STATUS status = CDF_STATUS_SUCCESS;
4902
4903 WMA_LOGD("%s Enter", __func__);
4904
4905 len = sizeof(*cmd);
4906
4907 /* alloc wmi buffer */
4908 buf = wmi_buf_alloc(wma->wmi_handle, len);
4909 if (!buf) {
4910 WMA_LOGE("wmi_buf_alloc failed for WMI_GTK_OFFLOAD_CMD");
4911 status = CDF_STATUS_E_NOMEM;
4912 goto out;
4913 }
4914
4915 cmd = (WMI_GTK_OFFLOAD_CMD_fixed_param *) wmi_buf_data(buf);
4916 WMITLV_SET_HDR(&cmd->tlv_header,
4917 WMITLV_TAG_STRUC_WMI_GTK_OFFLOAD_CMD_fixed_param,
4918 WMITLV_GET_STRUCT_TLVLEN
4919 (WMI_GTK_OFFLOAD_CMD_fixed_param));
4920
4921 cmd->vdev_id = vdev_id;
4922
4923 /* Request target to enable GTK offload */
4924 if (params->ulFlags == GTK_OFFLOAD_ENABLE) {
4925 cmd->flags = GTK_OFFLOAD_ENABLE_OPCODE;
4926 wma->wow.gtk_err_enable[vdev_id] = true;
4927
4928 /* Copy the keys and replay counter */
4929 cdf_mem_copy(cmd->KCK, params->aKCK, GTK_OFFLOAD_KCK_BYTES);
4930 cdf_mem_copy(cmd->KEK, params->aKEK, GTK_OFFLOAD_KEK_BYTES);
4931 cdf_mem_copy(cmd->replay_counter, &params->ullKeyReplayCounter,
4932 GTK_REPLAY_COUNTER_BYTES);
4933 } else {
4934 wma->wow.gtk_err_enable[vdev_id] = false;
4935 cmd->flags = GTK_OFFLOAD_DISABLE_OPCODE;
4936 }
4937
4938 /* send the wmi command */
4939 if (wmi_unified_cmd_send(wma->wmi_handle, buf, len,
4940 WMI_GTK_OFFLOAD_CMDID)) {
4941 WMA_LOGE("Failed to send WMI_GTK_OFFLOAD_CMDID");
4942 wmi_buf_free(buf);
4943 status = CDF_STATUS_E_FAILURE;
4944 }
4945
4946 WMA_LOGD("VDEVID: %d, GTK_FLAGS: x%x", vdev_id, cmd->flags);
4947out:
4948 WMA_LOGD("%s Exit", __func__);
4949 return status;
4950}
4951
4952/**
4953 * wma_process_gtk_offload_req() - process GTK offload req from umac
4954 * @handle: wma handle
4955 * @params: GTK offload params
4956 *
4957 * Return: CDF status
4958 */
4959CDF_STATUS wma_process_gtk_offload_req(tp_wma_handle wma,
4960 tpSirGtkOffloadParams params)
4961{
4962 uint8_t vdev_id;
4963 CDF_STATUS status = CDF_STATUS_SUCCESS;
4964
4965 WMA_LOGD("%s Enter", __func__);
4966
4967 /* Get the vdev id */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -08004968 if (!wma_find_vdev_by_bssid(wma, params->bssid.bytes, &vdev_id)) {
4969 WMA_LOGE("vdev handle is invalid for %pM", params->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004970 status = CDF_STATUS_E_INVAL;
4971 goto out;
4972 }
4973
4974 /* Validate vdev id */
4975 if (vdev_id >= wma->max_bssid) {
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -08004976 WMA_LOGE("invalid vdev_id %d for %pM", vdev_id,
4977 params->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004978 status = CDF_STATUS_E_INVAL;
4979 goto out;
4980 }
4981
4982 if ((params->ulFlags == GTK_OFFLOAD_ENABLE) &&
4983 (wma->wow.gtk_err_enable[vdev_id] == true)) {
4984 WMA_LOGE("%s GTK Offload already enabled. Disable it first "
4985 "vdev_id %d", __func__, vdev_id);
4986 params->ulFlags = GTK_OFFLOAD_DISABLE;
4987 status = wma_send_gtk_offload_req(wma, vdev_id, params);
4988 if (status != CDF_STATUS_SUCCESS) {
4989 WMA_LOGE("%s Failed to disable GTK Offload", __func__);
4990 goto out;
4991 }
4992 WMA_LOGD("%s Enable GTK Offload again with updated inputs",
4993 __func__);
4994 params->ulFlags = GTK_OFFLOAD_ENABLE;
4995 }
4996 status = wma_send_gtk_offload_req(wma, vdev_id, params);
4997out:
4998 cdf_mem_free(params);
4999 WMA_LOGD("%s Exit", __func__);
5000 return status;
5001}
5002
5003/**
5004 * wma_process_gtk_offload_getinfo_req() - send GTK offload cmd to fw
5005 * @wma: wma handle
5006 * @params: GTK offload params
5007 *
5008 * Return: CDF status
5009 */
5010CDF_STATUS wma_process_gtk_offload_getinfo_req(tp_wma_handle wma,
5011 tpSirGtkOffloadGetInfoRspParams params)
5012{
5013 uint8_t vdev_id;
5014 int len;
5015 wmi_buf_t buf;
5016 WMI_GTK_OFFLOAD_CMD_fixed_param *cmd;
5017 CDF_STATUS status = CDF_STATUS_SUCCESS;
5018
5019 WMA_LOGD("%s Enter", __func__);
5020
5021 /* Get the vdev id */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -08005022 if (!wma_find_vdev_by_bssid(wma, params->bssid.bytes, &vdev_id)) {
5023 WMA_LOGE("vdev handle is invalid for %pM", params->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005024 status = CDF_STATUS_E_INVAL;
5025 goto out;
5026 }
5027
5028 len = sizeof(*cmd);
5029
5030 /* alloc wmi buffer */
5031 buf = wmi_buf_alloc(wma->wmi_handle, len);
5032 if (!buf) {
5033 WMA_LOGE("wmi_buf_alloc failed for WMI_GTK_OFFLOAD_CMD");
5034 status = CDF_STATUS_E_NOMEM;
5035 goto out;
5036 }
5037
5038 cmd = (WMI_GTK_OFFLOAD_CMD_fixed_param *) wmi_buf_data(buf);
5039 WMITLV_SET_HDR(&cmd->tlv_header,
5040 WMITLV_TAG_STRUC_WMI_GTK_OFFLOAD_CMD_fixed_param,
5041 WMITLV_GET_STRUCT_TLVLEN
5042 (WMI_GTK_OFFLOAD_CMD_fixed_param));
5043
5044 /* Request for GTK offload status */
5045 cmd->flags = GTK_OFFLOAD_REQUEST_STATUS_OPCODE;
5046 cmd->vdev_id = vdev_id;
5047
5048 /* send the wmi command */
5049 if (wmi_unified_cmd_send(wma->wmi_handle, buf, len,
5050 WMI_GTK_OFFLOAD_CMDID)) {
5051 WMA_LOGE("Failed to send WMI_GTK_OFFLOAD_CMDID for req info");
5052 wmi_buf_free(buf);
5053 status = CDF_STATUS_E_FAILURE;
5054 }
5055out:
5056 cdf_mem_free(params);
5057 WMA_LOGD("%s Exit", __func__);
5058 return status;
5059}
5060#endif /* WLAN_FEATURE_GTK_OFFLOAD */
5061
5062/**
5063 * wma_enable_arp_ns_offload() - enable ARP NS offload
5064 * @wma: wma handle
5065 * @tpSirHostOffloadReq: offload request
5066 * @bArpOnly: flag
5067 *
5068 * To configure ARP NS off load data to firmware
5069 * when target goes to wow mode.
5070 *
5071 * Return: CDF Status
5072 */
5073CDF_STATUS wma_enable_arp_ns_offload(tp_wma_handle wma,
5074 tpSirHostOffloadReq
5075 pHostOffloadParams, bool bArpOnly)
5076{
5077 int32_t i;
5078 int32_t res;
5079 WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param *cmd;
5080 WMI_NS_OFFLOAD_TUPLE *ns_tuple;
5081 WMI_ARP_OFFLOAD_TUPLE *arp_tuple;
5082 A_UINT8 *buf_ptr;
5083 wmi_buf_t buf;
5084 int32_t len;
5085 uint8_t vdev_id;
5086 uint32_t count = 0, num_ns_ext_tuples = 0;
5087
5088 /* Get the vdev id */
Srinivas Girigowdab084b552015-11-24 12:39:12 -08005089 if (!wma_find_vdev_by_bssid(wma, pHostOffloadParams->bssid.bytes,
5090 &vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005091 WMA_LOGE("vdev handle is invalid for %pM",
Srinivas Girigowdab084b552015-11-24 12:39:12 -08005092 pHostOffloadParams->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005093 cdf_mem_free(pHostOffloadParams);
5094 return CDF_STATUS_E_INVAL;
5095 }
5096
5097 if (!wma->interfaces[vdev_id].vdev_up) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005098 WMA_LOGE("vdev %d is not up skipping arp/ns offload", vdev_id);
5099 cdf_mem_free(pHostOffloadParams);
5100 return CDF_STATUS_E_FAILURE;
5101 }
5102
5103 if (!bArpOnly)
5104 count = pHostOffloadParams->num_ns_offload_count;
5105
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005106 len = sizeof(WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param) + WMI_TLV_HDR_SIZE + /* TLV place holder size for array of NS tuples */
5107 WMI_MAX_NS_OFFLOADS * sizeof(WMI_NS_OFFLOAD_TUPLE) + WMI_TLV_HDR_SIZE + /* TLV place holder size for array of ARP tuples */
5108 WMI_MAX_ARP_OFFLOADS * sizeof(WMI_ARP_OFFLOAD_TUPLE);
5109
5110 /*
5111 * If there are more than WMI_MAX_NS_OFFLOADS addresses then allocate
5112 * extra length for extended NS offload tuples which follows ARP offload
5113 * tuples. Host needs to fill this structure in following format:
5114 * 2 NS ofload tuples
5115 * 2 ARP offload tuples
5116 * N numbers of extended NS offload tuples if HDD has given more than
5117 * 2 NS offload addresses
5118 */
5119 if (!bArpOnly && count > WMI_MAX_NS_OFFLOADS) {
5120 num_ns_ext_tuples = count - WMI_MAX_NS_OFFLOADS;
5121 len += WMI_TLV_HDR_SIZE + num_ns_ext_tuples *
5122 sizeof(WMI_NS_OFFLOAD_TUPLE);
5123 }
5124
5125 buf = wmi_buf_alloc(wma->wmi_handle, len);
5126 if (!buf) {
5127 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
5128 cdf_mem_free(pHostOffloadParams);
5129 return CDF_STATUS_E_NOMEM;
5130 }
5131
5132 buf_ptr = (A_UINT8 *) wmi_buf_data(buf);
5133 cmd = (WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param *) buf_ptr;
5134 WMITLV_SET_HDR(&cmd->tlv_header,
5135 WMITLV_TAG_STRUC_WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param,
5136 WMITLV_GET_STRUCT_TLVLEN
5137 (WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param));
5138 cmd->flags = 0;
5139 cmd->vdev_id = vdev_id;
5140 if (!bArpOnly)
5141 cmd->num_ns_ext_tuples = num_ns_ext_tuples;
5142
5143 WMA_LOGD("ARP NS Offload vdev_id: %d", cmd->vdev_id);
5144
5145 /* Have copy of arp info to send along with NS, Since FW expects
5146 * both ARP and NS info in single cmd */
5147 if (bArpOnly)
5148 cdf_mem_copy(&wma->mArpInfo, pHostOffloadParams,
5149 sizeof(tSirHostOffloadReq));
5150
5151 buf_ptr += sizeof(WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param);
5152 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
5153 (WMI_MAX_NS_OFFLOADS * sizeof(WMI_NS_OFFLOAD_TUPLE)));
5154 buf_ptr += WMI_TLV_HDR_SIZE;
5155 for (i = 0; i < WMI_MAX_NS_OFFLOADS; i++) {
5156 ns_tuple = (WMI_NS_OFFLOAD_TUPLE *) buf_ptr;
5157 WMITLV_SET_HDR(&ns_tuple->tlv_header,
5158 WMITLV_TAG_STRUC_WMI_NS_OFFLOAD_TUPLE,
5159 (sizeof(WMI_NS_OFFLOAD_TUPLE) -
5160 WMI_TLV_HDR_SIZE));
5161
5162 /* Fill data only for NS offload in the first ARP tuple for LA */
5163 if (!bArpOnly &&
5164 ((pHostOffloadParams->enableOrDisable & SIR_OFFLOAD_ENABLE))) {
5165 ns_tuple->flags |= WMI_NSOFF_FLAGS_VALID;
5166
5167#ifdef WLAN_NS_OFFLOAD
5168 /*Copy the target/solicitation/remote ip addr */
5169 if (pHostOffloadParams->nsOffloadInfo.
5170 targetIPv6AddrValid[i])
5171 A_MEMCPY(&ns_tuple->target_ipaddr[0],
5172 &pHostOffloadParams->nsOffloadInfo.
5173 targetIPv6Addr[i],
5174 sizeof(WMI_IPV6_ADDR));
5175 A_MEMCPY(&ns_tuple->solicitation_ipaddr,
5176 &pHostOffloadParams->nsOffloadInfo.
5177 selfIPv6Addr[i], sizeof(WMI_IPV6_ADDR));
5178 WMA_LOGD("NS solicitedIp: %pI6, targetIp: %pI6",
5179 &pHostOffloadParams->nsOffloadInfo.selfIPv6Addr[i],
5180 &pHostOffloadParams->nsOffloadInfo.
5181 targetIPv6Addr[i]);
5182
5183 /* target MAC is optional, check if it is valid,
5184 * if this is not valid, the target will use the known
5185 * local MAC address rather than the tuple
5186 */
5187 WMI_CHAR_ARRAY_TO_MAC_ADDR(pHostOffloadParams->
Srinivas Girigowda110d6202015-11-24 12:48:46 -08005188 nsOffloadInfo.self_macaddr.bytes,
5189 &ns_tuple->target_mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005190#endif /* WLAN_NS_OFFLOAD */
5191 if ((ns_tuple->target_mac.mac_addr31to0 != 0) ||
5192 (ns_tuple->target_mac.mac_addr47to32 != 0)) {
5193 ns_tuple->flags |= WMI_NSOFF_FLAGS_MAC_VALID;
5194 }
5195 }
5196 buf_ptr += sizeof(WMI_NS_OFFLOAD_TUPLE);
5197 }
5198
5199 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
5200 (WMI_MAX_ARP_OFFLOADS * sizeof(WMI_ARP_OFFLOAD_TUPLE)));
5201 buf_ptr += WMI_TLV_HDR_SIZE;
5202 for (i = 0; i < WMI_MAX_ARP_OFFLOADS; i++) {
5203 arp_tuple = (WMI_ARP_OFFLOAD_TUPLE *) buf_ptr;
5204 WMITLV_SET_HDR(&arp_tuple->tlv_header,
5205 WMITLV_TAG_STRUC_WMI_ARP_OFFLOAD_TUPLE,
5206 WMITLV_GET_STRUCT_TLVLEN(WMI_ARP_OFFLOAD_TUPLE));
5207
5208 /* Fill data for ARP and NS in the first tupple for LA */
5209 if ((wma->mArpInfo.enableOrDisable & SIR_OFFLOAD_ENABLE)
5210 && (i == 0)) {
5211 /*Copy the target ip addr and flags */
5212 arp_tuple->flags = WMI_ARPOFF_FLAGS_VALID;
5213 A_MEMCPY(&arp_tuple->target_ipaddr,
5214 wma->mArpInfo.params.hostIpv4Addr,
5215 SIR_IPV4_ADDR_LEN);
5216 WMA_LOGD("ARPOffload IP4 address: %pI4",
5217 wma->mArpInfo.params.hostIpv4Addr);
5218 }
5219 buf_ptr += sizeof(WMI_ARP_OFFLOAD_TUPLE);
5220 }
5221
5222 /* Populate extended NS offload tuples */
5223 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
5224 (num_ns_ext_tuples*sizeof(WMI_NS_OFFLOAD_TUPLE)));
5225 buf_ptr += WMI_TLV_HDR_SIZE;
5226
5227 if (num_ns_ext_tuples) {
5228 for (i = WMI_MAX_NS_OFFLOADS; i < count; i++) {
5229 ns_tuple = (WMI_NS_OFFLOAD_TUPLE *)buf_ptr;
5230 WMITLV_SET_HDR(&ns_tuple->tlv_header,
5231 WMITLV_TAG_STRUC_WMI_NS_OFFLOAD_TUPLE,
5232 (sizeof(WMI_NS_OFFLOAD_TUPLE)-WMI_TLV_HDR_SIZE));
5233
5234 /* Fill data only for NS offload in the first ARP tuple for LA */
5235 if (!bArpOnly &&
5236 ((pHostOffloadParams->enableOrDisable & SIR_OFFLOAD_ENABLE))) {
5237 ns_tuple->flags |= WMI_NSOFF_FLAGS_VALID;
5238#ifdef WLAN_NS_OFFLOAD
5239 /*Copy the target/solicitation/remote ip addr */
5240 if (pHostOffloadParams->nsOffloadInfo.targetIPv6AddrValid[i])
5241 A_MEMCPY(&ns_tuple->target_ipaddr[0],
5242 &pHostOffloadParams->nsOffloadInfo.targetIPv6Addr[i],
5243 sizeof(WMI_IPV6_ADDR));
5244 A_MEMCPY(&ns_tuple->solicitation_ipaddr,
5245 &pHostOffloadParams->nsOffloadInfo.selfIPv6Addr[i],
5246 sizeof(WMI_IPV6_ADDR));
5247 WMA_LOGD("Index %d NS solicitedIp: %pI6, targetIp: %pI6", i,
5248 &pHostOffloadParams->nsOffloadInfo.selfIPv6Addr[i],
5249 &pHostOffloadParams->nsOffloadInfo.targetIPv6Addr[i]);
5250
5251 /* target MAC is optional, check if it is valid, if this is not valid,
5252 * the target will use the known local MAC address rather than the tuple */
Srinivas Girigowda110d6202015-11-24 12:48:46 -08005253 WMI_CHAR_ARRAY_TO_MAC_ADDR(
5254 pHostOffloadParams->nsOffloadInfo.self_macaddr.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005255 &ns_tuple->target_mac);
5256#endif
5257 if ((ns_tuple->target_mac.mac_addr31to0 != 0) ||
5258 (ns_tuple->target_mac.mac_addr47to32 != 0)) {
5259 ns_tuple->flags |= WMI_NSOFF_FLAGS_MAC_VALID;
5260 }
5261 }
5262 buf_ptr += sizeof(WMI_NS_OFFLOAD_TUPLE);
5263 }
5264 }
5265
5266 res = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
5267 WMI_SET_ARP_NS_OFFLOAD_CMDID);
5268 if (res) {
5269 WMA_LOGE("Failed to enable ARP NDP/NSffload");
5270 wmi_buf_free(buf);
5271 cdf_mem_free(pHostOffloadParams);
5272 return CDF_STATUS_E_FAILURE;
5273 }
5274
5275 cdf_mem_free(pHostOffloadParams);
5276 return CDF_STATUS_SUCCESS;
5277}
5278
5279/**
5280 * wma_process_add_periodic_tx_ptrn_ind - add periodic tx ptrn
5281 * @handle: wma handle
5282 * @pAddPeriodicTxPtrnParams: tx ptrn params
5283 *
5284 * Retrun: CDF status
5285 */
5286CDF_STATUS wma_process_add_periodic_tx_ptrn_ind(WMA_HANDLE handle,
5287 tSirAddPeriodicTxPtrn *
5288 pAddPeriodicTxPtrnParams)
5289{
5290 tp_wma_handle wma_handle = (tp_wma_handle) handle;
5291 WMI_ADD_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param *cmd;
5292 wmi_buf_t wmi_buf;
5293 uint32_t len;
5294 uint8_t vdev_id;
5295 uint8_t *buf_ptr;
5296 uint32_t ptrn_len, ptrn_len_aligned;
5297 int j;
5298
5299 if (!wma_handle || !wma_handle->wmi_handle) {
5300 WMA_LOGE("%s: WMA is closed, can not issue fw add pattern cmd",
5301 __func__);
5302 return CDF_STATUS_E_INVAL;
5303 }
5304 ptrn_len = pAddPeriodicTxPtrnParams->ucPtrnSize;
5305 ptrn_len_aligned = roundup(ptrn_len, sizeof(uint32_t));
5306 len = sizeof(WMI_ADD_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param) +
5307 WMI_TLV_HDR_SIZE + ptrn_len_aligned;
5308
5309 wmi_buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
5310 if (!wmi_buf) {
5311 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
5312 return CDF_STATUS_E_NOMEM;
5313 }
5314 if (!wma_find_vdev_by_addr(wma_handle,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005315 pAddPeriodicTxPtrnParams->mac_address.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005316 &vdev_id)) {
5317 WMA_LOGE("%s: Failed to find vdev id for %pM", __func__,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005318 pAddPeriodicTxPtrnParams->mac_address.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005319 cdf_nbuf_free(wmi_buf);
5320 return CDF_STATUS_E_INVAL;
5321 }
5322 buf_ptr = (uint8_t *) wmi_buf_data(wmi_buf);
5323
5324 cmd = (WMI_ADD_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param *) buf_ptr;
5325 WMITLV_SET_HDR(&cmd->tlv_header,
5326 WMITLV_TAG_STRUC_WMI_ADD_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param,
5327 WMITLV_GET_STRUCT_TLVLEN
5328 (WMI_ADD_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param));
5329
5330 /* Pass the pattern id to delete for the corresponding vdev id */
5331 cmd->vdev_id = vdev_id;
5332 cmd->pattern_id = pAddPeriodicTxPtrnParams->ucPtrnId;
5333 cmd->timeout = pAddPeriodicTxPtrnParams->usPtrnIntervalMs;
5334 cmd->length = pAddPeriodicTxPtrnParams->ucPtrnSize;
5335
5336 /* Pattern info */
5337 buf_ptr += sizeof(WMI_ADD_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param);
5338 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, ptrn_len_aligned);
5339 buf_ptr += WMI_TLV_HDR_SIZE;
5340 cdf_mem_copy(buf_ptr, pAddPeriodicTxPtrnParams->ucPattern, ptrn_len);
5341 for (j = 0; j < pAddPeriodicTxPtrnParams->ucPtrnSize; j++) {
5342 WMA_LOGD("%s: Add Ptrn: %02x", __func__, buf_ptr[j] & 0xff);
5343 }
5344 WMA_LOGD("%s: Add ptrn id: %d vdev_id: %d",
5345 __func__, cmd->pattern_id, cmd->vdev_id);
5346
5347 if (wmi_unified_cmd_send(wma_handle->wmi_handle, wmi_buf, len,
5348 WMI_ADD_PROACTIVE_ARP_RSP_PATTERN_CMDID)) {
5349 WMA_LOGE("%s: failed to add pattern set state command",
5350 __func__);
5351 cdf_nbuf_free(wmi_buf);
5352 return CDF_STATUS_E_FAILURE;
5353 }
5354 return CDF_STATUS_SUCCESS;
5355}
5356
5357/**
5358 * wma_process_del_periodic_tx_ptrn_ind - del periodic tx ptrn
5359 * @handle: wma handle
5360 * @pDelPeriodicTxPtrnParams: tx ptrn params
5361 *
5362 * Retrun: CDF status
5363 */
5364CDF_STATUS wma_process_del_periodic_tx_ptrn_ind(WMA_HANDLE handle,
5365 tSirDelPeriodicTxPtrn *
5366 pDelPeriodicTxPtrnParams)
5367{
5368 tp_wma_handle wma_handle = (tp_wma_handle) handle;
5369 WMI_DEL_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param *cmd;
5370 wmi_buf_t wmi_buf;
5371 uint8_t vdev_id;
5372 uint32_t len =
5373 sizeof(WMI_DEL_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param);
5374
5375 if (!wma_handle || !wma_handle->wmi_handle) {
5376 WMA_LOGE("%s: WMA is closed, can not issue Del Pattern cmd",
5377 __func__);
5378 return CDF_STATUS_E_INVAL;
5379 }
5380 wmi_buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
5381 if (!wmi_buf) {
5382 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
5383 return CDF_STATUS_E_NOMEM;
5384 }
5385 if (!wma_find_vdev_by_addr(wma_handle,
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08005386 pDelPeriodicTxPtrnParams->mac_address.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005387 &vdev_id)) {
5388 WMA_LOGE("%s: Failed to find vdev id for %pM", __func__,
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08005389 pDelPeriodicTxPtrnParams->mac_address.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005390 cdf_nbuf_free(wmi_buf);
5391 return CDF_STATUS_E_INVAL;
5392 }
5393 cmd = (WMI_DEL_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param *)
5394 wmi_buf_data(wmi_buf);
5395 WMITLV_SET_HDR(&cmd->tlv_header,
5396 WMITLV_TAG_STRUC_WMI_DEL_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param,
5397 WMITLV_GET_STRUCT_TLVLEN
5398 (WMI_DEL_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param));
5399
5400 /* Pass the pattern id to delete for the corresponding vdev id */
5401 cmd->vdev_id = vdev_id;
5402 cmd->pattern_id = pDelPeriodicTxPtrnParams->ucPtrnId;
5403 WMA_LOGD("%s: Del ptrn id: %d vdev_id: %d",
5404 __func__, cmd->pattern_id, cmd->vdev_id);
5405
5406 if (wmi_unified_cmd_send(wma_handle->wmi_handle, wmi_buf, len,
5407 WMI_DEL_PROACTIVE_ARP_RSP_PATTERN_CMDID)) {
5408 WMA_LOGE("%s: failed to send del pattern command", __func__);
5409 cdf_nbuf_free(wmi_buf);
5410 return CDF_STATUS_E_FAILURE;
5411 }
5412 return CDF_STATUS_SUCCESS;
5413}
5414
5415#ifdef WLAN_FEATURE_STATS_EXT
5416/**
5417 * wma_stats_ext_req() - request ext stats from fw
5418 * @wma_ptr: wma handle
5419 * @preq: stats ext params
5420 *
5421 * Return: CDF status
5422 */
5423CDF_STATUS wma_stats_ext_req(void *wma_ptr, tpStatsExtRequest preq)
5424{
5425 int32_t ret;
5426 tp_wma_handle wma = (tp_wma_handle) wma_ptr;
5427 wmi_req_stats_ext_cmd_fixed_param *cmd;
5428 wmi_buf_t buf;
5429 uint16_t len;
5430 uint8_t *buf_ptr;
5431
5432 len = sizeof(*cmd) + WMI_TLV_HDR_SIZE + preq->request_data_len;
5433
5434 buf = wmi_buf_alloc(wma->wmi_handle, len);
5435 if (!buf) {
5436 WMA_LOGE("%s:wmi_buf_alloc failed", __func__);
5437 return -ENOMEM;
5438 }
5439
5440 buf_ptr = (uint8_t *) wmi_buf_data(buf);
5441 cmd = (wmi_req_stats_ext_cmd_fixed_param *) buf_ptr;
5442
5443 WMITLV_SET_HDR(&cmd->tlv_header,
5444 WMITLV_TAG_STRUC_wmi_req_stats_ext_cmd_fixed_param,
5445 WMITLV_GET_STRUCT_TLVLEN
5446 (wmi_req_stats_ext_cmd_fixed_param));
5447 cmd->vdev_id = preq->vdev_id;
5448 cmd->data_len = preq->request_data_len;
5449
5450 WMA_LOGD("%s: The data len value is %u and vdev id set is %u ",
5451 __func__, preq->request_data_len, preq->vdev_id);
5452
5453 buf_ptr += sizeof(wmi_req_stats_ext_cmd_fixed_param);
5454 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, cmd->data_len);
5455
5456 buf_ptr += WMI_TLV_HDR_SIZE;
5457 cdf_mem_copy(buf_ptr, preq->request_data, cmd->data_len);
5458
5459 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
5460 WMI_REQUEST_STATS_EXT_CMDID);
5461 if (ret != EOK) {
5462 WMA_LOGE("%s: Failed to send notify cmd ret = %d", __func__,
5463 ret);
5464 wmi_buf_free(buf);
5465 }
5466
5467 return ret;
5468}
5469
5470#endif /* WLAN_FEATURE_STATS_EXT */
5471
5472#ifdef WLAN_FEATURE_EXTWOW_SUPPORT
5473/**
5474 * wma_send_status_of_ext_wow() - send ext wow status to SME
5475 * @wma: wma handle
5476 * @status: status
5477 *
5478 * Return: none
5479 */
5480static void wma_send_status_of_ext_wow(tp_wma_handle wma, bool status)
5481{
5482 tSirReadyToExtWoWInd *ready_to_extwow;
5483 CDF_STATUS vstatus;
5484 cds_msg_t cds_msg;
5485 uint8_t len;
5486
5487 WMA_LOGD("Posting ready to suspend indication to umac");
5488
5489 len = sizeof(tSirReadyToExtWoWInd);
5490 ready_to_extwow = (tSirReadyToExtWoWInd *) cdf_mem_malloc(len);
5491
5492 if (NULL == ready_to_extwow) {
5493 WMA_LOGE("%s: Memory allocation failure", __func__);
5494 return;
5495 }
5496
5497 ready_to_extwow->mesgType = eWNI_SME_READY_TO_EXTWOW_IND;
5498 ready_to_extwow->mesgLen = len;
5499 ready_to_extwow->status = status;
5500
5501 cds_msg.type = eWNI_SME_READY_TO_EXTWOW_IND;
5502 cds_msg.bodyptr = (void *)ready_to_extwow;
5503 cds_msg.bodyval = 0;
5504
5505 vstatus = cds_mq_post_message(CDS_MQ_ID_SME, &cds_msg);
5506 if (vstatus != CDF_STATUS_SUCCESS) {
5507 WMA_LOGE("Failed to post ready to suspend");
5508 cdf_mem_free(ready_to_extwow);
5509 }
5510}
5511
5512/**
5513 * wma_enable_ext_wow() - enable ext wow in fw
5514 * @wma: wma handle
5515 * @params: ext wow params
5516 *
5517 * Return:0 for success or error code
5518 */
5519int wma_enable_ext_wow(tp_wma_handle wma, tpSirExtWoWParams params)
5520{
5521 wmi_extwow_enable_cmd_fixed_param *cmd;
5522 wmi_buf_t buf;
5523 int32_t len;
5524 int ret;
5525
5526 len = sizeof(wmi_extwow_enable_cmd_fixed_param);
5527 buf = wmi_buf_alloc(wma->wmi_handle, len);
5528 if (!buf) {
5529 WMA_LOGE("%s: Failed allocate wmi buffer", __func__);
5530 return CDF_STATUS_E_NOMEM;
5531 }
5532
5533 cmd = (wmi_extwow_enable_cmd_fixed_param *) wmi_buf_data(buf);
5534
5535 WMITLV_SET_HDR(&cmd->tlv_header,
5536 WMITLV_TAG_STRUC_wmi_extwow_enable_cmd_fixed_param,
5537 WMITLV_GET_STRUCT_TLVLEN
5538 (wmi_extwow_enable_cmd_fixed_param));
5539
5540 cmd->vdev_id = params->vdev_id;
5541 cmd->type = params->type;
5542 cmd->wakeup_pin_num = params->wakeup_pin_num;
5543
5544 WMA_LOGD("%s: vdev_id %d type %d Wakeup_pin_num %x",
5545 __func__, cmd->vdev_id, cmd->type, cmd->wakeup_pin_num);
5546
5547 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
5548 WMI_EXTWOW_ENABLE_CMDID);
5549 if (ret) {
5550 WMA_LOGE("%s: Failed to set EXTWOW Enable", __func__);
5551 wmi_buf_free(buf);
5552 wma_send_status_of_ext_wow(wma, false);
5553 return CDF_STATUS_E_FAILURE;
5554 }
5555
5556 wma_send_status_of_ext_wow(wma, true);
5557 return CDF_STATUS_SUCCESS;
5558
5559}
5560
5561/**
5562 * wma_set_app_type1_params_in_fw() - set app type1 params in fw
5563 * @wma: wma handle
5564 * @appType1Params: app type1 params
5565 *
5566 * Return: CDF status
5567 */
5568int wma_set_app_type1_params_in_fw(tp_wma_handle wma,
5569 tpSirAppType1Params appType1Params)
5570{
5571 wmi_extwow_set_app_type1_params_cmd_fixed_param *cmd;
5572 wmi_buf_t buf;
5573 int32_t len;
5574 int ret;
5575
5576 len = sizeof(wmi_extwow_set_app_type1_params_cmd_fixed_param);
5577 buf = wmi_buf_alloc(wma->wmi_handle, len);
5578 if (!buf) {
5579 WMA_LOGE("%s: Failed allocate wmi buffer", __func__);
5580 return CDF_STATUS_E_NOMEM;
5581 }
5582
5583 cmd = (wmi_extwow_set_app_type1_params_cmd_fixed_param *)
5584 wmi_buf_data(buf);
5585
5586 WMITLV_SET_HDR(&cmd->tlv_header,
5587 WMITLV_TAG_STRUC_wmi_extwow_set_app_type1_params_cmd_fixed_param,
5588 WMITLV_GET_STRUCT_TLVLEN
5589 (wmi_extwow_set_app_type1_params_cmd_fixed_param));
5590
5591 cmd->vdev_id = appType1Params->vdev_id;
Srinivas Girigowda04209912015-11-24 12:11:13 -08005592 WMI_CHAR_ARRAY_TO_MAC_ADDR(appType1Params->wakee_mac_addr.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005593 &cmd->wakee_mac);
5594 cdf_mem_copy(cmd->ident, appType1Params->identification_id, 8);
5595 cmd->ident_len = appType1Params->id_length;
5596 cdf_mem_copy(cmd->passwd, appType1Params->password, 16);
5597 cmd->passwd_len = appType1Params->pass_length;
5598
5599 WMA_LOGD("%s: vdev_id %d wakee_mac_addr %pM "
5600 "identification_id %.8s id_length %u "
5601 "password %.16s pass_length %u",
Srinivas Girigowda04209912015-11-24 12:11:13 -08005602 __func__, cmd->vdev_id, appType1Params->wakee_mac_addr.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005603 cmd->ident, cmd->ident_len, cmd->passwd, cmd->passwd_len);
5604
5605 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
5606 WMI_EXTWOW_SET_APP_TYPE1_PARAMS_CMDID);
5607 if (ret) {
5608 WMA_LOGE("%s: Failed to set APP TYPE1 PARAMS", __func__);
5609 wmi_buf_free(buf);
5610 return CDF_STATUS_E_FAILURE;
5611 }
5612
5613 return CDF_STATUS_SUCCESS;
5614}
5615
5616/**
5617 * wma_set_app_type2_params_in_fw() - set app type2 params in fw
5618 * @wma: wma handle
5619 * @appType2Params: app type2 params
5620 *
5621 * Return: CDF status
5622 */
5623int wma_set_app_type2_params_in_fw(tp_wma_handle wma,
5624 tpSirAppType2Params appType2Params)
5625{
5626 wmi_extwow_set_app_type2_params_cmd_fixed_param *cmd;
5627 wmi_buf_t buf;
5628 int32_t len;
5629 int ret;
5630
5631 len = sizeof(wmi_extwow_set_app_type2_params_cmd_fixed_param);
5632 buf = wmi_buf_alloc(wma->wmi_handle, len);
5633 if (!buf) {
5634 WMA_LOGE("%s: Failed allocate wmi buffer", __func__);
5635 return CDF_STATUS_E_NOMEM;
5636 }
5637
5638 cmd = (wmi_extwow_set_app_type2_params_cmd_fixed_param *)
5639 wmi_buf_data(buf);
5640
5641 WMITLV_SET_HDR(&cmd->tlv_header,
5642 WMITLV_TAG_STRUC_wmi_extwow_set_app_type2_params_cmd_fixed_param,
5643 WMITLV_GET_STRUCT_TLVLEN
5644 (wmi_extwow_set_app_type2_params_cmd_fixed_param));
5645
5646 cmd->vdev_id = appType2Params->vdev_id;
5647
5648 cdf_mem_copy(cmd->rc4_key, appType2Params->rc4_key, 16);
5649 cmd->rc4_key_len = appType2Params->rc4_key_len;
5650
5651 cmd->ip_id = appType2Params->ip_id;
5652 cmd->ip_device_ip = appType2Params->ip_device_ip;
5653 cmd->ip_server_ip = appType2Params->ip_server_ip;
5654
5655 cmd->tcp_src_port = appType2Params->tcp_src_port;
5656 cmd->tcp_dst_port = appType2Params->tcp_dst_port;
5657 cmd->tcp_seq = appType2Params->tcp_seq;
5658 cmd->tcp_ack_seq = appType2Params->tcp_ack_seq;
5659
5660 cmd->keepalive_init = appType2Params->keepalive_init;
5661 cmd->keepalive_min = appType2Params->keepalive_min;
5662 cmd->keepalive_max = appType2Params->keepalive_max;
5663 cmd->keepalive_inc = appType2Params->keepalive_inc;
5664
Srinivas Girigowda04209912015-11-24 12:11:13 -08005665 WMI_CHAR_ARRAY_TO_MAC_ADDR(appType2Params->gateway_mac.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005666 &cmd->gateway_mac);
5667 cmd->tcp_tx_timeout_val = appType2Params->tcp_tx_timeout_val;
5668 cmd->tcp_rx_timeout_val = appType2Params->tcp_rx_timeout_val;
5669
5670 WMA_LOGD("%s: vdev_id %d gateway_mac %pM "
5671 "rc4_key %.16s rc4_key_len %u "
5672 "ip_id %x ip_device_ip %x ip_server_ip %x "
5673 "tcp_src_port %u tcp_dst_port %u tcp_seq %u "
5674 "tcp_ack_seq %u keepalive_init %u keepalive_min %u "
5675 "keepalive_max %u keepalive_inc %u "
5676 "tcp_tx_timeout_val %u tcp_rx_timeout_val %u",
Srinivas Girigowda04209912015-11-24 12:11:13 -08005677 __func__, cmd->vdev_id, appType2Params->gateway_mac.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005678 cmd->rc4_key, cmd->rc4_key_len,
5679 cmd->ip_id, cmd->ip_device_ip, cmd->ip_server_ip,
5680 cmd->tcp_src_port, cmd->tcp_dst_port, cmd->tcp_seq,
5681 cmd->tcp_ack_seq, cmd->keepalive_init, cmd->keepalive_min,
5682 cmd->keepalive_max, cmd->keepalive_inc,
5683 cmd->tcp_tx_timeout_val, cmd->tcp_rx_timeout_val);
5684
5685 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
5686 WMI_EXTWOW_SET_APP_TYPE2_PARAMS_CMDID);
5687 if (ret) {
5688 WMA_LOGE("%s: Failed to set APP TYPE2 PARAMS", __func__);
5689 wmi_buf_free(buf);
5690 return CDF_STATUS_E_FAILURE;
5691 }
5692
5693 return CDF_STATUS_SUCCESS;
5694
5695}
5696#endif /* WLAN_FEATURE_EXTWOW_SUPPORT */
5697
5698#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
5699/**
5700 * wma_auto_shutdown_event_handler() - process auto shutdown timer trigger
5701 * @handle: wma handle
5702 * @event: event buffer
5703 * @len: buffer length
5704 *
5705 * Return: 0 for success or error code
5706 */
5707int wma_auto_shutdown_event_handler(void *handle, uint8_t *event,
5708 uint32_t len)
5709{
5710 wmi_host_auto_shutdown_event_fixed_param *wmi_auto_sh_evt;
5711 WMI_HOST_AUTO_SHUTDOWN_EVENTID_param_tlvs *param_buf =
5712 (WMI_HOST_AUTO_SHUTDOWN_EVENTID_param_tlvs *)
5713 event;
5714
5715 if (!param_buf || !param_buf->fixed_param) {
5716 WMA_LOGE("%s:%d: Invalid Auto shutdown timer evt", __func__,
5717 __LINE__);
5718 return -EINVAL;
5719 }
5720
5721 wmi_auto_sh_evt = param_buf->fixed_param;
5722
5723 if (wmi_auto_sh_evt->shutdown_reason
5724 != WMI_HOST_AUTO_SHUTDOWN_REASON_TIMER_EXPIRY) {
5725 WMA_LOGE("%s:%d: Invalid Auto shutdown timer evt", __func__,
5726 __LINE__);
5727 return -EINVAL;
5728 }
5729
5730 WMA_LOGD("%s:%d: Auto Shutdown Evt: %d", __func__, __LINE__,
5731 wmi_auto_sh_evt->shutdown_reason);
5732 return wma_post_auto_shutdown_msg();
5733}
5734
5735/**
5736 * wma_set_auto_shutdown_timer_req() - sets auto shutdown timer in firmware
5737 * @wma: wma handle
5738 * @auto_sh_cmd: auto shutdown timer value
5739 *
5740 * Return: CDF status
5741 */
5742CDF_STATUS wma_set_auto_shutdown_timer_req(tp_wma_handle wma_handle,
5743 tSirAutoShutdownCmdParams *
5744 auto_sh_cmd)
5745{
5746 int status = 0;
5747 wmi_buf_t buf = NULL;
5748 uint8_t *buf_ptr;
5749 wmi_host_auto_shutdown_cfg_cmd_fixed_param *wmi_auto_sh_cmd;
5750 int len = sizeof(wmi_host_auto_shutdown_cfg_cmd_fixed_param);
5751
5752 if (auto_sh_cmd == NULL) {
5753 WMA_LOGE("%s : Invalid Autoshutdown cfg cmd", __func__);
5754 return CDF_STATUS_E_FAILURE;
5755 }
5756
5757 WMA_LOGD("%s: Set WMI_HOST_AUTO_SHUTDOWN_CFG_CMDID:TIMER_VAL=%d",
5758 __func__, auto_sh_cmd->timer_val);
5759
5760 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
5761 if (!buf) {
5762 WMA_LOGE("%s : wmi_buf_alloc failed", __func__);
5763 return CDF_STATUS_E_NOMEM;
5764 }
5765
5766 buf_ptr = (uint8_t *) wmi_buf_data(buf);
5767 wmi_auto_sh_cmd =
5768 (wmi_host_auto_shutdown_cfg_cmd_fixed_param *) buf_ptr;
5769 wmi_auto_sh_cmd->timer_value = auto_sh_cmd->timer_val;
5770
5771 WMITLV_SET_HDR(&wmi_auto_sh_cmd->tlv_header,
5772 WMITLV_TAG_STRUC_wmi_host_auto_shutdown_cfg_cmd_fixed_param,
5773 WMITLV_GET_STRUCT_TLVLEN
5774 (wmi_host_auto_shutdown_cfg_cmd_fixed_param));
5775
5776 status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf,
5777 len, WMI_HOST_AUTO_SHUTDOWN_CFG_CMDID);
5778 if (status != EOK) {
5779 WMA_LOGE("%s: WMI_HOST_AUTO_SHUTDOWN_CFG_CMDID Err %d",
5780 __func__, status);
5781 wmi_buf_free(buf);
5782 return CDF_STATUS_E_FAILURE;
5783 }
5784
5785 return CDF_STATUS_SUCCESS;
5786}
5787#endif /* FEATURE_WLAN_AUTO_SHUTDOWN */
5788
5789#ifdef WLAN_FEATURE_NAN
5790/**
5791 * wma_nan_req() - to send nan request to target
5792 * @wma: wma_handle
5793 * @nan_req: request data which will be non-null
5794 *
5795 * Return: CDF status
5796 */
5797CDF_STATUS wma_nan_req(void *wma_ptr, tpNanRequest nan_req)
5798{
5799 int ret;
5800 tp_wma_handle wma_handle = (tp_wma_handle) wma_ptr;
5801 wmi_nan_cmd_param *cmd;
5802 wmi_buf_t buf;
5803 uint16_t len = sizeof(*cmd);
5804 uint16_t nan_data_len, nan_data_len_aligned;
5805 uint8_t *buf_ptr;
5806
5807 /*
5808 * <----- cmd ------------><-- WMI_TLV_HDR_SIZE --><--- data ---->
5809 * +------------+----------+-----------------------+--------------+
5810 * | tlv_header | data_len | WMITLV_TAG_ARRAY_BYTE | nan_req_data |
5811 * +------------+----------+-----------------------+--------------+
5812 */
5813 if (!nan_req) {
5814 WMA_LOGE("%s:nan req is not valid", __func__);
5815 return CDF_STATUS_E_FAILURE;
5816 }
5817 nan_data_len = nan_req->request_data_len;
5818 nan_data_len_aligned = roundup(nan_req->request_data_len,
5819 sizeof(uint32_t));
5820 len += WMI_TLV_HDR_SIZE + nan_data_len_aligned;
5821 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
5822 if (!buf) {
5823 WMA_LOGE("%s:wmi_buf_alloc failed", __func__);
5824 return CDF_STATUS_E_NOMEM;
5825 }
5826 buf_ptr = (uint8_t *) wmi_buf_data(buf);
5827 cmd = (wmi_nan_cmd_param *) buf_ptr;
5828 WMITLV_SET_HDR(&cmd->tlv_header,
5829 WMITLV_TAG_STRUC_wmi_nan_cmd_param,
5830 WMITLV_GET_STRUCT_TLVLEN(wmi_nan_cmd_param));
5831 cmd->data_len = nan_req->request_data_len;
5832 WMA_LOGD("%s: The data len value is %u",
5833 __func__, nan_req->request_data_len);
5834 buf_ptr += sizeof(wmi_nan_cmd_param);
5835 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, nan_data_len_aligned);
5836 buf_ptr += WMI_TLV_HDR_SIZE;
5837 cdf_mem_copy(buf_ptr, nan_req->request_data, cmd->data_len);
5838
5839 ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len,
5840 WMI_NAN_CMDID);
5841 if (ret != EOK) {
5842 WMA_LOGE("%s Failed to send set param command ret = %d",
5843 __func__, ret);
5844 wmi_buf_free(buf);
5845 }
5846 return ret;
5847}
5848#endif /* WLAN_FEATURE_NAN */
5849
5850#ifdef DHCP_SERVER_OFFLOAD
5851/**
5852 * wma_process_dhcpserver_offload() - enable DHCP server offload
5853 * @wma_handle: wma handle
5854 * @pDhcpSrvOffloadInfo: DHCP server offload info
5855 *
5856 * Return: 0 for success or error code
5857 */
5858int wma_process_dhcpserver_offload(tp_wma_handle wma_handle,
5859 tSirDhcpSrvOffloadInfo *
5860 pDhcpSrvOffloadInfo)
5861{
5862 wmi_set_dhcp_server_offload_cmd_fixed_param *cmd;
5863 wmi_buf_t buf;
5864 int err;
5865
5866 buf = wmi_buf_alloc(wma_handle->wmi_handle, sizeof(*cmd));
5867 if (!buf) {
5868 WMA_LOGE("Failed to allocate buffer to send "
5869 "set_dhcp_server_offload cmd");
5870 return -ENOMEM;
5871 }
5872
5873 cmd = (wmi_set_dhcp_server_offload_cmd_fixed_param *) wmi_buf_data(buf);
5874 cdf_mem_zero(cmd, sizeof(*cmd));
5875
5876 WMITLV_SET_HDR(&cmd->tlv_header,
5877 WMITLV_TAG_STRUC_wmi_set_dhcp_server_offload_cmd_fixed_param,
5878 WMITLV_GET_STRUCT_TLVLEN
5879 (wmi_set_dhcp_server_offload_cmd_fixed_param));
5880 cmd->vdev_id = pDhcpSrvOffloadInfo->vdev_id;
5881 cmd->enable = pDhcpSrvOffloadInfo->dhcpSrvOffloadEnabled;
5882 cmd->num_client = pDhcpSrvOffloadInfo->dhcpClientNum;
5883 cmd->srv_ipv4 = pDhcpSrvOffloadInfo->dhcpSrvIP;
5884 cmd->start_lsb = 0;
5885 err = wmi_unified_cmd_send(wma_handle->wmi_handle, buf,
5886 sizeof(*cmd),
5887 WMI_SET_DHCP_SERVER_OFFLOAD_CMDID);
5888 if (err) {
5889 WMA_LOGE("Failed to send set_dhcp_server_offload cmd");
5890 wmi_buf_free(buf);
5891 return -EIO;
5892 }
5893 WMA_LOGD("Set dhcp server offload to vdevId %d",
5894 pDhcpSrvOffloadInfo->vdev_id);
5895 return 0;
5896}
5897#endif /* DHCP_SERVER_OFFLOAD */
5898
5899#ifdef WLAN_FEATURE_GPIO_LED_FLASHING
5900/**
5901 * wma_set_led_flashing() - set led flashing in fw
5902 * @wma_handle: wma handle
5903 * @flashing: flashing request
5904 *
5905 * Return: CDF status
5906 */
5907CDF_STATUS wma_set_led_flashing(tp_wma_handle wma_handle,
5908 tSirLedFlashingReq *flashing)
5909{
5910 wmi_set_led_flashing_cmd_fixed_param *cmd;
5911 int status = 0;
5912 wmi_buf_t buf;
5913 uint8_t *buf_ptr;
5914 int32_t len = sizeof(wmi_set_led_flashing_cmd_fixed_param);
5915
5916 if (!wma_handle || !wma_handle->wmi_handle) {
5917 WMA_LOGE(FL("WMA is closed, can not issue cmd"));
5918 return CDF_STATUS_E_INVAL;
5919 }
5920 if (!flashing) {
5921 WMA_LOGE(FL("invalid parameter: flashing"));
5922 return CDF_STATUS_E_INVAL;
5923 }
5924
5925 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
5926 if (!buf) {
5927 WMA_LOGP(FL("wmi_buf_alloc failed"));
5928 return -ENOMEM;
5929 }
5930 buf_ptr = (uint8_t *) wmi_buf_data(buf);
5931 cmd = (wmi_set_led_flashing_cmd_fixed_param *) buf_ptr;
5932 WMITLV_SET_HDR(&cmd->tlv_header,
5933 WMITLV_TAG_STRUC_wmi_set_led_flashing_cmd_fixed_param,
5934 WMITLV_GET_STRUCT_TLVLEN
5935 (wmi_set_led_flashing_cmd_fixed_param));
5936 cmd->pattern_id = flashing->pattern_id;
5937 cmd->led_x0 = flashing->led_x0;
5938 cmd->led_x1 = flashing->led_x1;
5939
5940 status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len,
5941 WMI_PDEV_SET_LED_FLASHING_CMDID);
5942 if (status != EOK) {
5943 WMA_LOGE("%s: wmi_unified_cmd_send WMI_PEER_SET_PARAM_CMD"
5944 " returned Error %d", __func__, status);
5945 return CDF_STATUS_E_FAILURE;
5946 }
5947 return CDF_STATUS_SUCCESS;
5948}
5949#endif /* WLAN_FEATURE_GPIO_LED_FLASHING */
5950
5951#ifdef FEATURE_WLAN_CH_AVOID
5952/**
5953 * wma_channel_avoid_evt_handler() - process channel to avoid event from FW.
5954 * @handle: wma handle
5955 * @event: event buffer
5956 * @len: buffer length
5957 *
5958 * Return: 0 for success or error code
5959 */
5960int wma_channel_avoid_evt_handler(void *handle, uint8_t *event,
5961 uint32_t len)
5962{
5963 wmi_avoid_freq_ranges_event_fixed_param *afr_fixed_param;
5964 wmi_avoid_freq_range_desc *afr_desc;
5965 uint32_t num_freq_ranges, freq_range_idx;
5966 tSirChAvoidIndType *sca_indication;
5967 CDF_STATUS cdf_status;
5968 cds_msg_t sme_msg = { 0 };
5969 WMI_WLAN_FREQ_AVOID_EVENTID_param_tlvs *param_buf =
5970 (WMI_WLAN_FREQ_AVOID_EVENTID_param_tlvs *) event;
5971
5972 if (!param_buf) {
5973 WMA_LOGE("Invalid channel avoid event buffer");
5974 return -EINVAL;
5975 }
5976
5977 afr_fixed_param = param_buf->fixed_param;
5978 if (!afr_fixed_param) {
5979 WMA_LOGE("Invalid channel avoid event fixed param buffer");
5980 return -EINVAL;
5981 }
5982
5983 num_freq_ranges =
5984 (afr_fixed_param->num_freq_ranges >
5985 SIR_CH_AVOID_MAX_RANGE) ? SIR_CH_AVOID_MAX_RANGE :
5986 afr_fixed_param->num_freq_ranges;
5987
5988 WMA_LOGD("Channel avoid event received with %d ranges",
5989 num_freq_ranges);
5990 for (freq_range_idx = 0; freq_range_idx < num_freq_ranges;
5991 freq_range_idx++) {
5992 afr_desc = (wmi_avoid_freq_range_desc *)
5993 ((void *)param_buf->avd_freq_range +
5994 freq_range_idx * sizeof(wmi_avoid_freq_range_desc));
5995
5996 WMA_LOGD("range %d: tlv id = %u, start freq = %u, end freq = %u",
5997 freq_range_idx, afr_desc->tlv_header, afr_desc->start_freq,
5998 afr_desc->end_freq);
5999 }
6000
6001 sca_indication = (tSirChAvoidIndType *)
6002 cdf_mem_malloc(sizeof(tSirChAvoidIndType));
6003 if (!sca_indication) {
6004 WMA_LOGE("Invalid channel avoid indication buffer");
6005 return -EINVAL;
6006 }
6007
6008 sca_indication->avoid_range_count = num_freq_ranges;
6009 for (freq_range_idx = 0; freq_range_idx < num_freq_ranges;
6010 freq_range_idx++) {
6011 afr_desc = (wmi_avoid_freq_range_desc *)
6012 ((void *)param_buf->avd_freq_range +
6013 freq_range_idx * sizeof(wmi_avoid_freq_range_desc));
6014 sca_indication->avoid_freq_range[freq_range_idx].start_freq =
6015 afr_desc->start_freq;
6016 sca_indication->avoid_freq_range[freq_range_idx].end_freq =
6017 afr_desc->end_freq;
6018 }
6019
6020 sme_msg.type = eWNI_SME_CH_AVOID_IND;
6021 sme_msg.bodyptr = sca_indication;
6022 sme_msg.bodyval = 0;
6023
6024 cdf_status = cds_mq_post_message(CDF_MODULE_ID_SME, &sme_msg);
6025 if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
6026 WMA_LOGE("Fail to post eWNI_SME_CH_AVOID_IND msg to SME");
6027 cdf_mem_free(sca_indication);
6028 return -EINVAL;
6029 }
6030
6031 return 0;
6032}
6033
6034/**
6035 * wma_process_ch_avoid_update_req() - handles channel avoid update request
6036 * @wma_handle: wma handle
6037 * @ch_avoid_update_req: channel avoid update params
6038 *
6039 * Return: CDF status
6040 */
6041CDF_STATUS wma_process_ch_avoid_update_req(tp_wma_handle wma_handle,
6042 tSirChAvoidUpdateReq *
6043 ch_avoid_update_req)
6044{
6045 int status = 0;
6046 wmi_buf_t buf = NULL;
6047 uint8_t *buf_ptr;
6048 wmi_chan_avoid_update_cmd_param *ch_avoid_update_fp;
6049 int len = sizeof(wmi_chan_avoid_update_cmd_param);
6050
6051 if (ch_avoid_update_req == NULL) {
6052 WMA_LOGE("%s : ch_avoid_update_req is NULL", __func__);
6053 return CDF_STATUS_E_FAILURE;
6054 }
6055
6056 WMA_LOGI("%s: WMA --> WMI_CHAN_AVOID_UPDATE", __func__);
6057
6058 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
6059 if (!buf) {
6060 WMA_LOGE("%s : wmi_buf_alloc failed", __func__);
6061 return CDF_STATUS_E_NOMEM;
6062 }
6063
6064 buf_ptr = (uint8_t *) wmi_buf_data(buf);
6065 ch_avoid_update_fp = (wmi_chan_avoid_update_cmd_param *) buf_ptr;
6066 WMITLV_SET_HDR(&ch_avoid_update_fp->tlv_header,
6067 WMITLV_TAG_STRUC_wmi_chan_avoid_update_cmd_param,
6068 WMITLV_GET_STRUCT_TLVLEN
6069 (wmi_chan_avoid_update_cmd_param));
6070
6071 status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf,
6072 len, WMI_CHAN_AVOID_UPDATE_CMDID);
6073 if (status != EOK) {
6074 WMA_LOGE("wmi_unified_cmd_send"
6075 " WMITLV_TABLE_WMI_CHAN_AVOID_UPDATE"
6076 " returned Error %d", status);
6077 wmi_buf_free(buf);
6078 return CDF_STATUS_E_FAILURE;
6079 }
6080
6081 WMA_LOGI("%s: WMA --> WMI_CHAN_AVOID_UPDATE sent through WMI",
6082 __func__);
6083 return CDF_STATUS_SUCCESS;
6084}
6085#endif /* FEATURE_WLAN_CH_AVOID */
6086
6087/**
6088 * wma_set_reg_domain() - set reg domain
6089 * @clientCtxt: client context
6090 * @regId: reg id
6091 *
6092 * Return: CDF status
6093 */
6094CDF_STATUS wma_set_reg_domain(void *clientCtxt, v_REGDOMAIN_t regId)
6095{
6096 if (CDF_STATUS_SUCCESS !=
6097 cds_set_reg_domain(clientCtxt, regId))
6098 return CDF_STATUS_E_INVAL;
6099
6100 return CDF_STATUS_SUCCESS;
6101}
6102
6103/**
6104 * wma_send_regdomain_info_to_fw() - send regdomain info to fw
6105 * @reg_dmn: reg domain
6106 * @regdmn2G: 2G reg domain
6107 * @regdmn5G: 5G reg domain
6108 * @ctl2G: 2G test limit
6109 * @ctl5G: 5G test limit
6110 *
6111 * Return: none
6112 */
6113void wma_send_regdomain_info_to_fw(uint32_t reg_dmn, uint16_t regdmn2G,
6114 uint16_t regdmn5G, int8_t ctl2G,
6115 int8_t ctl5G)
6116{
6117 wmi_buf_t buf;
6118 wmi_pdev_set_regdomain_cmd_fixed_param *cmd;
6119 int32_t len = sizeof(*cmd);
6120 tp_wma_handle wma = cds_get_context(CDF_MODULE_ID_WMA);
6121 int32_t cck_mask_val = 0;
6122 int ret = 0;
6123
6124 if (NULL == wma) {
6125 WMA_LOGE("%s: wma context is NULL", __func__);
6126 return;
6127 }
6128
6129 buf = wmi_buf_alloc(wma->wmi_handle, len);
6130 if (!buf) {
6131 WMA_LOGP("%s: wmi_buf_alloc failed", __func__);
6132 return;
6133 }
6134 cmd = (wmi_pdev_set_regdomain_cmd_fixed_param *) wmi_buf_data(buf);
6135 WMITLV_SET_HDR(&cmd->tlv_header,
6136 WMITLV_TAG_STRUC_wmi_pdev_set_regdomain_cmd_fixed_param,
6137 WMITLV_GET_STRUCT_TLVLEN
6138 (wmi_pdev_set_regdomain_cmd_fixed_param));
6139 cmd->reg_domain = reg_dmn;
6140 cmd->reg_domain_2G = regdmn2G;
6141 cmd->reg_domain_5G = regdmn5G;
6142 cmd->conformance_test_limit_2G = ctl2G;
6143 cmd->conformance_test_limit_5G = ctl5G;
6144
6145 if (wmi_unified_cmd_send(wma->wmi_handle, buf, len,
6146 WMI_PDEV_SET_REGDOMAIN_CMDID)) {
6147 WMA_LOGP("%s: Failed to send pdev set regdomain command",
6148 __func__);
6149 cdf_nbuf_free(buf);
6150 }
6151
6152 if ((((reg_dmn & ~COUNTRY_ERD_FLAG) == CTRY_JAPAN) ||
6153 ((reg_dmn & ~COUNTRY_ERD_FLAG) == CTRY_KOREA_ROC)) &&
6154 (true == wma->tx_chain_mask_cck))
6155 cck_mask_val = 1;
6156
6157 cck_mask_val |= (wma->self_gen_frm_pwr << 16);
6158 ret = wmi_unified_pdev_set_param(wma->wmi_handle,
6159 WMI_PDEV_PARAM_TX_CHAIN_MASK_CCK,
6160 cck_mask_val);
6161 if (ret)
6162 WMA_LOGE("failed to set PDEV tx_chain_mask_cck %d",
6163 ret);
6164
6165 return;
6166}
6167
6168/**
6169 * wma_bus_suspend() - handles bus suspend request from hdd
6170 *
6171 * Calls the appropriate handler based on configuration and event
6172 *
6173 * Return: 0 for success or error code
6174 */
6175int wma_bus_suspend(void)
6176{
6177 WMA_HANDLE handle = cds_get_context(CDF_MODULE_ID_WMA);
6178 if (NULL == handle) {
6179 WMA_LOGE("%s: wma context is NULL", __func__);
6180 return -EFAULT;
6181 }
6182
6183 WMA_LOGE("%s: wow mode selected %d", __func__,
6184 wma_is_wow_mode_selected(handle));
6185
6186 if (wma_check_scan_in_progress(handle)) {
6187 WMA_LOGE("%s: Scan in progress. Aborting suspend", __func__);
6188 return -EBUSY;
6189 }
6190
6191 if (wma_is_wow_mode_selected(handle))
6192 return cdf_status_to_os_return(wma_enable_wow_in_fw(handle));
6193
6194 return wma_suspend_target(handle, 0);
6195}
6196
6197/**
6198 * wma_bus_resume() - handles bus resume request from hdd
6199 * @handle: valid wma handle
6200 *
6201 * Calls the appropriate handler based on configuration
6202 *
6203 * Return: 0 for success or error code
6204 */
6205int wma_bus_resume(void)
6206{
6207 WMA_HANDLE handle = cds_get_context(CDF_MODULE_ID_WMA);
6208 int wow_mode;
6209 if (NULL == handle) {
6210 WMA_LOGE("%s: wma context is NULL", __func__);
6211 return -EFAULT;
6212 }
6213
6214 wow_mode = wma_is_wow_mode_selected(handle);
6215 WMA_LOGE("%s: wow mode %d", __func__, wow_mode);
6216
6217 if (!wow_mode)
6218 return wma_resume_target(handle);
6219
6220 return cdf_status_to_os_return(wma_disable_wow_in_fw(handle));
6221}
6222
6223/**
6224 * wma_suspend_target() - suspend target
6225 * @handle: wma handle
6226 * @disable_target_intr: disable target interrupt
6227 *
6228 * Return: 0 for success or error code
6229 */
6230int wma_suspend_target(WMA_HANDLE handle, int disable_target_intr)
6231{
6232 tp_wma_handle wma_handle = (tp_wma_handle) handle;
6233 wmi_pdev_suspend_cmd_fixed_param *cmd;
6234 wmi_buf_t wmibuf;
6235 uint32_t len = sizeof(*cmd);
6236 struct ol_softc *scn;
6237 int ret;
Yue Mae1a85f32015-10-20 18:12:45 -07006238#ifdef CONFIG_CNSS
6239 tpAniSirGlobal pmac = cds_get_context(CDF_MODULE_ID_PE);
6240#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006241
6242 if (!wma_handle || !wma_handle->wmi_handle) {
6243 WMA_LOGE("WMA is closed. can not issue suspend cmd");
6244 return -EINVAL;
6245 }
Yue Mae1a85f32015-10-20 18:12:45 -07006246
6247#ifdef CONFIG_CNSS
6248 if (NULL == pmac) {
6249 WMA_LOGE("%s: Unable to get PE context", __func__);
6250 return -EINVAL;
6251 }
6252#endif
6253
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006254 /*
6255 * send the comand to Target to ignore the
6256 * PCIE reset so as to ensure that Host and target
6257 * states are in sync
6258 */
6259 wmibuf = wmi_buf_alloc(wma_handle->wmi_handle, len);
6260 if (wmibuf == NULL)
6261 return -ENOMEM;
6262
6263 cmd = (wmi_pdev_suspend_cmd_fixed_param *) wmi_buf_data(wmibuf);
6264 WMITLV_SET_HDR(&cmd->tlv_header,
6265 WMITLV_TAG_STRUC_wmi_pdev_suspend_cmd_fixed_param,
6266 WMITLV_GET_STRUCT_TLVLEN
6267 (wmi_pdev_suspend_cmd_fixed_param));
6268 if (disable_target_intr) {
6269 cmd->suspend_opt = WMI_PDEV_SUSPEND_AND_DISABLE_INTR;
6270 } else {
6271 cmd->suspend_opt = WMI_PDEV_SUSPEND;
6272 }
6273 cdf_event_reset(&wma_handle->target_suspend);
6274 ret = wmi_unified_cmd_send(wma_handle->wmi_handle, wmibuf, len,
6275 WMI_PDEV_SUSPEND_CMDID);
6276 if (ret < 0) {
6277 cdf_nbuf_free(wmibuf);
6278 return ret;
6279 }
6280
6281 wmi_set_target_suspend(wma_handle->wmi_handle, true);
6282
6283 if (cdf_wait_single_event(&wma_handle->target_suspend,
6284 WMA_TGT_SUSPEND_COMPLETE_TIMEOUT)
6285 != CDF_STATUS_SUCCESS) {
6286 WMA_LOGE("Failed to get ACK from firmware for pdev suspend");
6287 wmi_set_target_suspend(wma_handle->wmi_handle, false);
Yue Mae1a85f32015-10-20 18:12:45 -07006288#ifdef CONFIG_CNSS
Prashanth Bhatta9e143052015-12-04 11:56:47 -08006289 if (!cds_is_driver_recovering()) {
Yue Ma455aff62015-10-20 18:29:16 -07006290 if (pmac->sme.enableSelfRecovery) {
6291 cds_trigger_recovery();
6292 } else {
6293 CDF_BUG(0);
6294 }
Yue Mae1a85f32015-10-20 18:12:45 -07006295 } else {
Yue Ma455aff62015-10-20 18:29:16 -07006296 WMA_LOGE("%s: LOGP is in progress, ignore!", __func__);
Yue Mae1a85f32015-10-20 18:12:45 -07006297 }
6298#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006299 return -EFAULT;
6300 }
6301
6302 scn = cds_get_context(CDF_MODULE_ID_HIF);
6303
6304 if (scn == NULL) {
6305 WMA_LOGE("%s: Failed to get HIF context", __func__);
6306 CDF_ASSERT(0);
6307 return -EFAULT;
6308 }
6309
6310 htc_cancel_deferred_target_sleep(scn);
6311
6312 return 0;
6313}
6314
6315/**
6316 * wma_target_suspend_acknowledge() - update target susspend status
6317 * @context: wma context
6318 *
6319 * Return: none
6320 */
6321void wma_target_suspend_acknowledge(void *context)
6322{
6323 tp_wma_handle wma = cds_get_context(CDF_MODULE_ID_WMA);
6324 int wow_nack = *((int *)context);
6325
6326 if (NULL == wma) {
6327 WMA_LOGE("%s: wma is NULL", __func__);
6328 return;
6329 }
6330
6331 wma->wow_nack = wow_nack;
6332 cdf_event_set(&wma->target_suspend);
6333 if (wow_nack)
6334 cdf_wake_lock_timeout_acquire(&wma->wow_wake_lock,
6335 WMA_WAKE_LOCK_TIMEOUT,
6336 WIFI_POWER_EVENT_WAKELOCK_WOW);
6337}
6338
6339/**
6340 * wma_resume_target() - resume target
6341 * @handle: wma handle
6342 *
6343 * Return: 0 for success or error code
6344 */
6345int wma_resume_target(WMA_HANDLE handle)
6346{
6347 int ret;
6348 tp_wma_handle wma = (tp_wma_handle) handle;
6349 wmi_buf_t wmibuf;
6350 wmi_pdev_resume_cmd_fixed_param *cmd;
6351 CDF_STATUS cdf_status = CDF_STATUS_SUCCESS;
6352#ifdef CONFIG_CNSS
6353 tpAniSirGlobal pMac = cds_get_context(CDF_MODULE_ID_PE);
6354 if (NULL == pMac) {
6355 WMA_LOGE("%s: Unable to get PE context", __func__);
6356 return -EINVAL;
6357 }
6358#endif /* CONFIG_CNSS */
6359
6360 wmibuf = wmi_buf_alloc(wma->wmi_handle, sizeof(*cmd));
6361 if (wmibuf == NULL) {
6362 return -ENOMEM;
6363 }
6364 cmd = (wmi_pdev_resume_cmd_fixed_param *) wmi_buf_data(wmibuf);
6365 WMITLV_SET_HDR(&cmd->tlv_header,
6366 WMITLV_TAG_STRUC_wmi_pdev_resume_cmd_fixed_param,
6367 WMITLV_GET_STRUCT_TLVLEN
6368 (wmi_pdev_resume_cmd_fixed_param));
6369 cmd->reserved0 = 0;
6370 cdf_event_reset(&wma->wma_resume_event);
6371 ret = wmi_unified_cmd_send(wma->wmi_handle, wmibuf, sizeof(*cmd),
6372 WMI_PDEV_RESUME_CMDID);
6373 if (ret != EOK) {
6374 WMA_LOGE("Failed to send WMI_PDEV_RESUME_CMDID command");
6375 wmi_buf_free(wmibuf);
6376 }
6377
6378 cdf_status = cdf_wait_single_event(&(wma->wma_resume_event),
6379 WMA_RESUME_TIMEOUT);
6380 if (CDF_STATUS_SUCCESS != cdf_status) {
6381 WMA_LOGP("%s: Timeout waiting for resume event from FW",
6382 __func__);
6383 WMA_LOGP("%s: Pending commands %d credits %d", __func__,
6384 wmi_get_pending_cmds(wma->wmi_handle),
6385 wmi_get_host_credits(wma->wmi_handle));
Prashanth Bhatta9e143052015-12-04 11:56:47 -08006386 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006387#ifdef CONFIG_CNSS
6388 if (pMac->sme.enableSelfRecovery) {
6389 cds_trigger_recovery();
6390 } else {
6391 CDF_BUG(0);
6392 }
6393#else
6394 CDF_BUG(0);
6395#endif /* CONFIG_CNSS */
6396 } else {
6397 WMA_LOGE("%s: SSR in progress, ignore resume timeout",
6398 __func__);
6399 }
6400 } else {
6401 WMA_LOGD("Host wakeup received");
6402 }
6403
6404 if (CDF_STATUS_SUCCESS == cdf_status)
6405 wmi_set_target_suspend(wma->wmi_handle, false);
6406
6407 return ret;
6408}
6409
6410/**
6411 * wma_get_modeselect() - get modeSelect flag based on phy_capability
6412 * @wma: wma handle
6413 * @modeSelect: mode Select
6414 *
6415 * Return: none
6416 */
6417void wma_get_modeselect(tp_wma_handle wma, uint32_t *modeSelect)
6418{
6419
6420 switch (wma->phy_capability) {
6421 case WMI_11G_CAPABILITY:
6422 case WMI_11NG_CAPABILITY:
6423 *modeSelect &= ~(REGDMN_MODE_11A | REGDMN_MODE_TURBO |
6424 REGDMN_MODE_108A | REGDMN_MODE_11A_HALF_RATE |
6425 REGDMN_MODE_11A_QUARTER_RATE |
6426 REGDMN_MODE_11NA_HT20 |
6427 REGDMN_MODE_11NA_HT40PLUS |
6428 REGDMN_MODE_11NA_HT40MINUS |
6429 REGDMN_MODE_11AC_VHT20 |
6430 REGDMN_MODE_11AC_VHT40PLUS |
6431 REGDMN_MODE_11AC_VHT40MINUS |
6432 REGDMN_MODE_11AC_VHT80);
6433 break;
6434 case WMI_11A_CAPABILITY:
6435 case WMI_11NA_CAPABILITY:
6436 case WMI_11AC_CAPABILITY:
6437 *modeSelect &= ~(REGDMN_MODE_11B | REGDMN_MODE_11G |
6438 REGDMN_MODE_108G | REGDMN_MODE_11NG_HT20 |
6439 REGDMN_MODE_11NG_HT40PLUS |
6440 REGDMN_MODE_11NG_HT40MINUS |
6441 REGDMN_MODE_11AC_VHT20_2G |
6442 REGDMN_MODE_11AC_VHT40_2G |
6443 REGDMN_MODE_11AC_VHT80_2G);
6444 break;
6445 }
6446}
6447
6448
6449#ifdef FEATURE_WLAN_TDLS
6450/**
6451 * wma_tdls_event_handler() - handle TDLS event
6452 * @handle: wma handle
6453 * @event: event buffer
6454 * @len: buffer length
6455 *
6456 * Return: 0 for success or error code
6457 */
6458int wma_tdls_event_handler(void *handle, uint8_t *event, uint32_t len)
6459{
6460 tp_wma_handle wma = (tp_wma_handle) handle;
6461 WMI_TDLS_PEER_EVENTID_param_tlvs *param_buf = NULL;
6462 wmi_tdls_peer_event_fixed_param *peer_event = NULL;
6463 tSirTdlsEventnotify *tdls_event;
6464
6465 if (!event) {
6466 WMA_LOGE("%s: event param null", __func__);
6467 return -EINVAL;
6468 }
6469
6470 param_buf = (WMI_TDLS_PEER_EVENTID_param_tlvs *) event;
6471 if (!param_buf) {
6472 WMA_LOGE("%s: received null buf from target", __func__);
6473 return -EINVAL;
6474 }
6475
6476 peer_event = param_buf->fixed_param;
6477 if (!peer_event) {
6478 WMA_LOGE("%s: received null event data from target", __func__);
6479 return -EINVAL;
6480 }
6481
6482 tdls_event = (tSirTdlsEventnotify *)
6483 cdf_mem_malloc(sizeof(*tdls_event));
6484 if (!tdls_event) {
6485 WMA_LOGE("%s: failed to allocate memory for tdls_event",
6486 __func__);
6487 return -ENOMEM;
6488 }
6489
6490 tdls_event->sessionId = peer_event->vdev_id;
6491 WMI_MAC_ADDR_TO_CHAR_ARRAY(&peer_event->peer_macaddr,
Srinivas Girigowda4f593792015-11-19 15:33:42 -08006492 tdls_event->peermac.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006493
6494 switch (peer_event->peer_status) {
6495 case WMI_TDLS_SHOULD_DISCOVER:
6496 tdls_event->messageType = WMA_TDLS_SHOULD_DISCOVER_CMD;
6497 break;
6498 case WMI_TDLS_SHOULD_TEARDOWN:
6499 tdls_event->messageType = WMA_TDLS_SHOULD_TEARDOWN_CMD;
6500 break;
6501 case WMI_TDLS_PEER_DISCONNECTED:
6502 tdls_event->messageType = WMA_TDLS_PEER_DISCONNECTED_CMD;
6503 break;
6504 default:
6505 WMA_LOGE("%s: Discarding unknown tdls event(%d) from target",
6506 __func__, peer_event->peer_status);
6507 return -EINVAL;
6508 }
6509
6510 switch (peer_event->peer_reason) {
6511 case WMI_TDLS_TEARDOWN_REASON_TX:
6512 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_TX;
6513 break;
6514 case WMI_TDLS_TEARDOWN_REASON_RSSI:
6515 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_RSSI;
6516 break;
6517 case WMI_TDLS_TEARDOWN_REASON_SCAN:
6518 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_SCAN;
6519 break;
6520 case WMI_TDLS_DISCONNECTED_REASON_PEER_DELETE:
6521 tdls_event->peer_reason =
6522 eWNI_TDLS_DISCONNECTED_REASON_PEER_DELETE;
6523 break;
6524 case WMI_TDLS_TEARDOWN_REASON_PTR_TIMEOUT:
6525 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_PTR_TIMEOUT;
6526 break;
6527 case WMI_TDLS_TEARDOWN_REASON_BAD_PTR:
6528 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_BAD_PTR;
6529 break;
6530 case WMI_TDLS_TEARDOWN_REASON_NO_RESPONSE:
6531 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_NO_RESPONSE;
6532 break;
6533 default:
6534 WMA_LOGE("%s: unknown reason(%d) in tdls event(%d) from target",
6535 __func__, peer_event->peer_reason,
6536 peer_event->peer_status);
6537 return -EINVAL;
6538 }
6539
6540 WMA_LOGD("%s: sending msg to umac, messageType: 0x%x, "
6541 "for peer: %pM, reason: %d, smesessionId: %d",
Srinivas Girigowda4f593792015-11-19 15:33:42 -08006542 __func__, tdls_event->messageType, tdls_event->peermac.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006543 tdls_event->peer_reason, tdls_event->sessionId);
6544
6545 wma_send_msg(wma, tdls_event->messageType, (void *)tdls_event, 0);
6546 return 0;
6547}
6548
6549/**
6550 * wma_set_tdls_offchan_mode() - set tdls off channel mode
6551 * @handle: wma handle
6552 * @chan_switch_params: Pointer to tdls channel switch parameter structure
6553 *
6554 * This function sets tdls off channel mode
6555 *
6556 * Return: 0 on success; Negative errno otherwise
6557 */
6558int wma_set_tdls_offchan_mode(WMA_HANDLE handle,
6559 tdls_chan_switch_params *chan_switch_params)
6560{
6561 tp_wma_handle wma_handle = (tp_wma_handle) handle;
6562 wmi_tdls_set_offchan_mode_cmd_fixed_param *cmd;
6563 wmi_buf_t wmi_buf;
6564 u_int16_t len = sizeof(wmi_tdls_set_offchan_mode_cmd_fixed_param);
6565 int ret = 0;
6566
6567 if (!wma_handle || !wma_handle->wmi_handle) {
6568 WMA_LOGE(FL(
6569 "WMA is closed, can not issue tdls off channel cmd"
6570 ));
6571 ret = -EINVAL;
6572 goto end;
6573 }
6574 wmi_buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
6575 if (!wmi_buf) {
6576 WMA_LOGE(FL("wmi_buf_alloc failed"));
6577 ret = -ENOMEM;
6578 goto end;
6579 }
6580 cmd = (wmi_tdls_set_offchan_mode_cmd_fixed_param *)
6581 wmi_buf_data(wmi_buf);
6582 WMITLV_SET_HDR(&cmd->tlv_header,
6583 WMITLV_TAG_STRUC_wmi_tdls_set_offchan_mode_cmd_fixed_param,
6584 WMITLV_GET_STRUCT_TLVLEN(
6585 wmi_tdls_set_offchan_mode_cmd_fixed_param));
6586
6587 WMI_CHAR_ARRAY_TO_MAC_ADDR(chan_switch_params->peer_mac_addr,
6588 &cmd->peer_macaddr);
6589 cmd->vdev_id = chan_switch_params->vdev_id;
6590 cmd->offchan_mode = chan_switch_params->tdls_sw_mode;
6591 cmd->is_peer_responder = chan_switch_params->is_responder;
6592 cmd->offchan_num = chan_switch_params->tdls_off_ch;
6593 cmd->offchan_bw_bitmap = chan_switch_params->tdls_off_ch_bw_offset;
6594 cmd->offchan_oper_class = chan_switch_params->oper_class;
6595
6596 WMA_LOGD(FL("Peer MAC Addr mac_addr31to0: 0x%x, mac_addr47to32: 0x%x"),
6597 cmd->peer_macaddr.mac_addr31to0,
6598 cmd->peer_macaddr.mac_addr47to32);
6599
6600 WMA_LOGD(FL(
6601 "vdev_id: %d, off channel mode: %d, off channel Num: %d, off channel offset: 0x%x, is_peer_responder: %d, operating class: %d"
6602 ),
6603 cmd->vdev_id,
6604 cmd->offchan_mode,
6605 cmd->offchan_num,
6606 cmd->offchan_bw_bitmap,
6607 cmd->is_peer_responder,
6608 cmd->offchan_oper_class);
6609
6610 if (wmi_unified_cmd_send(wma_handle->wmi_handle, wmi_buf, len,
6611 WMI_TDLS_SET_OFFCHAN_MODE_CMDID)) {
6612 WMA_LOGP(FL("failed to send tdls off chan command"));
6613 cdf_nbuf_free(wmi_buf);
6614 ret = -EIO;
6615 }
6616
6617end:
6618 if (chan_switch_params)
6619 cdf_mem_free(chan_switch_params);
6620 return ret;
6621}
6622
6623/**
6624 * wma_update_fw_tdls_state() - send enable/disable tdls for a vdev
6625 * @wma: wma handle
6626 * @pwmaTdlsparams: TDLS params
6627 *
6628 * Return: 0 for sucess or error code
6629 */
6630int wma_update_fw_tdls_state(WMA_HANDLE handle, void *pwmaTdlsparams)
6631{
6632 tp_wma_handle wma_handle = (tp_wma_handle) handle;
6633 wmi_tdls_set_state_cmd_fixed_param *cmd;
6634 wmi_buf_t wmi_buf;
6635 t_wma_tdls_mode tdls_mode;
6636 t_wma_tdls_params *wma_tdls = (t_wma_tdls_params *) pwmaTdlsparams;
6637 uint16_t len = sizeof(wmi_tdls_set_state_cmd_fixed_param);
6638 int ret = 0;
6639
6640 if (!wma_handle || !wma_handle->wmi_handle) {
6641 WMA_LOGE("%s: WMA is closed, can not issue fw tdls state cmd",
6642 __func__);
6643 ret = -EINVAL;
6644 goto end_fw_tdls_state;
6645 }
6646
6647 wmi_buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
6648 if (!wmi_buf) {
6649 WMA_LOGE("%s: wmai_buf_alloc failed", __func__);
6650 ret = ENOMEM;
6651 goto end_fw_tdls_state;
6652 }
6653 tdls_mode = wma_tdls->tdls_state;
6654 cmd = (wmi_tdls_set_state_cmd_fixed_param *) wmi_buf_data(wmi_buf);
6655 WMITLV_SET_HDR(&cmd->tlv_header,
6656 WMITLV_TAG_STRUC_wmi_tdls_set_state_cmd_fixed_param,
6657 WMITLV_GET_STRUCT_TLVLEN
6658 (wmi_tdls_set_state_cmd_fixed_param));
6659 cmd->vdev_id = wma_tdls->vdev_id;
6660
6661 if (WMA_TDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY == tdls_mode) {
6662 cmd->state = WMI_TDLS_ENABLE_PASSIVE;
6663 } else if (WMA_TDLS_SUPPORT_ENABLED == tdls_mode) {
6664 cmd->state = WMI_TDLS_ENABLE_ACTIVE;
Kabilan Kannan421714b2015-11-23 04:44:59 -08006665 } else if (WMA_TDLS_SUPPORT_ACTIVE_EXTERNAL_CONTROL == tdls_mode) {
6666 cmd->state = WMI_TDLS_ENABLE_ACTIVE_EXTERNAL_CONTROL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006667 } else {
6668 cmd->state = WMI_TDLS_DISABLE;
6669 }
6670
6671 cmd->notification_interval_ms = wma_tdls->notification_interval_ms;
6672 cmd->tx_discovery_threshold = wma_tdls->tx_discovery_threshold;
6673 cmd->tx_teardown_threshold = wma_tdls->tx_teardown_threshold;
6674 cmd->rssi_teardown_threshold = wma_tdls->rssi_teardown_threshold;
6675 cmd->rssi_delta = wma_tdls->rssi_delta;
6676 cmd->tdls_options = wma_tdls->tdls_options;
6677 cmd->tdls_peer_traffic_ind_window = wma_tdls->peer_traffic_ind_window;
6678 cmd->tdls_peer_traffic_response_timeout_ms =
6679 wma_tdls->peer_traffic_response_timeout;
6680 cmd->tdls_puapsd_mask = wma_tdls->puapsd_mask;
6681 cmd->tdls_puapsd_inactivity_time_ms = wma_tdls->puapsd_inactivity_time;
6682 cmd->tdls_puapsd_rx_frame_threshold =
6683 wma_tdls->puapsd_rx_frame_threshold;
Kabilan Kannanca670be2015-11-23 01:56:12 -08006684 cmd->teardown_notification_ms =
6685 wma_tdls->teardown_notification_ms;
Kabilan Kannan421714b2015-11-23 04:44:59 -08006686 cmd->tdls_peer_kickout_threshold =
6687 wma_tdls->tdls_peer_kickout_threshold;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006688
6689 WMA_LOGD("%s: tdls_mode: %d, state: %d, "
6690 "notification_interval_ms: %d, "
6691 "tx_discovery_threshold: %d, "
6692 "tx_teardown_threshold: %d, "
6693 "rssi_teardown_threshold: %d, "
6694 "rssi_delta: %d, "
6695 "tdls_options: 0x%x, "
6696 "tdls_peer_traffic_ind_window: %d, "
6697 "tdls_peer_traffic_response_timeout: %d, "
6698 "tdls_puapsd_mask: 0x%x, "
6699 "tdls_puapsd_inactivity_time: %d, "
Kabilan Kannanca670be2015-11-23 01:56:12 -08006700 "tdls_puapsd_rx_frame_threshold: %d, "
Kabilan Kannan421714b2015-11-23 04:44:59 -08006701 "teardown_notification_ms: %d, "
6702 "tdls_peer_kickout_threshold: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006703 __func__, tdls_mode, cmd->state,
6704 cmd->notification_interval_ms,
6705 cmd->tx_discovery_threshold,
6706 cmd->tx_teardown_threshold,
6707 cmd->rssi_teardown_threshold,
6708 cmd->rssi_delta,
6709 cmd->tdls_options,
6710 cmd->tdls_peer_traffic_ind_window,
6711 cmd->tdls_peer_traffic_response_timeout_ms,
6712 cmd->tdls_puapsd_mask,
6713 cmd->tdls_puapsd_inactivity_time_ms,
Kabilan Kannanca670be2015-11-23 01:56:12 -08006714 cmd->tdls_puapsd_rx_frame_threshold,
Kabilan Kannan421714b2015-11-23 04:44:59 -08006715 cmd->teardown_notification_ms,
6716 cmd->tdls_peer_kickout_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006717
6718 if (wmi_unified_cmd_send(wma_handle->wmi_handle, wmi_buf, len,
6719 WMI_TDLS_SET_STATE_CMDID)) {
6720 WMA_LOGP("%s: failed to send tdls set state command", __func__);
6721 cdf_nbuf_free(wmi_buf);
6722 ret = -EIO;
6723 goto end_fw_tdls_state;
6724 }
6725 WMA_LOGD("%s: vdev_id %d", __func__, wma_tdls->vdev_id);
6726
6727end_fw_tdls_state:
6728 if (pwmaTdlsparams)
6729 cdf_mem_free(pwmaTdlsparams);
6730 return ret;
6731}
6732
6733/**
6734 * wma_update_tdls_peer_state() - update TDLS peer state
6735 * @handle: wma handle
6736 * @peerStateParams: TDLS peer state params
6737 *
6738 * Return: 0 for success or error code
6739 */
6740int wma_update_tdls_peer_state(WMA_HANDLE handle,
6741 tTdlsPeerStateParams *peerStateParams)
6742{
6743 tp_wma_handle wma_handle = (tp_wma_handle) handle;
6744 wmi_tdls_peer_update_cmd_fixed_param *cmd;
6745 wmi_tdls_peer_capabilities *peer_cap;
6746 wmi_channel *chan_info;
6747 wmi_buf_t wmi_buf;
6748 uint8_t *buf_ptr;
6749 uint32_t i;
6750 ol_txrx_pdev_handle pdev;
6751 uint8_t peer_id;
6752 struct ol_txrx_peer_t *peer;
6753 int32_t len = sizeof(wmi_tdls_peer_update_cmd_fixed_param) +
6754 sizeof(wmi_tdls_peer_capabilities);
6755 int ret = 0;
6756
6757 if (!wma_handle || !wma_handle->wmi_handle) {
6758 WMA_LOGE("%s: WMA is closed, can not issue cmd", __func__);
6759 ret = -EINVAL;
6760 goto end_tdls_peer_state;
6761 }
6762
6763 /* peer capability info is valid only when peer state is connected */
6764 if (WMA_TDLS_PEER_STATE_CONNECTED != peerStateParams->peerState) {
6765 cdf_mem_zero(&peerStateParams->peerCap,
6766 sizeof(tTdlsPeerCapParams));
6767 }
6768
6769 len += WMI_TLV_HDR_SIZE +
6770 sizeof(wmi_channel) * peerStateParams->peerCap.peerChanLen;
6771
6772 wmi_buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
6773 if (!wmi_buf) {
6774 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
6775 ret = ENOMEM;
6776 goto end_tdls_peer_state;
6777 }
6778
6779 buf_ptr = (uint8_t *) wmi_buf_data(wmi_buf);
6780 cmd = (wmi_tdls_peer_update_cmd_fixed_param *) buf_ptr;
6781 WMITLV_SET_HDR(&cmd->tlv_header,
6782 WMITLV_TAG_STRUC_wmi_tdls_peer_update_cmd_fixed_param,
6783 WMITLV_GET_STRUCT_TLVLEN
6784 (wmi_tdls_peer_update_cmd_fixed_param));
6785
6786 cmd->vdev_id = peerStateParams->vdevId;
6787 WMI_CHAR_ARRAY_TO_MAC_ADDR(peerStateParams->peerMacAddr,
6788 &cmd->peer_macaddr);
6789
6790 switch (peerStateParams->peerState) {
6791 case WMA_TDLS_PEER_STATE_PEERING:
6792 cmd->peer_state = WMI_TDLS_PEER_STATE_PEERING;
6793 break;
6794 case WMA_TDLS_PEER_STATE_CONNECTED:
6795 cmd->peer_state = WMI_TDLS_PEER_STATE_CONNECTED;
6796 break;
6797 case WMA_TDLS_PEER_STATE_TEARDOWN:
6798 cmd->peer_state = WMI_TDLS_PEER_STATE_TEARDOWN;
6799 break;
Kabilan Kannan421714b2015-11-23 04:44:59 -08006800 case WMA_TDLS_PEER_ADD_MAC_ADDR:
6801 cmd->peer_state = WMI_TDLS_PEER_ADD_MAC_ADDR;
6802 break;
6803 case WMA_TDLS_PEER_REMOVE_MAC_ADDR:
6804 cmd->peer_state = WMI_TDLS_PEER_REMOVE_MAC_ADDR;
6805 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006806 }
6807
6808 WMA_LOGD("%s: vdev_id: %d, peerStateParams->peerMacAddr: %pM, "
6809 "peer_macaddr.mac_addr31to0: 0x%x, "
6810 "peer_macaddr.mac_addr47to32: 0x%x, peer_state: %d",
6811 __func__, cmd->vdev_id, peerStateParams->peerMacAddr,
6812 cmd->peer_macaddr.mac_addr31to0,
6813 cmd->peer_macaddr.mac_addr47to32, cmd->peer_state);
6814
6815 buf_ptr += sizeof(wmi_tdls_peer_update_cmd_fixed_param);
6816 peer_cap = (wmi_tdls_peer_capabilities *) buf_ptr;
6817 WMITLV_SET_HDR(&peer_cap->tlv_header,
6818 WMITLV_TAG_STRUC_wmi_tdls_peer_capabilities,
6819 WMITLV_GET_STRUCT_TLVLEN(wmi_tdls_peer_capabilities));
6820
6821 if ((peerStateParams->peerCap.peerUapsdQueue & 0x08) >> 3)
6822 WMI_SET_TDLS_PEER_VO_UAPSD(peer_cap);
6823 if ((peerStateParams->peerCap.peerUapsdQueue & 0x04) >> 2)
6824 WMI_SET_TDLS_PEER_VI_UAPSD(peer_cap);
6825 if ((peerStateParams->peerCap.peerUapsdQueue & 0x02) >> 1)
6826 WMI_SET_TDLS_PEER_BK_UAPSD(peer_cap);
6827 if (peerStateParams->peerCap.peerUapsdQueue & 0x01)
6828 WMI_SET_TDLS_PEER_BE_UAPSD(peer_cap);
6829
6830 /* Ack and More Data Ack are sent as 0, so no need to set
6831 * but fill SP
6832 */
6833 WMI_SET_TDLS_PEER_SP_UAPSD(peer_cap,
6834 peerStateParams->peerCap.peerMaxSp);
6835
6836 peer_cap->buff_sta_support =
6837 peerStateParams->peerCap.peerBuffStaSupport;
6838 peer_cap->off_chan_support =
6839 peerStateParams->peerCap.peerOffChanSupport;
6840 peer_cap->peer_curr_operclass =
6841 peerStateParams->peerCap.peerCurrOperClass;
6842 /* self curr operclass is not being used and so pass op class for
6843 * preferred off chan in it.
6844 */
6845 peer_cap->self_curr_operclass =
6846 peerStateParams->peerCap.opClassForPrefOffChan;
6847 peer_cap->peer_chan_len = peerStateParams->peerCap.peerChanLen;
6848 peer_cap->peer_operclass_len =
6849 peerStateParams->peerCap.peerOperClassLen;
6850
6851 WMA_LOGD("%s: peer_operclass_len: %d",
6852 __func__, peer_cap->peer_operclass_len);
6853 for (i = 0; i < WMI_TDLS_MAX_SUPP_OPER_CLASSES; i++) {
6854 peer_cap->peer_operclass[i] =
6855 peerStateParams->peerCap.peerOperClass[i];
6856 WMA_LOGD("%s: peer_operclass[%d]: %d",
6857 __func__, i, peer_cap->peer_operclass[i]);
6858 }
6859
6860 peer_cap->is_peer_responder = peerStateParams->peerCap.isPeerResponder;
6861 peer_cap->pref_offchan_num = peerStateParams->peerCap.prefOffChanNum;
6862 peer_cap->pref_offchan_bw =
6863 peerStateParams->peerCap.prefOffChanBandwidth;
6864
6865 WMA_LOGD
6866 ("%s: peer_qos: 0x%x, buff_sta_support: %d, off_chan_support: %d, peer_curr_operclass: %d, self_curr_operclass: %d, peer_chan_len: %d, peer_operclass_len: %d, is_peer_responder: %d, pref_offchan_num: %d, pref_offchan_bw: %d",
6867 __func__, peer_cap->peer_qos, peer_cap->buff_sta_support,
6868 peer_cap->off_chan_support, peer_cap->peer_curr_operclass,
6869 peer_cap->self_curr_operclass, peer_cap->peer_chan_len,
6870 peer_cap->peer_operclass_len, peer_cap->is_peer_responder,
6871 peer_cap->pref_offchan_num, peer_cap->pref_offchan_bw);
6872
6873 /* next fill variable size array of peer chan info */
6874 buf_ptr += sizeof(wmi_tdls_peer_capabilities);
6875 WMITLV_SET_HDR(buf_ptr,
6876 WMITLV_TAG_ARRAY_STRUC,
6877 sizeof(wmi_channel) *
6878 peerStateParams->peerCap.peerChanLen);
6879 chan_info = (wmi_channel *) (buf_ptr + WMI_TLV_HDR_SIZE);
6880
6881 for (i = 0; i < peerStateParams->peerCap.peerChanLen; ++i) {
6882 WMITLV_SET_HDR(&chan_info->tlv_header,
6883 WMITLV_TAG_STRUC_wmi_channel,
6884 WMITLV_GET_STRUCT_TLVLEN(wmi_channel));
6885 chan_info->mhz =
6886 cds_chan_to_freq(peerStateParams->peerCap.peerChan[i].
6887 chanId);
6888 chan_info->band_center_freq1 = chan_info->mhz;
6889 chan_info->band_center_freq2 = 0;
6890
6891 WMA_LOGD("%s: chan[%d] = %u", __func__, i, chan_info->mhz);
6892
6893 if (peerStateParams->peerCap.peerChan[i].dfsSet) {
6894 WMI_SET_CHANNEL_FLAG(chan_info, WMI_CHAN_FLAG_PASSIVE);
6895 WMA_LOGI("chan[%d] DFS[%d]\n",
6896 peerStateParams->peerCap.peerChan[i].chanId,
6897 peerStateParams->peerCap.peerChan[i].dfsSet);
6898 }
6899
6900 if (chan_info->mhz < WMA_2_4_GHZ_MAX_FREQ) {
6901 WMI_SET_CHANNEL_MODE(chan_info, MODE_11G);
6902 } else {
6903 WMI_SET_CHANNEL_MODE(chan_info, MODE_11A);
6904 }
6905
6906 WMI_SET_CHANNEL_MAX_TX_POWER(chan_info,
6907 peerStateParams->peerCap.
6908 peerChan[i].pwr);
6909
6910 WMI_SET_CHANNEL_REG_POWER(chan_info,
6911 peerStateParams->peerCap.peerChan[i].
6912 pwr);
6913 WMA_LOGD("Channel TX power[%d] = %u: %d", i, chan_info->mhz,
6914 peerStateParams->peerCap.peerChan[i].pwr);
6915
6916 chan_info++;
6917 }
6918
6919 if (wmi_unified_cmd_send(wma_handle->wmi_handle, wmi_buf, len,
6920 WMI_TDLS_PEER_UPDATE_CMDID)) {
6921 WMA_LOGE("%s: failed to send tdls peer update state command",
6922 __func__);
6923 cdf_nbuf_free(wmi_buf);
6924 ret = -EIO;
6925 goto end_tdls_peer_state;
6926 }
6927
6928 /* in case of teardown, remove peer from fw */
6929 if (WMA_TDLS_PEER_STATE_TEARDOWN == peerStateParams->peerState) {
6930 pdev = cds_get_context(CDF_MODULE_ID_TXRX);
6931 if (!pdev) {
6932 WMA_LOGE("%s: Failed to find pdev", __func__);
6933 ret = -EIO;
6934 goto end_tdls_peer_state;
6935 }
6936
6937 peer = ol_txrx_find_peer_by_addr(pdev,
6938 peerStateParams->peerMacAddr,
6939 &peer_id);
6940 if (!peer) {
6941 WMA_LOGE("%s: Failed to get peer handle using peer mac %pM",
6942 __func__, peerStateParams->peerMacAddr);
6943 ret = -EIO;
6944 goto end_tdls_peer_state;
6945 }
6946
6947 WMA_LOGD("%s: calling wma_remove_peer for peer " MAC_ADDRESS_STR
6948 " vdevId: %d", __func__,
6949 MAC_ADDR_ARRAY(peer->mac_addr.raw),
6950 peerStateParams->vdevId);
6951 wma_remove_peer(wma_handle, peer->mac_addr.raw,
6952 peerStateParams->vdevId, peer, false);
6953 }
6954
6955end_tdls_peer_state:
6956 if (peerStateParams)
6957 cdf_mem_free(peerStateParams);
6958 return ret;
6959}
6960#endif /* FEATURE_WLAN_TDLS */
6961
6962
6963/**
6964 * wma_dfs_attach() - Attach DFS methods to the umac state.
6965 * @dfs_ic: ieee80211com ptr
6966 *
6967 * Return: Return ieee80211com ptr with updated info
6968 */
6969struct ieee80211com *wma_dfs_attach(struct ieee80211com *dfs_ic)
6970{
6971 /*Allocate memory for dfs_ic before passing it up to dfs_attach() */
6972 dfs_ic = (struct ieee80211com *)
6973 os_malloc(NULL, sizeof(struct ieee80211com), GFP_ATOMIC);
6974 if (dfs_ic == NULL) {
6975 WMA_LOGE("%s:Allocation of dfs_ic failed %zu",
6976 __func__, sizeof(struct ieee80211com));
6977 return NULL;
6978 }
6979 OS_MEMZERO(dfs_ic, sizeof(struct ieee80211com));
6980 /* DFS pattern matching hooks */
6981 dfs_ic->ic_dfs_attach = ol_if_dfs_attach;
6982 dfs_ic->ic_dfs_disable = ol_if_dfs_disable;
6983 dfs_ic->ic_find_channel = ieee80211_find_channel;
6984 dfs_ic->ic_dfs_enable = ol_if_dfs_enable;
6985 dfs_ic->ic_ieee2mhz = ieee80211_ieee2mhz;
6986
6987 /* Hardware facing hooks */
6988 dfs_ic->ic_get_ext_busy = ol_if_dfs_get_ext_busy;
6989 dfs_ic->ic_get_mib_cycle_counts_pct =
6990 ol_if_dfs_get_mib_cycle_counts_pct;
6991 dfs_ic->ic_get_TSF64 = ol_if_get_tsf64;
6992
6993 /* NOL related hooks */
6994 dfs_ic->ic_dfs_usenol = ol_if_dfs_usenol;
6995 /*
6996 * Hooks from wma/dfs/ back
6997 * into the PE/SME
6998 * and shared DFS code
6999 */
7000 dfs_ic->ic_dfs_notify_radar = ieee80211_mark_dfs;
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05307001 cdf_spinlock_init(&dfs_ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007002 /* Initializes DFS Data Structures and queues */
7003 dfs_attach(dfs_ic);
7004
7005 return dfs_ic;
7006}
7007
7008/**
7009 * wma_dfs_detach() - Detach DFS methods
7010 * @dfs_ic: ieee80211com ptr
7011 *
7012 * Return: none
7013 */
7014void wma_dfs_detach(struct ieee80211com *dfs_ic)
7015{
7016 dfs_detach(dfs_ic);
7017
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05307018 cdf_spinlock_destroy(&dfs_ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007019 if (NULL != dfs_ic->ic_curchan) {
7020 OS_FREE(dfs_ic->ic_curchan);
7021 dfs_ic->ic_curchan = NULL;
7022 }
7023
7024 OS_FREE(dfs_ic);
7025}
7026
7027/**
7028 * wma_dfs_configure() - configure dfs
7029 * @ic: ieee80211com ptr
7030 *
7031 * Configures Radar Filters during
7032 * vdev start/channel change/regulatory domain
7033 * change.This Configuration enables to program
7034 * the DFS pattern matching module.
7035 *
7036 * Return: none
7037 */
7038void wma_dfs_configure(struct ieee80211com *ic)
7039{
7040 struct ath_dfs_radar_tab_info rinfo;
7041 int dfsdomain;
7042 int radar_enabled_status = 0;
7043 if (ic == NULL) {
7044 WMA_LOGE("%s: DFS ic is Invalid", __func__);
7045 return;
7046 }
7047
7048 dfsdomain = ic->current_dfs_regdomain;
7049
7050 /* Fetch current radar patterns from the lmac */
7051 OS_MEMZERO(&rinfo, sizeof(rinfo));
7052
7053 /*
7054 * Look up the current DFS
7055 * regulatory domain and decide
7056 * which radar pulses to use.
7057 */
7058 switch (dfsdomain) {
7059 case DFS_FCC_DOMAIN:
7060 WMA_LOGI("%s: DFS-FCC domain", __func__);
7061 rinfo.dfsdomain = DFS_FCC_DOMAIN;
7062 rinfo.dfs_radars = dfs_fcc_radars;
7063 rinfo.numradars = CDF_ARRAY_SIZE(dfs_fcc_radars);
7064 rinfo.b5pulses = dfs_fcc_bin5pulses;
7065 rinfo.numb5radars = CDF_ARRAY_SIZE(dfs_fcc_bin5pulses);
7066 break;
7067 case DFS_ETSI_DOMAIN:
7068 WMA_LOGI("%s: DFS-ETSI domain", __func__);
7069 rinfo.dfsdomain = DFS_ETSI_DOMAIN;
7070 rinfo.dfs_radars = dfs_etsi_radars;
7071 rinfo.numradars = CDF_ARRAY_SIZE(dfs_etsi_radars);
7072 rinfo.b5pulses = NULL;
7073 rinfo.numb5radars = 0;
7074 break;
7075 case DFS_MKK4_DOMAIN:
7076 WMA_LOGI("%s: DFS-MKK4 domain", __func__);
7077 rinfo.dfsdomain = DFS_MKK4_DOMAIN;
7078 rinfo.dfs_radars = dfs_mkk4_radars;
7079 rinfo.numradars = CDF_ARRAY_SIZE(dfs_mkk4_radars);
7080 rinfo.b5pulses = dfs_jpn_bin5pulses;
7081 rinfo.numb5radars = CDF_ARRAY_SIZE(dfs_jpn_bin5pulses);
7082 break;
7083 default:
7084 WMA_LOGI("%s: DFS-UNINT domain", __func__);
7085 rinfo.dfsdomain = DFS_UNINIT_DOMAIN;
7086 rinfo.dfs_radars = NULL;
7087 rinfo.numradars = 0;
7088 rinfo.b5pulses = NULL;
7089 rinfo.numb5radars = 0;
7090 break;
7091 }
7092
7093 rinfo.dfs_pri_multiplier = ic->dfs_pri_multiplier;
7094
7095 /*
7096 * Set the regulatory domain,
7097 * radar pulse table and enable
7098 * radar events if required.
7099 * dfs_radar_enable() returns
7100 * 0 on success and non-zero
7101 * failure.
7102 */
7103 radar_enabled_status = dfs_radar_enable(ic, &rinfo);
7104 if (radar_enabled_status != DFS_STATUS_SUCCESS) {
7105 WMA_LOGE("%s[%d]: DFS- Radar Detection Enabling Failed",
7106 __func__, __LINE__);
7107 }
7108}
7109
7110/**
7111 * wma_dfs_configure_channel() - configure DFS channel
7112 * @dfs_ic: ieee80211com ptr
7113 * @chan: wmi channel
7114 * @chanmode: channel mode
7115 * @ req: vdev start request
7116 *
7117 * Set the Channel parameters in to DFS module
7118 * Also,configure the DFS radar filters for
7119 * matching the DFS phyerrors.
7120 *
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05307121 * Return: dfs_ieee80211_channel / NULL for error
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007122 */
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05307123struct dfs_ieee80211_channel *wma_dfs_configure_channel(
7124 struct ieee80211com *dfs_ic,
7125 wmi_channel *chan,
7126 WLAN_PHY_MODE chanmode,
7127 struct wma_vdev_start_req
7128 *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007129{
7130 if (dfs_ic == NULL) {
7131 WMA_LOGE("%s: DFS ic is Invalid", __func__);
7132 return NULL;
7133 }
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05307134
7135 if (!dfs_ic->ic_curchan) {
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05307136 dfs_ic->ic_curchan = (struct dfs_ieee80211_channel *)os_malloc(
7137 NULL,
7138 sizeof(struct dfs_ieee80211_channel),
7139 GFP_ATOMIC);
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05307140 if (dfs_ic->ic_curchan == NULL) {
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05307141 WMA_LOGE(
7142 "%s: allocation of dfs_ic->ic_curchan failed %zu",
7143 __func__, sizeof(struct dfs_ieee80211_channel));
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05307144 return NULL;
7145 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007146 }
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05307147
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05307148 OS_MEMZERO(dfs_ic->ic_curchan, sizeof(struct dfs_ieee80211_channel));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007149
7150 dfs_ic->ic_curchan->ic_ieee = req->chan;
7151 dfs_ic->ic_curchan->ic_freq = chan->mhz;
7152 dfs_ic->ic_curchan->ic_vhtop_ch_freq_seg1 = chan->band_center_freq1;
7153 dfs_ic->ic_curchan->ic_vhtop_ch_freq_seg2 = chan->band_center_freq2;
7154 dfs_ic->ic_curchan->ic_pri_freq_center_freq_mhz_separation =
7155 dfs_ic->ic_curchan->ic_freq -
7156 dfs_ic->ic_curchan->ic_vhtop_ch_freq_seg1;
7157
7158 if ((dfs_ic->ic_curchan->ic_ieee >= WMA_11A_CHANNEL_BEGIN) &&
7159 (dfs_ic->ic_curchan->ic_ieee <= WMA_11A_CHANNEL_END)) {
7160 dfs_ic->ic_curchan->ic_flags |= IEEE80211_CHAN_5GHZ;
7161 }
7162 if (CH_WIDTH_80MHZ == req->chan_width) {
7163 dfs_ic->ic_curchan->ic_flags |= IEEE80211_CHAN_VHT80;
7164 }
7165 if (CH_WIDTH_40MHZ == req->chan_width) {
7166 if (req->chan < req->ch_center_freq_seg0)
7167 dfs_ic->ic_curchan->ic_flags |= (req->vht_capable ?
7168 IEEE80211_CHAN_VHT40PLUS :
7169 IEEE80211_CHAN_HT40PLUS);
7170 else
7171 dfs_ic->ic_curchan->ic_flags |= (req->vht_capable ?
7172 IEEE80211_CHAN_VHT40MINUS :
7173 IEEE80211_CHAN_HT40MINUS);
7174 } else if (CH_WIDTH_20MHZ == req->chan_width) {
7175 dfs_ic->ic_curchan->ic_flags |=
7176 (req->vht_capable ? IEEE80211_CHAN_VHT20 :
7177 IEEE80211_CHAN_HT20);
7178 }
7179 dfs_ic->ic_curchan->ic_flagext |= IEEE80211_CHAN_DFS;
7180
7181 if (req->oper_mode == BSS_OPERATIONAL_MODE_AP) {
7182 dfs_ic->ic_opmode = IEEE80211_M_HOSTAP;
7183 dfs_ic->vdev_id = req->vdev_id;
7184 }
7185
7186 dfs_ic->dfs_pri_multiplier = req->dfs_pri_multiplier;
7187
7188 /*
7189 * Configuring the DFS with current channel and the radar filters
7190 */
7191 wma_dfs_configure(dfs_ic);
7192 WMA_LOGI("%s: DFS- CHANNEL CONFIGURED", __func__);
7193 return dfs_ic->ic_curchan;
7194}
7195
7196
7197/**
7198 * wma_set_dfs_region() - set DFS region
7199 * @wma: wma handle
7200 *
7201 * Configure the DFS region for DFS radar filter initialization
7202 *
7203 * Return: none
7204 */
7205void wma_set_dfs_region(tp_wma_handle wma, uint8_t dfs_region)
7206{
7207 /* dfs information is passed */
7208 if (dfs_region > DFS_MKK4_DOMAIN || dfs_region == DFS_UNINIT_DOMAIN)
7209 /* assign DFS_FCC_DOMAIN as default domain*/
7210 wma->dfs_ic->current_dfs_regdomain = DFS_FCC_DOMAIN;
7211 else
7212 wma->dfs_ic->current_dfs_regdomain = dfs_region;
7213
7214 WMA_LOGI("%s: DFS Region Domain: %d", __func__,
7215 wma->dfs_ic->current_dfs_regdomain);
7216}
7217
7218/**
7219 * wma_get_channels() - prepare dfs radar channel list
7220 * @ichan: channel
7221 * @chan_list: return channel list
7222 *
7223 * Return: return number of channels
7224 */
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05307225int wma_get_channels(struct dfs_ieee80211_channel *ichan,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007226 struct wma_dfs_radar_channel_list *chan_list)
7227{
7228 uint8_t center_chan = cds_freq_to_chan(ichan->ic_vhtop_ch_freq_seg1);
7229
7230 chan_list->nchannels = 0;
7231
7232 if (IEEE80211_IS_CHAN_11AC_VHT80(ichan)) {
7233 chan_list->nchannels = 4;
7234 chan_list->channels[0] = center_chan - 6;
7235 chan_list->channels[1] = center_chan - 2;
7236 chan_list->channels[2] = center_chan + 2;
7237 chan_list->channels[3] = center_chan + 6;
7238 } else if (IEEE80211_IS_CHAN_11N_HT40(ichan) ||
7239 IEEE80211_IS_CHAN_11AC_VHT40(ichan)) {
7240 chan_list->nchannels = 2;
7241 chan_list->channels[0] = center_chan - 2;
7242 chan_list->channels[1] = center_chan + 2;
7243 } else {
7244 chan_list->nchannels = 1;
7245 chan_list->channels[0] = center_chan;
7246 }
7247
7248 return chan_list->nchannels;
7249}
7250
7251
7252/**
7253 * wma_dfs_indicate_radar() - Indicate Radar to SAP/HDD
7254 * @ic: ieee80211com ptr
7255 * @ichan: ieee 80211 channel
7256 *
7257 * Return: 0 for success or error code
7258 */
7259int wma_dfs_indicate_radar(struct ieee80211com *ic,
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05307260 struct dfs_ieee80211_channel *ichan)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007261{
7262 tp_wma_handle wma;
7263 void *hdd_ctx;
7264 struct wma_dfs_radar_indication *radar_event;
7265 struct wma_dfs_radar_ind wma_radar_event;
7266 tpAniSirGlobal pmac = NULL;
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05307267 bool indication_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007268
7269 wma = cds_get_context(CDF_MODULE_ID_WMA);
7270 if (wma == NULL) {
7271 WMA_LOGE("%s: DFS- Invalid wma", __func__);
7272 return -ENOENT;
7273 }
7274
7275 hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD);
7276 pmac = (tpAniSirGlobal)
7277 cds_get_context(CDF_MODULE_ID_PE);
7278
7279 if (!pmac) {
7280 WMA_LOGE("%s: Invalid MAC handle", __func__);
7281 return -ENOENT;
7282 }
7283
7284 if (wma->dfs_ic != ic) {
7285 WMA_LOGE("%s:DFS- Invalid WMA handle", __func__);
7286 return -ENOENT;
7287 }
7288 radar_event = (struct wma_dfs_radar_indication *)
7289 cdf_mem_malloc(sizeof(struct wma_dfs_radar_indication));
7290 if (radar_event == NULL) {
7291 WMA_LOGE("%s:DFS- Invalid radar_event", __func__);
7292 return -ENOMEM;
7293 }
7294
7295 /*
7296 * Do not post multiple Radar events on the same channel.
7297 * But, when DFS test mode is enabled, allow multiple dfs
7298 * radar events to be posted on the same channel.
7299 */
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05307300 cdf_spin_lock_bh(&ic->chan_lock);
Edhar, Mahesh Kumar35d9b2e2015-10-26 17:06:23 +05307301 if (!pmac->sap.SapDfsInfo.disable_dfs_ch_switch)
7302 wma->dfs_ic->disable_phy_err_processing = true;
7303
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007304 if ((ichan->ic_ieee != (wma->dfs_ic->last_radar_found_chan)) ||
7305 (pmac->sap.SapDfsInfo.disable_dfs_ch_switch == true)) {
7306 wma->dfs_ic->last_radar_found_chan = ichan->ic_ieee;
7307 /* Indicate the radar event to HDD to stop the netif Tx queues */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007308 wma_radar_event.chan_freq = ichan->ic_freq;
7309 wma_radar_event.dfs_radar_status = WMA_DFS_RADAR_FOUND;
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05307310 indication_status =
7311 wma->dfs_radar_indication_cb(hdd_ctx, &wma_radar_event);
7312 if (indication_status == false) {
7313 WMA_LOGE("%s:Application triggered channel switch in progress!.. drop radar event indiaction to SAP",
7314 __func__);
7315 cdf_mem_free(radar_event);
7316 cdf_spin_unlock_bh(&ic->chan_lock);
7317 return 0;
7318 }
7319
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007320 WMA_LOGE("%s:DFS- RADAR INDICATED TO HDD", __func__);
7321
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05307322 wma_radar_event.ieee_chan_number = ichan->ic_ieee;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007323 /*
7324 * Indicate to the radar event to SAP to
7325 * select a new channel and set CSA IE
7326 */
7327 radar_event->vdev_id = ic->vdev_id;
7328 wma_get_channels(ichan, &radar_event->chan_list);
7329 radar_event->dfs_radar_status = WMA_DFS_RADAR_FOUND;
7330 radar_event->use_nol = ic->ic_dfs_usenol(ic);
7331 wma_send_msg(wma, WMA_DFS_RADAR_IND, (void *)radar_event, 0);
7332 WMA_LOGE("%s:DFS- WMA_DFS_RADAR_IND Message Posted", __func__);
7333 }
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05307334 cdf_spin_unlock_bh(&ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007335
7336 return 0;
7337}
7338
7339#ifdef WLAN_FEATURE_MEMDUMP
7340/*
7341 * wma_process_fw_mem_dump_req() - Function to request fw memory dump from
7342 * firmware
7343 * @wma: Pointer to WMA handle
7344 * @mem_dump_req: Pointer for mem_dump_req
7345 *
7346 * This function sends memory dump request to firmware
7347 *
7348 * Return: CDF_STATUS_SUCCESS for success otherwise failure
7349 *
7350 */
7351CDF_STATUS wma_process_fw_mem_dump_req(tp_wma_handle wma,
7352 struct fw_dump_req *mem_dump_req)
7353{
7354 wmi_get_fw_mem_dump_fixed_param *cmd;
7355 wmi_fw_mem_dump *dump_params;
7356 struct fw_dump_seg_req *seg_req;
7357 int32_t len;
7358 wmi_buf_t buf;
7359 u_int8_t *buf_ptr;
7360 int ret, loop;
7361
7362 if (!mem_dump_req || !wma) {
7363 WMA_LOGE(FL("input pointer is NULL"));
7364 return CDF_STATUS_E_FAILURE;
7365 }
7366
7367 /*
7368 * len = sizeof(fixed param) that includes tlv header +
7369 * tlv header for array of struc +
7370 * sizeof (each struct)
7371 */
7372 len = sizeof(*cmd) + WMI_TLV_HDR_SIZE;
7373 len += mem_dump_req->num_seg * sizeof(wmi_fw_mem_dump);
7374 buf = wmi_buf_alloc(wma->wmi_handle, len);
7375
7376 if (!buf) {
7377 WMA_LOGE(FL("Failed allocate wmi buffer"));
7378 return CDF_STATUS_E_NOMEM;
7379 }
7380
7381 buf_ptr = (u_int8_t *) wmi_buf_data(buf);
7382 cdf_mem_zero(buf_ptr, len);
7383 cmd = (wmi_get_fw_mem_dump_fixed_param *) buf_ptr;
7384
7385 WMITLV_SET_HDR(&cmd->tlv_header,
7386 WMITLV_TAG_STRUC_wmi_get_fw_mem_dump_fixed_param,
7387 WMITLV_GET_STRUCT_TLVLEN(wmi_get_fw_mem_dump_fixed_param));
7388
7389 cmd->request_id = mem_dump_req->request_id;
7390 cmd->num_fw_mem_dump_segs = mem_dump_req->num_seg;
7391
7392 /* TLV indicating array of structures to follow */
7393 buf_ptr += sizeof(wmi_get_fw_mem_dump_fixed_param);
7394 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
7395 sizeof(wmi_fw_mem_dump) *
7396 cmd->num_fw_mem_dump_segs);
7397
7398 buf_ptr += WMI_TLV_HDR_SIZE;
7399 dump_params = (wmi_fw_mem_dump *) buf_ptr;
7400
7401 WMA_LOGI(FL("request_id:%d num_seg:%d"),
7402 mem_dump_req->request_id, mem_dump_req->num_seg);
7403 for (loop = 0; loop < cmd->num_fw_mem_dump_segs; loop++) {
7404 seg_req = (struct fw_dump_seg_req *)
7405 ((uint8_t *)(mem_dump_req->segment) +
7406 loop * sizeof(*seg_req));
7407 WMITLV_SET_HDR(&dump_params->tlv_header,
7408 WMITLV_TAG_STRUC_wmi_fw_mem_dump_params,
7409 WMITLV_GET_STRUCT_TLVLEN(wmi_fw_mem_dump));
7410 dump_params->seg_id = seg_req->seg_id;
7411 dump_params->seg_start_addr_lo = seg_req->seg_start_addr_lo;
7412 dump_params->seg_start_addr_hi = seg_req->seg_start_addr_hi;
7413 dump_params->seg_length = seg_req->seg_length;
7414 dump_params->dest_addr_lo = seg_req->dst_addr_lo;
7415 dump_params->dest_addr_hi = seg_req->dst_addr_hi;
7416 WMA_LOGI(FL("seg_number:%d"), loop);
7417 WMA_LOGI(FL("seg_id:%d start_addr_lo:0x%x start_addr_hi:0x%x"),
7418 dump_params->seg_id, dump_params->seg_start_addr_lo,
7419 dump_params->seg_start_addr_hi);
7420 WMA_LOGI(FL("seg_length:%d dst_addr_lo:0x%x dst_addr_hi:0x%x"),
7421 dump_params->seg_length, dump_params->dest_addr_lo,
7422 dump_params->dest_addr_hi);
7423 dump_params++;
7424 }
7425
7426 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
7427 WMI_GET_FW_MEM_DUMP_CMDID);
7428 if (ret) {
7429 WMA_LOGE(FL("Failed to send get firmware mem dump request"));
7430 wmi_buf_free(buf);
7431 return CDF_STATUS_E_FAILURE;
7432 }
7433
7434 WMA_LOGI(FL("Get firmware mem dump request sent successfully"));
7435 return CDF_STATUS_SUCCESS;
7436}
7437
7438/**
7439 * wma_fw_mem_dump_rsp() - send fw mem dump response to SME
7440 *
7441 * @req_id - request id.
7442 * @status - copy status from the firmware.
7443 *
7444 * This function is called by the memory dump response handler to
7445 * indicate SME that firmware dump copy is complete
7446 *
7447 * Return: CDF_STATUS
7448 */
7449static CDF_STATUS wma_fw_mem_dump_rsp(uint32_t req_id, uint32_t status)
7450{
7451 struct fw_dump_rsp *dump_rsp;
7452 cds_msg_t sme_msg = {0};
7453 CDF_STATUS cdf_status = CDF_STATUS_SUCCESS;
7454
7455 dump_rsp = cdf_mem_malloc(sizeof(*dump_rsp));
7456
7457 if (!dump_rsp) {
7458 WMA_LOGE(FL("Memory allocation failed."));
7459 cdf_status = CDF_STATUS_E_NOMEM;
7460 return cdf_status;
7461 }
7462
7463 WMA_LOGI(FL("FW memory dump copy complete status: %d for request: %d"),
7464 status, req_id);
7465
7466 dump_rsp->request_id = req_id;
7467 dump_rsp->dump_complete = status;
7468
7469 sme_msg.type = eWNI_SME_FW_DUMP_IND;
7470 sme_msg.bodyptr = dump_rsp;
7471 sme_msg.bodyval = 0;
7472
7473 cdf_status = cds_mq_post_message(CDF_MODULE_ID_SME, &sme_msg);
7474 if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
7475 WMA_LOGE(FL("Fail to post fw mem dump ind msg"));
7476 cdf_mem_free(dump_rsp);
7477 }
7478
7479 return cdf_status;
7480}
7481
7482/**
7483 * wma_fw_mem_dump_event_handler() - handles fw memory dump event
7484 *
7485 * @handle: pointer to wma handle.
7486 * @cmd_param_info: pointer to TLV info received in the event.
7487 * @len: length of data in @cmd_param_info
7488 *
7489 * This function is a handler for firmware memory dump event.
7490 *
7491 * Return: integer (0 for success and error code otherwise)
7492 */
7493int wma_fw_mem_dump_event_handler(void *handle, u_int8_t *cmd_param_info,
7494 u_int32_t len)
7495{
7496 WMI_UPDATE_FW_MEM_DUMP_EVENTID_param_tlvs *param_buf;
7497 wmi_update_fw_mem_dump_fixed_param *event;
7498 CDF_STATUS status;
7499
7500 param_buf =
7501 (WMI_UPDATE_FW_MEM_DUMP_EVENTID_param_tlvs *) cmd_param_info;
7502 if (!param_buf) {
7503 WMA_LOGA("%s: Invalid stats event", __func__);
7504 return -EINVAL;
7505 }
7506
7507 event = param_buf->fixed_param;
7508
7509 status = wma_fw_mem_dump_rsp(event->request_id,
7510 event->fw_mem_dump_complete);
7511 if (CDF_STATUS_SUCCESS != status) {
7512 WMA_LOGE("Error posting FW MEM DUMP RSP.");
7513 return -EINVAL;
7514 }
7515
7516 WMA_LOGI("FW MEM DUMP RSP posted successfully");
7517 return 0;
7518}
7519#endif /* WLAN_FEATURE_MEMDUMP */
7520
7521/*
7522 * wma_process_set_ie_info() - Function to send IE info to firmware
7523 * @wma: Pointer to WMA handle
7524 * @ie_data: Pointer for ie data
7525 *
7526 * This function sends IE information to firmware
7527 *
7528 * Return: CDF_STATUS_SUCCESS for success otherwise failure
7529 *
7530 */
7531CDF_STATUS wma_process_set_ie_info(tp_wma_handle wma,
7532 struct vdev_ie_info *ie_info)
7533{
7534 wmi_vdev_set_ie_cmd_fixed_param *cmd;
7535 wmi_buf_t buf;
7536 uint8_t *buf_ptr;
7537 uint32_t len, ie_len_aligned;
7538 int ret;
7539
7540 if (!ie_info || !wma) {
7541 WMA_LOGE(FL("input pointer is NULL"));
7542 return CDF_STATUS_E_FAILURE;
7543 }
7544
7545 /* Validate the input */
7546 if (ie_info->length <= 0) {
7547 WMA_LOGE(FL("Invalid IE length"));
7548 return CDF_STATUS_E_INVAL;
7549 }
7550
7551 ie_len_aligned = roundup(ie_info->length, sizeof(uint32_t));
7552 /* Allocate memory for the WMI command */
7553 len = sizeof(*cmd) + WMI_TLV_HDR_SIZE + ie_len_aligned;
7554
7555 buf = wmi_buf_alloc(wma->wmi_handle, len);
7556 if (!buf) {
7557 WMA_LOGE(FL("wmi_buf_alloc failed"));
7558 return CDF_STATUS_E_NOMEM;
7559 }
7560
7561 buf_ptr = wmi_buf_data(buf);
7562 cdf_mem_zero(buf_ptr, len);
7563
7564 /* Populate the WMI command */
7565 cmd = (wmi_vdev_set_ie_cmd_fixed_param *)buf_ptr;
7566
7567 WMITLV_SET_HDR(&cmd->tlv_header,
7568 WMITLV_TAG_STRUC_wmi_vdev_set_ie_cmd_fixed_param,
7569 WMITLV_GET_STRUCT_TLVLEN(
7570 wmi_vdev_set_ie_cmd_fixed_param));
7571 cmd->vdev_id = ie_info->vdev_id;
7572 cmd->ie_id = ie_info->ie_id;
7573 cmd->ie_len = ie_info->length;
7574
7575 WMA_LOGD(FL("IE:%d of size:%d sent for vdev:%d"), ie_info->ie_id,
7576 ie_info->length, ie_info->vdev_id);
7577
7578 buf_ptr += sizeof(*cmd);
7579 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, ie_len_aligned);
7580 buf_ptr += WMI_TLV_HDR_SIZE;
7581
7582 cdf_mem_copy(buf_ptr, ie_info->data, cmd->ie_len);
7583
7584 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
7585 WMI_VDEV_SET_IE_CMDID);
7586 if (ret != EOK) {
7587 WMA_LOGE(FL("Failed to send set IE command ret = %d"), ret);
7588 wmi_buf_free(buf);
7589 }
7590
7591 return ret;
7592}
7593