blob: 134039cf721cdab6b10f792d2b594f6cba7c87c6 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Houston Hoffman79b4af22015-10-06 12:01:08 -07002 * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
28/**
29 * DOC: wma_mgmt.c
30 *
31 * This file contains STA/SAP/IBSS and protocol related functions.
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"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080046#include "wlan_tgt_def_config.h"
47
Nirav Shahcbc6d722016-03-01 16:24:53 +053048#include "qdf_nbuf.h"
Anurag Chouhan6d760662016-02-20 16:05:43 +053049#include "qdf_types.h"
Anurag Chouhan600c3a02016-03-01 10:33:54 +053050#include "qdf_mem.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080051#include "ol_txrx_peer_find.h"
52
53#include "wma_types.h"
54#include "lim_api.h"
55#include "lim_session_utils.h"
56
57#include "cds_utils.h"
58
59#if !defined(REMOVE_PKT_LOG)
60#include "pktlog_ac.h"
61#endif /* REMOVE_PKT_LOG */
62
63#include "dbglog_host.h"
64#include "csr_api.h"
65#include "ol_fw.h"
66#include "dfs.h"
67#include "wma_internal.h"
Chandrasekaran, Manishekar0d814c72015-11-05 10:42:48 +053068#include "cds_concurrency.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080069
70/**
71 * wma_send_bcn_buf_ll() - prepare and send beacon buffer to fw for LL
72 * @wma: wma handle
73 * @pdev: txrx pdev
74 * @vdev_id: vdev id
75 * @param_buf: SWBA parameters
76 *
77 * Return: none
78 */
79static void wma_send_bcn_buf_ll(tp_wma_handle wma,
80 ol_txrx_pdev_handle pdev,
81 uint8_t vdev_id,
82 WMI_HOST_SWBA_EVENTID_param_tlvs *param_buf)
83{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080084 struct ieee80211_frame *wh;
85 struct beacon_info *bcn;
86 wmi_tim_info *tim_info = param_buf->tim_info;
87 uint8_t *bcn_payload;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053088 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080089 struct beacon_tim_ie *tim_ie;
90 wmi_p2p_noa_info *p2p_noa_info = param_buf->p2p_noa_info;
91 struct p2p_sub_element_noa noa_ie;
Himanshu Agarwal009f1572016-03-09 17:26:02 +053092 struct wmi_bcn_send_from_host params;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080093 uint8_t i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080094
95 bcn = wma->interfaces[vdev_id].beacon;
96 if (!bcn->buf) {
97 WMA_LOGE("%s: Invalid beacon buffer", __func__);
98 return;
99 }
100
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530101 qdf_spin_lock_bh(&bcn->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800102
Nirav Shahcbc6d722016-03-01 16:24:53 +0530103 bcn_payload = qdf_nbuf_data(bcn->buf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800104
105 tim_ie = (struct beacon_tim_ie *)(&bcn_payload[bcn->tim_ie_offset]);
106
107 if (tim_info->tim_changed) {
108 if (tim_info->tim_num_ps_pending)
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530109 qdf_mem_copy(&tim_ie->tim_bitmap, tim_info->tim_bitmap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800110 WMA_TIM_SUPPORTED_PVB_LENGTH);
111 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530112 qdf_mem_zero(&tim_ie->tim_bitmap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800113 WMA_TIM_SUPPORTED_PVB_LENGTH);
114 /*
115 * Currently we support fixed number of
116 * peers as limited by HAL_NUM_STA.
117 * tim offset is always 0
118 */
119 tim_ie->tim_bitctl = 0;
120 }
121
122 /* Update DTIM Count */
123 if (tim_ie->dtim_count == 0)
124 tim_ie->dtim_count = tim_ie->dtim_period - 1;
125 else
126 tim_ie->dtim_count--;
127
128 /*
129 * DTIM count needs to be backedup so that
130 * when umac updates the beacon template
131 * current dtim count can be updated properly
132 */
133 bcn->dtim_count = tim_ie->dtim_count;
134
135 /* update state for buffered multicast frames on DTIM */
136 if (tim_info->tim_mcast && (tim_ie->dtim_count == 0 ||
137 tim_ie->dtim_period == 1))
138 tim_ie->tim_bitctl |= 1;
139 else
140 tim_ie->tim_bitctl &= ~1;
141
142 /* To avoid sw generated frame sequence the same as H/W generated frame,
143 * the value lower than min_sw_seq is reserved for HW generated frame */
144 if ((bcn->seq_no & IEEE80211_SEQ_MASK) < MIN_SW_SEQ)
145 bcn->seq_no = MIN_SW_SEQ;
146
147 wh = (struct ieee80211_frame *)bcn_payload;
148 *(uint16_t *) &wh->i_seq[0] = htole16(bcn->seq_no
149 << IEEE80211_SEQ_SEQ_SHIFT);
150 bcn->seq_no++;
151
152 if (WMI_UNIFIED_NOA_ATTR_IS_MODIFIED(p2p_noa_info)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530153 qdf_mem_zero(&noa_ie, sizeof(noa_ie));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800154
155 noa_ie.index =
156 (uint8_t) WMI_UNIFIED_NOA_ATTR_INDEX_GET(p2p_noa_info);
157 noa_ie.oppPS =
158 (uint8_t) WMI_UNIFIED_NOA_ATTR_OPP_PS_GET(p2p_noa_info);
159 noa_ie.ctwindow =
160 (uint8_t) WMI_UNIFIED_NOA_ATTR_CTWIN_GET(p2p_noa_info);
161 noa_ie.num_descriptors =
162 (uint8_t) WMI_UNIFIED_NOA_ATTR_NUM_DESC_GET(p2p_noa_info);
163 WMA_LOGI("%s: index %u, oppPs %u, ctwindow %u, "
164 "num_descriptors = %u", __func__, noa_ie.index,
165 noa_ie.oppPS, noa_ie.ctwindow, noa_ie.num_descriptors);
166 for (i = 0; i < noa_ie.num_descriptors; i++) {
167 noa_ie.noa_descriptors[i].type_count =
168 (uint8_t) p2p_noa_info->noa_descriptors[i].
169 type_count;
170 noa_ie.noa_descriptors[i].duration =
171 p2p_noa_info->noa_descriptors[i].duration;
172 noa_ie.noa_descriptors[i].interval =
173 p2p_noa_info->noa_descriptors[i].interval;
174 noa_ie.noa_descriptors[i].start_time =
175 p2p_noa_info->noa_descriptors[i].start_time;
176 WMA_LOGI("%s: NoA descriptor[%d] type_count %u, "
177 "duration %u, interval %u, start_time = %u",
178 __func__, i,
179 noa_ie.noa_descriptors[i].type_count,
180 noa_ie.noa_descriptors[i].duration,
181 noa_ie.noa_descriptors[i].interval,
182 noa_ie.noa_descriptors[i].start_time);
183 }
184 wma_update_noa(bcn, &noa_ie);
185
186 /* Send a msg to LIM to update the NoA IE in probe response
187 * frames transmitted by the host */
188 wma_update_probe_resp_noa(wma, &noa_ie);
189 }
190
191 if (bcn->dma_mapped) {
Nirav Shahcbc6d722016-03-01 16:24:53 +0530192 qdf_nbuf_unmap_single(pdev->osdev, bcn->buf, QDF_DMA_TO_DEVICE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800193 bcn->dma_mapped = 0;
194 }
Nirav Shahcbc6d722016-03-01 16:24:53 +0530195 ret = qdf_nbuf_map_single(pdev->osdev, bcn->buf, QDF_DMA_TO_DEVICE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530196 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800197 WMA_LOGE("%s: failed map beacon buf to DMA region", __func__);
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530198 qdf_spin_unlock_bh(&bcn->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800199 return;
200 }
201
202 bcn->dma_mapped = 1;
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530203 params.vdev_id = vdev_id;
204 params.data_len = bcn->len;
205 params.frame_ctrl = *((A_UINT16 *) wh->i_fc);
206 params.frag_ptr = qdf_nbuf_get_frag_paddr(bcn->buf, 0);
207 params.dtim_flag = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800208 /* notify Firmware of DTM and mcast/bcast traffic */
209 if (tim_ie->dtim_count == 0) {
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530210 params.dtim_flag |= WMI_BCN_SEND_DTIM_ZERO;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800211 /* deliver mcast/bcast traffic in next DTIM beacon */
212 if (tim_ie->tim_bitctl & 0x01)
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530213 params.dtim_flag |= WMI_BCN_SEND_DTIM_BITCTL_SET;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800214 }
215
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530216 wmi_unified_bcn_buf_ll_cmd(wma->wmi_handle,
217 &params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800218
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530219 qdf_spin_unlock_bh(&bcn->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800220}
221
222/**
223 * wma_beacon_swba_handler() - swba event handler
224 * @handle: wma handle
225 * @event: event data
226 * @len: data length
227 *
228 * SWBA event is alert event to Host requesting host to Queue a beacon
229 * for transmission use only in host beacon mode
230 *
231 * Return: 0 for success or error code
232 */
233int wma_beacon_swba_handler(void *handle, uint8_t *event, uint32_t len)
234{
235 tp_wma_handle wma = (tp_wma_handle) handle;
236 WMI_HOST_SWBA_EVENTID_param_tlvs *param_buf;
237 wmi_host_swba_event_fixed_param *swba_event;
238 uint32_t vdev_map;
239 ol_txrx_pdev_handle pdev;
240 uint8_t vdev_id = 0;
241
242 param_buf = (WMI_HOST_SWBA_EVENTID_param_tlvs *) event;
243 if (!param_buf) {
244 WMA_LOGE("Invalid swba event buffer");
245 return -EINVAL;
246 }
247 swba_event = param_buf->fixed_param;
248 vdev_map = swba_event->vdev_map;
249
Anurag Chouhan6d760662016-02-20 16:05:43 +0530250 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800251 if (!pdev) {
252 WMA_LOGE("%s: pdev is NULL", __func__);
253 return -EINVAL;
254 }
255
256 for (; vdev_map; vdev_id++, vdev_map >>= 1) {
257 if (!(vdev_map & 0x1))
258 continue;
259 if (!ol_cfg_is_high_latency(pdev->ctrl_pdev))
260 wma_send_bcn_buf_ll(wma, pdev, vdev_id, param_buf);
261 break;
262 }
263 return 0;
264}
265
266/**
267 * wma_peer_sta_kickout_event_handler() - kickout event handler
268 * @handle: wma handle
269 * @event: event data
270 * @len: data length
271 *
272 * Kickout event is received from firmware on observing beacon miss
273 * It handles kickout event for different modes and indicate to
274 * upper layers.
275 *
276 * Return: 0 for success or error code
277 */
278int wma_peer_sta_kickout_event_handler(void *handle, u8 *event, u32 len)
279{
280 tp_wma_handle wma = (tp_wma_handle) handle;
281 WMI_PEER_STA_KICKOUT_EVENTID_param_tlvs *param_buf = NULL;
282 wmi_peer_sta_kickout_event_fixed_param *kickout_event = NULL;
283 uint8_t vdev_id, peer_id, macaddr[IEEE80211_ADDR_LEN];
284 ol_txrx_peer_handle peer;
285 ol_txrx_pdev_handle pdev;
286 tpDeleteStaContext del_sta_ctx;
287 tpSirIbssPeerInactivityInd p_inactivity;
288
289 WMA_LOGD("%s: Enter", __func__);
290 param_buf = (WMI_PEER_STA_KICKOUT_EVENTID_param_tlvs *) event;
291 kickout_event = param_buf->fixed_param;
Anurag Chouhan6d760662016-02-20 16:05:43 +0530292 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800293 if (!pdev) {
294 WMA_LOGE("%s: pdev is NULL", __func__);
295 return -EINVAL;
296 }
297 WMI_MAC_ADDR_TO_CHAR_ARRAY(&kickout_event->peer_macaddr, macaddr);
298 peer = ol_txrx_find_peer_by_addr(pdev, macaddr, &peer_id);
299 if (!peer) {
300 WMA_LOGE("PEER [%pM] not found", macaddr);
301 return -EINVAL;
302 }
303
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530304 if (ol_txrx_get_vdevid(peer, &vdev_id) != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800305 WMA_LOGE("Not able to find BSSID for peer [%pM]", macaddr);
306 return -EINVAL;
307 }
308
309 WMA_LOGA("%s: PEER:[%pM], ADDR:[%pN], INTERFACE:%d, peer_id:%d, reason:%d",
310 __func__, macaddr, wma->interfaces[vdev_id].addr, vdev_id,
311 peer_id, kickout_event->reason);
312
313 switch (kickout_event->reason) {
314 case WMI_PEER_STA_KICKOUT_REASON_IBSS_DISCONNECT:
315 p_inactivity = (tpSirIbssPeerInactivityInd)
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530316 qdf_mem_malloc(sizeof(tSirIbssPeerInactivityInd));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800317 if (!p_inactivity) {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530318 WMA_LOGE("QDF MEM Alloc Failed for tSirIbssPeerInactivity");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800319 return -ENOMEM;
320 }
321
322 p_inactivity->staIdx = peer_id;
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530323 qdf_mem_copy(p_inactivity->peer_addr.bytes, macaddr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800324 IEEE80211_ADDR_LEN);
325 wma_send_msg(wma, WMA_IBSS_PEER_INACTIVITY_IND,
326 (void *)p_inactivity, 0);
327 goto exit_handler;
328 break;
329
330#ifdef FEATURE_WLAN_TDLS
331 case WMI_PEER_STA_KICKOUT_REASON_TDLS_DISCONNECT:
332 del_sta_ctx = (tpDeleteStaContext)
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530333 qdf_mem_malloc(sizeof(tDeleteStaContext));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800334 if (!del_sta_ctx) {
335 WMA_LOGE("%s: mem alloc failed for tDeleteStaContext for TDLS peer: %pM",
336 __func__, macaddr);
337 return -ENOMEM;
338 }
339
340 del_sta_ctx->staId = peer_id;
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530341 qdf_mem_copy(del_sta_ctx->addr2, macaddr, IEEE80211_ADDR_LEN);
342 qdf_mem_copy(del_sta_ctx->bssId, wma->interfaces[vdev_id].bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800343 IEEE80211_ADDR_LEN);
344 del_sta_ctx->reasonCode = HAL_DEL_STA_REASON_CODE_KEEP_ALIVE;
345 wma_send_msg(wma, SIR_LIM_DELETE_STA_CONTEXT_IND,
346 (void *)del_sta_ctx, 0);
347 goto exit_handler;
348 break;
349#endif /* FEATURE_WLAN_TDLS */
350
351 case WMI_PEER_STA_KICKOUT_REASON_XRETRY:
352 if (wma->interfaces[vdev_id].type == WMI_VDEV_TYPE_STA &&
353 (wma->interfaces[vdev_id].sub_type == 0 ||
354 wma->interfaces[vdev_id].sub_type ==
355 WMI_UNIFIED_VDEV_SUBTYPE_P2P_CLIENT) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530356 !qdf_mem_cmp(wma->interfaces[vdev_id].bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800357 macaddr, IEEE80211_ADDR_LEN)) {
358 /*
359 * KICKOUT event is for current station-AP connection.
360 * Treat it like final beacon miss. Station may not have
361 * missed beacons but not able to transmit frames to AP
362 * for a long time. Must disconnect to get out of
363 * this sticky situation.
364 * In future implementation, roaming module will also
365 * handle this event and perform a scan.
366 */
367 WMA_LOGW("%s: WMI_PEER_STA_KICKOUT_REASON_XRETRY event for STA",
368 __func__);
369 wma_beacon_miss_handler(wma, vdev_id);
370 goto exit_handler;
371 }
372 break;
373
374 case WMI_PEER_STA_KICKOUT_REASON_UNSPECIFIED:
375 /*
376 * Default legacy value used by original firmware implementation.
377 */
378 if (wma->interfaces[vdev_id].type == WMI_VDEV_TYPE_STA &&
379 (wma->interfaces[vdev_id].sub_type == 0 ||
380 wma->interfaces[vdev_id].sub_type ==
381 WMI_UNIFIED_VDEV_SUBTYPE_P2P_CLIENT) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530382 !qdf_mem_cmp(wma->interfaces[vdev_id].bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800383 macaddr, IEEE80211_ADDR_LEN)) {
384 /*
385 * KICKOUT event is for current station-AP connection.
386 * Treat it like final beacon miss. Station may not have
387 * missed beacons but not able to transmit frames to AP
388 * for a long time. Must disconnect to get out of
389 * this sticky situation.
390 * In future implementation, roaming module will also
391 * handle this event and perform a scan.
392 */
393 WMA_LOGW("%s: WMI_PEER_STA_KICKOUT_REASON_UNSPECIFIED event for STA",
394 __func__);
395 wma_beacon_miss_handler(wma, vdev_id);
396 goto exit_handler;
397 }
398 break;
399
400 case WMI_PEER_STA_KICKOUT_REASON_INACTIVITY:
mukul sharma72c8b222015-09-04 17:02:01 +0530401 /* Handle SA query kickout is same as inactivity kickout */
402 case WMI_PEER_STA_KICKOUT_REASON_SA_QUERY_TIMEOUT:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800403 default:
404 break;
405 }
406
407 /*
408 * default action is to send delete station context indication to LIM
409 */
410 del_sta_ctx =
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530411 (tpDeleteStaContext) qdf_mem_malloc(sizeof(tDeleteStaContext));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800412 if (!del_sta_ctx) {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530413 WMA_LOGE("QDF MEM Alloc Failed for tDeleteStaContext");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800414 return -ENOMEM;
415 }
416
417 del_sta_ctx->staId = peer_id;
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530418 qdf_mem_copy(del_sta_ctx->addr2, macaddr, IEEE80211_ADDR_LEN);
419 qdf_mem_copy(del_sta_ctx->bssId, wma->interfaces[vdev_id].addr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800420 IEEE80211_ADDR_LEN);
421 del_sta_ctx->reasonCode = HAL_DEL_STA_REASON_CODE_KEEP_ALIVE;
Kiran Kumar Lokere37d3aa22015-11-03 14:58:26 -0800422 del_sta_ctx->rssi = kickout_event->rssi + WMA_TGT_NOISE_FLOOR_DBM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800423 wma_send_msg(wma, SIR_LIM_DELETE_STA_CONTEXT_IND, (void *)del_sta_ctx,
424 0);
425
426exit_handler:
427 WMA_LOGD("%s: Exit", __func__);
428 return 0;
429}
430
431/**
432 * wma_unified_bcntx_status_event_handler() - beacon tx status event handler
433 * @handle: wma handle
434 * @cmd_param_info: event data
435 * @len: data length
436 *
437 * WMI Handler for WMI_OFFLOAD_BCN_TX_STATUS_EVENTID event from firmware.
438 * This event is generated by FW when the beacon transmission is offloaded
439 * and the host performs beacon template modification using WMI_BCN_TMPL_CMDID
440 * The FW generates this event when the first successful beacon transmission
441 * after template update
442 *
443 * Return: 0 for success or error code
444 */
445int wma_unified_bcntx_status_event_handler(void *handle,
446 uint8_t *cmd_param_info,
447 uint32_t len)
448{
449 tp_wma_handle wma = (tp_wma_handle) handle;
450 WMI_OFFLOAD_BCN_TX_STATUS_EVENTID_param_tlvs *param_buf;
451 wmi_offload_bcn_tx_status_event_fixed_param *resp_event;
452 tSirFirstBeaconTxCompleteInd *beacon_tx_complete_ind;
453
454 param_buf =
455 (WMI_OFFLOAD_BCN_TX_STATUS_EVENTID_param_tlvs *) cmd_param_info;
456 if (!param_buf) {
457 WMA_LOGE("Invalid bcn tx response event buffer");
458 return -EINVAL;
459 }
460
461 resp_event = param_buf->fixed_param;
462
463 /* Check for valid handle to ensure session is not
464 * deleted in any race
465 */
466 if (!wma->interfaces[resp_event->vdev_id].handle) {
467 WMA_LOGE("%s: The session does not exist", __func__);
468 return -EINVAL;
469 }
470
471 /* Beacon Tx Indication supports only AP mode. Ignore in other modes */
472 if (wma_is_vdev_in_ap_mode(wma, resp_event->vdev_id) == false) {
473 WMA_LOGI("%s: Beacon Tx Indication does not support type %d and sub_type %d",
474 __func__, wma->interfaces[resp_event->vdev_id].type,
475 wma->interfaces[resp_event->vdev_id].sub_type);
476 return 0;
477 }
478
479 beacon_tx_complete_ind = (tSirFirstBeaconTxCompleteInd *)
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530480 qdf_mem_malloc(sizeof(tSirFirstBeaconTxCompleteInd));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800481 if (!beacon_tx_complete_ind) {
482 WMA_LOGE("%s: Failed to alloc beacon_tx_complete_ind",
483 __func__);
484 return -ENOMEM;
485 }
486
487 beacon_tx_complete_ind->messageType = WMA_DFS_BEACON_TX_SUCCESS_IND;
488 beacon_tx_complete_ind->length = sizeof(tSirFirstBeaconTxCompleteInd);
489 beacon_tx_complete_ind->bssIdx = resp_event->vdev_id;
490
491 wma_send_msg(wma, WMA_DFS_BEACON_TX_SUCCESS_IND,
492 (void *)beacon_tx_complete_ind, 0);
493 return 0;
494}
495
496/**
497 * wma_get_link_probe_timeout() - get link timeout based on sub type
498 * @mac: UMAC handler
499 * @sub_type: vdev syb type
500 * @max_inactive_time: return max inactive time
501 * @max_unresponsive_time: return max unresponsive time
502 *
503 * Return: none
504 */
505static inline void wma_get_link_probe_timeout(struct sAniSirGlobal *mac,
506 uint32_t sub_type,
507 uint32_t *max_inactive_time,
508 uint32_t *max_unresponsive_time)
509{
510 uint32_t keep_alive;
511 uint16_t lm_id, ka_id;
512
513 switch (sub_type) {
514 case WMI_UNIFIED_VDEV_SUBTYPE_P2P_GO:
515 lm_id = WNI_CFG_GO_LINK_MONITOR_TIMEOUT;
516 ka_id = WNI_CFG_GO_KEEP_ALIVE_TIMEOUT;
517 break;
518 default:
519 /*For softAp the subtype value will be zero */
520 lm_id = WNI_CFG_AP_LINK_MONITOR_TIMEOUT;
521 ka_id = WNI_CFG_AP_KEEP_ALIVE_TIMEOUT;
522 }
523
524 if (wlan_cfg_get_int(mac, lm_id, max_inactive_time) != eSIR_SUCCESS) {
525 WMA_LOGE("Failed to read link monitor for subtype %d",
526 sub_type);
527 *max_inactive_time = WMA_LINK_MONITOR_DEFAULT_TIME_SECS;
528 }
529
530 if (wlan_cfg_get_int(mac, ka_id, &keep_alive) != eSIR_SUCCESS) {
531 WMA_LOGE("Failed to read keep alive for subtype %d", sub_type);
532 keep_alive = WMA_KEEP_ALIVE_DEFAULT_TIME_SECS;
533 }
534 *max_unresponsive_time = *max_inactive_time + keep_alive;
535}
536
537/**
538 * wma_set_sap_keepalive() - set SAP keep alive parameters to fw
539 * @wma: wma handle
540 * @vdev_id: vdev id
541 *
542 * Return: none
543 */
544void wma_set_sap_keepalive(tp_wma_handle wma, uint8_t vdev_id)
545{
546 uint32_t min_inactive_time, max_inactive_time, max_unresponsive_time;
Anurag Chouhan6d760662016-02-20 16:05:43 +0530547 struct sAniSirGlobal *mac = cds_get_context(QDF_MODULE_ID_PE);
Govind Singhd76a5b02016-03-08 15:12:14 +0530548 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800549
550 if (NULL == mac) {
551 WMA_LOGE("%s: Failed to get mac", __func__);
552 return;
553 }
554
555 wma_get_link_probe_timeout(mac, wma->interfaces[vdev_id].sub_type,
556 &max_inactive_time, &max_unresponsive_time);
557
558 min_inactive_time = max_inactive_time / 2;
559
Govind Singhd76a5b02016-03-08 15:12:14 +0530560 status = wma_vdev_set_param(wma->wmi_handle,
561 vdev_id,
562 WMI_VDEV_PARAM_AP_KEEPALIVE_MIN_IDLE_INACTIVE_TIME_SECS,
563 min_inactive_time);
564 if (QDF_IS_STATUS_ERROR(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800565 WMA_LOGE("Failed to Set AP MIN IDLE INACTIVE TIME");
566
Govind Singhd76a5b02016-03-08 15:12:14 +0530567 status = wma_vdev_set_param(wma->wmi_handle,
568 vdev_id,
569 WMI_VDEV_PARAM_AP_KEEPALIVE_MAX_IDLE_INACTIVE_TIME_SECS,
570 max_inactive_time);
571 if (QDF_IS_STATUS_ERROR(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800572 WMA_LOGE("Failed to Set AP MAX IDLE INACTIVE TIME");
573
Govind Singhd76a5b02016-03-08 15:12:14 +0530574 status = wma_vdev_set_param(wma->wmi_handle,
575 vdev_id,
576 WMI_VDEV_PARAM_AP_KEEPALIVE_MAX_UNRESPONSIVE_TIME_SECS,
577 max_unresponsive_time);
578 if (QDF_IS_STATUS_ERROR(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800579 WMA_LOGE("Failed to Set MAX UNRESPONSIVE TIME");
580
581 WMA_LOGD("%s:vdev_id:%d min_inactive_time: %u max_inactive_time: %u"
582 " max_unresponsive_time: %u", __func__, vdev_id,
583 min_inactive_time, max_inactive_time, max_unresponsive_time);
584}
585
586/**
mukul sharma72c8b222015-09-04 17:02:01 +0530587 * wma_set_sta_sa_query_param() - set sta sa query parameters
588 * @wma: wma handle
589 * @vdev_id: vdev id
590
591 * This function sets sta query related parameters in fw.
592 *
593 * Return: none
594 */
595
596void wma_set_sta_sa_query_param(tp_wma_handle wma,
597 uint8_t vdev_id)
598{
Anurag Chouhan6d760662016-02-20 16:05:43 +0530599 struct sAniSirGlobal *mac = cds_get_context(QDF_MODULE_ID_PE);
mukul sharma72c8b222015-09-04 17:02:01 +0530600 uint32_t max_retries, retry_interval;
mukul sharma72c8b222015-09-04 17:02:01 +0530601
602 WMA_LOGD(FL("Enter:"));
mukul sharma72c8b222015-09-04 17:02:01 +0530603
604 if (wlan_cfg_get_int
605 (mac, WNI_CFG_PMF_SA_QUERY_MAX_RETRIES,
606 &max_retries) != eSIR_SUCCESS) {
607 max_retries = DEFAULT_STA_SA_QUERY_MAX_RETRIES_COUNT;
608 WMA_LOGE(FL("Failed to get value for WNI_CFG_PMF_SA_QUERY_MAX_RETRIES"));
609 }
610 if (wlan_cfg_get_int
611 (mac, WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL,
612 &retry_interval) != eSIR_SUCCESS) {
613 retry_interval = DEFAULT_STA_SA_QUERY_RETRY_INTERVAL;
614 WMA_LOGE(FL("Failed to get value for WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL"));
615 }
616
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530617 wmi_unified_set_sta_sa_query_param_cmd(wma->wmi_handle,
618 vdev_id,
619 max_retries,
620 retry_interval);
mukul sharma72c8b222015-09-04 17:02:01 +0530621
622 WMA_LOGD(FL("Exit :"));
623 return;
624}
625
626/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800627 * wma_set_sta_keep_alive() - set sta keep alive parameters
628 * @wma: wma handle
629 * @vdev_id: vdev id
630 * @method: method for keep alive
631 * @timeperiod: time period
632 * @hostv4addr: host ipv4 address
633 * @destv4addr: dst ipv4 address
634 * @destmac: destination mac
635 *
636 * This function sets keep alive related parameters in fw.
637 *
638 * Return: none
639 */
640void wma_set_sta_keep_alive(tp_wma_handle wma, uint8_t vdev_id,
641 uint32_t method, uint32_t timeperiod,
642 uint8_t *hostv4addr, uint8_t *destv4addr,
643 uint8_t *destmac)
644{
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530645 struct sta_params params;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800646
647 WMA_LOGD("%s: Enter", __func__);
648
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530649 if (!wma) {
650 WMA_LOGE("%s: wma handle is NULL", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800651 return;
652 }
653
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530654 params.vdev_id = vdev_id;
655 params.method = method;
656 params.timeperiod = timeperiod;
657 params.hostv4addr = hostv4addr;
658 params.destv4addr = destv4addr;
659 params.destmac = destmac;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800660
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530661 wmi_unified_set_sta_keep_alive_cmd(wma->wmi_handle,
662 &params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800663
664 WMA_LOGD("%s: Exit", __func__);
665 return;
666}
667
668/**
669 * wma_vdev_install_key_complete_event_handler() - install key complete handler
670 * @handle: wma handle
671 * @event: event data
672 * @len: data length
673 *
674 * This event is sent by fw once WPA/WPA2 keys are installed in fw.
675 *
676 * Return: 0 for success or error code
677 */
678int wma_vdev_install_key_complete_event_handler(void *handle,
679 uint8_t *event,
680 uint32_t len)
681{
682 WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID_param_tlvs *param_buf = NULL;
683 wmi_vdev_install_key_complete_event_fixed_param *key_fp = NULL;
684
685 if (!event) {
686 WMA_LOGE("%s: event param null", __func__);
687 return -EINVAL;
688 }
689
690 param_buf = (WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID_param_tlvs *) event;
691 if (!param_buf) {
692 WMA_LOGE("%s: received null buf from target", __func__);
693 return -EINVAL;
694 }
695
696 key_fp = param_buf->fixed_param;
697 if (!key_fp) {
698 WMA_LOGE("%s: received null event data from target", __func__);
699 return -EINVAL;
700 }
701 /*
702 * Do nothing for now. Completion of set key is already indicated to lim
703 */
704 WMA_LOGI("%s: WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID", __func__);
705 return 0;
706}
707/*
708 * 802.11n D2.0 defined values for "Minimum MPDU Start Spacing":
709 * 0 for no restriction
710 * 1 for 1/4 us - Our lower layer calculations limit our precision to 1 msec
711 * 2 for 1/2 us - Our lower layer calculations limit our precision to 1 msec
712 * 3 for 1 us
713 * 4 for 2 us
714 * 5 for 4 us
715 * 6 for 8 us
716 * 7 for 16 us
717 */
718static const uint8_t wma_mpdu_spacing[] = { 0, 1, 1, 1, 2, 4, 8, 16 };
719
720/**
721 * wma_parse_mpdudensity() - give mpdu spacing from mpdu density
722 * @mpdudensity: mpdu density
723 *
724 * Return: mpdu spacing or 0 for error
725 */
726static inline uint8_t wma_parse_mpdudensity(uint8_t mpdudensity)
727{
728 if (mpdudensity < sizeof(wma_mpdu_spacing))
729 return wma_mpdu_spacing[mpdudensity];
730 else
731 return 0;
732}
733
734/**
735 * wmi_unified_send_peer_assoc() - send peer assoc command to fw
736 * @wma: wma handle
737 * @nw_type: nw type
738 * @params: add sta params
739 *
740 * This function send peer assoc command to firmware with
741 * different parameters.
742 *
Govind Singhb30d4c02016-03-24 11:01:23 +0530743 * Return: QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800744 */
Govind Singhb30d4c02016-03-24 11:01:23 +0530745QDF_STATUS wma_send_peer_assoc(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800746 tSirNwType nw_type,
747 tpAddStaParams params)
748{
749 ol_txrx_pdev_handle pdev;
Govind Singhb30d4c02016-03-24 11:01:23 +0530750 struct peer_assoc_params *cmd;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800751 int32_t ret, max_rates, i;
752 uint8_t rx_stbc, tx_stbc;
Govind Singhb30d4c02016-03-24 11:01:23 +0530753 uint8_t *rate_pos;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800754 wmi_rate_set peer_legacy_rates, peer_ht_rates;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800755 uint32_t num_peer_11b_rates = 0;
756 uint32_t num_peer_11a_rates = 0;
757 uint32_t phymode;
758 uint32_t peer_nss = 1;
759 struct wma_txrx_node *intr = NULL;
Govind Singhb30d4c02016-03-24 11:01:23 +0530760 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800761
Govind Singhb30d4c02016-03-24 11:01:23 +0530762 cmd = qdf_mem_malloc(sizeof(struct peer_assoc_params));
763 if (!cmd) {
764 WMA_LOGE("Failed to allocate peer_assoc_params param");
765 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800766 }
Govind Singhb30d4c02016-03-24 11:01:23 +0530767
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800768 intr = &wma->interfaces[params->smesessionId];
769
Anurag Chouhan6d760662016-02-20 16:05:43 +0530770 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800771
772 if (NULL == pdev) {
773 WMA_LOGE("%s: Failed to get pdev", __func__);
Govind Singhb30d4c02016-03-24 11:01:23 +0530774 qdf_mem_free(cmd);
775 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800776 }
777
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530778 qdf_mem_zero(&peer_legacy_rates, sizeof(wmi_rate_set));
779 qdf_mem_zero(&peer_ht_rates, sizeof(wmi_rate_set));
Govind Singhb30d4c02016-03-24 11:01:23 +0530780 qdf_mem_zero(cmd, sizeof(struct peer_assoc_params));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800781
782 phymode = wma_peer_phymode(nw_type, params->staType,
783 params->htCapable,
784 params->ch_width,
785 params->vhtCapable);
786
787 /* Legacy Rateset */
788 rate_pos = (uint8_t *) peer_legacy_rates.rates;
789 for (i = 0; i < SIR_NUM_11B_RATES; i++) {
790 if (!params->supportedRates.llbRates[i])
791 continue;
792 rate_pos[peer_legacy_rates.num_rates++] =
793 params->supportedRates.llbRates[i];
794 num_peer_11b_rates++;
795 }
796 for (i = 0; i < SIR_NUM_11A_RATES; i++) {
797 if (!params->supportedRates.llaRates[i])
798 continue;
799 rate_pos[peer_legacy_rates.num_rates++] =
800 params->supportedRates.llaRates[i];
801 num_peer_11a_rates++;
802 }
803
804 if ((phymode == MODE_11A && num_peer_11a_rates == 0) ||
805 (phymode == MODE_11B && num_peer_11b_rates == 0)) {
806 WMA_LOGW("%s: Invalid phy rates. phymode 0x%x, 11b_rates %d, 11a_rates %d",
807 __func__, phymode, num_peer_11b_rates, num_peer_11a_rates);
Govind Singhb30d4c02016-03-24 11:01:23 +0530808 qdf_mem_free(cmd);
809 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800810 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800811
812 /* HT Rateset */
813 max_rates = sizeof(peer_ht_rates.rates) /
814 sizeof(peer_ht_rates.rates[0]);
815 rate_pos = (uint8_t *) peer_ht_rates.rates;
816 for (i = 0; i < MAX_SUPPORTED_RATES; i++) {
817 if (params->supportedRates.supportedMCSSet[i / 8] &
818 (1 << (i % 8))) {
819 rate_pos[peer_ht_rates.num_rates++] = i;
820 if (i >= 8) {
821 /* MCS8 or higher rate is present, must be 2x2 */
822 peer_nss = 2;
823 }
824 }
825 if (peer_ht_rates.num_rates == max_rates)
826 break;
827 }
828
829 if (params->htCapable && !peer_ht_rates.num_rates) {
830 uint8_t temp_ni_rates[8] = { 0x0, 0x1, 0x2, 0x3,
831 0x4, 0x5, 0x6, 0x7};
832 /*
833 * Workaround for EV 116382: The peer is marked HT but with
834 * supported rx mcs set is set to 0. 11n spec mandates MCS0-7
835 * for a HT STA. So forcing the supported rx mcs rate to
836 * MCS 0-7. This workaround will be removed once we get
837 * clarification from WFA regarding this STA behavior.
838 */
839
840 /* TODO: Do we really need this? */
841 WMA_LOGW("Peer is marked as HT capable but supported mcs rate is 0");
842 peer_ht_rates.num_rates = sizeof(temp_ni_rates);
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530843 qdf_mem_copy((uint8_t *) peer_ht_rates.rates, temp_ni_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800844 peer_ht_rates.num_rates);
845 }
846
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800847 /* in ap/ibss mode and for tdls peer, use mac address of the peer in
848 * the other end as the new peer address; in sta mode, use bss id to
849 * be the new peer address
850 */
851 if ((wma_is_vdev_in_ap_mode(wma, params->smesessionId))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800852 || (wma_is_vdev_in_ibss_mode(wma, params->smesessionId))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800853#ifdef FEATURE_WLAN_TDLS
854 || (STA_ENTRY_TDLS_PEER == params->staType)
855#endif /* FEATURE_WLAN_TDLS */
856 )
857 WMI_CHAR_ARRAY_TO_MAC_ADDR(params->staMac, &cmd->peer_macaddr);
858 else
859 WMI_CHAR_ARRAY_TO_MAC_ADDR(params->bssId, &cmd->peer_macaddr);
860 cmd->vdev_id = params->smesessionId;
861 cmd->peer_new_assoc = 1;
862 cmd->peer_associd = params->assocId;
863
864 /*
865 * The target only needs a subset of the flags maintained in the host.
866 * Just populate those flags and send it down
867 */
868 cmd->peer_flags = 0;
869
870 if (params->wmmEnabled)
871 cmd->peer_flags |= WMI_PEER_QOS;
872
873 if (params->uAPSD) {
874 cmd->peer_flags |= WMI_PEER_APSD;
875 WMA_LOGD("Set WMI_PEER_APSD: uapsd Mask %d", params->uAPSD);
876 }
877
878 if (params->htCapable) {
879 cmd->peer_flags |= (WMI_PEER_HT | WMI_PEER_QOS);
880 cmd->peer_rate_caps |= WMI_RC_HT_FLAG;
881 }
882
883 if (params->ch_width) {
884 cmd->peer_flags |= WMI_PEER_40MHZ;
885 cmd->peer_rate_caps |= WMI_RC_CW40_FLAG;
886 if (params->fShortGI40Mhz)
887 cmd->peer_rate_caps |= WMI_RC_SGI_FLAG;
888 } else if (params->fShortGI20Mhz)
889 cmd->peer_rate_caps |= WMI_RC_SGI_FLAG;
890
891#ifdef WLAN_FEATURE_11AC
892 if (params->vhtCapable) {
893 cmd->peer_flags |= (WMI_PEER_HT | WMI_PEER_VHT | WMI_PEER_QOS);
894 cmd->peer_rate_caps |= WMI_RC_HT_FLAG;
895 }
896
897 if (params->ch_width == CH_WIDTH_80MHZ)
898 cmd->peer_flags |= WMI_PEER_80MHZ;
899 else if (params->ch_width == CH_WIDTH_160MHZ)
900 cmd->peer_flags |= WMI_PEER_160MHZ;
901 else if (params->ch_width == CH_WIDTH_80P80MHZ)
902 cmd->peer_flags |= WMI_PEER_160MHZ;
903
904 cmd->peer_vht_caps = params->vht_caps;
905#endif /* WLAN_FEATURE_11AC */
906
907 if (params->rmfEnabled)
908 cmd->peer_flags |= WMI_PEER_PMF;
909
910 rx_stbc = (params->ht_caps & IEEE80211_HTCAP_C_RXSTBC) >>
911 IEEE80211_HTCAP_C_RXSTBC_S;
912 if (rx_stbc) {
913 cmd->peer_flags |= WMI_PEER_STBC;
914 cmd->peer_rate_caps |= (rx_stbc << WMI_RC_RX_STBC_FLAG_S);
915 }
916
917 tx_stbc = (params->ht_caps & IEEE80211_HTCAP_C_TXSTBC) >>
918 IEEE80211_HTCAP_C_TXSTBC_S;
919 if (tx_stbc) {
920 cmd->peer_flags |= WMI_PEER_STBC;
921 cmd->peer_rate_caps |= (tx_stbc << WMI_RC_TX_STBC_FLAG_S);
922 }
923
924 if (params->htLdpcCapable || params->vhtLdpcCapable)
925 cmd->peer_flags |= WMI_PEER_LDPC;
926
927 switch (params->mimoPS) {
928 case eSIR_HT_MIMO_PS_STATIC:
929 cmd->peer_flags |= WMI_PEER_STATIC_MIMOPS;
930 break;
931 case eSIR_HT_MIMO_PS_DYNAMIC:
932 cmd->peer_flags |= WMI_PEER_DYN_MIMOPS;
933 break;
934 case eSIR_HT_MIMO_PS_NO_LIMIT:
935 cmd->peer_flags |= WMI_PEER_SPATIAL_MUX;
936 break;
937 default:
938 break;
939 }
940
941#ifdef FEATURE_WLAN_TDLS
942 if (STA_ENTRY_TDLS_PEER == params->staType)
943 cmd->peer_flags |= WMI_PEER_AUTH;
944#endif /* FEATURE_WLAN_TDLS */
945
946 if (params->wpa_rsn
947#ifdef FEATURE_WLAN_WAPI
948 || params->encryptType == eSIR_ED_WPI
949#endif /* FEATURE_WLAN_WAPI */
950 )
951 cmd->peer_flags |= WMI_PEER_NEED_PTK_4_WAY;
952 if (params->wpa_rsn >> 1)
953 cmd->peer_flags |= WMI_PEER_NEED_GTK_2_WAY;
954
955 ol_txrx_peer_state_update(pdev, params->bssId, ol_txrx_peer_state_auth);
956
957#ifdef FEATURE_WLAN_WAPI
958 if (params->encryptType == eSIR_ED_WPI) {
Govind Singhd76a5b02016-03-08 15:12:14 +0530959 ret = wma_vdev_set_param(wma->wmi_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800960 params->smesessionId,
961 WMI_VDEV_PARAM_DROP_UNENCRY,
962 false);
963 if (ret) {
964 WMA_LOGE
965 ("Set WMI_VDEV_PARAM_DROP_UNENCRY Param status:%d\n",
966 ret);
Govind Singhb30d4c02016-03-24 11:01:23 +0530967 qdf_mem_free(cmd);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800968 return ret;
969 }
970 }
971#endif /* FEATURE_WLAN_WAPI */
972
973 cmd->peer_caps = params->capab_info;
974 cmd->peer_listen_intval = params->listenInterval;
975 cmd->peer_ht_caps = params->ht_caps;
976 cmd->peer_max_mpdu = (1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR +
977 params->maxAmpduSize)) - 1;
978 cmd->peer_mpdu_density = wma_parse_mpdudensity(params->maxAmpduDensity);
979
980 if (params->supportedRates.supportedMCSSet[1] &&
981 params->supportedRates.supportedMCSSet[2])
982 cmd->peer_rate_caps |= WMI_RC_TS_FLAG;
983 else if (params->supportedRates.supportedMCSSet[1])
984 cmd->peer_rate_caps |= WMI_RC_DS_FLAG;
985
986 /* Update peer legacy rate information */
Govind Singhb30d4c02016-03-24 11:01:23 +0530987 cmd->peer_legacy_rates.num_rates = peer_legacy_rates.num_rates;
988 qdf_mem_copy(cmd->peer_legacy_rates.rates, peer_legacy_rates.rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800989 peer_legacy_rates.num_rates);
990
991 /* Update peer HT rate information */
Govind Singhb30d4c02016-03-24 11:01:23 +0530992 cmd->peer_ht_rates.num_rates = peer_ht_rates.num_rates;
993 qdf_mem_copy(cmd->peer_ht_rates.rates, peer_ht_rates.rates,
994 peer_ht_rates.num_rates);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800995
996 /* VHT Rates */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800997
998 cmd->peer_nss = peer_nss;
Naveen Rawatb14cab32015-11-02 17:01:51 -0800999 /*
1000 * Because of DBS a vdev may come up in any of the two MACs with
1001 * different capabilities. STBC capab should be fetched for given
1002 * hard_mode->MAC_id combo. It is planned that firmware should provide
1003 * these dev capabilities. But for now number of tx streams can be used
1004 * to identify if Tx STBC needs to be disabled.
1005 */
1006 if (intr->tx_streams < 2) {
1007 cmd->peer_vht_caps &= ~(1 << SIR_MAC_VHT_CAP_TXSTBC);
1008 WMA_LOGD("Num tx_streams: %d, Disabled txSTBC",
1009 intr->tx_streams);
1010 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001011 WMA_LOGD("peer_nss %d peer_ht_rates.num_rates %d ", cmd->peer_nss,
1012 peer_ht_rates.num_rates);
1013
Govind Singhb30d4c02016-03-24 11:01:23 +05301014 cmd->vht_capable = params->vhtCapable;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001015 if (params->vhtCapable) {
1016#define VHT2x2MCSMASK 0xc
Govind Singhb30d4c02016-03-24 11:01:23 +05301017 cmd->rx_max_rate = params->supportedRates.vhtRxHighestDataRate;
1018 cmd->rx_mcs_set = params->supportedRates.vhtRxMCSMap;
1019 cmd->tx_max_rate = params->supportedRates.vhtTxHighestDataRate;
1020 cmd->tx_mcs_set = params->supportedRates.vhtTxMCSMap;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001021
1022 if (params->vhtSupportedRxNss) {
1023 cmd->peer_nss = params->vhtSupportedRxNss;
1024 } else {
Govind Singhb30d4c02016-03-24 11:01:23 +05301025 cmd->peer_nss = ((cmd->rx_mcs_set & VHT2x2MCSMASK)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001026 == VHT2x2MCSMASK) ? 1 : 2;
1027 }
1028 }
1029
1030 /*
1031 * Limit nss to max number of rf chain supported by target
1032 * Otherwise Fw will crash
1033 */
1034 wma_update_txrx_chainmask(wma->num_rf_chains, &cmd->peer_nss);
1035
1036 intr->nss = cmd->peer_nss;
1037 cmd->peer_phymode = phymode;
1038 WMA_LOGD("%s: vdev_id %d associd %d peer_flags %x rate_caps %x "
1039 "peer_caps %x listen_intval %d ht_caps %x max_mpdu %d "
1040 "nss %d phymode %d peer_mpdu_density %d encr_type %d "
1041 "cmd->peer_vht_caps %x", __func__,
1042 cmd->vdev_id, cmd->peer_associd, cmd->peer_flags,
1043 cmd->peer_rate_caps, cmd->peer_caps,
1044 cmd->peer_listen_intval, cmd->peer_ht_caps,
1045 cmd->peer_max_mpdu, cmd->peer_nss, cmd->peer_phymode,
1046 cmd->peer_mpdu_density, params->encryptType,
1047 cmd->peer_vht_caps);
1048
Govind Singhb30d4c02016-03-24 11:01:23 +05301049 status = wmi_unified_peer_assoc_send(wma->wmi_handle,
1050 cmd);
1051 if (QDF_IS_STATUS_ERROR(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001052 WMA_LOGP("%s: Failed to send peer assoc command ret = %d",
1053 __func__, ret);
Govind Singhb30d4c02016-03-24 11:01:23 +05301054 qdf_mem_free(cmd);
1055
1056 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001057}
1058
1059/**
1060 * wmi_unified_vdev_set_gtx_cfg_send() - set GTX params
1061 * @wmi_handle: wmi handle
1062 * @if_id: vdev id
1063 * @gtx_info: GTX config params
1064 *
1065 * This function set GTX related params in firmware.
1066 *
1067 * Return: 0 for success or error code
1068 */
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301069QDF_STATUS wmi_unified_vdev_set_gtx_cfg_send(wmi_unified_t wmi_handle,
1070 uint32_t if_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001071 gtx_config_t *gtx_info)
1072{
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301073 struct wmi_gtx_config params;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001074
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301075 params.gtx_rt_mask[0] = gtx_info->gtxRTMask[0];
1076 params.gtx_rt_mask[1] = gtx_info->gtxRTMask[1];
1077 params.gtx_usrcfg = gtx_info->gtxUsrcfg;
1078 params.gtx_threshold = gtx_info->gtxPERThreshold;
1079 params.gtx_margin = gtx_info->gtxPERMargin;
1080 params.gtx_tpcstep = gtx_info->gtxTPCstep;
1081 params.gtx_tpcmin = gtx_info->gtxTPCMin;
1082 params.gtx_bwmask = gtx_info->gtxBWMask;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001083
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301084 return wmi_unified_vdev_set_gtx_cfg_cmd(wmi_handle,
1085 if_id, &params);
1086
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001087}
1088
1089/**
1090 * wma_update_protection_mode() - update protection mode
1091 * @wma: wma handle
1092 * @vdev_id: vdev id
1093 * @llbcoexist: protection mode info
1094 *
1095 * This function set protection mode(RTS/CTS) to fw for passed vdev id.
1096 *
1097 * Return: none
1098 */
1099void wma_update_protection_mode(tp_wma_handle wma, uint8_t vdev_id,
1100 uint8_t llbcoexist)
1101{
Govind Singhd76a5b02016-03-08 15:12:14 +05301102 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001103 enum ieee80211_protmode prot_mode;
1104
1105 prot_mode = llbcoexist ? IEEE80211_PROT_CTSONLY : IEEE80211_PROT_NONE;
1106
Govind Singhd76a5b02016-03-08 15:12:14 +05301107 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001108 WMI_VDEV_PARAM_PROTECTION_MODE,
1109 prot_mode);
1110
Govind Singhd76a5b02016-03-08 15:12:14 +05301111 if (QDF_IS_STATUS_ERROR(ret))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001112 WMA_LOGE("Failed to send wmi protection mode cmd");
1113 else
1114 WMA_LOGD("Updated protection mode %d to target", prot_mode);
1115}
1116
1117/**
1118 * wma_update_beacon_interval() - update beacon interval in fw
1119 * @wma: wma handle
1120 * @vdev_id: vdev id
1121 * @beaconInterval: becon interval
1122 *
1123 * Return: none
1124 */
1125static void
1126wma_update_beacon_interval(tp_wma_handle wma, uint8_t vdev_id,
1127 uint16_t beaconInterval)
1128{
Govind Singhd76a5b02016-03-08 15:12:14 +05301129 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001130
Govind Singhd76a5b02016-03-08 15:12:14 +05301131 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001132 WMI_VDEV_PARAM_BEACON_INTERVAL,
1133 beaconInterval);
1134
Govind Singhd76a5b02016-03-08 15:12:14 +05301135 if (QDF_IS_STATUS_ERROR(ret))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001136 WMA_LOGE("Failed to update beacon interval");
1137 else
1138 WMA_LOGI("Updated beacon interval %d for vdev %d",
1139 beaconInterval, vdev_id);
1140}
1141
1142/**
1143 * wma_process_update_beacon_params() - update beacon parameters to target
1144 * @wma: wma handle
1145 * @bcn_params: beacon parameters
1146 *
1147 * Return: none
1148 */
1149void
1150wma_process_update_beacon_params(tp_wma_handle wma,
1151 tUpdateBeaconParams *bcn_params)
1152{
1153 if (!bcn_params) {
1154 WMA_LOGE("bcn_params NULL");
1155 return;
1156 }
1157
1158 if (bcn_params->smeSessionId >= wma->max_bssid) {
1159 WMA_LOGE("Invalid vdev id %d", bcn_params->smeSessionId);
1160 return;
1161 }
1162
1163 if (bcn_params->paramChangeBitmap & PARAM_BCN_INTERVAL_CHANGED) {
1164 wma_update_beacon_interval(wma, bcn_params->smeSessionId,
1165 bcn_params->beaconInterval);
1166 }
1167
1168 if (bcn_params->paramChangeBitmap & PARAM_llBCOEXIST_CHANGED)
1169 wma_update_protection_mode(wma, bcn_params->smeSessionId,
1170 bcn_params->llbCoexist);
1171}
1172
1173/**
1174 * wma_update_cfg_params() - update cfg parameters to target
1175 * @wma: wma handle
1176 * @cfgParam: cfg parameter
1177 *
1178 * Return: none
1179 */
1180void wma_update_cfg_params(tp_wma_handle wma, tSirMsgQ *cfgParam)
1181{
1182 uint8_t vdev_id;
1183 uint32_t param_id;
1184 uint32_t cfg_val;
Govind Singhd76a5b02016-03-08 15:12:14 +05301185 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001186 /* get mac to acess CFG data base */
1187 struct sAniSirGlobal *pmac;
1188
1189 switch (cfgParam->bodyval) {
1190 case WNI_CFG_RTS_THRESHOLD:
1191 param_id = WMI_VDEV_PARAM_RTS_THRESHOLD;
1192 break;
1193 case WNI_CFG_FRAGMENTATION_THRESHOLD:
1194 param_id = WMI_VDEV_PARAM_FRAGMENTATION_THRESHOLD;
1195 break;
1196 default:
1197 WMA_LOGD("Unhandled cfg parameter %d", cfgParam->bodyval);
1198 return;
1199 }
1200
Anurag Chouhan6d760662016-02-20 16:05:43 +05301201 pmac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001202
1203 if (NULL == pmac) {
1204 WMA_LOGE("%s: Failed to get pmac", __func__);
1205 return;
1206 }
1207
1208 if (wlan_cfg_get_int(pmac, (uint16_t) cfgParam->bodyval,
1209 &cfg_val) != eSIR_SUCCESS) {
1210 WMA_LOGE("Failed to get value for CFG PARAMS %d. returning without updating",
1211 cfgParam->bodyval);
1212 return;
1213 }
1214
1215 for (vdev_id = 0; vdev_id < wma->max_bssid; vdev_id++) {
1216 if (wma->interfaces[vdev_id].handle != 0) {
Govind Singhd76a5b02016-03-08 15:12:14 +05301217 ret = wma_vdev_set_param(wma->wmi_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001218 vdev_id, param_id,
1219 cfg_val);
Govind Singhd76a5b02016-03-08 15:12:14 +05301220 if (QDF_IS_STATUS_ERROR(ret))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001221 WMA_LOGE("Update cfg params failed for vdevId %d",
1222 vdev_id);
1223 }
1224 }
1225}
1226
1227/**
1228 * wma_read_cfg_wepkey() - fill key_info for WEP key
1229 * @wma_handle: wma handle
1230 * @key_info: key_info ptr
1231 * @def_key_idx: default key index
1232 * @num_keys: number of keys
1233 *
1234 * This function reads WEP keys from cfg and fills
1235 * up key_info.
1236 *
1237 * Return: none
1238 */
1239static void wma_read_cfg_wepkey(tp_wma_handle wma_handle,
1240 tSirKeys *key_info, uint32_t *def_key_idx,
1241 uint8_t *num_keys)
1242{
1243 tSirRetStatus status;
1244 uint32_t val = SIR_MAC_KEY_LENGTH;
1245 uint8_t i, j;
1246
1247 WMA_LOGD("Reading WEP keys from cfg");
1248 /* NOTE:def_key_idx is initialized to 0 by the caller */
1249 status = wlan_cfg_get_int(wma_handle->mac_context,
1250 WNI_CFG_WEP_DEFAULT_KEYID, def_key_idx);
1251 if (status != eSIR_SUCCESS)
1252 WMA_LOGE("Unable to read default id, defaulting to 0");
1253
1254 for (i = 0, j = 0; i < SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS; i++) {
1255 status = wlan_cfg_get_str(wma_handle->mac_context,
1256 (uint16_t) WNI_CFG_WEP_DEFAULT_KEY_1 +
1257 i, key_info[j].key, &val);
1258 if (status != eSIR_SUCCESS) {
1259 WMA_LOGE("WEP key is not configured at :%d", i);
1260 } else {
1261 key_info[j].keyId = i;
1262 key_info[j].keyLength = (uint16_t) val;
1263 j++;
1264 }
1265 }
1266 *num_keys = j;
1267}
1268
1269/**
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301270 * wma_setup_install_key_cmd() - set key parameters
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001271 * @wma_handle: wma handle
1272 * @key_params: key parameters
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001273 * @mode: op mode
1274 *
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301275 * This function fills structure from information
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001276 * passed in key_params.
1277 *
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301278 * Return: QDF_STATUS_SUCCESS - success
1279 QDF_STATUS_E_FAILURE - failure
1280 QDF_STATUS_E_NOMEM - invalid request
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001281 */
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301282static QDF_STATUS wma_setup_install_key_cmd(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001283 struct wma_set_key_params
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301284 *key_params, uint8_t mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001285{
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301286 struct set_key_params params;
1287 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001288#ifdef WLAN_FEATURE_11W
1289 struct wma_txrx_node *iface = NULL;
1290#endif /* WLAN_FEATURE_11W */
1291 if ((key_params->key_type == eSIR_ED_NONE &&
1292 key_params->key_len) || (key_params->key_type != eSIR_ED_NONE &&
1293 !key_params->key_len)) {
1294 WMA_LOGE("%s:Invalid set key request", __func__);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301295 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001296 }
1297
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301298 params.vdev_id = key_params->vdev_id;
1299 params.key_idx = key_params->key_idx;
1300 qdf_mem_copy(params.peer_mac, key_params->peer_mac, IEEE80211_ADDR_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001301
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301302#ifdef FEATURE_WLAN_WAPI
1303 qdf_mem_set(params.tx_iv, 16, 0);
1304 qdf_mem_set(params.rx_iv, 16, 0);
1305#endif
1306 params.key_txmic_len = 0;
1307 params.key_rxmic_len = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001308
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301309 params.key_flags = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001310 if (key_params->unicast)
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301311 params.key_flags |= PAIRWISE_USAGE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001312 else
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301313 params.key_flags |= GROUP_USAGE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001314
1315 switch (key_params->key_type) {
1316 case eSIR_ED_NONE:
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301317 params.key_cipher = WMI_CIPHER_NONE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001318 break;
1319 case eSIR_ED_WEP40:
1320 case eSIR_ED_WEP104:
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301321 params.key_cipher = WMI_CIPHER_WEP;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001322 if (key_params->unicast &&
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301323 params.key_idx == key_params->def_key_idx) {
Ganesh Kondabattini59a4a952015-11-30 11:55:40 +05301324 WMA_LOGD("STA Mode: cmd->key_flags |= TX_USAGE");
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301325 params.key_flags |= TX_USAGE;
Ganesh Kondabattini59a4a952015-11-30 11:55:40 +05301326 } else if ((mode == wlan_op_mode_ap) &&
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301327 (params.key_idx == key_params->def_key_idx)) {
Ganesh Kondabattini59a4a952015-11-30 11:55:40 +05301328 WMA_LOGD("AP Mode: cmd->key_flags |= TX_USAGE");
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301329 params.key_flags |= TX_USAGE;
Ganesh Kondabattini59a4a952015-11-30 11:55:40 +05301330 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001331 break;
1332 case eSIR_ED_TKIP:
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301333 params.key_txmic_len = WMA_TXMIC_LEN;
1334 params.key_rxmic_len = WMA_RXMIC_LEN;
1335 params.key_cipher = WMI_CIPHER_TKIP;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001336 break;
1337#ifdef FEATURE_WLAN_WAPI
1338#define WPI_IV_LEN 16
1339 case eSIR_ED_WPI:
1340 {
1341 /*initialize receive and transmit IV with default values */
1342 /* **Note: tx_iv must be sent in reverse** */
1343 unsigned char tx_iv[16] = { 0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c,
1344 0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c,
1345 0x36, 0x5c, 0x36, 0x5c};
1346 unsigned char rx_iv[16] = { 0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36,
1347 0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36,
1348 0x5c, 0x36, 0x5c, 0x37};
1349 if (mode == wlan_op_mode_ap) {
1350 /* Authenticator initializes the value of PN as
1351 * 0x5C365C365C365C365C365C365C365C36 for MCastkey Update
1352 */
1353 if (key_params->unicast)
1354 tx_iv[0] = 0x37;
1355
1356 rx_iv[WPI_IV_LEN - 1] = 0x36;
1357 } else {
1358 if (!key_params->unicast)
1359 rx_iv[WPI_IV_LEN - 1] = 0x36;
1360 }
1361
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301362 params.key_txmic_len = WMA_TXMIC_LEN;
1363 params.key_rxmic_len = WMA_RXMIC_LEN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001364
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301365 qdf_mem_copy(&params.rx_iv, &rx_iv,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001366 WPI_IV_LEN);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301367 qdf_mem_copy(&params.tx_iv, &tx_iv,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001368 WPI_IV_LEN);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301369 params.key_cipher = WMI_CIPHER_WAPI;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001370 break;
1371 }
1372#endif /* FEATURE_WLAN_WAPI */
1373 case eSIR_ED_CCMP:
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301374 params.key_cipher = WMI_CIPHER_AES_CCM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001375 break;
1376#ifdef WLAN_FEATURE_11W
1377 case eSIR_ED_AES_128_CMAC:
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301378 params.key_cipher = WMI_CIPHER_AES_CMAC;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001379 break;
1380#endif /* WLAN_FEATURE_11W */
1381 default:
1382 /* TODO: MFP ? */
1383 WMA_LOGE("%s:Invalid encryption type:%d", __func__,
1384 key_params->key_type);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301385 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001386 }
1387
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001388#ifdef BIG_ENDIAN_HOST
1389 {
1390 /* for big endian host, copy engine byte_swap is enabled
1391 * But the key data content is in network byte order
1392 * Need to byte swap the key data content - so when copy engine
1393 * does byte_swap - target gets key_data content in the correct
1394 * order.
1395 */
1396 int8_t i;
1397 uint32_t *destp, *srcp;
1398
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301399 destp = (uint32_t *) params.key_data;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001400 srcp = (uint32_t *) key_params->key_data;
1401 for (i = 0;
1402 i < roundup(key_params->key_len, sizeof(uint32_t)) / 4;
1403 i++) {
1404 *destp = le32_to_cpu(*srcp);
1405 destp++;
1406 srcp++;
1407 }
1408 }
1409#else
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301410 qdf_mem_copy((void *)params.key_data,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001411 (const void *)key_params->key_data, key_params->key_len);
1412#endif /* BIG_ENDIAN_HOST */
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301413 params.key_len = key_params->key_len;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001414
1415#ifdef WLAN_FEATURE_11W
1416 if (key_params->key_type == eSIR_ED_AES_128_CMAC) {
1417 iface = &wma_handle->interfaces[key_params->vdev_id];
1418 if (iface) {
1419 iface->key.key_length = key_params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301420 qdf_mem_copy(iface->key.key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001421 (const void *)key_params->key_data,
1422 iface->key.key_length);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301423 if ((params.key_idx == WMA_IGTK_KEY_INDEX_4) ||
1424 (params.key_idx == WMA_IGTK_KEY_INDEX_5))
1425 qdf_mem_zero(iface->key.key_id[params.key_idx -
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001426 WMA_IGTK_KEY_INDEX_4].ipn,
1427 CMAC_IPN_LEN);
1428 }
1429 }
1430#endif /* WLAN_FEATURE_11W */
1431
1432 WMA_LOGD("Key setup : vdev_id %d key_idx %d key_type %d key_len %d"
1433 " unicast %d peer_mac %pM def_key_idx %d", key_params->vdev_id,
1434 key_params->key_idx, key_params->key_type, key_params->key_len,
1435 key_params->unicast, key_params->peer_mac,
1436 key_params->def_key_idx);
1437
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301438 status = wmi_unified_setup_install_key_cmd(wma_handle->wmi_handle,
1439 &params);
1440
1441 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001442}
1443
1444/**
1445 * wma_set_bsskey() - set encryption key to fw.
1446 * @wma_handle: wma handle
1447 * @key_info: key info
1448 *
1449 * Return: none
1450 */
1451void wma_set_bsskey(tp_wma_handle wma_handle, tpSetBssKeyParams key_info)
1452{
1453 struct wma_set_key_params key_params;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301454 QDF_STATUS status = QDF_STATUS_SUCCESS;
1455 uint32_t i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001456 uint32_t def_key_idx = 0;
1457 ol_txrx_vdev_handle txrx_vdev;
1458
1459 WMA_LOGD("BSS key setup");
1460 txrx_vdev = wma_find_vdev_by_id(wma_handle, key_info->smesessionId);
1461 if (!txrx_vdev) {
1462 WMA_LOGE("%s:Invalid vdev handle", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301463 key_info->status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001464 goto out;
1465 }
1466
1467 /*
1468 * For IBSS, WMI expects the BSS key to be set per peer key
1469 * So cache the BSS key in the wma_handle and re-use it when the
1470 * STA key is been setup for a peer
1471 */
1472 if (wlan_op_mode_ibss == txrx_vdev->opmode) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301473 key_info->status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001474 if (wma_handle->ibss_started > 0)
1475 goto out;
1476 WMA_LOGD("Caching IBSS Key");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301477 qdf_mem_copy(&wma_handle->ibsskey_info, key_info,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001478 sizeof(tSetBssKeyParams));
1479 }
1480
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301481 qdf_mem_set(&key_params, sizeof(key_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001482 key_params.vdev_id = key_info->smesessionId;
1483 key_params.key_type = key_info->encType;
1484 key_params.singl_tid_rc = key_info->singleTidRc;
1485 key_params.unicast = false;
1486 if (txrx_vdev->opmode == wlan_op_mode_sta) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301487 qdf_mem_copy(key_params.peer_mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001488 wma_handle->interfaces[key_info->smesessionId].bssid,
1489 IEEE80211_ADDR_LEN);
1490 } else {
1491 /* vdev mac address will be passed for all other modes */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301492 qdf_mem_copy(key_params.peer_mac, txrx_vdev->mac_addr.raw,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001493 IEEE80211_ADDR_LEN);
1494 WMA_LOGA("BSS Key setup with vdev_mac %pM\n",
1495 txrx_vdev->mac_addr.raw);
1496 }
1497
1498 if (key_info->numKeys == 0 &&
1499 (key_info->encType == eSIR_ED_WEP40 ||
1500 key_info->encType == eSIR_ED_WEP104)) {
1501 wma_read_cfg_wepkey(wma_handle, key_info->key,
1502 &def_key_idx, &key_info->numKeys);
1503 }
1504
1505 for (i = 0; i < key_info->numKeys; i++) {
1506 if (key_params.key_type != eSIR_ED_NONE &&
1507 !key_info->key[i].keyLength)
1508 continue;
1509 if (key_info->encType == eSIR_ED_WPI) {
1510 key_params.key_idx = key_info->key[i].keyId;
1511 key_params.def_key_idx = key_info->key[i].keyId;
1512 } else
1513 key_params.key_idx = key_info->key[i].keyId;
1514
1515 key_params.key_len = key_info->key[i].keyLength;
1516 if (key_info->encType == eSIR_ED_TKIP) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301517 qdf_mem_copy(key_params.key_data,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001518 key_info->key[i].key, 16);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301519 qdf_mem_copy(&key_params.key_data[16],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001520 &key_info->key[i].key[24], 8);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301521 qdf_mem_copy(&key_params.key_data[24],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001522 &key_info->key[i].key[16], 8);
1523 } else
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301524 qdf_mem_copy((void *)key_params.key_data,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001525 (const void *)key_info->key[i].key,
1526 key_info->key[i].keyLength);
1527
1528 WMA_LOGD("%s: bss key[%d] length %d", __func__, i,
1529 key_info->key[i].keyLength);
1530
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301531 status = wma_setup_install_key_cmd(wma_handle, &key_params,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001532 txrx_vdev->opmode);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301533 if (status == QDF_STATUS_E_NOMEM) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001534 WMA_LOGE("%s:Failed to setup install key buf",
1535 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301536 key_info->status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001537 goto out;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301538 } else if (status == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001539 WMA_LOGE("%s:Failed to send install key command",
1540 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301541 key_info->status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001542 goto out;
1543 }
1544 }
1545
1546 wma_handle->ibss_started++;
1547 /* TODO: Should we wait till we get HTT_T2H_MSG_TYPE_SEC_IND? */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301548 key_info->status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001549
1550out:
1551 wma_send_msg(wma_handle, WMA_SET_BSSKEY_RSP, (void *)key_info, 0);
1552}
1553
1554#ifdef QCA_IBSS_SUPPORT
1555/**
1556 * wma_calc_ibss_heart_beat_timer() - calculate IBSS heart beat timer
1557 * @peer_num: number of peers
1558 *
1559 * Return: heart beat timer value
1560 */
1561static uint16_t wma_calc_ibss_heart_beat_timer(int16_t peer_num)
1562{
1563 /* heart beat timer value look-up table */
1564 /* entry index : (the number of currently connected peers) - 1
1565 entry value : the heart time threshold value in seconds for
1566 detecting ibss peer departure */
1567 static const uint16_t heart_beat_timer[MAX_IBSS_PEERS] = {
1568 4, 4, 4, 4, 4, 4, 4, 4,
1569 8, 8, 8, 8, 8, 8, 8, 8,
1570 12, 12, 12, 12, 12, 12, 12, 12,
1571 16, 16, 16, 16, 16, 16, 16, 16
1572 };
1573
1574 if (peer_num < 1 || peer_num > MAX_IBSS_PEERS)
1575 return 0;
1576
1577 return heart_beat_timer[peer_num - 1];
1578
1579}
1580
1581/**
1582 * wma_adjust_ibss_heart_beat_timer() - set ibss heart beat timer in fw.
1583 * @wma: wma handle
1584 * @vdev_id: vdev id
1585 * @peer_num_delta: peer number delta value
1586 *
1587 * Return: none
1588 */
1589void wma_adjust_ibss_heart_beat_timer(tp_wma_handle wma,
1590 uint8_t vdev_id,
1591 int8_t peer_num_delta)
1592{
1593 ol_txrx_vdev_handle vdev;
1594 int16_t new_peer_num;
1595 uint16_t new_timer_value_sec;
1596 uint32_t new_timer_value_ms;
Govind Singhd76a5b02016-03-08 15:12:14 +05301597 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001598
1599 if (peer_num_delta != 1 && peer_num_delta != -1) {
1600 WMA_LOGE("Invalid peer_num_delta value %d", peer_num_delta);
1601 return;
1602 }
1603
1604 vdev = wma_find_vdev_by_id(wma, vdev_id);
1605 if (!vdev) {
1606 WMA_LOGE("vdev not found : vdev_id %d", vdev_id);
1607 return;
1608 }
1609
1610 new_peer_num = vdev->ibss_peer_num + peer_num_delta;
1611 if (new_peer_num > MAX_IBSS_PEERS || new_peer_num < 0) {
1612 WMA_LOGE("new peer num %d out of valid boundary", new_peer_num);
1613 return;
1614 }
1615
1616 /* adjust peer numbers */
1617 vdev->ibss_peer_num = new_peer_num;
1618
1619 /* reset timer value if all peers departed */
1620 if (new_peer_num == 0) {
1621 vdev->ibss_peer_heart_beat_timer = 0;
1622 return;
1623 }
1624
1625 /* calculate new timer value */
1626 new_timer_value_sec = wma_calc_ibss_heart_beat_timer(new_peer_num);
1627 if (new_timer_value_sec == 0) {
1628 WMA_LOGE("timer value %d is invalid for peer number %d",
1629 new_timer_value_sec, new_peer_num);
1630 return;
1631 }
1632 if (new_timer_value_sec == vdev->ibss_peer_heart_beat_timer) {
1633 WMA_LOGD("timer value %d stays same, no need to notify target",
1634 new_timer_value_sec);
1635 return;
1636 }
1637
1638 /* send new timer value to target */
1639 vdev->ibss_peer_heart_beat_timer = new_timer_value_sec;
1640
1641 new_timer_value_ms = ((uint32_t) new_timer_value_sec) * 1000;
1642
Govind Singhd76a5b02016-03-08 15:12:14 +05301643 status = wma_vdev_set_param(wma->wmi_handle, vdev_id,
1644 WMI_VDEV_PARAM_IBSS_MAX_BCN_LOST_MS,
1645 new_timer_value_ms);
1646 if (QDF_IS_STATUS_ERROR(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001647 WMA_LOGE("Failed to set IBSS link monitoring timer value");
1648 return;
1649 }
1650
1651 WMA_LOGD("Set IBSS link monitor timer: peer_num = %d timer_value = %d",
1652 new_peer_num, new_timer_value_ms);
1653}
1654
1655#endif /* QCA_IBSS_SUPPORT */
1656/**
1657 * wma_set_ibsskey_helper() - cached IBSS key in wma handle
1658 * @wma_handle: wma handle
1659 * @key_info: set bss key info
1660 * @peerMacAddr: peer mac address
1661 *
1662 * Return: none
1663 */
1664static void wma_set_ibsskey_helper(tp_wma_handle wma_handle,
1665 tpSetBssKeyParams key_info,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301666 struct qdf_mac_addr peer_macaddr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001667{
1668 struct wma_set_key_params key_params;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301669 QDF_STATUS status = QDF_STATUS_SUCCESS;
1670 uint32_t i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001671 uint32_t def_key_idx = 0;
1672 ol_txrx_vdev_handle txrx_vdev;
1673
1674 WMA_LOGD("BSS key setup for peer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001675 txrx_vdev = wma_find_vdev_by_id(wma_handle, key_info->smesessionId);
1676 if (!txrx_vdev) {
1677 WMA_LOGE("%s:Invalid vdev handle", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301678 key_info->status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001679 return;
1680 }
1681
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301682 qdf_mem_set(&key_params, sizeof(key_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001683 key_params.vdev_id = key_info->smesessionId;
1684 key_params.key_type = key_info->encType;
1685 key_params.singl_tid_rc = key_info->singleTidRc;
1686 key_params.unicast = false;
1687 ASSERT(wlan_op_mode_ibss == txrx_vdev->opmode);
1688
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301689 qdf_mem_copy(key_params.peer_mac, peer_macaddr.bytes,
Srinivas Girigowdad5965c42015-12-04 13:43:16 -08001690 IEEE80211_ADDR_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001691
1692 if (key_info->numKeys == 0 &&
1693 (key_info->encType == eSIR_ED_WEP40 ||
1694 key_info->encType == eSIR_ED_WEP104)) {
1695 wma_read_cfg_wepkey(wma_handle, key_info->key,
1696 &def_key_idx, &key_info->numKeys);
1697 }
1698
1699 for (i = 0; i < key_info->numKeys; i++) {
1700 if (key_params.key_type != eSIR_ED_NONE &&
1701 !key_info->key[i].keyLength)
1702 continue;
1703 key_params.key_idx = key_info->key[i].keyId;
1704 key_params.key_len = key_info->key[i].keyLength;
1705 if (key_info->encType == eSIR_ED_TKIP) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301706 qdf_mem_copy(key_params.key_data,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001707 key_info->key[i].key, 16);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301708 qdf_mem_copy(&key_params.key_data[16],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001709 &key_info->key[i].key[24], 8);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301710 qdf_mem_copy(&key_params.key_data[24],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001711 &key_info->key[i].key[16], 8);
1712 } else
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301713 qdf_mem_copy((void *)key_params.key_data,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001714 (const void *)key_info->key[i].key,
1715 key_info->key[i].keyLength);
1716
1717 WMA_LOGD("%s: peer bcast key[%d] length %d", __func__, i,
1718 key_info->key[i].keyLength);
1719
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301720 status = wma_setup_install_key_cmd(wma_handle, &key_params,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001721 txrx_vdev->opmode);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301722 if (status == QDF_STATUS_E_NOMEM) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001723 WMA_LOGE("%s:Failed to setup install key buf",
1724 __func__);
1725 return;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301726 } else if (status == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001727 WMA_LOGE("%s:Failed to send install key command",
1728 __func__);
1729 }
1730 }
1731}
1732
1733/**
1734 * wma_set_stakey() - set encryption key
1735 * @wma_handle: wma handle
1736 * @key_info: station key info
1737 *
1738 * This function sets encryption key for WEP/WPA/WPA2
1739 * encryption mode in firmware and send response to upper layer.
1740 *
1741 * Return: none
1742 */
1743void wma_set_stakey(tp_wma_handle wma_handle, tpSetStaKeyParams key_info)
1744{
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301745 int32_t i;
1746 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001747 ol_txrx_pdev_handle txrx_pdev;
1748 ol_txrx_vdev_handle txrx_vdev;
1749 struct ol_txrx_peer_t *peer;
1750 uint8_t num_keys = 0, peer_id;
1751 struct wma_set_key_params key_params;
1752 uint32_t def_key_idx = 0;
1753
1754 WMA_LOGD("STA key setup");
1755
1756 /* Get the txRx Pdev handle */
Anurag Chouhan6d760662016-02-20 16:05:43 +05301757 txrx_pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001758 if (!txrx_pdev) {
1759 WMA_LOGE("%s:Invalid txrx pdev handle", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301760 key_info->status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001761 goto out;
1762 }
1763
Srinivas Girigowdad5965c42015-12-04 13:43:16 -08001764 peer = ol_txrx_find_peer_by_addr(txrx_pdev,
1765 key_info->peer_macaddr.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001766 &peer_id);
1767 if (!peer) {
1768 WMA_LOGE("%s:Invalid peer for key setting", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301769 key_info->status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001770 goto out;
1771 }
1772
1773 txrx_vdev = wma_find_vdev_by_id(wma_handle, key_info->smesessionId);
1774 if (!txrx_vdev) {
1775 WMA_LOGE("%s:TxRx Vdev Handle is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301776 key_info->status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001777 goto out;
1778 }
1779
1780 if (key_info->defWEPIdx == WMA_INVALID_KEY_IDX &&
1781 (key_info->encType == eSIR_ED_WEP40 ||
1782 key_info->encType == eSIR_ED_WEP104) &&
1783 txrx_vdev->opmode != wlan_op_mode_ap) {
1784 wma_read_cfg_wepkey(wma_handle, key_info->key,
1785 &def_key_idx, &num_keys);
1786 key_info->defWEPIdx = def_key_idx;
1787 } else {
1788 num_keys = SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS;
1789 if (key_info->encType != eSIR_ED_NONE) {
1790 for (i = 0; i < num_keys; i++) {
1791 if (key_info->key[i].keyDirection ==
1792 eSIR_TX_DEFAULT) {
1793 key_info->defWEPIdx = i;
1794 break;
1795 }
1796 }
1797 }
1798 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301799 qdf_mem_set(&key_params, sizeof(key_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001800 key_params.vdev_id = key_info->smesessionId;
1801 key_params.key_type = key_info->encType;
1802 key_params.singl_tid_rc = key_info->singleTidRc;
1803 key_params.unicast = true;
1804 key_params.def_key_idx = key_info->defWEPIdx;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301805 qdf_mem_copy((void *)key_params.peer_mac,
Srinivas Girigowdad5965c42015-12-04 13:43:16 -08001806 (const void *)key_info->peer_macaddr.bytes,
1807 IEEE80211_ADDR_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001808 for (i = 0; i < num_keys; i++) {
1809 if (key_params.key_type != eSIR_ED_NONE &&
1810 !key_info->key[i].keyLength)
1811 continue;
1812 if (key_info->encType == eSIR_ED_TKIP) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301813 qdf_mem_copy(key_params.key_data,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001814 key_info->key[i].key, 16);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301815 qdf_mem_copy(&key_params.key_data[16],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001816 &key_info->key[i].key[24], 8);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301817 qdf_mem_copy(&key_params.key_data[24],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001818 &key_info->key[i].key[16], 8);
1819 } else
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301820 qdf_mem_copy(key_params.key_data, key_info->key[i].key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001821 key_info->key[i].keyLength);
1822 if (key_info->encType == eSIR_ED_WPI) {
1823 key_params.key_idx = key_info->key[i].keyId;
1824 key_params.def_key_idx = key_info->key[i].keyId;
1825 } else
1826 key_params.key_idx = i;
1827
1828 key_params.key_len = key_info->key[i].keyLength;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301829 status = wma_setup_install_key_cmd(wma_handle, &key_params,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001830 txrx_vdev->opmode);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301831 if (status == QDF_STATUS_E_NOMEM) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001832 WMA_LOGE("%s:Failed to setup install key buf",
1833 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301834 key_info->status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001835 goto out;
1836 }
1837
1838 WMA_LOGD("%s: peer unicast key[%d] %d ", __func__, i,
1839 key_info->key[i].keyLength);
1840
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301841 if (status == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001842 WMA_LOGE("%s:Failed to send install key command",
1843 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301844 key_info->status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001845 goto out;
1846 }
1847 }
1848
1849 /* In IBSS mode, set the BSS KEY for this peer
1850 * BSS key is supposed to be cache into wma_handle
1851 */
1852 if (wlan_op_mode_ibss == txrx_vdev->opmode) {
1853 wma_set_ibsskey_helper(wma_handle, &wma_handle->ibsskey_info,
Srinivas Girigowdad5965c42015-12-04 13:43:16 -08001854 key_info->peer_macaddr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001855 }
1856
1857 /* TODO: Should we wait till we get HTT_T2H_MSG_TYPE_SEC_IND? */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301858 key_info->status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001859out:
1860 if (key_info->sendRsp)
1861 wma_send_msg(wma_handle, WMA_SET_STAKEY_RSP, (void *)key_info,
1862 0);
1863}
1864
1865/**
1866 * wma_process_update_edca_param_req() - update EDCA params
1867 * @handle: wma handle
1868 * @edca_params: edca parameters
1869 *
1870 * This function updates EDCA parameters to the target
1871 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05301872 * Return: QDF Status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001873 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301874QDF_STATUS wma_process_update_edca_param_req(WMA_HANDLE handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001875 tEdcaParams *edca_params)
1876{
1877 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301878 wmi_wmm_vparams wmm_param[WME_NUM_AC];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001879 tSirMacEdcaParamRecord *edca_record;
1880 int ac;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001881 ol_txrx_pdev_handle pdev;
1882 struct ol_tx_wmm_param_t ol_tx_wmm_param;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301883 uint8_t vdev_id;
1884 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001885
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301886 vdev_id = edca_params->bssIdx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001887
1888 for (ac = 0; ac < WME_NUM_AC; ac++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001889 switch (ac) {
1890 case WME_AC_BE:
1891 edca_record = &edca_params->acbe;
1892 break;
1893 case WME_AC_BK:
1894 edca_record = &edca_params->acbk;
1895 break;
1896 case WME_AC_VI:
1897 edca_record = &edca_params->acvi;
1898 break;
1899 case WME_AC_VO:
1900 edca_record = &edca_params->acvo;
1901 break;
1902 default:
1903 goto fail;
1904 }
1905
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301906 wma_update_edca_params_for_ac(edca_record, &wmm_param[ac], ac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001907
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301908 ol_tx_wmm_param.ac[ac].aifs = wmm_param[ac].aifs;
1909 ol_tx_wmm_param.ac[ac].cwmin = wmm_param[ac].cwmin;
1910 ol_tx_wmm_param.ac[ac].cwmax = wmm_param[ac].cwmax;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001911 }
1912
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301913 status = wmi_unified_process_update_edca_param(wma_handle->wmi_handle,
1914 vdev_id, wmm_param);
1915 if (status == QDF_STATUS_E_NOMEM)
1916 return status;
1917 else if (status == QDF_STATUS_E_FAILURE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001918 goto fail;
1919
Anurag Chouhan6d760662016-02-20 16:05:43 +05301920 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Himanshu Agarwal94045e42015-10-19 19:16:19 +05301921 if (pdev)
1922 ol_txrx_set_wmm_param(pdev, ol_tx_wmm_param);
1923 else
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301924 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001925
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301926 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001927
1928fail:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001929 WMA_LOGE("%s: Failed to set WMM Paremeters", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301930 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001931}
1932
1933/**
1934 * wmi_unified_probe_rsp_tmpl_send() - send probe response template to fw
1935 * @wma: wma handle
1936 * @vdev_id: vdev id
1937 * @probe_rsp_info: probe response info
1938 *
1939 * Return: 0 for success or error code
1940 */
1941static int wmi_unified_probe_rsp_tmpl_send(tp_wma_handle wma,
1942 uint8_t vdev_id,
1943 tpSendProbeRespParams probe_rsp_info)
1944{
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301945 uint8_t *frm;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001946 uint64_t adjusted_tsf_le;
1947 struct ieee80211_frame *wh;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301948 struct wmi_probe_resp_params params;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001949
1950 WMA_LOGD(FL("Send probe response template for vdev %d"), vdev_id);
1951
1952 frm = probe_rsp_info->pProbeRespTemplate;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301953
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001954 /*
1955 * Make the TSF offset negative so probe response in the same
1956 * staggered batch have the same TSF.
1957 */
1958 adjusted_tsf_le = cpu_to_le64(0ULL -
1959 wma->interfaces[vdev_id].tsfadjust);
1960 /* Update the timstamp in the probe response buffer with adjusted TSF */
1961 wh = (struct ieee80211_frame *)frm;
1962 A_MEMCPY(&wh[1], &adjusted_tsf_le, sizeof(adjusted_tsf_le));
1963
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301964 params.pProbeRespTemplate = probe_rsp_info->pProbeRespTemplate;
1965 params.probeRespTemplateLen = probe_rsp_info->probeRespTemplateLen;
1966 qdf_mem_copy(params.bssId, probe_rsp_info->bssId,
1967 WMI_ETH_LEN);
1968 qdf_mem_copy(params.ucProxyProbeReqValidIEBmap,
1969 probe_rsp_info->ucProxyProbeReqValidIEBmap,
1970 8 * sizeof(uint32_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001971
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301972 return wmi_unified_probe_rsp_tmpl_send_cmd(wma->wmi_handle, vdev_id,
1973 &params, frm);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001974}
1975
1976/**
Govind Singh61ad2622016-02-22 17:25:02 +05301977 * wma_unified_bcn_tmpl_send() - send beacon template to fw
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001978 * @wma:wma handle
1979 * @vdev_id: vdev id
1980 * @bcn_info: beacon info
1981 * @bytes_to_strip: bytes to strip
1982 *
Govind Singh61ad2622016-02-22 17:25:02 +05301983 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001984 */
Govind Singh61ad2622016-02-22 17:25:02 +05301985static QDF_STATUS wma_unified_bcn_tmpl_send(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001986 uint8_t vdev_id,
Govind Singh61ad2622016-02-22 17:25:02 +05301987 const tpSendbeaconParams bcn_info,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001988 uint8_t bytes_to_strip)
1989{
Govind Singh61ad2622016-02-22 17:25:02 +05301990 struct beacon_params params = {0};
1991 uint32_t tmpl_len, tmpl_len_aligned;
1992 uint8_t *frm;
1993 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001994 uint8_t *p2p_ie;
1995 uint16_t p2p_ie_len = 0;
1996 uint64_t adjusted_tsf_le;
1997 struct ieee80211_frame *wh;
1998
1999 WMA_LOGD("Send beacon template for vdev %d", vdev_id);
2000
2001 if (bcn_info->p2pIeOffset) {
2002 p2p_ie = bcn_info->beacon + bcn_info->p2pIeOffset;
2003 p2p_ie_len = (uint16_t) p2p_ie[1] + 2;
2004 }
2005
2006 /*
2007 * XXX: The first byte of beacon buffer contains beacon length
2008 * only when UMAC in sending the beacon template. In othercases
2009 * (ex: from tbtt update) beacon length is read from beacon
2010 * information.
2011 */
2012 if (bytes_to_strip)
2013 tmpl_len = *(uint32_t *) &bcn_info->beacon[0];
2014 else
2015 tmpl_len = bcn_info->beaconLength;
2016 if (p2p_ie_len) {
2017 tmpl_len -= (uint32_t) p2p_ie_len;
2018 }
2019
2020 frm = bcn_info->beacon + bytes_to_strip;
2021 tmpl_len_aligned = roundup(tmpl_len, sizeof(A_UINT32));
2022 /*
2023 * Make the TSF offset negative so beacons in the same
2024 * staggered batch have the same TSF.
2025 */
2026 adjusted_tsf_le = cpu_to_le64(0ULL -
2027 wma->interfaces[vdev_id].tsfadjust);
2028 /* Update the timstamp in the beacon buffer with adjusted TSF */
2029 wh = (struct ieee80211_frame *)frm;
2030 A_MEMCPY(&wh[1], &adjusted_tsf_le, sizeof(adjusted_tsf_le));
2031
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002032
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002033
Govind Singh61ad2622016-02-22 17:25:02 +05302034 params.vdev_id = vdev_id;
2035 params.tim_ie_offset = bcn_info->timIeOffset - bytes_to_strip;
2036 params.tmpl_len = tmpl_len;
2037 params.frm = frm;
2038 params.tmpl_len_aligned = tmpl_len_aligned;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002039
Govind Singh61ad2622016-02-22 17:25:02 +05302040 ret = wmi_unified_beacon_send_cmd(wma->wmi_handle,
2041 &params);
2042 if (QDF_IS_STATUS_ERROR(ret)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002043 WMA_LOGE("%s: Failed to send bcn tmpl: %d", __func__, ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002044 }
2045
2046 return ret;
2047}
2048
2049/**
2050 * wma_store_bcn_tmpl() - store beacon template
2051 * @wma: wma handle
2052 * @vdev_id: vdev id
2053 * @bcn_info: beacon params
2054 *
2055 * This function stores beacon template locally.
2056 * This will send to target on the reception of
2057 * SWBA event.
2058 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302059 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002060 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302061QDF_STATUS wma_store_bcn_tmpl(tp_wma_handle wma, uint8_t vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002062 tpSendbeaconParams bcn_info)
2063{
2064 struct beacon_info *bcn;
2065 uint32_t len;
2066 uint8_t *bcn_payload;
2067 struct beacon_tim_ie *tim_ie;
2068
2069 bcn = wma->interfaces[vdev_id].beacon;
2070 if (!bcn || !bcn->buf) {
2071 WMA_LOGE("%s: Memory is not allocated to hold bcn template",
2072 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302073 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002074 }
2075
2076 len = *(u32 *) &bcn_info->beacon[0];
2077 if (len > WMA_BCN_BUF_MAX_SIZE) {
2078 WMA_LOGE("%s: Received beacon len %d exceeding max limit %d",
2079 __func__, len, WMA_BCN_BUF_MAX_SIZE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302080 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002081 }
2082 WMA_LOGD("%s: Storing received beacon template buf to local buffer",
2083 __func__);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302084 qdf_spin_lock_bh(&bcn->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002085
2086 /*
2087 * Copy received beacon template content in local buffer.
2088 * this will be send to target on the reception of SWBA
2089 * event from target.
2090 */
Nirav Shahcbc6d722016-03-01 16:24:53 +05302091 qdf_nbuf_trim_tail(bcn->buf, qdf_nbuf_len(bcn->buf));
2092 memcpy(qdf_nbuf_data(bcn->buf),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002093 bcn_info->beacon + 4 /* Exclude beacon length field */,
2094 len);
2095 if (bcn_info->timIeOffset > 3) {
2096 bcn->tim_ie_offset = bcn_info->timIeOffset - 4;
2097 } else {
2098 bcn->tim_ie_offset = bcn_info->timIeOffset;
2099 }
2100
2101 if (bcn_info->p2pIeOffset > 3) {
2102 bcn->p2p_ie_offset = bcn_info->p2pIeOffset - 4;
2103 } else {
2104 bcn->p2p_ie_offset = bcn_info->p2pIeOffset;
2105 }
Nirav Shahcbc6d722016-03-01 16:24:53 +05302106 bcn_payload = qdf_nbuf_data(bcn->buf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002107 if (bcn->tim_ie_offset) {
2108 tim_ie =
2109 (struct beacon_tim_ie *)(&bcn_payload[bcn->tim_ie_offset]);
2110 /*
2111 * Intial Value of bcn->dtim_count will be 0.
2112 * But if the beacon gets updated then current dtim
2113 * count will be restored
2114 */
2115 tim_ie->dtim_count = bcn->dtim_count;
2116 tim_ie->tim_bitctl = 0;
2117 }
2118
Nirav Shahcbc6d722016-03-01 16:24:53 +05302119 qdf_nbuf_put_tail(bcn->buf, len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002120 bcn->len = len;
2121
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302122 qdf_spin_unlock_bh(&bcn->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002123
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302124 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002125}
2126
2127/**
2128 * wma_tbttoffset_update_event_handler() - tbtt offset update handler
2129 * @handle: wma handle
2130 * @event: event buffer
2131 * @len: data length
2132 *
2133 * Return: 0 for success or error code
2134 */
2135int wma_tbttoffset_update_event_handler(void *handle, uint8_t *event,
2136 uint32_t len)
2137{
2138 tp_wma_handle wma = (tp_wma_handle) handle;
2139 WMI_TBTTOFFSET_UPDATE_EVENTID_param_tlvs *param_buf;
2140 wmi_tbtt_offset_event_fixed_param *tbtt_offset_event;
2141 struct wma_txrx_node *intf;
2142 struct beacon_info *bcn;
2143 tSendbeaconParams bcn_info;
2144 uint32_t *adjusted_tsf = NULL;
2145 uint32_t if_id = 0, vdev_map;
2146
2147 if (!wma) {
2148 WMA_LOGE("Invalid wma handle");
2149 return -EINVAL;
2150 }
2151
2152 param_buf = (WMI_TBTTOFFSET_UPDATE_EVENTID_param_tlvs *) event;
2153 if (!param_buf) {
2154 WMA_LOGE("Invalid tbtt update event buffer");
2155 return -EINVAL;
2156 }
2157
2158 tbtt_offset_event = param_buf->fixed_param;
2159 intf = wma->interfaces;
2160 vdev_map = tbtt_offset_event->vdev_map;
2161 adjusted_tsf = param_buf->tbttoffset_list;
2162 if (!adjusted_tsf) {
2163 WMA_LOGE("%s: Invalid adjusted_tsf", __func__);
2164 return -EINVAL;
2165 }
2166
2167 for (; (vdev_map); vdev_map >>= 1, if_id++) {
2168 if (!(vdev_map & 0x1) || (!(intf[if_id].handle)))
2169 continue;
2170
2171 bcn = intf[if_id].beacon;
2172 if (!bcn) {
2173 WMA_LOGE("%s: Invalid beacon", __func__);
2174 return -EINVAL;
2175 }
2176 if (!bcn->buf) {
2177 WMA_LOGE("%s: Invalid beacon buffer", __func__);
2178 return -EINVAL;
2179 }
2180 /* Save the adjusted TSF */
2181 intf[if_id].tsfadjust = adjusted_tsf[if_id];
2182
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302183 qdf_spin_lock_bh(&bcn->lock);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302184 qdf_mem_zero(&bcn_info, sizeof(bcn_info));
Nirav Shahcbc6d722016-03-01 16:24:53 +05302185 bcn_info.beacon = qdf_nbuf_data(bcn->buf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002186 bcn_info.p2pIeOffset = bcn->p2p_ie_offset;
2187 bcn_info.beaconLength = bcn->len;
2188 bcn_info.timIeOffset = bcn->tim_ie_offset;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302189 qdf_spin_unlock_bh(&bcn->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002190
2191 /* Update beacon template in firmware */
Govind Singh61ad2622016-02-22 17:25:02 +05302192 wma_unified_bcn_tmpl_send(wma, if_id, &bcn_info, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002193 }
2194 return 0;
2195}
2196
2197/**
2198 * wma_p2p_go_set_beacon_ie() - set beacon IE for p2p go
2199 * @wma_handle: wma handle
2200 * @vdev_id: vdev id
2201 * @p2pIe: p2p IE
2202 *
2203 * Return: 0 for success or error code
2204 */
2205static int wma_p2p_go_set_beacon_ie(t_wma_handle *wma_handle,
2206 A_UINT32 vdev_id, uint8_t *p2pIe)
2207{
Himanshu Agarwal009f1572016-03-09 17:26:02 +05302208 if (!wma_handle) {
2209 WMA_LOGE("%s: wma handle is NULL", __func__);
2210 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002211 }
2212
Himanshu Agarwal009f1572016-03-09 17:26:02 +05302213 return wmi_unified_p2p_go_set_beacon_ie_cmd(wma_handle->wmi_handle,
2214 vdev_id, p2pIe);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002215}
2216
2217/**
2218 * wma_send_probe_rsp_tmpl() - send probe resp template
2219 * @wma: wma handle
2220 * @probe_rsp_info: probe response info
2221 *
2222 * This funciton sends probe response template to fw which
2223 * firmware will use in case of probe response offload.
2224 *
2225 * Return: none
2226 */
2227void wma_send_probe_rsp_tmpl(tp_wma_handle wma,
2228 tpSendProbeRespParams probe_rsp_info)
2229{
2230 ol_txrx_vdev_handle vdev;
2231 uint8_t vdev_id;
2232 tpAniProbeRspStruct probe_rsp;
2233
2234 if (!probe_rsp_info) {
2235 WMA_LOGE(FL("probe_rsp_info is NULL"));
2236 return;
2237 }
2238
2239 probe_rsp = (tpAniProbeRspStruct) (probe_rsp_info->pProbeRespTemplate);
2240 if (!probe_rsp) {
2241 WMA_LOGE(FL("probe_rsp is NULL"));
2242 return;
2243 }
2244
2245 vdev = wma_find_vdev_by_addr(wma, probe_rsp->macHdr.sa, &vdev_id);
2246 if (!vdev) {
2247 WMA_LOGE(FL("failed to get vdev handle"));
2248 return;
2249 }
2250
2251 if (WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
2252 WMI_SERVICE_BEACON_OFFLOAD)) {
2253 WMA_LOGI("Beacon Offload Enabled Sending Unified command");
2254 if (wmi_unified_probe_rsp_tmpl_send(wma, vdev_id,
2255 probe_rsp_info) < 0) {
2256 WMA_LOGE(FL("wmi_unified_probe_rsp_tmpl_send Failed "));
2257 return;
2258 }
2259 }
2260}
2261
2262/**
2263 * wma_send_beacon() - send beacon template
2264 * @wma: wma handle
2265 * @bcn_info: beacon info
2266 *
2267 * This funciton store beacon template locally and
2268 * update keep alive parameters
2269 *
2270 * Return: none
2271 */
2272void wma_send_beacon(tp_wma_handle wma, tpSendbeaconParams bcn_info)
2273{
2274 ol_txrx_vdev_handle vdev;
2275 uint8_t vdev_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302276 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002277 uint8_t *p2p_ie;
2278 tpAniBeaconStruct beacon;
Govind Singhd76a5b02016-03-08 15:12:14 +05302279 struct vdev_up_params param = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002280
2281 beacon = (tpAniBeaconStruct) (bcn_info->beacon);
2282 vdev = wma_find_vdev_by_addr(wma, beacon->macHdr.sa, &vdev_id);
2283 if (!vdev) {
2284 WMA_LOGE("%s : failed to get vdev handle", __func__);
2285 return;
2286 }
2287
2288 if (WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
2289 WMI_SERVICE_BEACON_OFFLOAD)) {
2290 WMA_LOGI("Beacon Offload Enabled Sending Unified command");
Govind Singh61ad2622016-02-22 17:25:02 +05302291 status = wma_unified_bcn_tmpl_send(wma, vdev_id, bcn_info, 4);
2292 if (QDF_IS_STATUS_ERROR(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002293 WMA_LOGE("%s : wmi_unified_bcn_tmpl_send Failed ",
2294 __func__);
2295 return;
2296 }
2297
2298 if (bcn_info->p2pIeOffset) {
2299 p2p_ie = bcn_info->beacon + bcn_info->p2pIeOffset;
2300 WMA_LOGI
2301 (" %s: p2pIe is present - vdev_id %hu, p2p_ie = %p, p2p ie len = %hu",
2302 __func__, vdev_id, p2p_ie, p2p_ie[1]);
2303 if (wma_p2p_go_set_beacon_ie(wma, vdev_id, p2p_ie) < 0) {
2304 WMA_LOGE
2305 ("%s : wmi_unified_bcn_tmpl_send Failed ",
2306 __func__);
2307 return;
2308 }
2309 }
2310 }
2311 status = wma_store_bcn_tmpl(wma, vdev_id, bcn_info);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302312 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002313 WMA_LOGE("%s : wma_store_bcn_tmpl Failed", __func__);
2314 return;
2315 }
2316 if (!wma->interfaces[vdev_id].vdev_up) {
Govind Singhd76a5b02016-03-08 15:12:14 +05302317 param.vdev_id = vdev_id;
2318 param.assoc_id = 0;
2319 status = wmi_unified_vdev_up_send(wma->wmi_handle,
2320 bcn_info->bssId,
2321 &param);
2322 if (QDF_IS_STATUS_ERROR(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002323 WMA_LOGE("%s : failed to send vdev up", __func__);
2324 return;
2325 }
2326 wma->interfaces[vdev_id].vdev_up = true;
2327 wma_set_sap_keepalive(wma, vdev_id);
2328 }
2329}
2330
2331/**
2332 * wma_set_keepalive_req() - send keep alive request to fw
2333 * @wma: wma handle
2334 * @keepalive: keep alive parameters
2335 *
2336 * Return: none
2337 */
2338void wma_set_keepalive_req(tp_wma_handle wma,
2339 tSirKeepAliveReq *keepalive)
2340{
2341 WMA_LOGD("KEEPALIVE:PacketType:%d", keepalive->packetType);
2342 wma_set_sta_keep_alive(wma, keepalive->sessionId,
2343 keepalive->packetType,
2344 keepalive->timePeriod,
2345 keepalive->hostIpv4Addr,
Srinivas Girigowda9c330a92015-11-24 12:28:25 -08002346 keepalive->destIpv4Addr,
2347 keepalive->dest_macaddr.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002348
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302349 qdf_mem_free(keepalive);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002350}
2351
2352/**
2353 * wma_beacon_miss_handler() - beacon miss event handler
2354 * @wma: wma handle
2355 * @vdev_id: vdev id
2356 *
2357 * This function send beacon miss indication to upper layers.
2358 *
2359 * Return: none
2360 */
2361void wma_beacon_miss_handler(tp_wma_handle wma, uint32_t vdev_id)
2362{
2363 tSirSmeMissedBeaconInd *beacon_miss_ind;
2364
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302365 beacon_miss_ind = (tSirSmeMissedBeaconInd *) qdf_mem_malloc
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002366 (sizeof(tSirSmeMissedBeaconInd));
2367
2368 if (NULL == beacon_miss_ind) {
2369 WMA_LOGE("%s: Memory allocation failure", __func__);
2370 return;
2371 }
2372 beacon_miss_ind->messageType = WMA_MISSED_BEACON_IND;
2373 beacon_miss_ind->length = sizeof(tSirSmeMissedBeaconInd);
2374 beacon_miss_ind->bssIdx = vdev_id;
2375
2376 wma_send_msg(wma, WMA_MISSED_BEACON_IND, (void *)beacon_miss_ind, 0);
2377}
2378
2379/**
2380 * wma_mgmt_tx_completion_handler() - wma mgmt Tx completion event handler
2381 * @handle: wma handle
2382 * @cmpl_event_params: completion event handler data
2383 * @len: length of @cmpl_event_params
2384 *
2385 * Return: 0 on success; error number otherwise
2386 */
2387
2388int wma_mgmt_tx_completion_handler(void *handle, uint8_t *cmpl_event_params,
2389 uint32_t len)
2390{
2391 tp_wma_handle wma_handle = (tp_wma_handle)handle;
2392 WMI_MGMT_TX_COMPLETION_EVENTID_param_tlvs *param_buf;
2393 wmi_mgmt_tx_compl_event_fixed_param *cmpl_params;
2394 struct wmi_desc_t *wmi_desc;
2395
Anurag Chouhan6d760662016-02-20 16:05:43 +05302396 ol_txrx_pdev_handle pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002397
2398 param_buf = (WMI_MGMT_TX_COMPLETION_EVENTID_param_tlvs *)
2399 cmpl_event_params;
2400 if (!param_buf && !wma_handle) {
2401 WMA_LOGE("%s: Invalid mgmt Tx completion event", __func__);
2402 return -EINVAL;
2403 }
2404 cmpl_params = param_buf->fixed_param;
2405
2406 WMA_LOGI("%s: status:%d wmi_desc_id:%d", __func__, cmpl_params->status,
2407 cmpl_params->desc_id);
2408
2409 wmi_desc = (struct wmi_desc_t *)
2410 (&wma_handle->wmi_desc_pool.array[cmpl_params->desc_id]);
2411
2412 if (!wmi_desc) {
2413 WMA_LOGE("%s: Invalid wmi desc", __func__);
2414 return -EINVAL;
2415 }
2416
2417 if (wmi_desc->nbuf)
Nirav Shahcbc6d722016-03-01 16:24:53 +05302418 qdf_nbuf_unmap_single(pdev->osdev, wmi_desc->nbuf,
Anurag Chouhan6d760662016-02-20 16:05:43 +05302419 QDF_DMA_TO_DEVICE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002420 if (wmi_desc->tx_cmpl_cb)
2421 wmi_desc->tx_cmpl_cb(wma_handle->mac_context,
2422 wmi_desc->nbuf, 1);
2423
2424 if (wmi_desc->ota_post_proc_cb)
2425 wmi_desc->ota_post_proc_cb((tpAniSirGlobal)
2426 wma_handle->mac_context,
2427 cmpl_params->status);
2428
2429 wmi_desc_put(wma_handle, wmi_desc);
2430
2431 return 0;
2432}
2433
2434/**
2435 * wma_process_update_opmode() - process update VHT opmode cmd from UMAC
2436 * @wma_handle: wma handle
2437 * @update_vht_opmode: vht opmode
2438 *
2439 * Return: none
2440 */
2441void wma_process_update_opmode(tp_wma_handle wma_handle,
2442 tUpdateVHTOpMode *update_vht_opmode)
2443{
2444 WMA_LOGD("%s: opMode = %d", __func__, update_vht_opmode->opMode);
2445
2446 wma_set_peer_param(wma_handle, update_vht_opmode->peer_mac,
2447 WMI_PEER_CHWIDTH, update_vht_opmode->opMode,
2448 update_vht_opmode->smesessionId);
2449}
2450
2451/**
2452 * wma_process_update_rx_nss() - process update RX NSS cmd from UMAC
2453 * @wma_handle: wma handle
2454 * @update_rx_nss: rx nss value
2455 *
2456 * Return: none
2457 */
2458void wma_process_update_rx_nss(tp_wma_handle wma_handle,
2459 tUpdateRxNss *update_rx_nss)
2460{
2461 struct wma_txrx_node *intr =
2462 &wma_handle->interfaces[update_rx_nss->smesessionId];
2463 int rx_nss = update_rx_nss->rxNss;
2464
2465 wma_update_txrx_chainmask(wma_handle->num_rf_chains, &rx_nss);
2466
2467 intr->nss = (uint8_t)rx_nss;
2468 update_rx_nss->rxNss = (uint32_t)rx_nss;
2469
2470 WMA_LOGD("%s: Rx Nss = %d", __func__, update_rx_nss->rxNss);
2471
2472 wma_set_peer_param(wma_handle, update_rx_nss->peer_mac,
2473 WMI_PEER_NSS, update_rx_nss->rxNss,
2474 update_rx_nss->smesessionId);
2475}
2476
2477#ifdef WLAN_FEATURE_11AC
2478/**
2479 * wma_process_update_membership() - process update group membership cmd
2480 * @wma_handle: wma handle
2481 * @membership: group membership info
2482 *
2483 * Return: none
2484 */
2485void wma_process_update_membership(tp_wma_handle wma_handle,
2486 tUpdateMembership *membership)
2487{
2488 WMA_LOGD("%s: membership = %x ", __func__, membership->membership);
2489
2490 wma_set_peer_param(wma_handle, membership->peer_mac,
2491 WMI_PEER_MEMBERSHIP, membership->membership,
2492 membership->smesessionId);
2493}
2494
2495/**
2496 * wma_process_update_userpos() - process update user pos cmd from UMAC
2497 * @wma_handle: wma handle
2498 * @userpos: user pos value
2499 *
2500 * Return: none
2501 */
2502void wma_process_update_userpos(tp_wma_handle wma_handle,
2503 tUpdateUserPos *userpos)
2504{
2505 WMA_LOGD("%s: userPos = %x ", __func__, userpos->userPos);
2506
2507 wma_set_peer_param(wma_handle, userpos->peer_mac,
2508 WMI_PEER_USERPOS, userpos->userPos,
2509 userpos->smesessionId);
2510
2511 /* Now that membership/userpos is updated in fw,
2512 * enable GID PPS.
2513 */
2514 wma_set_ppsconfig(userpos->smesessionId, WMA_VHT_PPS_GID_MATCH, 1);
2515
2516}
2517#endif /* WLAN_FEATURE_11AC */
2518
2519/**
2520 * wma_set_htconfig() - set ht config parameters to target
2521 * @vdev_id: vdev id
2522 * @ht_capab: ht capablity
2523 * @value: value of ht param
2524 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302525 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002526 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302527QDF_STATUS wma_set_htconfig(uint8_t vdev_id, uint16_t ht_capab, int value)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002528{
Anurag Chouhan6d760662016-02-20 16:05:43 +05302529 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
Govind Singhd76a5b02016-03-08 15:12:14 +05302530 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002531
2532 if (NULL == wma) {
2533 WMA_LOGE("%s: Failed to get wma", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302534 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002535 }
2536
2537 switch (ht_capab) {
2538 case WNI_CFG_HT_CAP_INFO_ADVANCE_CODING:
Govind Singhd76a5b02016-03-08 15:12:14 +05302539 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002540 WMI_VDEV_PARAM_LDPC,
2541 value);
2542 break;
2543 case WNI_CFG_HT_CAP_INFO_TX_STBC:
Govind Singhd76a5b02016-03-08 15:12:14 +05302544 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002545 WMI_VDEV_PARAM_TX_STBC,
2546 value);
2547 break;
2548 case WNI_CFG_HT_CAP_INFO_RX_STBC:
Govind Singhd76a5b02016-03-08 15:12:14 +05302549 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002550 WMI_VDEV_PARAM_RX_STBC,
2551 value);
2552 break;
2553 case WNI_CFG_HT_CAP_INFO_SHORT_GI_20MHZ:
2554 case WNI_CFG_HT_CAP_INFO_SHORT_GI_40MHZ:
2555 WMA_LOGE("%s: ht_capab = %d, value = %d", __func__, ht_capab,
2556 value);
Govind Singhd76a5b02016-03-08 15:12:14 +05302557 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002558 WMI_VDEV_PARAM_SGI, value);
Govind Singhd76a5b02016-03-08 15:12:14 +05302559 if (ret == QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002560 wma->interfaces[vdev_id].config.shortgi = value;
2561 break;
2562 default:
2563 WMA_LOGE("%s:INVALID HT CONFIG", __func__);
2564 }
2565
Govind Singhd76a5b02016-03-08 15:12:14 +05302566 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002567}
2568
2569/**
2570 * wma_hidden_ssid_vdev_restart() - vdev restart for hidden ssid
2571 * @wma_handle: wma handle
2572 * @pReq: hidden ssid vdev restart request
2573 *
2574 * Return: none
2575 */
2576void wma_hidden_ssid_vdev_restart(tp_wma_handle wma_handle,
2577 tHalHiddenSsidVdevRestart *pReq)
2578{
2579 struct wma_txrx_node *intr = wma_handle->interfaces;
2580
2581 if ((pReq->sessionId !=
2582 intr[pReq->sessionId].vdev_restart_params.vdev_id)
2583 || !((intr[pReq->sessionId].type == WMI_VDEV_TYPE_AP)
2584 && (intr[pReq->sessionId].sub_type == 0))) {
2585 WMA_LOGE("%s : invalid session id", __func__);
2586 return;
2587 }
2588
2589 intr[pReq->sessionId].vdev_restart_params.ssidHidden = pReq->ssidHidden;
Anurag Chouhan8e0ccd32016-02-19 15:30:20 +05302590 qdf_atomic_set(&intr[pReq->sessionId].vdev_restart_params.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002591 hidden_ssid_restart_in_progress, 1);
2592
2593 /* vdev stop -> vdev restart -> vdev up */
2594 WMA_LOGD("%s, vdev_id: %d, pausing tx_ll_queue for VDEV_STOP",
2595 __func__, pReq->sessionId);
2596 ol_txrx_vdev_pause(wma_handle->interfaces[pReq->sessionId].handle,
2597 OL_TXQ_PAUSE_REASON_VDEV_STOP);
2598 wma_handle->interfaces[pReq->sessionId].pause_bitmap |=
2599 (1 << PAUSE_TYPE_HOST);
2600 if (wmi_unified_vdev_stop_send(wma_handle->wmi_handle, pReq->sessionId)) {
2601 WMA_LOGE("%s: %d Failed to send vdev stop", __func__, __LINE__);
Anurag Chouhan8e0ccd32016-02-19 15:30:20 +05302602 qdf_atomic_set(&intr[pReq->sessionId].vdev_restart_params.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002603 hidden_ssid_restart_in_progress, 0);
2604 return;
2605 }
2606}
2607
2608
2609#ifdef WLAN_FEATURE_11W
2610
2611/**
2612 * wma_extract_ccmp_pn() - extract 6 byte PN from the CCMP header
2613 * @ccmp_ptr: CCMP header
2614 *
2615 * Return: PN extracted from header.
2616 */
2617static uint64_t wma_extract_ccmp_pn(uint8_t *ccmp_ptr)
2618{
2619 uint8_t rsvd, key, pn[6];
2620 uint64_t new_pn;
2621
2622 /*
2623 * +-----+-----+------+----------+-----+-----+-----+-----+
2624 * | PN0 | PN1 | rsvd | rsvd/key | PN2 | PN3 | PN4 | PN5 |
2625 * +-----+-----+------+----------+-----+-----+-----+-----+
2626 * CCMP Header Format
2627 */
2628
2629 /* Extract individual bytes */
2630 pn[0] = (uint8_t) *ccmp_ptr;
2631 pn[1] = (uint8_t) *(ccmp_ptr + 1);
2632 rsvd = (uint8_t) *(ccmp_ptr + 2);
2633 key = (uint8_t) *(ccmp_ptr + 3);
2634 pn[2] = (uint8_t) *(ccmp_ptr + 4);
2635 pn[3] = (uint8_t) *(ccmp_ptr + 5);
2636 pn[4] = (uint8_t) *(ccmp_ptr + 6);
2637 pn[5] = (uint8_t) *(ccmp_ptr + 7);
2638
2639 /* Form 6 byte PN with 6 individual bytes of PN */
2640 new_pn = ((uint64_t) pn[5] << 40) |
2641 ((uint64_t) pn[4] << 32) |
2642 ((uint64_t) pn[3] << 24) |
2643 ((uint64_t) pn[2] << 16) |
2644 ((uint64_t) pn[1] << 8) | ((uint64_t) pn[0] << 0);
2645
2646 WMA_LOGE("PN of received packet is %llu", new_pn);
2647 return new_pn;
2648}
2649
2650/**
2651 * wma_is_ccmp_pn_replay_attack() - detect replay attacking using PN in CCMP
2652 * @cds_ctx: cds context
2653 * @wh: 802.11 frame header
2654 * @ccmp_ptr: CCMP frame header
2655 *
2656 * Return: true/false
2657 */
2658static bool
2659wma_is_ccmp_pn_replay_attack(void *cds_ctx, struct ieee80211_frame *wh,
2660 uint8_t *ccmp_ptr)
2661{
2662 ol_txrx_pdev_handle pdev;
2663 ol_txrx_vdev_handle vdev;
2664 ol_txrx_peer_handle peer;
2665 uint8_t vdev_id, peer_id;
2666 uint8_t *last_pn_valid;
2667 uint64_t *last_pn, new_pn;
2668 uint32_t *rmf_pn_replays;
2669
Anurag Chouhan6d760662016-02-20 16:05:43 +05302670 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002671 if (!pdev) {
2672 WMA_LOGE("%s: Failed to find pdev", __func__);
2673 return true;
2674 }
2675
Mukul Sharmaa748fbb2015-12-01 19:51:36 +05302676 vdev = wma_find_vdev_by_bssid(cds_ctx, wh->i_addr3, &vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002677 if (!vdev) {
2678 WMA_LOGE("%s: Failed to find vdev", __func__);
2679 return true;
2680 }
2681
2682 /* Retrieve the peer based on vdev and addr */
2683 peer = ol_txrx_find_peer_by_addr_and_vdev(pdev, vdev, wh->i_addr2,
2684 &peer_id);
2685
2686 if (NULL == peer) {
2687 WMA_LOGE("%s: Failed to find peer, Not able to validate PN",
2688 __func__);
2689 return true;
2690 }
2691
2692 new_pn = wma_extract_ccmp_pn(ccmp_ptr);
2693 last_pn_valid = &peer->last_rmf_pn_valid;
2694 last_pn = &peer->last_rmf_pn;
2695 rmf_pn_replays = &peer->rmf_pn_replays;
2696
2697 if (*last_pn_valid) {
2698 if (new_pn > *last_pn) {
2699 *last_pn = new_pn;
2700 WMA_LOGE("%s: PN validation successful", __func__);
2701 } else {
2702 WMA_LOGE("%s: PN Replay attack detected", __func__);
2703 /* per 11W amendment, keeping track of replay attacks */
2704 *rmf_pn_replays += 1;
2705 return true;
2706 }
2707 } else {
2708 *last_pn_valid = 1;
2709 *last_pn = new_pn;
2710 }
2711
2712 return false;
2713}
2714
2715/**
mukul sharma72c8b222015-09-04 17:02:01 +05302716 * wma_process_bip() - process mmie in rmf frame
2717 * @wma_handle: wma handle
2718 * @iface: txrx node
2719 * @wh: 80211 frame
2720 * @wbuf: Buffer
2721 *
2722 * Return: 0 for success or error code
2723 */
2724
2725static
2726int wma_process_bip(tp_wma_handle wma_handle,
2727 struct wma_txrx_node *iface,
2728 struct ieee80211_frame *wh,
Nirav Shahcbc6d722016-03-01 16:24:53 +05302729 qdf_nbuf_t wbuf
mukul sharma72c8b222015-09-04 17:02:01 +05302730)
2731{
2732 uint16_t key_id;
2733 uint8_t *efrm;
2734
Nirav Shahcbc6d722016-03-01 16:24:53 +05302735 efrm = qdf_nbuf_data(wbuf) + qdf_nbuf_len(wbuf);
mukul sharma72c8b222015-09-04 17:02:01 +05302736 key_id = (uint16_t)*(efrm - cds_get_mmie_size() + 2);
2737
2738 if (!((key_id == WMA_IGTK_KEY_INDEX_4)
2739 || (key_id == WMA_IGTK_KEY_INDEX_5))) {
2740 WMA_LOGE(FL("Invalid KeyID(%d) dropping the frame"), key_id);
2741 return -EINVAL;
2742 }
2743 if (WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap,
2744 WMI_SERVICE_STA_PMF_OFFLOAD)) {
2745 /*
2746 * if 11w offload is enabled then mmie validation is performed
2747 * in firmware, host just need to trim the mmie.
2748 */
Nirav Shahcbc6d722016-03-01 16:24:53 +05302749 qdf_nbuf_trim_tail(wbuf, cds_get_mmie_size());
mukul sharma72c8b222015-09-04 17:02:01 +05302750 } else {
2751 if (cds_is_mmie_valid(iface->key.key,
2752 iface->key.key_id[key_id - WMA_IGTK_KEY_INDEX_4].ipn,
2753 (uint8_t *) wh, efrm)) {
2754 WMA_LOGE(FL("Protected BC/MC frame MMIE validation successful"));
2755 /* Remove MMIE */
Nirav Shahcbc6d722016-03-01 16:24:53 +05302756 qdf_nbuf_trim_tail(wbuf, cds_get_mmie_size());
mukul sharma72c8b222015-09-04 17:02:01 +05302757 } else {
2758 WMA_LOGE(FL("BC/MC MIC error or MMIE not present, dropping the frame"));
2759 return -EINVAL;
2760 }
2761 }
2762 return 0;
2763}
2764
2765/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002766 * wma_process_rmf_frame() - process rmf frame
2767 * @wma_handle: wma handle
2768 * @iface: txrx node
2769 * @wh: 80211 frame
2770 * @rx_pkt: rx packet
2771 * @wbuf: Buffer
2772 *
2773 * Return: 0 for success or error code
2774 */
2775static
2776int wma_process_rmf_frame(tp_wma_handle wma_handle,
2777 struct wma_txrx_node *iface,
2778 struct ieee80211_frame *wh,
2779 cds_pkt_t *rx_pkt,
Nirav Shahcbc6d722016-03-01 16:24:53 +05302780 qdf_nbuf_t wbuf)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002781{
mukul sharma72c8b222015-09-04 17:02:01 +05302782 uint8_t *orig_hdr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002783 uint8_t *ccmp;
2784
2785 if ((wh)->i_fc[1] & IEEE80211_FC1_WEP) {
2786 if (IEEE80211_IS_BROADCAST(wh->i_addr1) ||
2787 IEEE80211_IS_MULTICAST(wh->i_addr1)) {
2788 WMA_LOGE("Encrypted BC/MC frame dropping the frame");
2789 cds_pkt_return_packet(rx_pkt);
2790 return -EINVAL;
2791 }
2792
Nirav Shahcbc6d722016-03-01 16:24:53 +05302793 orig_hdr = (uint8_t *) qdf_nbuf_data(wbuf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002794 /* Pointer to head of CCMP header */
2795 ccmp = orig_hdr + sizeof(*wh);
2796 if (wma_is_ccmp_pn_replay_attack(
2797 wma_handle, wh, ccmp)) {
2798 WMA_LOGE("Dropping the frame");
2799 cds_pkt_return_packet(rx_pkt);
2800 return -EINVAL;
2801 }
2802
2803 /* Strip privacy headers (and trailer)
2804 * for a received frame
2805 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302806 qdf_mem_move(orig_hdr +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002807 IEEE80211_CCMP_HEADERLEN, wh,
2808 sizeof(*wh));
Nirav Shahcbc6d722016-03-01 16:24:53 +05302809 qdf_nbuf_pull_head(wbuf,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002810 IEEE80211_CCMP_HEADERLEN);
Nirav Shahcbc6d722016-03-01 16:24:53 +05302811 qdf_nbuf_trim_tail(wbuf, IEEE80211_CCMP_MICLEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002812
2813 rx_pkt->pkt_meta.mpdu_hdr_ptr =
Nirav Shahcbc6d722016-03-01 16:24:53 +05302814 qdf_nbuf_data(wbuf);
2815 rx_pkt->pkt_meta.mpdu_len = qdf_nbuf_len(wbuf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002816 rx_pkt->pkt_meta.mpdu_data_len =
2817 rx_pkt->pkt_meta.mpdu_len -
2818 rx_pkt->pkt_meta.mpdu_hdr_len;
2819 rx_pkt->pkt_meta.mpdu_data_ptr =
2820 rx_pkt->pkt_meta.mpdu_hdr_ptr +
2821 rx_pkt->pkt_meta.mpdu_hdr_len;
2822 rx_pkt->pkt_meta.tsf_delta = rx_pkt->pkt_meta.tsf_delta;
2823 rx_pkt->pkt_buf = wbuf;
2824 WMA_LOGD(FL("BSSID: "MAC_ADDRESS_STR" tsf_delta: %u"),
2825 MAC_ADDR_ARRAY(wh->i_addr3), rx_pkt->pkt_meta.tsf_delta);
2826 } else {
2827 if (IEEE80211_IS_BROADCAST(wh->i_addr1) ||
2828 IEEE80211_IS_MULTICAST(wh->i_addr1)) {
mukul sharma72c8b222015-09-04 17:02:01 +05302829 if (0 != wma_process_bip(wma_handle, iface, wh, wbuf)) {
2830 cds_pkt_return_packet(rx_pkt);
2831 return -EINVAL;
Mukul Sharmaa748fbb2015-12-01 19:51:36 +05302832 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002833 } else {
2834 WMA_LOGE("Rx unprotected unicast mgmt frame");
2835 rx_pkt->pkt_meta.dpuFeedback =
2836 DPU_FEEDBACK_UNPROTECTED_ERROR;
2837 }
2838 }
2839 return 0;
2840}
2841#endif
2842
2843/**
2844 * wma_mgmt_rx_process() - process management rx frame.
2845 * @handle: wma handle
2846 * @data: rx data
2847 * @data_len: data length
2848 *
2849 * Return: 0 for success or error code
2850 */
2851static int wma_mgmt_rx_process(void *handle, uint8_t *data,
2852 uint32_t data_len)
2853{
2854 tp_wma_handle wma_handle = (tp_wma_handle) handle;
2855 WMI_MGMT_RX_EVENTID_param_tlvs *param_tlvs = NULL;
2856 wmi_mgmt_rx_hdr *hdr = NULL;
2857 struct wma_txrx_node *iface = NULL;
Mukul Sharmaa748fbb2015-12-01 19:51:36 +05302858 uint8_t vdev_id = WMA_INVALID_VDEV_ID;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002859 cds_pkt_t *rx_pkt;
Nirav Shahcbc6d722016-03-01 16:24:53 +05302860 qdf_nbuf_t wbuf;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002861 struct ieee80211_frame *wh;
2862 uint8_t mgt_type, mgt_subtype;
2863 int status;
2864
2865 if (!wma_handle) {
2866 WMA_LOGE("%s: Failed to get WMA context", __func__);
2867 return -EINVAL;
2868 }
2869
2870 param_tlvs = (WMI_MGMT_RX_EVENTID_param_tlvs *) data;
2871 if (!param_tlvs) {
2872 WMA_LOGE("Get NULL point message from FW");
2873 return -EINVAL;
2874 }
2875
2876 hdr = param_tlvs->hdr;
2877 if (!hdr) {
2878 WMA_LOGE("Rx event is NULL");
2879 return -EINVAL;
2880 }
2881
2882 if (hdr->buf_len < sizeof(struct ieee80211_frame)) {
2883 WMA_LOGE("Invalid rx mgmt packet");
2884 return -EINVAL;
2885 }
2886
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302887 rx_pkt = qdf_mem_malloc(sizeof(*rx_pkt));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002888 if (!rx_pkt) {
2889 WMA_LOGE("Failed to allocate rx packet");
2890 return -ENOMEM;
2891 }
2892
Rajeev Kumarfec3dbe2016-01-19 15:23:52 -08002893 if (cds_is_load_or_unload_in_progress()) {
Naveen Rawat10ccf872015-11-03 14:15:55 -08002894 WMA_LOGE("Load/Unload in progress");
2895 return -EINVAL;
2896 }
2897
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302898 qdf_mem_zero(rx_pkt, sizeof(*rx_pkt));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002899
2900 /*
2901 * Fill in meta information needed by pe/lim
2902 * TODO: Try to maintain rx metainfo as part of skb->data.
2903 */
2904 rx_pkt->pkt_meta.channel = hdr->channel;
2905 rx_pkt->pkt_meta.scan_src = hdr->flags;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -07002906
2907 /*
2908 * Get the rssi value from the current snr value
2909 * using standard noise floor of -96.
2910 */
2911 rx_pkt->pkt_meta.rssi = hdr->snr + WMA_NOISE_FLOOR_DBM_DEFAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002912 rx_pkt->pkt_meta.snr = hdr->snr;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -07002913
2914 /* If absolute rssi is available from firmware, use it */
2915 if (hdr->rssi != 0)
2916 rx_pkt->pkt_meta.rssi_raw = hdr->rssi;
2917 else
2918 rx_pkt->pkt_meta.rssi_raw = rx_pkt->pkt_meta.rssi;
2919
2920
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002921 /*
2922 * FIXME: Assigning the local timestamp as hw timestamp is not
2923 * available. Need to see if pe/lim really uses this data.
2924 */
2925 rx_pkt->pkt_meta.timestamp = (uint32_t) jiffies;
2926 rx_pkt->pkt_meta.mpdu_hdr_len = sizeof(struct ieee80211_frame);
2927 rx_pkt->pkt_meta.mpdu_len = hdr->buf_len;
2928 rx_pkt->pkt_meta.mpdu_data_len = hdr->buf_len -
2929 rx_pkt->pkt_meta.mpdu_hdr_len;
2930
2931 rx_pkt->pkt_meta.roamCandidateInd = 0;
2932
2933 /* Why not just use rx_event->hdr.buf_len? */
Nirav Shahcbc6d722016-03-01 16:24:53 +05302934 wbuf = qdf_nbuf_alloc(NULL, roundup(hdr->buf_len, 4), 0, 4, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002935 if (!wbuf) {
2936 WMA_LOGE("%s: Failed to allocate wbuf for mgmt rx len(%u)",
2937 __func__, hdr->buf_len);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302938 qdf_mem_free(rx_pkt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002939 return -ENOMEM;
2940 }
2941
Nirav Shahcbc6d722016-03-01 16:24:53 +05302942 qdf_nbuf_put_tail(wbuf, hdr->buf_len);
2943 qdf_nbuf_set_protocol(wbuf, ETH_P_CONTROL);
2944 wh = (struct ieee80211_frame *)qdf_nbuf_data(wbuf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002945
Nirav Shahcbc6d722016-03-01 16:24:53 +05302946 rx_pkt->pkt_meta.mpdu_hdr_ptr = qdf_nbuf_data(wbuf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002947 rx_pkt->pkt_meta.mpdu_data_ptr = rx_pkt->pkt_meta.mpdu_hdr_ptr +
2948 rx_pkt->pkt_meta.mpdu_hdr_len;
2949 rx_pkt->pkt_meta.tsf_delta = hdr->tsf_delta;
2950 rx_pkt->pkt_buf = wbuf;
2951
2952 WMA_LOGD(FL("BSSID: "MAC_ADDRESS_STR" tsf_delta: %u"),
2953 MAC_ADDR_ARRAY(wh->i_addr3), hdr->tsf_delta);
2954
2955#ifdef BIG_ENDIAN_HOST
2956 {
2957 /*
2958 * for big endian host, copy engine byte_swap is enabled
2959 * But the rx mgmt frame buffer content is in network byte order
2960 * Need to byte swap the mgmt frame buffer content - so when
2961 * copy engine does byte_swap - host gets buffer content in the
2962 * correct byte order.
2963 */
2964 int i;
2965 uint32_t *destp, *srcp;
2966 destp = (uint32_t *) wh;
2967 srcp = (uint32_t *) param_tlvs->bufp;
2968 for (i = 0;
2969 i < (roundup(hdr->buf_len, sizeof(uint32_t)) / 4); i++) {
2970 *destp = cpu_to_le32(*srcp);
2971 destp++;
2972 srcp++;
2973 }
2974 }
2975#else
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302976 qdf_mem_copy(wh, param_tlvs->bufp, hdr->buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002977#endif
2978
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -07002979 WMA_LOGD(
2980 FL("BSSID: "MAC_ADDRESS_STR" snr = %d, rssi = %d, rssi_raw = %d"),
2981 MAC_ADDR_ARRAY(wh->i_addr3),
2982 hdr->snr, rx_pkt->pkt_meta.rssi,
2983 rx_pkt->pkt_meta.rssi_raw);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002984 if (!wma_handle->mgmt_rx) {
2985 WMA_LOGE("Not registered for Mgmt rx, dropping the frame");
2986 cds_pkt_return_packet(rx_pkt);
2987 return -EINVAL;
2988 }
2989
2990 /* If it is a beacon/probe response, save it for future use */
2991 mgt_type = (wh)->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
2992 mgt_subtype = (wh)->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
2993
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002994#ifdef WLAN_FEATURE_11W
2995 if (mgt_type == IEEE80211_FC0_TYPE_MGT &&
2996 (mgt_subtype == IEEE80211_FC0_SUBTYPE_DISASSOC ||
2997 mgt_subtype == IEEE80211_FC0_SUBTYPE_DEAUTH ||
2998 mgt_subtype == IEEE80211_FC0_SUBTYPE_ACTION)) {
Mukul Sharmaa748fbb2015-12-01 19:51:36 +05302999 if (wma_find_vdev_by_bssid(
3000 wma_handle, wh->i_addr3, &vdev_id)) {
3001 iface = &(wma_handle->interfaces[vdev_id]);
3002 if (iface->rmfEnabled) {
3003 status = wma_process_rmf_frame(wma_handle,
3004 iface, wh, rx_pkt, wbuf);
3005 if (status != 0)
3006 return status;
3007 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003008 }
3009 }
3010#endif /* WLAN_FEATURE_11W */
Mukul Sharmaa748fbb2015-12-01 19:51:36 +05303011 rx_pkt->pkt_meta.sessionId =
3012 (vdev_id == WMA_INVALID_VDEV_ID ? 0 : vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003013 wma_handle->mgmt_rx(wma_handle, rx_pkt);
3014 return 0;
3015}
3016
3017/**
3018 * wma_de_register_mgmt_frm_client() - deregister management frame
3019 * @cds_ctx: cds context
3020 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303021 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003022 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303023QDF_STATUS wma_de_register_mgmt_frm_client(void *cds_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003024{
3025 tp_wma_handle wma_handle;
3026
3027#ifdef QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +05303028 if (cds_get_conparam() == QDF_GLOBAL_FTM_MODE)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303029 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003030#endif
3031
Anurag Chouhan6d760662016-02-20 16:05:43 +05303032 wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003033 if (!wma_handle) {
3034 WMA_LOGE("%s: Failed to get WMA context", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303035 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003036 }
3037
3038 if (wmi_unified_unregister_event_handler(wma_handle->wmi_handle,
3039 WMI_MGMT_RX_EVENTID) != 0) {
3040 WMA_LOGE("Failed to Unregister rx mgmt handler with wmi");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303041 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003042 }
3043 wma_handle->mgmt_rx = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303044 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003045}
3046
3047/**
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003048 * wma_register_roaming_callbacks() - Register roaming callbacks
3049 * @cds_ctx: CDS Context
3050 * @csr_roam_synch_cb: CSR roam synch callback routine pointer
3051 * @pe_roam_synch_cb: PE roam synch callback routine pointer
3052 *
3053 * Register the SME and PE callback routines with WMA for
3054 * handling roaming
3055 *
3056 * Return: Success or Failure Status
3057 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303058QDF_STATUS wma_register_roaming_callbacks(void *cds_ctx,
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003059 void (*csr_roam_synch_cb)(tpAniSirGlobal mac,
3060 roam_offload_synch_ind *roam_synch_data,
3061 tpSirBssDescription bss_desc_ptr, uint8_t reason),
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303062 QDF_STATUS (*pe_roam_synch_cb)(tpAniSirGlobal mac,
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003063 roam_offload_synch_ind *roam_synch_data,
3064 tpSirBssDescription bss_desc_ptr))
3065{
3066
Anurag Chouhan6d760662016-02-20 16:05:43 +05303067 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003068
3069 if (!wma) {
3070 WMA_LOGE("%s: Failed to get WMA context", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303071 return QDF_STATUS_E_FAILURE;
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003072 }
3073 wma->csr_roam_synch_cb = csr_roam_synch_cb;
3074 wma->pe_roam_synch_cb = pe_roam_synch_cb;
3075 WMA_LOGD("Registered roam synch callbacks with WMA successfully");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303076 return QDF_STATUS_SUCCESS;
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003077}
3078/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003079 * wma_register_mgmt_frm_client() - register management frame callback
3080 * @cds_ctx: cds context
3081 * @mgmt_frm_rx: management frame
3082 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303083 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003084 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303085QDF_STATUS wma_register_mgmt_frm_client(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003086 void *cds_ctx, wma_mgmt_frame_rx_callback mgmt_frm_rx)
3087{
Anurag Chouhan6d760662016-02-20 16:05:43 +05303088 tp_wma_handle wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003089
3090 if (!wma_handle) {
3091 WMA_LOGE("%s: Failed to get WMA context", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303092 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003093 }
3094
3095 if (wmi_unified_register_event_handler(wma_handle->wmi_handle,
3096 WMI_MGMT_RX_EVENTID,
Govind Singhd76a5b02016-03-08 15:12:14 +05303097 wma_mgmt_rx_process,
3098 WMA_RX_WORK_CTX) != 0) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003099 WMA_LOGE("Failed to register rx mgmt handler with wmi");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303100 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003101 }
3102 wma_handle->mgmt_rx = mgmt_frm_rx;
3103
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303104 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003105}