blob: acebf9b3ae3fe9857269eace07161ca2bceb2e4d [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
2 * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved.
3 *
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/**
983 * wmi_unified_pdev_green_ap_ps_enable_cmd() - enable green ap powersave command
984 * @wmi_handle: wmi handle
985 * @value: value
986 *
987 * Return: 0 for success or error code
988 */
989int32_t wmi_unified_pdev_green_ap_ps_enable_cmd(wmi_unified_t wmi_handle,
990 uint32_t value)
991{
992 wmi_pdev_green_ap_ps_enable_cmd_fixed_param *cmd;
993 wmi_buf_t buf;
994 int32_t len = sizeof(*cmd);
995
996 WMA_LOGD("Set Green AP PS val %d", value);
997
998 buf = wmi_buf_alloc(wmi_handle, len);
999 if (!buf) {
1000 WMA_LOGP("%s: Green AP PS Mem Alloc Failed", __func__);
1001 return -ENOMEM;
1002 }
1003
1004 cmd = (wmi_pdev_green_ap_ps_enable_cmd_fixed_param *) wmi_buf_data(buf);
1005 WMITLV_SET_HDR(&cmd->tlv_header,
1006 WMITLV_TAG_STRUC_wmi_pdev_green_ap_ps_enable_cmd_fixed_param,
1007 WMITLV_GET_STRUCT_TLVLEN
1008 (wmi_pdev_green_ap_ps_enable_cmd_fixed_param));
1009 cmd->reserved0 = 0;
1010 cmd->enable = value;
1011
1012 if (wmi_unified_cmd_send(wmi_handle, buf, len,
1013 WMI_PDEV_GREEN_AP_PS_ENABLE_CMDID)) {
1014 WMA_LOGE("Set Green AP PS param Failed val %d", value);
1015 cdf_nbuf_free(buf);
1016 return -EIO;
1017 }
1018 return 0;
1019}
1020#endif /* FEATURE_GREEN_AP */
1021
Govind Singha471e5e2015-10-12 17:11:14 +05301022/**
1023 * wmi_unified_fw_profiling_cmd() - send FW profiling cmd to WLAN FW
1024 * @wma: wma handle
1025 * @cmd: Profiling command index
1026 * @value1: parameter1 value
1027 * @value2: parameter2 value
1028 *
1029 * Return: 0 for success else error code
1030 */
1031int32_t wmi_unified_fw_profiling_cmd(wmi_unified_t wmi_handle,
1032 uint32_t cmd, uint32_t value1, uint32_t value2)
1033{
1034 wmi_buf_t buf;
1035 int32_t len = 0;
1036 int ret;
1037 wmi_wlan_profile_trigger_cmd_fixed_param *prof_trig_cmd;
1038 wmi_wlan_profile_set_hist_intvl_cmd_fixed_param *hist_intvl_cmd;
1039 wmi_wlan_profile_enable_profile_id_cmd_fixed_param *profile_enable_cmd;
1040 wmi_wlan_profile_get_prof_data_cmd_fixed_param *profile_getdata_cmd;
1041
1042 switch (cmd) {
1043 case WMI_WLAN_PROFILE_TRIGGER_CMDID:
1044 len = sizeof(wmi_wlan_profile_trigger_cmd_fixed_param);
1045 buf = wmi_buf_alloc(wmi_handle, len);
1046 if (!buf) {
1047 WMA_LOGP("%s: wmi_buf_alloc Failed", __func__);
1048 return -ENOMEM;
1049 }
1050 prof_trig_cmd =
1051 (wmi_wlan_profile_trigger_cmd_fixed_param *)
1052 wmi_buf_data(buf);
1053 WMITLV_SET_HDR(&prof_trig_cmd->tlv_header,
1054 WMITLV_TAG_STRUC_wmi_wlan_profile_trigger_cmd_fixed_param,
1055 WMITLV_GET_STRUCT_TLVLEN
1056 (wmi_wlan_profile_trigger_cmd_fixed_param));
1057 prof_trig_cmd->enable = value1;
1058 ret = wmi_unified_cmd_send(wmi_handle, buf, len,
1059 WMI_WLAN_PROFILE_TRIGGER_CMDID);
1060 if (ret) {
1061 WMA_LOGE("PROFILE_TRIGGER cmd Failed with value %d",
1062 value1);
1063 cdf_nbuf_free(buf);
1064 return ret;
1065 }
1066 break;
1067
1068 case WMI_WLAN_PROFILE_GET_PROFILE_DATA_CMDID:
1069 len = sizeof(wmi_wlan_profile_get_prof_data_cmd_fixed_param);
1070 buf = wmi_buf_alloc(wmi_handle, len);
1071 if (!buf) {
1072 WMA_LOGP("%s: wmi_buf_alloc Failed", __func__);
1073 return -ENOMEM;
1074 }
1075 profile_getdata_cmd =
1076 (wmi_wlan_profile_get_prof_data_cmd_fixed_param *)
1077 wmi_buf_data(buf);
1078 WMITLV_SET_HDR(&profile_getdata_cmd->tlv_header,
1079 WMITLV_TAG_STRUC_wmi_wlan_profile_get_prof_data_cmd_fixed_param,
1080 WMITLV_GET_STRUCT_TLVLEN
1081 (wmi_wlan_profile_get_prof_data_cmd_fixed_param));
1082 ret = wmi_unified_cmd_send(wmi_handle, buf, len,
1083 WMI_WLAN_PROFILE_GET_PROFILE_DATA_CMDID);
1084 if (ret) {
1085 WMA_LOGE("PROFILE_DATA cmd Failed for id %d value %d",
1086 value1, value2);
1087 cdf_nbuf_free(buf);
1088 return ret;
1089 }
1090 break;
1091
1092 case WMI_WLAN_PROFILE_SET_HIST_INTVL_CMDID:
1093 len = sizeof(wmi_wlan_profile_set_hist_intvl_cmd_fixed_param);
1094 buf = wmi_buf_alloc(wmi_handle, len);
1095 if (!buf) {
1096 WMA_LOGP("%s: wmi_buf_alloc Failed", __func__);
1097 return -ENOMEM;
1098 }
1099 hist_intvl_cmd =
1100 (wmi_wlan_profile_set_hist_intvl_cmd_fixed_param *)
1101 wmi_buf_data(buf);
1102 WMITLV_SET_HDR(&hist_intvl_cmd->tlv_header,
1103 WMITLV_TAG_STRUC_wmi_wlan_profile_set_hist_intvl_cmd_fixed_param,
1104 WMITLV_GET_STRUCT_TLVLEN
1105 (wmi_wlan_profile_set_hist_intvl_cmd_fixed_param));
1106 hist_intvl_cmd->profile_id = value1;
1107 hist_intvl_cmd->value = value2;
1108 ret = wmi_unified_cmd_send(wmi_handle, buf, len,
1109 WMI_WLAN_PROFILE_SET_HIST_INTVL_CMDID);
1110 if (ret) {
1111 WMA_LOGE("HIST_INTVL cmd Failed for id %d value %d",
1112 value1, value2);
1113 cdf_nbuf_free(buf);
1114 return ret;
1115 }
1116 break;
1117
1118 case WMI_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID:
1119 len =
1120 sizeof(wmi_wlan_profile_enable_profile_id_cmd_fixed_param);
1121 buf = wmi_buf_alloc(wmi_handle, len);
1122 if (!buf) {
1123 WMA_LOGP("%s: wmi_buf_alloc Failed", __func__);
1124 return -ENOMEM;
1125 }
1126 profile_enable_cmd =
1127 (wmi_wlan_profile_enable_profile_id_cmd_fixed_param *)
1128 wmi_buf_data(buf);
1129 WMITLV_SET_HDR(&profile_enable_cmd->tlv_header,
1130 WMITLV_TAG_STRUC_wmi_wlan_profile_enable_profile_id_cmd_fixed_param,
1131 WMITLV_GET_STRUCT_TLVLEN
1132 (wmi_wlan_profile_enable_profile_id_cmd_fixed_param));
1133 profile_enable_cmd->profile_id = value1;
1134 profile_enable_cmd->enable = value2;
1135 ret = wmi_unified_cmd_send(wmi_handle, buf, len,
1136 WMI_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID);
1137 if (ret) {
1138 WMA_LOGE("enable cmd Failed for id %d value %d",
1139 value1, value2);
1140 cdf_nbuf_free(buf);
1141 return ret;
1142 }
1143 break;
1144
1145 default:
1146 WMA_LOGD("%s: invalid profiling command", __func__);
1147 break;
1148 }
1149
1150 return 0;
1151}
1152
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001153#ifdef FEATURE_WLAN_LPHB
1154/**
1155 * wma_lphb_handler() - send LPHB indication to SME
1156 * @wma: wma handle
1157 * @event: event handler
1158 *
1159 * Return: 0 for success or error code
1160 */
1161static int wma_lphb_handler(tp_wma_handle wma, uint8_t *event)
1162{
1163 wmi_hb_ind_event_fixed_param *hb_fp;
1164 tSirLPHBInd *slphb_indication;
1165 CDF_STATUS cdf_status;
1166 cds_msg_t sme_msg = { 0 };
1167
1168 hb_fp = (wmi_hb_ind_event_fixed_param *) event;
1169 if (!hb_fp) {
1170 WMA_LOGE("Invalid wmi_hb_ind_event_fixed_param buffer");
1171 return -EINVAL;
1172 }
1173
1174 WMA_LOGD("lphb indication received with vdev_id=%d, session=%d, reason=%d",
1175 hb_fp->vdev_id, hb_fp->session, hb_fp->reason);
1176
1177 slphb_indication = (tSirLPHBInd *) cdf_mem_malloc(sizeof(tSirLPHBInd));
1178
1179 if (!slphb_indication) {
1180 WMA_LOGE("Invalid LPHB indication buffer");
1181 return -ENOMEM;
1182 }
1183
1184 slphb_indication->sessionIdx = hb_fp->session;
1185 slphb_indication->protocolType = hb_fp->reason;
1186 slphb_indication->eventReason = hb_fp->reason;
1187
1188 sme_msg.type = eWNI_SME_LPHB_IND;
1189 sme_msg.bodyptr = slphb_indication;
1190 sme_msg.bodyval = 0;
1191
1192 cdf_status = cds_mq_post_message(CDF_MODULE_ID_SME, &sme_msg);
1193 if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
1194 WMA_LOGE("Fail to post eWNI_SME_LPHB_IND msg to SME");
1195 cdf_mem_free(slphb_indication);
1196 return -EINVAL;
1197 }
1198
1199 return 0;
1200}
1201#endif /* FEATURE_WLAN_LPHB */
1202
1203#ifdef FEATURE_WLAN_RA_FILTERING
1204/**
1205 * wma_wow_sta_ra_filter() - set RA filter pattern in fw
1206 * @wma: wma handle
1207 * @vdev_id: vdev id
1208 *
1209 * Return: CDF status
1210 */
1211static CDF_STATUS wma_wow_sta_ra_filter(tp_wma_handle wma, uint8_t vdev_id)
1212{
1213
1214 WMI_WOW_ADD_PATTERN_CMD_fixed_param *cmd;
1215 struct wma_txrx_node *iface;
1216 wmi_buf_t buf;
1217 uint8_t *buf_ptr;
1218 int32_t len;
1219 int ret;
1220
1221 iface = &wma->interfaces[vdev_id];
1222
1223 len = sizeof(WMI_WOW_ADD_PATTERN_CMD_fixed_param) +
1224 WMI_TLV_HDR_SIZE +
1225 0 * sizeof(WOW_BITMAP_PATTERN_T) +
1226 WMI_TLV_HDR_SIZE +
1227 0 * sizeof(WOW_IPV4_SYNC_PATTERN_T) +
1228 WMI_TLV_HDR_SIZE +
1229 0 * sizeof(WOW_IPV6_SYNC_PATTERN_T) +
1230 WMI_TLV_HDR_SIZE +
1231 0 * sizeof(WOW_MAGIC_PATTERN_CMD) +
1232 WMI_TLV_HDR_SIZE +
1233 0 * sizeof(A_UINT32) + WMI_TLV_HDR_SIZE + 1 * sizeof(A_UINT32);
1234
1235 buf = wmi_buf_alloc(wma->wmi_handle, len);
1236 if (!buf) {
1237 WMA_LOGE("%s: Failed allocate wmi buffer", __func__);
1238 return CDF_STATUS_E_NOMEM;
1239 }
1240
1241 cmd = (WMI_WOW_ADD_PATTERN_CMD_fixed_param *) wmi_buf_data(buf);
1242 buf_ptr = (uint8_t *) cmd;
1243
1244 WMITLV_SET_HDR(&cmd->tlv_header,
1245 WMITLV_TAG_STRUC_WMI_WOW_ADD_PATTERN_CMD_fixed_param,
1246 WMITLV_GET_STRUCT_TLVLEN
1247 (WMI_WOW_ADD_PATTERN_CMD_fixed_param));
1248 cmd->vdev_id = vdev_id;
1249 cmd->pattern_id = iface->num_wow_default_patterns++,
1250 cmd->pattern_type = WOW_IPV6_RA_PATTERN;
1251 buf_ptr += sizeof(WMI_WOW_ADD_PATTERN_CMD_fixed_param);
1252
1253 /* Fill TLV for WMITLV_TAG_STRUC_WOW_BITMAP_PATTERN_T but no data. */
1254 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
1255 buf_ptr += WMI_TLV_HDR_SIZE;
1256
1257 /* Fill TLV for WMITLV_TAG_STRUC_WOW_IPV4_SYNC_PATTERN_T but no data. */
1258 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
1259 buf_ptr += WMI_TLV_HDR_SIZE;
1260
1261 /* Fill TLV for WMITLV_TAG_STRUC_WOW_IPV6_SYNC_PATTERN_T but no data. */
1262 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
1263 buf_ptr += WMI_TLV_HDR_SIZE;
1264
1265 /* Fill TLV for WMITLV_TAG_STRUC_WOW_MAGIC_PATTERN_CMD but no data. */
1266 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
1267 buf_ptr += WMI_TLV_HDR_SIZE;
1268
1269 /* Fill TLV for pattern_info_timeout but no data. */
1270 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, 0);
1271 buf_ptr += WMI_TLV_HDR_SIZE;
1272
1273 /* Fill TLV for ra_ratelimit_interval. */
1274 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, sizeof(A_UINT32));
1275 buf_ptr += WMI_TLV_HDR_SIZE;
1276
1277 *((A_UINT32 *) buf_ptr) = wma->RArateLimitInterval;
1278
1279 WMA_LOGD("%s: send RA rate limit [%d] to fw vdev = %d", __func__,
1280 wma->RArateLimitInterval, vdev_id);
1281
1282 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
1283 WMI_WOW_ADD_WAKE_PATTERN_CMDID);
1284 if (ret) {
1285 WMA_LOGE("%s: Failed to send RA rate limit to fw", __func__);
1286 wmi_buf_free(buf);
1287 iface->num_wow_default_patterns--;
1288 return CDF_STATUS_E_FAILURE;
1289 }
1290
1291 return CDF_STATUS_SUCCESS;
1292
1293}
1294#endif /* FEATURE_WLAN_RA_FILTERING */
1295
1296/**
1297 * wmi_unified_nat_keepalive_enable() - enable NAT keepalive filter
1298 * @wma: wma handle
1299 * @vdev_id: vdev id
1300 *
1301 * Return: 0 for success or error code
1302 */
1303int wmi_unified_nat_keepalive_enable(tp_wma_handle wma, uint8_t vdev_id)
1304{
1305 WMI_VDEV_IPSEC_NATKEEPALIVE_FILTER_CMD_fixed_param *cmd;
1306 wmi_buf_t buf;
1307 int32_t len = sizeof(*cmd);
1308
1309 WMA_LOGD("%s: vdev_id %d", __func__, vdev_id);
1310 buf = wmi_buf_alloc(wma->wmi_handle, len);
1311 if (!buf) {
1312 WMA_LOGP("%s: wmi_buf_alloc failed", __func__);
1313 return -ENOMEM;
1314 }
1315 cmd = (WMI_VDEV_IPSEC_NATKEEPALIVE_FILTER_CMD_fixed_param *)
1316 wmi_buf_data(buf);
1317 WMITLV_SET_HDR(&cmd->tlv_header,
1318 WMITLV_TAG_STRUC_WMI_VDEV_IPSEC_NATKEEPALIVE_FILTER_CMD_fixed_param,
1319 WMITLV_GET_STRUCT_TLVLEN
1320 (WMI_VDEV_IPSEC_NATKEEPALIVE_FILTER_CMD_fixed_param));
1321 cmd->vdev_id = vdev_id;
1322 cmd->action = IPSEC_NATKEEPALIVE_FILTER_ENABLE;
1323 if (wmi_unified_cmd_send(wma->wmi_handle, buf, len,
1324 WMI_VDEV_IPSEC_NATKEEPALIVE_FILTER_CMDID)) {
1325 WMA_LOGP("%s: Failed to send NAT keepalive enable command",
1326 __func__);
1327 wmi_buf_free(buf);
1328 return -EIO;
1329 }
1330 return 0;
1331}
1332
1333/**
1334 * wmi_unified_csa_offload_enable() - sen CSA offload enable command
1335 * @wma: wma handle
1336 * @vdev_id: vdev id
1337 *
1338 * Return: 0 for success or error code
1339 */
1340int wmi_unified_csa_offload_enable(tp_wma_handle wma, uint8_t vdev_id)
1341{
1342 wmi_csa_offload_enable_cmd_fixed_param *cmd;
1343 wmi_buf_t buf;
1344 int32_t len = sizeof(*cmd);
1345
1346 WMA_LOGD("%s: vdev_id %d", __func__, vdev_id);
1347 buf = wmi_buf_alloc(wma->wmi_handle, len);
1348 if (!buf) {
1349 WMA_LOGP("%s: wmi_buf_alloc failed", __func__);
1350 return -ENOMEM;
1351 }
1352 cmd = (wmi_csa_offload_enable_cmd_fixed_param *) wmi_buf_data(buf);
1353 WMITLV_SET_HDR(&cmd->tlv_header,
1354 WMITLV_TAG_STRUC_wmi_csa_offload_enable_cmd_fixed_param,
1355 WMITLV_GET_STRUCT_TLVLEN
1356 (wmi_csa_offload_enable_cmd_fixed_param));
1357 cmd->vdev_id = vdev_id;
1358 cmd->csa_offload_enable = WMI_CSA_OFFLOAD_ENABLE;
1359 if (wmi_unified_cmd_send(wma->wmi_handle, buf, len,
1360 WMI_CSA_OFFLOAD_ENABLE_CMDID)) {
1361 WMA_LOGP("%s: Failed to send CSA offload enable command",
1362 __func__);
1363 wmi_buf_free(buf);
1364 return -EIO;
1365 }
1366 return 0;
1367}
1368
1369#ifdef WLAN_FEATURE_NAN
1370/**
1371 * wma_nan_rsp_event_handler() - Function is used to handle nan response
1372 * @handle: wma handle
1373 * @event_buf: event buffer
1374 * @len: length of buffer
1375 *
1376 * Return: 0 for success or error code
1377 */
1378int wma_nan_rsp_event_handler(void *handle, uint8_t *event_buf,
1379 uint32_t len)
1380{
1381 WMI_NAN_EVENTID_param_tlvs *param_buf;
1382 tSirNanEvent *nan_rsp_event;
1383 wmi_nan_event_hdr *nan_rsp_event_hdr;
1384 CDF_STATUS status;
1385 cds_msg_t cds_msg;
1386 uint8_t *buf_ptr;
1387 uint32_t alloc_len;
1388
1389 /*
1390 * This is how received event_buf looks like
1391 *
1392 * <-------------------- event_buf ----------------------------------->
1393 *
1394 * <--wmi_nan_event_hdr--><---WMI_TLV_HDR_SIZE---><----- data -------->
1395 *
1396 * +-----------+---------+-----------------------+--------------------+
1397 * | tlv_header| data_len| WMITLV_TAG_ARRAY_BYTE | nan_rsp_event_data |
1398 * +-----------+---------+-----------------------+--------------------+
1399 */
1400
1401 WMA_LOGD("%s: Posting NaN response event to SME", __func__);
1402 param_buf = (WMI_NAN_EVENTID_param_tlvs *) event_buf;
1403 if (!param_buf) {
1404 WMA_LOGE("%s: Invalid nan response event buf", __func__);
1405 return -EINVAL;
1406 }
1407 nan_rsp_event_hdr = param_buf->fixed_param;
1408 buf_ptr = (uint8_t *) nan_rsp_event_hdr;
1409 alloc_len = sizeof(tSirNanEvent);
1410 alloc_len += nan_rsp_event_hdr->data_len;
1411 nan_rsp_event = (tSirNanEvent *) cdf_mem_malloc(alloc_len);
1412 if (NULL == nan_rsp_event) {
1413 WMA_LOGE("%s: Memory allocation failure", __func__);
1414 return -ENOMEM;
1415 }
1416
1417 nan_rsp_event->event_data_len = nan_rsp_event_hdr->data_len;
1418 cdf_mem_copy(nan_rsp_event->event_data, buf_ptr +
1419 sizeof(wmi_nan_event_hdr) + WMI_TLV_HDR_SIZE,
1420 nan_rsp_event->event_data_len);
1421 cds_msg.type = eWNI_SME_NAN_EVENT;
1422 cds_msg.bodyptr = (void *)nan_rsp_event;
1423 cds_msg.bodyval = 0;
1424
1425 status = cds_mq_post_message(CDS_MQ_ID_SME, &cds_msg);
1426 if (status != CDF_STATUS_SUCCESS) {
1427 WMA_LOGE("%s: Failed to post NaN response event to SME",
1428 __func__);
1429 cdf_mem_free(nan_rsp_event);
1430 return -EFAULT;
1431 }
1432 WMA_LOGD("%s: NaN response event Posted to SME", __func__);
1433 return 0;
1434}
1435#endif /* WLAN_FEATURE_NAN */
1436
1437/**
1438 * wma_csa_offload_handler() - CSA event handler
1439 * @handle: wma handle
1440 * @event: event buffer
1441 * @len: buffer length
1442 *
1443 * This event is sent by firmware when it receives CSA IE.
1444 *
1445 * Return: 0 for success or error code
1446 */
1447int wma_csa_offload_handler(void *handle, uint8_t *event, uint32_t len)
1448{
1449 tp_wma_handle wma = (tp_wma_handle) handle;
1450 WMI_CSA_HANDLING_EVENTID_param_tlvs *param_buf;
1451 wmi_csa_event_fixed_param *csa_event;
1452 uint8_t bssid[IEEE80211_ADDR_LEN];
1453 uint8_t vdev_id = 0;
1454 uint8_t cur_chan = 0;
1455 struct ieee80211_channelswitch_ie *csa_ie;
1456 tpCSAOffloadParams csa_offload_event;
1457 struct ieee80211_extendedchannelswitch_ie *xcsa_ie;
1458 struct ieee80211_ie_wide_bw_switch *wb_ie;
1459 struct wma_txrx_node *intr = wma->interfaces;
1460
1461 param_buf = (WMI_CSA_HANDLING_EVENTID_param_tlvs *) event;
1462
1463 WMA_LOGD("%s: Enter", __func__);
1464 if (!param_buf) {
1465 WMA_LOGE("Invalid csa event buffer");
1466 return -EINVAL;
1467 }
1468 csa_event = param_buf->fixed_param;
1469 WMI_MAC_ADDR_TO_CHAR_ARRAY(&csa_event->i_addr2, &bssid[0]);
1470
1471 if (wma_find_vdev_by_bssid(wma, bssid, &vdev_id) == NULL) {
1472 WMA_LOGE("Invalid bssid received %s:%d", __func__, __LINE__);
1473 return -EINVAL;
1474 }
1475
1476 csa_offload_event = cdf_mem_malloc(sizeof(*csa_offload_event));
1477 if (!csa_offload_event) {
1478 WMA_LOGE("CDF MEM Alloc Failed for csa_offload_event");
1479 return -EINVAL;
1480 }
1481
1482 cdf_mem_zero(csa_offload_event, sizeof(*csa_offload_event));
1483 cdf_mem_copy(csa_offload_event->bssId, &bssid, IEEE80211_ADDR_LEN);
1484
1485 if (csa_event->ies_present_flag & WMI_CSA_IE_PRESENT) {
1486 csa_ie = (struct ieee80211_channelswitch_ie *)
1487 (&csa_event->csa_ie[0]);
1488 csa_offload_event->channel = csa_ie->newchannel;
1489 csa_offload_event->switchmode = csa_ie->switchmode;
1490 } else if (csa_event->ies_present_flag & WMI_XCSA_IE_PRESENT) {
1491 xcsa_ie = (struct ieee80211_extendedchannelswitch_ie *)
1492 (&csa_event->xcsa_ie[0]);
1493 csa_offload_event->channel = xcsa_ie->newchannel;
1494 csa_offload_event->switchmode = xcsa_ie->switchmode;
Gupta, Kapil121bf212015-11-25 19:21:29 +05301495 csa_offload_event->new_op_class = xcsa_ie->newClass;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001496 } else {
1497 WMA_LOGE("CSA Event error: No CSA IE present");
1498 cdf_mem_free(csa_offload_event);
1499 return -EINVAL;
1500 }
1501
1502 if (csa_event->ies_present_flag & WMI_WBW_IE_PRESENT) {
1503 wb_ie = (struct ieee80211_ie_wide_bw_switch *)
1504 (&csa_event->wb_ie[0]);
1505 csa_offload_event->new_ch_width = wb_ie->new_ch_width;
1506 csa_offload_event->new_ch_freq_seg1 = wb_ie->new_ch_freq_seg1;
1507 csa_offload_event->new_ch_freq_seg2 = wb_ie->new_ch_freq_seg2;
1508 }
1509
1510 csa_offload_event->ies_present_flag = csa_event->ies_present_flag;
1511
1512 WMA_LOGD("CSA: New Channel = %d BSSID:%pM",
1513 csa_offload_event->channel, csa_offload_event->bssId);
1514
1515 cur_chan = cds_freq_to_chan(intr[vdev_id].mhz);
1516 /*
1517 * basic sanity check: requested channel should not be 0
1518 * and equal to home channel
1519 */
1520 if ((0 == csa_offload_event->channel) ||
1521 (cur_chan == csa_offload_event->channel)) {
1522 WMA_LOGE("CSA Event with channel %d. Ignore !!",
1523 csa_offload_event->channel);
1524 cdf_mem_free(csa_offload_event);
1525 return -EINVAL;
1526 }
1527 wma->interfaces[vdev_id].is_channel_switch = true;
1528 wma_send_msg(wma, WMA_CSA_OFFLOAD_EVENT, (void *)csa_offload_event, 0);
1529 return 0;
1530}
1531
1532#ifdef FEATURE_OEM_DATA_SUPPORT
1533
1534/**
1535 * wma_oem_capability_event_callback() - OEM capability event handler
1536 * @handle: wma handle
1537 * @datap: data ptr
1538 * @len: data length
1539 *
1540 * Return: 0 for success or error code
1541 */
1542int wma_oem_capability_event_callback(void *handle,
1543 uint8_t *datap, uint32_t len)
1544{
1545 tp_wma_handle wma = (tp_wma_handle) handle;
1546 WMI_OEM_CAPABILITY_EVENTID_param_tlvs *param_buf;
1547 uint8_t *data;
1548 uint32_t datalen;
1549 uint32_t *msg_subtype;
1550 tStartOemDataRsp *pStartOemDataRsp;
1551
1552 param_buf = (WMI_OEM_CAPABILITY_EVENTID_param_tlvs *) datap;
1553 if (!param_buf) {
1554 WMA_LOGE("%s: Received NULL buf ptr from FW", __func__);
1555 return -ENOMEM;
1556 }
1557
1558 data = param_buf->data;
1559 datalen = param_buf->num_data;
1560
1561 if (!data) {
1562 WMA_LOGE("%s: Received NULL data from FW", __func__);
1563 return -EINVAL;
1564 }
1565
1566 /* wma puts 4 bytes prefix for msg subtype, so length
1567 * of data received from target should be 4 bytes less
1568 * then max allowed
1569 */
1570 if (datalen > (OEM_DATA_RSP_SIZE - 4)) {
1571 WMA_LOGE("%s: Received data len (%d) exceeds max value (%d)",
1572 __func__, datalen, (OEM_DATA_RSP_SIZE - 4));
1573 return -EINVAL;
1574 }
1575
1576 pStartOemDataRsp = cdf_mem_malloc(sizeof(*pStartOemDataRsp));
1577 if (!pStartOemDataRsp) {
1578 WMA_LOGE("%s: Failed to alloc pStartOemDataRsp", __func__);
1579 return -ENOMEM;
1580 }
1581
1582 cdf_mem_zero(pStartOemDataRsp, sizeof(tStartOemDataRsp));
1583 msg_subtype = (uint32_t *) (&pStartOemDataRsp->oemDataRsp[0]);
1584 *msg_subtype = WMI_OEM_CAPABILITY_RSP;
1585 cdf_mem_copy(&pStartOemDataRsp->oemDataRsp[4], data, datalen);
1586
1587 WMA_LOGI("%s: Sending WMA_START_OEM_DATA_RSP, data len (%d)",
1588 __func__, datalen);
1589
1590 wma_send_msg(wma, WMA_START_OEM_DATA_RSP, (void *)pStartOemDataRsp, 0);
1591 return 0;
1592}
1593
1594/**
1595 * wma_oem_measurement_report_event_callback() - OEM measurement report handler
1596 * @handle: wma handle
1597 * @datap: data ptr
1598 * @len: data length
1599 *
1600 * Return: 0 for success or error code
1601 */
1602int wma_oem_measurement_report_event_callback(void *handle,
1603 uint8_t *datap,
1604 uint32_t len)
1605{
1606 tp_wma_handle wma = (tp_wma_handle) handle;
1607 WMI_OEM_MEASUREMENT_REPORT_EVENTID_param_tlvs *param_buf;
1608 uint8_t *data;
1609 uint32_t datalen;
1610 uint32_t *msg_subtype;
1611 tStartOemDataRsp *pStartOemDataRsp;
1612
1613 param_buf = (WMI_OEM_MEASUREMENT_REPORT_EVENTID_param_tlvs *) datap;
1614 if (!param_buf) {
1615 WMA_LOGE("%s: Received NULL buf ptr from FW", __func__);
1616 return -ENOMEM;
1617 }
1618
1619 data = param_buf->data;
1620 datalen = param_buf->num_data;
1621
1622 if (!data) {
1623 WMA_LOGE("%s: Received NULL data from FW", __func__);
1624 return -EINVAL;
1625 }
1626
1627 /* wma puts 4 bytes prefix for msg subtype, so length
1628 * of data received from target should be 4 bytes less
1629 * then max allowed
1630 */
1631 if (datalen > (OEM_DATA_RSP_SIZE - 4)) {
1632 WMA_LOGE("%s: Received data len (%d) exceeds max value (%d)",
1633 __func__, datalen, (OEM_DATA_RSP_SIZE - 4));
1634 return -EINVAL;
1635 }
1636
1637 pStartOemDataRsp = cdf_mem_malloc(sizeof(*pStartOemDataRsp));
1638 if (!pStartOemDataRsp) {
1639 WMA_LOGE("%s: Failed to alloc pStartOemDataRsp", __func__);
1640 return -ENOMEM;
1641 }
1642
1643 cdf_mem_zero(pStartOemDataRsp, sizeof(tStartOemDataRsp));
1644 msg_subtype = (uint32_t *) (&pStartOemDataRsp->oemDataRsp[0]);
1645 *msg_subtype = WMI_OEM_MEASUREMENT_RSP;
1646 cdf_mem_copy(&pStartOemDataRsp->oemDataRsp[4], data, datalen);
1647
1648 WMA_LOGI("%s: Sending WMA_START_OEM_DATA_RSP, data len (%d)",
1649 __func__, datalen);
1650
1651 wma_send_msg(wma, WMA_START_OEM_DATA_RSP, (void *)pStartOemDataRsp, 0);
1652 return 0;
1653}
1654
1655/**
1656 * wma_oem_error_report_event_callback() - OEM error report handler
1657 * @handle: wma handle
1658 * @datap: data ptr
1659 * @len: data length
1660 *
1661 * Return: 0 for success or error code
1662 */
1663int wma_oem_error_report_event_callback(void *handle,
1664 uint8_t *datap, uint32_t len)
1665{
1666 tp_wma_handle wma = (tp_wma_handle) handle;
1667 WMI_OEM_ERROR_REPORT_EVENTID_param_tlvs *param_buf;
1668 uint8_t *data;
1669 uint32_t datalen;
1670 uint32_t *msg_subtype;
1671 tStartOemDataRsp *pStartOemDataRsp;
1672
1673 param_buf = (WMI_OEM_ERROR_REPORT_EVENTID_param_tlvs *) datap;
1674 if (!param_buf) {
1675 WMA_LOGE("%s: Received NULL buf ptr from FW", __func__);
1676 return -ENOMEM;
1677 }
1678
1679 data = param_buf->data;
1680 datalen = param_buf->num_data;
1681
1682 if (!data) {
1683 WMA_LOGE("%s: Received NULL data from FW", __func__);
1684 return -EINVAL;
1685 }
1686
1687 /* wma puts 4 bytes prefix for msg subtype, so length
1688 * of data received from target should be 4 bytes less
1689 * then max allowed
1690 */
1691 if (datalen > (OEM_DATA_RSP_SIZE - 4)) {
1692 WMA_LOGE("%s: Received data len (%d) exceeds max value (%d)",
1693 __func__, datalen, (OEM_DATA_RSP_SIZE - 4));
1694 return -EINVAL;
1695 }
1696
1697 pStartOemDataRsp = cdf_mem_malloc(sizeof(*pStartOemDataRsp));
1698 if (!pStartOemDataRsp) {
1699 WMA_LOGE("%s: Failed to alloc pStartOemDataRsp", __func__);
1700 return -ENOMEM;
1701 }
1702
1703 cdf_mem_zero(pStartOemDataRsp, sizeof(tStartOemDataRsp));
1704 msg_subtype = (uint32_t *) (&pStartOemDataRsp->oemDataRsp[0]);
1705 *msg_subtype = WMI_OEM_ERROR_REPORT_RSP;
1706 cdf_mem_copy(&pStartOemDataRsp->oemDataRsp[4], data, datalen);
1707
1708 WMA_LOGI("%s: Sending WMA_START_OEM_DATA_RSP, data len (%d)",
1709 __func__, datalen);
1710
1711 wma_send_msg(wma, WMA_START_OEM_DATA_RSP, (void *)pStartOemDataRsp, 0);
1712 return 0;
1713}
1714
1715/**
1716 * wma_start_oem_data_req() - start OEM data request to target
1717 * @wma_handle: wma handle
1718 * @startOemDataReq: start request params
1719 *
1720 * Return: none
1721 */
1722void wma_start_oem_data_req(tp_wma_handle wma_handle,
1723 tStartOemDataReq *startOemDataReq)
1724{
1725 wmi_buf_t buf;
1726 uint8_t *cmd;
1727 int ret = 0;
1728 uint32_t *msg_subtype;
1729 tStartOemDataRsp *pStartOemDataRsp;
1730
1731 WMA_LOGD("%s: Send OEM Data Request to target", __func__);
1732
1733 if (!startOemDataReq) {
1734 WMA_LOGE("%s: startOemDataReq is null", __func__);
1735 goto out;
1736 }
1737
1738 if (!wma_handle || !wma_handle->wmi_handle) {
1739 WMA_LOGE("%s: WMA is closed, can not send Oem data request cmd",
1740 __func__);
1741 return;
1742 }
1743
1744 buf = wmi_buf_alloc(wma_handle->wmi_handle,
1745 (OEM_DATA_REQ_SIZE + WMI_TLV_HDR_SIZE));
1746 if (!buf) {
1747 WMA_LOGE("%s:wmi_buf_alloc failed", __func__);
1748 goto out;
1749 }
1750
1751 cmd = (uint8_t *) wmi_buf_data(buf);
1752
1753 WMITLV_SET_HDR(cmd, WMITLV_TAG_ARRAY_BYTE, OEM_DATA_REQ_SIZE);
1754 cmd += WMI_TLV_HDR_SIZE;
1755 cdf_mem_copy(cmd, &startOemDataReq->oemDataReq[0], OEM_DATA_REQ_SIZE);
1756
1757 WMA_LOGI("%s: Sending OEM Data Request to target, data len (%d)",
1758 __func__, OEM_DATA_REQ_SIZE);
1759
1760 ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf,
1761 (OEM_DATA_REQ_SIZE +
1762 WMI_TLV_HDR_SIZE), WMI_OEM_REQ_CMDID);
1763
1764 if (ret != EOK) {
1765 WMA_LOGE("%s:wmi cmd send failed", __func__);
1766 cdf_nbuf_free(buf);
1767 }
1768
1769out:
1770 /* free oem data req buffer received from UMAC */
1771 if (startOemDataReq)
1772 cdf_mem_free(startOemDataReq);
1773
1774 /* Now send data resp back to PE/SME with message sub-type of
1775 * WMI_OEM_INTERNAL_RSP. This is required so that PE/SME clears
1776 * up pending active command. Later when desired oem response(s)
1777 * comes as wmi event from target then those shall be passed
1778 * to oem application
1779 */
1780 pStartOemDataRsp = cdf_mem_malloc(sizeof(*pStartOemDataRsp));
1781 if (!pStartOemDataRsp) {
1782 WMA_LOGE("%s:failed to allocate memory for OEM Data Resp to PE",
1783 __func__);
1784 return;
1785 }
1786 cdf_mem_zero(pStartOemDataRsp, sizeof(tStartOemDataRsp));
1787 msg_subtype = (uint32_t *) (&pStartOemDataRsp->oemDataRsp[0]);
1788 *msg_subtype = WMI_OEM_INTERNAL_RSP;
1789
1790 WMA_LOGI("%s: Sending WMA_START_OEM_DATA_RSP to clear up PE/SME pending cmd",
1791 __func__);
1792
1793 wma_send_msg(wma_handle, WMA_START_OEM_DATA_RSP,
1794 (void *)pStartOemDataRsp, 0);
1795
1796 return;
1797}
1798#endif /* FEATURE_OEM_DATA_SUPPORT */
1799
1800
1801/**
1802 * wma_unified_dfs_radar_rx_event_handler() - dfs radar rx event handler
1803 * @handle: wma handle
1804 * @data: data buffer
1805 * @datalen: data length
1806 *
1807 * WMI handler for WMI_DFS_RADAR_EVENTID
1808 * This handler is registered for handling
1809 * filtered DFS Phyerror. This handler is
1810 * will be invoked only when DFS Phyerr
1811 * filtering offload is enabled.
1812 *
1813 * Return: 1 for Success and 0 for error
1814 */
1815static int wma_unified_dfs_radar_rx_event_handler(void *handle,
1816 uint8_t *data,
1817 uint32_t datalen)
1818{
1819 tp_wma_handle wma = (tp_wma_handle) handle;
1820 struct ieee80211com *ic;
1821 struct ath_dfs *dfs;
1822 struct dfs_event *event;
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05301823 struct dfs_ieee80211_channel *chan;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001824 int empty;
1825 int do_check_chirp = 0;
1826 int is_hw_chirp = 0;
1827 int is_sw_chirp = 0;
1828 int is_pri = 0;
1829
1830 WMI_DFS_RADAR_EVENTID_param_tlvs *param_tlvs;
1831 wmi_dfs_radar_event_fixed_param *radar_event;
1832
1833 ic = wma->dfs_ic;
1834 if (NULL == ic) {
1835 WMA_LOGE("%s: dfs_ic is NULL ", __func__);
1836 return 0;
1837 }
1838
1839 dfs = (struct ath_dfs *)ic->ic_dfs;
1840 param_tlvs = (WMI_DFS_RADAR_EVENTID_param_tlvs *) data;
1841
1842 if (NULL == dfs) {
1843 WMA_LOGE("%s: dfs is NULL ", __func__);
1844 return 0;
1845 }
1846 /*
1847 * This parameter holds the number
1848 * of phyerror interrupts to the host
1849 * after the phyerrors have passed through
1850 * false detect filters in the firmware.
1851 */
1852 dfs->dfs_phyerr_count++;
1853
1854 if (!param_tlvs) {
1855 WMA_LOGE("%s: Received NULL data from FW", __func__);
1856 return 0;
1857 }
1858
1859 radar_event = param_tlvs->fixed_param;
1860
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05301861 cdf_spin_lock_bh(&ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001862 chan = ic->ic_curchan;
Edhar, Mahesh Kumar35d9b2e2015-10-26 17:06:23 +05301863 if (ic->disable_phy_err_processing) {
1864 WMA_LOGD("%s: radar indication done,drop phyerror event",
1865 __func__);
1866 cdf_spin_unlock_bh(&ic->chan_lock);
1867 return 0;
1868 }
1869
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001870 if (CHANNEL_STATE_DFS != cds_get_channel_state(chan->ic_ieee)) {
1871 WMA_LOGE
1872 ("%s: Invalid DFS Phyerror event. Channel=%d is Non-DFS",
1873 __func__, chan->ic_ieee);
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05301874 cdf_spin_unlock_bh(&ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001875 return 0;
1876 }
1877
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05301878 cdf_spin_unlock_bh(&ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001879 dfs->ath_dfs_stats.total_phy_errors++;
1880
1881 if (dfs->dfs_caps.ath_chip_is_bb_tlv) {
1882 do_check_chirp = 1;
1883 is_pri = 1;
1884 is_hw_chirp = radar_event->pulse_is_chirp;
1885
1886 if ((uint32_t) dfs->dfs_phyerr_freq_min >
1887 radar_event->pulse_center_freq) {
1888 dfs->dfs_phyerr_freq_min =
1889 (int)radar_event->pulse_center_freq;
1890 }
1891
1892 if (dfs->dfs_phyerr_freq_max <
1893 (int)radar_event->pulse_center_freq) {
1894 dfs->dfs_phyerr_freq_max =
1895 (int)radar_event->pulse_center_freq;
1896 }
1897 }
1898
1899 /*
1900 * Now, add the parsed, checked and filtered
1901 * radar phyerror event radar pulse event list.
1902 * This event will then be processed by
1903 * dfs_radar_processevent() to see if the pattern
1904 * of pulses in radar pulse list match any radar
1905 * singnature in the current regulatory domain.
1906 */
1907
1908 ATH_DFSEVENTQ_LOCK(dfs);
1909 empty = STAILQ_EMPTY(&(dfs->dfs_eventq));
1910 ATH_DFSEVENTQ_UNLOCK(dfs);
1911 if (empty) {
1912 return 0;
1913 }
1914 /*
1915 * Add the event to the list, if there's space.
1916 */
1917 ATH_DFSEVENTQ_LOCK(dfs);
1918 event = STAILQ_FIRST(&(dfs->dfs_eventq));
1919 if (event == NULL) {
1920 ATH_DFSEVENTQ_UNLOCK(dfs);
1921 WMA_LOGE("%s: No more space left for queuing DFS Phyerror events",
1922 __func__);
1923 return 0;
1924 }
1925 STAILQ_REMOVE_HEAD(&(dfs->dfs_eventq), re_list);
1926 ATH_DFSEVENTQ_UNLOCK(dfs);
1927 dfs->dfs_phyerr_queued_count++;
1928 dfs->dfs_phyerr_w53_counter++;
1929 event->re_dur = (uint8_t) radar_event->pulse_duration;
1930 event->re_rssi = radar_event->rssi;
1931 event->re_ts = radar_event->pulse_detect_ts & DFS_TSMASK;
1932 event->re_full_ts = (((uint64_t) radar_event->upload_fullts_high) << 32)
1933 | radar_event->upload_fullts_low;
1934
1935 /*
1936 * Index of peak magnitude
1937 */
1938 event->sidx = radar_event->peak_sidx;
1939
1940 /*
1941 * Handle chirp flags.
1942 */
1943 if (do_check_chirp) {
1944 event->re_flags |= DFS_EVENT_CHECKCHIRP;
1945 if (is_hw_chirp) {
1946 event->re_flags |= DFS_EVENT_HW_CHIRP;
1947 }
1948 if (is_sw_chirp) {
1949 event->re_flags |= DFS_EVENT_SW_CHIRP;
1950 }
1951 }
1952 /*
1953 * Correctly set which channel is being reported on
1954 */
1955 if (is_pri) {
1956 event->re_chanindex = (uint8_t) dfs->dfs_curchan_radindex;
1957 } else {
1958 if (dfs->dfs_extchan_radindex == -1) {
1959 WMA_LOGI("%s phyerr on ext channel", __func__);
1960 }
1961 event->re_chanindex = (uint8_t) dfs->dfs_extchan_radindex;
1962 WMA_LOGI("%s:New extension channel event is added to queue",
1963 __func__);
1964 }
1965
1966 ATH_DFSQ_LOCK(dfs);
1967
1968 STAILQ_INSERT_TAIL(&(dfs->dfs_radarq), event, re_list);
1969
1970 empty = STAILQ_EMPTY(&dfs->dfs_radarq);
1971
1972 ATH_DFSQ_UNLOCK(dfs);
1973
1974 if (!empty && !dfs->ath_radar_tasksched) {
1975 dfs->ath_radar_tasksched = 1;
1976 OS_SET_TIMER(&dfs->ath_dfs_task_timer, 0);
1977 }
1978
1979 return 1;
1980
1981}
1982
1983/**
1984 * wma_unified_phyerr_rx_event_handler() - phyerr event handler
1985 * @handle: wma handle
1986 * @data: data buffer
1987 * @datalen: buffer length
1988 *
1989 * WMI Handler for WMI_PHYERR_EVENTID event from firmware.
1990 * This handler is currently handling only DFS phy errors.
1991 * This handler will be invoked only when the DFS phyerror
1992 * filtering offload is disabled.
1993 *
1994 * Return: 1:Success, 0:Failure
1995 */
1996static int wma_unified_phyerr_rx_event_handler(void *handle,
1997 uint8_t *data, uint32_t datalen)
1998{
1999 tp_wma_handle wma = (tp_wma_handle) handle;
2000 WMI_PHYERR_EVENTID_param_tlvs *param_tlvs;
2001 wmi_comb_phyerr_rx_hdr *pe_hdr;
2002 uint8_t *bufp;
2003 wmi_single_phyerr_rx_event *ev;
2004 struct ieee80211com *ic = wma->dfs_ic;
2005 cdf_size_t n;
2006 A_UINT64 tsf64 = 0;
2007 int phy_err_code = 0;
2008 int error = 0;
2009 tpAniSirGlobal mac_ctx =
2010 (tpAniSirGlobal)cds_get_context(CDF_MODULE_ID_PE);
2011 bool enable_log = false;
2012
2013 if (NULL == mac_ctx) {
2014 WMA_LOGE("%s: mac_ctx is NULL", __func__);
2015 return 0;
2016 }
2017 enable_log = mac_ctx->sap.enable_dfs_phy_error_logs;
2018
2019 param_tlvs = (WMI_PHYERR_EVENTID_param_tlvs *) data;
2020
2021 if (!param_tlvs) {
2022 WMA_LOGE("%s: Received NULL data from FW", __func__);
2023 return 0;
2024 }
2025
2026 pe_hdr = param_tlvs->hdr;
2027 if (pe_hdr == NULL) {
2028 WMA_LOGE("%s: Received Data PE Header is NULL", __func__);
2029 return 0;
2030 }
2031
2032 /* Ensure it's at least the size of the header */
2033 if (datalen < sizeof(*pe_hdr)) {
2034 WMA_LOGE("%s: Expected minimum size %zu, received %d",
2035 __func__, sizeof(*pe_hdr), datalen);
2036 return 0;
2037 }
2038 if (pe_hdr->buf_len > DFS_MAX_BUF_LENGHT) {
2039 WMA_LOGE("%s: Received Invalid Phyerror event buffer length = %d"
2040 "Maximum allowed buf length = %d", __func__,
2041 pe_hdr->buf_len, DFS_MAX_BUF_LENGHT);
2042
2043 return 0;
2044 }
2045
2046 /*
2047 * Reconstruct the 64 bit event TSF. This isn't from the MAC, it's
2048 * at the time the event was sent to us, the TSF value will be
2049 * in the future.
2050 */
2051 tsf64 = pe_hdr->tsf_l32;
2052 tsf64 |= (((uint64_t) pe_hdr->tsf_u32) << 32);
2053
2054 /*
2055 * Loop over the bufp, extracting out phyerrors
2056 * wmi_unified_comb_phyerr_rx_event.bufp is a char pointer,
2057 * which isn't correct here - what we have received here
2058 * is an array of TLV-style PHY errors.
2059 */
2060 n = 0; /* Start just after the header */
2061 bufp = param_tlvs->bufp;
2062 while (n < pe_hdr->buf_len) {
2063 /* ensure there's at least space for the header */
2064 if ((pe_hdr->buf_len - n) < sizeof(ev->hdr)) {
2065 WMA_LOGE("%s: Not enough space.(datalen=%d, n=%zu, hdr=%zu bytes",
2066 __func__, pe_hdr->buf_len, n, sizeof(ev->hdr));
2067 error = 1;
2068 break;
2069 }
2070 /*
2071 * Obtain a pointer to the beginning of the current event.
2072 * data[0] is the beginning of the WMI payload.
2073 */
2074 ev = (wmi_single_phyerr_rx_event *) &bufp[n];
2075
2076 /*
2077 * Sanity check the buffer length of the event against
2078 * what we currently have.
2079 * Since buf_len is 32 bits, we check if it overflows
2080 * a large 32 bit value. It's not 0x7fffffff because
2081 * we increase n by (buf_len + sizeof(hdr)), which would
2082 * in itself cause n to overflow.
2083 * If "int" is 64 bits then this becomes a moot point.
2084 */
2085 if (ev->hdr.buf_len > 0x7f000000) {
2086 WMA_LOGE("%s:buf_len is garbage (0x%x)", __func__,
2087 ev->hdr.buf_len);
2088 error = 1;
2089 break;
2090 }
2091 if (n + ev->hdr.buf_len > pe_hdr->buf_len) {
2092 WMA_LOGE("%s: buf_len exceeds available space n=%zu,"
2093 "buf_len=%d, datalen=%d",
2094 __func__, n, ev->hdr.buf_len, pe_hdr->buf_len);
2095 error = 1;
2096 break;
2097 }
2098 phy_err_code = WMI_UNIFIED_PHYERRCODE_GET(&ev->hdr);
2099
2100 /*
2101 * If the phyerror category matches,
2102 * pass radar events to the dfs pattern matching code.
2103 * Don't pass radar events with no buffer payload.
2104 */
2105 if (phy_err_code == 0x5 || phy_err_code == 0x24) {
2106 if (ev->hdr.buf_len > 0) {
2107 /* Calling in to the DFS module to process the phyerr */
2108 dfs_process_phyerr(ic, &ev->bufp[0],
2109 ev->hdr.buf_len,
2110 WMI_UNIFIED_RSSI_COMB_GET
2111 (&ev->hdr) & 0xff,
2112 /* Extension RSSI */
2113 WMI_UNIFIED_RSSI_COMB_GET
2114 (&ev->hdr) & 0xff,
2115 ev->hdr.tsf_timestamp,
2116 tsf64, enable_log);
2117 }
2118 }
2119
2120 /*
2121 * Advance the buffer pointer to the next PHY error.
2122 * buflen is the length of this payload, so we need to
2123 * advance past the current header _AND_ the payload.
2124 */
2125 n += sizeof(*ev) + ev->hdr.buf_len;
2126
2127 } /*end while() */
2128 if (error)
2129 return 0;
2130 else
2131 return 1;
2132}
2133
2134/**
2135 * wma_register_dfs_event_handler() - register dfs event handler
2136 * @wma_handle: wma handle
2137 *
2138 * Register appropriate dfs phyerror event handler
2139 * based on phyerror filtering offload is enabled
2140 * or disabled.
2141 *
2142 * Return: none
2143 */
2144void wma_register_dfs_event_handler(tp_wma_handle wma_handle)
2145{
2146 if (NULL == wma_handle) {
2147 WMA_LOGE("%s:wma_handle is NULL", __func__);
2148 return;
2149 }
2150
2151 if (false == wma_handle->dfs_phyerr_filter_offload) {
2152 /*
2153 * Register the wma_unified_phyerr_rx_event_handler
2154 * for filtering offload disabled case to handle
2155 * the DFS phyerrors.
2156 */
2157 WMA_LOGD("%s:Phyerror Filtering offload is Disabled in ini",
2158 __func__);
2159 wmi_unified_register_event_handler(wma_handle->wmi_handle,
2160 WMI_PHYERR_EVENTID,
2161 wma_unified_phyerr_rx_event_handler);
2162 WMA_LOGD("%s: WMI_PHYERR_EVENTID event handler registered",
2163 __func__);
2164 } else {
2165 WMA_LOGD("%s:Phyerror Filtering offload is Enabled in ini",
2166 __func__);
2167 wmi_unified_register_event_handler(wma_handle->wmi_handle,
2168 WMI_DFS_RADAR_EVENTID,
2169 wma_unified_dfs_radar_rx_event_handler);
2170 WMA_LOGD("%s:WMI_DFS_RADAR_EVENTID event handler registered",
2171 __func__);
2172 }
2173
2174 return;
2175}
2176
2177
2178/**
2179 * wma_unified_dfs_phyerr_filter_offload_enable() - enable dfs phyerr filter
2180 * @wma_handle: wma handle
2181 *
2182 * Send WMI_DFS_PHYERR_FILTER_ENA_CMDID or
2183 * WMI_DFS_PHYERR_FILTER_DIS_CMDID command
2184 * to firmware based on phyerr filtering
2185 * offload status.
2186 *
2187 * Return: 1 success, 0 failure
2188 */
2189int
2190wma_unified_dfs_phyerr_filter_offload_enable(tp_wma_handle wma_handle)
2191{
2192 wmi_dfs_phyerr_filter_ena_cmd_fixed_param *enable_phyerr_offload_cmd;
2193 wmi_dfs_phyerr_filter_dis_cmd_fixed_param *disable_phyerr_offload_cmd;
2194 wmi_buf_t buf;
2195 uint16_t len;
2196 int ret;
2197
2198 if (NULL == wma_handle) {
2199 WMA_LOGE("%s:wma_handle is NULL", __func__);
2200 return 0;
2201 }
2202
2203 if (false == wma_handle->dfs_phyerr_filter_offload) {
2204 WMA_LOGD("%s:Phyerror Filtering offload is Disabled in ini",
2205 __func__);
2206 len = sizeof(*disable_phyerr_offload_cmd);
2207 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
2208 if (!buf) {
2209 WMA_LOGE("%s:wmi_buf_alloc failed", __func__);
2210 return 0;
2211 }
2212 disable_phyerr_offload_cmd =
2213 (wmi_dfs_phyerr_filter_dis_cmd_fixed_param *)
2214 wmi_buf_data(buf);
2215
2216 WMITLV_SET_HDR(&disable_phyerr_offload_cmd->tlv_header,
2217 WMITLV_TAG_STRUC_wmi_dfs_phyerr_filter_dis_cmd_fixed_param,
2218 WMITLV_GET_STRUCT_TLVLEN
2219 (wmi_dfs_phyerr_filter_dis_cmd_fixed_param));
2220
2221 /*
2222 * Send WMI_DFS_PHYERR_FILTER_DIS_CMDID
2223 * to the firmware to disable the phyerror
2224 * filtering offload.
2225 */
2226 ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len,
2227 WMI_DFS_PHYERR_FILTER_DIS_CMDID);
2228 if (ret < 0) {
2229 WMA_LOGE("%s: Failed to send WMI_DFS_PHYERR_FILTER_DIS_CMDID ret=%d",
2230 __func__, ret);
2231 wmi_buf_free(buf);
2232 return 0;
2233 }
2234 WMA_LOGD("%s: WMI_DFS_PHYERR_FILTER_DIS_CMDID Send Success",
2235 __func__);
2236 } else {
2237 WMA_LOGD("%s:Phyerror Filtering offload is Enabled in ini",
2238 __func__);
2239
2240 len = sizeof(*enable_phyerr_offload_cmd);
2241 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
2242 if (!buf) {
2243 WMA_LOGE("%s:wmi_buf_alloc failed", __func__);
2244 return 0;
2245 }
2246
2247 enable_phyerr_offload_cmd =
2248 (wmi_dfs_phyerr_filter_ena_cmd_fixed_param *)
2249 wmi_buf_data(buf);
2250
2251 WMITLV_SET_HDR(&enable_phyerr_offload_cmd->tlv_header,
2252 WMITLV_TAG_STRUC_wmi_dfs_phyerr_filter_ena_cmd_fixed_param,
2253 WMITLV_GET_STRUCT_TLVLEN
2254 (wmi_dfs_phyerr_filter_ena_cmd_fixed_param));
2255
2256 /*
2257 * Send a WMI_DFS_PHYERR_FILTER_ENA_CMDID
2258 * to the firmware to enable the phyerror
2259 * filtering offload.
2260 */
2261 ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len,
2262 WMI_DFS_PHYERR_FILTER_ENA_CMDID);
2263
2264 if (ret < 0) {
2265 WMA_LOGE("%s: Failed to send WMI_DFS_PHYERR_FILTER_ENA_CMDID ret=%d",
2266 __func__, ret);
2267 wmi_buf_free(buf);
2268 return 0;
2269 }
2270 WMA_LOGD("%s: WMI_DFS_PHYERR_FILTER_ENA_CMDID Send Success",
2271 __func__);
2272 }
2273
2274 return 1;
2275}
2276
2277#if !defined(REMOVE_PKT_LOG)
2278/**
2279 * wma_pktlog_wmi_send_cmd() - send pktlog enable/disable command to target
2280 * @handle: wma handle
2281 * @params: pktlog params
2282 *
2283 * Return: CDF status
2284 */
2285CDF_STATUS wma_pktlog_wmi_send_cmd(WMA_HANDLE handle,
2286 struct ath_pktlog_wmi_params *params)
2287{
2288 tp_wma_handle wma_handle = (tp_wma_handle) handle;
2289 WMI_PKTLOG_EVENT PKTLOG_EVENT;
2290 WMI_CMD_ID CMD_ID;
2291 wmi_pdev_pktlog_enable_cmd_fixed_param *cmd;
2292 wmi_pdev_pktlog_disable_cmd_fixed_param *disable_cmd;
2293 int len = 0;
2294 wmi_buf_t buf;
2295
2296 /*Check if packet log is enabled in cfg.ini */
2297 if (!cds_is_packet_log_enabled()) {
2298 WMA_LOGE("%s:pkt log is not enabled in cfg.ini", __func__);
2299 return CDF_STATUS_E_FAILURE;
2300 }
2301
2302 PKTLOG_EVENT = params->pktlog_event;
2303 CMD_ID = params->cmd_id;
2304
2305 switch (CMD_ID) {
2306 case WMI_PDEV_PKTLOG_ENABLE_CMDID:
2307 len = sizeof(*cmd);
2308 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
2309 if (!buf) {
2310 WMA_LOGE("%s:wmi_buf_alloc failed", __func__);
2311 return CDF_STATUS_E_NOMEM;
2312 }
2313 cmd = (wmi_pdev_pktlog_enable_cmd_fixed_param *)
2314 wmi_buf_data(buf);
2315 WMITLV_SET_HDR(&cmd->tlv_header,
2316 WMITLV_TAG_STRUC_wmi_pdev_pktlog_enable_cmd_fixed_param,
2317 WMITLV_GET_STRUCT_TLVLEN
2318 (wmi_pdev_pktlog_enable_cmd_fixed_param));
2319 cmd->evlist = PKTLOG_EVENT;
2320 if (wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len,
2321 WMI_PDEV_PKTLOG_ENABLE_CMDID)) {
2322 WMA_LOGE("failed to send pktlog enable cmdid");
2323 goto wmi_send_failed;
2324 }
2325 break;
2326 case WMI_PDEV_PKTLOG_DISABLE_CMDID:
2327 len = sizeof(*disable_cmd);
2328 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
2329 if (!buf) {
2330 WMA_LOGE("%s:wmi_buf_alloc failed", __func__);
2331 return CDF_STATUS_E_NOMEM;
2332 }
2333 disable_cmd = (wmi_pdev_pktlog_disable_cmd_fixed_param *)
2334 wmi_buf_data(buf);
2335 WMITLV_SET_HDR(&disable_cmd->tlv_header,
2336 WMITLV_TAG_STRUC_wmi_pdev_pktlog_disable_cmd_fixed_param,
2337 WMITLV_GET_STRUCT_TLVLEN
2338 (wmi_pdev_pktlog_disable_cmd_fixed_param));
2339 disable_cmd->reserved0 = 0;
2340 if (wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len,
2341 WMI_PDEV_PKTLOG_DISABLE_CMDID)) {
2342 WMA_LOGE("failed to send pktlog disable cmdid");
2343 goto wmi_send_failed;
2344 }
2345 break;
2346 default:
2347 WMA_LOGD("%s: invalid PKTLOG command", __func__);
2348 break;
2349 }
2350
2351 return CDF_STATUS_SUCCESS;
2352
2353wmi_send_failed:
2354 wmi_buf_free(buf);
2355 return CDF_STATUS_E_FAILURE;
2356}
2357#endif /* REMOVE_PKT_LOG */
2358
2359static void wma_send_status_to_suspend_ind(tp_wma_handle wma, bool suspended)
2360{
2361 tSirReadyToSuspendInd *ready_to_suspend;
2362 CDF_STATUS status;
2363 cds_msg_t cds_msg;
2364 uint8_t len;
2365
2366 WMA_LOGD("Posting ready to suspend indication to umac");
2367
2368 len = sizeof(tSirReadyToSuspendInd);
2369 ready_to_suspend = (tSirReadyToSuspendInd *) cdf_mem_malloc(len);
2370
2371 if (NULL == ready_to_suspend) {
2372 WMA_LOGE("%s: Memory allocation failure", __func__);
2373 return;
2374 }
2375
2376 ready_to_suspend->mesgType = eWNI_SME_READY_TO_SUSPEND_IND;
2377 ready_to_suspend->mesgLen = len;
2378 ready_to_suspend->suspended = suspended;
2379
2380 cds_msg.type = eWNI_SME_READY_TO_SUSPEND_IND;
2381 cds_msg.bodyptr = (void *)ready_to_suspend;
2382 cds_msg.bodyval = 0;
2383
2384 status = cds_mq_post_message(CDS_MQ_ID_SME, &cds_msg);
2385 if (status != CDF_STATUS_SUCCESS) {
2386 WMA_LOGE("Failed to post ready to suspend");
2387 cdf_mem_free(ready_to_suspend);
2388 }
2389}
2390
2391/**
2392 * wma_wow_wake_reason_str() - Converts wow wakeup reason code to text format
2393 * @wake_reason - WOW wake reason
2394 *
2395 * Return: reason code in string format
2396 */
2397static const u8 *wma_wow_wake_reason_str(A_INT32 wake_reason)
2398{
2399 switch (wake_reason) {
2400 case WOW_REASON_UNSPECIFIED:
2401 return "UNSPECIFIED";
2402 case WOW_REASON_NLOD:
2403 return "NLOD";
2404 case WOW_REASON_AP_ASSOC_LOST:
2405 return "AP_ASSOC_LOST";
2406 case WOW_REASON_LOW_RSSI:
2407 return "LOW_RSSI";
2408 case WOW_REASON_DEAUTH_RECVD:
2409 return "DEAUTH_RECVD";
2410 case WOW_REASON_DISASSOC_RECVD:
2411 return "DISASSOC_RECVD";
2412 case WOW_REASON_GTK_HS_ERR:
2413 return "GTK_HS_ERR";
2414 case WOW_REASON_EAP_REQ:
2415 return "EAP_REQ";
2416 case WOW_REASON_FOURWAY_HS_RECV:
2417 return "FOURWAY_HS_RECV";
2418 case WOW_REASON_TIMER_INTR_RECV:
2419 return "TIMER_INTR_RECV";
2420 case WOW_REASON_PATTERN_MATCH_FOUND:
2421 return "PATTERN_MATCH_FOUND";
2422 case WOW_REASON_RECV_MAGIC_PATTERN:
2423 return "RECV_MAGIC_PATTERN";
2424 case WOW_REASON_P2P_DISC:
2425 return "P2P_DISC";
2426#ifdef FEATURE_WLAN_LPHB
2427 case WOW_REASON_WLAN_HB:
2428 return "WLAN_HB";
2429#endif /* FEATURE_WLAN_LPHB */
2430
2431 case WOW_REASON_CSA_EVENT:
2432 return "CSA_EVENT";
2433 case WOW_REASON_PROBE_REQ_WPS_IE_RECV:
2434 return "PROBE_REQ_RECV";
2435 case WOW_REASON_AUTH_REQ_RECV:
2436 return "AUTH_REQ_RECV";
2437 case WOW_REASON_ASSOC_REQ_RECV:
2438 return "ASSOC_REQ_RECV";
2439 case WOW_REASON_HTT_EVENT:
2440 return "WOW_REASON_HTT_EVENT";
2441#ifdef FEATURE_WLAN_RA_FILTERING
2442 case WOW_REASON_RA_MATCH:
2443 return "WOW_REASON_RA_MATCH";
2444#endif /* FEATURE_WLAN_RA_FILTERING */
2445 case WOW_REASON_BEACON_RECV:
2446 return "WOW_REASON_IBSS_BEACON_RECV";
2447#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
2448 case WOW_REASON_HOST_AUTO_SHUTDOWN:
2449 return "WOW_REASON_HOST_AUTO_SHUTDOWN";
2450#endif /* FEATURE_WLAN_AUTO_SHUTDOWN */
2451#ifdef WLAN_FEATURE_ROAM_OFFLOAD
2452 case WOW_REASON_ROAM_HO:
2453 return "WOW_REASON_ROAM_HO";
2454#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
2455#ifdef FEATURE_WLAN_EXTSCAN
2456 case WOW_REASON_EXTSCAN:
2457 return "WOW_REASON_EXTSCAN";
2458#endif
2459 case WOW_REASON_RSSI_BREACH_EVENT:
2460 return "WOW_REASON_RSSI_BREACH_EVENT";
Srinivas Girigowdae80cea92015-11-23 11:33:57 -08002461 case WOW_REASON_NLO_SCAN_COMPLETE:
2462 return "WOW_REASON_NLO_SCAN_COMPLETE";
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002463 }
2464 return "unknown";
2465}
2466
2467/**
2468 * wma_wow_wake_up_stats_display() - display wow wake up stats
2469 * @wma: Pointer to wma handle
2470 *
2471 * Return: none
2472 */
2473static void wma_wow_wake_up_stats_display(tp_wma_handle wma)
2474{
2475 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",
2476 wma->wow_ucast_wake_up_count,
2477 wma->wow_bcast_wake_up_count,
2478 wma->wow_ipv4_mcast_wake_up_count,
2479 wma->wow_ipv6_mcast_wake_up_count,
2480 wma->wow_ipv6_mcast_ra_stats,
2481 wma->wow_ipv6_mcast_ns_stats,
2482 wma->wow_ipv6_mcast_na_stats,
2483 wma->wow_pno_match_wake_up_count,
2484 wma->wow_pno_complete_wake_up_count,
2485 wma->wow_gscan_wake_up_count,
2486 wma->wow_low_rssi_wake_up_count,
2487 wma->wow_rssi_breach_wake_up_count);
2488
2489 return;
2490}
2491
2492/**
2493 * wma_wow_ipv6_mcast_stats() - ipv6 mcast wake up stats
2494 * @wma: Pointer to wma handle
2495 * @data: Pointer to pattern match data
2496 *
2497 * Return: none
2498 */
2499static void wma_wow_ipv6_mcast_stats(tp_wma_handle wma, uint8_t *data)
2500{
2501 static const uint8_t ipv6_mcast[] = {0x86, 0xDD};
2502
2503 if (!memcmp(ipv6_mcast, (data + WMA_ETHER_TYPE_OFFSET),
2504 sizeof(ipv6_mcast))) {
2505 if (WMA_ICMP_V6_HEADER_TYPE ==
2506 *(data + WMA_ICMP_V6_HEADER_OFFSET)) {
2507 if (WMA_ICMP_V6_RA_TYPE ==
2508 *(data + WMA_ICMP_V6_TYPE_OFFSET))
2509 wma->wow_ipv6_mcast_ra_stats++;
2510 else if (WMA_ICMP_V6_NS_TYPE ==
2511 *(data + WMA_ICMP_V6_TYPE_OFFSET))
2512 wma->wow_ipv6_mcast_ns_stats++;
2513 else if (WMA_ICMP_V6_NA_TYPE ==
2514 *(data + WMA_ICMP_V6_TYPE_OFFSET))
2515 wma->wow_ipv6_mcast_na_stats++;
2516 else
2517 WMA_LOGA("ICMP V6 type : 0x%x",
2518 *(data + WMA_ICMP_V6_TYPE_OFFSET));
2519 } else {
2520 WMA_LOGA("ICMP_V6 header 0x%x",
2521 *(data + WMA_ICMP_V6_HEADER_OFFSET));
2522 }
2523 } else {
2524 WMA_LOGA("Ethertype x%x:0x%x",
2525 *(data + WMA_ETHER_TYPE_OFFSET),
2526 *(data + WMA_ETHER_TYPE_OFFSET + 1));
2527 }
2528
2529 return;
2530}
2531
2532/**
2533 * wma_wow_wake_up_stats() - maintain wow pattern match wake up stats
2534 * @wma: Pointer to wma handle
2535 * @data: Pointer to pattern match data
2536 * @len: Pattern match data length
2537 * @event: Wake up event
2538 *
2539 * Return: none
2540 */
2541static void wma_wow_wake_up_stats(tp_wma_handle wma, uint8_t *data,
2542 int32_t len, WOW_WAKE_REASON_TYPE event)
2543{
2544 switch (event) {
2545
2546 case WOW_REASON_PATTERN_MATCH_FOUND:
2547 if (WMA_BCAST_MAC_ADDR == *data) {
2548 wma->wow_bcast_wake_up_count++;
2549 } else if (WMA_MCAST_IPV4_MAC_ADDR == *data) {
2550 wma->wow_ipv4_mcast_wake_up_count++;
2551 } else if (WMA_MCAST_IPV6_MAC_ADDR == *data) {
2552 wma->wow_ipv6_mcast_wake_up_count++;
2553 if (len > WMA_ICMP_V6_TYPE_OFFSET)
2554 wma_wow_ipv6_mcast_stats(wma, data);
2555 else
2556 WMA_LOGA("ICMP_V6 data len %d", len);
2557 } else {
2558 wma->wow_ucast_wake_up_count++;
2559 }
2560 break;
2561
2562 case WOW_REASON_RA_MATCH:
2563 wma->wow_ipv6_mcast_ra_stats++;
2564 break;
2565
2566 case WOW_REASON_NLOD:
2567 wma->wow_pno_match_wake_up_count++;
2568 break;
2569
2570 case WOW_REASON_NLO_SCAN_COMPLETE:
2571 wma->wow_pno_complete_wake_up_count++;
2572 break;
2573
2574 case WOW_REASON_LOW_RSSI:
2575 wma->wow_low_rssi_wake_up_count++;
2576 break;
2577
2578 case WOW_REASON_EXTSCAN:
2579 wma->wow_gscan_wake_up_count++;
2580 break;
2581
2582 case WOW_REASON_RSSI_BREACH_EVENT:
2583 wma->wow_rssi_breach_wake_up_count++;
2584 break;
2585
2586 default:
2587 WMA_LOGE("Unknown wake up reason");
2588 break;
2589 }
2590
2591 wma_wow_wake_up_stats_display(wma);
2592 return;
2593}
2594
2595/**
2596 * wma_wow_wakeup_host_event() - wakeup host event handler
2597 * @handle: wma handle
2598 * @event: event data
2599 * @len: buffer length
2600 *
2601 * Handler to catch wow wakeup host event. This event will have
2602 * reason why the firmware has woken the host.
2603 *
2604 * Return: 0 for success or error
2605 */
2606int wma_wow_wakeup_host_event(void *handle, uint8_t *event,
2607 uint32_t len)
2608{
2609 tp_wma_handle wma = (tp_wma_handle) handle;
2610 WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs *param_buf;
2611 WOW_EVENT_INFO_fixed_param *wake_info;
2612#ifdef FEATURE_WLAN_SCAN_PNO
2613 struct wma_txrx_node *node;
2614#endif /* FEATURE_WLAN_SCAN_PNO */
2615 uint32_t wake_lock_duration = 0;
2616 uint32_t wow_buf_pkt_len = 0;
2617
2618 param_buf = (WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs *) event;
2619 if (!param_buf) {
2620 WMA_LOGE("Invalid wow wakeup host event buf");
2621 return -EINVAL;
2622 }
2623
2624 wake_info = param_buf->fixed_param;
2625
2626 WMA_LOGA("WOW wakeup host event received (reason: %s(%d)) for vdev %d",
2627 wma_wow_wake_reason_str(wake_info->wake_reason),
2628 wake_info->wake_reason, wake_info->vdev_id);
2629
2630 cdf_event_set(&wma->wma_resume_event);
2631
2632 switch (wake_info->wake_reason) {
2633 case WOW_REASON_AUTH_REQ_RECV:
2634 wake_lock_duration = WMA_AUTH_REQ_RECV_WAKE_LOCK_TIMEOUT;
2635 break;
2636
2637 case WOW_REASON_ASSOC_REQ_RECV:
2638 wake_lock_duration = WMA_ASSOC_REQ_RECV_WAKE_LOCK_DURATION;
2639 break;
2640
2641 case WOW_REASON_DEAUTH_RECVD:
2642 wake_lock_duration = WMA_DEAUTH_RECV_WAKE_LOCK_DURATION;
2643 break;
2644
2645 case WOW_REASON_DISASSOC_RECVD:
2646 wake_lock_duration = WMA_DISASSOC_RECV_WAKE_LOCK_DURATION;
2647 break;
2648
2649 case WOW_REASON_AP_ASSOC_LOST:
2650 wake_lock_duration = WMA_BMISS_EVENT_WAKE_LOCK_DURATION;
2651 WMA_LOGA("Beacon miss indication on vdev %x",
2652 wake_info->vdev_id);
2653 wma_beacon_miss_handler(wma, wake_info->vdev_id);
2654 break;
2655#ifdef FEATURE_WLAN_RA_FILTERING
2656 case WOW_REASON_RA_MATCH:
2657 wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_RA_MATCH);
2658 break;
2659#endif /* FEATURE_WLAN_RA_FILTERING */
2660#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
2661 case WOW_REASON_HOST_AUTO_SHUTDOWN:
2662 wake_lock_duration = WMA_AUTO_SHUTDOWN_WAKE_LOCK_DURATION;
2663 WMA_LOGA("Received WOW Auto Shutdown trigger in suspend");
2664 if (wma_post_auto_shutdown_msg())
2665 return -EINVAL;
2666 break;
2667#endif /* FEATURE_WLAN_AUTO_SHUTDOWN */
2668#ifdef FEATURE_WLAN_SCAN_PNO
2669 case WOW_REASON_NLOD:
2670 wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_NLOD);
2671 node = &wma->interfaces[wake_info->vdev_id];
2672 if (node) {
2673 WMA_LOGD("NLO match happened");
2674 node->nlo_match_evt_received = true;
2675 cdf_wake_lock_timeout_acquire(&wma->pno_wake_lock,
2676 WMA_PNO_MATCH_WAKE_LOCK_TIMEOUT,
2677 WIFI_POWER_EVENT_WAKELOCK_PNO);
Srinivas Girigowdae80cea92015-11-23 11:33:57 -08002678 }
2679 break;
2680
2681 case WOW_REASON_NLO_SCAN_COMPLETE:
2682 {
2683 WMI_NLO_SCAN_COMPLETE_EVENTID_param_tlvs param;
2684
2685 WMA_LOGD("Host woken up due to pno scan complete reason");
2686
2687 /* First 4-bytes of wow_packet_buffer is the length */
2688 if (param_buf->wow_packet_buffer) {
2689 param.fixed_param = (wmi_nlo_event *)
2690 (param_buf->wow_packet_buffer + 4);
2691 wma_nlo_scan_cmp_evt_handler(handle,
2692 (u_int8_t *)&param, sizeof(param));
2693 } else
2694 WMA_LOGD("No wow_packet_buffer present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002695 }
2696 break;
2697#endif /* FEATURE_WLAN_SCAN_PNO */
2698
2699 case WOW_REASON_CSA_EVENT:
2700 {
2701 WMI_CSA_HANDLING_EVENTID_param_tlvs param;
2702 WMA_LOGD("Host woken up because of CSA IE");
2703 param.fixed_param = (wmi_csa_event_fixed_param *)
2704 (((uint8_t *) wake_info)
2705 + sizeof(WOW_EVENT_INFO_fixed_param)
2706 + WOW_CSA_EVENT_OFFSET);
2707 wma_csa_offload_handler(handle, (uint8_t *) &param,
2708 sizeof(param));
2709 }
2710 break;
2711
2712#ifdef FEATURE_WLAN_LPHB
2713 case WOW_REASON_WLAN_HB:
2714 wma_lphb_handler(wma, (uint8_t *) param_buf->hb_indevt);
2715 break;
2716#endif /* FEATURE_WLAN_LPHB */
2717
2718 case WOW_REASON_HTT_EVENT:
2719 break;
2720 case WOW_REASON_PATTERN_MATCH_FOUND:
2721 wma_wow_wake_up_stats_display(wma);
2722 WMA_LOGD("Wake up for Rx packet, dump starting from ethernet hdr");
2723 if (param_buf->wow_packet_buffer) {
2724 /* First 4-bytes of wow_packet_buffer is the length */
2725 cdf_mem_copy((uint8_t *) &wow_buf_pkt_len,
2726 param_buf->wow_packet_buffer, 4);
2727 wma_wow_wake_up_stats(wma,
2728 param_buf->wow_packet_buffer + 4,
2729 wow_buf_pkt_len,
2730 WOW_REASON_PATTERN_MATCH_FOUND);
2731 cdf_trace_hex_dump(CDF_MODULE_ID_WMA,
2732 CDF_TRACE_LEVEL_DEBUG,
2733 param_buf->wow_packet_buffer + 4,
2734 wow_buf_pkt_len);
2735 } else {
2736 WMA_LOGE("No wow packet buffer present");
2737 }
2738 break;
2739
2740 case WOW_REASON_LOW_RSSI:
2741 {
2742 /* WOW_REASON_LOW_RSSI is used for all roaming events.
2743 * WMI_ROAM_REASON_BETTER_AP, WMI_ROAM_REASON_BMISS,
2744 * WMI_ROAM_REASON_SUITABLE_AP will be handled by
2745 * wma_roam_event_callback().
2746 */
2747 WMI_ROAM_EVENTID_param_tlvs param;
2748 wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_LOW_RSSI);
2749 if (param_buf->wow_packet_buffer) {
2750 /* Roam event is embedded in wow_packet_buffer */
2751 WMA_LOGD("Host woken up because of roam event");
2752 cdf_mem_copy((uint8_t *) &wow_buf_pkt_len,
2753 param_buf->wow_packet_buffer, 4);
2754 WMA_LOGD("wow_packet_buffer dump");
2755 cdf_trace_hex_dump(CDF_MODULE_ID_WMA,
2756 CDF_TRACE_LEVEL_DEBUG,
2757 param_buf->wow_packet_buffer,
2758 wow_buf_pkt_len);
2759 if (wow_buf_pkt_len >= sizeof(param)) {
2760 param.fixed_param =
2761 (wmi_roam_event_fixed_param *)
2762 (param_buf->wow_packet_buffer + 4);
2763 wma_roam_event_callback(handle,
2764 (uint8_t *) &
2765 param,
2766 sizeof(param));
2767 } else {
2768 WMA_LOGE("Wrong length for roam event = %d bytes",
2769 wow_buf_pkt_len);
2770 }
2771 } else {
2772 /* No wow_packet_buffer means a better AP beacon
2773 * will follow in a later event.
2774 */
2775 WMA_LOGD("Host woken up because of better AP beacon");
2776 }
2777 break;
2778 }
2779 case WOW_REASON_CLIENT_KICKOUT_EVENT:
2780 {
2781 WMI_PEER_STA_KICKOUT_EVENTID_param_tlvs param;
2782 if (param_buf->wow_packet_buffer) {
2783 /* station kickout event embedded in wow_packet_buffer */
2784 WMA_LOGD("Host woken up because of sta_kickout event");
2785 cdf_mem_copy((u_int8_t *) &wow_buf_pkt_len,
2786 param_buf->wow_packet_buffer, 4);
2787 WMA_LOGD("wow_packet_buffer dump");
2788 cdf_trace_hex_dump(CDF_MODULE_ID_WMA,
2789 CDF_TRACE_LEVEL_DEBUG,
2790 param_buf->wow_packet_buffer, wow_buf_pkt_len);
2791 if (wow_buf_pkt_len >= sizeof(param)) {
2792 param.fixed_param = (wmi_peer_sta_kickout_event_fixed_param *)
2793 (param_buf->wow_packet_buffer + 4);
2794 wma_peer_sta_kickout_event_handler(handle,
2795 (u_int8_t *)&param, sizeof(param));
2796 } else {
2797 WMA_LOGE("Wrong length for sta_kickout event = %d bytes",
2798 wow_buf_pkt_len);
2799 }
2800 } else {
2801 WMA_LOGD("No wow_packet_buffer present");
2802 }
2803 break;
2804 }
2805#ifdef FEATURE_WLAN_EXTSCAN
2806 case WOW_REASON_EXTSCAN:
2807 WMA_LOGD("Host woken up because of extscan reason");
2808 wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_EXTSCAN);
2809 if (param_buf->wow_packet_buffer) {
2810 wow_buf_pkt_len =
2811 *(uint32_t *)param_buf->wow_packet_buffer;
2812 wma_extscan_wow_event_callback(handle,
2813 (u_int8_t *)(param_buf->wow_packet_buffer + 4),
2814 wow_buf_pkt_len);
2815 } else
2816 WMA_LOGE("wow_packet_buffer is empty");
2817 break;
2818#endif
2819 case WOW_REASON_RSSI_BREACH_EVENT:
2820 {
2821 WMI_RSSI_BREACH_EVENTID_param_tlvs param;
2822
2823 wma_wow_wake_up_stats(wma, NULL, 0,
2824 WOW_REASON_RSSI_BREACH_EVENT);
2825 WMA_LOGD("Host woken up because of rssi breach reason");
2826 /* rssi breach event is embedded in wow_packet_buffer */
2827 if (param_buf->wow_packet_buffer) {
2828 cdf_mem_copy((u_int8_t *) &wow_buf_pkt_len,
2829 param_buf->wow_packet_buffer, 4);
2830 if (wow_buf_pkt_len >= sizeof(param)) {
2831 param.fixed_param =
2832 (wmi_rssi_breach_event_fixed_param *)
2833 (param_buf->wow_packet_buffer + 4);
2834 wma_rssi_breached_event_handler(handle,
2835 (u_int8_t *)&param,
2836 sizeof(param));
2837 } else {
2838 WMA_LOGE("%s: Wrong length: %d bytes",
2839 __func__, wow_buf_pkt_len);
2840 }
2841 } else
2842 WMA_LOGD("No wow_packet_buffer present");
2843 }
2844 break;
2845 default:
2846 break;
2847 }
2848
2849 if (wake_lock_duration) {
2850 cdf_wake_lock_timeout_acquire(&wma->wow_wake_lock,
2851 wake_lock_duration,
2852 WIFI_POWER_EVENT_WAKELOCK_WOW);
2853 WMA_LOGA("Holding %d msec wake_lock", wake_lock_duration);
2854 }
2855
2856 return 0;
2857}
2858
2859/**
2860 * wma_pdev_resume_event_handler() - PDEV resume event handler
2861 * @handle: wma handle
2862 * @event: event data
2863 * @len: buffer length
2864 *
2865 * Return: 0 for success or error
2866 */
2867int wma_pdev_resume_event_handler(void *handle, uint8_t *event, uint32_t len)
2868{
2869 tp_wma_handle wma = (tp_wma_handle) handle;
2870
2871 WMA_LOGA("Received PDEV resume event");
2872
2873 cdf_event_set(&wma->wma_resume_event);
2874
2875 return 0;
2876}
2877/**
2878 * wma_set_wow_bus_suspend() - set suspend flag
2879 * @wma: wma handle
2880 * @val: value
2881 *
2882 * Return: none
2883 */
2884static inline void wma_set_wow_bus_suspend(tp_wma_handle wma, int val)
2885{
2886
2887 cdf_atomic_set(&wma->is_wow_bus_suspended, val);
2888}
2889
2890
2891
2892/**
2893 * wma_add_wow_wakeup_event() - Configures wow wakeup events.
2894 * @wma: wma handle
2895 * @vdev_id: vdev id
2896 * @bitmap: Event bitmap
2897 * @enable: enable/disable
2898 *
2899 * Return: CDF status
2900 */
2901static CDF_STATUS wma_add_wow_wakeup_event(tp_wma_handle wma,
2902 uint32_t vdev_id,
2903 uint32_t bitmap,
2904 bool enable)
2905{
2906 WMI_WOW_ADD_DEL_EVT_CMD_fixed_param *cmd;
2907 uint16_t len;
2908 wmi_buf_t buf;
2909 int ret;
2910
2911 len = sizeof(WMI_WOW_ADD_DEL_EVT_CMD_fixed_param);
2912 buf = wmi_buf_alloc(wma->wmi_handle, len);
2913 if (!buf) {
2914 WMA_LOGE("%s: Failed allocate wmi buffer", __func__);
2915 return CDF_STATUS_E_NOMEM;
2916 }
2917 cmd = (WMI_WOW_ADD_DEL_EVT_CMD_fixed_param *) wmi_buf_data(buf);
2918 WMITLV_SET_HDR(&cmd->tlv_header,
2919 WMITLV_TAG_STRUC_WMI_WOW_ADD_DEL_EVT_CMD_fixed_param,
2920 WMITLV_GET_STRUCT_TLVLEN
2921 (WMI_WOW_ADD_DEL_EVT_CMD_fixed_param));
2922 cmd->vdev_id = vdev_id;
2923 cmd->is_add = enable;
2924 cmd->event_bitmap = bitmap;
2925
2926 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
2927 WMI_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID);
2928 if (ret) {
2929 WMA_LOGE("Failed to config wow wakeup event");
2930 wmi_buf_free(buf);
2931 return CDF_STATUS_E_FAILURE;
2932 }
2933
2934 WMA_LOGD("Wakeup pattern 0x%x %s in fw", bitmap,
2935 enable ? "enabled" : "disabled");
2936
2937 return CDF_STATUS_SUCCESS;
2938}
2939
2940/**
2941 * wma_send_wow_patterns_to_fw() - Sends WOW patterns to FW.
2942 * @wma: wma handle
2943 * @vdev_id: vdev id
2944 * @ptrn_id: pattern id
2945 * @ptrn: pattern
2946 * @ptrn_len: pattern length
2947 * @ptrn_offset: pattern offset
2948 * @mask: mask
2949 * @mask_len: mask length
2950 * @user: true for user configured pattern and false for default pattern
2951 *
2952 * Return: CDF status
2953 */
2954static CDF_STATUS wma_send_wow_patterns_to_fw(tp_wma_handle wma,
2955 uint8_t vdev_id, uint8_t ptrn_id,
2956 const uint8_t *ptrn, uint8_t ptrn_len,
2957 uint8_t ptrn_offset, const uint8_t *mask,
2958 uint8_t mask_len, bool user)
2959{
2960 WMI_WOW_ADD_PATTERN_CMD_fixed_param *cmd;
2961 WOW_BITMAP_PATTERN_T *bitmap_pattern;
2962 struct wma_txrx_node *iface;
2963 wmi_buf_t buf;
2964 uint8_t *buf_ptr;
2965 int32_t len;
2966 int ret;
2967
2968 iface = &wma->interfaces[vdev_id];
2969
2970 len = sizeof(WMI_WOW_ADD_PATTERN_CMD_fixed_param) +
2971 WMI_TLV_HDR_SIZE +
2972 1 * sizeof(WOW_BITMAP_PATTERN_T) +
2973 WMI_TLV_HDR_SIZE +
2974 0 * sizeof(WOW_IPV4_SYNC_PATTERN_T) +
2975 WMI_TLV_HDR_SIZE +
2976 0 * sizeof(WOW_IPV6_SYNC_PATTERN_T) +
2977 WMI_TLV_HDR_SIZE +
2978 0 * sizeof(WOW_MAGIC_PATTERN_CMD) +
2979 WMI_TLV_HDR_SIZE +
2980 0 * sizeof(A_UINT32) + WMI_TLV_HDR_SIZE + 1 * sizeof(A_UINT32);
2981
2982 buf = wmi_buf_alloc(wma->wmi_handle, len);
2983 if (!buf) {
2984 WMA_LOGE("%s: Failed allocate wmi buffer", __func__);
2985 return CDF_STATUS_E_NOMEM;
2986 }
2987
2988 cmd = (WMI_WOW_ADD_PATTERN_CMD_fixed_param *) wmi_buf_data(buf);
2989 buf_ptr = (uint8_t *) cmd;
2990
2991 WMITLV_SET_HDR(&cmd->tlv_header,
2992 WMITLV_TAG_STRUC_WMI_WOW_ADD_PATTERN_CMD_fixed_param,
2993 WMITLV_GET_STRUCT_TLVLEN
2994 (WMI_WOW_ADD_PATTERN_CMD_fixed_param));
2995 cmd->vdev_id = vdev_id;
2996 /*
2997 * For user configured wow pattern use pattern id sent by HDD
2998 * and for default wow patterns generate pattern id internally
2999 */
3000 if (user)
3001 cmd->pattern_id = ptrn_id;
3002 else
3003 cmd->pattern_id = iface->num_wow_default_patterns++;
3004
3005 cmd->pattern_type = WOW_BITMAP_PATTERN;
3006 buf_ptr += sizeof(WMI_WOW_ADD_PATTERN_CMD_fixed_param);
3007
3008 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
3009 sizeof(WOW_BITMAP_PATTERN_T));
3010 buf_ptr += WMI_TLV_HDR_SIZE;
3011 bitmap_pattern = (WOW_BITMAP_PATTERN_T *) buf_ptr;
3012
3013 WMITLV_SET_HDR(&bitmap_pattern->tlv_header,
3014 WMITLV_TAG_STRUC_WOW_BITMAP_PATTERN_T,
3015 WMITLV_GET_STRUCT_TLVLEN(WOW_BITMAP_PATTERN_T));
3016
3017 cdf_mem_copy(&bitmap_pattern->patternbuf[0], ptrn, ptrn_len);
3018 cdf_mem_copy(&bitmap_pattern->bitmaskbuf[0], mask, mask_len);
3019
3020 bitmap_pattern->pattern_offset = ptrn_offset;
3021 bitmap_pattern->pattern_len = ptrn_len;
3022
3023 if (bitmap_pattern->pattern_len > WOW_DEFAULT_BITMAP_PATTERN_SIZE)
3024 bitmap_pattern->pattern_len = WOW_DEFAULT_BITMAP_PATTERN_SIZE;
3025
3026 if (bitmap_pattern->pattern_len > WOW_DEFAULT_BITMASK_SIZE)
3027 bitmap_pattern->pattern_len = WOW_DEFAULT_BITMASK_SIZE;
3028
3029 bitmap_pattern->bitmask_len = bitmap_pattern->pattern_len;
3030 bitmap_pattern->pattern_id = ptrn_id;
3031
3032 WMA_LOGI("vdev id : %d, ptrn id: %d, ptrn len: %d, ptrn offset: %d user %d",
3033 cmd->vdev_id, cmd->pattern_id, bitmap_pattern->pattern_len,
3034 bitmap_pattern->pattern_offset, user);
3035
3036 WMA_LOGI("Pattern : ");
3037 CDF_TRACE_HEX_DUMP(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_INFO,
3038 &bitmap_pattern->patternbuf[0], bitmap_pattern->pattern_len);
3039
3040 WMA_LOGI("Mask : ");
3041 CDF_TRACE_HEX_DUMP(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_INFO,
3042 &bitmap_pattern->bitmaskbuf[0], bitmap_pattern->pattern_len);
3043
3044 buf_ptr += sizeof(WOW_BITMAP_PATTERN_T);
3045
3046 /* Fill TLV for WMITLV_TAG_STRUC_WOW_IPV4_SYNC_PATTERN_T but no data. */
3047 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
3048 buf_ptr += WMI_TLV_HDR_SIZE;
3049
3050 /* Fill TLV for WMITLV_TAG_STRUC_WOW_IPV6_SYNC_PATTERN_T but no data. */
3051 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
3052 buf_ptr += WMI_TLV_HDR_SIZE;
3053
3054 /* Fill TLV for WMITLV_TAG_STRUC_WOW_MAGIC_PATTERN_CMD but no data. */
3055 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
3056 buf_ptr += WMI_TLV_HDR_SIZE;
3057
3058 /* Fill TLV for pattern_info_timeout but no data. */
3059 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, 0);
3060 buf_ptr += WMI_TLV_HDR_SIZE;
3061
3062 /* Fill TLV for ra_ratelimit_interval with dummy data as this fix elem */
3063 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, 1 * sizeof(A_UINT32));
3064 buf_ptr += WMI_TLV_HDR_SIZE;
3065 *(A_UINT32 *) buf_ptr = 0;
3066
3067 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
3068 WMI_WOW_ADD_WAKE_PATTERN_CMDID);
3069 if (ret) {
3070 WMA_LOGE("%s: Failed to send wow ptrn to fw", __func__);
3071 wmi_buf_free(buf);
3072 if (!user)
3073 iface->num_wow_default_patterns--;
3074 return CDF_STATUS_E_FAILURE;
3075 }
3076
3077 if (user)
3078 iface->num_wow_user_patterns++;
3079
3080 return CDF_STATUS_SUCCESS;
3081}
3082
3083/**
3084 * wma_wow_ap() - set WOW patterns in ap mode
3085 * @wma: wma handle
3086 * @vdev_id: vdev id
3087 *
3088 * Configures default WOW pattern for the given vdev_id which is in AP mode.
3089 *
3090 * Return: CDF status
3091 */
3092static CDF_STATUS wma_wow_ap(tp_wma_handle wma, uint8_t vdev_id)
3093{
3094 CDF_STATUS ret;
3095 uint8_t arp_offset = 20;
3096 uint8_t mac_mask[IEEE80211_ADDR_LEN];
3097
3098 /* Setup unicast pkt pattern */
3099 cdf_mem_set(&mac_mask, IEEE80211_ADDR_LEN, 0xFF);
3100 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
3101 wma->interfaces[vdev_id].addr,
3102 IEEE80211_ADDR_LEN, 0, mac_mask,
3103 IEEE80211_ADDR_LEN, false);
3104 if (ret != CDF_STATUS_SUCCESS) {
3105 WMA_LOGE("Failed to add WOW unicast pattern ret %d", ret);
3106 return ret;
3107 }
3108
3109 /*
3110 * Setup all ARP pkt pattern. This is dummy pattern hence the length
3111 * is zero
3112 */
3113 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
3114 arp_ptrn, 0, arp_offset, arp_mask, 0, false);
3115 if (ret != CDF_STATUS_SUCCESS) {
3116 WMA_LOGE("Failed to add WOW ARP pattern ret %d", ret);
3117 return ret;
3118 }
3119
3120 return ret;
3121}
3122
3123/**
3124 * wma_wow_sta() - set WOW patterns in sta mode
3125 * @wma: wma handle
3126 * @vdev_id: vdev id
3127 *
3128 * Configures default WOW pattern for the given vdev_id which is in sta mode.
3129 *
3130 * Return: CDF status
3131 */
3132static CDF_STATUS wma_wow_sta(tp_wma_handle wma, uint8_t vdev_id)
3133{
3134 uint8_t arp_offset = 12;
3135 uint8_t discvr_offset = 30;
3136 uint8_t mac_mask[IEEE80211_ADDR_LEN];
3137 CDF_STATUS ret = CDF_STATUS_SUCCESS;
3138
3139 /* Setup unicast pkt pattern */
3140 cdf_mem_set(&mac_mask, IEEE80211_ADDR_LEN, 0xFF);
3141 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
3142 wma->interfaces[vdev_id].addr,
3143 IEEE80211_ADDR_LEN, 0, mac_mask,
3144 IEEE80211_ADDR_LEN, false);
3145 if (ret != CDF_STATUS_SUCCESS) {
3146 WMA_LOGE("Failed to add WOW unicast pattern ret %d", ret);
3147 return ret;
3148 }
3149
3150 /*
3151 * Setup multicast pattern for mDNS 224.0.0.251,
3152 * SSDP 239.255.255.250 and LLMNR 224.0.0.252
3153 */
3154 if (wma->ssdp) {
3155 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
3156 discvr_ptrn, sizeof(discvr_ptrn), discvr_offset,
3157 discvr_mask, sizeof(discvr_ptrn), false);
3158 if (ret != CDF_STATUS_SUCCESS) {
3159 WMA_LOGE("Failed to add WOW mDNS/SSDP/LLMNR pattern");
3160 return ret;
3161 }
3162 } else
3163 WMA_LOGD("mDNS, SSDP, LLMNR patterns are disabled from ini");
3164
3165 /* when arp offload or ns offloaded is disabled
3166 * from ini file, configure broad cast arp pattern
3167 * to fw, so that host can wake up
3168 */
3169 if (!(wma->ol_ini_info & 0x1)) {
3170 /* Setup all ARP pkt pattern */
3171 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
3172 arp_ptrn, sizeof(arp_ptrn), arp_offset,
3173 arp_mask, sizeof(arp_mask), false);
3174 if (ret != CDF_STATUS_SUCCESS) {
3175 WMA_LOGE("Failed to add WOW ARP pattern");
3176 return ret;
3177 }
3178 }
3179
3180 /* for NS or NDP offload packets */
3181 if (!(wma->ol_ini_info & 0x2)) {
3182 /* Setup all NS pkt pattern */
3183 ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0,
3184 ns_ptrn, sizeof(arp_ptrn), arp_offset,
3185 arp_mask, sizeof(arp_mask), false);
3186 if (ret != CDF_STATUS_SUCCESS) {
3187 WMA_LOGE("Failed to add WOW NS pattern");
3188 return ret;
3189 }
3190 }
3191
3192 return ret;
3193}
3194
3195/**
3196 * wma_register_wow_default_patterns() - register default wow patterns with fw
3197 * @handle: Pointer to wma handle
3198 * @vdev_id: vdev id
3199 *
3200 * WoW default wake up pattern rule is:
3201 * - For STA & P2P CLI mode register for same STA specific wow patterns
3202 * - For SAP/P2P GO & IBSS mode register for same SAP specific wow patterns
3203 *
3204 * Return: none
3205 */
3206void wma_register_wow_default_patterns(WMA_HANDLE handle, uint8_t vdev_id)
3207{
3208 tp_wma_handle wma = handle;
3209 struct wma_txrx_node *iface;
3210
3211 if (vdev_id > wma->max_bssid) {
3212 WMA_LOGE("Invalid vdev id %d", vdev_id);
3213 return;
3214 }
3215 iface = &wma->interfaces[vdev_id];
3216
3217 if (iface->ptrn_match_enable) {
3218 if (wma_is_vdev_in_ap_mode(wma, vdev_id)
3219#ifdef QCA_IBSS_SUPPORT
3220 ||
3221 wma_is_vdev_in_ibss_mode(wma, vdev_id)
3222#endif
3223 ) {
3224 /* Configure SAP/GO/IBSS mode default wow patterns */
3225 WMA_LOGI("Config SAP specific default wow patterns vdev_id %d",
3226 vdev_id);
3227 wma_wow_ap(wma, vdev_id);
3228 } else {
3229 /* Configure STA/P2P CLI mode default wow patterns */
3230 WMA_LOGI("Config STA specific default wow patterns vdev_id %d",
3231 vdev_id);
3232 wma_wow_sta(wma, vdev_id);
3233 if (wma->IsRArateLimitEnabled) {
3234 WMA_LOGI("Config STA RA limit wow patterns vdev_id %d",
3235 vdev_id);
3236 wma_wow_sta_ra_filter(wma, vdev_id);
3237 }
3238 }
3239 }
3240
3241 return;
3242}
3243
3244/**
3245 * wma_register_wow_wakeup_events() - register vdev specific wake events with fw
3246 * @handle: Pointer to wma handle
3247 * @vdev_id: vdev Id
3248 * @vdev_type: vdev type
3249 * @vdev_subtype: vdev sub type
3250 *
3251 * WoW wake up event rule is following:
3252 * 1) STA mode and P2P CLI mode wake up events are same
3253 * 2) SAP mode and P2P GO mode wake up events are same
3254 * 3) IBSS mode wake events are same as STA mode plus WOW_BEACON_EVENT
3255 *
3256 * Return: none
3257 */
3258void wma_register_wow_wakeup_events(WMA_HANDLE handle,
3259 uint8_t vdev_id,
3260 uint8_t vdev_type,
3261 uint8_t vdev_subtype)
3262{
3263 tp_wma_handle wma = handle;
3264 uint32_t event_bitmap;
3265
3266 WMA_LOGI("vdev_type %d vdev_subtype %d vdev_id %d", vdev_type,
3267 vdev_subtype, vdev_id);
3268
3269 if ((WMI_VDEV_TYPE_STA == vdev_type) ||
3270 ((WMI_VDEV_TYPE_AP == vdev_type) &&
3271 (WMI_UNIFIED_VDEV_SUBTYPE_P2P_DEVICE == vdev_subtype))) {
3272 /* Configure STA/P2P CLI mode specific default wake up events */
3273 event_bitmap = WMA_WOW_STA_WAKE_UP_EVENTS;
3274 WMA_LOGI("STA specific default wake up event 0x%x vdev id %d",
3275 event_bitmap, vdev_id);
3276 } else if (WMI_VDEV_TYPE_IBSS == vdev_type) {
3277 /* Configure IBSS mode specific default wake up events */
3278 event_bitmap = (WMA_WOW_STA_WAKE_UP_EVENTS |
3279 (1 << WOW_BEACON_EVENT));
3280 WMA_LOGI("IBSS specific default wake up event 0x%x vdev id %d",
3281 event_bitmap, vdev_id);
3282 } else if (WMI_VDEV_TYPE_AP == vdev_type) {
3283 /* Configure SAP/GO mode specific default wake up events */
3284 event_bitmap = WMA_WOW_SAP_WAKE_UP_EVENTS;
3285 WMA_LOGI("SAP specific default wake up event 0x%x vdev id %d",
3286 event_bitmap, vdev_id);
3287 } else {
3288 WMA_LOGE("unknown type %d subtype %d", vdev_type, vdev_subtype);
3289 return;
3290 }
3291
3292 wma_add_wow_wakeup_event(wma, vdev_id, event_bitmap, true);
3293
3294 return;
3295}
3296
3297/**
3298 * wma_enable_disable_wakeup_event() - Configures wow wakeup events
3299 * @wma: wma handle
3300 * @vdev_id: vdev id
3301 * @bitmap: Event bitmap
3302 * @enable: enable/disable
3303 *
3304 * Return: none
3305 */
3306void wma_enable_disable_wakeup_event(WMA_HANDLE handle,
3307 uint32_t vdev_id,
3308 uint32_t bitmap,
3309 bool enable)
3310{
3311 tp_wma_handle wma = handle;
3312
3313 WMA_LOGI("vdev_id %d wake up event 0x%x enable %d",
3314 vdev_id, bitmap, enable);
3315 wma_add_wow_wakeup_event(wma, vdev_id, bitmap, enable);
3316}
3317
3318/**
3319 * wma_enable_wow_in_fw() - wnable wow in fw
3320 * @wma: wma handle
3321 *
3322 * Return: CDF status
3323 */
3324CDF_STATUS wma_enable_wow_in_fw(WMA_HANDLE handle)
3325{
3326 tp_wma_handle wma = handle;
3327 wmi_wow_enable_cmd_fixed_param *cmd;
3328 wmi_buf_t buf;
3329 int32_t len;
3330 int ret;
3331 struct ol_softc *scn;
3332 int host_credits;
3333 int wmi_pending_cmds;
3334#ifdef CONFIG_CNSS
3335 tpAniSirGlobal pMac = cds_get_context(CDF_MODULE_ID_PE);
3336
3337 if (NULL == pMac) {
3338 WMA_LOGE("%s: Unable to get PE context", __func__);
3339 return CDF_STATUS_E_FAILURE;
3340 }
3341#endif /* CONFIG_CNSS */
3342
3343 len = sizeof(wmi_wow_enable_cmd_fixed_param);
3344
3345 buf = wmi_buf_alloc(wma->wmi_handle, len);
3346 if (!buf) {
3347 WMA_LOGE("%s: Failed allocate wmi buffer", __func__);
3348 return CDF_STATUS_E_NOMEM;
3349 }
3350
3351 cmd = (wmi_wow_enable_cmd_fixed_param *) wmi_buf_data(buf);
3352 WMITLV_SET_HDR(&cmd->tlv_header,
3353 WMITLV_TAG_STRUC_wmi_wow_enable_cmd_fixed_param,
3354 WMITLV_GET_STRUCT_TLVLEN
3355 (wmi_wow_enable_cmd_fixed_param));
3356 cmd->enable = true;
3357 if (hif_can_suspend_link())
3358 cmd->pause_iface_config = WOW_IFACE_PAUSE_ENABLED;
3359 else
3360 cmd->pause_iface_config = WOW_IFACE_PAUSE_DISABLED;
3361
3362 WMA_LOGI("suspend type: %s",
3363 cmd->pause_iface_config == WOW_IFACE_PAUSE_ENABLED ?
3364 "WOW_IFACE_PAUSE_ENABLED" : "WOW_IFACE_PAUSE_DISABLED");
3365
3366 cdf_event_reset(&wma->target_suspend);
3367 wma->wow_nack = 0;
3368
3369 host_credits = wmi_get_host_credits(wma->wmi_handle);
3370 wmi_pending_cmds = wmi_get_pending_cmds(wma->wmi_handle);
3371
3372 WMA_LOGD("Credits:%d; Pending_Cmds: %d",
3373 host_credits, wmi_pending_cmds);
3374
3375 if (host_credits < WMI_WOW_REQUIRED_CREDITS) {
3376 WMA_LOGE("%s: Host Doesn't have enough credits to Post WMI_WOW_ENABLE_CMDID! "
3377 "Credits:%d, pending_cmds:%d\n", __func__, host_credits,
3378 wmi_pending_cmds);
3379#ifndef QCA_WIFI_3_0_EMU
3380 goto error;
3381#endif
3382 }
3383
3384 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
3385 WMI_WOW_ENABLE_CMDID);
3386 if (ret) {
3387 WMA_LOGE("Failed to enable wow in fw");
3388 goto error;
3389 }
3390
3391 wmi_set_target_suspend(wma->wmi_handle, true);
3392
3393 if (cdf_wait_single_event(&wma->target_suspend,
3394 WMA_TGT_SUSPEND_COMPLETE_TIMEOUT)
3395 != CDF_STATUS_SUCCESS) {
3396 WMA_LOGE("Failed to receive WoW Enable Ack from FW");
3397 WMA_LOGE("Credits:%d; Pending_Cmds: %d",
3398 wmi_get_host_credits(wma->wmi_handle),
3399 wmi_get_pending_cmds(wma->wmi_handle));
Yue Ma455aff62015-10-20 18:29:16 -07003400 if (!cds_is_logp_in_progress()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003401#ifdef CONFIG_CNSS
Yue Ma455aff62015-10-20 18:29:16 -07003402 if (pMac->sme.enableSelfRecovery) {
3403 cds_trigger_recovery();
3404 } else {
3405 CDF_BUG(0);
3406 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003407#else
Yue Ma455aff62015-10-20 18:29:16 -07003408 CDF_BUG(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003409#endif /* CONFIG_CNSS */
Yue Ma455aff62015-10-20 18:29:16 -07003410 } else {
3411 WMA_LOGE("%s: LOGP is in progress, ignore!", __func__);
3412 }
3413
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003414 wmi_set_target_suspend(wma->wmi_handle, false);
3415 return CDF_STATUS_E_FAILURE;
3416 }
3417
3418 if (wma->wow_nack) {
3419 WMA_LOGE("FW not ready to WOW");
3420 wmi_set_target_suspend(wma->wmi_handle, false);
3421 return CDF_STATUS_E_AGAIN;
3422 }
3423
3424 host_credits = wmi_get_host_credits(wma->wmi_handle);
3425 wmi_pending_cmds = wmi_get_pending_cmds(wma->wmi_handle);
3426
3427 if (host_credits < WMI_WOW_REQUIRED_CREDITS) {
3428 WMA_LOGE("%s: No Credits after HTC ACK:%d, pending_cmds:%d, "
3429 "cannot resume back", __func__, host_credits,
3430 wmi_pending_cmds);
3431 htc_dump_counter_info(wma->htc_handle);
3432 if (!cds_is_logp_in_progress())
3433 CDF_BUG(0);
3434 else
3435 WMA_LOGE("%s: SSR in progress, ignore no credit issue",
3436 __func__);
3437 }
3438
3439 WMA_LOGD("WOW enabled successfully in fw: credits:%d"
3440 "pending_cmds: %d", host_credits, wmi_pending_cmds);
3441
3442 scn = cds_get_context(CDF_MODULE_ID_HIF);
3443
3444 if (scn == NULL) {
3445 WMA_LOGE("%s: Failed to get HIF context", __func__);
3446 CDF_ASSERT(0);
3447 return CDF_STATUS_E_FAULT;
3448 }
3449
3450 htc_cancel_deferred_target_sleep(scn);
3451
3452 wma->wow.wow_enable_cmd_sent = true;
3453
3454 return CDF_STATUS_SUCCESS;
3455
3456error:
3457 wmi_buf_free(buf);
3458 return CDF_STATUS_E_FAILURE;
3459}
3460
3461/**
3462 * wma_resume_req() - clear configured wow patterns in fw
3463 * @wma: wma handle
3464 *
3465 * Return: CDF status
3466 */
3467CDF_STATUS wma_resume_req(tp_wma_handle wma)
3468{
3469 wma->no_of_resume_ind++;
3470
3471 if (wma->no_of_resume_ind < wma_get_vdev_count(wma))
3472 return CDF_STATUS_SUCCESS;
3473
3474 wma->no_of_resume_ind = 0;
3475
3476 /* Reset the DTIM Parameters */
3477 wma_set_resume_dtim(wma);
3478 /* need to reset if hif_pci_suspend_fails */
3479 wma_set_wow_bus_suspend(wma, 0);
3480 /* unpause the vdev if left paused and hif_pci_suspend fails */
3481 wma_unpause_vdev(wma);
3482
3483 return CDF_STATUS_SUCCESS;
3484}
3485
3486/**
3487 * wma_wow_delete_pattern() - delete wow pattern in target
3488 * @wma: wma handle
3489 * @ptrn_id: pattern id
3490 * @vdev_id: vdev id
3491 * @user: true for user pattern and false for default pattern
3492 *
3493 * Return: CDF status
3494 */
3495static CDF_STATUS wma_wow_delete_pattern(tp_wma_handle wma, uint8_t ptrn_id,
3496 uint8_t vdev_id, bool user)
3497{
3498 WMI_WOW_DEL_PATTERN_CMD_fixed_param *cmd;
3499 struct wma_txrx_node *iface;
3500 wmi_buf_t buf;
3501 int32_t len;
3502 int ret;
3503
3504 len = sizeof(WMI_WOW_DEL_PATTERN_CMD_fixed_param);
3505
3506 iface = &wma->interfaces[vdev_id];
3507
3508 buf = wmi_buf_alloc(wma->wmi_handle, len);
3509 if (!buf) {
3510 WMA_LOGE("%s: Failed allocate wmi buffer", __func__);
3511 return CDF_STATUS_E_NOMEM;
3512 }
3513
3514 cmd = (WMI_WOW_DEL_PATTERN_CMD_fixed_param *) wmi_buf_data(buf);
3515
3516 WMITLV_SET_HDR(&cmd->tlv_header,
3517 WMITLV_TAG_STRUC_WMI_WOW_DEL_PATTERN_CMD_fixed_param,
3518 WMITLV_GET_STRUCT_TLVLEN(
3519 WMI_WOW_DEL_PATTERN_CMD_fixed_param));
3520 cmd->vdev_id = vdev_id;
3521 cmd->pattern_id = ptrn_id;
3522 cmd->pattern_type = WOW_BITMAP_PATTERN;
3523
3524 WMA_LOGI("Deleting pattern id: %d vdev id %d in fw",
3525 cmd->pattern_id, vdev_id);
3526
3527 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
3528 WMI_WOW_DEL_WAKE_PATTERN_CMDID);
3529 if (ret) {
3530 WMA_LOGE("%s: Failed to delete wow ptrn from fw", __func__);
3531 wmi_buf_free(buf);
3532 return CDF_STATUS_E_FAILURE;
3533 }
3534
3535 if (user)
3536 iface->num_wow_user_patterns--;
3537
3538 return CDF_STATUS_SUCCESS;
3539}
3540
3541/**
3542 * wma_wow_add_pattern() - add wow pattern in target
3543 * @wma: wma handle
3544 * @ptrn: wow pattern
3545 *
3546 * This function does following:
3547 * 1) Delete all default patterns of the vdev
3548 * 2) Add received wow patterns for given vdev in target.
3549 *
3550 * Target is responsible for caching wow patterns accross multiple
3551 * suspend/resumes until the pattern is deleted by user
3552 *
3553 * Return: CDF status
3554 */
3555CDF_STATUS wma_wow_add_pattern(tp_wma_handle wma, struct wow_add_pattern *ptrn)
3556{
3557 uint8_t id;
3558 uint8_t bit_to_check, pos;
3559 struct wma_txrx_node *iface;
3560 CDF_STATUS ret = CDF_STATUS_SUCCESS;
3561 uint8_t new_mask[SIR_WOWL_BCAST_PATTERN_MAX_SIZE];
3562
3563 if (ptrn->session_id > wma->max_bssid) {
3564 WMA_LOGE("Invalid vdev id (%d)", ptrn->session_id);
3565 return CDF_STATUS_E_INVAL;
3566 }
3567
3568 iface = &wma->interfaces[ptrn->session_id];
3569
3570 /* clear all default patterns cofigured by wma */
3571 for (id = 0; id < iface->num_wow_default_patterns; id++)
3572 wma_wow_delete_pattern(wma, id, ptrn->session_id, false);
3573
3574 iface->num_wow_default_patterns = 0;
3575
3576 WMA_LOGI("Add user passed wow pattern id %d vdev id %d",
3577 ptrn->pattern_id, ptrn->session_id);
3578 /*
3579 * Convert received pattern mask value from bit representation
3580 * to byte representation.
3581 *
3582 * For example, received value from umac,
3583 *
3584 * Mask value : A1 (equivalent binary is "1010 0001")
3585 * Pattern value : 12:00:13:00:00:00:00:44
3586 *
3587 * The value which goes to FW after the conversion from this
3588 * function (1 in mask value will become FF and 0 will
3589 * become 00),
3590 *
3591 * Mask value : FF:00:FF:00:0:00:00:FF
3592 * Pattern value : 12:00:13:00:00:00:00:44
3593 */
3594 cdf_mem_zero(new_mask, sizeof(new_mask));
3595 for (pos = 0; pos < ptrn->pattern_size; pos++) {
3596 bit_to_check = (WMA_NUM_BITS_IN_BYTE - 1) -
3597 (pos % WMA_NUM_BITS_IN_BYTE);
3598 bit_to_check = 0x1 << bit_to_check;
3599 if (ptrn->pattern_mask[pos / WMA_NUM_BITS_IN_BYTE] &
3600 bit_to_check)
3601 new_mask[pos] = WMA_WOW_PTRN_MASK_VALID;
3602 }
3603
3604 ret = wma_send_wow_patterns_to_fw(wma, ptrn->session_id,
3605 ptrn->pattern_id,
3606 ptrn->pattern, ptrn->pattern_size,
3607 ptrn->pattern_byte_offset, new_mask,
3608 ptrn->pattern_size, true);
3609 if (ret != CDF_STATUS_SUCCESS)
3610 WMA_LOGE("Failed to add wow pattern %d", ptrn->pattern_id);
3611
3612 return ret;
3613}
3614
3615/**
3616 * wma_wow_delete_user_pattern() - delete user configured wow pattern in target
3617 * @wma: wma handle
3618 * @ptrn: wow pattern
3619 *
3620 * This function does following:
3621 * 1) Deletes a particular user configured wow pattern in target
3622 * 2) After deleting all user wow patterns add default wow patterns
3623 * specific to that vdev.
3624 *
3625 * Return: CDF status
3626 */
3627CDF_STATUS wma_wow_delete_user_pattern(tp_wma_handle wma,
3628 struct wow_delete_pattern *pattern)
3629{
3630 struct wma_txrx_node *iface;
3631
3632 if (pattern->session_id > wma->max_bssid) {
3633 WMA_LOGE("Invalid vdev id %d", pattern->session_id);
3634 return CDF_STATUS_E_INVAL;
3635 }
3636
3637 iface = &wma->interfaces[pattern->session_id];
3638 if (iface->num_wow_user_patterns <= 0) {
3639 WMA_LOGE("No valid user pattern. Num user pattern %u vdev %d",
3640 iface->num_wow_user_patterns, pattern->session_id);
3641 return CDF_STATUS_E_INVAL;
3642 }
3643
3644 WMA_LOGI("Delete user passed wow pattern id %d total user pattern %d",
3645 pattern->pattern_id, iface->num_wow_user_patterns);
3646
3647 wma_wow_delete_pattern(wma, pattern->pattern_id,
3648 pattern->session_id, true);
3649
3650 /* configure default patterns once all user patterns are deleted */
3651 if (!iface->num_wow_user_patterns)
3652 wma_register_wow_default_patterns(wma, pattern->session_id);
3653
3654 return CDF_STATUS_SUCCESS;
3655}
3656
3657/**
3658 * wma_wow_enter() - store enable/disable status for pattern
3659 * @wma: wma handle
3660 * @info: wow parameters
3661 *
3662 * Records pattern enable/disable status locally. This choice will
3663 * take effect when the driver enter into suspend state.
3664 *
3665 * Return: CDF status
3666 */
3667CDF_STATUS wma_wow_enter(tp_wma_handle wma, tpSirHalWowlEnterParams info)
3668{
3669 struct wma_txrx_node *iface;
3670
3671 WMA_LOGD("wow enable req received for vdev id: %d", info->sessionId);
3672
3673 if (info->sessionId > wma->max_bssid) {
3674 WMA_LOGE("Invalid vdev id (%d)", info->sessionId);
3675 cdf_mem_free(info);
3676 return CDF_STATUS_E_INVAL;
3677 }
3678
3679 iface = &wma->interfaces[info->sessionId];
3680 iface->ptrn_match_enable = info->ucPatternFilteringEnable ?
3681 true : false;
3682 wma->wow.magic_ptrn_enable = info->ucMagicPktEnable ? true : false;
3683 wma->wow.deauth_enable = info->ucWowDeauthRcv ? true : false;
3684 wma->wow.disassoc_enable = info->ucWowDeauthRcv ? true : false;
3685 wma->wow.bmiss_enable = info->ucWowMaxMissedBeacons ? true : false;
3686
3687 cdf_mem_free(info);
3688
3689 return CDF_STATUS_SUCCESS;
3690}
3691
3692/**
3693 * wma_wow_exit() - clear all wma states
3694 * @wma: wma handle
3695 * @info: wow params
3696 *
3697 * Return: CDF status
3698 */
3699CDF_STATUS wma_wow_exit(tp_wma_handle wma, tpSirHalWowlExitParams info)
3700{
3701 struct wma_txrx_node *iface;
3702
3703 WMA_LOGD("wow disable req received for vdev id: %d", info->sessionId);
3704
3705 if (info->sessionId > wma->max_bssid) {
3706 WMA_LOGE("Invalid vdev id (%d)", info->sessionId);
3707 cdf_mem_free(info);
3708 return CDF_STATUS_E_INVAL;
3709 }
3710
3711 iface = &wma->interfaces[info->sessionId];
3712 iface->ptrn_match_enable = false;
3713 wma->wow.magic_ptrn_enable = false;
3714 cdf_mem_free(info);
3715
3716 return CDF_STATUS_SUCCESS;
3717}
3718
Srinivas Girigowda0f09f992015-11-23 11:43:10 -08003719#ifdef FEATURE_WLAN_EXTSCAN
3720/**
3721 * wma_is_extscan_in_progress(): check if extscan is in progress
3722 * @wma: wma handle
3723 *
3724 * Return: true is extscan in progress, false otherwise.
3725 */
3726static bool wma_is_extscan_in_progress(tp_wma_handle wma)
3727{
3728 int i;
3729
3730 for (i = 0; i < wma->max_bssid; i++) {
3731 if (wma->interfaces[i].extscan_in_progress) {
3732 WMA_LOGD("Extscan is in progress, enabling wow");
3733 return true;
3734 }
3735 }
3736
3737 return false;
3738}
3739#else
3740static bool wma_is_extscan_in_progress(tp_wma_handle wma)
3741{
3742 return false;
3743}
3744#endif
3745
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003746/**
3747 * wma_suspend_req() - Handles suspend indication request received from umac.
3748 * @wma: wma handle
3749 * @info: suspend params
3750 *
3751 * Return: CDF status
3752 */
3753CDF_STATUS wma_suspend_req(tp_wma_handle wma, tpSirWlanSuspendParam info)
3754{
3755 struct wma_txrx_node *iface;
Ryan Hsu04aec8e2015-10-09 10:15:46 -07003756 bool pno_in_progress = false;
Srinivas Girigowdaa4db76f2015-11-23 11:39:24 -08003757 uint8_t i, vdev_id = 0;
3758 bool extscan_in_progress = false, pno_matched = false;
Ryan Hsu04aec8e2015-10-09 10:15:46 -07003759 bool enable_wow = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003760
3761 wma->no_of_suspend_ind++;
3762
3763 if (info->sessionId > wma->max_bssid) {
3764 WMA_LOGE("Invalid vdev id (%d)", info->sessionId);
3765 cdf_mem_free(info);
3766 return CDF_STATUS_E_INVAL;
3767 }
3768
3769 iface = &wma->interfaces[info->sessionId];
3770 if (!iface) {
3771 WMA_LOGD("vdev %d node is not found", info->sessionId);
3772 cdf_mem_free(info);
3773 return CDF_STATUS_SUCCESS;
3774 }
3775
3776 if (!wma->wow.magic_ptrn_enable && !iface->ptrn_match_enable) {
3777 cdf_mem_free(info);
3778
3779 if (wma->no_of_suspend_ind == wma_get_vdev_count(wma)) {
3780 WMA_LOGD("Both magic and pattern byte match are disabled");
3781 wma->no_of_suspend_ind = 0;
3782 goto send_ready_to_suspend;
3783 }
3784
3785 return CDF_STATUS_SUCCESS;
3786 }
3787
3788 iface->conn_state = (info->connectedState) ? true : false;
3789
3790 /*
3791 * Once WOW is enabled in FW, host can't send anymore
3792 * data to fw. umac sends suspend indication on each
3793 * vdev during platform suspend. WMA has to wait until
3794 * suspend indication received on last vdev before
3795 * enabling wow in fw.
3796 */
3797 if (wma->no_of_suspend_ind < wma_get_vdev_count(wma)) {
3798 cdf_mem_free(info);
3799 return CDF_STATUS_SUCCESS;
3800 }
3801
3802 wma->no_of_suspend_ind = 0;
3803 wma->wow.gtk_pdev_enable = 0;
3804 /*
3805 * Enable WOW if any one of the condition meets,
3806 * 1) Is any one of vdev in beaconning mode (in AP mode) ?
3807 * 2) Is any one of vdev in connected state (in STA mode) ?
3808 * 3) Is PNO in progress in any one of vdev ?
3809 * 4) Is Extscan in progress in any one of vdev ?
3810 */
3811 for (i = 0; i < wma->max_bssid; i++) {
3812 if ((wma_is_vdev_in_ap_mode(wma, i)
3813#ifdef QCA_IBSS_SUPPORT
3814 || wma_is_vdev_in_ibss_mode(wma, i)
3815#endif /* QCA_IBSS_SUPPORT */
3816 ) && wma->interfaces[i].vdev_up &&
3817 WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
3818 WMI_SERVICE_BEACON_OFFLOAD)) {
3819 WMA_LOGD("vdev %d is in beaconning mode, enabling wow",
3820 i);
Ryan Hsu04aec8e2015-10-09 10:15:46 -07003821 enable_wow = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003822 }
3823 }
3824 for (i = 0; i < wma->max_bssid; i++) {
Ryan Hsu04aec8e2015-10-09 10:15:46 -07003825 if (wma->interfaces[i].conn_state)
3826 enable_wow = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003827#ifdef FEATURE_WLAN_SCAN_PNO
3828 if (wma->interfaces[i].pno_in_progress) {
3829 WMA_LOGD("PNO is in progress, enabling wow");
Ryan Hsu04aec8e2015-10-09 10:15:46 -07003830 enable_wow = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003831 pno_in_progress = true;
Srinivas Girigowdaa4db76f2015-11-23 11:39:24 -08003832 vdev_id = i;
3833 if (wma->interfaces[i].nlo_match_evt_received)
3834 pno_matched = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003835 break;
3836 }
3837#endif /* FEATURE_WLAN_SCAN_PNO */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003838 }
Srinivas Girigowda0f09f992015-11-23 11:43:10 -08003839 extscan_in_progress = wma_is_extscan_in_progress(wma);
Ryan Hsu04aec8e2015-10-09 10:15:46 -07003840 if (extscan_in_progress)
3841 enable_wow = true;
Srinivas Girigowda0f09f992015-11-23 11:43:10 -08003842
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003843 for (i = 0; i < wma->max_bssid; i++) {
3844 wma->wow.gtk_pdev_enable |= wma->wow.gtk_err_enable[i];
3845 WMA_LOGD("VDEV_ID:%d, gtk_err_enable[%d]:%d, gtk_pdev_enable:%d", i,
3846 i, wma->wow.gtk_err_enable[i], wma->wow.gtk_pdev_enable);
3847 }
3848
Ryan Hsu04aec8e2015-10-09 10:15:46 -07003849 if (!enable_wow) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003850 WMA_LOGD("All vdev are in disconnected state and pno/extscan is not in progress, skipping wow");
3851 cdf_mem_free(info);
3852 goto send_ready_to_suspend;
3853 }
3854
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003855 WMA_LOGE("WOW Suspend");
3856
3857 /*
3858 * At this point, suspend indication is received on
3859 * last vdev. It's the time to enable wow in fw.
3860 */
3861#ifdef FEATURE_WLAN_LPHB
3862 /* LPHB cache, if any item was enabled, should be
3863 * applied.
3864 */
3865 WMA_LOGD("%s: checking LPHB cache", __func__);
3866 for (i = 0; i < 2; i++) {
3867 if (wma->wow.lphb_cache[i].params.lphbEnableReq.enable) {
3868 WMA_LOGD("%s: LPHB cache for item %d is marked as enable",
3869 __func__, i + 1);
3870 wma_lphb_conf_hbenable(wma, &(wma->wow.lphb_cache[i]),
3871 false);
3872 }
3873 }
3874#endif /* FEATURE_WLAN_LPHB */
3875
Srinivas Girigowdaa4db76f2015-11-23 11:39:24 -08003876 if (pno_matched)
3877 wma_enable_disable_wakeup_event(wma, vdev_id,
3878 (1 << WOW_NLO_SCAN_COMPLETE_EVENT),
3879 pno_matched);
3880
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003881 wma->wow.wow_enable = true;
3882 wma->wow.wow_enable_cmd_sent = false;
3883
3884 cdf_mem_free(info);
3885
3886send_ready_to_suspend:
3887 /* Set the Suspend DTIM Parameters */
3888 wma_set_suspend_dtim(wma);
3889 wma_send_status_to_suspend_ind(wma, true);
3890
3891 /* to handle race between hif_pci_suspend and
3892 * unpause/pause tx handler
3893 */
3894 wma_set_wow_bus_suspend(wma, 1);
3895
3896 return CDF_STATUS_SUCCESS;
3897}
3898
3899/**
3900 * wma_send_host_wakeup_ind_to_fw() - send wakeup ind to fw
3901 * @wma: wma handle
3902 *
3903 * Sends host wakeup indication to FW. On receiving this indication,
3904 * FW will come out of WOW.
3905 *
3906 * Return: CDF status
3907 */
3908static CDF_STATUS wma_send_host_wakeup_ind_to_fw(tp_wma_handle wma)
3909{
3910 wmi_wow_hostwakeup_from_sleep_cmd_fixed_param *cmd;
3911 wmi_buf_t buf;
3912 CDF_STATUS cdf_status = CDF_STATUS_SUCCESS;
3913 int32_t len;
3914 int ret;
3915#ifdef CONFIG_CNSS
3916 tpAniSirGlobal pMac = cds_get_context(CDF_MODULE_ID_PE);
3917 if (NULL == pMac) {
3918 WMA_LOGE("%s: Unable to get PE context", __func__);
3919 return CDF_STATUS_E_FAILURE;
3920 }
3921#endif /* CONFIG_CNSS */
3922
3923 len = sizeof(wmi_wow_hostwakeup_from_sleep_cmd_fixed_param);
3924
3925 buf = wmi_buf_alloc(wma->wmi_handle, len);
3926 if (!buf) {
3927 WMA_LOGE("%s: Failed allocate wmi buffer", __func__);
3928 return CDF_STATUS_E_NOMEM;
3929 }
3930
3931 cmd = (wmi_wow_hostwakeup_from_sleep_cmd_fixed_param *)
3932 wmi_buf_data(buf);
3933 WMITLV_SET_HDR(&cmd->tlv_header,
3934 WMITLV_TAG_STRUC_wmi_wow_hostwakeup_from_sleep_cmd_fixed_param,
3935 WMITLV_GET_STRUCT_TLVLEN
3936 (wmi_wow_hostwakeup_from_sleep_cmd_fixed_param));
3937
3938 cdf_event_reset(&wma->wma_resume_event);
3939
3940 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
3941 WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID);
3942 if (ret) {
3943 WMA_LOGE("Failed to send host wakeup indication to fw");
3944 wmi_buf_free(buf);
3945 return CDF_STATUS_E_FAILURE;
3946 }
3947
3948 WMA_LOGD("Host wakeup indication sent to fw");
3949
3950 cdf_status = cdf_wait_single_event(&(wma->wma_resume_event),
3951 WMA_RESUME_TIMEOUT);
3952 if (CDF_STATUS_SUCCESS != cdf_status) {
3953 WMA_LOGP("%s: Timeout waiting for resume event from FW",
3954 __func__);
3955 WMA_LOGP("%s: Pending commands %d credits %d", __func__,
3956 wmi_get_pending_cmds(wma->wmi_handle),
3957 wmi_get_host_credits(wma->wmi_handle));
3958 if (!cds_is_logp_in_progress()) {
3959#ifdef CONFIG_CNSS
3960 if (pMac->sme.enableSelfRecovery) {
3961 cds_trigger_recovery();
3962 } else {
3963 CDF_BUG(0);
3964 }
3965#else
3966 CDF_BUG(0);
3967#endif /* CONFIG_CNSS */
3968 } else {
3969 WMA_LOGE("%s: SSR in progress, ignore resume timeout",
3970 __func__);
3971 }
3972 } else {
3973 WMA_LOGD("Host wakeup received");
3974 }
3975
3976 if (CDF_STATUS_SUCCESS == cdf_status)
3977 wmi_set_target_suspend(wma->wmi_handle, false);
3978
3979 return cdf_status;
3980}
3981
3982/**
3983 * wma_disable_wow_in_fw() - Disable wow in PCIe resume context.
3984 * @handle: wma handle
3985 *
3986 * Return: 0 for success or error code
3987 */
3988CDF_STATUS wma_disable_wow_in_fw(WMA_HANDLE handle)
3989{
3990 tp_wma_handle wma = handle;
3991 CDF_STATUS ret;
3992
3993 if (!wma->wow.wow_enable || !wma->wow.wow_enable_cmd_sent)
3994 return CDF_STATUS_SUCCESS;
3995
3996 ret = wma_send_host_wakeup_ind_to_fw(wma);
3997
3998 if (ret != CDF_STATUS_SUCCESS)
3999 return ret;
4000
4001 wma->wow.wow_enable = false;
4002 wma->wow.wow_enable_cmd_sent = false;
4003
4004 /* To allow the tx pause/unpause events */
4005 wma_set_wow_bus_suspend(wma, 0);
4006 /* Unpause the vdev as we are resuming */
4007 wma_unpause_vdev(wma);
4008
4009 return ret;
4010}
4011
4012#ifdef WLAN_FEATURE_LPSS
4013/**
4014 * wma_is_lpass_enabled() - check if lpass is enabled
4015 * @handle: Pointer to wma handle
4016 *
4017 * WoW is needed if LPASS or NaN feature is enabled in INI because
4018 * target can't wake up itself if its put in PDEV suspend when LPASS
4019 * or NaN features are supported
4020 *
4021 * Return: true if lpass is enabled else false
4022 */
4023bool static wma_is_lpass_enabled(tp_wma_handle wma)
4024{
4025 if (wma->is_lpass_enabled)
4026 return true;
4027 else
4028 return false;
4029}
4030#else
4031bool static wma_is_lpass_enabled(tp_wma_handle wma)
4032{
4033 return false;
4034}
4035#endif
4036
4037#ifdef WLAN_FEATURE_NAN
4038/**
4039 * wma_is_nan_enabled() - check if NaN is enabled
4040 * @handle: Pointer to wma handle
4041 *
4042 * WoW is needed if LPASS or NaN feature is enabled in INI because
4043 * target can't wake up itself if its put in PDEV suspend when LPASS
4044 * or NaN features are supported
4045 *
4046 * Return: true if NaN is enabled else false
4047 */
4048bool static wma_is_nan_enabled(tp_wma_handle wma)
4049{
4050 if (wma->is_nan_enabled)
4051 return true;
4052 else
4053 return false;
4054}
4055#else
4056bool static wma_is_nan_enabled(tp_wma_handle wma)
4057{
4058 return false;
4059}
4060#endif
4061
4062/**
4063 * wma_is_wow_mode_selected() - check if wow needs to be enabled in fw
4064 * @handle: Pointer to wma handle
4065 *
4066 * If lpass is enabled then always do wow else check wow_enable config
4067 *
4068 * Return: true is wow mode is needed else false
4069 */
4070int wma_is_wow_mode_selected(WMA_HANDLE handle)
4071{
4072 tp_wma_handle wma = (tp_wma_handle) handle;
4073
4074 if (wma_is_lpass_enabled(wma)) {
4075 WMA_LOGD("LPASS is enabled select WoW");
4076 return true;
4077 } else if (wma_is_nan_enabled(wma)) {
4078 WMA_LOGD("NAN is enabled select WoW");
4079 return true;
4080 } else {
4081 WMA_LOGD("WoW enable %d", wma->wow.wow_enable);
4082 return wma->wow.wow_enable;
4083 }
4084}
4085
4086/**
4087 * wma_del_ts_req() - send DELTS request to fw
4088 * @wma: wma handle
4089 * @msg: delts params
4090 *
4091 * Return: none
4092 */
4093void wma_del_ts_req(tp_wma_handle wma, tDelTsParams *msg)
4094{
4095 wmi_vdev_wmm_delts_cmd_fixed_param *cmd;
4096 wmi_buf_t buf;
4097 int32_t len = sizeof(*cmd);
4098
4099 buf = wmi_buf_alloc(wma->wmi_handle, len);
4100 if (!buf) {
4101 WMA_LOGP("%s: wmi_buf_alloc failed", __func__);
4102 goto err;
4103 }
4104 cmd = (wmi_vdev_wmm_delts_cmd_fixed_param *) wmi_buf_data(buf);
4105 WMITLV_SET_HDR(&cmd->tlv_header,
4106 WMITLV_TAG_STRUC_wmi_vdev_wmm_delts_cmd_fixed_param,
4107 WMITLV_GET_STRUCT_TLVLEN
4108 (wmi_vdev_wmm_delts_cmd_fixed_param));
4109 cmd->vdev_id = msg->sessionId;
4110 cmd->ac = TID_TO_WME_AC(msg->userPrio);
4111
4112 WMA_LOGD("Delts vdev:%d, ac:%d, %s:%d",
4113 cmd->vdev_id, cmd->ac, __FUNCTION__, __LINE__);
4114 if (wmi_unified_cmd_send(wma->wmi_handle, buf, len,
4115 WMI_VDEV_WMM_DELTS_CMDID)) {
4116 WMA_LOGP("%s: Failed to send vdev DELTS command", __func__);
4117 cdf_nbuf_free(buf);
4118 }
4119#ifdef WLAN_FEATURE_ROAM_OFFLOAD
4120 if (msg->setRICparams == true)
4121 wma_set_ric_req(wma, msg, false);
4122#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
4123
4124err:
4125 cdf_mem_free(msg);
4126}
4127
4128/**
4129 * wma_aggr_qos_req() - send aggr qos request to fw
4130 * @wma: handle to wma
4131 * @pAggrQosRspMsg - combined struct for all ADD_TS requests.
4132 *
4133 * A function to handle WMA_AGGR_QOS_REQ. This will send out
4134 * ADD_TS requestes to firmware in loop for all the ACs with
4135 * active flow.
4136 *
4137 * Return: none
4138 */
4139void wma_aggr_qos_req(tp_wma_handle wma,
4140 tAggrAddTsParams *pAggrQosRspMsg)
4141{
4142 int i = 0;
4143 wmi_vdev_wmm_addts_cmd_fixed_param *cmd;
4144 wmi_buf_t buf;
4145 int32_t len = sizeof(*cmd);
4146
4147 for (i = 0; i < HAL_QOS_NUM_AC_MAX; i++) {
4148 /* if flow in this AC is active */
4149 if (((1 << i) & pAggrQosRspMsg->tspecIdx)) {
4150 /*
4151 * as per implementation of wma_add_ts_req() we
4152 * are not waiting any response from firmware so
4153 * apart from sending ADDTS to firmware just send
4154 * success to upper layers
4155 */
4156 pAggrQosRspMsg->status[i] = CDF_STATUS_SUCCESS;
4157
4158 buf = wmi_buf_alloc(wma->wmi_handle, len);
4159 if (!buf) {
4160 WMA_LOGP("%s: wmi_buf_alloc failed", __func__);
4161 goto aggr_qos_exit;
4162 }
4163 cmd = (wmi_vdev_wmm_addts_cmd_fixed_param *)
4164 wmi_buf_data(buf);
4165 WMITLV_SET_HDR(&cmd->tlv_header,
4166 WMITLV_TAG_STRUC_wmi_vdev_wmm_addts_cmd_fixed_param,
4167 WMITLV_GET_STRUCT_TLVLEN
4168 (wmi_vdev_wmm_addts_cmd_fixed_param));
4169 cmd->vdev_id = pAggrQosRspMsg->sessionId;
4170 cmd->ac =
4171 TID_TO_WME_AC(pAggrQosRspMsg->tspec[i].tsinfo.
4172 traffic.userPrio);
4173 cmd->medium_time_us =
4174 pAggrQosRspMsg->tspec[i].mediumTime * 32;
4175 cmd->downgrade_type = WMM_AC_DOWNGRADE_DEPRIO;
4176 WMA_LOGD("%s:%d: Addts vdev:%d, ac:%d, mediumTime:%d downgrade_type:%d",
4177 __func__, __LINE__, cmd->vdev_id, cmd->ac,
4178 cmd->medium_time_us, cmd->downgrade_type);
4179 if (wmi_unified_cmd_send
4180 (wma->wmi_handle, buf, len,
4181 WMI_VDEV_WMM_ADDTS_CMDID)) {
4182 WMA_LOGP("%s: Failed to send vdev ADDTS command",
4183 __func__);
4184 pAggrQosRspMsg->status[i] =
4185 CDF_STATUS_E_FAILURE;
4186 cdf_nbuf_free(buf);
4187 }
4188 }
4189 }
4190
4191aggr_qos_exit:
4192 /* send reponse to upper layers from here only. */
4193 wma_send_msg(wma, WMA_AGGR_QOS_RSP, pAggrQosRspMsg, 0);
4194}
4195
4196/**
4197 * wma_add_ts_req() - send ADDTS request to fw
4198 * @wma: wma handle
4199 * @msg: ADDTS params
4200 *
4201 * Return: none
4202 */
4203void wma_add_ts_req(tp_wma_handle wma, tAddTsParams *msg)
4204{
4205 wmi_vdev_wmm_addts_cmd_fixed_param *cmd;
4206 wmi_buf_t buf;
4207 int32_t len = sizeof(*cmd);
4208
4209#ifdef FEATURE_WLAN_ESE
4210 /*
4211 * msmt_interval is in unit called TU (1 TU = 1024 us)
4212 * max value of msmt_interval cannot make resulting
4213 * interval_miliseconds overflow 32 bit
4214 */
4215 uint32_t intervalMiliseconds;
4216 ol_txrx_pdev_handle pdev = cds_get_context(CDF_MODULE_ID_TXRX);
4217 if (NULL == pdev) {
4218 WMA_LOGE("%s: Failed to get pdev", __func__);
4219 goto err;
4220 }
4221
4222 intervalMiliseconds = (msg->tsm_interval * 1024) / 1000;
4223
4224 ol_tx_set_compute_interval(pdev, intervalMiliseconds);
4225#endif /* FEATURE_WLAN_ESE */
4226 msg->status = CDF_STATUS_SUCCESS;
4227
4228 buf = wmi_buf_alloc(wma->wmi_handle, len);
4229 if (!buf) {
4230 WMA_LOGP("%s: wmi_buf_alloc failed", __func__);
4231 goto err;
4232 }
4233 cmd = (wmi_vdev_wmm_addts_cmd_fixed_param *) wmi_buf_data(buf);
4234 WMITLV_SET_HDR(&cmd->tlv_header,
4235 WMITLV_TAG_STRUC_wmi_vdev_wmm_addts_cmd_fixed_param,
4236 WMITLV_GET_STRUCT_TLVLEN
4237 (wmi_vdev_wmm_addts_cmd_fixed_param));
4238 cmd->vdev_id = msg->sme_session_id;
4239 cmd->ac = TID_TO_WME_AC(msg->tspec.tsinfo.traffic.userPrio);
4240 cmd->medium_time_us = msg->tspec.mediumTime * 32;
4241 cmd->downgrade_type = WMM_AC_DOWNGRADE_DROP;
4242 WMA_LOGD("Addts vdev:%d, ac:%d, mediumTime:%d, downgrade_type:%d %s:%d",
4243 cmd->vdev_id, cmd->ac, cmd->medium_time_us,
4244 cmd->downgrade_type, __func__, __LINE__);
4245 if (wmi_unified_cmd_send(wma->wmi_handle, buf, len,
4246 WMI_VDEV_WMM_ADDTS_CMDID)) {
4247 WMA_LOGP("%s: Failed to send vdev ADDTS command", __func__);
4248 msg->status = CDF_STATUS_E_FAILURE;
4249 cdf_nbuf_free(buf);
4250 }
4251#ifdef WLAN_FEATURE_ROAM_OFFLOAD
4252 if (msg->setRICparams == true)
4253 wma_set_ric_req(wma, msg, true);
4254#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
4255
4256err:
4257 wma_send_msg(wma, WMA_ADD_TS_RSP, msg, 0);
4258}
4259
4260/**
4261 * wma_enable_disable_packet_filter() - enable/disable packet filter in target
4262 * @wma: Pointer to wma handle
4263 * @vdev_id: vdev id
4264 * @enable: Flag to enable/disable packet filter
4265 *
4266 * Return: 0 for success or error code
4267 */
4268static int wma_enable_disable_packet_filter(tp_wma_handle wma,
4269 uint8_t vdev_id, bool enable)
4270{
4271 int32_t len;
4272 int ret = 0;
4273 wmi_buf_t buf;
4274 WMI_PACKET_FILTER_ENABLE_CMD_fixed_param *cmd;
4275
4276 len = sizeof(WMI_PACKET_FILTER_ENABLE_CMD_fixed_param);
4277
4278 buf = wmi_buf_alloc(wma->wmi_handle, len);
4279 if (!buf) {
4280 WMA_LOGE("%s: Failed allocate wmi buffer", __func__);
4281 return -ENOMEM;
4282 }
4283
4284 cmd = (WMI_PACKET_FILTER_ENABLE_CMD_fixed_param *) wmi_buf_data(buf);
4285 WMITLV_SET_HDR(&cmd->tlv_header,
4286 WMITLV_TAG_STRUC_wmi_packet_filter_enable_fixed_param,
4287 WMITLV_GET_STRUCT_TLVLEN(
4288 WMI_PACKET_FILTER_ENABLE_CMD_fixed_param));
4289
4290 cmd->vdev_id = vdev_id;
4291 if (enable)
4292 cmd->enable = PACKET_FILTER_SET_ENABLE;
4293 else
4294 cmd->enable = PACKET_FILTER_SET_DISABLE;
4295
4296 WMA_LOGE("%s: Packet filter enable %d for vdev_id %d",
4297 __func__, cmd->enable, vdev_id);
4298
4299 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
4300 WMI_PACKET_FILTER_ENABLE_CMDID);
4301 if (ret)
4302 WMA_LOGE("Failed to send packet filter wmi cmd to fw");
4303
4304 return ret;
4305}
4306
4307/**
4308 * wma_config_packet_filter() - configure packet filter in target
4309 * @wma: Pointer to wma handle
4310 * @vdev_id: vdev id
4311 * @rcv_filter_param: Packet filter parameters
4312 * @filter_id: Filter id
4313 * @enable: Flag to add/delete packet filter configuration
4314 *
4315 * Return: 0 for success or error code
4316 */
4317static int wma_config_packet_filter(tp_wma_handle wma,
4318 uint8_t vdev_id, tSirRcvPktFilterCfgType *rcv_filter_param,
4319 uint8_t filter_id, bool enable)
4320{
4321 int len, i;
4322 int err = 0;
4323 wmi_buf_t buf;
4324 WMI_PACKET_FILTER_CONFIG_CMD_fixed_param *cmd;
4325
4326
4327 /* allocate the memory */
4328 len = sizeof(*cmd);
4329 buf = wmi_buf_alloc(wma->wmi_handle, len);
4330 if (!buf) {
4331 WMA_LOGE("Failed to allocate buffer to send set_param cmd");
4332 return -ENOMEM;
4333 }
4334
4335 cmd = (WMI_PACKET_FILTER_CONFIG_CMD_fixed_param *)wmi_buf_data(buf);
4336 WMITLV_SET_HDR(&cmd->tlv_header,
4337 WMITLV_TAG_STRUC_wmi_packet_filter_config_fixed_param,
4338 WMITLV_GET_STRUCT_TLVLEN
4339 (WMI_PACKET_FILTER_CONFIG_CMD_fixed_param));
4340
4341 cmd->vdev_id = vdev_id;
4342 cmd->filter_id = filter_id;
4343 if (enable)
4344 cmd->filter_action = PACKET_FILTER_SET_ACTIVE;
4345 else
4346 cmd->filter_action = PACKET_FILTER_SET_INACTIVE;
4347
4348 if (enable) {
4349 cmd->num_params = CDF_MIN(
4350 WMI_PACKET_FILTER_MAX_CMP_PER_PACKET_FILTER,
4351 rcv_filter_param->numFieldParams);
4352 cmd->filter_type = rcv_filter_param->filterType;
4353 cmd->coalesce_time = rcv_filter_param->coalesceTime;
4354
4355 for (i = 0; i < cmd->num_params; i++) {
4356 cmd->paramsData[i].proto_type =
4357 rcv_filter_param->paramsData[i].protocolLayer;
4358 cmd->paramsData[i].cmp_type =
4359 rcv_filter_param->paramsData[i].cmpFlag;
4360 cmd->paramsData[i].data_length =
4361 rcv_filter_param->paramsData[i].dataLength;
4362 cmd->paramsData[i].data_offset =
4363 rcv_filter_param->paramsData[i].dataOffset;
4364 memcpy(&cmd->paramsData[i].compareData,
4365 rcv_filter_param->paramsData[i].compareData,
4366 sizeof(cmd->paramsData[i].compareData));
4367 memcpy(&cmd->paramsData[i].dataMask,
4368 rcv_filter_param->paramsData[i].dataMask,
4369 sizeof(cmd->paramsData[i].dataMask));
4370 }
4371 }
4372
4373 WMA_LOGE("Packet filter action %d filter with id: %d, num_params=%d",
4374 cmd->filter_action, cmd->filter_id, cmd->num_params);
4375 /* send the command along with data */
4376 err = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
4377 WMI_PACKET_FILTER_CONFIG_CMDID);
4378 if (err) {
4379 WMA_LOGE("Failed to send pkt_filter cmd");
4380 wmi_buf_free(buf);
4381 return -EIO;
4382 }
4383
4384 /* Enable packet filter */
4385 if (enable)
4386 wma_enable_disable_packet_filter(wma, vdev_id, true);
4387
4388 return 0;
4389}
4390
4391/**
4392 * wma_process_receive_filter_set_filter_req() - enable packet filter
4393 * @wma_handle: wma handle
4394 * @rcv_filter_param: filter params
4395 *
4396 * Return: 0 for success or error code
4397 */
4398int wma_process_receive_filter_set_filter_req(tp_wma_handle wma,
4399 tSirRcvPktFilterCfgType *rcv_filter_param)
4400{
4401 int ret = 0;
4402 uint8_t vdev_id;
4403
4404 /* Get the vdev id */
Srinivas Girigowda98530492015-11-20 17:39:24 -08004405 if (!wma_find_vdev_by_bssid(wma,
4406 rcv_filter_param->bssid.bytes, &vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004407 WMA_LOGE("vdev handle is invalid for %pM",
Srinivas Girigowda98530492015-11-20 17:39:24 -08004408 rcv_filter_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004409 return -EINVAL;
4410 }
4411
4412 ret = wma_config_packet_filter(wma, vdev_id, rcv_filter_param,
4413 rcv_filter_param->filterId, true);
4414
4415 return ret;
4416}
4417
4418/**
4419 * wma_process_receive_filter_clear_filter_req() - disable packet filter
4420 * @wma_handle: wma handle
4421 * @rcv_clear_param: filter params
4422 *
4423 * Return: 0 for success or error code
4424 */
4425int wma_process_receive_filter_clear_filter_req(tp_wma_handle wma,
4426 tSirRcvFltPktClearParam *rcv_clear_param)
4427{
4428 int ret = 0;
4429 uint8_t vdev_id;
4430
4431 /* Get the vdev id */
Srinivas Girigowda98530492015-11-20 17:39:24 -08004432 if (!wma_find_vdev_by_bssid(wma,
4433 rcv_clear_param->bssid.bytes, &vdev_id)) {
4434 WMA_LOGE("vdev handle is invalid for %pM",
4435 rcv_clear_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004436 return -EINVAL;
4437 }
4438
4439 ret = wma_config_packet_filter(wma, vdev_id, NULL,
4440 rcv_clear_param->filterId, false);
4441
4442 return ret;
4443}
4444
4445#ifdef FEATURE_WLAN_ESE
4446
4447#define TSM_DELAY_HISTROGRAM_BINS 4
4448/**
4449 * wma_process_tsm_stats_req() - process tsm stats request
4450 * @wma_handler - handle to wma
4451 * @pTsmStatsMsg - TSM stats struct that needs to be populated and
4452 * passed in message.
4453 *
4454 * A parallel function to WMA_ProcessTsmStatsReq for pronto. This
4455 * function fetches stats from data path APIs and post
4456 * WMA_TSM_STATS_RSP msg back to LIM.
4457 *
4458 * Return: CDF status
4459 */
4460CDF_STATUS wma_process_tsm_stats_req(tp_wma_handle wma_handler,
4461 void *pTsmStatsMsg)
4462{
4463 uint8_t counter;
4464 uint32_t queue_delay_microsec = 0;
4465 uint32_t tx_delay_microsec = 0;
4466 uint16_t packet_count = 0;
4467 uint16_t packet_loss_count = 0;
4468 tpAniTrafStrmMetrics pTsmMetric = NULL;
4469#ifdef FEATURE_WLAN_ESE_UPLOAD
4470 tpAniGetTsmStatsReq pStats = (tpAniGetTsmStatsReq) pTsmStatsMsg;
4471 tpAniGetTsmStatsRsp pTsmRspParams = NULL;
4472#else
4473 tpTSMStats pStats = (tpTSMStats) pTsmStatsMsg;
4474#endif /* FEATURE_WLAN_ESE_UPLOAD */
4475 int tid = pStats->tid;
4476 /*
4477 * The number of histrogram bin report by data path api are different
4478 * than required by TSM, hence different (6) size array used
4479 */
4480 uint16_t bin_values[QCA_TX_DELAY_HIST_REPORT_BINS] = { 0, };
4481
4482 ol_txrx_pdev_handle pdev = cds_get_context(CDF_MODULE_ID_TXRX);
4483
4484 if (NULL == pdev) {
4485 WMA_LOGE("%s: Failed to get pdev", __func__);
4486 cdf_mem_free(pTsmStatsMsg);
4487 return CDF_STATUS_E_INVAL;
4488 }
4489
4490 /* get required values from data path APIs */
4491 ol_tx_delay(pdev, &queue_delay_microsec, &tx_delay_microsec, tid);
4492 ol_tx_delay_hist(pdev, bin_values, tid);
4493 ol_tx_packet_count(pdev, &packet_count, &packet_loss_count, tid);
4494
4495#ifdef FEATURE_WLAN_ESE_UPLOAD
4496 pTsmRspParams =
4497 (tpAniGetTsmStatsRsp) cdf_mem_malloc(sizeof(tAniGetTsmStatsRsp));
4498 if (NULL == pTsmRspParams) {
4499 CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_ERROR,
4500 "%s: CDF MEM Alloc Failure", __func__);
4501 CDF_ASSERT(0);
4502 cdf_mem_free(pTsmStatsMsg);
4503 return CDF_STATUS_E_NOMEM;
4504 }
4505 pTsmRspParams->staId = pStats->staId;
4506 pTsmRspParams->rc = eSIR_FAILURE;
4507 pTsmRspParams->tsmStatsReq = pStats;
4508 pTsmMetric = &pTsmRspParams->tsmMetrics;
4509#else
4510 pTsmMetric = (tpAniTrafStrmMetrics)&(pStats->tsmMetrics);
4511#endif /* FEATURE_WLAN_ESE_UPLOAD */
4512 /* populate pTsmMetric */
4513 pTsmMetric->UplinkPktQueueDly = queue_delay_microsec;
4514 /* store only required number of bin values */
4515 for (counter = 0; counter < TSM_DELAY_HISTROGRAM_BINS; counter++) {
4516 pTsmMetric->UplinkPktQueueDlyHist[counter] =
4517 bin_values[counter];
4518 }
4519 pTsmMetric->UplinkPktTxDly = tx_delay_microsec;
4520 pTsmMetric->UplinkPktLoss = packet_loss_count;
4521 pTsmMetric->UplinkPktCount = packet_count;
4522
4523 /*
4524 * No need to populate roaming delay and roaming count as they are
4525 * being populated just before sending IAPP frame out
4526 */
4527 /* post this message to LIM/PE */
4528#ifdef FEATURE_WLAN_ESE_UPLOAD
4529 wma_send_msg(wma_handler, WMA_TSM_STATS_RSP, (void *)pTsmRspParams, 0);
4530#else
4531 wma_send_msg(wma_handler, WMA_TSM_STATS_RSP, (void *)pTsmStatsMsg, 0);
4532#endif /* FEATURE_WLAN_ESE_UPLOAD */
4533 return CDF_STATUS_SUCCESS;
4534}
4535
4536#endif /* FEATURE_WLAN_ESE */
4537
4538/**
4539 * wma_add_clear_mcbc_filter() - set mcast filter command to fw
4540 * @wma_handle: wma handle
4541 * @vdev_id: vdev id
4542 * @multicastAddr: mcast address
4543 * @clearList: clear list flag
4544 *
4545 * Return: 0 for success or error code
4546 */
4547static int wma_add_clear_mcbc_filter(tp_wma_handle wma_handle, uint8_t vdev_id,
Srinivas Girigowda98530492015-11-20 17:39:24 -08004548 struct cdf_mac_addr multicast_addr,
4549 bool clearList)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004550{
4551 WMI_SET_MCASTBCAST_FILTER_CMD_fixed_param *cmd;
4552 wmi_buf_t buf;
4553 int err;
4554
4555 buf = wmi_buf_alloc(wma_handle->wmi_handle, sizeof(*cmd));
4556 if (!buf) {
4557 WMA_LOGE("Failed to allocate buffer to send set_param cmd");
4558 return -ENOMEM;
4559 }
4560
4561 cmd = (WMI_SET_MCASTBCAST_FILTER_CMD_fixed_param *) wmi_buf_data(buf);
4562 cdf_mem_zero(cmd, sizeof(*cmd));
4563
4564 WMITLV_SET_HDR(&cmd->tlv_header,
4565 WMITLV_TAG_STRUC_WMI_SET_MCASTBCAST_FILTER_CMD_fixed_param,
4566 WMITLV_GET_STRUCT_TLVLEN
4567 (WMI_SET_MCASTBCAST_FILTER_CMD_fixed_param));
4568 cmd->action =
4569 (clearList ? WMI_MCAST_FILTER_DELETE : WMI_MCAST_FILTER_SET);
4570 cmd->vdev_id = vdev_id;
Srinivas Girigowda98530492015-11-20 17:39:24 -08004571 WMI_CHAR_ARRAY_TO_MAC_ADDR(multicast_addr.bytes, &cmd->mcastbdcastaddr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004572 err = wmi_unified_cmd_send(wma_handle->wmi_handle, buf,
4573 sizeof(*cmd),
4574 WMI_SET_MCASTBCAST_FILTER_CMDID);
4575 if (err) {
4576 WMA_LOGE("Failed to send set_param cmd");
4577 cdf_mem_free(buf);
4578 return -EIO;
4579 }
Srinivas Girigowda98530492015-11-20 17:39:24 -08004580 WMA_LOGD("Action:%d; vdev_id:%d; clearList:%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004581 cmd->action, vdev_id, clearList);
Srinivas Girigowda98530492015-11-20 17:39:24 -08004582 WMA_LOGD("MCBC MAC Addr: "MAC_ADDRESS_STR,
4583 MAC_ADDR_ARRAY(multicast_addr.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004584 return 0;
4585}
4586
4587/**
4588 * wma_process_mcbc_set_filter_req() - process mcbc set filter request
4589 * @wma_handle: wma handle
4590 * @mcbc_param: mcbc params
4591 *
4592 * Return: CDF status
4593 */
4594CDF_STATUS wma_process_mcbc_set_filter_req(tp_wma_handle wma_handle,
4595 tSirRcvFltMcAddrList * mcbc_param)
4596{
4597 uint8_t vdev_id = 0;
4598 int i;
4599
4600 if (mcbc_param->ulMulticastAddrCnt <= 0) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004601 WMA_LOGW("Number of multicast addresses is 0");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004602 return CDF_STATUS_E_FAILURE;
4603 }
4604
Srinivas Girigowda98530492015-11-20 17:39:24 -08004605 if (!wma_find_vdev_by_addr(wma_handle,
4606 mcbc_param->self_macaddr.bytes, &vdev_id)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004607 WMA_LOGE("%s: Failed to find vdev id for %pM", __func__,
Srinivas Girigowda98530492015-11-20 17:39:24 -08004608 mcbc_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004609 return CDF_STATUS_E_FAILURE;
4610 }
4611 /* set mcbc_param->action to clear MCList and reset
4612 * to configure the MCList in FW
4613 */
4614
4615 for (i = 0; i < mcbc_param->ulMulticastAddrCnt; i++) {
4616 wma_add_clear_mcbc_filter(wma_handle, vdev_id,
4617 mcbc_param->multicastAddr[i],
4618 (mcbc_param->action == 0));
4619 }
4620 return CDF_STATUS_SUCCESS;
4621}
4622
4623#ifdef WLAN_FEATURE_GTK_OFFLOAD
4624#define GTK_OFFLOAD_ENABLE 0
4625#define GTK_OFFLOAD_DISABLE 1
4626
4627/**
4628 * wma_gtk_offload_status_event() - GTK offload status event handler
4629 * @handle: wma handle
4630 * @event: event buffer
4631 * @len: buffer length
4632 *
4633 * Return: 0 for success or error code
4634 */
4635int wma_gtk_offload_status_event(void *handle, uint8_t *event,
4636 uint32_t len)
4637{
4638 tp_wma_handle wma = (tp_wma_handle) handle;
4639 WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param *status;
4640 WMI_GTK_OFFLOAD_STATUS_EVENTID_param_tlvs *param_buf;
4641 tpSirGtkOffloadGetInfoRspParams resp;
4642 cds_msg_t cds_msg;
4643 uint8_t *bssid;
4644
4645 WMA_LOGD("%s Enter", __func__);
4646
4647 param_buf = (WMI_GTK_OFFLOAD_STATUS_EVENTID_param_tlvs *) event;
4648 if (!param_buf) {
4649 WMA_LOGE("param_buf is NULL");
4650 return -EINVAL;
4651 }
4652
4653 status = (WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param *) param_buf->fixed_param;
4654
4655 if (len < sizeof(WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param)) {
4656 WMA_LOGE("Invalid length for GTK status");
4657 return -EINVAL;
4658 }
4659 bssid = wma_find_bssid_by_vdev_id(wma, status->vdev_id);
4660 if (!bssid) {
4661 WMA_LOGE("invalid bssid for vdev id %d", status->vdev_id);
4662 return -ENOENT;
4663 }
4664
4665 resp = cdf_mem_malloc(sizeof(*resp));
4666 if (!resp) {
4667 WMA_LOGE("%s: Failed to alloc response", __func__);
4668 return -ENOMEM;
4669 }
4670 cdf_mem_zero(resp, sizeof(*resp));
4671 resp->mesgType = eWNI_PMC_GTK_OFFLOAD_GETINFO_RSP;
4672 resp->mesgLen = sizeof(*resp);
4673 resp->ulStatus = CDF_STATUS_SUCCESS;
4674 resp->ulTotalRekeyCount = status->refresh_cnt;
4675 /* TODO: Is the total rekey count and GTK rekey count same? */
4676 resp->ulGTKRekeyCount = status->refresh_cnt;
4677
4678 cdf_mem_copy(&resp->ullKeyReplayCounter, &status->replay_counter,
4679 GTK_REPLAY_COUNTER_BYTES);
4680
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -08004681 cdf_mem_copy(resp->bssid.bytes, bssid, IEEE80211_ADDR_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004682
4683#ifdef IGTK_OFFLOAD
4684 /* TODO: Is the refresh count same for GTK and IGTK? */
4685 resp->ulIGTKRekeyCount = status->refresh_cnt;
4686#endif /* IGTK_OFFLOAD */
4687
4688 cds_msg.type = eWNI_PMC_GTK_OFFLOAD_GETINFO_RSP;
4689 cds_msg.bodyptr = (void *)resp;
4690 cds_msg.bodyval = 0;
4691
4692 if (cds_mq_post_message(CDS_MQ_ID_SME, (cds_msg_t *) &cds_msg)
4693 != CDF_STATUS_SUCCESS) {
4694 WMA_LOGE("Failed to post GTK response to SME");
4695 cdf_mem_free(resp);
4696 return -EINVAL;
4697 }
4698
4699 WMA_LOGD("GTK: got target status with replay counter "
4700 "%02x%02x%02x%02x%02x%02x%02x%02x. vdev %d "
4701 "Refresh GTK %d times exchanges since last set operation",
4702 status->replay_counter[0],
4703 status->replay_counter[1],
4704 status->replay_counter[2],
4705 status->replay_counter[3],
4706 status->replay_counter[4],
4707 status->replay_counter[5],
4708 status->replay_counter[6],
4709 status->replay_counter[7],
4710 status->vdev_id, status->refresh_cnt);
4711
4712 WMA_LOGD("%s Exit", __func__);
4713
4714 return 0;
4715}
4716
4717/**
4718 * wma_send_gtk_offload_req() - send GTK offload command to fw
4719 * @wma: wma handle
4720 * @vdev_id: vdev id
4721 * @params: GTK offload parameters
4722 *
4723 * Return: CDF status
4724 */
4725static CDF_STATUS wma_send_gtk_offload_req(tp_wma_handle wma, uint8_t vdev_id,
4726 tpSirGtkOffloadParams params)
4727{
4728 int len;
4729 wmi_buf_t buf;
4730 WMI_GTK_OFFLOAD_CMD_fixed_param *cmd;
4731 CDF_STATUS status = CDF_STATUS_SUCCESS;
4732
4733 WMA_LOGD("%s Enter", __func__);
4734
4735 len = sizeof(*cmd);
4736
4737 /* alloc wmi buffer */
4738 buf = wmi_buf_alloc(wma->wmi_handle, len);
4739 if (!buf) {
4740 WMA_LOGE("wmi_buf_alloc failed for WMI_GTK_OFFLOAD_CMD");
4741 status = CDF_STATUS_E_NOMEM;
4742 goto out;
4743 }
4744
4745 cmd = (WMI_GTK_OFFLOAD_CMD_fixed_param *) wmi_buf_data(buf);
4746 WMITLV_SET_HDR(&cmd->tlv_header,
4747 WMITLV_TAG_STRUC_WMI_GTK_OFFLOAD_CMD_fixed_param,
4748 WMITLV_GET_STRUCT_TLVLEN
4749 (WMI_GTK_OFFLOAD_CMD_fixed_param));
4750
4751 cmd->vdev_id = vdev_id;
4752
4753 /* Request target to enable GTK offload */
4754 if (params->ulFlags == GTK_OFFLOAD_ENABLE) {
4755 cmd->flags = GTK_OFFLOAD_ENABLE_OPCODE;
4756 wma->wow.gtk_err_enable[vdev_id] = true;
4757
4758 /* Copy the keys and replay counter */
4759 cdf_mem_copy(cmd->KCK, params->aKCK, GTK_OFFLOAD_KCK_BYTES);
4760 cdf_mem_copy(cmd->KEK, params->aKEK, GTK_OFFLOAD_KEK_BYTES);
4761 cdf_mem_copy(cmd->replay_counter, &params->ullKeyReplayCounter,
4762 GTK_REPLAY_COUNTER_BYTES);
4763 } else {
4764 wma->wow.gtk_err_enable[vdev_id] = false;
4765 cmd->flags = GTK_OFFLOAD_DISABLE_OPCODE;
4766 }
4767
4768 /* send the wmi command */
4769 if (wmi_unified_cmd_send(wma->wmi_handle, buf, len,
4770 WMI_GTK_OFFLOAD_CMDID)) {
4771 WMA_LOGE("Failed to send WMI_GTK_OFFLOAD_CMDID");
4772 wmi_buf_free(buf);
4773 status = CDF_STATUS_E_FAILURE;
4774 }
4775
4776 WMA_LOGD("VDEVID: %d, GTK_FLAGS: x%x", vdev_id, cmd->flags);
4777out:
4778 WMA_LOGD("%s Exit", __func__);
4779 return status;
4780}
4781
4782/**
4783 * wma_process_gtk_offload_req() - process GTK offload req from umac
4784 * @handle: wma handle
4785 * @params: GTK offload params
4786 *
4787 * Return: CDF status
4788 */
4789CDF_STATUS wma_process_gtk_offload_req(tp_wma_handle wma,
4790 tpSirGtkOffloadParams params)
4791{
4792 uint8_t vdev_id;
4793 CDF_STATUS status = CDF_STATUS_SUCCESS;
4794
4795 WMA_LOGD("%s Enter", __func__);
4796
4797 /* Get the vdev id */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -08004798 if (!wma_find_vdev_by_bssid(wma, params->bssid.bytes, &vdev_id)) {
4799 WMA_LOGE("vdev handle is invalid for %pM", params->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004800 status = CDF_STATUS_E_INVAL;
4801 goto out;
4802 }
4803
4804 /* Validate vdev id */
4805 if (vdev_id >= wma->max_bssid) {
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -08004806 WMA_LOGE("invalid vdev_id %d for %pM", vdev_id,
4807 params->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004808 status = CDF_STATUS_E_INVAL;
4809 goto out;
4810 }
4811
4812 if ((params->ulFlags == GTK_OFFLOAD_ENABLE) &&
4813 (wma->wow.gtk_err_enable[vdev_id] == true)) {
4814 WMA_LOGE("%s GTK Offload already enabled. Disable it first "
4815 "vdev_id %d", __func__, vdev_id);
4816 params->ulFlags = GTK_OFFLOAD_DISABLE;
4817 status = wma_send_gtk_offload_req(wma, vdev_id, params);
4818 if (status != CDF_STATUS_SUCCESS) {
4819 WMA_LOGE("%s Failed to disable GTK Offload", __func__);
4820 goto out;
4821 }
4822 WMA_LOGD("%s Enable GTK Offload again with updated inputs",
4823 __func__);
4824 params->ulFlags = GTK_OFFLOAD_ENABLE;
4825 }
4826 status = wma_send_gtk_offload_req(wma, vdev_id, params);
4827out:
4828 cdf_mem_free(params);
4829 WMA_LOGD("%s Exit", __func__);
4830 return status;
4831}
4832
4833/**
4834 * wma_process_gtk_offload_getinfo_req() - send GTK offload cmd to fw
4835 * @wma: wma handle
4836 * @params: GTK offload params
4837 *
4838 * Return: CDF status
4839 */
4840CDF_STATUS wma_process_gtk_offload_getinfo_req(tp_wma_handle wma,
4841 tpSirGtkOffloadGetInfoRspParams params)
4842{
4843 uint8_t vdev_id;
4844 int len;
4845 wmi_buf_t buf;
4846 WMI_GTK_OFFLOAD_CMD_fixed_param *cmd;
4847 CDF_STATUS status = CDF_STATUS_SUCCESS;
4848
4849 WMA_LOGD("%s Enter", __func__);
4850
4851 /* Get the vdev id */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -08004852 if (!wma_find_vdev_by_bssid(wma, params->bssid.bytes, &vdev_id)) {
4853 WMA_LOGE("vdev handle is invalid for %pM", params->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004854 status = CDF_STATUS_E_INVAL;
4855 goto out;
4856 }
4857
4858 len = sizeof(*cmd);
4859
4860 /* alloc wmi buffer */
4861 buf = wmi_buf_alloc(wma->wmi_handle, len);
4862 if (!buf) {
4863 WMA_LOGE("wmi_buf_alloc failed for WMI_GTK_OFFLOAD_CMD");
4864 status = CDF_STATUS_E_NOMEM;
4865 goto out;
4866 }
4867
4868 cmd = (WMI_GTK_OFFLOAD_CMD_fixed_param *) wmi_buf_data(buf);
4869 WMITLV_SET_HDR(&cmd->tlv_header,
4870 WMITLV_TAG_STRUC_WMI_GTK_OFFLOAD_CMD_fixed_param,
4871 WMITLV_GET_STRUCT_TLVLEN
4872 (WMI_GTK_OFFLOAD_CMD_fixed_param));
4873
4874 /* Request for GTK offload status */
4875 cmd->flags = GTK_OFFLOAD_REQUEST_STATUS_OPCODE;
4876 cmd->vdev_id = vdev_id;
4877
4878 /* send the wmi command */
4879 if (wmi_unified_cmd_send(wma->wmi_handle, buf, len,
4880 WMI_GTK_OFFLOAD_CMDID)) {
4881 WMA_LOGE("Failed to send WMI_GTK_OFFLOAD_CMDID for req info");
4882 wmi_buf_free(buf);
4883 status = CDF_STATUS_E_FAILURE;
4884 }
4885out:
4886 cdf_mem_free(params);
4887 WMA_LOGD("%s Exit", __func__);
4888 return status;
4889}
4890#endif /* WLAN_FEATURE_GTK_OFFLOAD */
4891
4892/**
4893 * wma_enable_arp_ns_offload() - enable ARP NS offload
4894 * @wma: wma handle
4895 * @tpSirHostOffloadReq: offload request
4896 * @bArpOnly: flag
4897 *
4898 * To configure ARP NS off load data to firmware
4899 * when target goes to wow mode.
4900 *
4901 * Return: CDF Status
4902 */
4903CDF_STATUS wma_enable_arp_ns_offload(tp_wma_handle wma,
4904 tpSirHostOffloadReq
4905 pHostOffloadParams, bool bArpOnly)
4906{
4907 int32_t i;
4908 int32_t res;
4909 WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param *cmd;
4910 WMI_NS_OFFLOAD_TUPLE *ns_tuple;
4911 WMI_ARP_OFFLOAD_TUPLE *arp_tuple;
4912 A_UINT8 *buf_ptr;
4913 wmi_buf_t buf;
4914 int32_t len;
4915 uint8_t vdev_id;
4916 uint32_t count = 0, num_ns_ext_tuples = 0;
4917
4918 /* Get the vdev id */
4919 if (!wma_find_vdev_by_bssid(wma, pHostOffloadParams->bssId, &vdev_id)) {
4920 WMA_LOGE("vdev handle is invalid for %pM",
4921 pHostOffloadParams->bssId);
4922 cdf_mem_free(pHostOffloadParams);
4923 return CDF_STATUS_E_INVAL;
4924 }
4925
4926 if (!wma->interfaces[vdev_id].vdev_up) {
4927
4928 WMA_LOGE("vdev %d is not up skipping arp/ns offload", vdev_id);
4929 cdf_mem_free(pHostOffloadParams);
4930 return CDF_STATUS_E_FAILURE;
4931 }
4932
4933 if (!bArpOnly)
4934 count = pHostOffloadParams->num_ns_offload_count;
4935
4936
4937 len = sizeof(WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param) + WMI_TLV_HDR_SIZE + /* TLV place holder size for array of NS tuples */
4938 WMI_MAX_NS_OFFLOADS * sizeof(WMI_NS_OFFLOAD_TUPLE) + WMI_TLV_HDR_SIZE + /* TLV place holder size for array of ARP tuples */
4939 WMI_MAX_ARP_OFFLOADS * sizeof(WMI_ARP_OFFLOAD_TUPLE);
4940
4941 /*
4942 * If there are more than WMI_MAX_NS_OFFLOADS addresses then allocate
4943 * extra length for extended NS offload tuples which follows ARP offload
4944 * tuples. Host needs to fill this structure in following format:
4945 * 2 NS ofload tuples
4946 * 2 ARP offload tuples
4947 * N numbers of extended NS offload tuples if HDD has given more than
4948 * 2 NS offload addresses
4949 */
4950 if (!bArpOnly && count > WMI_MAX_NS_OFFLOADS) {
4951 num_ns_ext_tuples = count - WMI_MAX_NS_OFFLOADS;
4952 len += WMI_TLV_HDR_SIZE + num_ns_ext_tuples *
4953 sizeof(WMI_NS_OFFLOAD_TUPLE);
4954 }
4955
4956 buf = wmi_buf_alloc(wma->wmi_handle, len);
4957 if (!buf) {
4958 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
4959 cdf_mem_free(pHostOffloadParams);
4960 return CDF_STATUS_E_NOMEM;
4961 }
4962
4963 buf_ptr = (A_UINT8 *) wmi_buf_data(buf);
4964 cmd = (WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param *) buf_ptr;
4965 WMITLV_SET_HDR(&cmd->tlv_header,
4966 WMITLV_TAG_STRUC_WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param,
4967 WMITLV_GET_STRUCT_TLVLEN
4968 (WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param));
4969 cmd->flags = 0;
4970 cmd->vdev_id = vdev_id;
4971 if (!bArpOnly)
4972 cmd->num_ns_ext_tuples = num_ns_ext_tuples;
4973
4974 WMA_LOGD("ARP NS Offload vdev_id: %d", cmd->vdev_id);
4975
4976 /* Have copy of arp info to send along with NS, Since FW expects
4977 * both ARP and NS info in single cmd */
4978 if (bArpOnly)
4979 cdf_mem_copy(&wma->mArpInfo, pHostOffloadParams,
4980 sizeof(tSirHostOffloadReq));
4981
4982 buf_ptr += sizeof(WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param);
4983 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
4984 (WMI_MAX_NS_OFFLOADS * sizeof(WMI_NS_OFFLOAD_TUPLE)));
4985 buf_ptr += WMI_TLV_HDR_SIZE;
4986 for (i = 0; i < WMI_MAX_NS_OFFLOADS; i++) {
4987 ns_tuple = (WMI_NS_OFFLOAD_TUPLE *) buf_ptr;
4988 WMITLV_SET_HDR(&ns_tuple->tlv_header,
4989 WMITLV_TAG_STRUC_WMI_NS_OFFLOAD_TUPLE,
4990 (sizeof(WMI_NS_OFFLOAD_TUPLE) -
4991 WMI_TLV_HDR_SIZE));
4992
4993 /* Fill data only for NS offload in the first ARP tuple for LA */
4994 if (!bArpOnly &&
4995 ((pHostOffloadParams->enableOrDisable & SIR_OFFLOAD_ENABLE))) {
4996 ns_tuple->flags |= WMI_NSOFF_FLAGS_VALID;
4997
4998#ifdef WLAN_NS_OFFLOAD
4999 /*Copy the target/solicitation/remote ip addr */
5000 if (pHostOffloadParams->nsOffloadInfo.
5001 targetIPv6AddrValid[i])
5002 A_MEMCPY(&ns_tuple->target_ipaddr[0],
5003 &pHostOffloadParams->nsOffloadInfo.
5004 targetIPv6Addr[i],
5005 sizeof(WMI_IPV6_ADDR));
5006 A_MEMCPY(&ns_tuple->solicitation_ipaddr,
5007 &pHostOffloadParams->nsOffloadInfo.
5008 selfIPv6Addr[i], sizeof(WMI_IPV6_ADDR));
5009 WMA_LOGD("NS solicitedIp: %pI6, targetIp: %pI6",
5010 &pHostOffloadParams->nsOffloadInfo.selfIPv6Addr[i],
5011 &pHostOffloadParams->nsOffloadInfo.
5012 targetIPv6Addr[i]);
5013
5014 /* target MAC is optional, check if it is valid,
5015 * if this is not valid, the target will use the known
5016 * local MAC address rather than the tuple
5017 */
5018 WMI_CHAR_ARRAY_TO_MAC_ADDR(pHostOffloadParams->
5019 nsOffloadInfo.selfMacAddr,
5020 &ns_tuple->target_mac);
5021#endif /* WLAN_NS_OFFLOAD */
5022 if ((ns_tuple->target_mac.mac_addr31to0 != 0) ||
5023 (ns_tuple->target_mac.mac_addr47to32 != 0)) {
5024 ns_tuple->flags |= WMI_NSOFF_FLAGS_MAC_VALID;
5025 }
5026 }
5027 buf_ptr += sizeof(WMI_NS_OFFLOAD_TUPLE);
5028 }
5029
5030 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
5031 (WMI_MAX_ARP_OFFLOADS * sizeof(WMI_ARP_OFFLOAD_TUPLE)));
5032 buf_ptr += WMI_TLV_HDR_SIZE;
5033 for (i = 0; i < WMI_MAX_ARP_OFFLOADS; i++) {
5034 arp_tuple = (WMI_ARP_OFFLOAD_TUPLE *) buf_ptr;
5035 WMITLV_SET_HDR(&arp_tuple->tlv_header,
5036 WMITLV_TAG_STRUC_WMI_ARP_OFFLOAD_TUPLE,
5037 WMITLV_GET_STRUCT_TLVLEN(WMI_ARP_OFFLOAD_TUPLE));
5038
5039 /* Fill data for ARP and NS in the first tupple for LA */
5040 if ((wma->mArpInfo.enableOrDisable & SIR_OFFLOAD_ENABLE)
5041 && (i == 0)) {
5042 /*Copy the target ip addr and flags */
5043 arp_tuple->flags = WMI_ARPOFF_FLAGS_VALID;
5044 A_MEMCPY(&arp_tuple->target_ipaddr,
5045 wma->mArpInfo.params.hostIpv4Addr,
5046 SIR_IPV4_ADDR_LEN);
5047 WMA_LOGD("ARPOffload IP4 address: %pI4",
5048 wma->mArpInfo.params.hostIpv4Addr);
5049 }
5050 buf_ptr += sizeof(WMI_ARP_OFFLOAD_TUPLE);
5051 }
5052
5053 /* Populate extended NS offload tuples */
5054 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
5055 (num_ns_ext_tuples*sizeof(WMI_NS_OFFLOAD_TUPLE)));
5056 buf_ptr += WMI_TLV_HDR_SIZE;
5057
5058 if (num_ns_ext_tuples) {
5059 for (i = WMI_MAX_NS_OFFLOADS; i < count; i++) {
5060 ns_tuple = (WMI_NS_OFFLOAD_TUPLE *)buf_ptr;
5061 WMITLV_SET_HDR(&ns_tuple->tlv_header,
5062 WMITLV_TAG_STRUC_WMI_NS_OFFLOAD_TUPLE,
5063 (sizeof(WMI_NS_OFFLOAD_TUPLE)-WMI_TLV_HDR_SIZE));
5064
5065 /* Fill data only for NS offload in the first ARP tuple for LA */
5066 if (!bArpOnly &&
5067 ((pHostOffloadParams->enableOrDisable & SIR_OFFLOAD_ENABLE))) {
5068 ns_tuple->flags |= WMI_NSOFF_FLAGS_VALID;
5069#ifdef WLAN_NS_OFFLOAD
5070 /*Copy the target/solicitation/remote ip addr */
5071 if (pHostOffloadParams->nsOffloadInfo.targetIPv6AddrValid[i])
5072 A_MEMCPY(&ns_tuple->target_ipaddr[0],
5073 &pHostOffloadParams->nsOffloadInfo.targetIPv6Addr[i],
5074 sizeof(WMI_IPV6_ADDR));
5075 A_MEMCPY(&ns_tuple->solicitation_ipaddr,
5076 &pHostOffloadParams->nsOffloadInfo.selfIPv6Addr[i],
5077 sizeof(WMI_IPV6_ADDR));
5078 WMA_LOGD("Index %d NS solicitedIp: %pI6, targetIp: %pI6", i,
5079 &pHostOffloadParams->nsOffloadInfo.selfIPv6Addr[i],
5080 &pHostOffloadParams->nsOffloadInfo.targetIPv6Addr[i]);
5081
5082 /* target MAC is optional, check if it is valid, if this is not valid,
5083 * the target will use the known local MAC address rather than the tuple */
5084 WMI_CHAR_ARRAY_TO_MAC_ADDR(pHostOffloadParams->nsOffloadInfo.selfMacAddr,
5085 &ns_tuple->target_mac);
5086#endif
5087 if ((ns_tuple->target_mac.mac_addr31to0 != 0) ||
5088 (ns_tuple->target_mac.mac_addr47to32 != 0)) {
5089 ns_tuple->flags |= WMI_NSOFF_FLAGS_MAC_VALID;
5090 }
5091 }
5092 buf_ptr += sizeof(WMI_NS_OFFLOAD_TUPLE);
5093 }
5094 }
5095
5096 res = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
5097 WMI_SET_ARP_NS_OFFLOAD_CMDID);
5098 if (res) {
5099 WMA_LOGE("Failed to enable ARP NDP/NSffload");
5100 wmi_buf_free(buf);
5101 cdf_mem_free(pHostOffloadParams);
5102 return CDF_STATUS_E_FAILURE;
5103 }
5104
5105 cdf_mem_free(pHostOffloadParams);
5106 return CDF_STATUS_SUCCESS;
5107}
5108
5109/**
5110 * wma_process_add_periodic_tx_ptrn_ind - add periodic tx ptrn
5111 * @handle: wma handle
5112 * @pAddPeriodicTxPtrnParams: tx ptrn params
5113 *
5114 * Retrun: CDF status
5115 */
5116CDF_STATUS wma_process_add_periodic_tx_ptrn_ind(WMA_HANDLE handle,
5117 tSirAddPeriodicTxPtrn *
5118 pAddPeriodicTxPtrnParams)
5119{
5120 tp_wma_handle wma_handle = (tp_wma_handle) handle;
5121 WMI_ADD_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param *cmd;
5122 wmi_buf_t wmi_buf;
5123 uint32_t len;
5124 uint8_t vdev_id;
5125 uint8_t *buf_ptr;
5126 uint32_t ptrn_len, ptrn_len_aligned;
5127 int j;
5128
5129 if (!wma_handle || !wma_handle->wmi_handle) {
5130 WMA_LOGE("%s: WMA is closed, can not issue fw add pattern cmd",
5131 __func__);
5132 return CDF_STATUS_E_INVAL;
5133 }
5134 ptrn_len = pAddPeriodicTxPtrnParams->ucPtrnSize;
5135 ptrn_len_aligned = roundup(ptrn_len, sizeof(uint32_t));
5136 len = sizeof(WMI_ADD_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param) +
5137 WMI_TLV_HDR_SIZE + ptrn_len_aligned;
5138
5139 wmi_buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
5140 if (!wmi_buf) {
5141 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
5142 return CDF_STATUS_E_NOMEM;
5143 }
5144 if (!wma_find_vdev_by_addr(wma_handle,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005145 pAddPeriodicTxPtrnParams->mac_address.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005146 &vdev_id)) {
5147 WMA_LOGE("%s: Failed to find vdev id for %pM", __func__,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005148 pAddPeriodicTxPtrnParams->mac_address.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005149 cdf_nbuf_free(wmi_buf);
5150 return CDF_STATUS_E_INVAL;
5151 }
5152 buf_ptr = (uint8_t *) wmi_buf_data(wmi_buf);
5153
5154 cmd = (WMI_ADD_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param *) buf_ptr;
5155 WMITLV_SET_HDR(&cmd->tlv_header,
5156 WMITLV_TAG_STRUC_WMI_ADD_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param,
5157 WMITLV_GET_STRUCT_TLVLEN
5158 (WMI_ADD_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param));
5159
5160 /* Pass the pattern id to delete for the corresponding vdev id */
5161 cmd->vdev_id = vdev_id;
5162 cmd->pattern_id = pAddPeriodicTxPtrnParams->ucPtrnId;
5163 cmd->timeout = pAddPeriodicTxPtrnParams->usPtrnIntervalMs;
5164 cmd->length = pAddPeriodicTxPtrnParams->ucPtrnSize;
5165
5166 /* Pattern info */
5167 buf_ptr += sizeof(WMI_ADD_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param);
5168 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, ptrn_len_aligned);
5169 buf_ptr += WMI_TLV_HDR_SIZE;
5170 cdf_mem_copy(buf_ptr, pAddPeriodicTxPtrnParams->ucPattern, ptrn_len);
5171 for (j = 0; j < pAddPeriodicTxPtrnParams->ucPtrnSize; j++) {
5172 WMA_LOGD("%s: Add Ptrn: %02x", __func__, buf_ptr[j] & 0xff);
5173 }
5174 WMA_LOGD("%s: Add ptrn id: %d vdev_id: %d",
5175 __func__, cmd->pattern_id, cmd->vdev_id);
5176
5177 if (wmi_unified_cmd_send(wma_handle->wmi_handle, wmi_buf, len,
5178 WMI_ADD_PROACTIVE_ARP_RSP_PATTERN_CMDID)) {
5179 WMA_LOGE("%s: failed to add pattern set state command",
5180 __func__);
5181 cdf_nbuf_free(wmi_buf);
5182 return CDF_STATUS_E_FAILURE;
5183 }
5184 return CDF_STATUS_SUCCESS;
5185}
5186
5187/**
5188 * wma_process_del_periodic_tx_ptrn_ind - del periodic tx ptrn
5189 * @handle: wma handle
5190 * @pDelPeriodicTxPtrnParams: tx ptrn params
5191 *
5192 * Retrun: CDF status
5193 */
5194CDF_STATUS wma_process_del_periodic_tx_ptrn_ind(WMA_HANDLE handle,
5195 tSirDelPeriodicTxPtrn *
5196 pDelPeriodicTxPtrnParams)
5197{
5198 tp_wma_handle wma_handle = (tp_wma_handle) handle;
5199 WMI_DEL_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param *cmd;
5200 wmi_buf_t wmi_buf;
5201 uint8_t vdev_id;
5202 uint32_t len =
5203 sizeof(WMI_DEL_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param);
5204
5205 if (!wma_handle || !wma_handle->wmi_handle) {
5206 WMA_LOGE("%s: WMA is closed, can not issue Del Pattern cmd",
5207 __func__);
5208 return CDF_STATUS_E_INVAL;
5209 }
5210 wmi_buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
5211 if (!wmi_buf) {
5212 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
5213 return CDF_STATUS_E_NOMEM;
5214 }
5215 if (!wma_find_vdev_by_addr(wma_handle,
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08005216 pDelPeriodicTxPtrnParams->mac_address.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005217 &vdev_id)) {
5218 WMA_LOGE("%s: Failed to find vdev id for %pM", __func__,
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08005219 pDelPeriodicTxPtrnParams->mac_address.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005220 cdf_nbuf_free(wmi_buf);
5221 return CDF_STATUS_E_INVAL;
5222 }
5223 cmd = (WMI_DEL_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param *)
5224 wmi_buf_data(wmi_buf);
5225 WMITLV_SET_HDR(&cmd->tlv_header,
5226 WMITLV_TAG_STRUC_WMI_DEL_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param,
5227 WMITLV_GET_STRUCT_TLVLEN
5228 (WMI_DEL_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param));
5229
5230 /* Pass the pattern id to delete for the corresponding vdev id */
5231 cmd->vdev_id = vdev_id;
5232 cmd->pattern_id = pDelPeriodicTxPtrnParams->ucPtrnId;
5233 WMA_LOGD("%s: Del ptrn id: %d vdev_id: %d",
5234 __func__, cmd->pattern_id, cmd->vdev_id);
5235
5236 if (wmi_unified_cmd_send(wma_handle->wmi_handle, wmi_buf, len,
5237 WMI_DEL_PROACTIVE_ARP_RSP_PATTERN_CMDID)) {
5238 WMA_LOGE("%s: failed to send del pattern command", __func__);
5239 cdf_nbuf_free(wmi_buf);
5240 return CDF_STATUS_E_FAILURE;
5241 }
5242 return CDF_STATUS_SUCCESS;
5243}
5244
5245#ifdef WLAN_FEATURE_STATS_EXT
5246/**
5247 * wma_stats_ext_req() - request ext stats from fw
5248 * @wma_ptr: wma handle
5249 * @preq: stats ext params
5250 *
5251 * Return: CDF status
5252 */
5253CDF_STATUS wma_stats_ext_req(void *wma_ptr, tpStatsExtRequest preq)
5254{
5255 int32_t ret;
5256 tp_wma_handle wma = (tp_wma_handle) wma_ptr;
5257 wmi_req_stats_ext_cmd_fixed_param *cmd;
5258 wmi_buf_t buf;
5259 uint16_t len;
5260 uint8_t *buf_ptr;
5261
5262 len = sizeof(*cmd) + WMI_TLV_HDR_SIZE + preq->request_data_len;
5263
5264 buf = wmi_buf_alloc(wma->wmi_handle, len);
5265 if (!buf) {
5266 WMA_LOGE("%s:wmi_buf_alloc failed", __func__);
5267 return -ENOMEM;
5268 }
5269
5270 buf_ptr = (uint8_t *) wmi_buf_data(buf);
5271 cmd = (wmi_req_stats_ext_cmd_fixed_param *) buf_ptr;
5272
5273 WMITLV_SET_HDR(&cmd->tlv_header,
5274 WMITLV_TAG_STRUC_wmi_req_stats_ext_cmd_fixed_param,
5275 WMITLV_GET_STRUCT_TLVLEN
5276 (wmi_req_stats_ext_cmd_fixed_param));
5277 cmd->vdev_id = preq->vdev_id;
5278 cmd->data_len = preq->request_data_len;
5279
5280 WMA_LOGD("%s: The data len value is %u and vdev id set is %u ",
5281 __func__, preq->request_data_len, preq->vdev_id);
5282
5283 buf_ptr += sizeof(wmi_req_stats_ext_cmd_fixed_param);
5284 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, cmd->data_len);
5285
5286 buf_ptr += WMI_TLV_HDR_SIZE;
5287 cdf_mem_copy(buf_ptr, preq->request_data, cmd->data_len);
5288
5289 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
5290 WMI_REQUEST_STATS_EXT_CMDID);
5291 if (ret != EOK) {
5292 WMA_LOGE("%s: Failed to send notify cmd ret = %d", __func__,
5293 ret);
5294 wmi_buf_free(buf);
5295 }
5296
5297 return ret;
5298}
5299
5300#endif /* WLAN_FEATURE_STATS_EXT */
5301
5302#ifdef WLAN_FEATURE_EXTWOW_SUPPORT
5303/**
5304 * wma_send_status_of_ext_wow() - send ext wow status to SME
5305 * @wma: wma handle
5306 * @status: status
5307 *
5308 * Return: none
5309 */
5310static void wma_send_status_of_ext_wow(tp_wma_handle wma, bool status)
5311{
5312 tSirReadyToExtWoWInd *ready_to_extwow;
5313 CDF_STATUS vstatus;
5314 cds_msg_t cds_msg;
5315 uint8_t len;
5316
5317 WMA_LOGD("Posting ready to suspend indication to umac");
5318
5319 len = sizeof(tSirReadyToExtWoWInd);
5320 ready_to_extwow = (tSirReadyToExtWoWInd *) cdf_mem_malloc(len);
5321
5322 if (NULL == ready_to_extwow) {
5323 WMA_LOGE("%s: Memory allocation failure", __func__);
5324 return;
5325 }
5326
5327 ready_to_extwow->mesgType = eWNI_SME_READY_TO_EXTWOW_IND;
5328 ready_to_extwow->mesgLen = len;
5329 ready_to_extwow->status = status;
5330
5331 cds_msg.type = eWNI_SME_READY_TO_EXTWOW_IND;
5332 cds_msg.bodyptr = (void *)ready_to_extwow;
5333 cds_msg.bodyval = 0;
5334
5335 vstatus = cds_mq_post_message(CDS_MQ_ID_SME, &cds_msg);
5336 if (vstatus != CDF_STATUS_SUCCESS) {
5337 WMA_LOGE("Failed to post ready to suspend");
5338 cdf_mem_free(ready_to_extwow);
5339 }
5340}
5341
5342/**
5343 * wma_enable_ext_wow() - enable ext wow in fw
5344 * @wma: wma handle
5345 * @params: ext wow params
5346 *
5347 * Return:0 for success or error code
5348 */
5349int wma_enable_ext_wow(tp_wma_handle wma, tpSirExtWoWParams params)
5350{
5351 wmi_extwow_enable_cmd_fixed_param *cmd;
5352 wmi_buf_t buf;
5353 int32_t len;
5354 int ret;
5355
5356 len = sizeof(wmi_extwow_enable_cmd_fixed_param);
5357 buf = wmi_buf_alloc(wma->wmi_handle, len);
5358 if (!buf) {
5359 WMA_LOGE("%s: Failed allocate wmi buffer", __func__);
5360 return CDF_STATUS_E_NOMEM;
5361 }
5362
5363 cmd = (wmi_extwow_enable_cmd_fixed_param *) wmi_buf_data(buf);
5364
5365 WMITLV_SET_HDR(&cmd->tlv_header,
5366 WMITLV_TAG_STRUC_wmi_extwow_enable_cmd_fixed_param,
5367 WMITLV_GET_STRUCT_TLVLEN
5368 (wmi_extwow_enable_cmd_fixed_param));
5369
5370 cmd->vdev_id = params->vdev_id;
5371 cmd->type = params->type;
5372 cmd->wakeup_pin_num = params->wakeup_pin_num;
5373
5374 WMA_LOGD("%s: vdev_id %d type %d Wakeup_pin_num %x",
5375 __func__, cmd->vdev_id, cmd->type, cmd->wakeup_pin_num);
5376
5377 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
5378 WMI_EXTWOW_ENABLE_CMDID);
5379 if (ret) {
5380 WMA_LOGE("%s: Failed to set EXTWOW Enable", __func__);
5381 wmi_buf_free(buf);
5382 wma_send_status_of_ext_wow(wma, false);
5383 return CDF_STATUS_E_FAILURE;
5384 }
5385
5386 wma_send_status_of_ext_wow(wma, true);
5387 return CDF_STATUS_SUCCESS;
5388
5389}
5390
5391/**
5392 * wma_set_app_type1_params_in_fw() - set app type1 params in fw
5393 * @wma: wma handle
5394 * @appType1Params: app type1 params
5395 *
5396 * Return: CDF status
5397 */
5398int wma_set_app_type1_params_in_fw(tp_wma_handle wma,
5399 tpSirAppType1Params appType1Params)
5400{
5401 wmi_extwow_set_app_type1_params_cmd_fixed_param *cmd;
5402 wmi_buf_t buf;
5403 int32_t len;
5404 int ret;
5405
5406 len = sizeof(wmi_extwow_set_app_type1_params_cmd_fixed_param);
5407 buf = wmi_buf_alloc(wma->wmi_handle, len);
5408 if (!buf) {
5409 WMA_LOGE("%s: Failed allocate wmi buffer", __func__);
5410 return CDF_STATUS_E_NOMEM;
5411 }
5412
5413 cmd = (wmi_extwow_set_app_type1_params_cmd_fixed_param *)
5414 wmi_buf_data(buf);
5415
5416 WMITLV_SET_HDR(&cmd->tlv_header,
5417 WMITLV_TAG_STRUC_wmi_extwow_set_app_type1_params_cmd_fixed_param,
5418 WMITLV_GET_STRUCT_TLVLEN
5419 (wmi_extwow_set_app_type1_params_cmd_fixed_param));
5420
5421 cmd->vdev_id = appType1Params->vdev_id;
5422 WMI_CHAR_ARRAY_TO_MAC_ADDR(appType1Params->wakee_mac_addr,
5423 &cmd->wakee_mac);
5424 cdf_mem_copy(cmd->ident, appType1Params->identification_id, 8);
5425 cmd->ident_len = appType1Params->id_length;
5426 cdf_mem_copy(cmd->passwd, appType1Params->password, 16);
5427 cmd->passwd_len = appType1Params->pass_length;
5428
5429 WMA_LOGD("%s: vdev_id %d wakee_mac_addr %pM "
5430 "identification_id %.8s id_length %u "
5431 "password %.16s pass_length %u",
5432 __func__, cmd->vdev_id, appType1Params->wakee_mac_addr,
5433 cmd->ident, cmd->ident_len, cmd->passwd, cmd->passwd_len);
5434
5435 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
5436 WMI_EXTWOW_SET_APP_TYPE1_PARAMS_CMDID);
5437 if (ret) {
5438 WMA_LOGE("%s: Failed to set APP TYPE1 PARAMS", __func__);
5439 wmi_buf_free(buf);
5440 return CDF_STATUS_E_FAILURE;
5441 }
5442
5443 return CDF_STATUS_SUCCESS;
5444}
5445
5446/**
5447 * wma_set_app_type2_params_in_fw() - set app type2 params in fw
5448 * @wma: wma handle
5449 * @appType2Params: app type2 params
5450 *
5451 * Return: CDF status
5452 */
5453int wma_set_app_type2_params_in_fw(tp_wma_handle wma,
5454 tpSirAppType2Params appType2Params)
5455{
5456 wmi_extwow_set_app_type2_params_cmd_fixed_param *cmd;
5457 wmi_buf_t buf;
5458 int32_t len;
5459 int ret;
5460
5461 len = sizeof(wmi_extwow_set_app_type2_params_cmd_fixed_param);
5462 buf = wmi_buf_alloc(wma->wmi_handle, len);
5463 if (!buf) {
5464 WMA_LOGE("%s: Failed allocate wmi buffer", __func__);
5465 return CDF_STATUS_E_NOMEM;
5466 }
5467
5468 cmd = (wmi_extwow_set_app_type2_params_cmd_fixed_param *)
5469 wmi_buf_data(buf);
5470
5471 WMITLV_SET_HDR(&cmd->tlv_header,
5472 WMITLV_TAG_STRUC_wmi_extwow_set_app_type2_params_cmd_fixed_param,
5473 WMITLV_GET_STRUCT_TLVLEN
5474 (wmi_extwow_set_app_type2_params_cmd_fixed_param));
5475
5476 cmd->vdev_id = appType2Params->vdev_id;
5477
5478 cdf_mem_copy(cmd->rc4_key, appType2Params->rc4_key, 16);
5479 cmd->rc4_key_len = appType2Params->rc4_key_len;
5480
5481 cmd->ip_id = appType2Params->ip_id;
5482 cmd->ip_device_ip = appType2Params->ip_device_ip;
5483 cmd->ip_server_ip = appType2Params->ip_server_ip;
5484
5485 cmd->tcp_src_port = appType2Params->tcp_src_port;
5486 cmd->tcp_dst_port = appType2Params->tcp_dst_port;
5487 cmd->tcp_seq = appType2Params->tcp_seq;
5488 cmd->tcp_ack_seq = appType2Params->tcp_ack_seq;
5489
5490 cmd->keepalive_init = appType2Params->keepalive_init;
5491 cmd->keepalive_min = appType2Params->keepalive_min;
5492 cmd->keepalive_max = appType2Params->keepalive_max;
5493 cmd->keepalive_inc = appType2Params->keepalive_inc;
5494
5495 WMI_CHAR_ARRAY_TO_MAC_ADDR(appType2Params->gateway_mac,
5496 &cmd->gateway_mac);
5497 cmd->tcp_tx_timeout_val = appType2Params->tcp_tx_timeout_val;
5498 cmd->tcp_rx_timeout_val = appType2Params->tcp_rx_timeout_val;
5499
5500 WMA_LOGD("%s: vdev_id %d gateway_mac %pM "
5501 "rc4_key %.16s rc4_key_len %u "
5502 "ip_id %x ip_device_ip %x ip_server_ip %x "
5503 "tcp_src_port %u tcp_dst_port %u tcp_seq %u "
5504 "tcp_ack_seq %u keepalive_init %u keepalive_min %u "
5505 "keepalive_max %u keepalive_inc %u "
5506 "tcp_tx_timeout_val %u tcp_rx_timeout_val %u",
5507 __func__, cmd->vdev_id, appType2Params->gateway_mac,
5508 cmd->rc4_key, cmd->rc4_key_len,
5509 cmd->ip_id, cmd->ip_device_ip, cmd->ip_server_ip,
5510 cmd->tcp_src_port, cmd->tcp_dst_port, cmd->tcp_seq,
5511 cmd->tcp_ack_seq, cmd->keepalive_init, cmd->keepalive_min,
5512 cmd->keepalive_max, cmd->keepalive_inc,
5513 cmd->tcp_tx_timeout_val, cmd->tcp_rx_timeout_val);
5514
5515 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
5516 WMI_EXTWOW_SET_APP_TYPE2_PARAMS_CMDID);
5517 if (ret) {
5518 WMA_LOGE("%s: Failed to set APP TYPE2 PARAMS", __func__);
5519 wmi_buf_free(buf);
5520 return CDF_STATUS_E_FAILURE;
5521 }
5522
5523 return CDF_STATUS_SUCCESS;
5524
5525}
5526#endif /* WLAN_FEATURE_EXTWOW_SUPPORT */
5527
5528#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
5529/**
5530 * wma_auto_shutdown_event_handler() - process auto shutdown timer trigger
5531 * @handle: wma handle
5532 * @event: event buffer
5533 * @len: buffer length
5534 *
5535 * Return: 0 for success or error code
5536 */
5537int wma_auto_shutdown_event_handler(void *handle, uint8_t *event,
5538 uint32_t len)
5539{
5540 wmi_host_auto_shutdown_event_fixed_param *wmi_auto_sh_evt;
5541 WMI_HOST_AUTO_SHUTDOWN_EVENTID_param_tlvs *param_buf =
5542 (WMI_HOST_AUTO_SHUTDOWN_EVENTID_param_tlvs *)
5543 event;
5544
5545 if (!param_buf || !param_buf->fixed_param) {
5546 WMA_LOGE("%s:%d: Invalid Auto shutdown timer evt", __func__,
5547 __LINE__);
5548 return -EINVAL;
5549 }
5550
5551 wmi_auto_sh_evt = param_buf->fixed_param;
5552
5553 if (wmi_auto_sh_evt->shutdown_reason
5554 != WMI_HOST_AUTO_SHUTDOWN_REASON_TIMER_EXPIRY) {
5555 WMA_LOGE("%s:%d: Invalid Auto shutdown timer evt", __func__,
5556 __LINE__);
5557 return -EINVAL;
5558 }
5559
5560 WMA_LOGD("%s:%d: Auto Shutdown Evt: %d", __func__, __LINE__,
5561 wmi_auto_sh_evt->shutdown_reason);
5562 return wma_post_auto_shutdown_msg();
5563}
5564
5565/**
5566 * wma_set_auto_shutdown_timer_req() - sets auto shutdown timer in firmware
5567 * @wma: wma handle
5568 * @auto_sh_cmd: auto shutdown timer value
5569 *
5570 * Return: CDF status
5571 */
5572CDF_STATUS wma_set_auto_shutdown_timer_req(tp_wma_handle wma_handle,
5573 tSirAutoShutdownCmdParams *
5574 auto_sh_cmd)
5575{
5576 int status = 0;
5577 wmi_buf_t buf = NULL;
5578 uint8_t *buf_ptr;
5579 wmi_host_auto_shutdown_cfg_cmd_fixed_param *wmi_auto_sh_cmd;
5580 int len = sizeof(wmi_host_auto_shutdown_cfg_cmd_fixed_param);
5581
5582 if (auto_sh_cmd == NULL) {
5583 WMA_LOGE("%s : Invalid Autoshutdown cfg cmd", __func__);
5584 return CDF_STATUS_E_FAILURE;
5585 }
5586
5587 WMA_LOGD("%s: Set WMI_HOST_AUTO_SHUTDOWN_CFG_CMDID:TIMER_VAL=%d",
5588 __func__, auto_sh_cmd->timer_val);
5589
5590 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
5591 if (!buf) {
5592 WMA_LOGE("%s : wmi_buf_alloc failed", __func__);
5593 return CDF_STATUS_E_NOMEM;
5594 }
5595
5596 buf_ptr = (uint8_t *) wmi_buf_data(buf);
5597 wmi_auto_sh_cmd =
5598 (wmi_host_auto_shutdown_cfg_cmd_fixed_param *) buf_ptr;
5599 wmi_auto_sh_cmd->timer_value = auto_sh_cmd->timer_val;
5600
5601 WMITLV_SET_HDR(&wmi_auto_sh_cmd->tlv_header,
5602 WMITLV_TAG_STRUC_wmi_host_auto_shutdown_cfg_cmd_fixed_param,
5603 WMITLV_GET_STRUCT_TLVLEN
5604 (wmi_host_auto_shutdown_cfg_cmd_fixed_param));
5605
5606 status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf,
5607 len, WMI_HOST_AUTO_SHUTDOWN_CFG_CMDID);
5608 if (status != EOK) {
5609 WMA_LOGE("%s: WMI_HOST_AUTO_SHUTDOWN_CFG_CMDID Err %d",
5610 __func__, status);
5611 wmi_buf_free(buf);
5612 return CDF_STATUS_E_FAILURE;
5613 }
5614
5615 return CDF_STATUS_SUCCESS;
5616}
5617#endif /* FEATURE_WLAN_AUTO_SHUTDOWN */
5618
5619#ifdef WLAN_FEATURE_NAN
5620/**
5621 * wma_nan_req() - to send nan request to target
5622 * @wma: wma_handle
5623 * @nan_req: request data which will be non-null
5624 *
5625 * Return: CDF status
5626 */
5627CDF_STATUS wma_nan_req(void *wma_ptr, tpNanRequest nan_req)
5628{
5629 int ret;
5630 tp_wma_handle wma_handle = (tp_wma_handle) wma_ptr;
5631 wmi_nan_cmd_param *cmd;
5632 wmi_buf_t buf;
5633 uint16_t len = sizeof(*cmd);
5634 uint16_t nan_data_len, nan_data_len_aligned;
5635 uint8_t *buf_ptr;
5636
5637 /*
5638 * <----- cmd ------------><-- WMI_TLV_HDR_SIZE --><--- data ---->
5639 * +------------+----------+-----------------------+--------------+
5640 * | tlv_header | data_len | WMITLV_TAG_ARRAY_BYTE | nan_req_data |
5641 * +------------+----------+-----------------------+--------------+
5642 */
5643 if (!nan_req) {
5644 WMA_LOGE("%s:nan req is not valid", __func__);
5645 return CDF_STATUS_E_FAILURE;
5646 }
5647 nan_data_len = nan_req->request_data_len;
5648 nan_data_len_aligned = roundup(nan_req->request_data_len,
5649 sizeof(uint32_t));
5650 len += WMI_TLV_HDR_SIZE + nan_data_len_aligned;
5651 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
5652 if (!buf) {
5653 WMA_LOGE("%s:wmi_buf_alloc failed", __func__);
5654 return CDF_STATUS_E_NOMEM;
5655 }
5656 buf_ptr = (uint8_t *) wmi_buf_data(buf);
5657 cmd = (wmi_nan_cmd_param *) buf_ptr;
5658 WMITLV_SET_HDR(&cmd->tlv_header,
5659 WMITLV_TAG_STRUC_wmi_nan_cmd_param,
5660 WMITLV_GET_STRUCT_TLVLEN(wmi_nan_cmd_param));
5661 cmd->data_len = nan_req->request_data_len;
5662 WMA_LOGD("%s: The data len value is %u",
5663 __func__, nan_req->request_data_len);
5664 buf_ptr += sizeof(wmi_nan_cmd_param);
5665 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, nan_data_len_aligned);
5666 buf_ptr += WMI_TLV_HDR_SIZE;
5667 cdf_mem_copy(buf_ptr, nan_req->request_data, cmd->data_len);
5668
5669 ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len,
5670 WMI_NAN_CMDID);
5671 if (ret != EOK) {
5672 WMA_LOGE("%s Failed to send set param command ret = %d",
5673 __func__, ret);
5674 wmi_buf_free(buf);
5675 }
5676 return ret;
5677}
5678#endif /* WLAN_FEATURE_NAN */
5679
5680#ifdef DHCP_SERVER_OFFLOAD
5681/**
5682 * wma_process_dhcpserver_offload() - enable DHCP server offload
5683 * @wma_handle: wma handle
5684 * @pDhcpSrvOffloadInfo: DHCP server offload info
5685 *
5686 * Return: 0 for success or error code
5687 */
5688int wma_process_dhcpserver_offload(tp_wma_handle wma_handle,
5689 tSirDhcpSrvOffloadInfo *
5690 pDhcpSrvOffloadInfo)
5691{
5692 wmi_set_dhcp_server_offload_cmd_fixed_param *cmd;
5693 wmi_buf_t buf;
5694 int err;
5695
5696 buf = wmi_buf_alloc(wma_handle->wmi_handle, sizeof(*cmd));
5697 if (!buf) {
5698 WMA_LOGE("Failed to allocate buffer to send "
5699 "set_dhcp_server_offload cmd");
5700 return -ENOMEM;
5701 }
5702
5703 cmd = (wmi_set_dhcp_server_offload_cmd_fixed_param *) wmi_buf_data(buf);
5704 cdf_mem_zero(cmd, sizeof(*cmd));
5705
5706 WMITLV_SET_HDR(&cmd->tlv_header,
5707 WMITLV_TAG_STRUC_wmi_set_dhcp_server_offload_cmd_fixed_param,
5708 WMITLV_GET_STRUCT_TLVLEN
5709 (wmi_set_dhcp_server_offload_cmd_fixed_param));
5710 cmd->vdev_id = pDhcpSrvOffloadInfo->vdev_id;
5711 cmd->enable = pDhcpSrvOffloadInfo->dhcpSrvOffloadEnabled;
5712 cmd->num_client = pDhcpSrvOffloadInfo->dhcpClientNum;
5713 cmd->srv_ipv4 = pDhcpSrvOffloadInfo->dhcpSrvIP;
5714 cmd->start_lsb = 0;
5715 err = wmi_unified_cmd_send(wma_handle->wmi_handle, buf,
5716 sizeof(*cmd),
5717 WMI_SET_DHCP_SERVER_OFFLOAD_CMDID);
5718 if (err) {
5719 WMA_LOGE("Failed to send set_dhcp_server_offload cmd");
5720 wmi_buf_free(buf);
5721 return -EIO;
5722 }
5723 WMA_LOGD("Set dhcp server offload to vdevId %d",
5724 pDhcpSrvOffloadInfo->vdev_id);
5725 return 0;
5726}
5727#endif /* DHCP_SERVER_OFFLOAD */
5728
5729#ifdef WLAN_FEATURE_GPIO_LED_FLASHING
5730/**
5731 * wma_set_led_flashing() - set led flashing in fw
5732 * @wma_handle: wma handle
5733 * @flashing: flashing request
5734 *
5735 * Return: CDF status
5736 */
5737CDF_STATUS wma_set_led_flashing(tp_wma_handle wma_handle,
5738 tSirLedFlashingReq *flashing)
5739{
5740 wmi_set_led_flashing_cmd_fixed_param *cmd;
5741 int status = 0;
5742 wmi_buf_t buf;
5743 uint8_t *buf_ptr;
5744 int32_t len = sizeof(wmi_set_led_flashing_cmd_fixed_param);
5745
5746 if (!wma_handle || !wma_handle->wmi_handle) {
5747 WMA_LOGE(FL("WMA is closed, can not issue cmd"));
5748 return CDF_STATUS_E_INVAL;
5749 }
5750 if (!flashing) {
5751 WMA_LOGE(FL("invalid parameter: flashing"));
5752 return CDF_STATUS_E_INVAL;
5753 }
5754
5755 buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
5756 if (!buf) {
5757 WMA_LOGP(FL("wmi_buf_alloc failed"));
5758 return -ENOMEM;
5759 }
5760 buf_ptr = (uint8_t *) wmi_buf_data(buf);
5761 cmd = (wmi_set_led_flashing_cmd_fixed_param *) buf_ptr;
5762 WMITLV_SET_HDR(&cmd->tlv_header,
5763 WMITLV_TAG_STRUC_wmi_set_led_flashing_cmd_fixed_param,
5764 WMITLV_GET_STRUCT_TLVLEN
5765 (wmi_set_led_flashing_cmd_fixed_param));
5766 cmd->pattern_id = flashing->pattern_id;
5767 cmd->led_x0 = flashing->led_x0;
5768 cmd->led_x1 = flashing->led_x1;
5769
5770 status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len,
5771 WMI_PDEV_SET_LED_FLASHING_CMDID);
5772 if (status != EOK) {
5773 WMA_LOGE("%s: wmi_unified_cmd_send WMI_PEER_SET_PARAM_CMD"
5774 " returned Error %d", __func__, status);
5775 return CDF_STATUS_E_FAILURE;
5776 }
5777 return CDF_STATUS_SUCCESS;
5778}
5779#endif /* WLAN_FEATURE_GPIO_LED_FLASHING */
5780
5781#ifdef FEATURE_WLAN_CH_AVOID
5782/**
5783 * wma_channel_avoid_evt_handler() - process channel to avoid event from FW.
5784 * @handle: wma handle
5785 * @event: event buffer
5786 * @len: buffer length
5787 *
5788 * Return: 0 for success or error code
5789 */
5790int wma_channel_avoid_evt_handler(void *handle, uint8_t *event,
5791 uint32_t len)
5792{
5793 wmi_avoid_freq_ranges_event_fixed_param *afr_fixed_param;
5794 wmi_avoid_freq_range_desc *afr_desc;
5795 uint32_t num_freq_ranges, freq_range_idx;
5796 tSirChAvoidIndType *sca_indication;
5797 CDF_STATUS cdf_status;
5798 cds_msg_t sme_msg = { 0 };
5799 WMI_WLAN_FREQ_AVOID_EVENTID_param_tlvs *param_buf =
5800 (WMI_WLAN_FREQ_AVOID_EVENTID_param_tlvs *) event;
5801
5802 if (!param_buf) {
5803 WMA_LOGE("Invalid channel avoid event buffer");
5804 return -EINVAL;
5805 }
5806
5807 afr_fixed_param = param_buf->fixed_param;
5808 if (!afr_fixed_param) {
5809 WMA_LOGE("Invalid channel avoid event fixed param buffer");
5810 return -EINVAL;
5811 }
5812
5813 num_freq_ranges =
5814 (afr_fixed_param->num_freq_ranges >
5815 SIR_CH_AVOID_MAX_RANGE) ? SIR_CH_AVOID_MAX_RANGE :
5816 afr_fixed_param->num_freq_ranges;
5817
5818 WMA_LOGD("Channel avoid event received with %d ranges",
5819 num_freq_ranges);
5820 for (freq_range_idx = 0; freq_range_idx < num_freq_ranges;
5821 freq_range_idx++) {
5822 afr_desc = (wmi_avoid_freq_range_desc *)
5823 ((void *)param_buf->avd_freq_range +
5824 freq_range_idx * sizeof(wmi_avoid_freq_range_desc));
5825
5826 WMA_LOGD("range %d: tlv id = %u, start freq = %u, end freq = %u",
5827 freq_range_idx, afr_desc->tlv_header, afr_desc->start_freq,
5828 afr_desc->end_freq);
5829 }
5830
5831 sca_indication = (tSirChAvoidIndType *)
5832 cdf_mem_malloc(sizeof(tSirChAvoidIndType));
5833 if (!sca_indication) {
5834 WMA_LOGE("Invalid channel avoid indication buffer");
5835 return -EINVAL;
5836 }
5837
5838 sca_indication->avoid_range_count = num_freq_ranges;
5839 for (freq_range_idx = 0; freq_range_idx < num_freq_ranges;
5840 freq_range_idx++) {
5841 afr_desc = (wmi_avoid_freq_range_desc *)
5842 ((void *)param_buf->avd_freq_range +
5843 freq_range_idx * sizeof(wmi_avoid_freq_range_desc));
5844 sca_indication->avoid_freq_range[freq_range_idx].start_freq =
5845 afr_desc->start_freq;
5846 sca_indication->avoid_freq_range[freq_range_idx].end_freq =
5847 afr_desc->end_freq;
5848 }
5849
5850 sme_msg.type = eWNI_SME_CH_AVOID_IND;
5851 sme_msg.bodyptr = sca_indication;
5852 sme_msg.bodyval = 0;
5853
5854 cdf_status = cds_mq_post_message(CDF_MODULE_ID_SME, &sme_msg);
5855 if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
5856 WMA_LOGE("Fail to post eWNI_SME_CH_AVOID_IND msg to SME");
5857 cdf_mem_free(sca_indication);
5858 return -EINVAL;
5859 }
5860
5861 return 0;
5862}
5863
5864/**
5865 * wma_process_ch_avoid_update_req() - handles channel avoid update request
5866 * @wma_handle: wma handle
5867 * @ch_avoid_update_req: channel avoid update params
5868 *
5869 * Return: CDF status
5870 */
5871CDF_STATUS wma_process_ch_avoid_update_req(tp_wma_handle wma_handle,
5872 tSirChAvoidUpdateReq *
5873 ch_avoid_update_req)
5874{
5875 int status = 0;
5876 wmi_buf_t buf = NULL;
5877 uint8_t *buf_ptr;
5878 wmi_chan_avoid_update_cmd_param *ch_avoid_update_fp;
5879 int len = sizeof(wmi_chan_avoid_update_cmd_param);
5880
5881 if (ch_avoid_update_req == NULL) {
5882 WMA_LOGE("%s : ch_avoid_update_req is NULL", __func__);
5883 return CDF_STATUS_E_FAILURE;
5884 }
5885
5886 WMA_LOGI("%s: WMA --> WMI_CHAN_AVOID_UPDATE", __func__);
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 ch_avoid_update_fp = (wmi_chan_avoid_update_cmd_param *) buf_ptr;
5896 WMITLV_SET_HDR(&ch_avoid_update_fp->tlv_header,
5897 WMITLV_TAG_STRUC_wmi_chan_avoid_update_cmd_param,
5898 WMITLV_GET_STRUCT_TLVLEN
5899 (wmi_chan_avoid_update_cmd_param));
5900
5901 status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf,
5902 len, WMI_CHAN_AVOID_UPDATE_CMDID);
5903 if (status != EOK) {
5904 WMA_LOGE("wmi_unified_cmd_send"
5905 " WMITLV_TABLE_WMI_CHAN_AVOID_UPDATE"
5906 " returned Error %d", status);
5907 wmi_buf_free(buf);
5908 return CDF_STATUS_E_FAILURE;
5909 }
5910
5911 WMA_LOGI("%s: WMA --> WMI_CHAN_AVOID_UPDATE sent through WMI",
5912 __func__);
5913 return CDF_STATUS_SUCCESS;
5914}
5915#endif /* FEATURE_WLAN_CH_AVOID */
5916
5917/**
5918 * wma_set_reg_domain() - set reg domain
5919 * @clientCtxt: client context
5920 * @regId: reg id
5921 *
5922 * Return: CDF status
5923 */
5924CDF_STATUS wma_set_reg_domain(void *clientCtxt, v_REGDOMAIN_t regId)
5925{
5926 if (CDF_STATUS_SUCCESS !=
5927 cds_set_reg_domain(clientCtxt, regId))
5928 return CDF_STATUS_E_INVAL;
5929
5930 return CDF_STATUS_SUCCESS;
5931}
5932
5933/**
5934 * wma_send_regdomain_info_to_fw() - send regdomain info to fw
5935 * @reg_dmn: reg domain
5936 * @regdmn2G: 2G reg domain
5937 * @regdmn5G: 5G reg domain
5938 * @ctl2G: 2G test limit
5939 * @ctl5G: 5G test limit
5940 *
5941 * Return: none
5942 */
5943void wma_send_regdomain_info_to_fw(uint32_t reg_dmn, uint16_t regdmn2G,
5944 uint16_t regdmn5G, int8_t ctl2G,
5945 int8_t ctl5G)
5946{
5947 wmi_buf_t buf;
5948 wmi_pdev_set_regdomain_cmd_fixed_param *cmd;
5949 int32_t len = sizeof(*cmd);
5950 tp_wma_handle wma = cds_get_context(CDF_MODULE_ID_WMA);
5951 int32_t cck_mask_val = 0;
5952 int ret = 0;
5953
5954 if (NULL == wma) {
5955 WMA_LOGE("%s: wma context is NULL", __func__);
5956 return;
5957 }
5958
5959 buf = wmi_buf_alloc(wma->wmi_handle, len);
5960 if (!buf) {
5961 WMA_LOGP("%s: wmi_buf_alloc failed", __func__);
5962 return;
5963 }
5964 cmd = (wmi_pdev_set_regdomain_cmd_fixed_param *) wmi_buf_data(buf);
5965 WMITLV_SET_HDR(&cmd->tlv_header,
5966 WMITLV_TAG_STRUC_wmi_pdev_set_regdomain_cmd_fixed_param,
5967 WMITLV_GET_STRUCT_TLVLEN
5968 (wmi_pdev_set_regdomain_cmd_fixed_param));
5969 cmd->reg_domain = reg_dmn;
5970 cmd->reg_domain_2G = regdmn2G;
5971 cmd->reg_domain_5G = regdmn5G;
5972 cmd->conformance_test_limit_2G = ctl2G;
5973 cmd->conformance_test_limit_5G = ctl5G;
5974
5975 if (wmi_unified_cmd_send(wma->wmi_handle, buf, len,
5976 WMI_PDEV_SET_REGDOMAIN_CMDID)) {
5977 WMA_LOGP("%s: Failed to send pdev set regdomain command",
5978 __func__);
5979 cdf_nbuf_free(buf);
5980 }
5981
5982 if ((((reg_dmn & ~COUNTRY_ERD_FLAG) == CTRY_JAPAN) ||
5983 ((reg_dmn & ~COUNTRY_ERD_FLAG) == CTRY_KOREA_ROC)) &&
5984 (true == wma->tx_chain_mask_cck))
5985 cck_mask_val = 1;
5986
5987 cck_mask_val |= (wma->self_gen_frm_pwr << 16);
5988 ret = wmi_unified_pdev_set_param(wma->wmi_handle,
5989 WMI_PDEV_PARAM_TX_CHAIN_MASK_CCK,
5990 cck_mask_val);
5991 if (ret)
5992 WMA_LOGE("failed to set PDEV tx_chain_mask_cck %d",
5993 ret);
5994
5995 return;
5996}
5997
5998/**
5999 * wma_bus_suspend() - handles bus suspend request from hdd
6000 *
6001 * Calls the appropriate handler based on configuration and event
6002 *
6003 * Return: 0 for success or error code
6004 */
6005int wma_bus_suspend(void)
6006{
6007 WMA_HANDLE handle = cds_get_context(CDF_MODULE_ID_WMA);
6008 if (NULL == handle) {
6009 WMA_LOGE("%s: wma context is NULL", __func__);
6010 return -EFAULT;
6011 }
6012
6013 WMA_LOGE("%s: wow mode selected %d", __func__,
6014 wma_is_wow_mode_selected(handle));
6015
6016 if (wma_check_scan_in_progress(handle)) {
6017 WMA_LOGE("%s: Scan in progress. Aborting suspend", __func__);
6018 return -EBUSY;
6019 }
6020
6021 if (wma_is_wow_mode_selected(handle))
6022 return cdf_status_to_os_return(wma_enable_wow_in_fw(handle));
6023
6024 return wma_suspend_target(handle, 0);
6025}
6026
6027/**
6028 * wma_bus_resume() - handles bus resume request from hdd
6029 * @handle: valid wma handle
6030 *
6031 * Calls the appropriate handler based on configuration
6032 *
6033 * Return: 0 for success or error code
6034 */
6035int wma_bus_resume(void)
6036{
6037 WMA_HANDLE handle = cds_get_context(CDF_MODULE_ID_WMA);
6038 int wow_mode;
6039 if (NULL == handle) {
6040 WMA_LOGE("%s: wma context is NULL", __func__);
6041 return -EFAULT;
6042 }
6043
6044 wow_mode = wma_is_wow_mode_selected(handle);
6045 WMA_LOGE("%s: wow mode %d", __func__, wow_mode);
6046
6047 if (!wow_mode)
6048 return wma_resume_target(handle);
6049
6050 return cdf_status_to_os_return(wma_disable_wow_in_fw(handle));
6051}
6052
6053/**
6054 * wma_suspend_target() - suspend target
6055 * @handle: wma handle
6056 * @disable_target_intr: disable target interrupt
6057 *
6058 * Return: 0 for success or error code
6059 */
6060int wma_suspend_target(WMA_HANDLE handle, int disable_target_intr)
6061{
6062 tp_wma_handle wma_handle = (tp_wma_handle) handle;
6063 wmi_pdev_suspend_cmd_fixed_param *cmd;
6064 wmi_buf_t wmibuf;
6065 uint32_t len = sizeof(*cmd);
6066 struct ol_softc *scn;
6067 int ret;
Yue Mae1a85f32015-10-20 18:12:45 -07006068#ifdef CONFIG_CNSS
6069 tpAniSirGlobal pmac = cds_get_context(CDF_MODULE_ID_PE);
6070#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006071
6072 if (!wma_handle || !wma_handle->wmi_handle) {
6073 WMA_LOGE("WMA is closed. can not issue suspend cmd");
6074 return -EINVAL;
6075 }
Yue Mae1a85f32015-10-20 18:12:45 -07006076
6077#ifdef CONFIG_CNSS
6078 if (NULL == pmac) {
6079 WMA_LOGE("%s: Unable to get PE context", __func__);
6080 return -EINVAL;
6081 }
6082#endif
6083
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006084 /*
6085 * send the comand to Target to ignore the
6086 * PCIE reset so as to ensure that Host and target
6087 * states are in sync
6088 */
6089 wmibuf = wmi_buf_alloc(wma_handle->wmi_handle, len);
6090 if (wmibuf == NULL)
6091 return -ENOMEM;
6092
6093 cmd = (wmi_pdev_suspend_cmd_fixed_param *) wmi_buf_data(wmibuf);
6094 WMITLV_SET_HDR(&cmd->tlv_header,
6095 WMITLV_TAG_STRUC_wmi_pdev_suspend_cmd_fixed_param,
6096 WMITLV_GET_STRUCT_TLVLEN
6097 (wmi_pdev_suspend_cmd_fixed_param));
6098 if (disable_target_intr) {
6099 cmd->suspend_opt = WMI_PDEV_SUSPEND_AND_DISABLE_INTR;
6100 } else {
6101 cmd->suspend_opt = WMI_PDEV_SUSPEND;
6102 }
6103 cdf_event_reset(&wma_handle->target_suspend);
6104 ret = wmi_unified_cmd_send(wma_handle->wmi_handle, wmibuf, len,
6105 WMI_PDEV_SUSPEND_CMDID);
6106 if (ret < 0) {
6107 cdf_nbuf_free(wmibuf);
6108 return ret;
6109 }
6110
6111 wmi_set_target_suspend(wma_handle->wmi_handle, true);
6112
6113 if (cdf_wait_single_event(&wma_handle->target_suspend,
6114 WMA_TGT_SUSPEND_COMPLETE_TIMEOUT)
6115 != CDF_STATUS_SUCCESS) {
6116 WMA_LOGE("Failed to get ACK from firmware for pdev suspend");
6117 wmi_set_target_suspend(wma_handle->wmi_handle, false);
Yue Mae1a85f32015-10-20 18:12:45 -07006118#ifdef CONFIG_CNSS
Yue Ma455aff62015-10-20 18:29:16 -07006119 if (!cds_is_logp_in_progress()) {
6120 if (pmac->sme.enableSelfRecovery) {
6121 cds_trigger_recovery();
6122 } else {
6123 CDF_BUG(0);
6124 }
Yue Mae1a85f32015-10-20 18:12:45 -07006125 } else {
Yue Ma455aff62015-10-20 18:29:16 -07006126 WMA_LOGE("%s: LOGP is in progress, ignore!", __func__);
Yue Mae1a85f32015-10-20 18:12:45 -07006127 }
6128#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006129 return -EFAULT;
6130 }
6131
6132 scn = cds_get_context(CDF_MODULE_ID_HIF);
6133
6134 if (scn == NULL) {
6135 WMA_LOGE("%s: Failed to get HIF context", __func__);
6136 CDF_ASSERT(0);
6137 return -EFAULT;
6138 }
6139
6140 htc_cancel_deferred_target_sleep(scn);
6141
6142 return 0;
6143}
6144
6145/**
6146 * wma_target_suspend_acknowledge() - update target susspend status
6147 * @context: wma context
6148 *
6149 * Return: none
6150 */
6151void wma_target_suspend_acknowledge(void *context)
6152{
6153 tp_wma_handle wma = cds_get_context(CDF_MODULE_ID_WMA);
6154 int wow_nack = *((int *)context);
6155
6156 if (NULL == wma) {
6157 WMA_LOGE("%s: wma is NULL", __func__);
6158 return;
6159 }
6160
6161 wma->wow_nack = wow_nack;
6162 cdf_event_set(&wma->target_suspend);
6163 if (wow_nack)
6164 cdf_wake_lock_timeout_acquire(&wma->wow_wake_lock,
6165 WMA_WAKE_LOCK_TIMEOUT,
6166 WIFI_POWER_EVENT_WAKELOCK_WOW);
6167}
6168
6169/**
6170 * wma_resume_target() - resume target
6171 * @handle: wma handle
6172 *
6173 * Return: 0 for success or error code
6174 */
6175int wma_resume_target(WMA_HANDLE handle)
6176{
6177 int ret;
6178 tp_wma_handle wma = (tp_wma_handle) handle;
6179 wmi_buf_t wmibuf;
6180 wmi_pdev_resume_cmd_fixed_param *cmd;
6181 CDF_STATUS cdf_status = CDF_STATUS_SUCCESS;
6182#ifdef CONFIG_CNSS
6183 tpAniSirGlobal pMac = cds_get_context(CDF_MODULE_ID_PE);
6184 if (NULL == pMac) {
6185 WMA_LOGE("%s: Unable to get PE context", __func__);
6186 return -EINVAL;
6187 }
6188#endif /* CONFIG_CNSS */
6189
6190 wmibuf = wmi_buf_alloc(wma->wmi_handle, sizeof(*cmd));
6191 if (wmibuf == NULL) {
6192 return -ENOMEM;
6193 }
6194 cmd = (wmi_pdev_resume_cmd_fixed_param *) wmi_buf_data(wmibuf);
6195 WMITLV_SET_HDR(&cmd->tlv_header,
6196 WMITLV_TAG_STRUC_wmi_pdev_resume_cmd_fixed_param,
6197 WMITLV_GET_STRUCT_TLVLEN
6198 (wmi_pdev_resume_cmd_fixed_param));
6199 cmd->reserved0 = 0;
6200 cdf_event_reset(&wma->wma_resume_event);
6201 ret = wmi_unified_cmd_send(wma->wmi_handle, wmibuf, sizeof(*cmd),
6202 WMI_PDEV_RESUME_CMDID);
6203 if (ret != EOK) {
6204 WMA_LOGE("Failed to send WMI_PDEV_RESUME_CMDID command");
6205 wmi_buf_free(wmibuf);
6206 }
6207
6208 cdf_status = cdf_wait_single_event(&(wma->wma_resume_event),
6209 WMA_RESUME_TIMEOUT);
6210 if (CDF_STATUS_SUCCESS != cdf_status) {
6211 WMA_LOGP("%s: Timeout waiting for resume event from FW",
6212 __func__);
6213 WMA_LOGP("%s: Pending commands %d credits %d", __func__,
6214 wmi_get_pending_cmds(wma->wmi_handle),
6215 wmi_get_host_credits(wma->wmi_handle));
6216 if (!cds_is_logp_in_progress()) {
6217#ifdef CONFIG_CNSS
6218 if (pMac->sme.enableSelfRecovery) {
6219 cds_trigger_recovery();
6220 } else {
6221 CDF_BUG(0);
6222 }
6223#else
6224 CDF_BUG(0);
6225#endif /* CONFIG_CNSS */
6226 } else {
6227 WMA_LOGE("%s: SSR in progress, ignore resume timeout",
6228 __func__);
6229 }
6230 } else {
6231 WMA_LOGD("Host wakeup received");
6232 }
6233
6234 if (CDF_STATUS_SUCCESS == cdf_status)
6235 wmi_set_target_suspend(wma->wmi_handle, false);
6236
6237 return ret;
6238}
6239
6240/**
6241 * wma_get_modeselect() - get modeSelect flag based on phy_capability
6242 * @wma: wma handle
6243 * @modeSelect: mode Select
6244 *
6245 * Return: none
6246 */
6247void wma_get_modeselect(tp_wma_handle wma, uint32_t *modeSelect)
6248{
6249
6250 switch (wma->phy_capability) {
6251 case WMI_11G_CAPABILITY:
6252 case WMI_11NG_CAPABILITY:
6253 *modeSelect &= ~(REGDMN_MODE_11A | REGDMN_MODE_TURBO |
6254 REGDMN_MODE_108A | REGDMN_MODE_11A_HALF_RATE |
6255 REGDMN_MODE_11A_QUARTER_RATE |
6256 REGDMN_MODE_11NA_HT20 |
6257 REGDMN_MODE_11NA_HT40PLUS |
6258 REGDMN_MODE_11NA_HT40MINUS |
6259 REGDMN_MODE_11AC_VHT20 |
6260 REGDMN_MODE_11AC_VHT40PLUS |
6261 REGDMN_MODE_11AC_VHT40MINUS |
6262 REGDMN_MODE_11AC_VHT80);
6263 break;
6264 case WMI_11A_CAPABILITY:
6265 case WMI_11NA_CAPABILITY:
6266 case WMI_11AC_CAPABILITY:
6267 *modeSelect &= ~(REGDMN_MODE_11B | REGDMN_MODE_11G |
6268 REGDMN_MODE_108G | REGDMN_MODE_11NG_HT20 |
6269 REGDMN_MODE_11NG_HT40PLUS |
6270 REGDMN_MODE_11NG_HT40MINUS |
6271 REGDMN_MODE_11AC_VHT20_2G |
6272 REGDMN_MODE_11AC_VHT40_2G |
6273 REGDMN_MODE_11AC_VHT80_2G);
6274 break;
6275 }
6276}
6277
6278
6279#ifdef FEATURE_WLAN_TDLS
6280/**
6281 * wma_tdls_event_handler() - handle TDLS event
6282 * @handle: wma handle
6283 * @event: event buffer
6284 * @len: buffer length
6285 *
6286 * Return: 0 for success or error code
6287 */
6288int wma_tdls_event_handler(void *handle, uint8_t *event, uint32_t len)
6289{
6290 tp_wma_handle wma = (tp_wma_handle) handle;
6291 WMI_TDLS_PEER_EVENTID_param_tlvs *param_buf = NULL;
6292 wmi_tdls_peer_event_fixed_param *peer_event = NULL;
6293 tSirTdlsEventnotify *tdls_event;
6294
6295 if (!event) {
6296 WMA_LOGE("%s: event param null", __func__);
6297 return -EINVAL;
6298 }
6299
6300 param_buf = (WMI_TDLS_PEER_EVENTID_param_tlvs *) event;
6301 if (!param_buf) {
6302 WMA_LOGE("%s: received null buf from target", __func__);
6303 return -EINVAL;
6304 }
6305
6306 peer_event = param_buf->fixed_param;
6307 if (!peer_event) {
6308 WMA_LOGE("%s: received null event data from target", __func__);
6309 return -EINVAL;
6310 }
6311
6312 tdls_event = (tSirTdlsEventnotify *)
6313 cdf_mem_malloc(sizeof(*tdls_event));
6314 if (!tdls_event) {
6315 WMA_LOGE("%s: failed to allocate memory for tdls_event",
6316 __func__);
6317 return -ENOMEM;
6318 }
6319
6320 tdls_event->sessionId = peer_event->vdev_id;
6321 WMI_MAC_ADDR_TO_CHAR_ARRAY(&peer_event->peer_macaddr,
Srinivas Girigowda4f593792015-11-19 15:33:42 -08006322 tdls_event->peermac.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006323
6324 switch (peer_event->peer_status) {
6325 case WMI_TDLS_SHOULD_DISCOVER:
6326 tdls_event->messageType = WMA_TDLS_SHOULD_DISCOVER_CMD;
6327 break;
6328 case WMI_TDLS_SHOULD_TEARDOWN:
6329 tdls_event->messageType = WMA_TDLS_SHOULD_TEARDOWN_CMD;
6330 break;
6331 case WMI_TDLS_PEER_DISCONNECTED:
6332 tdls_event->messageType = WMA_TDLS_PEER_DISCONNECTED_CMD;
6333 break;
6334 default:
6335 WMA_LOGE("%s: Discarding unknown tdls event(%d) from target",
6336 __func__, peer_event->peer_status);
6337 return -EINVAL;
6338 }
6339
6340 switch (peer_event->peer_reason) {
6341 case WMI_TDLS_TEARDOWN_REASON_TX:
6342 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_TX;
6343 break;
6344 case WMI_TDLS_TEARDOWN_REASON_RSSI:
6345 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_RSSI;
6346 break;
6347 case WMI_TDLS_TEARDOWN_REASON_SCAN:
6348 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_SCAN;
6349 break;
6350 case WMI_TDLS_DISCONNECTED_REASON_PEER_DELETE:
6351 tdls_event->peer_reason =
6352 eWNI_TDLS_DISCONNECTED_REASON_PEER_DELETE;
6353 break;
6354 case WMI_TDLS_TEARDOWN_REASON_PTR_TIMEOUT:
6355 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_PTR_TIMEOUT;
6356 break;
6357 case WMI_TDLS_TEARDOWN_REASON_BAD_PTR:
6358 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_BAD_PTR;
6359 break;
6360 case WMI_TDLS_TEARDOWN_REASON_NO_RESPONSE:
6361 tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_NO_RESPONSE;
6362 break;
6363 default:
6364 WMA_LOGE("%s: unknown reason(%d) in tdls event(%d) from target",
6365 __func__, peer_event->peer_reason,
6366 peer_event->peer_status);
6367 return -EINVAL;
6368 }
6369
6370 WMA_LOGD("%s: sending msg to umac, messageType: 0x%x, "
6371 "for peer: %pM, reason: %d, smesessionId: %d",
Srinivas Girigowda4f593792015-11-19 15:33:42 -08006372 __func__, tdls_event->messageType, tdls_event->peermac.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006373 tdls_event->peer_reason, tdls_event->sessionId);
6374
6375 wma_send_msg(wma, tdls_event->messageType, (void *)tdls_event, 0);
6376 return 0;
6377}
6378
6379/**
6380 * wma_set_tdls_offchan_mode() - set tdls off channel mode
6381 * @handle: wma handle
6382 * @chan_switch_params: Pointer to tdls channel switch parameter structure
6383 *
6384 * This function sets tdls off channel mode
6385 *
6386 * Return: 0 on success; Negative errno otherwise
6387 */
6388int wma_set_tdls_offchan_mode(WMA_HANDLE handle,
6389 tdls_chan_switch_params *chan_switch_params)
6390{
6391 tp_wma_handle wma_handle = (tp_wma_handle) handle;
6392 wmi_tdls_set_offchan_mode_cmd_fixed_param *cmd;
6393 wmi_buf_t wmi_buf;
6394 u_int16_t len = sizeof(wmi_tdls_set_offchan_mode_cmd_fixed_param);
6395 int ret = 0;
6396
6397 if (!wma_handle || !wma_handle->wmi_handle) {
6398 WMA_LOGE(FL(
6399 "WMA is closed, can not issue tdls off channel cmd"
6400 ));
6401 ret = -EINVAL;
6402 goto end;
6403 }
6404 wmi_buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
6405 if (!wmi_buf) {
6406 WMA_LOGE(FL("wmi_buf_alloc failed"));
6407 ret = -ENOMEM;
6408 goto end;
6409 }
6410 cmd = (wmi_tdls_set_offchan_mode_cmd_fixed_param *)
6411 wmi_buf_data(wmi_buf);
6412 WMITLV_SET_HDR(&cmd->tlv_header,
6413 WMITLV_TAG_STRUC_wmi_tdls_set_offchan_mode_cmd_fixed_param,
6414 WMITLV_GET_STRUCT_TLVLEN(
6415 wmi_tdls_set_offchan_mode_cmd_fixed_param));
6416
6417 WMI_CHAR_ARRAY_TO_MAC_ADDR(chan_switch_params->peer_mac_addr,
6418 &cmd->peer_macaddr);
6419 cmd->vdev_id = chan_switch_params->vdev_id;
6420 cmd->offchan_mode = chan_switch_params->tdls_sw_mode;
6421 cmd->is_peer_responder = chan_switch_params->is_responder;
6422 cmd->offchan_num = chan_switch_params->tdls_off_ch;
6423 cmd->offchan_bw_bitmap = chan_switch_params->tdls_off_ch_bw_offset;
6424 cmd->offchan_oper_class = chan_switch_params->oper_class;
6425
6426 WMA_LOGD(FL("Peer MAC Addr mac_addr31to0: 0x%x, mac_addr47to32: 0x%x"),
6427 cmd->peer_macaddr.mac_addr31to0,
6428 cmd->peer_macaddr.mac_addr47to32);
6429
6430 WMA_LOGD(FL(
6431 "vdev_id: %d, off channel mode: %d, off channel Num: %d, off channel offset: 0x%x, is_peer_responder: %d, operating class: %d"
6432 ),
6433 cmd->vdev_id,
6434 cmd->offchan_mode,
6435 cmd->offchan_num,
6436 cmd->offchan_bw_bitmap,
6437 cmd->is_peer_responder,
6438 cmd->offchan_oper_class);
6439
6440 if (wmi_unified_cmd_send(wma_handle->wmi_handle, wmi_buf, len,
6441 WMI_TDLS_SET_OFFCHAN_MODE_CMDID)) {
6442 WMA_LOGP(FL("failed to send tdls off chan command"));
6443 cdf_nbuf_free(wmi_buf);
6444 ret = -EIO;
6445 }
6446
6447end:
6448 if (chan_switch_params)
6449 cdf_mem_free(chan_switch_params);
6450 return ret;
6451}
6452
6453/**
6454 * wma_update_fw_tdls_state() - send enable/disable tdls for a vdev
6455 * @wma: wma handle
6456 * @pwmaTdlsparams: TDLS params
6457 *
6458 * Return: 0 for sucess or error code
6459 */
6460int wma_update_fw_tdls_state(WMA_HANDLE handle, void *pwmaTdlsparams)
6461{
6462 tp_wma_handle wma_handle = (tp_wma_handle) handle;
6463 wmi_tdls_set_state_cmd_fixed_param *cmd;
6464 wmi_buf_t wmi_buf;
6465 t_wma_tdls_mode tdls_mode;
6466 t_wma_tdls_params *wma_tdls = (t_wma_tdls_params *) pwmaTdlsparams;
6467 uint16_t len = sizeof(wmi_tdls_set_state_cmd_fixed_param);
6468 int ret = 0;
6469
6470 if (!wma_handle || !wma_handle->wmi_handle) {
6471 WMA_LOGE("%s: WMA is closed, can not issue fw tdls state cmd",
6472 __func__);
6473 ret = -EINVAL;
6474 goto end_fw_tdls_state;
6475 }
6476
6477 wmi_buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
6478 if (!wmi_buf) {
6479 WMA_LOGE("%s: wmai_buf_alloc failed", __func__);
6480 ret = ENOMEM;
6481 goto end_fw_tdls_state;
6482 }
6483 tdls_mode = wma_tdls->tdls_state;
6484 cmd = (wmi_tdls_set_state_cmd_fixed_param *) wmi_buf_data(wmi_buf);
6485 WMITLV_SET_HDR(&cmd->tlv_header,
6486 WMITLV_TAG_STRUC_wmi_tdls_set_state_cmd_fixed_param,
6487 WMITLV_GET_STRUCT_TLVLEN
6488 (wmi_tdls_set_state_cmd_fixed_param));
6489 cmd->vdev_id = wma_tdls->vdev_id;
6490
6491 if (WMA_TDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY == tdls_mode) {
6492 cmd->state = WMI_TDLS_ENABLE_PASSIVE;
6493 } else if (WMA_TDLS_SUPPORT_ENABLED == tdls_mode) {
6494 cmd->state = WMI_TDLS_ENABLE_ACTIVE;
Kabilan Kannan421714b2015-11-23 04:44:59 -08006495 } else if (WMA_TDLS_SUPPORT_ACTIVE_EXTERNAL_CONTROL == tdls_mode) {
6496 cmd->state = WMI_TDLS_ENABLE_ACTIVE_EXTERNAL_CONTROL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006497 } else {
6498 cmd->state = WMI_TDLS_DISABLE;
6499 }
6500
6501 cmd->notification_interval_ms = wma_tdls->notification_interval_ms;
6502 cmd->tx_discovery_threshold = wma_tdls->tx_discovery_threshold;
6503 cmd->tx_teardown_threshold = wma_tdls->tx_teardown_threshold;
6504 cmd->rssi_teardown_threshold = wma_tdls->rssi_teardown_threshold;
6505 cmd->rssi_delta = wma_tdls->rssi_delta;
6506 cmd->tdls_options = wma_tdls->tdls_options;
6507 cmd->tdls_peer_traffic_ind_window = wma_tdls->peer_traffic_ind_window;
6508 cmd->tdls_peer_traffic_response_timeout_ms =
6509 wma_tdls->peer_traffic_response_timeout;
6510 cmd->tdls_puapsd_mask = wma_tdls->puapsd_mask;
6511 cmd->tdls_puapsd_inactivity_time_ms = wma_tdls->puapsd_inactivity_time;
6512 cmd->tdls_puapsd_rx_frame_threshold =
6513 wma_tdls->puapsd_rx_frame_threshold;
Kabilan Kannanca670be2015-11-23 01:56:12 -08006514 cmd->teardown_notification_ms =
6515 wma_tdls->teardown_notification_ms;
Kabilan Kannan421714b2015-11-23 04:44:59 -08006516 cmd->tdls_peer_kickout_threshold =
6517 wma_tdls->tdls_peer_kickout_threshold;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006518
6519 WMA_LOGD("%s: tdls_mode: %d, state: %d, "
6520 "notification_interval_ms: %d, "
6521 "tx_discovery_threshold: %d, "
6522 "tx_teardown_threshold: %d, "
6523 "rssi_teardown_threshold: %d, "
6524 "rssi_delta: %d, "
6525 "tdls_options: 0x%x, "
6526 "tdls_peer_traffic_ind_window: %d, "
6527 "tdls_peer_traffic_response_timeout: %d, "
6528 "tdls_puapsd_mask: 0x%x, "
6529 "tdls_puapsd_inactivity_time: %d, "
Kabilan Kannanca670be2015-11-23 01:56:12 -08006530 "tdls_puapsd_rx_frame_threshold: %d, "
Kabilan Kannan421714b2015-11-23 04:44:59 -08006531 "teardown_notification_ms: %d, "
6532 "tdls_peer_kickout_threshold: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006533 __func__, tdls_mode, cmd->state,
6534 cmd->notification_interval_ms,
6535 cmd->tx_discovery_threshold,
6536 cmd->tx_teardown_threshold,
6537 cmd->rssi_teardown_threshold,
6538 cmd->rssi_delta,
6539 cmd->tdls_options,
6540 cmd->tdls_peer_traffic_ind_window,
6541 cmd->tdls_peer_traffic_response_timeout_ms,
6542 cmd->tdls_puapsd_mask,
6543 cmd->tdls_puapsd_inactivity_time_ms,
Kabilan Kannanca670be2015-11-23 01:56:12 -08006544 cmd->tdls_puapsd_rx_frame_threshold,
Kabilan Kannan421714b2015-11-23 04:44:59 -08006545 cmd->teardown_notification_ms,
6546 cmd->tdls_peer_kickout_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006547
6548 if (wmi_unified_cmd_send(wma_handle->wmi_handle, wmi_buf, len,
6549 WMI_TDLS_SET_STATE_CMDID)) {
6550 WMA_LOGP("%s: failed to send tdls set state command", __func__);
6551 cdf_nbuf_free(wmi_buf);
6552 ret = -EIO;
6553 goto end_fw_tdls_state;
6554 }
6555 WMA_LOGD("%s: vdev_id %d", __func__, wma_tdls->vdev_id);
6556
6557end_fw_tdls_state:
6558 if (pwmaTdlsparams)
6559 cdf_mem_free(pwmaTdlsparams);
6560 return ret;
6561}
6562
6563/**
6564 * wma_update_tdls_peer_state() - update TDLS peer state
6565 * @handle: wma handle
6566 * @peerStateParams: TDLS peer state params
6567 *
6568 * Return: 0 for success or error code
6569 */
6570int wma_update_tdls_peer_state(WMA_HANDLE handle,
6571 tTdlsPeerStateParams *peerStateParams)
6572{
6573 tp_wma_handle wma_handle = (tp_wma_handle) handle;
6574 wmi_tdls_peer_update_cmd_fixed_param *cmd;
6575 wmi_tdls_peer_capabilities *peer_cap;
6576 wmi_channel *chan_info;
6577 wmi_buf_t wmi_buf;
6578 uint8_t *buf_ptr;
6579 uint32_t i;
6580 ol_txrx_pdev_handle pdev;
6581 uint8_t peer_id;
6582 struct ol_txrx_peer_t *peer;
6583 int32_t len = sizeof(wmi_tdls_peer_update_cmd_fixed_param) +
6584 sizeof(wmi_tdls_peer_capabilities);
6585 int ret = 0;
6586
6587 if (!wma_handle || !wma_handle->wmi_handle) {
6588 WMA_LOGE("%s: WMA is closed, can not issue cmd", __func__);
6589 ret = -EINVAL;
6590 goto end_tdls_peer_state;
6591 }
6592
6593 /* peer capability info is valid only when peer state is connected */
6594 if (WMA_TDLS_PEER_STATE_CONNECTED != peerStateParams->peerState) {
6595 cdf_mem_zero(&peerStateParams->peerCap,
6596 sizeof(tTdlsPeerCapParams));
6597 }
6598
6599 len += WMI_TLV_HDR_SIZE +
6600 sizeof(wmi_channel) * peerStateParams->peerCap.peerChanLen;
6601
6602 wmi_buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
6603 if (!wmi_buf) {
6604 WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
6605 ret = ENOMEM;
6606 goto end_tdls_peer_state;
6607 }
6608
6609 buf_ptr = (uint8_t *) wmi_buf_data(wmi_buf);
6610 cmd = (wmi_tdls_peer_update_cmd_fixed_param *) buf_ptr;
6611 WMITLV_SET_HDR(&cmd->tlv_header,
6612 WMITLV_TAG_STRUC_wmi_tdls_peer_update_cmd_fixed_param,
6613 WMITLV_GET_STRUCT_TLVLEN
6614 (wmi_tdls_peer_update_cmd_fixed_param));
6615
6616 cmd->vdev_id = peerStateParams->vdevId;
6617 WMI_CHAR_ARRAY_TO_MAC_ADDR(peerStateParams->peerMacAddr,
6618 &cmd->peer_macaddr);
6619
6620 switch (peerStateParams->peerState) {
6621 case WMA_TDLS_PEER_STATE_PEERING:
6622 cmd->peer_state = WMI_TDLS_PEER_STATE_PEERING;
6623 break;
6624 case WMA_TDLS_PEER_STATE_CONNECTED:
6625 cmd->peer_state = WMI_TDLS_PEER_STATE_CONNECTED;
6626 break;
6627 case WMA_TDLS_PEER_STATE_TEARDOWN:
6628 cmd->peer_state = WMI_TDLS_PEER_STATE_TEARDOWN;
6629 break;
Kabilan Kannan421714b2015-11-23 04:44:59 -08006630 case WMA_TDLS_PEER_ADD_MAC_ADDR:
6631 cmd->peer_state = WMI_TDLS_PEER_ADD_MAC_ADDR;
6632 break;
6633 case WMA_TDLS_PEER_REMOVE_MAC_ADDR:
6634 cmd->peer_state = WMI_TDLS_PEER_REMOVE_MAC_ADDR;
6635 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006636 }
6637
6638 WMA_LOGD("%s: vdev_id: %d, peerStateParams->peerMacAddr: %pM, "
6639 "peer_macaddr.mac_addr31to0: 0x%x, "
6640 "peer_macaddr.mac_addr47to32: 0x%x, peer_state: %d",
6641 __func__, cmd->vdev_id, peerStateParams->peerMacAddr,
6642 cmd->peer_macaddr.mac_addr31to0,
6643 cmd->peer_macaddr.mac_addr47to32, cmd->peer_state);
6644
6645 buf_ptr += sizeof(wmi_tdls_peer_update_cmd_fixed_param);
6646 peer_cap = (wmi_tdls_peer_capabilities *) buf_ptr;
6647 WMITLV_SET_HDR(&peer_cap->tlv_header,
6648 WMITLV_TAG_STRUC_wmi_tdls_peer_capabilities,
6649 WMITLV_GET_STRUCT_TLVLEN(wmi_tdls_peer_capabilities));
6650
6651 if ((peerStateParams->peerCap.peerUapsdQueue & 0x08) >> 3)
6652 WMI_SET_TDLS_PEER_VO_UAPSD(peer_cap);
6653 if ((peerStateParams->peerCap.peerUapsdQueue & 0x04) >> 2)
6654 WMI_SET_TDLS_PEER_VI_UAPSD(peer_cap);
6655 if ((peerStateParams->peerCap.peerUapsdQueue & 0x02) >> 1)
6656 WMI_SET_TDLS_PEER_BK_UAPSD(peer_cap);
6657 if (peerStateParams->peerCap.peerUapsdQueue & 0x01)
6658 WMI_SET_TDLS_PEER_BE_UAPSD(peer_cap);
6659
6660 /* Ack and More Data Ack are sent as 0, so no need to set
6661 * but fill SP
6662 */
6663 WMI_SET_TDLS_PEER_SP_UAPSD(peer_cap,
6664 peerStateParams->peerCap.peerMaxSp);
6665
6666 peer_cap->buff_sta_support =
6667 peerStateParams->peerCap.peerBuffStaSupport;
6668 peer_cap->off_chan_support =
6669 peerStateParams->peerCap.peerOffChanSupport;
6670 peer_cap->peer_curr_operclass =
6671 peerStateParams->peerCap.peerCurrOperClass;
6672 /* self curr operclass is not being used and so pass op class for
6673 * preferred off chan in it.
6674 */
6675 peer_cap->self_curr_operclass =
6676 peerStateParams->peerCap.opClassForPrefOffChan;
6677 peer_cap->peer_chan_len = peerStateParams->peerCap.peerChanLen;
6678 peer_cap->peer_operclass_len =
6679 peerStateParams->peerCap.peerOperClassLen;
6680
6681 WMA_LOGD("%s: peer_operclass_len: %d",
6682 __func__, peer_cap->peer_operclass_len);
6683 for (i = 0; i < WMI_TDLS_MAX_SUPP_OPER_CLASSES; i++) {
6684 peer_cap->peer_operclass[i] =
6685 peerStateParams->peerCap.peerOperClass[i];
6686 WMA_LOGD("%s: peer_operclass[%d]: %d",
6687 __func__, i, peer_cap->peer_operclass[i]);
6688 }
6689
6690 peer_cap->is_peer_responder = peerStateParams->peerCap.isPeerResponder;
6691 peer_cap->pref_offchan_num = peerStateParams->peerCap.prefOffChanNum;
6692 peer_cap->pref_offchan_bw =
6693 peerStateParams->peerCap.prefOffChanBandwidth;
6694
6695 WMA_LOGD
6696 ("%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",
6697 __func__, peer_cap->peer_qos, peer_cap->buff_sta_support,
6698 peer_cap->off_chan_support, peer_cap->peer_curr_operclass,
6699 peer_cap->self_curr_operclass, peer_cap->peer_chan_len,
6700 peer_cap->peer_operclass_len, peer_cap->is_peer_responder,
6701 peer_cap->pref_offchan_num, peer_cap->pref_offchan_bw);
6702
6703 /* next fill variable size array of peer chan info */
6704 buf_ptr += sizeof(wmi_tdls_peer_capabilities);
6705 WMITLV_SET_HDR(buf_ptr,
6706 WMITLV_TAG_ARRAY_STRUC,
6707 sizeof(wmi_channel) *
6708 peerStateParams->peerCap.peerChanLen);
6709 chan_info = (wmi_channel *) (buf_ptr + WMI_TLV_HDR_SIZE);
6710
6711 for (i = 0; i < peerStateParams->peerCap.peerChanLen; ++i) {
6712 WMITLV_SET_HDR(&chan_info->tlv_header,
6713 WMITLV_TAG_STRUC_wmi_channel,
6714 WMITLV_GET_STRUCT_TLVLEN(wmi_channel));
6715 chan_info->mhz =
6716 cds_chan_to_freq(peerStateParams->peerCap.peerChan[i].
6717 chanId);
6718 chan_info->band_center_freq1 = chan_info->mhz;
6719 chan_info->band_center_freq2 = 0;
6720
6721 WMA_LOGD("%s: chan[%d] = %u", __func__, i, chan_info->mhz);
6722
6723 if (peerStateParams->peerCap.peerChan[i].dfsSet) {
6724 WMI_SET_CHANNEL_FLAG(chan_info, WMI_CHAN_FLAG_PASSIVE);
6725 WMA_LOGI("chan[%d] DFS[%d]\n",
6726 peerStateParams->peerCap.peerChan[i].chanId,
6727 peerStateParams->peerCap.peerChan[i].dfsSet);
6728 }
6729
6730 if (chan_info->mhz < WMA_2_4_GHZ_MAX_FREQ) {
6731 WMI_SET_CHANNEL_MODE(chan_info, MODE_11G);
6732 } else {
6733 WMI_SET_CHANNEL_MODE(chan_info, MODE_11A);
6734 }
6735
6736 WMI_SET_CHANNEL_MAX_TX_POWER(chan_info,
6737 peerStateParams->peerCap.
6738 peerChan[i].pwr);
6739
6740 WMI_SET_CHANNEL_REG_POWER(chan_info,
6741 peerStateParams->peerCap.peerChan[i].
6742 pwr);
6743 WMA_LOGD("Channel TX power[%d] = %u: %d", i, chan_info->mhz,
6744 peerStateParams->peerCap.peerChan[i].pwr);
6745
6746 chan_info++;
6747 }
6748
6749 if (wmi_unified_cmd_send(wma_handle->wmi_handle, wmi_buf, len,
6750 WMI_TDLS_PEER_UPDATE_CMDID)) {
6751 WMA_LOGE("%s: failed to send tdls peer update state command",
6752 __func__);
6753 cdf_nbuf_free(wmi_buf);
6754 ret = -EIO;
6755 goto end_tdls_peer_state;
6756 }
6757
6758 /* in case of teardown, remove peer from fw */
6759 if (WMA_TDLS_PEER_STATE_TEARDOWN == peerStateParams->peerState) {
6760 pdev = cds_get_context(CDF_MODULE_ID_TXRX);
6761 if (!pdev) {
6762 WMA_LOGE("%s: Failed to find pdev", __func__);
6763 ret = -EIO;
6764 goto end_tdls_peer_state;
6765 }
6766
6767 peer = ol_txrx_find_peer_by_addr(pdev,
6768 peerStateParams->peerMacAddr,
6769 &peer_id);
6770 if (!peer) {
6771 WMA_LOGE("%s: Failed to get peer handle using peer mac %pM",
6772 __func__, peerStateParams->peerMacAddr);
6773 ret = -EIO;
6774 goto end_tdls_peer_state;
6775 }
6776
6777 WMA_LOGD("%s: calling wma_remove_peer for peer " MAC_ADDRESS_STR
6778 " vdevId: %d", __func__,
6779 MAC_ADDR_ARRAY(peer->mac_addr.raw),
6780 peerStateParams->vdevId);
6781 wma_remove_peer(wma_handle, peer->mac_addr.raw,
6782 peerStateParams->vdevId, peer, false);
6783 }
6784
6785end_tdls_peer_state:
6786 if (peerStateParams)
6787 cdf_mem_free(peerStateParams);
6788 return ret;
6789}
6790#endif /* FEATURE_WLAN_TDLS */
6791
6792
6793/**
6794 * wma_dfs_attach() - Attach DFS methods to the umac state.
6795 * @dfs_ic: ieee80211com ptr
6796 *
6797 * Return: Return ieee80211com ptr with updated info
6798 */
6799struct ieee80211com *wma_dfs_attach(struct ieee80211com *dfs_ic)
6800{
6801 /*Allocate memory for dfs_ic before passing it up to dfs_attach() */
6802 dfs_ic = (struct ieee80211com *)
6803 os_malloc(NULL, sizeof(struct ieee80211com), GFP_ATOMIC);
6804 if (dfs_ic == NULL) {
6805 WMA_LOGE("%s:Allocation of dfs_ic failed %zu",
6806 __func__, sizeof(struct ieee80211com));
6807 return NULL;
6808 }
6809 OS_MEMZERO(dfs_ic, sizeof(struct ieee80211com));
6810 /* DFS pattern matching hooks */
6811 dfs_ic->ic_dfs_attach = ol_if_dfs_attach;
6812 dfs_ic->ic_dfs_disable = ol_if_dfs_disable;
6813 dfs_ic->ic_find_channel = ieee80211_find_channel;
6814 dfs_ic->ic_dfs_enable = ol_if_dfs_enable;
6815 dfs_ic->ic_ieee2mhz = ieee80211_ieee2mhz;
6816
6817 /* Hardware facing hooks */
6818 dfs_ic->ic_get_ext_busy = ol_if_dfs_get_ext_busy;
6819 dfs_ic->ic_get_mib_cycle_counts_pct =
6820 ol_if_dfs_get_mib_cycle_counts_pct;
6821 dfs_ic->ic_get_TSF64 = ol_if_get_tsf64;
6822
6823 /* NOL related hooks */
6824 dfs_ic->ic_dfs_usenol = ol_if_dfs_usenol;
6825 /*
6826 * Hooks from wma/dfs/ back
6827 * into the PE/SME
6828 * and shared DFS code
6829 */
6830 dfs_ic->ic_dfs_notify_radar = ieee80211_mark_dfs;
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05306831 cdf_spinlock_init(&dfs_ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006832 /* Initializes DFS Data Structures and queues */
6833 dfs_attach(dfs_ic);
6834
6835 return dfs_ic;
6836}
6837
6838/**
6839 * wma_dfs_detach() - Detach DFS methods
6840 * @dfs_ic: ieee80211com ptr
6841 *
6842 * Return: none
6843 */
6844void wma_dfs_detach(struct ieee80211com *dfs_ic)
6845{
6846 dfs_detach(dfs_ic);
6847
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05306848 cdf_spinlock_destroy(&dfs_ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006849 if (NULL != dfs_ic->ic_curchan) {
6850 OS_FREE(dfs_ic->ic_curchan);
6851 dfs_ic->ic_curchan = NULL;
6852 }
6853
6854 OS_FREE(dfs_ic);
6855}
6856
6857/**
6858 * wma_dfs_configure() - configure dfs
6859 * @ic: ieee80211com ptr
6860 *
6861 * Configures Radar Filters during
6862 * vdev start/channel change/regulatory domain
6863 * change.This Configuration enables to program
6864 * the DFS pattern matching module.
6865 *
6866 * Return: none
6867 */
6868void wma_dfs_configure(struct ieee80211com *ic)
6869{
6870 struct ath_dfs_radar_tab_info rinfo;
6871 int dfsdomain;
6872 int radar_enabled_status = 0;
6873 if (ic == NULL) {
6874 WMA_LOGE("%s: DFS ic is Invalid", __func__);
6875 return;
6876 }
6877
6878 dfsdomain = ic->current_dfs_regdomain;
6879
6880 /* Fetch current radar patterns from the lmac */
6881 OS_MEMZERO(&rinfo, sizeof(rinfo));
6882
6883 /*
6884 * Look up the current DFS
6885 * regulatory domain and decide
6886 * which radar pulses to use.
6887 */
6888 switch (dfsdomain) {
6889 case DFS_FCC_DOMAIN:
6890 WMA_LOGI("%s: DFS-FCC domain", __func__);
6891 rinfo.dfsdomain = DFS_FCC_DOMAIN;
6892 rinfo.dfs_radars = dfs_fcc_radars;
6893 rinfo.numradars = CDF_ARRAY_SIZE(dfs_fcc_radars);
6894 rinfo.b5pulses = dfs_fcc_bin5pulses;
6895 rinfo.numb5radars = CDF_ARRAY_SIZE(dfs_fcc_bin5pulses);
6896 break;
6897 case DFS_ETSI_DOMAIN:
6898 WMA_LOGI("%s: DFS-ETSI domain", __func__);
6899 rinfo.dfsdomain = DFS_ETSI_DOMAIN;
6900 rinfo.dfs_radars = dfs_etsi_radars;
6901 rinfo.numradars = CDF_ARRAY_SIZE(dfs_etsi_radars);
6902 rinfo.b5pulses = NULL;
6903 rinfo.numb5radars = 0;
6904 break;
6905 case DFS_MKK4_DOMAIN:
6906 WMA_LOGI("%s: DFS-MKK4 domain", __func__);
6907 rinfo.dfsdomain = DFS_MKK4_DOMAIN;
6908 rinfo.dfs_radars = dfs_mkk4_radars;
6909 rinfo.numradars = CDF_ARRAY_SIZE(dfs_mkk4_radars);
6910 rinfo.b5pulses = dfs_jpn_bin5pulses;
6911 rinfo.numb5radars = CDF_ARRAY_SIZE(dfs_jpn_bin5pulses);
6912 break;
6913 default:
6914 WMA_LOGI("%s: DFS-UNINT domain", __func__);
6915 rinfo.dfsdomain = DFS_UNINIT_DOMAIN;
6916 rinfo.dfs_radars = NULL;
6917 rinfo.numradars = 0;
6918 rinfo.b5pulses = NULL;
6919 rinfo.numb5radars = 0;
6920 break;
6921 }
6922
6923 rinfo.dfs_pri_multiplier = ic->dfs_pri_multiplier;
6924
6925 /*
6926 * Set the regulatory domain,
6927 * radar pulse table and enable
6928 * radar events if required.
6929 * dfs_radar_enable() returns
6930 * 0 on success and non-zero
6931 * failure.
6932 */
6933 radar_enabled_status = dfs_radar_enable(ic, &rinfo);
6934 if (radar_enabled_status != DFS_STATUS_SUCCESS) {
6935 WMA_LOGE("%s[%d]: DFS- Radar Detection Enabling Failed",
6936 __func__, __LINE__);
6937 }
6938}
6939
6940/**
6941 * wma_dfs_configure_channel() - configure DFS channel
6942 * @dfs_ic: ieee80211com ptr
6943 * @chan: wmi channel
6944 * @chanmode: channel mode
6945 * @ req: vdev start request
6946 *
6947 * Set the Channel parameters in to DFS module
6948 * Also,configure the DFS radar filters for
6949 * matching the DFS phyerrors.
6950 *
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306951 * Return: dfs_ieee80211_channel / NULL for error
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006952 */
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306953struct dfs_ieee80211_channel *wma_dfs_configure_channel(
6954 struct ieee80211com *dfs_ic,
6955 wmi_channel *chan,
6956 WLAN_PHY_MODE chanmode,
6957 struct wma_vdev_start_req
6958 *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006959{
6960 if (dfs_ic == NULL) {
6961 WMA_LOGE("%s: DFS ic is Invalid", __func__);
6962 return NULL;
6963 }
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05306964
6965 if (!dfs_ic->ic_curchan) {
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306966 dfs_ic->ic_curchan = (struct dfs_ieee80211_channel *)os_malloc(
6967 NULL,
6968 sizeof(struct dfs_ieee80211_channel),
6969 GFP_ATOMIC);
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05306970 if (dfs_ic->ic_curchan == NULL) {
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306971 WMA_LOGE(
6972 "%s: allocation of dfs_ic->ic_curchan failed %zu",
6973 __func__, sizeof(struct dfs_ieee80211_channel));
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05306974 return NULL;
6975 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006976 }
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05306977
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05306978 OS_MEMZERO(dfs_ic->ic_curchan, sizeof(struct dfs_ieee80211_channel));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006979
6980 dfs_ic->ic_curchan->ic_ieee = req->chan;
6981 dfs_ic->ic_curchan->ic_freq = chan->mhz;
6982 dfs_ic->ic_curchan->ic_vhtop_ch_freq_seg1 = chan->band_center_freq1;
6983 dfs_ic->ic_curchan->ic_vhtop_ch_freq_seg2 = chan->band_center_freq2;
6984 dfs_ic->ic_curchan->ic_pri_freq_center_freq_mhz_separation =
6985 dfs_ic->ic_curchan->ic_freq -
6986 dfs_ic->ic_curchan->ic_vhtop_ch_freq_seg1;
6987
6988 if ((dfs_ic->ic_curchan->ic_ieee >= WMA_11A_CHANNEL_BEGIN) &&
6989 (dfs_ic->ic_curchan->ic_ieee <= WMA_11A_CHANNEL_END)) {
6990 dfs_ic->ic_curchan->ic_flags |= IEEE80211_CHAN_5GHZ;
6991 }
6992 if (CH_WIDTH_80MHZ == req->chan_width) {
6993 dfs_ic->ic_curchan->ic_flags |= IEEE80211_CHAN_VHT80;
6994 }
6995 if (CH_WIDTH_40MHZ == req->chan_width) {
6996 if (req->chan < req->ch_center_freq_seg0)
6997 dfs_ic->ic_curchan->ic_flags |= (req->vht_capable ?
6998 IEEE80211_CHAN_VHT40PLUS :
6999 IEEE80211_CHAN_HT40PLUS);
7000 else
7001 dfs_ic->ic_curchan->ic_flags |= (req->vht_capable ?
7002 IEEE80211_CHAN_VHT40MINUS :
7003 IEEE80211_CHAN_HT40MINUS);
7004 } else if (CH_WIDTH_20MHZ == req->chan_width) {
7005 dfs_ic->ic_curchan->ic_flags |=
7006 (req->vht_capable ? IEEE80211_CHAN_VHT20 :
7007 IEEE80211_CHAN_HT20);
7008 }
7009 dfs_ic->ic_curchan->ic_flagext |= IEEE80211_CHAN_DFS;
7010
7011 if (req->oper_mode == BSS_OPERATIONAL_MODE_AP) {
7012 dfs_ic->ic_opmode = IEEE80211_M_HOSTAP;
7013 dfs_ic->vdev_id = req->vdev_id;
7014 }
7015
7016 dfs_ic->dfs_pri_multiplier = req->dfs_pri_multiplier;
7017
7018 /*
7019 * Configuring the DFS with current channel and the radar filters
7020 */
7021 wma_dfs_configure(dfs_ic);
7022 WMA_LOGI("%s: DFS- CHANNEL CONFIGURED", __func__);
7023 return dfs_ic->ic_curchan;
7024}
7025
7026
7027/**
7028 * wma_set_dfs_region() - set DFS region
7029 * @wma: wma handle
7030 *
7031 * Configure the DFS region for DFS radar filter initialization
7032 *
7033 * Return: none
7034 */
7035void wma_set_dfs_region(tp_wma_handle wma, uint8_t dfs_region)
7036{
7037 /* dfs information is passed */
7038 if (dfs_region > DFS_MKK4_DOMAIN || dfs_region == DFS_UNINIT_DOMAIN)
7039 /* assign DFS_FCC_DOMAIN as default domain*/
7040 wma->dfs_ic->current_dfs_regdomain = DFS_FCC_DOMAIN;
7041 else
7042 wma->dfs_ic->current_dfs_regdomain = dfs_region;
7043
7044 WMA_LOGI("%s: DFS Region Domain: %d", __func__,
7045 wma->dfs_ic->current_dfs_regdomain);
7046}
7047
7048/**
7049 * wma_get_channels() - prepare dfs radar channel list
7050 * @ichan: channel
7051 * @chan_list: return channel list
7052 *
7053 * Return: return number of channels
7054 */
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05307055int wma_get_channels(struct dfs_ieee80211_channel *ichan,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007056 struct wma_dfs_radar_channel_list *chan_list)
7057{
7058 uint8_t center_chan = cds_freq_to_chan(ichan->ic_vhtop_ch_freq_seg1);
7059
7060 chan_list->nchannels = 0;
7061
7062 if (IEEE80211_IS_CHAN_11AC_VHT80(ichan)) {
7063 chan_list->nchannels = 4;
7064 chan_list->channels[0] = center_chan - 6;
7065 chan_list->channels[1] = center_chan - 2;
7066 chan_list->channels[2] = center_chan + 2;
7067 chan_list->channels[3] = center_chan + 6;
7068 } else if (IEEE80211_IS_CHAN_11N_HT40(ichan) ||
7069 IEEE80211_IS_CHAN_11AC_VHT40(ichan)) {
7070 chan_list->nchannels = 2;
7071 chan_list->channels[0] = center_chan - 2;
7072 chan_list->channels[1] = center_chan + 2;
7073 } else {
7074 chan_list->nchannels = 1;
7075 chan_list->channels[0] = center_chan;
7076 }
7077
7078 return chan_list->nchannels;
7079}
7080
7081
7082/**
7083 * wma_dfs_indicate_radar() - Indicate Radar to SAP/HDD
7084 * @ic: ieee80211com ptr
7085 * @ichan: ieee 80211 channel
7086 *
7087 * Return: 0 for success or error code
7088 */
7089int wma_dfs_indicate_radar(struct ieee80211com *ic,
Chandrasekaran, Manishekar22a7e1e2015-11-05 10:38:49 +05307090 struct dfs_ieee80211_channel *ichan)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007091{
7092 tp_wma_handle wma;
7093 void *hdd_ctx;
7094 struct wma_dfs_radar_indication *radar_event;
7095 struct wma_dfs_radar_ind wma_radar_event;
7096 tpAniSirGlobal pmac = NULL;
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05307097 bool indication_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007098
7099 wma = cds_get_context(CDF_MODULE_ID_WMA);
7100 if (wma == NULL) {
7101 WMA_LOGE("%s: DFS- Invalid wma", __func__);
7102 return -ENOENT;
7103 }
7104
7105 hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD);
7106 pmac = (tpAniSirGlobal)
7107 cds_get_context(CDF_MODULE_ID_PE);
7108
7109 if (!pmac) {
7110 WMA_LOGE("%s: Invalid MAC handle", __func__);
7111 return -ENOENT;
7112 }
7113
7114 if (wma->dfs_ic != ic) {
7115 WMA_LOGE("%s:DFS- Invalid WMA handle", __func__);
7116 return -ENOENT;
7117 }
7118 radar_event = (struct wma_dfs_radar_indication *)
7119 cdf_mem_malloc(sizeof(struct wma_dfs_radar_indication));
7120 if (radar_event == NULL) {
7121 WMA_LOGE("%s:DFS- Invalid radar_event", __func__);
7122 return -ENOMEM;
7123 }
7124
7125 /*
7126 * Do not post multiple Radar events on the same channel.
7127 * But, when DFS test mode is enabled, allow multiple dfs
7128 * radar events to be posted on the same channel.
7129 */
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05307130 cdf_spin_lock_bh(&ic->chan_lock);
Edhar, Mahesh Kumar35d9b2e2015-10-26 17:06:23 +05307131 if (!pmac->sap.SapDfsInfo.disable_dfs_ch_switch)
7132 wma->dfs_ic->disable_phy_err_processing = true;
7133
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007134 if ((ichan->ic_ieee != (wma->dfs_ic->last_radar_found_chan)) ||
7135 (pmac->sap.SapDfsInfo.disable_dfs_ch_switch == true)) {
7136 wma->dfs_ic->last_radar_found_chan = ichan->ic_ieee;
7137 /* Indicate the radar event to HDD to stop the netif Tx queues */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007138 wma_radar_event.chan_freq = ichan->ic_freq;
7139 wma_radar_event.dfs_radar_status = WMA_DFS_RADAR_FOUND;
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05307140 indication_status =
7141 wma->dfs_radar_indication_cb(hdd_ctx, &wma_radar_event);
7142 if (indication_status == false) {
7143 WMA_LOGE("%s:Application triggered channel switch in progress!.. drop radar event indiaction to SAP",
7144 __func__);
7145 cdf_mem_free(radar_event);
7146 cdf_spin_unlock_bh(&ic->chan_lock);
7147 return 0;
7148 }
7149
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007150 WMA_LOGE("%s:DFS- RADAR INDICATED TO HDD", __func__);
7151
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05307152 wma_radar_event.ieee_chan_number = ichan->ic_ieee;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007153 /*
7154 * Indicate to the radar event to SAP to
7155 * select a new channel and set CSA IE
7156 */
7157 radar_event->vdev_id = ic->vdev_id;
7158 wma_get_channels(ichan, &radar_event->chan_list);
7159 radar_event->dfs_radar_status = WMA_DFS_RADAR_FOUND;
7160 radar_event->use_nol = ic->ic_dfs_usenol(ic);
7161 wma_send_msg(wma, WMA_DFS_RADAR_IND, (void *)radar_event, 0);
7162 WMA_LOGE("%s:DFS- WMA_DFS_RADAR_IND Message Posted", __func__);
7163 }
Edhar, Mahesh Kumarb0319c42015-10-26 16:53:30 +05307164 cdf_spin_unlock_bh(&ic->chan_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007165
7166 return 0;
7167}
7168
7169#ifdef WLAN_FEATURE_MEMDUMP
7170/*
7171 * wma_process_fw_mem_dump_req() - Function to request fw memory dump from
7172 * firmware
7173 * @wma: Pointer to WMA handle
7174 * @mem_dump_req: Pointer for mem_dump_req
7175 *
7176 * This function sends memory dump request to firmware
7177 *
7178 * Return: CDF_STATUS_SUCCESS for success otherwise failure
7179 *
7180 */
7181CDF_STATUS wma_process_fw_mem_dump_req(tp_wma_handle wma,
7182 struct fw_dump_req *mem_dump_req)
7183{
7184 wmi_get_fw_mem_dump_fixed_param *cmd;
7185 wmi_fw_mem_dump *dump_params;
7186 struct fw_dump_seg_req *seg_req;
7187 int32_t len;
7188 wmi_buf_t buf;
7189 u_int8_t *buf_ptr;
7190 int ret, loop;
7191
7192 if (!mem_dump_req || !wma) {
7193 WMA_LOGE(FL("input pointer is NULL"));
7194 return CDF_STATUS_E_FAILURE;
7195 }
7196
7197 /*
7198 * len = sizeof(fixed param) that includes tlv header +
7199 * tlv header for array of struc +
7200 * sizeof (each struct)
7201 */
7202 len = sizeof(*cmd) + WMI_TLV_HDR_SIZE;
7203 len += mem_dump_req->num_seg * sizeof(wmi_fw_mem_dump);
7204 buf = wmi_buf_alloc(wma->wmi_handle, len);
7205
7206 if (!buf) {
7207 WMA_LOGE(FL("Failed allocate wmi buffer"));
7208 return CDF_STATUS_E_NOMEM;
7209 }
7210
7211 buf_ptr = (u_int8_t *) wmi_buf_data(buf);
7212 cdf_mem_zero(buf_ptr, len);
7213 cmd = (wmi_get_fw_mem_dump_fixed_param *) buf_ptr;
7214
7215 WMITLV_SET_HDR(&cmd->tlv_header,
7216 WMITLV_TAG_STRUC_wmi_get_fw_mem_dump_fixed_param,
7217 WMITLV_GET_STRUCT_TLVLEN(wmi_get_fw_mem_dump_fixed_param));
7218
7219 cmd->request_id = mem_dump_req->request_id;
7220 cmd->num_fw_mem_dump_segs = mem_dump_req->num_seg;
7221
7222 /* TLV indicating array of structures to follow */
7223 buf_ptr += sizeof(wmi_get_fw_mem_dump_fixed_param);
7224 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
7225 sizeof(wmi_fw_mem_dump) *
7226 cmd->num_fw_mem_dump_segs);
7227
7228 buf_ptr += WMI_TLV_HDR_SIZE;
7229 dump_params = (wmi_fw_mem_dump *) buf_ptr;
7230
7231 WMA_LOGI(FL("request_id:%d num_seg:%d"),
7232 mem_dump_req->request_id, mem_dump_req->num_seg);
7233 for (loop = 0; loop < cmd->num_fw_mem_dump_segs; loop++) {
7234 seg_req = (struct fw_dump_seg_req *)
7235 ((uint8_t *)(mem_dump_req->segment) +
7236 loop * sizeof(*seg_req));
7237 WMITLV_SET_HDR(&dump_params->tlv_header,
7238 WMITLV_TAG_STRUC_wmi_fw_mem_dump_params,
7239 WMITLV_GET_STRUCT_TLVLEN(wmi_fw_mem_dump));
7240 dump_params->seg_id = seg_req->seg_id;
7241 dump_params->seg_start_addr_lo = seg_req->seg_start_addr_lo;
7242 dump_params->seg_start_addr_hi = seg_req->seg_start_addr_hi;
7243 dump_params->seg_length = seg_req->seg_length;
7244 dump_params->dest_addr_lo = seg_req->dst_addr_lo;
7245 dump_params->dest_addr_hi = seg_req->dst_addr_hi;
7246 WMA_LOGI(FL("seg_number:%d"), loop);
7247 WMA_LOGI(FL("seg_id:%d start_addr_lo:0x%x start_addr_hi:0x%x"),
7248 dump_params->seg_id, dump_params->seg_start_addr_lo,
7249 dump_params->seg_start_addr_hi);
7250 WMA_LOGI(FL("seg_length:%d dst_addr_lo:0x%x dst_addr_hi:0x%x"),
7251 dump_params->seg_length, dump_params->dest_addr_lo,
7252 dump_params->dest_addr_hi);
7253 dump_params++;
7254 }
7255
7256 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
7257 WMI_GET_FW_MEM_DUMP_CMDID);
7258 if (ret) {
7259 WMA_LOGE(FL("Failed to send get firmware mem dump request"));
7260 wmi_buf_free(buf);
7261 return CDF_STATUS_E_FAILURE;
7262 }
7263
7264 WMA_LOGI(FL("Get firmware mem dump request sent successfully"));
7265 return CDF_STATUS_SUCCESS;
7266}
7267
7268/**
7269 * wma_fw_mem_dump_rsp() - send fw mem dump response to SME
7270 *
7271 * @req_id - request id.
7272 * @status - copy status from the firmware.
7273 *
7274 * This function is called by the memory dump response handler to
7275 * indicate SME that firmware dump copy is complete
7276 *
7277 * Return: CDF_STATUS
7278 */
7279static CDF_STATUS wma_fw_mem_dump_rsp(uint32_t req_id, uint32_t status)
7280{
7281 struct fw_dump_rsp *dump_rsp;
7282 cds_msg_t sme_msg = {0};
7283 CDF_STATUS cdf_status = CDF_STATUS_SUCCESS;
7284
7285 dump_rsp = cdf_mem_malloc(sizeof(*dump_rsp));
7286
7287 if (!dump_rsp) {
7288 WMA_LOGE(FL("Memory allocation failed."));
7289 cdf_status = CDF_STATUS_E_NOMEM;
7290 return cdf_status;
7291 }
7292
7293 WMA_LOGI(FL("FW memory dump copy complete status: %d for request: %d"),
7294 status, req_id);
7295
7296 dump_rsp->request_id = req_id;
7297 dump_rsp->dump_complete = status;
7298
7299 sme_msg.type = eWNI_SME_FW_DUMP_IND;
7300 sme_msg.bodyptr = dump_rsp;
7301 sme_msg.bodyval = 0;
7302
7303 cdf_status = cds_mq_post_message(CDF_MODULE_ID_SME, &sme_msg);
7304 if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
7305 WMA_LOGE(FL("Fail to post fw mem dump ind msg"));
7306 cdf_mem_free(dump_rsp);
7307 }
7308
7309 return cdf_status;
7310}
7311
7312/**
7313 * wma_fw_mem_dump_event_handler() - handles fw memory dump event
7314 *
7315 * @handle: pointer to wma handle.
7316 * @cmd_param_info: pointer to TLV info received in the event.
7317 * @len: length of data in @cmd_param_info
7318 *
7319 * This function is a handler for firmware memory dump event.
7320 *
7321 * Return: integer (0 for success and error code otherwise)
7322 */
7323int wma_fw_mem_dump_event_handler(void *handle, u_int8_t *cmd_param_info,
7324 u_int32_t len)
7325{
7326 WMI_UPDATE_FW_MEM_DUMP_EVENTID_param_tlvs *param_buf;
7327 wmi_update_fw_mem_dump_fixed_param *event;
7328 CDF_STATUS status;
7329
7330 param_buf =
7331 (WMI_UPDATE_FW_MEM_DUMP_EVENTID_param_tlvs *) cmd_param_info;
7332 if (!param_buf) {
7333 WMA_LOGA("%s: Invalid stats event", __func__);
7334 return -EINVAL;
7335 }
7336
7337 event = param_buf->fixed_param;
7338
7339 status = wma_fw_mem_dump_rsp(event->request_id,
7340 event->fw_mem_dump_complete);
7341 if (CDF_STATUS_SUCCESS != status) {
7342 WMA_LOGE("Error posting FW MEM DUMP RSP.");
7343 return -EINVAL;
7344 }
7345
7346 WMA_LOGI("FW MEM DUMP RSP posted successfully");
7347 return 0;
7348}
7349#endif /* WLAN_FEATURE_MEMDUMP */
7350
7351/*
7352 * wma_process_set_ie_info() - Function to send IE info to firmware
7353 * @wma: Pointer to WMA handle
7354 * @ie_data: Pointer for ie data
7355 *
7356 * This function sends IE information to firmware
7357 *
7358 * Return: CDF_STATUS_SUCCESS for success otherwise failure
7359 *
7360 */
7361CDF_STATUS wma_process_set_ie_info(tp_wma_handle wma,
7362 struct vdev_ie_info *ie_info)
7363{
7364 wmi_vdev_set_ie_cmd_fixed_param *cmd;
7365 wmi_buf_t buf;
7366 uint8_t *buf_ptr;
7367 uint32_t len, ie_len_aligned;
7368 int ret;
7369
7370 if (!ie_info || !wma) {
7371 WMA_LOGE(FL("input pointer is NULL"));
7372 return CDF_STATUS_E_FAILURE;
7373 }
7374
7375 /* Validate the input */
7376 if (ie_info->length <= 0) {
7377 WMA_LOGE(FL("Invalid IE length"));
7378 return CDF_STATUS_E_INVAL;
7379 }
7380
7381 ie_len_aligned = roundup(ie_info->length, sizeof(uint32_t));
7382 /* Allocate memory for the WMI command */
7383 len = sizeof(*cmd) + WMI_TLV_HDR_SIZE + ie_len_aligned;
7384
7385 buf = wmi_buf_alloc(wma->wmi_handle, len);
7386 if (!buf) {
7387 WMA_LOGE(FL("wmi_buf_alloc failed"));
7388 return CDF_STATUS_E_NOMEM;
7389 }
7390
7391 buf_ptr = wmi_buf_data(buf);
7392 cdf_mem_zero(buf_ptr, len);
7393
7394 /* Populate the WMI command */
7395 cmd = (wmi_vdev_set_ie_cmd_fixed_param *)buf_ptr;
7396
7397 WMITLV_SET_HDR(&cmd->tlv_header,
7398 WMITLV_TAG_STRUC_wmi_vdev_set_ie_cmd_fixed_param,
7399 WMITLV_GET_STRUCT_TLVLEN(
7400 wmi_vdev_set_ie_cmd_fixed_param));
7401 cmd->vdev_id = ie_info->vdev_id;
7402 cmd->ie_id = ie_info->ie_id;
7403 cmd->ie_len = ie_info->length;
7404
7405 WMA_LOGD(FL("IE:%d of size:%d sent for vdev:%d"), ie_info->ie_id,
7406 ie_info->length, ie_info->vdev_id);
7407
7408 buf_ptr += sizeof(*cmd);
7409 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, ie_len_aligned);
7410 buf_ptr += WMI_TLV_HDR_SIZE;
7411
7412 cdf_mem_copy(buf_ptr, ie_info->data, cmd->ie_len);
7413
7414 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
7415 WMI_VDEV_SET_IE_CMDID);
7416 if (ret != EOK) {
7417 WMA_LOGE(FL("Failed to send set IE command ret = %d"), ret);
7418 wmi_buf_free(buf);
7419 }
7420
7421 return ret;
7422}
7423