blob: 5bd515e647fe673c8944d866541ac314485deba6 [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) {
Houston Hoffman79b4af22015-10-06 12:01:08 -07003394 if (wma_is_vdev_in_beaconning_mode(wma, vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003395 /* Configure SAP/GO/IBSS mode default wow patterns */
3396 WMA_LOGI("Config SAP specific default wow patterns vdev_id %d",
3397 vdev_id);
3398 wma_wow_ap(wma, vdev_id);
3399 } else {
3400 /* Configure STA/P2P CLI mode default wow patterns */
3401 WMA_LOGI("Config STA specific default wow patterns vdev_id %d",
3402 vdev_id);
3403 wma_wow_sta(wma, vdev_id);
3404 if (wma->IsRArateLimitEnabled) {
3405 WMA_LOGI("Config STA RA limit wow patterns vdev_id %d",
3406 vdev_id);
3407 wma_wow_sta_ra_filter(wma, vdev_id);
3408 }
3409 }
3410 }
3411
3412 return;
3413}
3414
3415/**
3416 * wma_register_wow_wakeup_events() - register vdev specific wake events with fw
3417 * @handle: Pointer to wma handle
3418 * @vdev_id: vdev Id
3419 * @vdev_type: vdev type
3420 * @vdev_subtype: vdev sub type
3421 *
3422 * WoW wake up event rule is following:
3423 * 1) STA mode and P2P CLI mode wake up events are same
3424 * 2) SAP mode and P2P GO mode wake up events are same
3425 * 3) IBSS mode wake events are same as STA mode plus WOW_BEACON_EVENT
3426 *
3427 * Return: none
3428 */
3429void wma_register_wow_wakeup_events(WMA_HANDLE handle,
3430 uint8_t vdev_id,
3431 uint8_t vdev_type,
3432 uint8_t vdev_subtype)
3433{
3434 tp_wma_handle wma = handle;
3435 uint32_t event_bitmap;
3436
3437 WMA_LOGI("vdev_type %d vdev_subtype %d vdev_id %d", vdev_type,
3438 vdev_subtype, vdev_id);
3439
3440 if ((WMI_VDEV_TYPE_STA == vdev_type) ||
3441 ((WMI_VDEV_TYPE_AP == vdev_type) &&
3442 (WMI_UNIFIED_VDEV_SUBTYPE_P2P_DEVICE == vdev_subtype))) {
3443 /* Configure STA/P2P CLI mode specific default wake up events */
3444 event_bitmap = WMA_WOW_STA_WAKE_UP_EVENTS;
3445 WMA_LOGI("STA specific default wake up event 0x%x vdev id %d",
3446 event_bitmap, vdev_id);
3447 } else if (WMI_VDEV_TYPE_IBSS == vdev_type) {
3448 /* Configure IBSS mode specific default wake up events */
3449 event_bitmap = (WMA_WOW_STA_WAKE_UP_EVENTS |
3450 (1 << WOW_BEACON_EVENT));
3451 WMA_LOGI("IBSS specific default wake up event 0x%x vdev id %d",
3452 event_bitmap, vdev_id);
3453 } else if (WMI_VDEV_TYPE_AP == vdev_type) {
3454 /* Configure SAP/GO mode specific default wake up events */
3455 event_bitmap = WMA_WOW_SAP_WAKE_UP_EVENTS;
3456 WMA_LOGI("SAP specific default wake up event 0x%x vdev id %d",
3457 event_bitmap, vdev_id);
3458 } else {
3459 WMA_LOGE("unknown type %d subtype %d", vdev_type, vdev_subtype);
3460 return;
3461 }
3462
3463 wma_add_wow_wakeup_event(wma, vdev_id, event_bitmap, true);
3464
3465 return;
3466}
3467
3468/**
3469 * wma_enable_disable_wakeup_event() - Configures wow wakeup events
3470 * @wma: wma handle
3471 * @vdev_id: vdev id
3472 * @bitmap: Event bitmap
3473 * @enable: enable/disable
3474 *
3475 * Return: none
3476 */
3477void wma_enable_disable_wakeup_event(WMA_HANDLE handle,
3478 uint32_t vdev_id,
3479 uint32_t bitmap,
3480 bool enable)
3481{
3482 tp_wma_handle wma = handle;
3483
3484 WMA_LOGI("vdev_id %d wake up event 0x%x enable %d",
3485 vdev_id, bitmap, enable);
3486 wma_add_wow_wakeup_event(wma, vdev_id, bitmap, enable);
3487}
3488
3489/**
3490 * wma_enable_wow_in_fw() - wnable wow in fw
3491 * @wma: wma handle
3492 *
3493 * Return: CDF status
3494 */
3495CDF_STATUS wma_enable_wow_in_fw(WMA_HANDLE handle)
3496{
3497 tp_wma_handle wma = handle;
3498 wmi_wow_enable_cmd_fixed_param *cmd;
3499 wmi_buf_t buf;
3500 int32_t len;
3501 int ret;
3502 struct ol_softc *scn;
3503 int host_credits;
3504 int wmi_pending_cmds;
3505#ifdef CONFIG_CNSS
3506 tpAniSirGlobal pMac = cds_get_context(CDF_MODULE_ID_PE);
3507
3508 if (NULL == pMac) {
3509 WMA_LOGE("%s: Unable to get PE context", __func__);
3510 return CDF_STATUS_E_FAILURE;
3511 }
3512#endif /* CONFIG_CNSS */
3513
3514 len = sizeof(wmi_wow_enable_cmd_fixed_param);
3515
3516 buf = wmi_buf_alloc(wma->wmi_handle, len);
3517 if (!buf) {
3518 WMA_LOGE("%s: Failed allocate wmi buffer", __func__);
3519 return CDF_STATUS_E_NOMEM;
3520 }
3521
3522 cmd = (wmi_wow_enable_cmd_fixed_param *) wmi_buf_data(buf);
3523 WMITLV_SET_HDR(&cmd->tlv_header,
3524 WMITLV_TAG_STRUC_wmi_wow_enable_cmd_fixed_param,
3525 WMITLV_GET_STRUCT_TLVLEN
3526 (wmi_wow_enable_cmd_fixed_param));
3527 cmd->enable = true;
3528 if (hif_can_suspend_link())
3529 cmd->pause_iface_config = WOW_IFACE_PAUSE_ENABLED;
3530 else
3531 cmd->pause_iface_config = WOW_IFACE_PAUSE_DISABLED;
3532
3533 WMA_LOGI("suspend type: %s",
3534 cmd->pause_iface_config == WOW_IFACE_PAUSE_ENABLED ?
3535 "WOW_IFACE_PAUSE_ENABLED" : "WOW_IFACE_PAUSE_DISABLED");
3536
3537 cdf_event_reset(&wma->target_suspend);
3538 wma->wow_nack = 0;
3539
3540 host_credits = wmi_get_host_credits(wma->wmi_handle);
3541 wmi_pending_cmds = wmi_get_pending_cmds(wma->wmi_handle);
3542
3543 WMA_LOGD("Credits:%d; Pending_Cmds: %d",
3544 host_credits, wmi_pending_cmds);
3545
3546 if (host_credits < WMI_WOW_REQUIRED_CREDITS) {
3547 WMA_LOGE("%s: Host Doesn't have enough credits to Post WMI_WOW_ENABLE_CMDID! "
3548 "Credits:%d, pending_cmds:%d\n", __func__, host_credits,
3549 wmi_pending_cmds);
3550#ifndef QCA_WIFI_3_0_EMU
3551 goto error;
3552#endif
3553 }
3554
3555 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
3556 WMI_WOW_ENABLE_CMDID);
3557 if (ret) {
3558 WMA_LOGE("Failed to enable wow in fw");
3559 goto error;
3560 }
3561
3562 wmi_set_target_suspend(wma->wmi_handle, true);
3563
3564 if (cdf_wait_single_event(&wma->target_suspend,
3565 WMA_TGT_SUSPEND_COMPLETE_TIMEOUT)
3566 != CDF_STATUS_SUCCESS) {
3567 WMA_LOGE("Failed to receive WoW Enable Ack from FW");
3568 WMA_LOGE("Credits:%d; Pending_Cmds: %d",
3569 wmi_get_host_credits(wma->wmi_handle),
3570 wmi_get_pending_cmds(wma->wmi_handle));
Prashanth Bhatta9e143052015-12-04 11:56:47 -08003571 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003572#ifdef CONFIG_CNSS
Yue Ma455aff62015-10-20 18:29:16 -07003573 if (pMac->sme.enableSelfRecovery) {
3574 cds_trigger_recovery();
3575 } else {
3576 CDF_BUG(0);
3577 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003578#else
Yue Ma455aff62015-10-20 18:29:16 -07003579 CDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003580#endif /* CONFIG_CNSS */
Yue Ma455aff62015-10-20 18:29:16 -07003581 } else {
3582 WMA_LOGE("%s: LOGP is in progress, ignore!", __func__);
3583 }
3584
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003585 wmi_set_target_suspend(wma->wmi_handle, false);
3586 return CDF_STATUS_E_FAILURE;
3587 }
3588
3589 if (wma->wow_nack) {
3590 WMA_LOGE("FW not ready to WOW");
3591 wmi_set_target_suspend(wma->wmi_handle, false);
3592 return CDF_STATUS_E_AGAIN;
3593 }
3594
3595 host_credits = wmi_get_host_credits(wma->wmi_handle);
3596 wmi_pending_cmds = wmi_get_pending_cmds(wma->wmi_handle);
3597
3598 if (host_credits < WMI_WOW_REQUIRED_CREDITS) {
3599 WMA_LOGE("%s: No Credits after HTC ACK:%d, pending_cmds:%d, "
3600 "cannot resume back", __func__, host_credits,
3601 wmi_pending_cmds);
3602 htc_dump_counter_info(wma->htc_handle);
Prashanth Bhatta9e143052015-12-04 11:56:47 -08003603 if (!cds_is_driver_recovering())
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003604 CDF_BUG(0);
3605 else
3606 WMA_LOGE("%s: SSR in progress, ignore no credit issue",
3607 __func__);
3608 }
3609
3610 WMA_LOGD("WOW enabled successfully in fw: credits:%d"
3611 "pending_cmds: %d", host_credits, wmi_pending_cmds);
3612
3613 scn = cds_get_context(CDF_MODULE_ID_HIF);
3614
3615 if (scn == NULL) {
3616 WMA_LOGE("%s: Failed to get HIF context", __func__);
3617 CDF_ASSERT(0);
3618 return CDF_STATUS_E_FAULT;
3619 }
3620
3621 htc_cancel_deferred_target_sleep(scn);
3622
3623 wma->wow.wow_enable_cmd_sent = true;
3624
3625 return CDF_STATUS_SUCCESS;
3626
3627error:
3628 wmi_buf_free(buf);
3629 return CDF_STATUS_E_FAILURE;
3630}
3631
3632/**
3633 * wma_resume_req() - clear configured wow patterns in fw
3634 * @wma: wma handle
Houston Hoffmana76591b2015-11-10 16:52:05 -08003635 * @type: type of suspend
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003636 *
3637 * Return: CDF status
3638 */
Houston Hoffmana76591b2015-11-10 16:52:05 -08003639CDF_STATUS wma_resume_req(tp_wma_handle wma, enum cdf_suspend_type type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003640{
Houston Hoffmana76591b2015-11-10 16:52:05 -08003641 if (type == CDF_SYSTEM_SUSPEND) {
3642 wma->no_of_resume_ind++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003643
Houston Hoffmana76591b2015-11-10 16:52:05 -08003644 if (wma->no_of_resume_ind < wma_get_vdev_count(wma))
3645 return CDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003646
Houston Hoffmana76591b2015-11-10 16:52:05 -08003647 wma->no_of_resume_ind = 0;
3648 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003649
3650 /* Reset the DTIM Parameters */
3651 wma_set_resume_dtim(wma);
3652 /* need to reset if hif_pci_suspend_fails */
3653 wma_set_wow_bus_suspend(wma, 0);
3654 /* unpause the vdev if left paused and hif_pci_suspend fails */
3655 wma_unpause_vdev(wma);
3656
Houston Hoffman1460fa32015-11-18 02:36:30 -08003657 wmi_set_runtime_pm_inprogress(wma->wmi_handle, false);
3658
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003659 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
3895/**
Houston Hoffmana76591b2015-11-10 16:52:05 -08003896 * wma_calculate_and_update_conn_state(): calculate each interfaces conn state
3897 * @wma: validated wma handle
3898 *
3899 * Identifies any vdev that is up and not in ap mode as connected.
3900 * stores this in the interfaces conn_state varible.
3901 */
3902void wma_calculate_and_update_conn_state(tp_wma_handle wma)
3903{
3904 int i;
3905 for (i = 0; i < wma->max_bssid; i++) {
3906 wma->interfaces[i].conn_state =
3907 !!(wma->interfaces[i].vdev_up &&
3908 !wma_is_vdev_in_ap_mode(wma, i));
3909 }
3910}
3911
3912/**
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003913 * wma_update_conn_state(): synchronize wma & hdd
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003914 * @wma: wma handle
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003915 * @conn_state: boolean array to populate
3916 * @len: validation parameter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003917 *
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003918 * populate interfaces conn_state with true if the interface
3919 * is a connected client and wow will configure a pattern.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003920 */
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003921void wma_update_conn_state(tp_wma_handle wma, uint32_t conn_mask)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003922{
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003923 int i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003924 for (i = 0; i < wma->max_bssid; i++) {
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003925 if (conn_mask & (1 << i))
3926 wma->interfaces[i].conn_state = true;
3927 else
3928 wma->interfaces[i].conn_state = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003929 }
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003930
3931 if (wma->wow.magic_ptrn_enable)
3932 return;
3933
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003934 for (i = 0; i < wma->max_bssid; i++) {
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003935 if (!wma->interfaces[i].ptrn_match_enable)
3936 wma->interfaces[i].conn_state = false;
3937 }
3938}
3939
3940/**
3941 * wma_is_beaconning_vdev_up(): check if a beaconning vdev is up
3942 * @wma: wma handle
3943 *
3944 * Return TRUE if beaconning vdev is up
3945 */
3946static inline
3947bool wma_is_beaconning_vdev_up(tp_wma_handle wma)
3948{
3949 int i;
3950 for (i = 0; i < wma->max_bssid; i++) {
3951 if (wma_is_vdev_in_beaconning_mode(wma, i)
3952 && wma->interfaces[i].vdev_up)
3953 return true;
3954 }
3955 return false;
3956}
3957
3958/**
3959 * wma_support_wow_for_beaconing: wow query for beaconning
3960 * @wma: wma handle
3961 *
3962 * Need to configure wow to enable beaconning offload when
3963 * a beaconing vdev is up and beaonning offload is configured.
3964 *
3965 * Return: true if we need to enable wow for beaconning offload
3966 */
3967static inline
3968bool wma_support_wow_for_beaconing(tp_wma_handle wma)
3969{
3970 if (WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
3971 WMI_SERVICE_BEACON_OFFLOAD)) {
3972 if (wma_is_beaconning_vdev_up(wma))
3973 return true;
3974 }
3975 return false;
3976}
3977
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003978#ifdef FEATURE_WLAN_SCAN_PNO
Houston Hoffman7260ecb2015-10-05 18:43:07 -07003979/**
3980 * wma_is_pnoscan_in_progress(): check if a pnoscan is in progress
3981 * @wma: wma handle
3982 * @vdev_id: vdev_id
3983 *
3984 * Return: TRUE/FALSE
3985 */
3986static inline
3987bool wma_is_pnoscan_in_progress(tp_wma_handle wma, int vdev_id)
3988{
3989 return wma->interfaces[vdev_id].pno_in_progress;
3990}
Houston Hoffman345fa402015-12-16 11:28:51 -08003991
3992/**
3993 * wma_is_pnoscan_match_found(): check if a scan match was found
3994 * @wma: wma handle
3995 * @vdev_id: vdev_id
3996 *
3997 * Return: TRUE/FALSE
3998 */
3999static inline
4000bool wma_is_pnoscan_match_found(tp_wma_handle wma, int vdev_id)
4001{
4002 return wma->interfaces[vdev_id].nlo_match_evt_received;
4003}
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004004#else
4005/**
4006 * wma_is_pnoscan_in_progress(): dummy
4007 *
Houston Hoffman345fa402015-12-16 11:28:51 -08004008 * Return: False since no pnoscan cannot be in progress
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004009 * when feature flag is not defined.
4010 */
4011bool wma_is_pnoscan_in_progress(tp_wma_handle wma, int vdev_id)
4012{
4013 return FALSE;
4014}
Houston Hoffman345fa402015-12-16 11:28:51 -08004015
4016/**
4017 * wma_is_pnoscan_match_found(): dummy
4018 * @wma: wma handle
4019 * @vdev_id: vdev_id
4020 *
4021 * Return: False since no pnoscan cannot occur
4022 * when feature flag is not defined.
4023 */
4024static inline
4025bool wma_is_pnoscan_match_found(tp_wma_handle wma, int vdev_id)
4026{
4027 return FALSE;
4028}
Houston Hoffman61667962015-12-15 20:15:41 -08004029#endif
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004030
4031#ifdef FEATURE_WLAN_EXTSCAN
4032static inline
4033/**
4034 * wma_is_extscan_in_progress(): check if an extscan is in progress
4035 * @wma: wma handle
4036 * @vdev_id: vdev_id
4037 *
4038 * Return: TRUE/FALSvE
4039 */
4040bool wma_is_extscan_in_progress(tp_wma_handle wma, int vdev_id)
4041{
4042 return wma->interfaces[vdev_id].extscan_in_progress;
4043}
4044#else
4045/**
4046 * wma_is_extscan_in_progress(): dummy
4047 *
4048 * Return: False since no extscan can be in progress
4049 * when feature flag is not defined.
4050 */
4051bool wma_is_extscan_in_progress(tp_wma_handle wma, int vdev_id)
4052{
4053 return false;
4054}
4055#endif
4056
4057/**
4058 * wma_is_wow_applicable(): should enable wow
4059 * @wma: wma handle
4060 *
4061 * Enable WOW if any one of the condition meets,
4062 * 1) Is any one of vdev in beaconning mode (in AP mode) ?
4063 * 2) Is any one of vdev in connected state (in STA mode) ?
4064 * 3) Is PNO in progress in any one of vdev ?
4065 * 4) Is Extscan in progress in any one of vdev ?
4066 *
4067 * Return: true if wma needs to configure wow.
4068 */
4069bool wma_is_wow_applicable(tp_wma_handle wma)
4070{
4071 int vdev_id;
4072 if (wma_support_wow_for_beaconing(wma)) {
4073 WMA_LOGD("vdev is in beaconning mode, enabling wow");
4074 return true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004075 }
4076
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004077 for (vdev_id = 0; vdev_id < wma->max_bssid; vdev_id++) {
4078 if (wma->interfaces[vdev_id].conn_state) {
4079 WMA_LOGD("STA is connected, enabling wow");
4080 return true;
4081 } else if (wma_is_pnoscan_in_progress(wma, vdev_id)) {
4082 WMA_LOGD("PNO is in progress, enabling wow");
4083 return true;
4084 } else if (wma_is_extscan_in_progress(wma, vdev_id)) {
4085 WMA_LOGD("EXT is in progress, enabling wow");
4086 return true;
4087 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004088 }
4089
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004090 WMA_LOGD("All vdev are in disconnected state and pno/extscan is not in progress, skipping wow");
4091 return true;
4092}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004093
Houston Hoffman345fa402015-12-16 11:28:51 -08004094/**
4095 * wma_configure_dynamic_wake_events(): configure dyanmic wake events
4096 * @wma: wma handle
4097 *
4098 * Some wake events need to be enabled dynamically. Controll those here.
4099 *
4100 * Return: none
4101 */
4102void wma_configure_dynamic_wake_events(tp_wma_handle wma)
4103{
4104 int vdev_id;
4105 int enable_mask;
4106 int disable_mask;
4107
4108 for (vdev_id = 0; vdev_id < wma->max_bssid; vdev_id++) {
4109 enable_mask = 0;
4110 disable_mask = 0;
4111
4112 if (wma_is_pnoscan_in_progress(wma, vdev_id)) {
4113 if (wma_is_pnoscan_match_found(wma, vdev_id))
4114 enable_mask |=
4115 (1 << WOW_NLO_SCAN_COMPLETE_EVENT);
4116 else
4117 disable_mask |=
4118 (1 << WOW_NLO_SCAN_COMPLETE_EVENT);
4119 }
4120
4121 if (enable_mask != 0)
4122 wma_enable_disable_wakeup_event(wma, vdev_id,
4123 enable_mask, true);
4124 if (disable_mask != 0)
4125 wma_enable_disable_wakeup_event(wma, vdev_id,
4126 disable_mask, false);
4127 }
4128}
4129
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004130#ifdef FEATURE_WLAN_LPHB
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004131/**
4132 * wma_apply_lphb(): apply cached LPHB settings
4133 * @wma: wma handle
4134 *
4135 * LPHB cache, if any item was enabled, should be
4136 * applied.
4137 */
4138static inline
4139void wma_apply_lphb(tp_wma_handle wma)
4140{
4141 int i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004142 WMA_LOGD("%s: checking LPHB cache", __func__);
4143 for (i = 0; i < 2; i++) {
4144 if (wma->wow.lphb_cache[i].params.lphbEnableReq.enable) {
4145 WMA_LOGD("%s: LPHB cache for item %d is marked as enable",
4146 __func__, i + 1);
4147 wma_lphb_conf_hbenable(wma, &(wma->wow.lphb_cache[i]),
4148 false);
4149 }
4150 }
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004151}
4152#else
4153void wma_apply_lphb(tp_wma_handle wma) {}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004154#endif /* FEATURE_WLAN_LPHB */
4155
Houston Hoffmana76591b2015-11-10 16:52:05 -08004156static void wma_notify_suspend_req_procesed(tp_wma_handle wma,
4157 enum cdf_suspend_type type)
4158{
4159 if (type == CDF_SYSTEM_SUSPEND)
4160 wma_send_status_to_suspend_ind(wma, true);
4161 else if (type == CDF_RUNTIME_SUSPEND)
4162 cdf_event_set(&wma->runtime_suspend);
4163}
4164
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004165/**
4166 * wma_suspend_req() - Handles suspend indication request received from umac.
4167 * @wma: wma handle
Houston Hoffmana76591b2015-11-10 16:52:05 -08004168 * @type: type of suspend
4169 *
4170 * The type controlls how we notify the indicator that the indication has
4171 * been processed
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004172 *
4173 * Return: CDF status
4174 */
Houston Hoffmana76591b2015-11-10 16:52:05 -08004175CDF_STATUS wma_suspend_req(tp_wma_handle wma, enum cdf_suspend_type type)
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004176{
Houston Hoffman1460fa32015-11-18 02:36:30 -08004177 if (type == CDF_RUNTIME_SUSPEND)
4178 wmi_set_runtime_pm_inprogress(wma->wmi_handle, true);
4179
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004180 if (wma_is_wow_applicable(wma)) {
4181 WMA_LOGE("WOW Suspend");
4182 wma_apply_lphb(wma);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004183
Houston Hoffman345fa402015-12-16 11:28:51 -08004184 wma_configure_dynamic_wake_events(wma);
4185
Houston Hoffman7260ecb2015-10-05 18:43:07 -07004186 wma->wow.wow_enable = true;
4187 wma->wow.wow_enable_cmd_sent = false;
4188 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004189
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004190 /* Set the Suspend DTIM Parameters */
4191 wma_set_suspend_dtim(wma);
Houston Hoffmana76591b2015-11-10 16:52:05 -08004192
4193 wma_notify_suspend_req_procesed(wma, type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004194
4195 /* to handle race between hif_pci_suspend and
4196 * unpause/pause tx handler
4197 */
4198 wma_set_wow_bus_suspend(wma, 1);
4199
4200 return CDF_STATUS_SUCCESS;
4201}
4202
4203/**
4204 * wma_send_host_wakeup_ind_to_fw() - send wakeup ind to fw
4205 * @wma: wma handle
4206 *
4207 * Sends host wakeup indication to FW. On receiving this indication,
4208 * FW will come out of WOW.
4209 *
4210 * Return: CDF status
4211 */
4212static CDF_STATUS wma_send_host_wakeup_ind_to_fw(tp_wma_handle wma)
4213{
4214 wmi_wow_hostwakeup_from_sleep_cmd_fixed_param *cmd;
4215 wmi_buf_t buf;
4216 CDF_STATUS cdf_status = CDF_STATUS_SUCCESS;
4217 int32_t len;
4218 int ret;
4219#ifdef CONFIG_CNSS
4220 tpAniSirGlobal pMac = cds_get_context(CDF_MODULE_ID_PE);
4221 if (NULL == pMac) {
4222 WMA_LOGE("%s: Unable to get PE context", __func__);
4223 return CDF_STATUS_E_FAILURE;
4224 }
4225#endif /* CONFIG_CNSS */
4226
4227 len = sizeof(wmi_wow_hostwakeup_from_sleep_cmd_fixed_param);
4228
4229 buf = wmi_buf_alloc(wma->wmi_handle, len);
4230 if (!buf) {
4231 WMA_LOGE("%s: Failed allocate wmi buffer", __func__);
4232 return CDF_STATUS_E_NOMEM;
4233 }
4234
4235 cmd = (wmi_wow_hostwakeup_from_sleep_cmd_fixed_param *)
4236 wmi_buf_data(buf);
4237 WMITLV_SET_HDR(&cmd->tlv_header,
4238 WMITLV_TAG_STRUC_wmi_wow_hostwakeup_from_sleep_cmd_fixed_param,
4239 WMITLV_GET_STRUCT_TLVLEN
4240 (wmi_wow_hostwakeup_from_sleep_cmd_fixed_param));
4241
4242 cdf_event_reset(&wma->wma_resume_event);
4243
4244 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
4245 WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID);
4246 if (ret) {
4247 WMA_LOGE("Failed to send host wakeup indication to fw");
4248 wmi_buf_free(buf);
4249 return CDF_STATUS_E_FAILURE;
4250 }
4251
4252 WMA_LOGD("Host wakeup indication sent to fw");
4253
4254 cdf_status = cdf_wait_single_event(&(wma->wma_resume_event),
4255 WMA_RESUME_TIMEOUT);
4256 if (CDF_STATUS_SUCCESS != cdf_status) {
4257 WMA_LOGP("%s: Timeout waiting for resume event from FW",
4258 __func__);
4259 WMA_LOGP("%s: Pending commands %d credits %d", __func__,
4260 wmi_get_pending_cmds(wma->wmi_handle),
4261 wmi_get_host_credits(wma->wmi_handle));
Prashanth Bhatta9e143052015-12-04 11:56:47 -08004262 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004263#ifdef CONFIG_CNSS
4264 if (pMac->sme.enableSelfRecovery) {
4265 cds_trigger_recovery();
4266 } else {
4267 CDF_BUG(0);
4268 }
4269#else
4270 CDF_BUG(0);
4271#endif /* CONFIG_CNSS */
4272 } else {
4273 WMA_LOGE("%s: SSR in progress, ignore resume timeout",
4274 __func__);
4275 }
4276 } else {
4277 WMA_LOGD("Host wakeup received");
4278 }
4279
4280 if (CDF_STATUS_SUCCESS == cdf_status)
4281 wmi_set_target_suspend(wma->wmi_handle, false);
4282
4283 return cdf_status;
4284}
4285
4286/**
4287 * wma_disable_wow_in_fw() - Disable wow in PCIe resume context.
4288 * @handle: wma handle
4289 *
4290 * Return: 0 for success or error code
4291 */
4292CDF_STATUS wma_disable_wow_in_fw(WMA_HANDLE handle)
4293{
4294 tp_wma_handle wma = handle;
4295 CDF_STATUS ret;
4296
4297 if (!wma->wow.wow_enable || !wma->wow.wow_enable_cmd_sent)
4298 return CDF_STATUS_SUCCESS;
4299
4300 ret = wma_send_host_wakeup_ind_to_fw(wma);
4301
4302 if (ret != CDF_STATUS_SUCCESS)
4303 return ret;
4304
4305 wma->wow.wow_enable = false;
4306 wma->wow.wow_enable_cmd_sent = false;
4307
4308 /* To allow the tx pause/unpause events */
4309 wma_set_wow_bus_suspend(wma, 0);
4310 /* Unpause the vdev as we are resuming */
4311 wma_unpause_vdev(wma);
4312
4313 return ret;
4314}
4315
4316#ifdef WLAN_FEATURE_LPSS
4317/**
4318 * wma_is_lpass_enabled() - check if lpass is enabled
4319 * @handle: Pointer to wma handle
4320 *
4321 * WoW is needed if LPASS or NaN feature is enabled in INI because
4322 * target can't wake up itself if its put in PDEV suspend when LPASS
4323 * or NaN features are supported
4324 *
4325 * Return: true if lpass is enabled else false
4326 */
4327bool static wma_is_lpass_enabled(tp_wma_handle wma)
4328{
4329 if (wma->is_lpass_enabled)
4330 return true;
4331 else
4332 return false;
4333}
4334#else
4335bool static wma_is_lpass_enabled(tp_wma_handle wma)
4336{
4337 return false;
4338}
4339#endif
4340
4341#ifdef WLAN_FEATURE_NAN
4342/**
4343 * wma_is_nan_enabled() - check if NaN is enabled
4344 * @handle: Pointer to wma handle
4345 *
4346 * WoW is needed if LPASS or NaN feature is enabled in INI because
4347 * target can't wake up itself if its put in PDEV suspend when LPASS
4348 * or NaN features are supported
4349 *
4350 * Return: true if NaN is enabled else false
4351 */
4352bool static wma_is_nan_enabled(tp_wma_handle wma)
4353{
4354 if (wma->is_nan_enabled)
4355 return true;
4356 else
4357 return false;
4358}
4359#else
4360bool static wma_is_nan_enabled(tp_wma_handle wma)
4361{
4362 return false;
4363}
4364#endif
4365
4366/**
4367 * wma_is_wow_mode_selected() - check if wow needs to be enabled in fw
4368 * @handle: Pointer to wma handle
4369 *
4370 * If lpass is enabled then always do wow else check wow_enable config
4371 *
4372 * Return: true is wow mode is needed else false
4373 */
Houston Hoffmana76591b2015-11-10 16:52:05 -08004374bool wma_is_wow_mode_selected(WMA_HANDLE handle)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004375{
4376 tp_wma_handle wma = (tp_wma_handle) handle;
4377
4378 if (wma_is_lpass_enabled(wma)) {
4379 WMA_LOGD("LPASS is enabled select WoW");
4380 return true;
4381 } else if (wma_is_nan_enabled(wma)) {
4382 WMA_LOGD("NAN is enabled select WoW");
4383 return true;
4384 } else {
4385 WMA_LOGD("WoW enable %d", wma->wow.wow_enable);
4386 return wma->wow.wow_enable;
4387 }
4388}
4389
4390/**
4391 * wma_del_ts_req() - send DELTS request to fw
4392 * @wma: wma handle
4393 * @msg: delts params
4394 *
4395 * Return: none
4396 */
4397void wma_del_ts_req(tp_wma_handle wma, tDelTsParams *msg)
4398{
4399 wmi_vdev_wmm_delts_cmd_fixed_param *cmd;
4400 wmi_buf_t buf;
4401 int32_t len = sizeof(*cmd);
4402
4403 buf = wmi_buf_alloc(wma->wmi_handle, len);
4404 if (!buf) {
4405 WMA_LOGP("%s: wmi_buf_alloc failed", __func__);
4406 goto err;
4407 }
4408 cmd = (wmi_vdev_wmm_delts_cmd_fixed_param *) wmi_buf_data(buf);
4409 WMITLV_SET_HDR(&cmd->tlv_header,
4410 WMITLV_TAG_STRUC_wmi_vdev_wmm_delts_cmd_fixed_param,
4411 WMITLV_GET_STRUCT_TLVLEN
4412 (wmi_vdev_wmm_delts_cmd_fixed_param));
4413 cmd->vdev_id = msg->sessionId;
4414 cmd->ac = TID_TO_WME_AC(msg->userPrio);
4415
4416 WMA_LOGD("Delts vdev:%d, ac:%d, %s:%d",
4417 cmd->vdev_id, cmd->ac, __FUNCTION__, __LINE__);
4418 if (wmi_unified_cmd_send(wma->wmi_handle, buf, len,
4419 WMI_VDEV_WMM_DELTS_CMDID)) {
4420 WMA_LOGP("%s: Failed to send vdev DELTS command", __func__);
4421 cdf_nbuf_free(buf);
4422 }
4423#ifdef WLAN_FEATURE_ROAM_OFFLOAD
4424 if (msg->setRICparams == true)
4425 wma_set_ric_req(wma, msg, false);
4426#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
4427
4428err:
4429 cdf_mem_free(msg);
4430}
4431
4432/**
4433 * wma_aggr_qos_req() - send aggr qos request to fw
4434 * @wma: handle to wma
4435 * @pAggrQosRspMsg - combined struct for all ADD_TS requests.
4436 *
4437 * A function to handle WMA_AGGR_QOS_REQ. This will send out
4438 * ADD_TS requestes to firmware in loop for all the ACs with
4439 * active flow.
4440 *
4441 * Return: none
4442 */
4443void wma_aggr_qos_req(tp_wma_handle wma,
4444 tAggrAddTsParams *pAggrQosRspMsg)
4445{
4446 int i = 0;
4447 wmi_vdev_wmm_addts_cmd_fixed_param *cmd;
4448 wmi_buf_t buf;
4449 int32_t len = sizeof(*cmd);
4450
4451 for (i = 0; i < HAL_QOS_NUM_AC_MAX; i++) {
4452 /* if flow in this AC is active */
4453 if (((1 << i) & pAggrQosRspMsg->tspecIdx)) {
4454 /*
4455 * as per implementation of wma_add_ts_req() we
4456 * are not waiting any response from firmware so
4457 * apart from sending ADDTS to firmware just send
4458 * success to upper layers
4459 */
4460 pAggrQosRspMsg->status[i] = CDF_STATUS_SUCCESS;
4461
4462 buf = wmi_buf_alloc(wma->wmi_handle, len);
4463 if (!buf) {
4464 WMA_LOGP("%s: wmi_buf_alloc failed", __func__);
4465 goto aggr_qos_exit;
4466 }
4467 cmd = (wmi_vdev_wmm_addts_cmd_fixed_param *)
4468 wmi_buf_data(buf);
4469 WMITLV_SET_HDR(&cmd->tlv_header,
4470 WMITLV_TAG_STRUC_wmi_vdev_wmm_addts_cmd_fixed_param,
4471 WMITLV_GET_STRUCT_TLVLEN
4472 (wmi_vdev_wmm_addts_cmd_fixed_param));
4473 cmd->vdev_id = pAggrQosRspMsg->sessionId;
4474 cmd->ac =
4475 TID_TO_WME_AC(pAggrQosRspMsg->tspec[i].tsinfo.
4476 traffic.userPrio);
4477 cmd->medium_time_us =
4478 pAggrQosRspMsg->tspec[i].mediumTime * 32;
4479 cmd->downgrade_type = WMM_AC_DOWNGRADE_DEPRIO;
4480 WMA_LOGD("%s:%d: Addts vdev:%d, ac:%d, mediumTime:%d downgrade_type:%d",
4481 __func__, __LINE__, cmd->vdev_id, cmd->ac,
4482 cmd->medium_time_us, cmd->downgrade_type);
4483 if (wmi_unified_cmd_send
4484 (wma->wmi_handle, buf, len,
4485 WMI_VDEV_WMM_ADDTS_CMDID)) {
4486 WMA_LOGP("%s: Failed to send vdev ADDTS command",
4487 __func__);
4488 pAggrQosRspMsg->status[i] =
4489 CDF_STATUS_E_FAILURE;
4490 cdf_nbuf_free(buf);
4491 }
4492 }
4493 }
4494
4495aggr_qos_exit:
4496 /* send reponse to upper layers from here only. */
4497 wma_send_msg(wma, WMA_AGGR_QOS_RSP, pAggrQosRspMsg, 0);
4498}
4499
4500/**
4501 * wma_add_ts_req() - send ADDTS request to fw
4502 * @wma: wma handle
4503 * @msg: ADDTS params
4504 *
4505 * Return: none
4506 */
4507void wma_add_ts_req(tp_wma_handle wma, tAddTsParams *msg)
4508{
4509 wmi_vdev_wmm_addts_cmd_fixed_param *cmd;
4510 wmi_buf_t buf;
4511 int32_t len = sizeof(*cmd);
4512
4513#ifdef FEATURE_WLAN_ESE
4514 /*
4515 * msmt_interval is in unit called TU (1 TU = 1024 us)
4516 * max value of msmt_interval cannot make resulting
4517 * interval_miliseconds overflow 32 bit
4518 */
4519 uint32_t intervalMiliseconds;
4520 ol_txrx_pdev_handle pdev = cds_get_context(CDF_MODULE_ID_TXRX);
4521 if (NULL == pdev) {
4522 WMA_LOGE("%s: Failed to get pdev", __func__);
4523 goto err;
4524 }
4525
4526 intervalMiliseconds = (msg->tsm_interval * 1024) / 1000;
4527
4528 ol_tx_set_compute_interval(pdev, intervalMiliseconds);
4529#endif /* FEATURE_WLAN_ESE */
4530 msg->status = CDF_STATUS_SUCCESS;
4531
4532 buf = wmi_buf_alloc(wma->wmi_handle, len);
4533 if (!buf) {
4534 WMA_LOGP("%s: wmi_buf_alloc failed", __func__);
4535 goto err;
4536 }
4537 cmd = (wmi_vdev_wmm_addts_cmd_fixed_param *) wmi_buf_data(buf);
4538 WMITLV_SET_HDR(&cmd->tlv_header,
4539 WMITLV_TAG_STRUC_wmi_vdev_wmm_addts_cmd_fixed_param,
4540 WMITLV_GET_STRUCT_TLVLEN
4541 (wmi_vdev_wmm_addts_cmd_fixed_param));
4542 cmd->vdev_id = msg->sme_session_id;
4543 cmd->ac = TID_TO_WME_AC(msg->tspec.tsinfo.traffic.userPrio);
4544 cmd->medium_time_us = msg->tspec.mediumTime * 32;
4545 cmd->downgrade_type = WMM_AC_DOWNGRADE_DROP;
4546 WMA_LOGD("Addts vdev:%d, ac:%d, mediumTime:%d, downgrade_type:%d %s:%d",
4547 cmd->vdev_id, cmd->ac, cmd->medium_time_us,
4548 cmd->downgrade_type, __func__, __LINE__);
4549 if (wmi_unified_cmd_send(wma->wmi_handle, buf, len,
4550 WMI_VDEV_WMM_ADDTS_CMDID)) {
4551 WMA_LOGP("%s: Failed to send vdev ADDTS command", __func__);
4552 msg->status = CDF_STATUS_E_FAILURE;
4553 cdf_nbuf_free(buf);
4554 }
4555#ifdef WLAN_FEATURE_ROAM_OFFLOAD
4556 if (msg->setRICparams == true)
4557 wma_set_ric_req(wma, msg, true);
4558#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
4559
4560err:
4561 wma_send_msg(wma, WMA_ADD_TS_RSP, msg, 0);
4562}
4563
4564/**
4565 * wma_enable_disable_packet_filter() - enable/disable packet filter in target
4566 * @wma: Pointer to wma handle
4567 * @vdev_id: vdev id
4568 * @enable: Flag to enable/disable packet filter
4569 *
4570 * Return: 0 for success or error code
4571 */
4572static int wma_enable_disable_packet_filter(tp_wma_handle wma,
4573 uint8_t vdev_id, bool enable)
4574{
4575 int32_t len;
4576 int ret = 0;
4577 wmi_buf_t buf;
4578 WMI_PACKET_FILTER_ENABLE_CMD_fixed_param *cmd;
4579
4580 len = sizeof(WMI_PACKET_FILTER_ENABLE_CMD_fixed_param);
4581
4582 buf = wmi_buf_alloc(wma->wmi_handle, len);
4583 if (!buf) {
4584 WMA_LOGE("%s: Failed allocate wmi buffer", __func__);
4585 return -ENOMEM;
4586 }
4587
4588 cmd = (WMI_PACKET_FILTER_ENABLE_CMD_fixed_param *) wmi_buf_data(buf);
4589 WMITLV_SET_HDR(&cmd->tlv_header,
4590 WMITLV_TAG_STRUC_wmi_packet_filter_enable_fixed_param,
4591 WMITLV_GET_STRUCT_TLVLEN(
4592 WMI_PACKET_FILTER_ENABLE_CMD_fixed_param));
4593
4594 cmd->vdev_id = vdev_id;
4595 if (enable)
4596 cmd->enable = PACKET_FILTER_SET_ENABLE;
4597 else
4598 cmd->enable = PACKET_FILTER_SET_DISABLE;
4599
4600 WMA_LOGE("%s: Packet filter enable %d for vdev_id %d",
4601 __func__, cmd->enable, vdev_id);
4602
4603 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
4604 WMI_PACKET_FILTER_ENABLE_CMDID);
4605 if (ret)
4606 WMA_LOGE("Failed to send packet filter wmi cmd to fw");
4607
4608 return ret;
4609}
4610
4611/**
4612 * wma_config_packet_filter() - configure packet filter in target
4613 * @wma: Pointer to wma handle
4614 * @vdev_id: vdev id
4615 * @rcv_filter_param: Packet filter parameters
4616 * @filter_id: Filter id
4617 * @enable: Flag to add/delete packet filter configuration
4618 *
4619 * Return: 0 for success or error code
4620 */
4621static int wma_config_packet_filter(tp_wma_handle wma,
4622 uint8_t vdev_id, tSirRcvPktFilterCfgType *rcv_filter_param,
4623 uint8_t filter_id, bool enable)
4624{
4625 int len, i;
4626 int err = 0;
4627 wmi_buf_t buf;
4628 WMI_PACKET_FILTER_CONFIG_CMD_fixed_param *cmd;
4629
4630
4631 /* allocate the memory */
4632 len = sizeof(*cmd);
4633 buf = wmi_buf_alloc(wma->wmi_handle, len);
4634 if (!buf) {
4635 WMA_LOGE("Failed to allocate buffer to send set_param cmd");
4636 return -ENOMEM;
4637 }
4638
4639 cmd = (WMI_PACKET_FILTER_CONFIG_CMD_fixed_param *)wmi_buf_data(buf);
4640 WMITLV_SET_HDR(&cmd->tlv_header,
4641 WMITLV_TAG_STRUC_wmi_packet_filter_config_fixed_param,
4642 WMITLV_GET_STRUCT_TLVLEN
4643 (WMI_PACKET_FILTER_CONFIG_CMD_fixed_param));
4644
4645 cmd->vdev_id = vdev_id;
4646 cmd->filter_id = filter_id;
4647 if (enable)
4648 cmd->filter_action = PACKET_FILTER_SET_ACTIVE;
4649 else
4650 cmd->filter_action = PACKET_FILTER_SET_INACTIVE;
4651
4652 if (enable) {
4653 cmd->num_params = CDF_MIN(
4654 WMI_PACKET_FILTER_MAX_CMP_PER_PACKET_FILTER,
4655 rcv_filter_param->numFieldParams);
4656 cmd->filter_type = rcv_filter_param->filterType;
4657 cmd->coalesce_time = rcv_filter_param->coalesceTime;
4658
4659 for (i = 0; i < cmd->num_params; i++) {
4660 cmd->paramsData[i].proto_type =
4661 rcv_filter_param->paramsData[i].protocolLayer;
4662 cmd->paramsData[i].cmp_type =
4663 rcv_filter_param->paramsData[i].cmpFlag;
4664 cmd->paramsData[i].data_length =
4665 rcv_filter_param->paramsData[i].dataLength;
4666 cmd->paramsData[i].data_offset =
4667 rcv_filter_param->paramsData[i].dataOffset;
4668 memcpy(&cmd->paramsData[i].compareData,
4669 rcv_filter_param->paramsData[i].compareData,
4670 sizeof(cmd->paramsData[i].compareData));
4671 memcpy(&cmd->paramsData[i].dataMask,
4672 rcv_filter_param->paramsData[i].dataMask,
4673 sizeof(cmd->paramsData[i].dataMask));
4674 }
4675 }
4676
4677 WMA_LOGE("Packet filter action %d filter with id: %d, num_params=%d",
4678 cmd->filter_action, cmd->filter_id, cmd->num_params);
4679 /* send the command along with data */
4680 err = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
4681 WMI_PACKET_FILTER_CONFIG_CMDID);
4682 if (err) {
4683 WMA_LOGE("Failed to send pkt_filter cmd");
4684 wmi_buf_free(buf);
4685 return -EIO;
4686 }
4687
4688 /* Enable packet filter */
4689 if (enable)
4690 wma_enable_disable_packet_filter(wma, vdev_id, true);
4691
4692 return 0;
4693}
4694
4695/**
4696 * wma_process_receive_filter_set_filter_req() - enable packet filter
4697 * @wma_handle: wma handle
4698 * @rcv_filter_param: filter params
4699 *
4700 * Return: 0 for success or error code
4701 */
4702int wma_process_receive_filter_set_filter_req(tp_wma_handle wma,
4703 tSirRcvPktFilterCfgType *rcv_filter_param)
4704{
4705 int ret = 0;
4706 uint8_t vdev_id;
4707
4708 /* Get the vdev id */
Srinivas Girigowda98530492015-11-20 17:39:24 -08004709 if (!wma_find_vdev_by_bssid(wma,
4710 rcv_filter_param->bssid.bytes, &vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004711 WMA_LOGE("vdev handle is invalid for %pM",
Srinivas Girigowda98530492015-11-20 17:39:24 -08004712 rcv_filter_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004713 return -EINVAL;
4714 }
4715
4716 ret = wma_config_packet_filter(wma, vdev_id, rcv_filter_param,
4717 rcv_filter_param->filterId, true);
4718
4719 return ret;
4720}
4721
4722/**
4723 * wma_process_receive_filter_clear_filter_req() - disable packet filter
4724 * @wma_handle: wma handle
4725 * @rcv_clear_param: filter params
4726 *
4727 * Return: 0 for success or error code
4728 */
4729int wma_process_receive_filter_clear_filter_req(tp_wma_handle wma,
4730 tSirRcvFltPktClearParam *rcv_clear_param)
4731{
4732 int ret = 0;
4733 uint8_t vdev_id;
4734
4735 /* Get the vdev id */
Srinivas Girigowda98530492015-11-20 17:39:24 -08004736 if (!wma_find_vdev_by_bssid(wma,
4737 rcv_clear_param->bssid.bytes, &vdev_id)) {
4738 WMA_LOGE("vdev handle is invalid for %pM",
4739 rcv_clear_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004740 return -EINVAL;
4741 }
4742
4743 ret = wma_config_packet_filter(wma, vdev_id, NULL,
4744 rcv_clear_param->filterId, false);
4745
4746 return ret;
4747}
4748
4749#ifdef FEATURE_WLAN_ESE
4750
4751#define TSM_DELAY_HISTROGRAM_BINS 4
4752/**
4753 * wma_process_tsm_stats_req() - process tsm stats request
4754 * @wma_handler - handle to wma
4755 * @pTsmStatsMsg - TSM stats struct that needs to be populated and
4756 * passed in message.
4757 *
4758 * A parallel function to WMA_ProcessTsmStatsReq for pronto. This
4759 * function fetches stats from data path APIs and post
4760 * WMA_TSM_STATS_RSP msg back to LIM.
4761 *
4762 * Return: CDF status
4763 */
4764CDF_STATUS wma_process_tsm_stats_req(tp_wma_handle wma_handler,
4765 void *pTsmStatsMsg)
4766{
4767 uint8_t counter;
4768 uint32_t queue_delay_microsec = 0;
4769 uint32_t tx_delay_microsec = 0;
4770 uint16_t packet_count = 0;
4771 uint16_t packet_loss_count = 0;
4772 tpAniTrafStrmMetrics pTsmMetric = NULL;
4773#ifdef FEATURE_WLAN_ESE_UPLOAD
4774 tpAniGetTsmStatsReq pStats = (tpAniGetTsmStatsReq) pTsmStatsMsg;
4775 tpAniGetTsmStatsRsp pTsmRspParams = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004776#endif /* FEATURE_WLAN_ESE_UPLOAD */
4777 int tid = pStats->tid;
4778 /*
4779 * The number of histrogram bin report by data path api are different
4780 * than required by TSM, hence different (6) size array used
4781 */
4782 uint16_t bin_values[QCA_TX_DELAY_HIST_REPORT_BINS] = { 0, };
4783
4784 ol_txrx_pdev_handle pdev = cds_get_context(CDF_MODULE_ID_TXRX);
4785
4786 if (NULL == pdev) {
4787 WMA_LOGE("%s: Failed to get pdev", __func__);
4788 cdf_mem_free(pTsmStatsMsg);
4789 return CDF_STATUS_E_INVAL;
4790 }
4791
4792 /* get required values from data path APIs */
4793 ol_tx_delay(pdev, &queue_delay_microsec, &tx_delay_microsec, tid);
4794 ol_tx_delay_hist(pdev, bin_values, tid);
4795 ol_tx_packet_count(pdev, &packet_count, &packet_loss_count, tid);
4796
4797#ifdef FEATURE_WLAN_ESE_UPLOAD
4798 pTsmRspParams =
4799 (tpAniGetTsmStatsRsp) cdf_mem_malloc(sizeof(tAniGetTsmStatsRsp));
4800 if (NULL == pTsmRspParams) {
4801 CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_ERROR,
4802 "%s: CDF MEM Alloc Failure", __func__);
4803 CDF_ASSERT(0);
4804 cdf_mem_free(pTsmStatsMsg);
4805 return CDF_STATUS_E_NOMEM;
4806 }
4807 pTsmRspParams->staId = pStats->staId;
4808 pTsmRspParams->rc = eSIR_FAILURE;
4809 pTsmRspParams->tsmStatsReq = pStats;
4810 pTsmMetric = &pTsmRspParams->tsmMetrics;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004811#endif /* FEATURE_WLAN_ESE_UPLOAD */
4812 /* populate pTsmMetric */
4813 pTsmMetric->UplinkPktQueueDly = queue_delay_microsec;
4814 /* store only required number of bin values */
4815 for (counter = 0; counter < TSM_DELAY_HISTROGRAM_BINS; counter++) {
4816 pTsmMetric->UplinkPktQueueDlyHist[counter] =
4817 bin_values[counter];
4818 }
4819 pTsmMetric->UplinkPktTxDly = tx_delay_microsec;
4820 pTsmMetric->UplinkPktLoss = packet_loss_count;
4821 pTsmMetric->UplinkPktCount = packet_count;
4822
4823 /*
4824 * No need to populate roaming delay and roaming count as they are
4825 * being populated just before sending IAPP frame out
4826 */
4827 /* post this message to LIM/PE */
4828#ifdef FEATURE_WLAN_ESE_UPLOAD
4829 wma_send_msg(wma_handler, WMA_TSM_STATS_RSP, (void *)pTsmRspParams, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004830#endif /* FEATURE_WLAN_ESE_UPLOAD */
4831 return CDF_STATUS_SUCCESS;
4832}
4833
4834#endif /* FEATURE_WLAN_ESE */
4835
4836/**
4837 * wma_add_clear_mcbc_filter() - set mcast filter command to fw
4838 * @wma_handle: wma handle
4839 * @vdev_id: vdev id
4840 * @multicastAddr: mcast address
4841 * @clearList: clear list flag
4842 *
4843 * Return: 0 for success or error code
4844 */
4845static int wma_add_clear_mcbc_filter(tp_wma_handle wma_handle, uint8_t vdev_id,
Srinivas Girigowda98530492015-11-20 17:39:24 -08004846 struct cdf_mac_addr multicast_addr,
4847 bool clearList)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004848{
4849 WMI_SET_MCASTBCAST_FILTER_CMD_fixed_param *cmd;
4850 wmi_buf_t buf;
4851 int err;
4852
4853 buf = wmi_buf_alloc(wma_handle->wmi_handle, sizeof(*cmd));
4854 if (!buf) {
4855 WMA_LOGE("Failed to allocate buffer to send set_param cmd");
4856 return -ENOMEM;
4857 }
4858
4859 cmd = (WMI_SET_MCASTBCAST_FILTER_CMD_fixed_param *) wmi_buf_data(buf);
4860 cdf_mem_zero(cmd, sizeof(*cmd));
4861
4862 WMITLV_SET_HDR(&cmd->tlv_header,
4863 WMITLV_TAG_STRUC_WMI_SET_MCASTBCAST_FILTER_CMD_fixed_param,
4864 WMITLV_GET_STRUCT_TLVLEN
4865 (WMI_SET_MCASTBCAST_FILTER_CMD_fixed_param));
4866 cmd->action =
4867 (clearList ? WMI_MCAST_FILTER_DELETE : WMI_MCAST_FILTER_SET);
4868 cmd->vdev_id = vdev_id;
Srinivas Girigowda98530492015-11-20 17:39:24 -08004869 WMI_CHAR_ARRAY_TO_MAC_ADDR(multicast_addr.bytes, &cmd->mcastbdcastaddr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004870 err = wmi_unified_cmd_send(wma_handle->wmi_handle, buf,
4871 sizeof(*cmd),
4872 WMI_SET_MCASTBCAST_FILTER_CMDID);
4873 if (err) {
4874 WMA_LOGE("Failed to send set_param cmd");
4875 cdf_mem_free(buf);
4876 return -EIO;
4877 }
Srinivas Girigowda98530492015-11-20 17:39:24 -08004878 WMA_LOGD("Action:%d; vdev_id:%d; clearList:%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004879 cmd->action, vdev_id, clearList);
Srinivas Girigowda98530492015-11-20 17:39:24 -08004880 WMA_LOGD("MCBC MAC Addr: "MAC_ADDRESS_STR,
4881 MAC_ADDR_ARRAY(multicast_addr.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004882 return 0;
4883}
4884
4885/**
4886 * wma_process_mcbc_set_filter_req() - process mcbc set filter request
4887 * @wma_handle: wma handle
4888 * @mcbc_param: mcbc params
4889 *
4890 * Return: CDF status
4891 */
4892CDF_STATUS wma_process_mcbc_set_filter_req(tp_wma_handle wma_handle,
4893 tSirRcvFltMcAddrList * mcbc_param)
4894{
4895 uint8_t vdev_id = 0;
4896 int i;
4897
4898 if (mcbc_param->ulMulticastAddrCnt <= 0) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004899 WMA_LOGW("Number of multicast addresses is 0");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004900 return CDF_STATUS_E_FAILURE;
4901 }
4902
Srinivas Girigowda98530492015-11-20 17:39:24 -08004903 if (!wma_find_vdev_by_addr(wma_handle,
4904 mcbc_param->self_macaddr.bytes, &vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004905 WMA_LOGE("%s: Failed to find vdev id for %pM", __func__,
Srinivas Girigowda98530492015-11-20 17:39:24 -08004906 mcbc_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004907 return CDF_STATUS_E_FAILURE;
4908 }
4909 /* set mcbc_param->action to clear MCList and reset
4910 * to configure the MCList in FW
4911 */
4912
4913 for (i = 0; i < mcbc_param->ulMulticastAddrCnt; i++) {
4914 wma_add_clear_mcbc_filter(wma_handle, vdev_id,
4915 mcbc_param->multicastAddr[i],
4916 (mcbc_param->action == 0));
4917 }
4918 return CDF_STATUS_SUCCESS;
4919}
4920
4921#ifdef WLAN_FEATURE_GTK_OFFLOAD
4922#define GTK_OFFLOAD_ENABLE 0
4923#define GTK_OFFLOAD_DISABLE 1
4924
4925/**
4926 * wma_gtk_offload_status_event() - GTK offload status event handler
4927 * @handle: wma handle
4928 * @event: event buffer
4929 * @len: buffer length
4930 *
4931 * Return: 0 for success or error code
4932 */
4933int wma_gtk_offload_status_event(void *handle, uint8_t *event,
4934 uint32_t len)
4935{
4936 tp_wma_handle wma = (tp_wma_handle) handle;
4937 WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param *status;
4938 WMI_GTK_OFFLOAD_STATUS_EVENTID_param_tlvs *param_buf;
4939 tpSirGtkOffloadGetInfoRspParams resp;
4940 cds_msg_t cds_msg;
4941 uint8_t *bssid;
4942
4943 WMA_LOGD("%s Enter", __func__);
4944
4945 param_buf = (WMI_GTK_OFFLOAD_STATUS_EVENTID_param_tlvs *) event;
4946 if (!param_buf) {
4947 WMA_LOGE("param_buf is NULL");
4948 return -EINVAL;
4949 }
4950
4951 status = (WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param *) param_buf->fixed_param;
4952
4953 if (len < sizeof(WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param)) {
4954 WMA_LOGE("Invalid length for GTK status");
4955 return -EINVAL;
4956 }
4957 bssid = wma_find_bssid_by_vdev_id(wma, status->vdev_id);
4958 if (!bssid) {
4959 WMA_LOGE("invalid bssid for vdev id %d", status->vdev_id);
4960 return -ENOENT;
4961 }
4962
4963 resp = cdf_mem_malloc(sizeof(*resp));
4964 if (!resp) {
4965 WMA_LOGE("%s: Failed to alloc response", __func__);
4966 return -ENOMEM;
4967 }
4968 cdf_mem_zero(resp, sizeof(*resp));
4969 resp->mesgType = eWNI_PMC_GTK_OFFLOAD_GETINFO_RSP;
4970 resp->mesgLen = sizeof(*resp);
4971 resp->ulStatus = CDF_STATUS_SUCCESS;
4972 resp->ulTotalRekeyCount = status->refresh_cnt;
4973 /* TODO: Is the total rekey count and GTK rekey count same? */
4974 resp->ulGTKRekeyCount = status->refresh_cnt;
4975
4976 cdf_mem_copy(&resp->ullKeyReplayCounter, &status->replay_counter,
4977 GTK_REPLAY_COUNTER_BYTES);
4978
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -08004979 cdf_mem_copy(resp->bssid.bytes, bssid, IEEE80211_ADDR_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004980
4981#ifdef IGTK_OFFLOAD
4982 /* TODO: Is the refresh count same for GTK and IGTK? */
4983 resp->ulIGTKRekeyCount = status->refresh_cnt;
4984#endif /* IGTK_OFFLOAD */
4985
4986 cds_msg.type = eWNI_PMC_GTK_OFFLOAD_GETINFO_RSP;
4987 cds_msg.bodyptr = (void *)resp;
4988 cds_msg.bodyval = 0;
4989
4990 if (cds_mq_post_message(CDS_MQ_ID_SME, (cds_msg_t *) &cds_msg)
4991 != CDF_STATUS_SUCCESS) {
4992 WMA_LOGE("Failed to post GTK response to SME");
4993 cdf_mem_free(resp);
4994 return -EINVAL;
4995 }
4996
4997 WMA_LOGD("GTK: got target status with replay counter "
4998 "%02x%02x%02x%02x%02x%02x%02x%02x. vdev %d "
4999 "Refresh GTK %d times exchanges since last set operation",
5000 status->replay_counter[0],
5001 status->replay_counter[1],
5002 status->replay_counter[2],
5003 status->replay_counter[3],
5004 status->replay_counter[4],
5005 status->replay_counter[5],
5006 status->replay_counter[6],
5007 status->replay_counter[7],
5008 status->vdev_id, status->refresh_cnt);
5009
5010 WMA_LOGD("%s Exit", __func__);
5011
5012 return 0;
5013}
5014
5015/**
5016 * wma_send_gtk_offload_req() - send GTK offload command to fw
5017 * @wma: wma handle
5018 * @vdev_id: vdev id
5019 * @params: GTK offload parameters
5020 *
5021 * Return: CDF status
5022 */
5023static CDF_STATUS wma_send_gtk_offload_req(tp_wma_handle wma, uint8_t vdev_id,
5024 tpSirGtkOffloadParams params)
5025{
5026 int len;
5027 wmi_buf_t buf;
5028 WMI_GTK_OFFLOAD_CMD_fixed_param *cmd;
5029 CDF_STATUS status = CDF_STATUS_SUCCESS;
5030
5031 WMA_LOGD("%s Enter", __func__);
5032
5033 len = sizeof(*cmd);
5034
5035 /* alloc wmi buffer */
5036 buf = wmi_buf_alloc(wma->wmi_handle, len);
5037 if (!buf) {
5038 WMA_LOGE("wmi_buf_alloc failed for WMI_GTK_OFFLOAD_CMD");
5039 status = CDF_STATUS_E_NOMEM;
5040 goto out;
5041 }
5042
5043 cmd = (WMI_GTK_OFFLOAD_CMD_fixed_param *) wmi_buf_data(buf);
5044 WMITLV_SET_HDR(&cmd->tlv_header,
5045 WMITLV_TAG_STRUC_WMI_GTK_OFFLOAD_CMD_fixed_param,
5046 WMITLV_GET_STRUCT_TLVLEN
5047 (WMI_GTK_OFFLOAD_CMD_fixed_param));
5048
5049 cmd->vdev_id = vdev_id;
5050
5051 /* Request target to enable GTK offload */
5052 if (params->ulFlags == GTK_OFFLOAD_ENABLE) {
5053 cmd->flags = GTK_OFFLOAD_ENABLE_OPCODE;
5054 wma->wow.gtk_err_enable[vdev_id] = true;
5055
5056 /* Copy the keys and replay counter */
5057 cdf_mem_copy(cmd->KCK, params->aKCK, GTK_OFFLOAD_KCK_BYTES);
5058 cdf_mem_copy(cmd->KEK, params->aKEK, GTK_OFFLOAD_KEK_BYTES);
5059 cdf_mem_copy(cmd->replay_counter, &params->ullKeyReplayCounter,
5060 GTK_REPLAY_COUNTER_BYTES);
5061 } else {
5062 wma->wow.gtk_err_enable[vdev_id] = false;
5063 cmd->flags = GTK_OFFLOAD_DISABLE_OPCODE;
5064 }
5065
5066 /* send the wmi command */
5067 if (wmi_unified_cmd_send(wma->wmi_handle, buf, len,
5068 WMI_GTK_OFFLOAD_CMDID)) {
5069 WMA_LOGE("Failed to send WMI_GTK_OFFLOAD_CMDID");
5070 wmi_buf_free(buf);
5071 status = CDF_STATUS_E_FAILURE;
5072 }
5073
5074 WMA_LOGD("VDEVID: %d, GTK_FLAGS: x%x", vdev_id, cmd->flags);
5075out:
5076 WMA_LOGD("%s Exit", __func__);
5077 return status;
5078}
5079
5080/**
5081 * wma_process_gtk_offload_req() - process GTK offload req from umac
5082 * @handle: wma handle
5083 * @params: GTK offload params
5084 *
5085 * Return: CDF status
5086 */
5087CDF_STATUS wma_process_gtk_offload_req(tp_wma_handle wma,
5088 tpSirGtkOffloadParams params)
5089{
5090 uint8_t vdev_id;
5091 CDF_STATUS status = CDF_STATUS_SUCCESS;
5092
5093 WMA_LOGD("%s Enter", __func__);
5094
5095 /* Get the vdev id */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -08005096 if (!wma_find_vdev_by_bssid(wma, params->bssid.bytes, &vdev_id)) {
5097 WMA_LOGE("vdev handle is invalid for %pM", params->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005098 status = CDF_STATUS_E_INVAL;
5099 goto out;
5100 }
5101
5102 /* Validate vdev id */
5103 if (vdev_id >= wma->max_bssid) {
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -08005104 WMA_LOGE("invalid vdev_id %d for %pM", vdev_id,
5105 params->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005106 status = CDF_STATUS_E_INVAL;
5107 goto out;
5108 }
5109
5110 if ((params->ulFlags == GTK_OFFLOAD_ENABLE) &&
5111 (wma->wow.gtk_err_enable[vdev_id] == true)) {
5112 WMA_LOGE("%s GTK Offload already enabled. Disable it first "
5113 "vdev_id %d", __func__, vdev_id);
5114 params->ulFlags = GTK_OFFLOAD_DISABLE;
5115 status = wma_send_gtk_offload_req(wma, vdev_id, params);
5116 if (status != CDF_STATUS_SUCCESS) {
5117 WMA_LOGE("%s Failed to disable GTK Offload", __func__);
5118 goto out;
5119 }
5120 WMA_LOGD("%s Enable GTK Offload again with updated inputs",
5121 __func__);
5122 params->ulFlags = GTK_OFFLOAD_ENABLE;
5123 }
5124 status = wma_send_gtk_offload_req(wma, vdev_id, params);
5125out:
5126 cdf_mem_free(params);
5127 WMA_LOGD("%s Exit", __func__);
5128 return status;
5129}
5130
5131/**
5132 * wma_process_gtk_offload_getinfo_req() - send GTK offload cmd to fw
5133 * @wma: wma handle
5134 * @params: GTK offload params
5135 *
5136 * Return: CDF status
5137 */
5138CDF_STATUS wma_process_gtk_offload_getinfo_req(tp_wma_handle wma,
5139 tpSirGtkOffloadGetInfoRspParams params)
5140{
5141 uint8_t vdev_id;
5142 int len;
5143 wmi_buf_t buf;
5144 WMI_GTK_OFFLOAD_CMD_fixed_param *cmd;
5145 CDF_STATUS status = CDF_STATUS_SUCCESS;
5146
5147 WMA_LOGD("%s Enter", __func__);
5148
5149 /* Get the vdev id */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -08005150 if (!wma_find_vdev_by_bssid(wma, params->bssid.bytes, &vdev_id)) {
5151 WMA_LOGE("vdev handle is invalid for %pM", params->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005152 status = CDF_STATUS_E_INVAL;
5153 goto out;
5154 }
5155
5156 len = sizeof(*cmd);
5157
5158 /* alloc wmi buffer */
5159 buf = wmi_buf_alloc(wma->wmi_handle, len);
5160 if (!buf) {
5161 WMA_LOGE("wmi_buf_alloc failed for WMI_GTK_OFFLOAD_CMD");
5162 status = CDF_STATUS_E_NOMEM;
5163 goto out;
5164 }
5165
5166 cmd = (WMI_GTK_OFFLOAD_CMD_fixed_param *) wmi_buf_data(buf);
5167 WMITLV_SET_HDR(&cmd->tlv_header,
5168 WMITLV_TAG_STRUC_WMI_GTK_OFFLOAD_CMD_fixed_param,
5169 WMITLV_GET_STRUCT_TLVLEN
5170 (WMI_GTK_OFFLOAD_CMD_fixed_param));
5171
5172 /* Request for GTK offload status */
5173 cmd->flags = GTK_OFFLOAD_REQUEST_STATUS_OPCODE;
5174 cmd->vdev_id = vdev_id;
5175
5176 /* send the wmi command */
5177 if (wmi_unified_cmd_send(wma->wmi_handle, buf, len,
5178 WMI_GTK_OFFLOAD_CMDID)) {
5179 WMA_LOGE("Failed to send WMI_GTK_OFFLOAD_CMDID for req info");
5180 wmi_buf_free(buf);
5181 status = CDF_STATUS_E_FAILURE;
5182 }
5183out:
5184 cdf_mem_free(params);
5185 WMA_LOGD("%s Exit", __func__);
5186 return status;
5187}
5188#endif /* WLAN_FEATURE_GTK_OFFLOAD */
5189
5190/**
5191 * wma_enable_arp_ns_offload() - enable ARP NS offload
5192 * @wma: wma handle
5193 * @tpSirHostOffloadReq: offload request
5194 * @bArpOnly: flag
5195 *
5196 * To configure ARP NS off load data to firmware
5197 * when target goes to wow mode.
5198 *
5199 * Return: CDF Status
5200 */
5201CDF_STATUS wma_enable_arp_ns_offload(tp_wma_handle wma,
5202 tpSirHostOffloadReq
5203 pHostOffloadParams, bool bArpOnly)
5204{
5205 int32_t i;
5206 int32_t res;
5207 WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param *cmd;
5208 WMI_NS_OFFLOAD_TUPLE *ns_tuple;
5209 WMI_ARP_OFFLOAD_TUPLE *arp_tuple;
5210 A_UINT8 *buf_ptr;
5211 wmi_buf_t buf;
5212 int32_t len;
5213 uint8_t vdev_id;
5214 uint32_t count = 0, num_ns_ext_tuples = 0;
5215
5216 /* Get the vdev id */
Srinivas Girigowdab084b552015-11-24 12:39:12 -08005217 if (!wma_find_vdev_by_bssid(wma, pHostOffloadParams->bssid.bytes,
5218 &vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005219 WMA_LOGE("vdev handle is invalid for %pM",
Srinivas Girigowdab084b552015-11-24 12:39:12 -08005220 pHostOffloadParams->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005221 cdf_mem_free(pHostOffloadParams);
5222 return CDF_STATUS_E_INVAL;
5223 }
5224
5225 if (!wma->interfaces[vdev_id].vdev_up) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005226 WMA_LOGE("vdev %d is not up skipping arp/ns offload", vdev_id);
5227 cdf_mem_free(pHostOffloadParams);
5228 return CDF_STATUS_E_FAILURE;
5229 }
5230
5231 if (!bArpOnly)
5232 count = pHostOffloadParams->num_ns_offload_count;
5233
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005234 len = sizeof(WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param) + WMI_TLV_HDR_SIZE + /* TLV place holder size for array of NS tuples */
5235 WMI_MAX_NS_OFFLOADS * sizeof(WMI_NS_OFFLOAD_TUPLE) + WMI_TLV_HDR_SIZE + /* TLV place holder size for array of ARP tuples */
5236 WMI_MAX_ARP_OFFLOADS * sizeof(WMI_ARP_OFFLOAD_TUPLE);
5237
5238 /*
5239 * If there are more than WMI_MAX_NS_OFFLOADS addresses then allocate
5240 * extra length for extended NS offload tuples which follows ARP offload
5241 * tuples. Host needs to fill this structure in following format:
5242 * 2 NS ofload tuples
5243 * 2 ARP offload tuples
5244 * N numbers of extended NS offload tuples if HDD has given more than
5245 * 2 NS offload addresses
5246 */
5247 if (!bArpOnly && count > WMI_MAX_NS_OFFLOADS) {
5248 num_ns_ext_tuples = count - WMI_MAX_NS_OFFLOADS;
5249 len += WMI_TLV_HDR_SIZE + num_ns_ext_tuples *
5250 sizeof(WMI_NS_OFFLOAD_TUPLE);
5251 }
5252
5253 buf = wmi_buf_alloc(wma->wmi_handle, len);
5254 if (!buf) {
5255 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
5256 cdf_mem_free(pHostOffloadParams);
5257 return CDF_STATUS_E_NOMEM;
5258 }
5259
5260 buf_ptr = (A_UINT8 *) wmi_buf_data(buf);
5261 cmd = (WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param *) buf_ptr;
5262 WMITLV_SET_HDR(&cmd->tlv_header,
5263 WMITLV_TAG_STRUC_WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param,
5264 WMITLV_GET_STRUCT_TLVLEN
5265 (WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param));
5266 cmd->flags = 0;
5267 cmd->vdev_id = vdev_id;
5268 if (!bArpOnly)
5269 cmd->num_ns_ext_tuples = num_ns_ext_tuples;
5270
5271 WMA_LOGD("ARP NS Offload vdev_id: %d", cmd->vdev_id);
5272
5273 /* Have copy of arp info to send along with NS, Since FW expects
5274 * both ARP and NS info in single cmd */
5275 if (bArpOnly)
5276 cdf_mem_copy(&wma->mArpInfo, pHostOffloadParams,
5277 sizeof(tSirHostOffloadReq));
5278
5279 buf_ptr += sizeof(WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param);
5280 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
5281 (WMI_MAX_NS_OFFLOADS * sizeof(WMI_NS_OFFLOAD_TUPLE)));
5282 buf_ptr += WMI_TLV_HDR_SIZE;
5283 for (i = 0; i < WMI_MAX_NS_OFFLOADS; i++) {
5284 ns_tuple = (WMI_NS_OFFLOAD_TUPLE *) buf_ptr;
5285 WMITLV_SET_HDR(&ns_tuple->tlv_header,
5286 WMITLV_TAG_STRUC_WMI_NS_OFFLOAD_TUPLE,
5287 (sizeof(WMI_NS_OFFLOAD_TUPLE) -
5288 WMI_TLV_HDR_SIZE));
5289
5290 /* Fill data only for NS offload in the first ARP tuple for LA */
5291 if (!bArpOnly &&
5292 ((pHostOffloadParams->enableOrDisable & SIR_OFFLOAD_ENABLE))) {
5293 ns_tuple->flags |= WMI_NSOFF_FLAGS_VALID;
5294
5295#ifdef WLAN_NS_OFFLOAD
5296 /*Copy the target/solicitation/remote ip addr */
5297 if (pHostOffloadParams->nsOffloadInfo.
5298 targetIPv6AddrValid[i])
5299 A_MEMCPY(&ns_tuple->target_ipaddr[0],
5300 &pHostOffloadParams->nsOffloadInfo.
5301 targetIPv6Addr[i],
5302 sizeof(WMI_IPV6_ADDR));
5303 A_MEMCPY(&ns_tuple->solicitation_ipaddr,
5304 &pHostOffloadParams->nsOffloadInfo.
5305 selfIPv6Addr[i], sizeof(WMI_IPV6_ADDR));
5306 WMA_LOGD("NS solicitedIp: %pI6, targetIp: %pI6",
5307 &pHostOffloadParams->nsOffloadInfo.selfIPv6Addr[i],
5308 &pHostOffloadParams->nsOffloadInfo.
5309 targetIPv6Addr[i]);
5310
5311 /* target MAC is optional, check if it is valid,
5312 * if this is not valid, the target will use the known
5313 * local MAC address rather than the tuple
5314 */
5315 WMI_CHAR_ARRAY_TO_MAC_ADDR(pHostOffloadParams->
Srinivas Girigowda110d6202015-11-24 12:48:46 -08005316 nsOffloadInfo.self_macaddr.bytes,
5317 &ns_tuple->target_mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005318#endif /* WLAN_NS_OFFLOAD */
5319 if ((ns_tuple->target_mac.mac_addr31to0 != 0) ||
5320 (ns_tuple->target_mac.mac_addr47to32 != 0)) {
5321 ns_tuple->flags |= WMI_NSOFF_FLAGS_MAC_VALID;
5322 }
5323 }
5324 buf_ptr += sizeof(WMI_NS_OFFLOAD_TUPLE);
5325 }
5326
5327 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
5328 (WMI_MAX_ARP_OFFLOADS * sizeof(WMI_ARP_OFFLOAD_TUPLE)));
5329 buf_ptr += WMI_TLV_HDR_SIZE;
5330 for (i = 0; i < WMI_MAX_ARP_OFFLOADS; i++) {
5331 arp_tuple = (WMI_ARP_OFFLOAD_TUPLE *) buf_ptr;
5332 WMITLV_SET_HDR(&arp_tuple->tlv_header,
5333 WMITLV_TAG_STRUC_WMI_ARP_OFFLOAD_TUPLE,
5334 WMITLV_GET_STRUCT_TLVLEN(WMI_ARP_OFFLOAD_TUPLE));
5335
5336 /* Fill data for ARP and NS in the first tupple for LA */
5337 if ((wma->mArpInfo.enableOrDisable & SIR_OFFLOAD_ENABLE)
5338 && (i == 0)) {
5339 /*Copy the target ip addr and flags */
5340 arp_tuple->flags = WMI_ARPOFF_FLAGS_VALID;
5341 A_MEMCPY(&arp_tuple->target_ipaddr,
5342 wma->mArpInfo.params.hostIpv4Addr,
5343 SIR_IPV4_ADDR_LEN);
5344 WMA_LOGD("ARPOffload IP4 address: %pI4",
5345 wma->mArpInfo.params.hostIpv4Addr);
5346 }
5347 buf_ptr += sizeof(WMI_ARP_OFFLOAD_TUPLE);
5348 }
5349
5350 /* Populate extended NS offload tuples */
5351 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
5352 (num_ns_ext_tuples*sizeof(WMI_NS_OFFLOAD_TUPLE)));
5353 buf_ptr += WMI_TLV_HDR_SIZE;
5354
5355 if (num_ns_ext_tuples) {
5356 for (i = WMI_MAX_NS_OFFLOADS; i < count; i++) {
5357 ns_tuple = (WMI_NS_OFFLOAD_TUPLE *)buf_ptr;
5358 WMITLV_SET_HDR(&ns_tuple->tlv_header,
5359 WMITLV_TAG_STRUC_WMI_NS_OFFLOAD_TUPLE,
5360 (sizeof(WMI_NS_OFFLOAD_TUPLE)-WMI_TLV_HDR_SIZE));
5361
5362 /* Fill data only for NS offload in the first ARP tuple for LA */
5363 if (!bArpOnly &&
5364 ((pHostOffloadParams->enableOrDisable & SIR_OFFLOAD_ENABLE))) {
5365 ns_tuple->flags |= WMI_NSOFF_FLAGS_VALID;
5366#ifdef WLAN_NS_OFFLOAD
5367 /*Copy the target/solicitation/remote ip addr */
5368 if (pHostOffloadParams->nsOffloadInfo.targetIPv6AddrValid[i])
5369 A_MEMCPY(&ns_tuple->target_ipaddr[0],
5370 &pHostOffloadParams->nsOffloadInfo.targetIPv6Addr[i],
5371 sizeof(WMI_IPV6_ADDR));
5372 A_MEMCPY(&ns_tuple->solicitation_ipaddr,
5373 &pHostOffloadParams->nsOffloadInfo.selfIPv6Addr[i],
5374 sizeof(WMI_IPV6_ADDR));
5375 WMA_LOGD("Index %d NS solicitedIp: %pI6, targetIp: %pI6", i,
5376 &pHostOffloadParams->nsOffloadInfo.selfIPv6Addr[i],
5377 &pHostOffloadParams->nsOffloadInfo.targetIPv6Addr[i]);
5378
5379 /* target MAC is optional, check if it is valid, if this is not valid,
5380 * the target will use the known local MAC address rather than the tuple */
Srinivas Girigowda110d6202015-11-24 12:48:46 -08005381 WMI_CHAR_ARRAY_TO_MAC_ADDR(
5382 pHostOffloadParams->nsOffloadInfo.self_macaddr.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005383 &ns_tuple->target_mac);
5384#endif
5385 if ((ns_tuple->target_mac.mac_addr31to0 != 0) ||
5386 (ns_tuple->target_mac.mac_addr47to32 != 0)) {
5387 ns_tuple->flags |= WMI_NSOFF_FLAGS_MAC_VALID;
5388 }
5389 }
5390 buf_ptr += sizeof(WMI_NS_OFFLOAD_TUPLE);
5391 }
5392 }
5393
5394 res = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
5395 WMI_SET_ARP_NS_OFFLOAD_CMDID);
5396 if (res) {
5397 WMA_LOGE("Failed to enable ARP NDP/NSffload");
5398 wmi_buf_free(buf);
5399 cdf_mem_free(pHostOffloadParams);
5400 return CDF_STATUS_E_FAILURE;
5401 }
5402
5403 cdf_mem_free(pHostOffloadParams);
5404 return CDF_STATUS_SUCCESS;
5405}
5406
5407/**
5408 * wma_process_add_periodic_tx_ptrn_ind - add periodic tx ptrn
5409 * @handle: wma handle
5410 * @pAddPeriodicTxPtrnParams: tx ptrn params
5411 *
5412 * Retrun: CDF status
5413 */
5414CDF_STATUS wma_process_add_periodic_tx_ptrn_ind(WMA_HANDLE handle,
5415 tSirAddPeriodicTxPtrn *
5416 pAddPeriodicTxPtrnParams)
5417{
5418 tp_wma_handle wma_handle = (tp_wma_handle) handle;
5419 WMI_ADD_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param *cmd;
5420 wmi_buf_t wmi_buf;
5421 uint32_t len;
5422 uint8_t vdev_id;
5423 uint8_t *buf_ptr;
5424 uint32_t ptrn_len, ptrn_len_aligned;
5425 int j;
5426
5427 if (!wma_handle || !wma_handle->wmi_handle) {
5428 WMA_LOGE("%s: WMA is closed, can not issue fw add pattern cmd",
5429 __func__);
5430 return CDF_STATUS_E_INVAL;
5431 }
5432 ptrn_len = pAddPeriodicTxPtrnParams->ucPtrnSize;
5433 ptrn_len_aligned = roundup(ptrn_len, sizeof(uint32_t));
5434 len = sizeof(WMI_ADD_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param) +
5435 WMI_TLV_HDR_SIZE + ptrn_len_aligned;
5436
5437 wmi_buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
5438 if (!wmi_buf) {
5439 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
5440 return CDF_STATUS_E_NOMEM;
5441 }
5442 if (!wma_find_vdev_by_addr(wma_handle,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005443 pAddPeriodicTxPtrnParams->mac_address.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005444 &vdev_id)) {
5445 WMA_LOGE("%s: Failed to find vdev id for %pM", __func__,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005446 pAddPeriodicTxPtrnParams->mac_address.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005447 cdf_nbuf_free(wmi_buf);
5448 return CDF_STATUS_E_INVAL;
5449 }
5450 buf_ptr = (uint8_t *) wmi_buf_data(wmi_buf);
5451
5452 cmd = (WMI_ADD_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param *) buf_ptr;
5453 WMITLV_SET_HDR(&cmd->tlv_header,
5454 WMITLV_TAG_STRUC_WMI_ADD_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param,
5455 WMITLV_GET_STRUCT_TLVLEN
5456 (WMI_ADD_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param));
5457
5458 /* Pass the pattern id to delete for the corresponding vdev id */
5459 cmd->vdev_id = vdev_id;
5460 cmd->pattern_id = pAddPeriodicTxPtrnParams->ucPtrnId;
5461 cmd->timeout = pAddPeriodicTxPtrnParams->usPtrnIntervalMs;
5462 cmd->length = pAddPeriodicTxPtrnParams->ucPtrnSize;
5463
5464 /* Pattern info */
5465 buf_ptr += sizeof(WMI_ADD_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param);
5466 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, ptrn_len_aligned);
5467 buf_ptr += WMI_TLV_HDR_SIZE;
5468 cdf_mem_copy(buf_ptr, pAddPeriodicTxPtrnParams->ucPattern, ptrn_len);
5469 for (j = 0; j < pAddPeriodicTxPtrnParams->ucPtrnSize; j++) {
5470 WMA_LOGD("%s: Add Ptrn: %02x", __func__, buf_ptr[j] & 0xff);
5471 }
5472 WMA_LOGD("%s: Add ptrn id: %d vdev_id: %d",
5473 __func__, cmd->pattern_id, cmd->vdev_id);
5474
5475 if (wmi_unified_cmd_send(wma_handle->wmi_handle, wmi_buf, len,
5476 WMI_ADD_PROACTIVE_ARP_RSP_PATTERN_CMDID)) {
5477 WMA_LOGE("%s: failed to add pattern set state command",
5478 __func__);
5479 cdf_nbuf_free(wmi_buf);
5480 return CDF_STATUS_E_FAILURE;
5481 }
5482 return CDF_STATUS_SUCCESS;
5483}
5484
5485/**
5486 * wma_process_del_periodic_tx_ptrn_ind - del periodic tx ptrn
5487 * @handle: wma handle
5488 * @pDelPeriodicTxPtrnParams: tx ptrn params
5489 *
5490 * Retrun: CDF status
5491 */
5492CDF_STATUS wma_process_del_periodic_tx_ptrn_ind(WMA_HANDLE handle,
5493 tSirDelPeriodicTxPtrn *
5494 pDelPeriodicTxPtrnParams)
5495{
5496 tp_wma_handle wma_handle = (tp_wma_handle) handle;
5497 WMI_DEL_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param *cmd;
5498 wmi_buf_t wmi_buf;
5499 uint8_t vdev_id;
5500 uint32_t len =
5501 sizeof(WMI_DEL_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param);
5502
5503 if (!wma_handle || !wma_handle->wmi_handle) {
5504 WMA_LOGE("%s: WMA is closed, can not issue Del Pattern cmd",
5505 __func__);
5506 return CDF_STATUS_E_INVAL;
5507 }
5508 wmi_buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
5509 if (!wmi_buf) {
5510 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
5511 return CDF_STATUS_E_NOMEM;
5512 }
5513 if (!wma_find_vdev_by_addr(wma_handle,
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08005514 pDelPeriodicTxPtrnParams->mac_address.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005515 &vdev_id)) {
5516 WMA_LOGE("%s: Failed to find vdev id for %pM", __func__,
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08005517 pDelPeriodicTxPtrnParams->mac_address.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005518 cdf_nbuf_free(wmi_buf);
5519 return CDF_STATUS_E_INVAL;
5520 }
5521 cmd = (WMI_DEL_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param *)
5522 wmi_buf_data(wmi_buf);
5523 WMITLV_SET_HDR(&cmd->tlv_header,
5524 WMITLV_TAG_STRUC_WMI_DEL_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param,
5525 WMITLV_GET_STRUCT_TLVLEN
5526 (WMI_DEL_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param));
5527
5528 /* Pass the pattern id to delete for the corresponding vdev id */
5529 cmd->vdev_id = vdev_id;
5530 cmd->pattern_id = pDelPeriodicTxPtrnParams->ucPtrnId;
5531 WMA_LOGD("%s: Del ptrn id: %d vdev_id: %d",
5532 __func__, cmd->pattern_id, cmd->vdev_id);
5533
5534 if (wmi_unified_cmd_send(wma_handle->wmi_handle, wmi_buf, len,
5535 WMI_DEL_PROACTIVE_ARP_RSP_PATTERN_CMDID)) {
5536 WMA_LOGE("%s: failed to send del pattern command", __func__);
5537 cdf_nbuf_free(wmi_buf);
5538 return CDF_STATUS_E_FAILURE;
5539 }
5540 return CDF_STATUS_SUCCESS;
5541}
5542
5543#ifdef WLAN_FEATURE_STATS_EXT
5544/**
5545 * wma_stats_ext_req() - request ext stats from fw
5546 * @wma_ptr: wma handle
5547 * @preq: stats ext params
5548 *
5549 * Return: CDF status
5550 */
5551CDF_STATUS wma_stats_ext_req(void *wma_ptr, tpStatsExtRequest preq)
5552{
5553 int32_t ret;
5554 tp_wma_handle wma = (tp_wma_handle) wma_ptr;
5555 wmi_req_stats_ext_cmd_fixed_param *cmd;
5556 wmi_buf_t buf;
5557 uint16_t len;
5558 uint8_t *buf_ptr;
5559
5560 len = sizeof(*cmd) + WMI_TLV_HDR_SIZE + preq->request_data_len;
5561
5562 buf = wmi_buf_alloc(wma->wmi_handle, len);
5563 if (!buf) {
5564 WMA_LOGE("%s:wmi_buf_alloc failed", __func__);
5565 return -ENOMEM;
5566 }
5567
5568 buf_ptr = (uint8_t *) wmi_buf_data(buf);
5569 cmd = (wmi_req_stats_ext_cmd_fixed_param *) buf_ptr;
5570
5571 WMITLV_SET_HDR(&cmd->tlv_header,
5572 WMITLV_TAG_STRUC_wmi_req_stats_ext_cmd_fixed_param,
5573 WMITLV_GET_STRUCT_TLVLEN
5574 (wmi_req_stats_ext_cmd_fixed_param));
5575 cmd->vdev_id = preq->vdev_id;
5576 cmd->data_len = preq->request_data_len;
5577
5578 WMA_LOGD("%s: The data len value is %u and vdev id set is %u ",
5579 __func__, preq->request_data_len, preq->vdev_id);
5580
5581 buf_ptr += sizeof(wmi_req_stats_ext_cmd_fixed_param);
5582 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, cmd->data_len);
5583
5584 buf_ptr += WMI_TLV_HDR_SIZE;
5585 cdf_mem_copy(buf_ptr, preq->request_data, cmd->data_len);
5586
5587 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
5588 WMI_REQUEST_STATS_EXT_CMDID);
5589 if (ret != EOK) {
5590 WMA_LOGE("%s: Failed to send notify cmd ret = %d", __func__,
5591 ret);
5592 wmi_buf_free(buf);
5593 }
5594
5595 return ret;
5596}
5597
5598#endif /* WLAN_FEATURE_STATS_EXT */
5599
5600#ifdef WLAN_FEATURE_EXTWOW_SUPPORT
5601/**
5602 * wma_send_status_of_ext_wow() - send ext wow status to SME
5603 * @wma: wma handle
5604 * @status: status
5605 *
5606 * Return: none
5607 */
5608static void wma_send_status_of_ext_wow(tp_wma_handle wma, bool status)
5609{
5610 tSirReadyToExtWoWInd *ready_to_extwow;
5611 CDF_STATUS vstatus;
5612 cds_msg_t cds_msg;
5613 uint8_t len;
5614
5615 WMA_LOGD("Posting ready to suspend indication to umac");
5616
5617 len = sizeof(tSirReadyToExtWoWInd);
5618 ready_to_extwow = (tSirReadyToExtWoWInd *) cdf_mem_malloc(len);
5619
5620 if (NULL == ready_to_extwow) {
5621 WMA_LOGE("%s: Memory allocation failure", __func__);
5622 return;
5623 }
5624
5625 ready_to_extwow->mesgType = eWNI_SME_READY_TO_EXTWOW_IND;
5626 ready_to_extwow->mesgLen = len;
5627 ready_to_extwow->status = status;
5628
5629 cds_msg.type = eWNI_SME_READY_TO_EXTWOW_IND;
5630 cds_msg.bodyptr = (void *)ready_to_extwow;
5631 cds_msg.bodyval = 0;
5632
5633 vstatus = cds_mq_post_message(CDS_MQ_ID_SME, &cds_msg);
5634 if (vstatus != CDF_STATUS_SUCCESS) {
5635 WMA_LOGE("Failed to post ready to suspend");
5636 cdf_mem_free(ready_to_extwow);
5637 }
5638}
5639
5640/**
5641 * wma_enable_ext_wow() - enable ext wow in fw
5642 * @wma: wma handle
5643 * @params: ext wow params
5644 *
5645 * Return:0 for success or error code
5646 */
5647int wma_enable_ext_wow(tp_wma_handle wma, tpSirExtWoWParams params)
5648{
5649 wmi_extwow_enable_cmd_fixed_param *cmd;
5650 wmi_buf_t buf;
5651 int32_t len;
5652 int ret;
5653
5654 len = sizeof(wmi_extwow_enable_cmd_fixed_param);
5655 buf = wmi_buf_alloc(wma->wmi_handle, len);
5656 if (!buf) {
5657 WMA_LOGE("%s: Failed allocate wmi buffer", __func__);
5658 return CDF_STATUS_E_NOMEM;
5659 }
5660
5661 cmd = (wmi_extwow_enable_cmd_fixed_param *) wmi_buf_data(buf);
5662
5663 WMITLV_SET_HDR(&cmd->tlv_header,
5664 WMITLV_TAG_STRUC_wmi_extwow_enable_cmd_fixed_param,
5665 WMITLV_GET_STRUCT_TLVLEN
5666 (wmi_extwow_enable_cmd_fixed_param));
5667
5668 cmd->vdev_id = params->vdev_id;
5669 cmd->type = params->type;
5670 cmd->wakeup_pin_num = params->wakeup_pin_num;
5671
5672 WMA_LOGD("%s: vdev_id %d type %d Wakeup_pin_num %x",
5673 __func__, cmd->vdev_id, cmd->type, cmd->wakeup_pin_num);
5674
5675 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
5676 WMI_EXTWOW_ENABLE_CMDID);
5677 if (ret) {
5678 WMA_LOGE("%s: Failed to set EXTWOW Enable", __func__);
5679 wmi_buf_free(buf);
5680 wma_send_status_of_ext_wow(wma, false);
5681 return CDF_STATUS_E_FAILURE;
5682 }
5683
5684 wma_send_status_of_ext_wow(wma, true);
5685 return CDF_STATUS_SUCCESS;
5686
5687}
5688
5689/**
5690 * wma_set_app_type1_params_in_fw() - set app type1 params in fw
5691 * @wma: wma handle
5692 * @appType1Params: app type1 params
5693 *
5694 * Return: CDF status
5695 */
5696int wma_set_app_type1_params_in_fw(tp_wma_handle wma,
5697 tpSirAppType1Params appType1Params)
5698{
5699 wmi_extwow_set_app_type1_params_cmd_fixed_param *cmd;
5700 wmi_buf_t buf;
5701 int32_t len;
5702 int ret;
5703
5704 len = sizeof(wmi_extwow_set_app_type1_params_cmd_fixed_param);
5705 buf = wmi_buf_alloc(wma->wmi_handle, len);
5706 if (!buf) {
5707 WMA_LOGE("%s: Failed allocate wmi buffer", __func__);
5708 return CDF_STATUS_E_NOMEM;
5709 }
5710
5711 cmd = (wmi_extwow_set_app_type1_params_cmd_fixed_param *)
5712 wmi_buf_data(buf);
5713
5714 WMITLV_SET_HDR(&cmd->tlv_header,
5715 WMITLV_TAG_STRUC_wmi_extwow_set_app_type1_params_cmd_fixed_param,
5716 WMITLV_GET_STRUCT_TLVLEN
5717 (wmi_extwow_set_app_type1_params_cmd_fixed_param));
5718
5719 cmd->vdev_id = appType1Params->vdev_id;
Srinivas Girigowda04209912015-11-24 12:11:13 -08005720 WMI_CHAR_ARRAY_TO_MAC_ADDR(appType1Params->wakee_mac_addr.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005721 &cmd->wakee_mac);
5722 cdf_mem_copy(cmd->ident, appType1Params->identification_id, 8);
5723 cmd->ident_len = appType1Params->id_length;
5724 cdf_mem_copy(cmd->passwd, appType1Params->password, 16);
5725 cmd->passwd_len = appType1Params->pass_length;
5726
5727 WMA_LOGD("%s: vdev_id %d wakee_mac_addr %pM "
5728 "identification_id %.8s id_length %u "
5729 "password %.16s pass_length %u",
Srinivas Girigowda04209912015-11-24 12:11:13 -08005730 __func__, cmd->vdev_id, appType1Params->wakee_mac_addr.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005731 cmd->ident, cmd->ident_len, cmd->passwd, cmd->passwd_len);
5732
5733 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
5734 WMI_EXTWOW_SET_APP_TYPE1_PARAMS_CMDID);
5735 if (ret) {
5736 WMA_LOGE("%s: Failed to set APP TYPE1 PARAMS", __func__);
5737 wmi_buf_free(buf);
5738 return CDF_STATUS_E_FAILURE;
5739 }
5740
5741 return CDF_STATUS_SUCCESS;
5742}
5743
5744/**
5745 * wma_set_app_type2_params_in_fw() - set app type2 params in fw
5746 * @wma: wma handle
5747 * @appType2Params: app type2 params
5748 *
5749 * Return: CDF status
5750 */
5751int wma_set_app_type2_params_in_fw(tp_wma_handle wma,
5752 tpSirAppType2Params appType2Params)
5753{
5754 wmi_extwow_set_app_type2_params_cmd_fixed_param *cmd;
5755 wmi_buf_t buf;
5756 int32_t len;
5757 int ret;
5758
5759 len = sizeof(wmi_extwow_set_app_type2_params_cmd_fixed_param);
5760 buf = wmi_buf_alloc(wma->wmi_handle, len);
5761 if (!buf) {
5762 WMA_LOGE("%s: Failed allocate wmi buffer", __func__);
5763 return CDF_STATUS_E_NOMEM;
5764 }
5765
5766 cmd = (wmi_extwow_set_app_type2_params_cmd_fixed_param *)
5767 wmi_buf_data(buf);
5768
5769 WMITLV_SET_HDR(&cmd->tlv_header,
5770 WMITLV_TAG_STRUC_wmi_extwow_set_app_type2_params_cmd_fixed_param,
5771 WMITLV_GET_STRUCT_TLVLEN
5772 (wmi_extwow_set_app_type2_params_cmd_fixed_param));
5773
5774 cmd->vdev_id = appType2Params->vdev_id;
5775
5776 cdf_mem_copy(cmd->rc4_key, appType2Params->rc4_key, 16);
5777 cmd->rc4_key_len = appType2Params->rc4_key_len;
5778
5779 cmd->ip_id = appType2Params->ip_id;
5780 cmd->ip_device_ip = appType2Params->ip_device_ip;
5781 cmd->ip_server_ip = appType2Params->ip_server_ip;
5782
5783 cmd->tcp_src_port = appType2Params->tcp_src_port;
5784 cmd->tcp_dst_port = appType2Params->tcp_dst_port;
5785 cmd->tcp_seq = appType2Params->tcp_seq;
5786 cmd->tcp_ack_seq = appType2Params->tcp_ack_seq;
5787
5788 cmd->keepalive_init = appType2Params->keepalive_init;
5789 cmd->keepalive_min = appType2Params->keepalive_min;
5790 cmd->keepalive_max = appType2Params->keepalive_max;
5791 cmd->keepalive_inc = appType2Params->keepalive_inc;
5792
Srinivas Girigowda04209912015-11-24 12:11:13 -08005793 WMI_CHAR_ARRAY_TO_MAC_ADDR(appType2Params->gateway_mac.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005794 &cmd->gateway_mac);
5795 cmd->tcp_tx_timeout_val = appType2Params->tcp_tx_timeout_val;
5796 cmd->tcp_rx_timeout_val = appType2Params->tcp_rx_timeout_val;
5797
5798 WMA_LOGD("%s: vdev_id %d gateway_mac %pM "
5799 "rc4_key %.16s rc4_key_len %u "
5800 "ip_id %x ip_device_ip %x ip_server_ip %x "
5801 "tcp_src_port %u tcp_dst_port %u tcp_seq %u "
5802 "tcp_ack_seq %u keepalive_init %u keepalive_min %u "
5803 "keepalive_max %u keepalive_inc %u "
5804 "tcp_tx_timeout_val %u tcp_rx_timeout_val %u",
Srinivas Girigowda04209912015-11-24 12:11:13 -08005805 __func__, cmd->vdev_id, appType2Params->gateway_mac.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005806 cmd->rc4_key, cmd->rc4_key_len,
5807 cmd->ip_id, cmd->ip_device_ip, cmd->ip_server_ip,
5808 cmd->tcp_src_port, cmd->tcp_dst_port, cmd->tcp_seq,
5809 cmd->tcp_ack_seq, cmd->keepalive_init, cmd->keepalive_min,
5810 cmd->keepalive_max, cmd->keepalive_inc,
5811 cmd->tcp_tx_timeout_val, cmd->tcp_rx_timeout_val);
5812
5813 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
5814 WMI_EXTWOW_SET_APP_TYPE2_PARAMS_CMDID);
5815 if (ret) {
5816 WMA_LOGE("%s: Failed to set APP TYPE2 PARAMS", __func__);
5817 wmi_buf_free(buf);
5818 return CDF_STATUS_E_FAILURE;
5819 }
5820
5821 return CDF_STATUS_SUCCESS;
5822
5823}
5824#endif /* WLAN_FEATURE_EXTWOW_SUPPORT */
5825
5826#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
5827/**
5828 * wma_auto_shutdown_event_handler() - process auto shutdown timer trigger
5829 * @handle: wma handle
5830 * @event: event buffer
5831 * @len: buffer length
5832 *
5833 * Return: 0 for success or error code
5834 */
5835int wma_auto_shutdown_event_handler(void *handle, uint8_t *event,
5836 uint32_t len)
5837{
5838 wmi_host_auto_shutdown_event_fixed_param *wmi_auto_sh_evt;
5839 WMI_HOST_AUTO_SHUTDOWN_EVENTID_param_tlvs *param_buf =
5840 (WMI_HOST_AUTO_SHUTDOWN_EVENTID_param_tlvs *)
5841 event;
5842
5843 if (!param_buf || !param_buf->fixed_param) {
5844 WMA_LOGE("%s:%d: Invalid Auto shutdown timer evt", __func__,
5845 __LINE__);
5846 return -EINVAL;
5847 }
5848
5849 wmi_auto_sh_evt = param_buf->fixed_param;
5850
5851 if (wmi_auto_sh_evt->shutdown_reason
5852 != WMI_HOST_AUTO_SHUTDOWN_REASON_TIMER_EXPIRY) {
5853 WMA_LOGE("%s:%d: Invalid Auto shutdown timer evt", __func__,
5854 __LINE__);
5855 return -EINVAL;
5856 }
5857
5858 WMA_LOGD("%s:%d: Auto Shutdown Evt: %d", __func__, __LINE__,
5859 wmi_auto_sh_evt->shutdown_reason);
5860 return wma_post_auto_shutdown_msg();
5861}
5862
5863/**
5864 * wma_set_auto_shutdown_timer_req() - sets auto shutdown timer in firmware
5865 * @wma: wma handle
5866 * @auto_sh_cmd: auto shutdown timer value
5867 *
5868 * Return: CDF status
5869 */
5870CDF_STATUS wma_set_auto_shutdown_timer_req(tp_wma_handle wma_handle,
5871 tSirAutoShutdownCmdParams *
5872 auto_sh_cmd)
5873{
5874 int status = 0;
5875 wmi_buf_t buf = NULL;
5876 uint8_t *buf_ptr;
5877 wmi_host_auto_shutdown_cfg_cmd_fixed_param *wmi_auto_sh_cmd;
5878 int len = sizeof(wmi_host_auto_shutdown_cfg_cmd_fixed_param);
5879
5880 if (auto_sh_cmd == NULL) {
5881 WMA_LOGE("%s : Invalid Autoshutdown cfg cmd", __func__);
5882 return CDF_STATUS_E_FAILURE;
5883 }
5884
5885 WMA_LOGD("%s: Set WMI_HOST_AUTO_SHUTDOWN_CFG_CMDID:TIMER_VAL=%d",
5886 __func__, auto_sh_cmd->timer_val);
5887
5888 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
5889 if (!buf) {
5890 WMA_LOGE("%s : wmi_buf_alloc failed", __func__);
5891 return CDF_STATUS_E_NOMEM;
5892 }
5893
5894 buf_ptr = (uint8_t *) wmi_buf_data(buf);
5895 wmi_auto_sh_cmd =
5896 (wmi_host_auto_shutdown_cfg_cmd_fixed_param *) buf_ptr;
5897 wmi_auto_sh_cmd->timer_value = auto_sh_cmd->timer_val;
5898
5899 WMITLV_SET_HDR(&wmi_auto_sh_cmd->tlv_header,
5900 WMITLV_TAG_STRUC_wmi_host_auto_shutdown_cfg_cmd_fixed_param,
5901 WMITLV_GET_STRUCT_TLVLEN
5902 (wmi_host_auto_shutdown_cfg_cmd_fixed_param));
5903
5904 status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf,
5905 len, WMI_HOST_AUTO_SHUTDOWN_CFG_CMDID);
5906 if (status != EOK) {
5907 WMA_LOGE("%s: WMI_HOST_AUTO_SHUTDOWN_CFG_CMDID Err %d",
5908 __func__, status);
5909 wmi_buf_free(buf);
5910 return CDF_STATUS_E_FAILURE;
5911 }
5912
5913 return CDF_STATUS_SUCCESS;
5914}
5915#endif /* FEATURE_WLAN_AUTO_SHUTDOWN */
5916
5917#ifdef WLAN_FEATURE_NAN
5918/**
5919 * wma_nan_req() - to send nan request to target
5920 * @wma: wma_handle
5921 * @nan_req: request data which will be non-null
5922 *
5923 * Return: CDF status
5924 */
5925CDF_STATUS wma_nan_req(void *wma_ptr, tpNanRequest nan_req)
5926{
5927 int ret;
5928 tp_wma_handle wma_handle = (tp_wma_handle) wma_ptr;
5929 wmi_nan_cmd_param *cmd;
5930 wmi_buf_t buf;
5931 uint16_t len = sizeof(*cmd);
5932 uint16_t nan_data_len, nan_data_len_aligned;
5933 uint8_t *buf_ptr;
5934
5935 /*
5936 * <----- cmd ------------><-- WMI_TLV_HDR_SIZE --><--- data ---->
5937 * +------------+----------+-----------------------+--------------+
5938 * | tlv_header | data_len | WMITLV_TAG_ARRAY_BYTE | nan_req_data |
5939 * +------------+----------+-----------------------+--------------+
5940 */
5941 if (!nan_req) {
5942 WMA_LOGE("%s:nan req is not valid", __func__);
5943 return CDF_STATUS_E_FAILURE;
5944 }
5945 nan_data_len = nan_req->request_data_len;
5946 nan_data_len_aligned = roundup(nan_req->request_data_len,
5947 sizeof(uint32_t));
5948 len += WMI_TLV_HDR_SIZE + nan_data_len_aligned;
5949 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
5950 if (!buf) {
5951 WMA_LOGE("%s:wmi_buf_alloc failed", __func__);
5952 return CDF_STATUS_E_NOMEM;
5953 }
5954 buf_ptr = (uint8_t *) wmi_buf_data(buf);
5955 cmd = (wmi_nan_cmd_param *) buf_ptr;
5956 WMITLV_SET_HDR(&cmd->tlv_header,
5957 WMITLV_TAG_STRUC_wmi_nan_cmd_param,
5958 WMITLV_GET_STRUCT_TLVLEN(wmi_nan_cmd_param));
5959 cmd->data_len = nan_req->request_data_len;
5960 WMA_LOGD("%s: The data len value is %u",
5961 __func__, nan_req->request_data_len);
5962 buf_ptr += sizeof(wmi_nan_cmd_param);
5963 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, nan_data_len_aligned);
5964 buf_ptr += WMI_TLV_HDR_SIZE;
5965 cdf_mem_copy(buf_ptr, nan_req->request_data, cmd->data_len);
5966
5967 ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len,
5968 WMI_NAN_CMDID);
5969 if (ret != EOK) {
5970 WMA_LOGE("%s Failed to send set param command ret = %d",
5971 __func__, ret);
5972 wmi_buf_free(buf);
5973 }
5974 return ret;
5975}
5976#endif /* WLAN_FEATURE_NAN */
5977
5978#ifdef DHCP_SERVER_OFFLOAD
5979/**
5980 * wma_process_dhcpserver_offload() - enable DHCP server offload
5981 * @wma_handle: wma handle
5982 * @pDhcpSrvOffloadInfo: DHCP server offload info
5983 *
5984 * Return: 0 for success or error code
5985 */
5986int wma_process_dhcpserver_offload(tp_wma_handle wma_handle,
5987 tSirDhcpSrvOffloadInfo *
5988 pDhcpSrvOffloadInfo)
5989{
5990 wmi_set_dhcp_server_offload_cmd_fixed_param *cmd;
5991 wmi_buf_t buf;
5992 int err;
5993
5994 buf = wmi_buf_alloc(wma_handle->wmi_handle, sizeof(*cmd));
5995 if (!buf) {
5996 WMA_LOGE("Failed to allocate buffer to send "
5997 "set_dhcp_server_offload cmd");
5998 return -ENOMEM;
5999 }
6000
6001 cmd = (wmi_set_dhcp_server_offload_cmd_fixed_param *) wmi_buf_data(buf);
6002 cdf_mem_zero(cmd, sizeof(*cmd));
6003
6004 WMITLV_SET_HDR(&cmd->tlv_header,
6005 WMITLV_TAG_STRUC_wmi_set_dhcp_server_offload_cmd_fixed_param,
6006 WMITLV_GET_STRUCT_TLVLEN
6007 (wmi_set_dhcp_server_offload_cmd_fixed_param));
6008 cmd->vdev_id = pDhcpSrvOffloadInfo->vdev_id;
6009 cmd->enable = pDhcpSrvOffloadInfo->dhcpSrvOffloadEnabled;
6010 cmd->num_client = pDhcpSrvOffloadInfo->dhcpClientNum;
6011 cmd->srv_ipv4 = pDhcpSrvOffloadInfo->dhcpSrvIP;
6012 cmd->start_lsb = 0;
6013 err = wmi_unified_cmd_send(wma_handle->wmi_handle, buf,
6014 sizeof(*cmd),
6015 WMI_SET_DHCP_SERVER_OFFLOAD_CMDID);
6016 if (err) {
6017 WMA_LOGE("Failed to send set_dhcp_server_offload cmd");
6018 wmi_buf_free(buf);
6019 return -EIO;
6020 }
6021 WMA_LOGD("Set dhcp server offload to vdevId %d",
6022 pDhcpSrvOffloadInfo->vdev_id);
6023 return 0;
6024}
6025#endif /* DHCP_SERVER_OFFLOAD */
6026
6027#ifdef WLAN_FEATURE_GPIO_LED_FLASHING
6028/**
6029 * wma_set_led_flashing() - set led flashing in fw
6030 * @wma_handle: wma handle
6031 * @flashing: flashing request
6032 *
6033 * Return: CDF status
6034 */
6035CDF_STATUS wma_set_led_flashing(tp_wma_handle wma_handle,
6036 tSirLedFlashingReq *flashing)
6037{
6038 wmi_set_led_flashing_cmd_fixed_param *cmd;
6039 int status = 0;
6040 wmi_buf_t buf;
6041 uint8_t *buf_ptr;
6042 int32_t len = sizeof(wmi_set_led_flashing_cmd_fixed_param);
6043
6044 if (!wma_handle || !wma_handle->wmi_handle) {
6045 WMA_LOGE(FL("WMA is closed, can not issue cmd"));
6046 return CDF_STATUS_E_INVAL;
6047 }
6048 if (!flashing) {
6049 WMA_LOGE(FL("invalid parameter: flashing"));
6050 return CDF_STATUS_E_INVAL;
6051 }
6052
6053 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
6054 if (!buf) {
6055 WMA_LOGP(FL("wmi_buf_alloc failed"));
6056 return -ENOMEM;
6057 }
6058 buf_ptr = (uint8_t *) wmi_buf_data(buf);
6059 cmd = (wmi_set_led_flashing_cmd_fixed_param *) buf_ptr;
6060 WMITLV_SET_HDR(&cmd->tlv_header,
6061 WMITLV_TAG_STRUC_wmi_set_led_flashing_cmd_fixed_param,
6062 WMITLV_GET_STRUCT_TLVLEN
6063 (wmi_set_led_flashing_cmd_fixed_param));
6064 cmd->pattern_id = flashing->pattern_id;
6065 cmd->led_x0 = flashing->led_x0;
6066 cmd->led_x1 = flashing->led_x1;
6067
6068 status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len,
6069 WMI_PDEV_SET_LED_FLASHING_CMDID);
6070 if (status != EOK) {
6071 WMA_LOGE("%s: wmi_unified_cmd_send WMI_PEER_SET_PARAM_CMD"
6072 " returned Error %d", __func__, status);
6073 return CDF_STATUS_E_FAILURE;
6074 }
6075 return CDF_STATUS_SUCCESS;
6076}
6077#endif /* WLAN_FEATURE_GPIO_LED_FLASHING */
6078
6079#ifdef FEATURE_WLAN_CH_AVOID
6080/**
6081 * wma_channel_avoid_evt_handler() - process channel to avoid event from FW.
6082 * @handle: wma handle
6083 * @event: event buffer
6084 * @len: buffer length
6085 *
6086 * Return: 0 for success or error code
6087 */
6088int wma_channel_avoid_evt_handler(void *handle, uint8_t *event,
6089 uint32_t len)
6090{
6091 wmi_avoid_freq_ranges_event_fixed_param *afr_fixed_param;
6092 wmi_avoid_freq_range_desc *afr_desc;
6093 uint32_t num_freq_ranges, freq_range_idx;
6094 tSirChAvoidIndType *sca_indication;
6095 CDF_STATUS cdf_status;
6096 cds_msg_t sme_msg = { 0 };
6097 WMI_WLAN_FREQ_AVOID_EVENTID_param_tlvs *param_buf =
6098 (WMI_WLAN_FREQ_AVOID_EVENTID_param_tlvs *) event;
6099
6100 if (!param_buf) {
6101 WMA_LOGE("Invalid channel avoid event buffer");
6102 return -EINVAL;
6103 }
6104
6105 afr_fixed_param = param_buf->fixed_param;
6106 if (!afr_fixed_param) {
6107 WMA_LOGE("Invalid channel avoid event fixed param buffer");
6108 return -EINVAL;
6109 }
6110
6111 num_freq_ranges =
6112 (afr_fixed_param->num_freq_ranges >
6113 SIR_CH_AVOID_MAX_RANGE) ? SIR_CH_AVOID_MAX_RANGE :
6114 afr_fixed_param->num_freq_ranges;
6115
6116 WMA_LOGD("Channel avoid event received with %d ranges",
6117 num_freq_ranges);
6118 for (freq_range_idx = 0; freq_range_idx < num_freq_ranges;
6119 freq_range_idx++) {
6120 afr_desc = (wmi_avoid_freq_range_desc *)
6121 ((void *)param_buf->avd_freq_range +
6122 freq_range_idx * sizeof(wmi_avoid_freq_range_desc));
6123
6124 WMA_LOGD("range %d: tlv id = %u, start freq = %u, end freq = %u",
6125 freq_range_idx, afr_desc->tlv_header, afr_desc->start_freq,
6126 afr_desc->end_freq);
6127 }
6128
6129 sca_indication = (tSirChAvoidIndType *)
6130 cdf_mem_malloc(sizeof(tSirChAvoidIndType));
6131 if (!sca_indication) {
6132 WMA_LOGE("Invalid channel avoid indication buffer");
6133 return -EINVAL;
6134 }
6135
6136 sca_indication->avoid_range_count = num_freq_ranges;
6137 for (freq_range_idx = 0; freq_range_idx < num_freq_ranges;
6138 freq_range_idx++) {
6139 afr_desc = (wmi_avoid_freq_range_desc *)
6140 ((void *)param_buf->avd_freq_range +
6141 freq_range_idx * sizeof(wmi_avoid_freq_range_desc));
6142 sca_indication->avoid_freq_range[freq_range_idx].start_freq =
6143 afr_desc->start_freq;
6144 sca_indication->avoid_freq_range[freq_range_idx].end_freq =
6145 afr_desc->end_freq;
6146 }
6147
6148 sme_msg.type = eWNI_SME_CH_AVOID_IND;
6149 sme_msg.bodyptr = sca_indication;
6150 sme_msg.bodyval = 0;
6151
6152 cdf_status = cds_mq_post_message(CDF_MODULE_ID_SME, &sme_msg);
6153 if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
6154 WMA_LOGE("Fail to post eWNI_SME_CH_AVOID_IND msg to SME");
6155 cdf_mem_free(sca_indication);
6156 return -EINVAL;
6157 }
6158
6159 return 0;
6160}
6161
6162/**
6163 * wma_process_ch_avoid_update_req() - handles channel avoid update request
6164 * @wma_handle: wma handle
6165 * @ch_avoid_update_req: channel avoid update params
6166 *
6167 * Return: CDF status
6168 */
6169CDF_STATUS wma_process_ch_avoid_update_req(tp_wma_handle wma_handle,
6170 tSirChAvoidUpdateReq *
6171 ch_avoid_update_req)
6172{
6173 int status = 0;
6174 wmi_buf_t buf = NULL;
6175 uint8_t *buf_ptr;
6176 wmi_chan_avoid_update_cmd_param *ch_avoid_update_fp;
6177 int len = sizeof(wmi_chan_avoid_update_cmd_param);
6178
6179 if (ch_avoid_update_req == NULL) {
6180 WMA_LOGE("%s : ch_avoid_update_req is NULL", __func__);
6181 return CDF_STATUS_E_FAILURE;
6182 }
6183
6184 WMA_LOGI("%s: WMA --> WMI_CHAN_AVOID_UPDATE", __func__);
6185
6186 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
6187 if (!buf) {
6188 WMA_LOGE("%s : wmi_buf_alloc failed", __func__);
6189 return CDF_STATUS_E_NOMEM;
6190 }
6191
6192 buf_ptr = (uint8_t *) wmi_buf_data(buf);
6193 ch_avoid_update_fp = (wmi_chan_avoid_update_cmd_param *) buf_ptr;
6194 WMITLV_SET_HDR(&ch_avoid_update_fp->tlv_header,
6195 WMITLV_TAG_STRUC_wmi_chan_avoid_update_cmd_param,
6196 WMITLV_GET_STRUCT_TLVLEN
6197 (wmi_chan_avoid_update_cmd_param));
6198
6199 status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf,
6200 len, WMI_CHAN_AVOID_UPDATE_CMDID);
6201 if (status != EOK) {
6202 WMA_LOGE("wmi_unified_cmd_send"
6203 " WMITLV_TABLE_WMI_CHAN_AVOID_UPDATE"
6204 " returned Error %d", status);
6205 wmi_buf_free(buf);
6206 return CDF_STATUS_E_FAILURE;
6207 }
6208
6209 WMA_LOGI("%s: WMA --> WMI_CHAN_AVOID_UPDATE sent through WMI",
6210 __func__);
6211 return CDF_STATUS_SUCCESS;
6212}
6213#endif /* FEATURE_WLAN_CH_AVOID */
6214
6215/**
6216 * wma_set_reg_domain() - set reg domain
6217 * @clientCtxt: client context
6218 * @regId: reg id
6219 *
6220 * Return: CDF status
6221 */
6222CDF_STATUS wma_set_reg_domain(void *clientCtxt, v_REGDOMAIN_t regId)
6223{
6224 if (CDF_STATUS_SUCCESS !=
6225 cds_set_reg_domain(clientCtxt, regId))
6226 return CDF_STATUS_E_INVAL;
6227
6228 return CDF_STATUS_SUCCESS;
6229}
6230
6231/**
6232 * wma_send_regdomain_info_to_fw() - send regdomain info to fw
6233 * @reg_dmn: reg domain
6234 * @regdmn2G: 2G reg domain
6235 * @regdmn5G: 5G reg domain
6236 * @ctl2G: 2G test limit
6237 * @ctl5G: 5G test limit
6238 *
6239 * Return: none
6240 */
6241void wma_send_regdomain_info_to_fw(uint32_t reg_dmn, uint16_t regdmn2G,
6242 uint16_t regdmn5G, int8_t ctl2G,
6243 int8_t ctl5G)
6244{
6245 wmi_buf_t buf;
6246 wmi_pdev_set_regdomain_cmd_fixed_param *cmd;
6247 int32_t len = sizeof(*cmd);
6248 tp_wma_handle wma = cds_get_context(CDF_MODULE_ID_WMA);
6249 int32_t cck_mask_val = 0;
6250 int ret = 0;
6251
6252 if (NULL == wma) {
6253 WMA_LOGE("%s: wma context is NULL", __func__);
6254 return;
6255 }
6256
6257 buf = wmi_buf_alloc(wma->wmi_handle, len);
6258 if (!buf) {
6259 WMA_LOGP("%s: wmi_buf_alloc failed", __func__);
6260 return;
6261 }
6262 cmd = (wmi_pdev_set_regdomain_cmd_fixed_param *) wmi_buf_data(buf);
6263 WMITLV_SET_HDR(&cmd->tlv_header,
6264 WMITLV_TAG_STRUC_wmi_pdev_set_regdomain_cmd_fixed_param,
6265 WMITLV_GET_STRUCT_TLVLEN
6266 (wmi_pdev_set_regdomain_cmd_fixed_param));
6267 cmd->reg_domain = reg_dmn;
6268 cmd->reg_domain_2G = regdmn2G;
6269 cmd->reg_domain_5G = regdmn5G;
6270 cmd->conformance_test_limit_2G = ctl2G;
6271 cmd->conformance_test_limit_5G = ctl5G;
6272
6273 if (wmi_unified_cmd_send(wma->wmi_handle, buf, len,
6274 WMI_PDEV_SET_REGDOMAIN_CMDID)) {
6275 WMA_LOGP("%s: Failed to send pdev set regdomain command",
6276 __func__);
6277 cdf_nbuf_free(buf);
6278 }
6279
6280 if ((((reg_dmn & ~COUNTRY_ERD_FLAG) == CTRY_JAPAN) ||
6281 ((reg_dmn & ~COUNTRY_ERD_FLAG) == CTRY_KOREA_ROC)) &&
6282 (true == wma->tx_chain_mask_cck))
6283 cck_mask_val = 1;
6284
6285 cck_mask_val |= (wma->self_gen_frm_pwr << 16);
6286 ret = wmi_unified_pdev_set_param(wma->wmi_handle,
6287 WMI_PDEV_PARAM_TX_CHAIN_MASK_CCK,
6288 cck_mask_val);
6289 if (ret)
6290 WMA_LOGE("failed to set PDEV tx_chain_mask_cck %d",
6291 ret);
6292
6293 return;
6294}
6295
6296/**
Houston Hoffmana76591b2015-11-10 16:52:05 -08006297 * wma_post_runtime_resume_msg() - post the resume request
6298 * @handle: validated wma handle
6299 *
6300 * request the MC thread unpaus the vdev and set resume dtim
6301 *
6302 * Return: cdf status of the mq post
6303 */
6304static CDF_STATUS wma_post_runtime_resume_msg(WMA_HANDLE handle)
6305{
6306 cds_msg_t resume_msg;
6307
6308 resume_msg.bodyptr = NULL;
6309 resume_msg.type = WMA_RUNTIME_PM_RESUME_IND;
6310 return cds_mq_post_message(CDF_MODULE_ID_WMA, &resume_msg);
6311}
6312
6313/**
6314 * wma_post_runtime_suspend_msg() - post the suspend request
6315 * @handle: validated wma handle
6316 *
6317 * Requests for offloads to be configured for runtime suspend
6318 * on the MC thread
6319 *
6320 * Return CDF_STATUS_E_AGAIN in case of timeout or CDF_STATUS_SUCCESS
6321 */
6322static CDF_STATUS wma_post_runtime_suspend_msg(WMA_HANDLE handle)
6323{
6324 cds_msg_t cds_msg;
6325 CDF_STATUS cdf_status;
6326 tp_wma_handle wma = (tp_wma_handle) handle;
6327
6328 cdf_event_reset(&wma->runtime_suspend);
6329
6330 cds_msg.bodyptr = NULL;
6331 cds_msg.type = WMA_RUNTIME_PM_SUSPEND_IND;
6332 cdf_status = cds_mq_post_message(CDF_MODULE_ID_WMA, &cds_msg);
6333
6334 if (cdf_status != CDF_STATUS_SUCCESS)
6335 goto failure;
6336
6337 if (cdf_wait_single_event(&wma->runtime_suspend,
6338 WMA_TGT_SUSPEND_COMPLETE_TIMEOUT) !=
6339 CDF_STATUS_SUCCESS) {
6340 WMA_LOGE("Failed to get runtime suspend event");
6341 goto failure;
6342 }
6343
6344 return CDF_STATUS_SUCCESS;
6345
6346failure:
6347 return CDF_STATUS_E_AGAIN;
6348}
6349
6350/**
6351 * __wma_bus_suspend(): handles bus suspend for wma
6352 * @type: is this suspend part of runtime suspend or system suspend?
6353 *
6354 * Bails if a scan is in progress.
6355 * Calls the appropriate handlers based on configuration and event.
6356 *
6357 * Return: 0 for success or error code
6358 */
6359static int __wma_bus_suspend(enum cdf_suspend_type type)
6360{
6361 WMA_HANDLE handle = cds_get_context(CDF_MODULE_ID_WMA);
6362 if (NULL == handle) {
6363 WMA_LOGE("%s: wma context is NULL", __func__);
6364 return -EFAULT;
6365 }
6366
6367 if (wma_check_scan_in_progress(handle)) {
6368 WMA_LOGE("%s: Scan in progress. Aborting suspend", __func__);
6369 return -EBUSY;
6370 }
6371
6372 if (type == CDF_RUNTIME_SUSPEND) {
6373 CDF_STATUS status = wma_post_runtime_suspend_msg(handle);
6374 if (status)
6375 return cdf_status_to_os_return(status);
6376 }
6377
6378 if (type == CDF_SYSTEM_SUSPEND)
6379 WMA_LOGE("%s: wow mode selected %d", __func__,
6380 wma_is_wow_mode_selected(handle));
6381
6382 if (wma_is_wow_mode_selected(handle)) {
6383 CDF_STATUS status = wma_enable_wow_in_fw(handle);
6384 return cdf_status_to_os_return(status);
6385 }
6386
6387 return wma_suspend_target(handle, 0);
6388}
6389
6390/**
6391 * wma_runtime_suspend() - handles runtime suspend request from hdd
6392 *
6393 * Calls the appropriate handler based on configuration and event.
6394 * Last busy marking should prevent race conditions between processing
6395 * of asyncronous fw events and the running of runtime suspend.
6396 * (eg. last busy marking should guarantee that any auth requests have
6397 * been processed)
6398 * Events comming from the host are not protected, but aren't expected
6399 * to be an issue.
6400 *
6401 * Return: 0 for success or error code
6402 */
6403int wma_runtime_suspend(void)
6404{
6405 return __wma_bus_suspend(CDF_RUNTIME_SUSPEND);
6406}
6407
6408/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006409 * wma_bus_suspend() - handles bus suspend request from hdd
6410 *
6411 * Calls the appropriate handler based on configuration and event
6412 *
6413 * Return: 0 for success or error code
6414 */
6415int wma_bus_suspend(void)
6416{
Houston Hoffmana76591b2015-11-10 16:52:05 -08006417
6418 return __wma_bus_suspend(CDF_RUNTIME_SUSPEND);
6419}
6420
6421/**
6422 * __wma_bus_resume() - bus resume for wma
6423 *
6424 * does the part of the bus resume common to bus and system suspend
6425 *
6426 * Return: os error code.
6427 */
6428int __wma_bus_resume(WMA_HANDLE handle)
6429{
6430 bool wow_mode = wma_is_wow_mode_selected(handle);
6431 CDF_STATUS status;
6432
6433 WMA_LOGE("%s: wow mode %d", __func__, wow_mode);
6434
6435 if (!wow_mode)
6436 return wma_resume_target(handle);
6437
6438 status = wma_disable_wow_in_fw(handle);
6439 return cdf_status_to_os_return(status);
6440}
6441
6442/**
6443 * wma_runtime_resume() - do the runtime resume operation for wma
6444 *
6445 * Return: os error code.
6446 */
6447int wma_runtime_resume(void)
6448{
6449 int ret;
6450 CDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006451 WMA_HANDLE handle = cds_get_context(CDF_MODULE_ID_WMA);
6452 if (NULL == handle) {
6453 WMA_LOGE("%s: wma context is NULL", __func__);
6454 return -EFAULT;
6455 }
6456
Houston Hoffmana76591b2015-11-10 16:52:05 -08006457 ret = __wma_bus_resume(handle);
6458 if (ret)
6459 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006460
Houston Hoffmana76591b2015-11-10 16:52:05 -08006461 status = wma_post_runtime_resume_msg(handle);
6462 return cdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006463}
6464
6465/**
6466 * wma_bus_resume() - handles bus resume request from hdd
6467 * @handle: valid wma handle
6468 *
6469 * Calls the appropriate handler based on configuration
6470 *
6471 * Return: 0 for success or error code
6472 */
6473int wma_bus_resume(void)
6474{
6475 WMA_HANDLE handle = cds_get_context(CDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006476 if (NULL == handle) {
6477 WMA_LOGE("%s: wma context is NULL", __func__);
6478 return -EFAULT;
6479 }
6480
Houston Hoffmana76591b2015-11-10 16:52:05 -08006481 return __wma_bus_resume(handle);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006482}
6483
6484/**
6485 * wma_suspend_target() - suspend target
6486 * @handle: wma handle
6487 * @disable_target_intr: disable target interrupt
6488 *
6489 * Return: 0 for success or error code
6490 */
6491int wma_suspend_target(WMA_HANDLE handle, int disable_target_intr)
6492{
6493 tp_wma_handle wma_handle = (tp_wma_handle) handle;
6494 wmi_pdev_suspend_cmd_fixed_param *cmd;
6495 wmi_buf_t wmibuf;
6496 uint32_t len = sizeof(*cmd);
6497 struct ol_softc *scn;
6498 int ret;
Yue Mae1a85f32015-10-20 18:12:45 -07006499#ifdef CONFIG_CNSS
6500 tpAniSirGlobal pmac = cds_get_context(CDF_MODULE_ID_PE);
6501#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006502
6503 if (!wma_handle || !wma_handle->wmi_handle) {
6504 WMA_LOGE("WMA is closed. can not issue suspend cmd");
6505 return -EINVAL;
6506 }
Yue Mae1a85f32015-10-20 18:12:45 -07006507
6508#ifdef CONFIG_CNSS
6509 if (NULL == pmac) {
6510 WMA_LOGE("%s: Unable to get PE context", __func__);
6511 return -EINVAL;
6512 }
6513#endif
6514
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006515 /*
6516 * send the comand to Target to ignore the
6517 * PCIE reset so as to ensure that Host and target
6518 * states are in sync
6519 */
6520 wmibuf = wmi_buf_alloc(wma_handle->wmi_handle, len);
6521 if (wmibuf == NULL)
6522 return -ENOMEM;
6523
6524 cmd = (wmi_pdev_suspend_cmd_fixed_param *) wmi_buf_data(wmibuf);
6525 WMITLV_SET_HDR(&cmd->tlv_header,
6526 WMITLV_TAG_STRUC_wmi_pdev_suspend_cmd_fixed_param,
6527 WMITLV_GET_STRUCT_TLVLEN
6528 (wmi_pdev_suspend_cmd_fixed_param));
6529 if (disable_target_intr) {
6530 cmd->suspend_opt = WMI_PDEV_SUSPEND_AND_DISABLE_INTR;
6531 } else {
6532 cmd->suspend_opt = WMI_PDEV_SUSPEND;
6533 }
6534 cdf_event_reset(&wma_handle->target_suspend);
6535 ret = wmi_unified_cmd_send(wma_handle->wmi_handle, wmibuf, len,
6536 WMI_PDEV_SUSPEND_CMDID);
6537 if (ret < 0) {
6538 cdf_nbuf_free(wmibuf);
6539 return ret;
6540 }
6541
6542 wmi_set_target_suspend(wma_handle->wmi_handle, true);
6543
6544 if (cdf_wait_single_event(&wma_handle->target_suspend,
6545 WMA_TGT_SUSPEND_COMPLETE_TIMEOUT)
6546 != CDF_STATUS_SUCCESS) {
6547 WMA_LOGE("Failed to get ACK from firmware for pdev suspend");
6548 wmi_set_target_suspend(wma_handle->wmi_handle, false);
Yue Mae1a85f32015-10-20 18:12:45 -07006549#ifdef CONFIG_CNSS
Prashanth Bhatta9e143052015-12-04 11:56:47 -08006550 if (!cds_is_driver_recovering()) {
Yue Ma455aff62015-10-20 18:29:16 -07006551 if (pmac->sme.enableSelfRecovery) {
6552 cds_trigger_recovery();
6553 } else {
6554 CDF_BUG(0);
6555 }
Yue Mae1a85f32015-10-20 18:12:45 -07006556 } else {
Yue Ma455aff62015-10-20 18:29:16 -07006557 WMA_LOGE("%s: LOGP is in progress, ignore!", __func__);
Yue Mae1a85f32015-10-20 18:12:45 -07006558 }
6559#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006560 return -EFAULT;
6561 }
6562
6563 scn = cds_get_context(CDF_MODULE_ID_HIF);
6564
6565 if (scn == NULL) {
6566 WMA_LOGE("%s: Failed to get HIF context", __func__);
6567 CDF_ASSERT(0);
6568 return -EFAULT;
6569 }
6570
6571 htc_cancel_deferred_target_sleep(scn);
6572
6573 return 0;
6574}
6575
6576/**
6577 * wma_target_suspend_acknowledge() - update target susspend status
6578 * @context: wma context
6579 *
6580 * Return: none
6581 */
6582void wma_target_suspend_acknowledge(void *context)
6583{
6584 tp_wma_handle wma = cds_get_context(CDF_MODULE_ID_WMA);
6585 int wow_nack = *((int *)context);
6586
6587 if (NULL == wma) {
6588 WMA_LOGE("%s: wma is NULL", __func__);
6589 return;
6590 }
6591
6592 wma->wow_nack = wow_nack;
6593 cdf_event_set(&wma->target_suspend);
6594 if (wow_nack)
6595 cdf_wake_lock_timeout_acquire(&wma->wow_wake_lock,
6596 WMA_WAKE_LOCK_TIMEOUT,
6597 WIFI_POWER_EVENT_WAKELOCK_WOW);
6598}
6599
6600/**
6601 * wma_resume_target() - resume target
6602 * @handle: wma handle
6603 *
6604 * Return: 0 for success or error code
6605 */
6606int wma_resume_target(WMA_HANDLE handle)
6607{
6608 int ret;
6609 tp_wma_handle wma = (tp_wma_handle) handle;
6610 wmi_buf_t wmibuf;
6611 wmi_pdev_resume_cmd_fixed_param *cmd;
6612 CDF_STATUS cdf_status = CDF_STATUS_SUCCESS;
6613#ifdef CONFIG_CNSS
6614 tpAniSirGlobal pMac = cds_get_context(CDF_MODULE_ID_PE);
6615 if (NULL == pMac) {
6616 WMA_LOGE("%s: Unable to get PE context", __func__);
6617 return -EINVAL;
6618 }
6619#endif /* CONFIG_CNSS */
6620
6621 wmibuf = wmi_buf_alloc(wma->wmi_handle, sizeof(*cmd));
6622 if (wmibuf == NULL) {
6623 return -ENOMEM;
6624 }
6625 cmd = (wmi_pdev_resume_cmd_fixed_param *) wmi_buf_data(wmibuf);
6626 WMITLV_SET_HDR(&cmd->tlv_header,
6627 WMITLV_TAG_STRUC_wmi_pdev_resume_cmd_fixed_param,
6628 WMITLV_GET_STRUCT_TLVLEN
6629 (wmi_pdev_resume_cmd_fixed_param));
6630 cmd->reserved0 = 0;
6631 cdf_event_reset(&wma->wma_resume_event);
6632 ret = wmi_unified_cmd_send(wma->wmi_handle, wmibuf, sizeof(*cmd),
6633 WMI_PDEV_RESUME_CMDID);
6634 if (ret != EOK) {
6635 WMA_LOGE("Failed to send WMI_PDEV_RESUME_CMDID command");
6636 wmi_buf_free(wmibuf);
6637 }
6638
6639 cdf_status = cdf_wait_single_event(&(wma->wma_resume_event),
6640 WMA_RESUME_TIMEOUT);
6641 if (CDF_STATUS_SUCCESS != cdf_status) {
6642 WMA_LOGP("%s: Timeout waiting for resume event from FW",
6643 __func__);
6644 WMA_LOGP("%s: Pending commands %d credits %d", __func__,
6645 wmi_get_pending_cmds(wma->wmi_handle),
6646 wmi_get_host_credits(wma->wmi_handle));
Prashanth Bhatta9e143052015-12-04 11:56:47 -08006647 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006648#ifdef CONFIG_CNSS
6649 if (pMac->sme.enableSelfRecovery) {
6650 cds_trigger_recovery();
6651 } else {
6652 CDF_BUG(0);
6653 }
6654#else
6655 CDF_BUG(0);
6656#endif /* CONFIG_CNSS */
6657 } else {
6658 WMA_LOGE("%s: SSR in progress, ignore resume timeout",
6659 __func__);
6660 }
6661 } else {
6662 WMA_LOGD("Host wakeup received");
6663 }
6664
6665 if (CDF_STATUS_SUCCESS == cdf_status)
6666 wmi_set_target_suspend(wma->wmi_handle, false);
6667
6668 return ret;
6669}
6670
6671/**
6672 * wma_get_modeselect() - get modeSelect flag based on phy_capability
6673 * @wma: wma handle
6674 * @modeSelect: mode Select
6675 *
6676 * Return: none
6677 */
6678void wma_get_modeselect(tp_wma_handle wma, uint32_t *modeSelect)
6679{
6680
6681 switch (wma->phy_capability) {
6682 case WMI_11G_CAPABILITY:
6683 case WMI_11NG_CAPABILITY:
6684 *modeSelect &= ~(REGDMN_MODE_11A | REGDMN_MODE_TURBO |
6685 REGDMN_MODE_108A | REGDMN_MODE_11A_HALF_RATE |
6686 REGDMN_MODE_11A_QUARTER_RATE |
6687 REGDMN_MODE_11NA_HT20 |
6688 REGDMN_MODE_11NA_HT40PLUS |
6689 REGDMN_MODE_11NA_HT40MINUS |
6690 REGDMN_MODE_11AC_VHT20 |
6691 REGDMN_MODE_11AC_VHT40PLUS |
6692 REGDMN_MODE_11AC_VHT40MINUS |
6693 REGDMN_MODE_11AC_VHT80);
6694 break;
6695 case WMI_11A_CAPABILITY:
6696 case WMI_11NA_CAPABILITY:
6697 case WMI_11AC_CAPABILITY:
6698 *modeSelect &= ~(REGDMN_MODE_11B | REGDMN_MODE_11G |
6699 REGDMN_MODE_108G | REGDMN_MODE_11NG_HT20 |
6700 REGDMN_MODE_11NG_HT40PLUS |
6701 REGDMN_MODE_11NG_HT40MINUS |
6702 REGDMN_MODE_11AC_VHT20_2G |
6703 REGDMN_MODE_11AC_VHT40_2G |
6704 REGDMN_MODE_11AC_VHT80_2G);
6705 break;
6706 }
6707}
6708
6709
6710#ifdef FEATURE_WLAN_TDLS
6711/**
6712 * wma_tdls_event_handler() - handle TDLS event
6713 * @handle: wma handle
6714 * @event: event buffer
6715 * @len: buffer length
6716 *
6717 * Return: 0 for success or error code
6718 */
6719int wma_tdls_event_handler(void *handle, uint8_t *event, uint32_t len)
6720{
6721 tp_wma_handle wma = (tp_wma_handle) handle;
6722 WMI_TDLS_PEER_EVENTID_param_tlvs *param_buf = NULL;
6723 wmi_tdls_peer_event_fixed_param *peer_event = NULL;
6724 tSirTdlsEventnotify *tdls_event;
6725
6726 if (!event) {
6727 WMA_LOGE("%s: event param null", __func__);
6728 return -EINVAL;
6729 }
6730
6731 param_buf = (WMI_TDLS_PEER_EVENTID_param_tlvs *) event;
6732 if (!param_buf) {
6733 WMA_LOGE("%s: received null buf from target", __func__);
6734 return -EINVAL;
6735 }
6736
6737 peer_event = param_buf->fixed_param;
6738 if (!peer_event) {
6739 WMA_LOGE("%s: received null event data from target", __func__);
6740 return -EINVAL;
6741 }
6742
6743 tdls_event = (tSirTdlsEventnotify *)
6744 cdf_mem_malloc(sizeof(*tdls_event));
6745 if (!tdls_event) {
6746 WMA_LOGE("%s: failed to allocate memory for tdls_event",
6747 __func__);
6748 return -ENOMEM;
6749 }
6750
6751 tdls_event->sessionId = peer_event->vdev_id;
6752 WMI_MAC_ADDR_TO_CHAR_ARRAY(&peer_event->peer_macaddr,
Srinivas Girigowda4f593792015-11-19 15:33:42 -08006753 tdls_event->peermac.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006754
6755 switch (peer_event->peer_status) {
6756 case WMI_TDLS_SHOULD_DISCOVER:
6757 tdls_event->messageType = WMA_TDLS_SHOULD_DISCOVER_CMD;
6758 break;
6759 case WMI_TDLS_SHOULD_TEARDOWN:
6760 tdls_event->messageType = WMA_TDLS_SHOULD_TEARDOWN_CMD;
6761 break;
6762 case WMI_TDLS_PEER_DISCONNECTED:
6763 tdls_event->messageType = WMA_TDLS_PEER_DISCONNECTED_CMD;
6764 break;
6765 default:
6766 WMA_LOGE("%s: Discarding unknown tdls event(%d) from target",
6767 __func__, peer_event->peer_status);
6768 return -EINVAL;
6769 }
6770
6771 switch (peer_event->peer_reason) {
6772 case WMI_TDLS_TEARDOWN_REASON_TX:
6773 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_TX;
6774 break;
6775 case WMI_TDLS_TEARDOWN_REASON_RSSI:
6776 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_RSSI;
6777 break;
6778 case WMI_TDLS_TEARDOWN_REASON_SCAN:
6779 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_SCAN;
6780 break;
6781 case WMI_TDLS_DISCONNECTED_REASON_PEER_DELETE:
6782 tdls_event->peer_reason =
6783 eWNI_TDLS_DISCONNECTED_REASON_PEER_DELETE;
6784 break;
6785 case WMI_TDLS_TEARDOWN_REASON_PTR_TIMEOUT:
6786 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_PTR_TIMEOUT;
6787 break;
6788 case WMI_TDLS_TEARDOWN_REASON_BAD_PTR:
6789 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_BAD_PTR;
6790 break;
6791 case WMI_TDLS_TEARDOWN_REASON_NO_RESPONSE:
6792 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_NO_RESPONSE;
6793 break;
6794 default:
6795 WMA_LOGE("%s: unknown reason(%d) in tdls event(%d) from target",
6796 __func__, peer_event->peer_reason,
6797 peer_event->peer_status);
6798 return -EINVAL;
6799 }
6800
6801 WMA_LOGD("%s: sending msg to umac, messageType: 0x%x, "
6802 "for peer: %pM, reason: %d, smesessionId: %d",
Srinivas Girigowda4f593792015-11-19 15:33:42 -08006803 __func__, tdls_event->messageType, tdls_event->peermac.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006804 tdls_event->peer_reason, tdls_event->sessionId);
6805
6806 wma_send_msg(wma, tdls_event->messageType, (void *)tdls_event, 0);
6807 return 0;
6808}
6809
6810/**
6811 * wma_set_tdls_offchan_mode() - set tdls off channel mode
6812 * @handle: wma handle
6813 * @chan_switch_params: Pointer to tdls channel switch parameter structure
6814 *
6815 * This function sets tdls off channel mode
6816 *
6817 * Return: 0 on success; Negative errno otherwise
6818 */
6819int wma_set_tdls_offchan_mode(WMA_HANDLE handle,
6820 tdls_chan_switch_params *chan_switch_params)
6821{
6822 tp_wma_handle wma_handle = (tp_wma_handle) handle;
6823 wmi_tdls_set_offchan_mode_cmd_fixed_param *cmd;
6824 wmi_buf_t wmi_buf;
6825 u_int16_t len = sizeof(wmi_tdls_set_offchan_mode_cmd_fixed_param);
6826 int ret = 0;
6827
6828 if (!wma_handle || !wma_handle->wmi_handle) {
6829 WMA_LOGE(FL(
6830 "WMA is closed, can not issue tdls off channel cmd"
6831 ));
6832 ret = -EINVAL;
6833 goto end;
6834 }
6835 wmi_buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
6836 if (!wmi_buf) {
6837 WMA_LOGE(FL("wmi_buf_alloc failed"));
6838 ret = -ENOMEM;
6839 goto end;
6840 }
6841 cmd = (wmi_tdls_set_offchan_mode_cmd_fixed_param *)
6842 wmi_buf_data(wmi_buf);
6843 WMITLV_SET_HDR(&cmd->tlv_header,
6844 WMITLV_TAG_STRUC_wmi_tdls_set_offchan_mode_cmd_fixed_param,
6845 WMITLV_GET_STRUCT_TLVLEN(
6846 wmi_tdls_set_offchan_mode_cmd_fixed_param));
6847
6848 WMI_CHAR_ARRAY_TO_MAC_ADDR(chan_switch_params->peer_mac_addr,
6849 &cmd->peer_macaddr);
6850 cmd->vdev_id = chan_switch_params->vdev_id;
6851 cmd->offchan_mode = chan_switch_params->tdls_sw_mode;
6852 cmd->is_peer_responder = chan_switch_params->is_responder;
6853 cmd->offchan_num = chan_switch_params->tdls_off_ch;
6854 cmd->offchan_bw_bitmap = chan_switch_params->tdls_off_ch_bw_offset;
6855 cmd->offchan_oper_class = chan_switch_params->oper_class;
6856
6857 WMA_LOGD(FL("Peer MAC Addr mac_addr31to0: 0x%x, mac_addr47to32: 0x%x"),
6858 cmd->peer_macaddr.mac_addr31to0,
6859 cmd->peer_macaddr.mac_addr47to32);
6860
6861 WMA_LOGD(FL(
6862 "vdev_id: %d, off channel mode: %d, off channel Num: %d, off channel offset: 0x%x, is_peer_responder: %d, operating class: %d"
6863 ),
6864 cmd->vdev_id,
6865 cmd->offchan_mode,
6866 cmd->offchan_num,
6867 cmd->offchan_bw_bitmap,
6868 cmd->is_peer_responder,
6869 cmd->offchan_oper_class);
6870
6871 if (wmi_unified_cmd_send(wma_handle->wmi_handle, wmi_buf, len,
6872 WMI_TDLS_SET_OFFCHAN_MODE_CMDID)) {
6873 WMA_LOGP(FL("failed to send tdls off chan command"));
6874 cdf_nbuf_free(wmi_buf);
6875 ret = -EIO;
6876 }
6877
6878end:
6879 if (chan_switch_params)
6880 cdf_mem_free(chan_switch_params);
6881 return ret;
6882}
6883
6884/**
6885 * wma_update_fw_tdls_state() - send enable/disable tdls for a vdev
6886 * @wma: wma handle
6887 * @pwmaTdlsparams: TDLS params
6888 *
6889 * Return: 0 for sucess or error code
6890 */
6891int wma_update_fw_tdls_state(WMA_HANDLE handle, void *pwmaTdlsparams)
6892{
6893 tp_wma_handle wma_handle = (tp_wma_handle) handle;
6894 wmi_tdls_set_state_cmd_fixed_param *cmd;
6895 wmi_buf_t wmi_buf;
6896 t_wma_tdls_mode tdls_mode;
6897 t_wma_tdls_params *wma_tdls = (t_wma_tdls_params *) pwmaTdlsparams;
6898 uint16_t len = sizeof(wmi_tdls_set_state_cmd_fixed_param);
6899 int ret = 0;
6900
6901 if (!wma_handle || !wma_handle->wmi_handle) {
6902 WMA_LOGE("%s: WMA is closed, can not issue fw tdls state cmd",
6903 __func__);
6904 ret = -EINVAL;
6905 goto end_fw_tdls_state;
6906 }
6907
6908 wmi_buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
6909 if (!wmi_buf) {
6910 WMA_LOGE("%s: wmai_buf_alloc failed", __func__);
6911 ret = ENOMEM;
6912 goto end_fw_tdls_state;
6913 }
6914 tdls_mode = wma_tdls->tdls_state;
6915 cmd = (wmi_tdls_set_state_cmd_fixed_param *) wmi_buf_data(wmi_buf);
6916 WMITLV_SET_HDR(&cmd->tlv_header,
6917 WMITLV_TAG_STRUC_wmi_tdls_set_state_cmd_fixed_param,
6918 WMITLV_GET_STRUCT_TLVLEN
6919 (wmi_tdls_set_state_cmd_fixed_param));
6920 cmd->vdev_id = wma_tdls->vdev_id;
6921
6922 if (WMA_TDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY == tdls_mode) {
6923 cmd->state = WMI_TDLS_ENABLE_PASSIVE;
6924 } else if (WMA_TDLS_SUPPORT_ENABLED == tdls_mode) {
6925 cmd->state = WMI_TDLS_ENABLE_ACTIVE;
Kabilan Kannan421714b2015-11-23 04:44:59 -08006926 } else if (WMA_TDLS_SUPPORT_ACTIVE_EXTERNAL_CONTROL == tdls_mode) {
6927 cmd->state = WMI_TDLS_ENABLE_ACTIVE_EXTERNAL_CONTROL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006928 } else {
6929 cmd->state = WMI_TDLS_DISABLE;
6930 }
6931
6932 cmd->notification_interval_ms = wma_tdls->notification_interval_ms;
6933 cmd->tx_discovery_threshold = wma_tdls->tx_discovery_threshold;
6934 cmd->tx_teardown_threshold = wma_tdls->tx_teardown_threshold;
6935 cmd->rssi_teardown_threshold = wma_tdls->rssi_teardown_threshold;
6936 cmd->rssi_delta = wma_tdls->rssi_delta;
6937 cmd->tdls_options = wma_tdls->tdls_options;
6938 cmd->tdls_peer_traffic_ind_window = wma_tdls->peer_traffic_ind_window;
6939 cmd->tdls_peer_traffic_response_timeout_ms =
6940 wma_tdls->peer_traffic_response_timeout;
6941 cmd->tdls_puapsd_mask = wma_tdls->puapsd_mask;
6942 cmd->tdls_puapsd_inactivity_time_ms = wma_tdls->puapsd_inactivity_time;
6943 cmd->tdls_puapsd_rx_frame_threshold =
6944 wma_tdls->puapsd_rx_frame_threshold;
Kabilan Kannanca670be2015-11-23 01:56:12 -08006945 cmd->teardown_notification_ms =
6946 wma_tdls->teardown_notification_ms;
Kabilan Kannan421714b2015-11-23 04:44:59 -08006947 cmd->tdls_peer_kickout_threshold =
6948 wma_tdls->tdls_peer_kickout_threshold;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006949
6950 WMA_LOGD("%s: tdls_mode: %d, state: %d, "
6951 "notification_interval_ms: %d, "
6952 "tx_discovery_threshold: %d, "
6953 "tx_teardown_threshold: %d, "
6954 "rssi_teardown_threshold: %d, "
6955 "rssi_delta: %d, "
6956 "tdls_options: 0x%x, "
6957 "tdls_peer_traffic_ind_window: %d, "
6958 "tdls_peer_traffic_response_timeout: %d, "
6959 "tdls_puapsd_mask: 0x%x, "
6960 "tdls_puapsd_inactivity_time: %d, "
Kabilan Kannanca670be2015-11-23 01:56:12 -08006961 "tdls_puapsd_rx_frame_threshold: %d, "
Kabilan Kannan421714b2015-11-23 04:44:59 -08006962 "teardown_notification_ms: %d, "
6963 "tdls_peer_kickout_threshold: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006964 __func__, tdls_mode, cmd->state,
6965 cmd->notification_interval_ms,
6966 cmd->tx_discovery_threshold,
6967 cmd->tx_teardown_threshold,
6968 cmd->rssi_teardown_threshold,
6969 cmd->rssi_delta,
6970 cmd->tdls_options,
6971 cmd->tdls_peer_traffic_ind_window,
6972 cmd->tdls_peer_traffic_response_timeout_ms,
6973 cmd->tdls_puapsd_mask,
6974 cmd->tdls_puapsd_inactivity_time_ms,
Kabilan Kannanca670be2015-11-23 01:56:12 -08006975 cmd->tdls_puapsd_rx_frame_threshold,
Kabilan Kannan421714b2015-11-23 04:44:59 -08006976 cmd->teardown_notification_ms,
6977 cmd->tdls_peer_kickout_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006978
6979 if (wmi_unified_cmd_send(wma_handle->wmi_handle, wmi_buf, len,
6980 WMI_TDLS_SET_STATE_CMDID)) {
6981 WMA_LOGP("%s: failed to send tdls set state command", __func__);
6982 cdf_nbuf_free(wmi_buf);
6983 ret = -EIO;
6984 goto end_fw_tdls_state;
6985 }
6986 WMA_LOGD("%s: vdev_id %d", __func__, wma_tdls->vdev_id);
6987
6988end_fw_tdls_state:
6989 if (pwmaTdlsparams)
6990 cdf_mem_free(pwmaTdlsparams);
6991 return ret;
6992}
6993
6994/**
6995 * wma_update_tdls_peer_state() - update TDLS peer state
6996 * @handle: wma handle
6997 * @peerStateParams: TDLS peer state params
6998 *
6999 * Return: 0 for success or error code
7000 */
7001int wma_update_tdls_peer_state(WMA_HANDLE handle,
7002 tTdlsPeerStateParams *peerStateParams)
7003{
7004 tp_wma_handle wma_handle = (tp_wma_handle) handle;
7005 wmi_tdls_peer_update_cmd_fixed_param *cmd;
7006 wmi_tdls_peer_capabilities *peer_cap;
7007 wmi_channel *chan_info;
7008 wmi_buf_t wmi_buf;
7009 uint8_t *buf_ptr;
7010 uint32_t i;
7011 ol_txrx_pdev_handle pdev;
7012 uint8_t peer_id;
7013 struct ol_txrx_peer_t *peer;
7014 int32_t len = sizeof(wmi_tdls_peer_update_cmd_fixed_param) +
7015 sizeof(wmi_tdls_peer_capabilities);
7016 int ret = 0;
7017
7018 if (!wma_handle || !wma_handle->wmi_handle) {
7019 WMA_LOGE("%s: WMA is closed, can not issue cmd", __func__);
7020 ret = -EINVAL;
7021 goto end_tdls_peer_state;
7022 }
7023
7024 /* peer capability info is valid only when peer state is connected */
7025 if (WMA_TDLS_PEER_STATE_CONNECTED != peerStateParams->peerState) {
7026 cdf_mem_zero(&peerStateParams->peerCap,
7027 sizeof(tTdlsPeerCapParams));
7028 }
7029
7030 len += WMI_TLV_HDR_SIZE +
7031 sizeof(wmi_channel) * peerStateParams->peerCap.peerChanLen;
7032
7033 wmi_buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
7034 if (!wmi_buf) {
7035 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
7036 ret = ENOMEM;
7037 goto end_tdls_peer_state;
7038 }
7039
7040 buf_ptr = (uint8_t *) wmi_buf_data(wmi_buf);
7041 cmd = (wmi_tdls_peer_update_cmd_fixed_param *) buf_ptr;
7042 WMITLV_SET_HDR(&cmd->tlv_header,
7043 WMITLV_TAG_STRUC_wmi_tdls_peer_update_cmd_fixed_param,
7044 WMITLV_GET_STRUCT_TLVLEN
7045 (wmi_tdls_peer_update_cmd_fixed_param));
7046
7047 cmd->vdev_id = peerStateParams->vdevId;
7048 WMI_CHAR_ARRAY_TO_MAC_ADDR(peerStateParams->peerMacAddr,
7049 &cmd->peer_macaddr);
7050
7051 switch (peerStateParams->peerState) {
7052 case WMA_TDLS_PEER_STATE_PEERING:
7053 cmd->peer_state = WMI_TDLS_PEER_STATE_PEERING;
7054 break;
7055 case WMA_TDLS_PEER_STATE_CONNECTED:
7056 cmd->peer_state = WMI_TDLS_PEER_STATE_CONNECTED;
7057 break;
7058 case WMA_TDLS_PEER_STATE_TEARDOWN:
7059 cmd->peer_state = WMI_TDLS_PEER_STATE_TEARDOWN;
7060 break;
Kabilan Kannan421714b2015-11-23 04:44:59 -08007061 case WMA_TDLS_PEER_ADD_MAC_ADDR:
7062 cmd->peer_state = WMI_TDLS_PEER_ADD_MAC_ADDR;
7063 break;
7064 case WMA_TDLS_PEER_REMOVE_MAC_ADDR:
7065 cmd->peer_state = WMI_TDLS_PEER_REMOVE_MAC_ADDR;
7066 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007067 }
7068
7069 WMA_LOGD("%s: vdev_id: %d, peerStateParams->peerMacAddr: %pM, "
7070 "peer_macaddr.mac_addr31to0: 0x%x, "
7071 "peer_macaddr.mac_addr47to32: 0x%x, peer_state: %d",
7072 __func__, cmd->vdev_id, peerStateParams->peerMacAddr,
7073 cmd->peer_macaddr.mac_addr31to0,
7074 cmd->peer_macaddr.mac_addr47to32, cmd->peer_state);
7075
7076 buf_ptr += sizeof(wmi_tdls_peer_update_cmd_fixed_param);
7077 peer_cap = (wmi_tdls_peer_capabilities *) buf_ptr;
7078 WMITLV_SET_HDR(&peer_cap->tlv_header,
7079 WMITLV_TAG_STRUC_wmi_tdls_peer_capabilities,
7080 WMITLV_GET_STRUCT_TLVLEN(wmi_tdls_peer_capabilities));
7081
7082 if ((peerStateParams->peerCap.peerUapsdQueue & 0x08) >> 3)
7083 WMI_SET_TDLS_PEER_VO_UAPSD(peer_cap);
7084 if ((peerStateParams->peerCap.peerUapsdQueue & 0x04) >> 2)
7085 WMI_SET_TDLS_PEER_VI_UAPSD(peer_cap);
7086 if ((peerStateParams->peerCap.peerUapsdQueue & 0x02) >> 1)
7087 WMI_SET_TDLS_PEER_BK_UAPSD(peer_cap);
7088 if (peerStateParams->peerCap.peerUapsdQueue & 0x01)
7089 WMI_SET_TDLS_PEER_BE_UAPSD(peer_cap);
7090
7091 /* Ack and More Data Ack are sent as 0, so no need to set
7092 * but fill SP
7093 */
7094 WMI_SET_TDLS_PEER_SP_UAPSD(peer_cap,
7095 peerStateParams->peerCap.peerMaxSp);
7096
7097 peer_cap->buff_sta_support =
7098 peerStateParams->peerCap.peerBuffStaSupport;
7099 peer_cap->off_chan_support =
7100 peerStateParams->peerCap.peerOffChanSupport;
7101 peer_cap->peer_curr_operclass =
7102 peerStateParams->peerCap.peerCurrOperClass;
7103 /* self curr operclass is not being used and so pass op class for
7104 * preferred off chan in it.
7105 */
7106 peer_cap->self_curr_operclass =
7107 peerStateParams->peerCap.opClassForPrefOffChan;
7108 peer_cap->peer_chan_len = peerStateParams->peerCap.peerChanLen;
7109 peer_cap->peer_operclass_len =
7110 peerStateParams->peerCap.peerOperClassLen;
7111
7112 WMA_LOGD("%s: peer_operclass_len: %d",
7113 __func__, peer_cap->peer_operclass_len);
7114 for (i = 0; i < WMI_TDLS_MAX_SUPP_OPER_CLASSES; i++) {
7115 peer_cap->peer_operclass[i] =
7116 peerStateParams->peerCap.peerOperClass[i];
7117 WMA_LOGD("%s: peer_operclass[%d]: %d",
7118 __func__, i, peer_cap->peer_operclass[i]);
7119 }
7120
7121 peer_cap->is_peer_responder = peerStateParams->peerCap.isPeerResponder;
7122 peer_cap->pref_offchan_num = peerStateParams->peerCap.prefOffChanNum;
7123 peer_cap->pref_offchan_bw =
7124 peerStateParams->peerCap.prefOffChanBandwidth;
7125
7126 WMA_LOGD
7127 ("%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",
7128 __func__, peer_cap->peer_qos, peer_cap->buff_sta_support,
7129 peer_cap->off_chan_support, peer_cap->peer_curr_operclass,
7130 peer_cap->self_curr_operclass, peer_cap->peer_chan_len,
7131 peer_cap->peer_operclass_len, peer_cap->is_peer_responder,
7132 peer_cap->pref_offchan_num, peer_cap->pref_offchan_bw);
7133
7134 /* next fill variable size array of peer chan info */
7135 buf_ptr += sizeof(wmi_tdls_peer_capabilities);
7136 WMITLV_SET_HDR(buf_ptr,
7137 WMITLV_TAG_ARRAY_STRUC,
7138 sizeof(wmi_channel) *
7139 peerStateParams->peerCap.peerChanLen);
7140 chan_info = (wmi_channel *) (buf_ptr + WMI_TLV_HDR_SIZE);
7141
7142 for (i = 0; i < peerStateParams->peerCap.peerChanLen; ++i) {
7143 WMITLV_SET_HDR(&chan_info->tlv_header,
7144 WMITLV_TAG_STRUC_wmi_channel,
7145 WMITLV_GET_STRUCT_TLVLEN(wmi_channel));
7146 chan_info->mhz =
7147 cds_chan_to_freq(peerStateParams->peerCap.peerChan[i].
7148 chanId);
7149 chan_info->band_center_freq1 = chan_info->mhz;
7150 chan_info->band_center_freq2 = 0;
7151
7152 WMA_LOGD("%s: chan[%d] = %u", __func__, i, chan_info->mhz);
7153
7154 if (peerStateParams->peerCap.peerChan[i].dfsSet) {
7155 WMI_SET_CHANNEL_FLAG(chan_info, WMI_CHAN_FLAG_PASSIVE);
7156 WMA_LOGI("chan[%d] DFS[%d]\n",
7157 peerStateParams->peerCap.peerChan[i].chanId,
7158 peerStateParams->peerCap.peerChan[i].dfsSet);
7159 }
7160
7161 if (chan_info->mhz < WMA_2_4_GHZ_MAX_FREQ) {
7162 WMI_SET_CHANNEL_MODE(chan_info, MODE_11G);
7163 } else {
7164 WMI_SET_CHANNEL_MODE(chan_info, MODE_11A);
7165 }
7166
7167 WMI_SET_CHANNEL_MAX_TX_POWER(chan_info,
7168 peerStateParams->peerCap.
7169 peerChan[i].pwr);
7170
7171 WMI_SET_CHANNEL_REG_POWER(chan_info,
7172 peerStateParams->peerCap.peerChan[i].
7173 pwr);
7174 WMA_LOGD("Channel TX power[%d] = %u: %d", i, chan_info->mhz,
7175 peerStateParams->peerCap.peerChan[i].pwr);
7176
7177 chan_info++;
7178 }
7179
7180 if (wmi_unified_cmd_send(wma_handle->wmi_handle, wmi_buf, len,
7181 WMI_TDLS_PEER_UPDATE_CMDID)) {
7182 WMA_LOGE("%s: failed to send tdls peer update state command",
7183 __func__);
7184 cdf_nbuf_free(wmi_buf);
7185 ret = -EIO;
7186 goto end_tdls_peer_state;
7187 }
7188
7189 /* in case of teardown, remove peer from fw */
7190 if (WMA_TDLS_PEER_STATE_TEARDOWN == peerStateParams->peerState) {
7191 pdev = cds_get_context(CDF_MODULE_ID_TXRX);
7192 if (!pdev) {
7193 WMA_LOGE("%s: Failed to find pdev", __func__);
7194 ret = -EIO;
7195 goto end_tdls_peer_state;
7196 }
7197
7198 peer = ol_txrx_find_peer_by_addr(pdev,
7199 peerStateParams->peerMacAddr,
7200 &peer_id);
7201 if (!peer) {
7202 WMA_LOGE("%s: Failed to get peer handle using peer mac %pM",
7203 __func__, peerStateParams->peerMacAddr);
7204 ret = -EIO;
7205 goto end_tdls_peer_state;
7206 }
7207
7208 WMA_LOGD("%s: calling wma_remove_peer for peer " MAC_ADDRESS_STR
7209 " vdevId: %d", __func__,
7210 MAC_ADDR_ARRAY(peer->mac_addr.raw),
7211 peerStateParams->vdevId);
7212 wma_remove_peer(wma_handle, peer->mac_addr.raw,
7213 peerStateParams->vdevId, peer, false);
7214 }
7215
7216end_tdls_peer_state:
7217 if (peerStateParams)
7218 cdf_mem_free(peerStateParams);
7219 return ret;
7220}
7221#endif /* FEATURE_WLAN_TDLS */
7222
7223
7224/**
7225 * wma_dfs_attach() - Attach DFS methods to the umac state.
7226 * @dfs_ic: ieee80211com ptr
7227 *
7228 * Return: Return ieee80211com ptr with updated info
7229 */
7230struct ieee80211com *wma_dfs_attach(struct ieee80211com *dfs_ic)
7231{
7232 /*Allocate memory for dfs_ic before passing it up to dfs_attach() */
7233 dfs_ic = (struct ieee80211com *)
7234 os_malloc(NULL, sizeof(struct ieee80211com), GFP_ATOMIC);
7235 if (dfs_ic == NULL) {
7236 WMA_LOGE("%s:Allocation of dfs_ic failed %zu",
7237 __func__, sizeof(struct ieee80211com));
7238 return NULL;
7239 }
7240 OS_MEMZERO(dfs_ic, sizeof(struct ieee80211com));
7241 /* DFS pattern matching hooks */
7242 dfs_ic->ic_dfs_attach = ol_if_dfs_attach;
7243 dfs_ic->ic_dfs_disable = ol_if_dfs_disable;
7244 dfs_ic->ic_find_channel = ieee80211_find_channel;
7245 dfs_ic->ic_dfs_enable = ol_if_dfs_enable;
7246 dfs_ic->ic_ieee2mhz = ieee80211_ieee2mhz;
7247
7248 /* Hardware facing hooks */
7249 dfs_ic->ic_get_ext_busy = ol_if_dfs_get_ext_busy;
7250 dfs_ic->ic_get_mib_cycle_counts_pct =
7251 ol_if_dfs_get_mib_cycle_counts_pct;
7252 dfs_ic->ic_get_TSF64 = ol_if_get_tsf64;
7253
7254 /* NOL related hooks */
7255 dfs_ic->ic_dfs_usenol = ol_if_dfs_usenol;
7256 /*
7257 * Hooks from wma/dfs/ back
7258 * into the PE/SME
7259 * and shared DFS code
7260 */
7261 dfs_ic->ic_dfs_notify_radar = ieee80211_mark_dfs;
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05307262 cdf_spinlock_init(&dfs_ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007263 /* Initializes DFS Data Structures and queues */
7264 dfs_attach(dfs_ic);
7265
7266 return dfs_ic;
7267}
7268
7269/**
7270 * wma_dfs_detach() - Detach DFS methods
7271 * @dfs_ic: ieee80211com ptr
7272 *
7273 * Return: none
7274 */
7275void wma_dfs_detach(struct ieee80211com *dfs_ic)
7276{
7277 dfs_detach(dfs_ic);
7278
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05307279 cdf_spinlock_destroy(&dfs_ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007280 if (NULL != dfs_ic->ic_curchan) {
7281 OS_FREE(dfs_ic->ic_curchan);
7282 dfs_ic->ic_curchan = NULL;
7283 }
7284
7285 OS_FREE(dfs_ic);
7286}
7287
7288/**
7289 * wma_dfs_configure() - configure dfs
7290 * @ic: ieee80211com ptr
7291 *
7292 * Configures Radar Filters during
7293 * vdev start/channel change/regulatory domain
7294 * change.This Configuration enables to program
7295 * the DFS pattern matching module.
7296 *
7297 * Return: none
7298 */
7299void wma_dfs_configure(struct ieee80211com *ic)
7300{
7301 struct ath_dfs_radar_tab_info rinfo;
7302 int dfsdomain;
7303 int radar_enabled_status = 0;
7304 if (ic == NULL) {
7305 WMA_LOGE("%s: DFS ic is Invalid", __func__);
7306 return;
7307 }
7308
7309 dfsdomain = ic->current_dfs_regdomain;
7310
7311 /* Fetch current radar patterns from the lmac */
7312 OS_MEMZERO(&rinfo, sizeof(rinfo));
7313
7314 /*
7315 * Look up the current DFS
7316 * regulatory domain and decide
7317 * which radar pulses to use.
7318 */
7319 switch (dfsdomain) {
7320 case DFS_FCC_DOMAIN:
7321 WMA_LOGI("%s: DFS-FCC domain", __func__);
7322 rinfo.dfsdomain = DFS_FCC_DOMAIN;
7323 rinfo.dfs_radars = dfs_fcc_radars;
7324 rinfo.numradars = CDF_ARRAY_SIZE(dfs_fcc_radars);
7325 rinfo.b5pulses = dfs_fcc_bin5pulses;
7326 rinfo.numb5radars = CDF_ARRAY_SIZE(dfs_fcc_bin5pulses);
7327 break;
7328 case DFS_ETSI_DOMAIN:
7329 WMA_LOGI("%s: DFS-ETSI domain", __func__);
7330 rinfo.dfsdomain = DFS_ETSI_DOMAIN;
7331 rinfo.dfs_radars = dfs_etsi_radars;
7332 rinfo.numradars = CDF_ARRAY_SIZE(dfs_etsi_radars);
7333 rinfo.b5pulses = NULL;
7334 rinfo.numb5radars = 0;
7335 break;
7336 case DFS_MKK4_DOMAIN:
7337 WMA_LOGI("%s: DFS-MKK4 domain", __func__);
7338 rinfo.dfsdomain = DFS_MKK4_DOMAIN;
7339 rinfo.dfs_radars = dfs_mkk4_radars;
7340 rinfo.numradars = CDF_ARRAY_SIZE(dfs_mkk4_radars);
7341 rinfo.b5pulses = dfs_jpn_bin5pulses;
7342 rinfo.numb5radars = CDF_ARRAY_SIZE(dfs_jpn_bin5pulses);
7343 break;
7344 default:
7345 WMA_LOGI("%s: DFS-UNINT domain", __func__);
7346 rinfo.dfsdomain = DFS_UNINIT_DOMAIN;
7347 rinfo.dfs_radars = NULL;
7348 rinfo.numradars = 0;
7349 rinfo.b5pulses = NULL;
7350 rinfo.numb5radars = 0;
7351 break;
7352 }
7353
7354 rinfo.dfs_pri_multiplier = ic->dfs_pri_multiplier;
7355
7356 /*
7357 * Set the regulatory domain,
7358 * radar pulse table and enable
7359 * radar events if required.
7360 * dfs_radar_enable() returns
7361 * 0 on success and non-zero
7362 * failure.
7363 */
7364 radar_enabled_status = dfs_radar_enable(ic, &rinfo);
7365 if (radar_enabled_status != DFS_STATUS_SUCCESS) {
7366 WMA_LOGE("%s[%d]: DFS- Radar Detection Enabling Failed",
7367 __func__, __LINE__);
7368 }
7369}
7370
7371/**
7372 * wma_dfs_configure_channel() - configure DFS channel
7373 * @dfs_ic: ieee80211com ptr
7374 * @chan: wmi channel
7375 * @chanmode: channel mode
7376 * @ req: vdev start request
7377 *
7378 * Set the Channel parameters in to DFS module
7379 * Also,configure the DFS radar filters for
7380 * matching the DFS phyerrors.
7381 *
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05307382 * Return: dfs_ieee80211_channel / NULL for error
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007383 */
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05307384struct dfs_ieee80211_channel *wma_dfs_configure_channel(
7385 struct ieee80211com *dfs_ic,
7386 wmi_channel *chan,
7387 WLAN_PHY_MODE chanmode,
7388 struct wma_vdev_start_req
7389 *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007390{
7391 if (dfs_ic == NULL) {
7392 WMA_LOGE("%s: DFS ic is Invalid", __func__);
7393 return NULL;
7394 }
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05307395
7396 if (!dfs_ic->ic_curchan) {
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05307397 dfs_ic->ic_curchan = (struct dfs_ieee80211_channel *)os_malloc(
7398 NULL,
7399 sizeof(struct dfs_ieee80211_channel),
7400 GFP_ATOMIC);
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05307401 if (dfs_ic->ic_curchan == NULL) {
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05307402 WMA_LOGE(
7403 "%s: allocation of dfs_ic->ic_curchan failed %zu",
7404 __func__, sizeof(struct dfs_ieee80211_channel));
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05307405 return NULL;
7406 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007407 }
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05307408
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05307409 OS_MEMZERO(dfs_ic->ic_curchan, sizeof(struct dfs_ieee80211_channel));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007410
7411 dfs_ic->ic_curchan->ic_ieee = req->chan;
7412 dfs_ic->ic_curchan->ic_freq = chan->mhz;
7413 dfs_ic->ic_curchan->ic_vhtop_ch_freq_seg1 = chan->band_center_freq1;
7414 dfs_ic->ic_curchan->ic_vhtop_ch_freq_seg2 = chan->band_center_freq2;
7415 dfs_ic->ic_curchan->ic_pri_freq_center_freq_mhz_separation =
7416 dfs_ic->ic_curchan->ic_freq -
7417 dfs_ic->ic_curchan->ic_vhtop_ch_freq_seg1;
7418
7419 if ((dfs_ic->ic_curchan->ic_ieee >= WMA_11A_CHANNEL_BEGIN) &&
7420 (dfs_ic->ic_curchan->ic_ieee <= WMA_11A_CHANNEL_END)) {
7421 dfs_ic->ic_curchan->ic_flags |= IEEE80211_CHAN_5GHZ;
7422 }
7423 if (CH_WIDTH_80MHZ == req->chan_width) {
7424 dfs_ic->ic_curchan->ic_flags |= IEEE80211_CHAN_VHT80;
7425 }
7426 if (CH_WIDTH_40MHZ == req->chan_width) {
7427 if (req->chan < req->ch_center_freq_seg0)
7428 dfs_ic->ic_curchan->ic_flags |= (req->vht_capable ?
7429 IEEE80211_CHAN_VHT40PLUS :
7430 IEEE80211_CHAN_HT40PLUS);
7431 else
7432 dfs_ic->ic_curchan->ic_flags |= (req->vht_capable ?
7433 IEEE80211_CHAN_VHT40MINUS :
7434 IEEE80211_CHAN_HT40MINUS);
7435 } else if (CH_WIDTH_20MHZ == req->chan_width) {
7436 dfs_ic->ic_curchan->ic_flags |=
7437 (req->vht_capable ? IEEE80211_CHAN_VHT20 :
7438 IEEE80211_CHAN_HT20);
7439 }
7440 dfs_ic->ic_curchan->ic_flagext |= IEEE80211_CHAN_DFS;
7441
7442 if (req->oper_mode == BSS_OPERATIONAL_MODE_AP) {
7443 dfs_ic->ic_opmode = IEEE80211_M_HOSTAP;
7444 dfs_ic->vdev_id = req->vdev_id;
7445 }
7446
7447 dfs_ic->dfs_pri_multiplier = req->dfs_pri_multiplier;
7448
7449 /*
7450 * Configuring the DFS with current channel and the radar filters
7451 */
7452 wma_dfs_configure(dfs_ic);
7453 WMA_LOGI("%s: DFS- CHANNEL CONFIGURED", __func__);
7454 return dfs_ic->ic_curchan;
7455}
7456
7457
7458/**
7459 * wma_set_dfs_region() - set DFS region
7460 * @wma: wma handle
7461 *
7462 * Configure the DFS region for DFS radar filter initialization
7463 *
7464 * Return: none
7465 */
7466void wma_set_dfs_region(tp_wma_handle wma, uint8_t dfs_region)
7467{
7468 /* dfs information is passed */
7469 if (dfs_region > DFS_MKK4_DOMAIN || dfs_region == DFS_UNINIT_DOMAIN)
7470 /* assign DFS_FCC_DOMAIN as default domain*/
7471 wma->dfs_ic->current_dfs_regdomain = DFS_FCC_DOMAIN;
7472 else
7473 wma->dfs_ic->current_dfs_regdomain = dfs_region;
7474
7475 WMA_LOGI("%s: DFS Region Domain: %d", __func__,
7476 wma->dfs_ic->current_dfs_regdomain);
7477}
7478
7479/**
7480 * wma_get_channels() - prepare dfs radar channel list
7481 * @ichan: channel
7482 * @chan_list: return channel list
7483 *
7484 * Return: return number of channels
7485 */
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05307486int wma_get_channels(struct dfs_ieee80211_channel *ichan,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007487 struct wma_dfs_radar_channel_list *chan_list)
7488{
7489 uint8_t center_chan = cds_freq_to_chan(ichan->ic_vhtop_ch_freq_seg1);
7490
7491 chan_list->nchannels = 0;
7492
7493 if (IEEE80211_IS_CHAN_11AC_VHT80(ichan)) {
7494 chan_list->nchannels = 4;
7495 chan_list->channels[0] = center_chan - 6;
7496 chan_list->channels[1] = center_chan - 2;
7497 chan_list->channels[2] = center_chan + 2;
7498 chan_list->channels[3] = center_chan + 6;
7499 } else if (IEEE80211_IS_CHAN_11N_HT40(ichan) ||
7500 IEEE80211_IS_CHAN_11AC_VHT40(ichan)) {
7501 chan_list->nchannels = 2;
7502 chan_list->channels[0] = center_chan - 2;
7503 chan_list->channels[1] = center_chan + 2;
7504 } else {
7505 chan_list->nchannels = 1;
7506 chan_list->channels[0] = center_chan;
7507 }
7508
7509 return chan_list->nchannels;
7510}
7511
7512
7513/**
7514 * wma_dfs_indicate_radar() - Indicate Radar to SAP/HDD
7515 * @ic: ieee80211com ptr
7516 * @ichan: ieee 80211 channel
7517 *
7518 * Return: 0 for success or error code
7519 */
7520int wma_dfs_indicate_radar(struct ieee80211com *ic,
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05307521 struct dfs_ieee80211_channel *ichan)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007522{
7523 tp_wma_handle wma;
7524 void *hdd_ctx;
7525 struct wma_dfs_radar_indication *radar_event;
7526 struct wma_dfs_radar_ind wma_radar_event;
7527 tpAniSirGlobal pmac = NULL;
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05307528 bool indication_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007529
7530 wma = cds_get_context(CDF_MODULE_ID_WMA);
7531 if (wma == NULL) {
7532 WMA_LOGE("%s: DFS- Invalid wma", __func__);
7533 return -ENOENT;
7534 }
7535
7536 hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD);
7537 pmac = (tpAniSirGlobal)
7538 cds_get_context(CDF_MODULE_ID_PE);
7539
7540 if (!pmac) {
7541 WMA_LOGE("%s: Invalid MAC handle", __func__);
7542 return -ENOENT;
7543 }
7544
7545 if (wma->dfs_ic != ic) {
7546 WMA_LOGE("%s:DFS- Invalid WMA handle", __func__);
7547 return -ENOENT;
7548 }
7549 radar_event = (struct wma_dfs_radar_indication *)
7550 cdf_mem_malloc(sizeof(struct wma_dfs_radar_indication));
7551 if (radar_event == NULL) {
7552 WMA_LOGE("%s:DFS- Invalid radar_event", __func__);
7553 return -ENOMEM;
7554 }
7555
7556 /*
7557 * Do not post multiple Radar events on the same channel.
7558 * But, when DFS test mode is enabled, allow multiple dfs
7559 * radar events to be posted on the same channel.
7560 */
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05307561 cdf_spin_lock_bh(&ic->chan_lock);
Edhar, Mahesh Kumar35d9b2e2015-10-26 17:06:23 +05307562 if (!pmac->sap.SapDfsInfo.disable_dfs_ch_switch)
7563 wma->dfs_ic->disable_phy_err_processing = true;
7564
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007565 if ((ichan->ic_ieee != (wma->dfs_ic->last_radar_found_chan)) ||
7566 (pmac->sap.SapDfsInfo.disable_dfs_ch_switch == true)) {
7567 wma->dfs_ic->last_radar_found_chan = ichan->ic_ieee;
7568 /* Indicate the radar event to HDD to stop the netif Tx queues */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007569 wma_radar_event.chan_freq = ichan->ic_freq;
7570 wma_radar_event.dfs_radar_status = WMA_DFS_RADAR_FOUND;
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05307571 indication_status =
7572 wma->dfs_radar_indication_cb(hdd_ctx, &wma_radar_event);
7573 if (indication_status == false) {
7574 WMA_LOGE("%s:Application triggered channel switch in progress!.. drop radar event indiaction to SAP",
7575 __func__);
7576 cdf_mem_free(radar_event);
7577 cdf_spin_unlock_bh(&ic->chan_lock);
7578 return 0;
7579 }
7580
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007581 WMA_LOGE("%s:DFS- RADAR INDICATED TO HDD", __func__);
7582
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05307583 wma_radar_event.ieee_chan_number = ichan->ic_ieee;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007584 /*
7585 * Indicate to the radar event to SAP to
7586 * select a new channel and set CSA IE
7587 */
7588 radar_event->vdev_id = ic->vdev_id;
7589 wma_get_channels(ichan, &radar_event->chan_list);
7590 radar_event->dfs_radar_status = WMA_DFS_RADAR_FOUND;
7591 radar_event->use_nol = ic->ic_dfs_usenol(ic);
7592 wma_send_msg(wma, WMA_DFS_RADAR_IND, (void *)radar_event, 0);
7593 WMA_LOGE("%s:DFS- WMA_DFS_RADAR_IND Message Posted", __func__);
7594 }
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05307595 cdf_spin_unlock_bh(&ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007596
7597 return 0;
7598}
7599
7600#ifdef WLAN_FEATURE_MEMDUMP
7601/*
7602 * wma_process_fw_mem_dump_req() - Function to request fw memory dump from
7603 * firmware
7604 * @wma: Pointer to WMA handle
7605 * @mem_dump_req: Pointer for mem_dump_req
7606 *
7607 * This function sends memory dump request to firmware
7608 *
7609 * Return: CDF_STATUS_SUCCESS for success otherwise failure
7610 *
7611 */
7612CDF_STATUS wma_process_fw_mem_dump_req(tp_wma_handle wma,
7613 struct fw_dump_req *mem_dump_req)
7614{
7615 wmi_get_fw_mem_dump_fixed_param *cmd;
7616 wmi_fw_mem_dump *dump_params;
7617 struct fw_dump_seg_req *seg_req;
7618 int32_t len;
7619 wmi_buf_t buf;
7620 u_int8_t *buf_ptr;
7621 int ret, loop;
7622
7623 if (!mem_dump_req || !wma) {
7624 WMA_LOGE(FL("input pointer is NULL"));
7625 return CDF_STATUS_E_FAILURE;
7626 }
7627
7628 /*
7629 * len = sizeof(fixed param) that includes tlv header +
7630 * tlv header for array of struc +
7631 * sizeof (each struct)
7632 */
7633 len = sizeof(*cmd) + WMI_TLV_HDR_SIZE;
7634 len += mem_dump_req->num_seg * sizeof(wmi_fw_mem_dump);
7635 buf = wmi_buf_alloc(wma->wmi_handle, len);
7636
7637 if (!buf) {
7638 WMA_LOGE(FL("Failed allocate wmi buffer"));
7639 return CDF_STATUS_E_NOMEM;
7640 }
7641
7642 buf_ptr = (u_int8_t *) wmi_buf_data(buf);
7643 cdf_mem_zero(buf_ptr, len);
7644 cmd = (wmi_get_fw_mem_dump_fixed_param *) buf_ptr;
7645
7646 WMITLV_SET_HDR(&cmd->tlv_header,
7647 WMITLV_TAG_STRUC_wmi_get_fw_mem_dump_fixed_param,
7648 WMITLV_GET_STRUCT_TLVLEN(wmi_get_fw_mem_dump_fixed_param));
7649
7650 cmd->request_id = mem_dump_req->request_id;
7651 cmd->num_fw_mem_dump_segs = mem_dump_req->num_seg;
7652
7653 /* TLV indicating array of structures to follow */
7654 buf_ptr += sizeof(wmi_get_fw_mem_dump_fixed_param);
7655 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
7656 sizeof(wmi_fw_mem_dump) *
7657 cmd->num_fw_mem_dump_segs);
7658
7659 buf_ptr += WMI_TLV_HDR_SIZE;
7660 dump_params = (wmi_fw_mem_dump *) buf_ptr;
7661
7662 WMA_LOGI(FL("request_id:%d num_seg:%d"),
7663 mem_dump_req->request_id, mem_dump_req->num_seg);
7664 for (loop = 0; loop < cmd->num_fw_mem_dump_segs; loop++) {
7665 seg_req = (struct fw_dump_seg_req *)
7666 ((uint8_t *)(mem_dump_req->segment) +
7667 loop * sizeof(*seg_req));
7668 WMITLV_SET_HDR(&dump_params->tlv_header,
7669 WMITLV_TAG_STRUC_wmi_fw_mem_dump_params,
7670 WMITLV_GET_STRUCT_TLVLEN(wmi_fw_mem_dump));
7671 dump_params->seg_id = seg_req->seg_id;
7672 dump_params->seg_start_addr_lo = seg_req->seg_start_addr_lo;
7673 dump_params->seg_start_addr_hi = seg_req->seg_start_addr_hi;
7674 dump_params->seg_length = seg_req->seg_length;
7675 dump_params->dest_addr_lo = seg_req->dst_addr_lo;
7676 dump_params->dest_addr_hi = seg_req->dst_addr_hi;
7677 WMA_LOGI(FL("seg_number:%d"), loop);
7678 WMA_LOGI(FL("seg_id:%d start_addr_lo:0x%x start_addr_hi:0x%x"),
7679 dump_params->seg_id, dump_params->seg_start_addr_lo,
7680 dump_params->seg_start_addr_hi);
7681 WMA_LOGI(FL("seg_length:%d dst_addr_lo:0x%x dst_addr_hi:0x%x"),
7682 dump_params->seg_length, dump_params->dest_addr_lo,
7683 dump_params->dest_addr_hi);
7684 dump_params++;
7685 }
7686
7687 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
7688 WMI_GET_FW_MEM_DUMP_CMDID);
7689 if (ret) {
7690 WMA_LOGE(FL("Failed to send get firmware mem dump request"));
7691 wmi_buf_free(buf);
7692 return CDF_STATUS_E_FAILURE;
7693 }
7694
7695 WMA_LOGI(FL("Get firmware mem dump request sent successfully"));
7696 return CDF_STATUS_SUCCESS;
7697}
7698
7699/**
7700 * wma_fw_mem_dump_rsp() - send fw mem dump response to SME
7701 *
7702 * @req_id - request id.
7703 * @status - copy status from the firmware.
7704 *
7705 * This function is called by the memory dump response handler to
7706 * indicate SME that firmware dump copy is complete
7707 *
7708 * Return: CDF_STATUS
7709 */
7710static CDF_STATUS wma_fw_mem_dump_rsp(uint32_t req_id, uint32_t status)
7711{
7712 struct fw_dump_rsp *dump_rsp;
7713 cds_msg_t sme_msg = {0};
7714 CDF_STATUS cdf_status = CDF_STATUS_SUCCESS;
7715
7716 dump_rsp = cdf_mem_malloc(sizeof(*dump_rsp));
7717
7718 if (!dump_rsp) {
7719 WMA_LOGE(FL("Memory allocation failed."));
7720 cdf_status = CDF_STATUS_E_NOMEM;
7721 return cdf_status;
7722 }
7723
7724 WMA_LOGI(FL("FW memory dump copy complete status: %d for request: %d"),
7725 status, req_id);
7726
7727 dump_rsp->request_id = req_id;
7728 dump_rsp->dump_complete = status;
7729
7730 sme_msg.type = eWNI_SME_FW_DUMP_IND;
7731 sme_msg.bodyptr = dump_rsp;
7732 sme_msg.bodyval = 0;
7733
7734 cdf_status = cds_mq_post_message(CDF_MODULE_ID_SME, &sme_msg);
7735 if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
7736 WMA_LOGE(FL("Fail to post fw mem dump ind msg"));
7737 cdf_mem_free(dump_rsp);
7738 }
7739
7740 return cdf_status;
7741}
7742
7743/**
7744 * wma_fw_mem_dump_event_handler() - handles fw memory dump event
7745 *
7746 * @handle: pointer to wma handle.
7747 * @cmd_param_info: pointer to TLV info received in the event.
7748 * @len: length of data in @cmd_param_info
7749 *
7750 * This function is a handler for firmware memory dump event.
7751 *
7752 * Return: integer (0 for success and error code otherwise)
7753 */
7754int wma_fw_mem_dump_event_handler(void *handle, u_int8_t *cmd_param_info,
7755 u_int32_t len)
7756{
7757 WMI_UPDATE_FW_MEM_DUMP_EVENTID_param_tlvs *param_buf;
7758 wmi_update_fw_mem_dump_fixed_param *event;
7759 CDF_STATUS status;
7760
7761 param_buf =
7762 (WMI_UPDATE_FW_MEM_DUMP_EVENTID_param_tlvs *) cmd_param_info;
7763 if (!param_buf) {
7764 WMA_LOGA("%s: Invalid stats event", __func__);
7765 return -EINVAL;
7766 }
7767
7768 event = param_buf->fixed_param;
7769
7770 status = wma_fw_mem_dump_rsp(event->request_id,
7771 event->fw_mem_dump_complete);
7772 if (CDF_STATUS_SUCCESS != status) {
7773 WMA_LOGE("Error posting FW MEM DUMP RSP.");
7774 return -EINVAL;
7775 }
7776
7777 WMA_LOGI("FW MEM DUMP RSP posted successfully");
7778 return 0;
7779}
7780#endif /* WLAN_FEATURE_MEMDUMP */
7781
7782/*
7783 * wma_process_set_ie_info() - Function to send IE info to firmware
7784 * @wma: Pointer to WMA handle
7785 * @ie_data: Pointer for ie data
7786 *
7787 * This function sends IE information to firmware
7788 *
7789 * Return: CDF_STATUS_SUCCESS for success otherwise failure
7790 *
7791 */
7792CDF_STATUS wma_process_set_ie_info(tp_wma_handle wma,
7793 struct vdev_ie_info *ie_info)
7794{
7795 wmi_vdev_set_ie_cmd_fixed_param *cmd;
7796 wmi_buf_t buf;
7797 uint8_t *buf_ptr;
7798 uint32_t len, ie_len_aligned;
7799 int ret;
7800
7801 if (!ie_info || !wma) {
7802 WMA_LOGE(FL("input pointer is NULL"));
7803 return CDF_STATUS_E_FAILURE;
7804 }
7805
7806 /* Validate the input */
7807 if (ie_info->length <= 0) {
7808 WMA_LOGE(FL("Invalid IE length"));
7809 return CDF_STATUS_E_INVAL;
7810 }
7811
7812 ie_len_aligned = roundup(ie_info->length, sizeof(uint32_t));
7813 /* Allocate memory for the WMI command */
7814 len = sizeof(*cmd) + WMI_TLV_HDR_SIZE + ie_len_aligned;
7815
7816 buf = wmi_buf_alloc(wma->wmi_handle, len);
7817 if (!buf) {
7818 WMA_LOGE(FL("wmi_buf_alloc failed"));
7819 return CDF_STATUS_E_NOMEM;
7820 }
7821
7822 buf_ptr = wmi_buf_data(buf);
7823 cdf_mem_zero(buf_ptr, len);
7824
7825 /* Populate the WMI command */
7826 cmd = (wmi_vdev_set_ie_cmd_fixed_param *)buf_ptr;
7827
7828 WMITLV_SET_HDR(&cmd->tlv_header,
7829 WMITLV_TAG_STRUC_wmi_vdev_set_ie_cmd_fixed_param,
7830 WMITLV_GET_STRUCT_TLVLEN(
7831 wmi_vdev_set_ie_cmd_fixed_param));
7832 cmd->vdev_id = ie_info->vdev_id;
7833 cmd->ie_id = ie_info->ie_id;
7834 cmd->ie_len = ie_info->length;
7835
7836 WMA_LOGD(FL("IE:%d of size:%d sent for vdev:%d"), ie_info->ie_id,
7837 ie_info->length, ie_info->vdev_id);
7838
7839 buf_ptr += sizeof(*cmd);
7840 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, ie_len_aligned);
7841 buf_ptr += WMI_TLV_HDR_SIZE;
7842
7843 cdf_mem_copy(buf_ptr, ie_info->data, cmd->ie_len);
7844
7845 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
7846 WMI_VDEV_SET_IE_CMDID);
7847 if (ret != EOK) {
7848 WMA_LOGE(FL("Failed to send set IE command ret = %d"), ret);
7849 wmi_buf_free(buf);
7850 }
7851
7852 return ret;
7853}
7854