blob: e7eed705db8b1199bc69fc7aaff6b01e71f653c6 [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"
Dhanashri Atreb08959a2016-03-01 17:28:03 -080069#include "cdp_txrx_flow_ctrl_legacy.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080070
71/**
72 * wma_send_bcn_buf_ll() - prepare and send beacon buffer to fw for LL
73 * @wma: wma handle
74 * @pdev: txrx pdev
75 * @vdev_id: vdev id
76 * @param_buf: SWBA parameters
77 *
78 * Return: none
79 */
80static void wma_send_bcn_buf_ll(tp_wma_handle wma,
81 ol_txrx_pdev_handle pdev,
82 uint8_t vdev_id,
83 WMI_HOST_SWBA_EVENTID_param_tlvs *param_buf)
84{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080085 struct ieee80211_frame *wh;
86 struct beacon_info *bcn;
87 wmi_tim_info *tim_info = param_buf->tim_info;
88 uint8_t *bcn_payload;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053089 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080090 struct beacon_tim_ie *tim_ie;
91 wmi_p2p_noa_info *p2p_noa_info = param_buf->p2p_noa_info;
92 struct p2p_sub_element_noa noa_ie;
Himanshu Agarwal009f1572016-03-09 17:26:02 +053093 struct wmi_bcn_send_from_host params;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080094 uint8_t i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080095
96 bcn = wma->interfaces[vdev_id].beacon;
97 if (!bcn->buf) {
98 WMA_LOGE("%s: Invalid beacon buffer", __func__);
99 return;
100 }
101
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530102 qdf_spin_lock_bh(&bcn->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800103
Nirav Shahcbc6d722016-03-01 16:24:53 +0530104 bcn_payload = qdf_nbuf_data(bcn->buf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800105
106 tim_ie = (struct beacon_tim_ie *)(&bcn_payload[bcn->tim_ie_offset]);
107
108 if (tim_info->tim_changed) {
109 if (tim_info->tim_num_ps_pending)
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530110 qdf_mem_copy(&tim_ie->tim_bitmap, tim_info->tim_bitmap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800111 WMA_TIM_SUPPORTED_PVB_LENGTH);
112 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530113 qdf_mem_zero(&tim_ie->tim_bitmap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800114 WMA_TIM_SUPPORTED_PVB_LENGTH);
115 /*
116 * Currently we support fixed number of
117 * peers as limited by HAL_NUM_STA.
118 * tim offset is always 0
119 */
120 tim_ie->tim_bitctl = 0;
121 }
122
123 /* Update DTIM Count */
124 if (tim_ie->dtim_count == 0)
125 tim_ie->dtim_count = tim_ie->dtim_period - 1;
126 else
127 tim_ie->dtim_count--;
128
129 /*
130 * DTIM count needs to be backedup so that
131 * when umac updates the beacon template
132 * current dtim count can be updated properly
133 */
134 bcn->dtim_count = tim_ie->dtim_count;
135
136 /* update state for buffered multicast frames on DTIM */
137 if (tim_info->tim_mcast && (tim_ie->dtim_count == 0 ||
138 tim_ie->dtim_period == 1))
139 tim_ie->tim_bitctl |= 1;
140 else
141 tim_ie->tim_bitctl &= ~1;
142
143 /* To avoid sw generated frame sequence the same as H/W generated frame,
144 * the value lower than min_sw_seq is reserved for HW generated frame */
145 if ((bcn->seq_no & IEEE80211_SEQ_MASK) < MIN_SW_SEQ)
146 bcn->seq_no = MIN_SW_SEQ;
147
148 wh = (struct ieee80211_frame *)bcn_payload;
149 *(uint16_t *) &wh->i_seq[0] = htole16(bcn->seq_no
150 << IEEE80211_SEQ_SEQ_SHIFT);
151 bcn->seq_no++;
152
153 if (WMI_UNIFIED_NOA_ATTR_IS_MODIFIED(p2p_noa_info)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530154 qdf_mem_zero(&noa_ie, sizeof(noa_ie));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800155
156 noa_ie.index =
157 (uint8_t) WMI_UNIFIED_NOA_ATTR_INDEX_GET(p2p_noa_info);
158 noa_ie.oppPS =
159 (uint8_t) WMI_UNIFIED_NOA_ATTR_OPP_PS_GET(p2p_noa_info);
160 noa_ie.ctwindow =
161 (uint8_t) WMI_UNIFIED_NOA_ATTR_CTWIN_GET(p2p_noa_info);
162 noa_ie.num_descriptors =
163 (uint8_t) WMI_UNIFIED_NOA_ATTR_NUM_DESC_GET(p2p_noa_info);
164 WMA_LOGI("%s: index %u, oppPs %u, ctwindow %u, "
165 "num_descriptors = %u", __func__, noa_ie.index,
166 noa_ie.oppPS, noa_ie.ctwindow, noa_ie.num_descriptors);
167 for (i = 0; i < noa_ie.num_descriptors; i++) {
168 noa_ie.noa_descriptors[i].type_count =
169 (uint8_t) p2p_noa_info->noa_descriptors[i].
170 type_count;
171 noa_ie.noa_descriptors[i].duration =
172 p2p_noa_info->noa_descriptors[i].duration;
173 noa_ie.noa_descriptors[i].interval =
174 p2p_noa_info->noa_descriptors[i].interval;
175 noa_ie.noa_descriptors[i].start_time =
176 p2p_noa_info->noa_descriptors[i].start_time;
177 WMA_LOGI("%s: NoA descriptor[%d] type_count %u, "
178 "duration %u, interval %u, start_time = %u",
179 __func__, i,
180 noa_ie.noa_descriptors[i].type_count,
181 noa_ie.noa_descriptors[i].duration,
182 noa_ie.noa_descriptors[i].interval,
183 noa_ie.noa_descriptors[i].start_time);
184 }
185 wma_update_noa(bcn, &noa_ie);
186
187 /* Send a msg to LIM to update the NoA IE in probe response
188 * frames transmitted by the host */
189 wma_update_probe_resp_noa(wma, &noa_ie);
190 }
191
192 if (bcn->dma_mapped) {
Nirav Shahcbc6d722016-03-01 16:24:53 +0530193 qdf_nbuf_unmap_single(pdev->osdev, bcn->buf, QDF_DMA_TO_DEVICE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800194 bcn->dma_mapped = 0;
195 }
Nirav Shahcbc6d722016-03-01 16:24:53 +0530196 ret = qdf_nbuf_map_single(pdev->osdev, bcn->buf, QDF_DMA_TO_DEVICE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530197 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800198 WMA_LOGE("%s: failed map beacon buf to DMA region", __func__);
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530199 qdf_spin_unlock_bh(&bcn->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800200 return;
201 }
202
203 bcn->dma_mapped = 1;
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530204 params.vdev_id = vdev_id;
205 params.data_len = bcn->len;
206 params.frame_ctrl = *((A_UINT16 *) wh->i_fc);
207 params.frag_ptr = qdf_nbuf_get_frag_paddr(bcn->buf, 0);
208 params.dtim_flag = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800209 /* notify Firmware of DTM and mcast/bcast traffic */
210 if (tim_ie->dtim_count == 0) {
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530211 params.dtim_flag |= WMI_BCN_SEND_DTIM_ZERO;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800212 /* deliver mcast/bcast traffic in next DTIM beacon */
213 if (tim_ie->tim_bitctl & 0x01)
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530214 params.dtim_flag |= WMI_BCN_SEND_DTIM_BITCTL_SET;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800215 }
216
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530217 wmi_unified_bcn_buf_ll_cmd(wma->wmi_handle,
218 &params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800219
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530220 qdf_spin_unlock_bh(&bcn->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800221}
222
223/**
224 * wma_beacon_swba_handler() - swba event handler
225 * @handle: wma handle
226 * @event: event data
227 * @len: data length
228 *
229 * SWBA event is alert event to Host requesting host to Queue a beacon
230 * for transmission use only in host beacon mode
231 *
232 * Return: 0 for success or error code
233 */
234int wma_beacon_swba_handler(void *handle, uint8_t *event, uint32_t len)
235{
236 tp_wma_handle wma = (tp_wma_handle) handle;
237 WMI_HOST_SWBA_EVENTID_param_tlvs *param_buf;
238 wmi_host_swba_event_fixed_param *swba_event;
239 uint32_t vdev_map;
240 ol_txrx_pdev_handle pdev;
241 uint8_t vdev_id = 0;
242
243 param_buf = (WMI_HOST_SWBA_EVENTID_param_tlvs *) event;
244 if (!param_buf) {
245 WMA_LOGE("Invalid swba event buffer");
246 return -EINVAL;
247 }
248 swba_event = param_buf->fixed_param;
249 vdev_map = swba_event->vdev_map;
250
Anurag Chouhan6d760662016-02-20 16:05:43 +0530251 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800252 if (!pdev) {
253 WMA_LOGE("%s: pdev is NULL", __func__);
254 return -EINVAL;
255 }
256
257 for (; vdev_map; vdev_id++, vdev_map >>= 1) {
258 if (!(vdev_map & 0x1))
259 continue;
260 if (!ol_cfg_is_high_latency(pdev->ctrl_pdev))
261 wma_send_bcn_buf_ll(wma, pdev, vdev_id, param_buf);
262 break;
263 }
264 return 0;
265}
266
267/**
268 * wma_peer_sta_kickout_event_handler() - kickout event handler
269 * @handle: wma handle
270 * @event: event data
271 * @len: data length
272 *
273 * Kickout event is received from firmware on observing beacon miss
274 * It handles kickout event for different modes and indicate to
275 * upper layers.
276 *
277 * Return: 0 for success or error code
278 */
279int wma_peer_sta_kickout_event_handler(void *handle, u8 *event, u32 len)
280{
281 tp_wma_handle wma = (tp_wma_handle) handle;
282 WMI_PEER_STA_KICKOUT_EVENTID_param_tlvs *param_buf = NULL;
283 wmi_peer_sta_kickout_event_fixed_param *kickout_event = NULL;
284 uint8_t vdev_id, peer_id, macaddr[IEEE80211_ADDR_LEN];
285 ol_txrx_peer_handle peer;
286 ol_txrx_pdev_handle pdev;
287 tpDeleteStaContext del_sta_ctx;
288 tpSirIbssPeerInactivityInd p_inactivity;
289
290 WMA_LOGD("%s: Enter", __func__);
291 param_buf = (WMI_PEER_STA_KICKOUT_EVENTID_param_tlvs *) event;
292 kickout_event = param_buf->fixed_param;
Anurag Chouhan6d760662016-02-20 16:05:43 +0530293 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800294 if (!pdev) {
295 WMA_LOGE("%s: pdev is NULL", __func__);
296 return -EINVAL;
297 }
298 WMI_MAC_ADDR_TO_CHAR_ARRAY(&kickout_event->peer_macaddr, macaddr);
299 peer = ol_txrx_find_peer_by_addr(pdev, macaddr, &peer_id);
300 if (!peer) {
301 WMA_LOGE("PEER [%pM] not found", macaddr);
302 return -EINVAL;
303 }
304
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530305 if (ol_txrx_get_vdevid(peer, &vdev_id) != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800306 WMA_LOGE("Not able to find BSSID for peer [%pM]", macaddr);
307 return -EINVAL;
308 }
309
310 WMA_LOGA("%s: PEER:[%pM], ADDR:[%pN], INTERFACE:%d, peer_id:%d, reason:%d",
311 __func__, macaddr, wma->interfaces[vdev_id].addr, vdev_id,
312 peer_id, kickout_event->reason);
313
314 switch (kickout_event->reason) {
315 case WMI_PEER_STA_KICKOUT_REASON_IBSS_DISCONNECT:
316 p_inactivity = (tpSirIbssPeerInactivityInd)
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530317 qdf_mem_malloc(sizeof(tSirIbssPeerInactivityInd));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800318 if (!p_inactivity) {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530319 WMA_LOGE("QDF MEM Alloc Failed for tSirIbssPeerInactivity");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800320 return -ENOMEM;
321 }
322
323 p_inactivity->staIdx = peer_id;
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530324 qdf_mem_copy(p_inactivity->peer_addr.bytes, macaddr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800325 IEEE80211_ADDR_LEN);
326 wma_send_msg(wma, WMA_IBSS_PEER_INACTIVITY_IND,
327 (void *)p_inactivity, 0);
328 goto exit_handler;
329 break;
330
331#ifdef FEATURE_WLAN_TDLS
332 case WMI_PEER_STA_KICKOUT_REASON_TDLS_DISCONNECT:
333 del_sta_ctx = (tpDeleteStaContext)
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530334 qdf_mem_malloc(sizeof(tDeleteStaContext));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800335 if (!del_sta_ctx) {
336 WMA_LOGE("%s: mem alloc failed for tDeleteStaContext for TDLS peer: %pM",
337 __func__, macaddr);
338 return -ENOMEM;
339 }
340
341 del_sta_ctx->staId = peer_id;
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530342 qdf_mem_copy(del_sta_ctx->addr2, macaddr, IEEE80211_ADDR_LEN);
343 qdf_mem_copy(del_sta_ctx->bssId, wma->interfaces[vdev_id].bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800344 IEEE80211_ADDR_LEN);
345 del_sta_ctx->reasonCode = HAL_DEL_STA_REASON_CODE_KEEP_ALIVE;
346 wma_send_msg(wma, SIR_LIM_DELETE_STA_CONTEXT_IND,
347 (void *)del_sta_ctx, 0);
348 goto exit_handler;
349 break;
350#endif /* FEATURE_WLAN_TDLS */
351
352 case WMI_PEER_STA_KICKOUT_REASON_XRETRY:
353 if (wma->interfaces[vdev_id].type == WMI_VDEV_TYPE_STA &&
354 (wma->interfaces[vdev_id].sub_type == 0 ||
355 wma->interfaces[vdev_id].sub_type ==
356 WMI_UNIFIED_VDEV_SUBTYPE_P2P_CLIENT) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530357 !qdf_mem_cmp(wma->interfaces[vdev_id].bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800358 macaddr, IEEE80211_ADDR_LEN)) {
359 /*
360 * KICKOUT event is for current station-AP connection.
361 * Treat it like final beacon miss. Station may not have
362 * missed beacons but not able to transmit frames to AP
363 * for a long time. Must disconnect to get out of
364 * this sticky situation.
365 * In future implementation, roaming module will also
366 * handle this event and perform a scan.
367 */
368 WMA_LOGW("%s: WMI_PEER_STA_KICKOUT_REASON_XRETRY event for STA",
369 __func__);
370 wma_beacon_miss_handler(wma, vdev_id);
371 goto exit_handler;
372 }
373 break;
374
375 case WMI_PEER_STA_KICKOUT_REASON_UNSPECIFIED:
376 /*
377 * Default legacy value used by original firmware implementation.
378 */
379 if (wma->interfaces[vdev_id].type == WMI_VDEV_TYPE_STA &&
380 (wma->interfaces[vdev_id].sub_type == 0 ||
381 wma->interfaces[vdev_id].sub_type ==
382 WMI_UNIFIED_VDEV_SUBTYPE_P2P_CLIENT) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530383 !qdf_mem_cmp(wma->interfaces[vdev_id].bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800384 macaddr, IEEE80211_ADDR_LEN)) {
385 /*
386 * KICKOUT event is for current station-AP connection.
387 * Treat it like final beacon miss. Station may not have
388 * missed beacons but not able to transmit frames to AP
389 * for a long time. Must disconnect to get out of
390 * this sticky situation.
391 * In future implementation, roaming module will also
392 * handle this event and perform a scan.
393 */
394 WMA_LOGW("%s: WMI_PEER_STA_KICKOUT_REASON_UNSPECIFIED event for STA",
395 __func__);
396 wma_beacon_miss_handler(wma, vdev_id);
397 goto exit_handler;
398 }
399 break;
400
401 case WMI_PEER_STA_KICKOUT_REASON_INACTIVITY:
mukul sharma72c8b222015-09-04 17:02:01 +0530402 /* Handle SA query kickout is same as inactivity kickout */
403 case WMI_PEER_STA_KICKOUT_REASON_SA_QUERY_TIMEOUT:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800404 default:
405 break;
406 }
407
408 /*
409 * default action is to send delete station context indication to LIM
410 */
411 del_sta_ctx =
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530412 (tpDeleteStaContext) qdf_mem_malloc(sizeof(tDeleteStaContext));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800413 if (!del_sta_ctx) {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530414 WMA_LOGE("QDF MEM Alloc Failed for tDeleteStaContext");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800415 return -ENOMEM;
416 }
417
418 del_sta_ctx->staId = peer_id;
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530419 qdf_mem_copy(del_sta_ctx->addr2, macaddr, IEEE80211_ADDR_LEN);
420 qdf_mem_copy(del_sta_ctx->bssId, wma->interfaces[vdev_id].addr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800421 IEEE80211_ADDR_LEN);
422 del_sta_ctx->reasonCode = HAL_DEL_STA_REASON_CODE_KEEP_ALIVE;
Kiran Kumar Lokere37d3aa22015-11-03 14:58:26 -0800423 del_sta_ctx->rssi = kickout_event->rssi + WMA_TGT_NOISE_FLOOR_DBM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800424 wma_send_msg(wma, SIR_LIM_DELETE_STA_CONTEXT_IND, (void *)del_sta_ctx,
425 0);
426
427exit_handler:
428 WMA_LOGD("%s: Exit", __func__);
429 return 0;
430}
431
432/**
433 * wma_unified_bcntx_status_event_handler() - beacon tx status event handler
434 * @handle: wma handle
435 * @cmd_param_info: event data
436 * @len: data length
437 *
438 * WMI Handler for WMI_OFFLOAD_BCN_TX_STATUS_EVENTID event from firmware.
439 * This event is generated by FW when the beacon transmission is offloaded
440 * and the host performs beacon template modification using WMI_BCN_TMPL_CMDID
441 * The FW generates this event when the first successful beacon transmission
442 * after template update
443 *
444 * Return: 0 for success or error code
445 */
446int wma_unified_bcntx_status_event_handler(void *handle,
447 uint8_t *cmd_param_info,
448 uint32_t len)
449{
450 tp_wma_handle wma = (tp_wma_handle) handle;
451 WMI_OFFLOAD_BCN_TX_STATUS_EVENTID_param_tlvs *param_buf;
452 wmi_offload_bcn_tx_status_event_fixed_param *resp_event;
453 tSirFirstBeaconTxCompleteInd *beacon_tx_complete_ind;
454
455 param_buf =
456 (WMI_OFFLOAD_BCN_TX_STATUS_EVENTID_param_tlvs *) cmd_param_info;
457 if (!param_buf) {
458 WMA_LOGE("Invalid bcn tx response event buffer");
459 return -EINVAL;
460 }
461
462 resp_event = param_buf->fixed_param;
463
464 /* Check for valid handle to ensure session is not
465 * deleted in any race
466 */
467 if (!wma->interfaces[resp_event->vdev_id].handle) {
468 WMA_LOGE("%s: The session does not exist", __func__);
469 return -EINVAL;
470 }
471
472 /* Beacon Tx Indication supports only AP mode. Ignore in other modes */
473 if (wma_is_vdev_in_ap_mode(wma, resp_event->vdev_id) == false) {
474 WMA_LOGI("%s: Beacon Tx Indication does not support type %d and sub_type %d",
475 __func__, wma->interfaces[resp_event->vdev_id].type,
476 wma->interfaces[resp_event->vdev_id].sub_type);
477 return 0;
478 }
479
480 beacon_tx_complete_ind = (tSirFirstBeaconTxCompleteInd *)
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530481 qdf_mem_malloc(sizeof(tSirFirstBeaconTxCompleteInd));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800482 if (!beacon_tx_complete_ind) {
483 WMA_LOGE("%s: Failed to alloc beacon_tx_complete_ind",
484 __func__);
485 return -ENOMEM;
486 }
487
488 beacon_tx_complete_ind->messageType = WMA_DFS_BEACON_TX_SUCCESS_IND;
489 beacon_tx_complete_ind->length = sizeof(tSirFirstBeaconTxCompleteInd);
490 beacon_tx_complete_ind->bssIdx = resp_event->vdev_id;
491
492 wma_send_msg(wma, WMA_DFS_BEACON_TX_SUCCESS_IND,
493 (void *)beacon_tx_complete_ind, 0);
494 return 0;
495}
496
497/**
498 * wma_get_link_probe_timeout() - get link timeout based on sub type
499 * @mac: UMAC handler
500 * @sub_type: vdev syb type
501 * @max_inactive_time: return max inactive time
502 * @max_unresponsive_time: return max unresponsive time
503 *
504 * Return: none
505 */
506static inline void wma_get_link_probe_timeout(struct sAniSirGlobal *mac,
507 uint32_t sub_type,
508 uint32_t *max_inactive_time,
509 uint32_t *max_unresponsive_time)
510{
511 uint32_t keep_alive;
512 uint16_t lm_id, ka_id;
513
514 switch (sub_type) {
515 case WMI_UNIFIED_VDEV_SUBTYPE_P2P_GO:
516 lm_id = WNI_CFG_GO_LINK_MONITOR_TIMEOUT;
517 ka_id = WNI_CFG_GO_KEEP_ALIVE_TIMEOUT;
518 break;
519 default:
520 /*For softAp the subtype value will be zero */
521 lm_id = WNI_CFG_AP_LINK_MONITOR_TIMEOUT;
522 ka_id = WNI_CFG_AP_KEEP_ALIVE_TIMEOUT;
523 }
524
525 if (wlan_cfg_get_int(mac, lm_id, max_inactive_time) != eSIR_SUCCESS) {
526 WMA_LOGE("Failed to read link monitor for subtype %d",
527 sub_type);
528 *max_inactive_time = WMA_LINK_MONITOR_DEFAULT_TIME_SECS;
529 }
530
531 if (wlan_cfg_get_int(mac, ka_id, &keep_alive) != eSIR_SUCCESS) {
532 WMA_LOGE("Failed to read keep alive for subtype %d", sub_type);
533 keep_alive = WMA_KEEP_ALIVE_DEFAULT_TIME_SECS;
534 }
535 *max_unresponsive_time = *max_inactive_time + keep_alive;
536}
537
538/**
539 * wma_set_sap_keepalive() - set SAP keep alive parameters to fw
540 * @wma: wma handle
541 * @vdev_id: vdev id
542 *
543 * Return: none
544 */
545void wma_set_sap_keepalive(tp_wma_handle wma, uint8_t vdev_id)
546{
547 uint32_t min_inactive_time, max_inactive_time, max_unresponsive_time;
Anurag Chouhan6d760662016-02-20 16:05:43 +0530548 struct sAniSirGlobal *mac = cds_get_context(QDF_MODULE_ID_PE);
Govind Singhd76a5b02016-03-08 15:12:14 +0530549 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800550
551 if (NULL == mac) {
552 WMA_LOGE("%s: Failed to get mac", __func__);
553 return;
554 }
555
556 wma_get_link_probe_timeout(mac, wma->interfaces[vdev_id].sub_type,
557 &max_inactive_time, &max_unresponsive_time);
558
559 min_inactive_time = max_inactive_time / 2;
560
Govind Singhd76a5b02016-03-08 15:12:14 +0530561 status = wma_vdev_set_param(wma->wmi_handle,
562 vdev_id,
563 WMI_VDEV_PARAM_AP_KEEPALIVE_MIN_IDLE_INACTIVE_TIME_SECS,
564 min_inactive_time);
565 if (QDF_IS_STATUS_ERROR(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800566 WMA_LOGE("Failed to Set AP MIN IDLE INACTIVE TIME");
567
Govind Singhd76a5b02016-03-08 15:12:14 +0530568 status = wma_vdev_set_param(wma->wmi_handle,
569 vdev_id,
570 WMI_VDEV_PARAM_AP_KEEPALIVE_MAX_IDLE_INACTIVE_TIME_SECS,
571 max_inactive_time);
572 if (QDF_IS_STATUS_ERROR(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800573 WMA_LOGE("Failed to Set AP MAX IDLE INACTIVE TIME");
574
Govind Singhd76a5b02016-03-08 15:12:14 +0530575 status = wma_vdev_set_param(wma->wmi_handle,
576 vdev_id,
577 WMI_VDEV_PARAM_AP_KEEPALIVE_MAX_UNRESPONSIVE_TIME_SECS,
578 max_unresponsive_time);
579 if (QDF_IS_STATUS_ERROR(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800580 WMA_LOGE("Failed to Set MAX UNRESPONSIVE TIME");
581
582 WMA_LOGD("%s:vdev_id:%d min_inactive_time: %u max_inactive_time: %u"
583 " max_unresponsive_time: %u", __func__, vdev_id,
584 min_inactive_time, max_inactive_time, max_unresponsive_time);
585}
586
587/**
mukul sharma72c8b222015-09-04 17:02:01 +0530588 * wma_set_sta_sa_query_param() - set sta sa query parameters
589 * @wma: wma handle
590 * @vdev_id: vdev id
591
592 * This function sets sta query related parameters in fw.
593 *
594 * Return: none
595 */
596
597void wma_set_sta_sa_query_param(tp_wma_handle wma,
598 uint8_t vdev_id)
599{
Anurag Chouhan6d760662016-02-20 16:05:43 +0530600 struct sAniSirGlobal *mac = cds_get_context(QDF_MODULE_ID_PE);
mukul sharma72c8b222015-09-04 17:02:01 +0530601 uint32_t max_retries, retry_interval;
mukul sharma72c8b222015-09-04 17:02:01 +0530602
603 WMA_LOGD(FL("Enter:"));
mukul sharma72c8b222015-09-04 17:02:01 +0530604
605 if (wlan_cfg_get_int
606 (mac, WNI_CFG_PMF_SA_QUERY_MAX_RETRIES,
607 &max_retries) != eSIR_SUCCESS) {
608 max_retries = DEFAULT_STA_SA_QUERY_MAX_RETRIES_COUNT;
609 WMA_LOGE(FL("Failed to get value for WNI_CFG_PMF_SA_QUERY_MAX_RETRIES"));
610 }
611 if (wlan_cfg_get_int
612 (mac, WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL,
613 &retry_interval) != eSIR_SUCCESS) {
614 retry_interval = DEFAULT_STA_SA_QUERY_RETRY_INTERVAL;
615 WMA_LOGE(FL("Failed to get value for WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL"));
616 }
617
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530618 wmi_unified_set_sta_sa_query_param_cmd(wma->wmi_handle,
619 vdev_id,
620 max_retries,
621 retry_interval);
mukul sharma72c8b222015-09-04 17:02:01 +0530622
623 WMA_LOGD(FL("Exit :"));
624 return;
625}
626
627/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800628 * wma_set_sta_keep_alive() - set sta keep alive parameters
629 * @wma: wma handle
630 * @vdev_id: vdev id
631 * @method: method for keep alive
632 * @timeperiod: time period
633 * @hostv4addr: host ipv4 address
634 * @destv4addr: dst ipv4 address
635 * @destmac: destination mac
636 *
637 * This function sets keep alive related parameters in fw.
638 *
639 * Return: none
640 */
641void wma_set_sta_keep_alive(tp_wma_handle wma, uint8_t vdev_id,
642 uint32_t method, uint32_t timeperiod,
643 uint8_t *hostv4addr, uint8_t *destv4addr,
644 uint8_t *destmac)
645{
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530646 struct sta_params params;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800647
648 WMA_LOGD("%s: Enter", __func__);
649
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530650 if (!wma) {
651 WMA_LOGE("%s: wma handle is NULL", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800652 return;
653 }
654
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530655 params.vdev_id = vdev_id;
656 params.method = method;
657 params.timeperiod = timeperiod;
658 params.hostv4addr = hostv4addr;
659 params.destv4addr = destv4addr;
660 params.destmac = destmac;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800661
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530662 wmi_unified_set_sta_keep_alive_cmd(wma->wmi_handle,
663 &params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800664
665 WMA_LOGD("%s: Exit", __func__);
666 return;
667}
668
669/**
670 * wma_vdev_install_key_complete_event_handler() - install key complete handler
671 * @handle: wma handle
672 * @event: event data
673 * @len: data length
674 *
675 * This event is sent by fw once WPA/WPA2 keys are installed in fw.
676 *
677 * Return: 0 for success or error code
678 */
679int wma_vdev_install_key_complete_event_handler(void *handle,
680 uint8_t *event,
681 uint32_t len)
682{
683 WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID_param_tlvs *param_buf = NULL;
684 wmi_vdev_install_key_complete_event_fixed_param *key_fp = NULL;
685
686 if (!event) {
687 WMA_LOGE("%s: event param null", __func__);
688 return -EINVAL;
689 }
690
691 param_buf = (WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID_param_tlvs *) event;
692 if (!param_buf) {
693 WMA_LOGE("%s: received null buf from target", __func__);
694 return -EINVAL;
695 }
696
697 key_fp = param_buf->fixed_param;
698 if (!key_fp) {
699 WMA_LOGE("%s: received null event data from target", __func__);
700 return -EINVAL;
701 }
702 /*
703 * Do nothing for now. Completion of set key is already indicated to lim
704 */
705 WMA_LOGI("%s: WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID", __func__);
706 return 0;
707}
708/*
709 * 802.11n D2.0 defined values for "Minimum MPDU Start Spacing":
710 * 0 for no restriction
711 * 1 for 1/4 us - Our lower layer calculations limit our precision to 1 msec
712 * 2 for 1/2 us - Our lower layer calculations limit our precision to 1 msec
713 * 3 for 1 us
714 * 4 for 2 us
715 * 5 for 4 us
716 * 6 for 8 us
717 * 7 for 16 us
718 */
719static const uint8_t wma_mpdu_spacing[] = { 0, 1, 1, 1, 2, 4, 8, 16 };
720
721/**
722 * wma_parse_mpdudensity() - give mpdu spacing from mpdu density
723 * @mpdudensity: mpdu density
724 *
725 * Return: mpdu spacing or 0 for error
726 */
727static inline uint8_t wma_parse_mpdudensity(uint8_t mpdudensity)
728{
729 if (mpdudensity < sizeof(wma_mpdu_spacing))
730 return wma_mpdu_spacing[mpdudensity];
731 else
732 return 0;
733}
734
735/**
736 * wmi_unified_send_peer_assoc() - send peer assoc command to fw
737 * @wma: wma handle
738 * @nw_type: nw type
739 * @params: add sta params
740 *
741 * This function send peer assoc command to firmware with
742 * different parameters.
743 *
Govind Singhb30d4c02016-03-24 11:01:23 +0530744 * Return: QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800745 */
Govind Singhb30d4c02016-03-24 11:01:23 +0530746QDF_STATUS wma_send_peer_assoc(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800747 tSirNwType nw_type,
748 tpAddStaParams params)
749{
750 ol_txrx_pdev_handle pdev;
Govind Singhb30d4c02016-03-24 11:01:23 +0530751 struct peer_assoc_params *cmd;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800752 int32_t ret, max_rates, i;
753 uint8_t rx_stbc, tx_stbc;
Govind Singhb30d4c02016-03-24 11:01:23 +0530754 uint8_t *rate_pos;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800755 wmi_rate_set peer_legacy_rates, peer_ht_rates;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800756 uint32_t num_peer_11b_rates = 0;
757 uint32_t num_peer_11a_rates = 0;
758 uint32_t phymode;
759 uint32_t peer_nss = 1;
760 struct wma_txrx_node *intr = NULL;
Govind Singhb30d4c02016-03-24 11:01:23 +0530761 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800762
Govind Singhb30d4c02016-03-24 11:01:23 +0530763 cmd = qdf_mem_malloc(sizeof(struct peer_assoc_params));
764 if (!cmd) {
765 WMA_LOGE("Failed to allocate peer_assoc_params param");
766 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800767 }
Govind Singhb30d4c02016-03-24 11:01:23 +0530768
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800769 intr = &wma->interfaces[params->smesessionId];
770
Anurag Chouhan6d760662016-02-20 16:05:43 +0530771 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800772
773 if (NULL == pdev) {
774 WMA_LOGE("%s: Failed to get pdev", __func__);
Govind Singhb30d4c02016-03-24 11:01:23 +0530775 qdf_mem_free(cmd);
776 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800777 }
778
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530779 qdf_mem_zero(&peer_legacy_rates, sizeof(wmi_rate_set));
780 qdf_mem_zero(&peer_ht_rates, sizeof(wmi_rate_set));
Govind Singhb30d4c02016-03-24 11:01:23 +0530781 qdf_mem_zero(cmd, sizeof(struct peer_assoc_params));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800782
783 phymode = wma_peer_phymode(nw_type, params->staType,
784 params->htCapable,
785 params->ch_width,
786 params->vhtCapable);
787
788 /* Legacy Rateset */
789 rate_pos = (uint8_t *) peer_legacy_rates.rates;
790 for (i = 0; i < SIR_NUM_11B_RATES; i++) {
791 if (!params->supportedRates.llbRates[i])
792 continue;
793 rate_pos[peer_legacy_rates.num_rates++] =
794 params->supportedRates.llbRates[i];
795 num_peer_11b_rates++;
796 }
797 for (i = 0; i < SIR_NUM_11A_RATES; i++) {
798 if (!params->supportedRates.llaRates[i])
799 continue;
800 rate_pos[peer_legacy_rates.num_rates++] =
801 params->supportedRates.llaRates[i];
802 num_peer_11a_rates++;
803 }
804
805 if ((phymode == MODE_11A && num_peer_11a_rates == 0) ||
806 (phymode == MODE_11B && num_peer_11b_rates == 0)) {
807 WMA_LOGW("%s: Invalid phy rates. phymode 0x%x, 11b_rates %d, 11a_rates %d",
808 __func__, phymode, num_peer_11b_rates, num_peer_11a_rates);
Govind Singhb30d4c02016-03-24 11:01:23 +0530809 qdf_mem_free(cmd);
810 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800811 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800812
813 /* HT Rateset */
814 max_rates = sizeof(peer_ht_rates.rates) /
815 sizeof(peer_ht_rates.rates[0]);
816 rate_pos = (uint8_t *) peer_ht_rates.rates;
817 for (i = 0; i < MAX_SUPPORTED_RATES; i++) {
818 if (params->supportedRates.supportedMCSSet[i / 8] &
819 (1 << (i % 8))) {
820 rate_pos[peer_ht_rates.num_rates++] = i;
821 if (i >= 8) {
822 /* MCS8 or higher rate is present, must be 2x2 */
823 peer_nss = 2;
824 }
825 }
826 if (peer_ht_rates.num_rates == max_rates)
827 break;
828 }
829
830 if (params->htCapable && !peer_ht_rates.num_rates) {
831 uint8_t temp_ni_rates[8] = { 0x0, 0x1, 0x2, 0x3,
832 0x4, 0x5, 0x6, 0x7};
833 /*
834 * Workaround for EV 116382: The peer is marked HT but with
835 * supported rx mcs set is set to 0. 11n spec mandates MCS0-7
836 * for a HT STA. So forcing the supported rx mcs rate to
837 * MCS 0-7. This workaround will be removed once we get
838 * clarification from WFA regarding this STA behavior.
839 */
840
841 /* TODO: Do we really need this? */
842 WMA_LOGW("Peer is marked as HT capable but supported mcs rate is 0");
843 peer_ht_rates.num_rates = sizeof(temp_ni_rates);
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530844 qdf_mem_copy((uint8_t *) peer_ht_rates.rates, temp_ni_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800845 peer_ht_rates.num_rates);
846 }
847
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800848 /* in ap/ibss mode and for tdls peer, use mac address of the peer in
849 * the other end as the new peer address; in sta mode, use bss id to
850 * be the new peer address
851 */
852 if ((wma_is_vdev_in_ap_mode(wma, params->smesessionId))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800853 || (wma_is_vdev_in_ibss_mode(wma, params->smesessionId))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800854#ifdef FEATURE_WLAN_TDLS
855 || (STA_ENTRY_TDLS_PEER == params->staType)
856#endif /* FEATURE_WLAN_TDLS */
857 )
858 WMI_CHAR_ARRAY_TO_MAC_ADDR(params->staMac, &cmd->peer_macaddr);
859 else
860 WMI_CHAR_ARRAY_TO_MAC_ADDR(params->bssId, &cmd->peer_macaddr);
861 cmd->vdev_id = params->smesessionId;
862 cmd->peer_new_assoc = 1;
863 cmd->peer_associd = params->assocId;
864
865 /*
866 * The target only needs a subset of the flags maintained in the host.
867 * Just populate those flags and send it down
868 */
869 cmd->peer_flags = 0;
870
871 if (params->wmmEnabled)
872 cmd->peer_flags |= WMI_PEER_QOS;
873
874 if (params->uAPSD) {
875 cmd->peer_flags |= WMI_PEER_APSD;
876 WMA_LOGD("Set WMI_PEER_APSD: uapsd Mask %d", params->uAPSD);
877 }
878
879 if (params->htCapable) {
880 cmd->peer_flags |= (WMI_PEER_HT | WMI_PEER_QOS);
881 cmd->peer_rate_caps |= WMI_RC_HT_FLAG;
882 }
883
884 if (params->ch_width) {
885 cmd->peer_flags |= WMI_PEER_40MHZ;
886 cmd->peer_rate_caps |= WMI_RC_CW40_FLAG;
887 if (params->fShortGI40Mhz)
888 cmd->peer_rate_caps |= WMI_RC_SGI_FLAG;
889 } else if (params->fShortGI20Mhz)
890 cmd->peer_rate_caps |= WMI_RC_SGI_FLAG;
891
892#ifdef WLAN_FEATURE_11AC
893 if (params->vhtCapable) {
894 cmd->peer_flags |= (WMI_PEER_HT | WMI_PEER_VHT | WMI_PEER_QOS);
895 cmd->peer_rate_caps |= WMI_RC_HT_FLAG;
896 }
897
898 if (params->ch_width == CH_WIDTH_80MHZ)
899 cmd->peer_flags |= WMI_PEER_80MHZ;
900 else if (params->ch_width == CH_WIDTH_160MHZ)
901 cmd->peer_flags |= WMI_PEER_160MHZ;
902 else if (params->ch_width == CH_WIDTH_80P80MHZ)
903 cmd->peer_flags |= WMI_PEER_160MHZ;
904
905 cmd->peer_vht_caps = params->vht_caps;
906#endif /* WLAN_FEATURE_11AC */
907
908 if (params->rmfEnabled)
909 cmd->peer_flags |= WMI_PEER_PMF;
910
911 rx_stbc = (params->ht_caps & IEEE80211_HTCAP_C_RXSTBC) >>
912 IEEE80211_HTCAP_C_RXSTBC_S;
913 if (rx_stbc) {
914 cmd->peer_flags |= WMI_PEER_STBC;
915 cmd->peer_rate_caps |= (rx_stbc << WMI_RC_RX_STBC_FLAG_S);
916 }
917
918 tx_stbc = (params->ht_caps & IEEE80211_HTCAP_C_TXSTBC) >>
919 IEEE80211_HTCAP_C_TXSTBC_S;
920 if (tx_stbc) {
921 cmd->peer_flags |= WMI_PEER_STBC;
922 cmd->peer_rate_caps |= (tx_stbc << WMI_RC_TX_STBC_FLAG_S);
923 }
924
925 if (params->htLdpcCapable || params->vhtLdpcCapable)
926 cmd->peer_flags |= WMI_PEER_LDPC;
927
928 switch (params->mimoPS) {
929 case eSIR_HT_MIMO_PS_STATIC:
930 cmd->peer_flags |= WMI_PEER_STATIC_MIMOPS;
931 break;
932 case eSIR_HT_MIMO_PS_DYNAMIC:
933 cmd->peer_flags |= WMI_PEER_DYN_MIMOPS;
934 break;
935 case eSIR_HT_MIMO_PS_NO_LIMIT:
936 cmd->peer_flags |= WMI_PEER_SPATIAL_MUX;
937 break;
938 default:
939 break;
940 }
941
942#ifdef FEATURE_WLAN_TDLS
943 if (STA_ENTRY_TDLS_PEER == params->staType)
944 cmd->peer_flags |= WMI_PEER_AUTH;
945#endif /* FEATURE_WLAN_TDLS */
946
947 if (params->wpa_rsn
948#ifdef FEATURE_WLAN_WAPI
949 || params->encryptType == eSIR_ED_WPI
950#endif /* FEATURE_WLAN_WAPI */
951 )
952 cmd->peer_flags |= WMI_PEER_NEED_PTK_4_WAY;
953 if (params->wpa_rsn >> 1)
954 cmd->peer_flags |= WMI_PEER_NEED_GTK_2_WAY;
955
Dhanashri Atreb08959a2016-03-01 17:28:03 -0800956 ol_txrx_peer_state_update(pdev, params->bssId, OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800957
958#ifdef FEATURE_WLAN_WAPI
959 if (params->encryptType == eSIR_ED_WPI) {
Govind Singhd76a5b02016-03-08 15:12:14 +0530960 ret = wma_vdev_set_param(wma->wmi_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800961 params->smesessionId,
962 WMI_VDEV_PARAM_DROP_UNENCRY,
963 false);
964 if (ret) {
965 WMA_LOGE
966 ("Set WMI_VDEV_PARAM_DROP_UNENCRY Param status:%d\n",
967 ret);
Govind Singhb30d4c02016-03-24 11:01:23 +0530968 qdf_mem_free(cmd);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800969 return ret;
970 }
971 }
972#endif /* FEATURE_WLAN_WAPI */
973
974 cmd->peer_caps = params->capab_info;
975 cmd->peer_listen_intval = params->listenInterval;
976 cmd->peer_ht_caps = params->ht_caps;
977 cmd->peer_max_mpdu = (1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR +
978 params->maxAmpduSize)) - 1;
979 cmd->peer_mpdu_density = wma_parse_mpdudensity(params->maxAmpduDensity);
980
981 if (params->supportedRates.supportedMCSSet[1] &&
982 params->supportedRates.supportedMCSSet[2])
983 cmd->peer_rate_caps |= WMI_RC_TS_FLAG;
984 else if (params->supportedRates.supportedMCSSet[1])
985 cmd->peer_rate_caps |= WMI_RC_DS_FLAG;
986
987 /* Update peer legacy rate information */
Govind Singhb30d4c02016-03-24 11:01:23 +0530988 cmd->peer_legacy_rates.num_rates = peer_legacy_rates.num_rates;
989 qdf_mem_copy(cmd->peer_legacy_rates.rates, peer_legacy_rates.rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800990 peer_legacy_rates.num_rates);
991
992 /* Update peer HT rate information */
Govind Singhb30d4c02016-03-24 11:01:23 +0530993 cmd->peer_ht_rates.num_rates = peer_ht_rates.num_rates;
994 qdf_mem_copy(cmd->peer_ht_rates.rates, peer_ht_rates.rates,
995 peer_ht_rates.num_rates);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800996
997 /* VHT Rates */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800998
999 cmd->peer_nss = peer_nss;
Naveen Rawatb14cab32015-11-02 17:01:51 -08001000 /*
1001 * Because of DBS a vdev may come up in any of the two MACs with
1002 * different capabilities. STBC capab should be fetched for given
1003 * hard_mode->MAC_id combo. It is planned that firmware should provide
1004 * these dev capabilities. But for now number of tx streams can be used
1005 * to identify if Tx STBC needs to be disabled.
1006 */
1007 if (intr->tx_streams < 2) {
1008 cmd->peer_vht_caps &= ~(1 << SIR_MAC_VHT_CAP_TXSTBC);
1009 WMA_LOGD("Num tx_streams: %d, Disabled txSTBC",
1010 intr->tx_streams);
1011 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001012 WMA_LOGD("peer_nss %d peer_ht_rates.num_rates %d ", cmd->peer_nss,
1013 peer_ht_rates.num_rates);
1014
Govind Singhb30d4c02016-03-24 11:01:23 +05301015 cmd->vht_capable = params->vhtCapable;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001016 if (params->vhtCapable) {
1017#define VHT2x2MCSMASK 0xc
Govind Singhb30d4c02016-03-24 11:01:23 +05301018 cmd->rx_max_rate = params->supportedRates.vhtRxHighestDataRate;
1019 cmd->rx_mcs_set = params->supportedRates.vhtRxMCSMap;
1020 cmd->tx_max_rate = params->supportedRates.vhtTxHighestDataRate;
1021 cmd->tx_mcs_set = params->supportedRates.vhtTxMCSMap;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001022
1023 if (params->vhtSupportedRxNss) {
1024 cmd->peer_nss = params->vhtSupportedRxNss;
1025 } else {
Govind Singhb30d4c02016-03-24 11:01:23 +05301026 cmd->peer_nss = ((cmd->rx_mcs_set & VHT2x2MCSMASK)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001027 == VHT2x2MCSMASK) ? 1 : 2;
1028 }
1029 }
1030
1031 /*
1032 * Limit nss to max number of rf chain supported by target
1033 * Otherwise Fw will crash
1034 */
1035 wma_update_txrx_chainmask(wma->num_rf_chains, &cmd->peer_nss);
1036
1037 intr->nss = cmd->peer_nss;
1038 cmd->peer_phymode = phymode;
1039 WMA_LOGD("%s: vdev_id %d associd %d peer_flags %x rate_caps %x "
1040 "peer_caps %x listen_intval %d ht_caps %x max_mpdu %d "
1041 "nss %d phymode %d peer_mpdu_density %d encr_type %d "
1042 "cmd->peer_vht_caps %x", __func__,
1043 cmd->vdev_id, cmd->peer_associd, cmd->peer_flags,
1044 cmd->peer_rate_caps, cmd->peer_caps,
1045 cmd->peer_listen_intval, cmd->peer_ht_caps,
1046 cmd->peer_max_mpdu, cmd->peer_nss, cmd->peer_phymode,
1047 cmd->peer_mpdu_density, params->encryptType,
1048 cmd->peer_vht_caps);
1049
Govind Singhb30d4c02016-03-24 11:01:23 +05301050 status = wmi_unified_peer_assoc_send(wma->wmi_handle,
1051 cmd);
1052 if (QDF_IS_STATUS_ERROR(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001053 WMA_LOGP("%s: Failed to send peer assoc command ret = %d",
1054 __func__, ret);
Govind Singhb30d4c02016-03-24 11:01:23 +05301055 qdf_mem_free(cmd);
1056
1057 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001058}
1059
1060/**
1061 * wmi_unified_vdev_set_gtx_cfg_send() - set GTX params
1062 * @wmi_handle: wmi handle
1063 * @if_id: vdev id
1064 * @gtx_info: GTX config params
1065 *
1066 * This function set GTX related params in firmware.
1067 *
1068 * Return: 0 for success or error code
1069 */
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301070QDF_STATUS wmi_unified_vdev_set_gtx_cfg_send(wmi_unified_t wmi_handle,
1071 uint32_t if_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001072 gtx_config_t *gtx_info)
1073{
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301074 struct wmi_gtx_config params;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001075
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301076 params.gtx_rt_mask[0] = gtx_info->gtxRTMask[0];
1077 params.gtx_rt_mask[1] = gtx_info->gtxRTMask[1];
1078 params.gtx_usrcfg = gtx_info->gtxUsrcfg;
1079 params.gtx_threshold = gtx_info->gtxPERThreshold;
1080 params.gtx_margin = gtx_info->gtxPERMargin;
1081 params.gtx_tpcstep = gtx_info->gtxTPCstep;
1082 params.gtx_tpcmin = gtx_info->gtxTPCMin;
1083 params.gtx_bwmask = gtx_info->gtxBWMask;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001084
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301085 return wmi_unified_vdev_set_gtx_cfg_cmd(wmi_handle,
1086 if_id, &params);
1087
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001088}
1089
1090/**
1091 * wma_update_protection_mode() - update protection mode
1092 * @wma: wma handle
1093 * @vdev_id: vdev id
1094 * @llbcoexist: protection mode info
1095 *
1096 * This function set protection mode(RTS/CTS) to fw for passed vdev id.
1097 *
1098 * Return: none
1099 */
1100void wma_update_protection_mode(tp_wma_handle wma, uint8_t vdev_id,
1101 uint8_t llbcoexist)
1102{
Govind Singhd76a5b02016-03-08 15:12:14 +05301103 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001104 enum ieee80211_protmode prot_mode;
1105
1106 prot_mode = llbcoexist ? IEEE80211_PROT_CTSONLY : IEEE80211_PROT_NONE;
1107
Govind Singhd76a5b02016-03-08 15:12:14 +05301108 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001109 WMI_VDEV_PARAM_PROTECTION_MODE,
1110 prot_mode);
1111
Govind Singhd76a5b02016-03-08 15:12:14 +05301112 if (QDF_IS_STATUS_ERROR(ret))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001113 WMA_LOGE("Failed to send wmi protection mode cmd");
1114 else
1115 WMA_LOGD("Updated protection mode %d to target", prot_mode);
1116}
1117
1118/**
1119 * wma_update_beacon_interval() - update beacon interval in fw
1120 * @wma: wma handle
1121 * @vdev_id: vdev id
1122 * @beaconInterval: becon interval
1123 *
1124 * Return: none
1125 */
1126static void
1127wma_update_beacon_interval(tp_wma_handle wma, uint8_t vdev_id,
1128 uint16_t beaconInterval)
1129{
Govind Singhd76a5b02016-03-08 15:12:14 +05301130 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001131
Govind Singhd76a5b02016-03-08 15:12:14 +05301132 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001133 WMI_VDEV_PARAM_BEACON_INTERVAL,
1134 beaconInterval);
1135
Govind Singhd76a5b02016-03-08 15:12:14 +05301136 if (QDF_IS_STATUS_ERROR(ret))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001137 WMA_LOGE("Failed to update beacon interval");
1138 else
1139 WMA_LOGI("Updated beacon interval %d for vdev %d",
1140 beaconInterval, vdev_id);
1141}
1142
1143/**
1144 * wma_process_update_beacon_params() - update beacon parameters to target
1145 * @wma: wma handle
1146 * @bcn_params: beacon parameters
1147 *
1148 * Return: none
1149 */
1150void
1151wma_process_update_beacon_params(tp_wma_handle wma,
1152 tUpdateBeaconParams *bcn_params)
1153{
1154 if (!bcn_params) {
1155 WMA_LOGE("bcn_params NULL");
1156 return;
1157 }
1158
1159 if (bcn_params->smeSessionId >= wma->max_bssid) {
1160 WMA_LOGE("Invalid vdev id %d", bcn_params->smeSessionId);
1161 return;
1162 }
1163
1164 if (bcn_params->paramChangeBitmap & PARAM_BCN_INTERVAL_CHANGED) {
1165 wma_update_beacon_interval(wma, bcn_params->smeSessionId,
1166 bcn_params->beaconInterval);
1167 }
1168
1169 if (bcn_params->paramChangeBitmap & PARAM_llBCOEXIST_CHANGED)
1170 wma_update_protection_mode(wma, bcn_params->smeSessionId,
1171 bcn_params->llbCoexist);
1172}
1173
1174/**
1175 * wma_update_cfg_params() - update cfg parameters to target
1176 * @wma: wma handle
1177 * @cfgParam: cfg parameter
1178 *
1179 * Return: none
1180 */
1181void wma_update_cfg_params(tp_wma_handle wma, tSirMsgQ *cfgParam)
1182{
1183 uint8_t vdev_id;
1184 uint32_t param_id;
1185 uint32_t cfg_val;
Govind Singhd76a5b02016-03-08 15:12:14 +05301186 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001187 /* get mac to acess CFG data base */
1188 struct sAniSirGlobal *pmac;
1189
1190 switch (cfgParam->bodyval) {
1191 case WNI_CFG_RTS_THRESHOLD:
1192 param_id = WMI_VDEV_PARAM_RTS_THRESHOLD;
1193 break;
1194 case WNI_CFG_FRAGMENTATION_THRESHOLD:
1195 param_id = WMI_VDEV_PARAM_FRAGMENTATION_THRESHOLD;
1196 break;
1197 default:
1198 WMA_LOGD("Unhandled cfg parameter %d", cfgParam->bodyval);
1199 return;
1200 }
1201
Anurag Chouhan6d760662016-02-20 16:05:43 +05301202 pmac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001203
1204 if (NULL == pmac) {
1205 WMA_LOGE("%s: Failed to get pmac", __func__);
1206 return;
1207 }
1208
1209 if (wlan_cfg_get_int(pmac, (uint16_t) cfgParam->bodyval,
1210 &cfg_val) != eSIR_SUCCESS) {
1211 WMA_LOGE("Failed to get value for CFG PARAMS %d. returning without updating",
1212 cfgParam->bodyval);
1213 return;
1214 }
1215
1216 for (vdev_id = 0; vdev_id < wma->max_bssid; vdev_id++) {
1217 if (wma->interfaces[vdev_id].handle != 0) {
Govind Singhd76a5b02016-03-08 15:12:14 +05301218 ret = wma_vdev_set_param(wma->wmi_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001219 vdev_id, param_id,
1220 cfg_val);
Govind Singhd76a5b02016-03-08 15:12:14 +05301221 if (QDF_IS_STATUS_ERROR(ret))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001222 WMA_LOGE("Update cfg params failed for vdevId %d",
1223 vdev_id);
1224 }
1225 }
1226}
1227
1228/**
1229 * wma_read_cfg_wepkey() - fill key_info for WEP key
1230 * @wma_handle: wma handle
1231 * @key_info: key_info ptr
1232 * @def_key_idx: default key index
1233 * @num_keys: number of keys
1234 *
1235 * This function reads WEP keys from cfg and fills
1236 * up key_info.
1237 *
1238 * Return: none
1239 */
1240static void wma_read_cfg_wepkey(tp_wma_handle wma_handle,
1241 tSirKeys *key_info, uint32_t *def_key_idx,
1242 uint8_t *num_keys)
1243{
1244 tSirRetStatus status;
1245 uint32_t val = SIR_MAC_KEY_LENGTH;
1246 uint8_t i, j;
1247
1248 WMA_LOGD("Reading WEP keys from cfg");
1249 /* NOTE:def_key_idx is initialized to 0 by the caller */
1250 status = wlan_cfg_get_int(wma_handle->mac_context,
1251 WNI_CFG_WEP_DEFAULT_KEYID, def_key_idx);
1252 if (status != eSIR_SUCCESS)
1253 WMA_LOGE("Unable to read default id, defaulting to 0");
1254
1255 for (i = 0, j = 0; i < SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS; i++) {
1256 status = wlan_cfg_get_str(wma_handle->mac_context,
1257 (uint16_t) WNI_CFG_WEP_DEFAULT_KEY_1 +
1258 i, key_info[j].key, &val);
1259 if (status != eSIR_SUCCESS) {
1260 WMA_LOGE("WEP key is not configured at :%d", i);
1261 } else {
1262 key_info[j].keyId = i;
1263 key_info[j].keyLength = (uint16_t) val;
1264 j++;
1265 }
1266 }
1267 *num_keys = j;
1268}
1269
1270/**
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301271 * wma_setup_install_key_cmd() - set key parameters
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001272 * @wma_handle: wma handle
1273 * @key_params: key parameters
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001274 * @mode: op mode
1275 *
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301276 * This function fills structure from information
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001277 * passed in key_params.
1278 *
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301279 * Return: QDF_STATUS_SUCCESS - success
1280 QDF_STATUS_E_FAILURE - failure
1281 QDF_STATUS_E_NOMEM - invalid request
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001282 */
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301283static QDF_STATUS wma_setup_install_key_cmd(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001284 struct wma_set_key_params
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301285 *key_params, uint8_t mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001286{
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301287 struct set_key_params params;
1288 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001289#ifdef WLAN_FEATURE_11W
1290 struct wma_txrx_node *iface = NULL;
1291#endif /* WLAN_FEATURE_11W */
1292 if ((key_params->key_type == eSIR_ED_NONE &&
1293 key_params->key_len) || (key_params->key_type != eSIR_ED_NONE &&
1294 !key_params->key_len)) {
1295 WMA_LOGE("%s:Invalid set key request", __func__);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301296 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001297 }
1298
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301299 params.vdev_id = key_params->vdev_id;
1300 params.key_idx = key_params->key_idx;
1301 qdf_mem_copy(params.peer_mac, key_params->peer_mac, IEEE80211_ADDR_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001302
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301303#ifdef FEATURE_WLAN_WAPI
1304 qdf_mem_set(params.tx_iv, 16, 0);
1305 qdf_mem_set(params.rx_iv, 16, 0);
1306#endif
1307 params.key_txmic_len = 0;
1308 params.key_rxmic_len = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001309
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301310 params.key_flags = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001311 if (key_params->unicast)
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301312 params.key_flags |= PAIRWISE_USAGE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001313 else
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301314 params.key_flags |= GROUP_USAGE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001315
1316 switch (key_params->key_type) {
1317 case eSIR_ED_NONE:
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301318 params.key_cipher = WMI_CIPHER_NONE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001319 break;
1320 case eSIR_ED_WEP40:
1321 case eSIR_ED_WEP104:
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301322 params.key_cipher = WMI_CIPHER_WEP;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001323 if (key_params->unicast &&
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301324 params.key_idx == key_params->def_key_idx) {
Ganesh Kondabattini59a4a952015-11-30 11:55:40 +05301325 WMA_LOGD("STA Mode: cmd->key_flags |= TX_USAGE");
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301326 params.key_flags |= TX_USAGE;
Ganesh Kondabattini59a4a952015-11-30 11:55:40 +05301327 } else if ((mode == wlan_op_mode_ap) &&
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301328 (params.key_idx == key_params->def_key_idx)) {
Ganesh Kondabattini59a4a952015-11-30 11:55:40 +05301329 WMA_LOGD("AP Mode: cmd->key_flags |= TX_USAGE");
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301330 params.key_flags |= TX_USAGE;
Ganesh Kondabattini59a4a952015-11-30 11:55:40 +05301331 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001332 break;
1333 case eSIR_ED_TKIP:
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301334 params.key_txmic_len = WMA_TXMIC_LEN;
1335 params.key_rxmic_len = WMA_RXMIC_LEN;
1336 params.key_cipher = WMI_CIPHER_TKIP;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001337 break;
1338#ifdef FEATURE_WLAN_WAPI
1339#define WPI_IV_LEN 16
1340 case eSIR_ED_WPI:
1341 {
1342 /*initialize receive and transmit IV with default values */
1343 /* **Note: tx_iv must be sent in reverse** */
1344 unsigned char tx_iv[16] = { 0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c,
1345 0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c,
1346 0x36, 0x5c, 0x36, 0x5c};
1347 unsigned char rx_iv[16] = { 0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36,
1348 0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36,
1349 0x5c, 0x36, 0x5c, 0x37};
1350 if (mode == wlan_op_mode_ap) {
1351 /* Authenticator initializes the value of PN as
1352 * 0x5C365C365C365C365C365C365C365C36 for MCastkey Update
1353 */
1354 if (key_params->unicast)
1355 tx_iv[0] = 0x37;
1356
1357 rx_iv[WPI_IV_LEN - 1] = 0x36;
1358 } else {
1359 if (!key_params->unicast)
1360 rx_iv[WPI_IV_LEN - 1] = 0x36;
1361 }
1362
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301363 params.key_txmic_len = WMA_TXMIC_LEN;
1364 params.key_rxmic_len = WMA_RXMIC_LEN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001365
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301366 qdf_mem_copy(&params.rx_iv, &rx_iv,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001367 WPI_IV_LEN);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301368 qdf_mem_copy(&params.tx_iv, &tx_iv,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001369 WPI_IV_LEN);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301370 params.key_cipher = WMI_CIPHER_WAPI;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001371 break;
1372 }
1373#endif /* FEATURE_WLAN_WAPI */
1374 case eSIR_ED_CCMP:
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301375 params.key_cipher = WMI_CIPHER_AES_CCM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001376 break;
1377#ifdef WLAN_FEATURE_11W
1378 case eSIR_ED_AES_128_CMAC:
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301379 params.key_cipher = WMI_CIPHER_AES_CMAC;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001380 break;
1381#endif /* WLAN_FEATURE_11W */
1382 default:
1383 /* TODO: MFP ? */
1384 WMA_LOGE("%s:Invalid encryption type:%d", __func__,
1385 key_params->key_type);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301386 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001387 }
1388
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001389#ifdef BIG_ENDIAN_HOST
1390 {
1391 /* for big endian host, copy engine byte_swap is enabled
1392 * But the key data content is in network byte order
1393 * Need to byte swap the key data content - so when copy engine
1394 * does byte_swap - target gets key_data content in the correct
1395 * order.
1396 */
1397 int8_t i;
1398 uint32_t *destp, *srcp;
1399
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301400 destp = (uint32_t *) params.key_data;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001401 srcp = (uint32_t *) key_params->key_data;
1402 for (i = 0;
1403 i < roundup(key_params->key_len, sizeof(uint32_t)) / 4;
1404 i++) {
1405 *destp = le32_to_cpu(*srcp);
1406 destp++;
1407 srcp++;
1408 }
1409 }
1410#else
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301411 qdf_mem_copy((void *)params.key_data,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001412 (const void *)key_params->key_data, key_params->key_len);
1413#endif /* BIG_ENDIAN_HOST */
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301414 params.key_len = key_params->key_len;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001415
1416#ifdef WLAN_FEATURE_11W
1417 if (key_params->key_type == eSIR_ED_AES_128_CMAC) {
1418 iface = &wma_handle->interfaces[key_params->vdev_id];
1419 if (iface) {
1420 iface->key.key_length = key_params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301421 qdf_mem_copy(iface->key.key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001422 (const void *)key_params->key_data,
1423 iface->key.key_length);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301424 if ((params.key_idx == WMA_IGTK_KEY_INDEX_4) ||
1425 (params.key_idx == WMA_IGTK_KEY_INDEX_5))
1426 qdf_mem_zero(iface->key.key_id[params.key_idx -
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001427 WMA_IGTK_KEY_INDEX_4].ipn,
1428 CMAC_IPN_LEN);
1429 }
1430 }
1431#endif /* WLAN_FEATURE_11W */
1432
1433 WMA_LOGD("Key setup : vdev_id %d key_idx %d key_type %d key_len %d"
1434 " unicast %d peer_mac %pM def_key_idx %d", key_params->vdev_id,
1435 key_params->key_idx, key_params->key_type, key_params->key_len,
1436 key_params->unicast, key_params->peer_mac,
1437 key_params->def_key_idx);
1438
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301439 status = wmi_unified_setup_install_key_cmd(wma_handle->wmi_handle,
1440 &params);
1441
1442 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001443}
1444
1445/**
1446 * wma_set_bsskey() - set encryption key to fw.
1447 * @wma_handle: wma handle
1448 * @key_info: key info
1449 *
1450 * Return: none
1451 */
1452void wma_set_bsskey(tp_wma_handle wma_handle, tpSetBssKeyParams key_info)
1453{
1454 struct wma_set_key_params key_params;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301455 QDF_STATUS status = QDF_STATUS_SUCCESS;
1456 uint32_t i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001457 uint32_t def_key_idx = 0;
1458 ol_txrx_vdev_handle txrx_vdev;
1459
1460 WMA_LOGD("BSS key setup");
1461 txrx_vdev = wma_find_vdev_by_id(wma_handle, key_info->smesessionId);
1462 if (!txrx_vdev) {
1463 WMA_LOGE("%s:Invalid vdev handle", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301464 key_info->status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001465 goto out;
1466 }
1467
1468 /*
1469 * For IBSS, WMI expects the BSS key to be set per peer key
1470 * So cache the BSS key in the wma_handle and re-use it when the
1471 * STA key is been setup for a peer
1472 */
1473 if (wlan_op_mode_ibss == txrx_vdev->opmode) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301474 key_info->status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001475 if (wma_handle->ibss_started > 0)
1476 goto out;
1477 WMA_LOGD("Caching IBSS Key");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301478 qdf_mem_copy(&wma_handle->ibsskey_info, key_info,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001479 sizeof(tSetBssKeyParams));
1480 }
1481
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301482 qdf_mem_set(&key_params, sizeof(key_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001483 key_params.vdev_id = key_info->smesessionId;
1484 key_params.key_type = key_info->encType;
1485 key_params.singl_tid_rc = key_info->singleTidRc;
1486 key_params.unicast = false;
1487 if (txrx_vdev->opmode == wlan_op_mode_sta) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301488 qdf_mem_copy(key_params.peer_mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001489 wma_handle->interfaces[key_info->smesessionId].bssid,
1490 IEEE80211_ADDR_LEN);
1491 } else {
1492 /* vdev mac address will be passed for all other modes */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301493 qdf_mem_copy(key_params.peer_mac, txrx_vdev->mac_addr.raw,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001494 IEEE80211_ADDR_LEN);
1495 WMA_LOGA("BSS Key setup with vdev_mac %pM\n",
1496 txrx_vdev->mac_addr.raw);
1497 }
1498
1499 if (key_info->numKeys == 0 &&
1500 (key_info->encType == eSIR_ED_WEP40 ||
1501 key_info->encType == eSIR_ED_WEP104)) {
1502 wma_read_cfg_wepkey(wma_handle, key_info->key,
1503 &def_key_idx, &key_info->numKeys);
1504 }
1505
1506 for (i = 0; i < key_info->numKeys; i++) {
1507 if (key_params.key_type != eSIR_ED_NONE &&
1508 !key_info->key[i].keyLength)
1509 continue;
1510 if (key_info->encType == eSIR_ED_WPI) {
1511 key_params.key_idx = key_info->key[i].keyId;
1512 key_params.def_key_idx = key_info->key[i].keyId;
1513 } else
1514 key_params.key_idx = key_info->key[i].keyId;
1515
1516 key_params.key_len = key_info->key[i].keyLength;
1517 if (key_info->encType == eSIR_ED_TKIP) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301518 qdf_mem_copy(key_params.key_data,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001519 key_info->key[i].key, 16);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301520 qdf_mem_copy(&key_params.key_data[16],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001521 &key_info->key[i].key[24], 8);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301522 qdf_mem_copy(&key_params.key_data[24],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001523 &key_info->key[i].key[16], 8);
1524 } else
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301525 qdf_mem_copy((void *)key_params.key_data,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001526 (const void *)key_info->key[i].key,
1527 key_info->key[i].keyLength);
1528
1529 WMA_LOGD("%s: bss key[%d] length %d", __func__, i,
1530 key_info->key[i].keyLength);
1531
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301532 status = wma_setup_install_key_cmd(wma_handle, &key_params,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001533 txrx_vdev->opmode);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301534 if (status == QDF_STATUS_E_NOMEM) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001535 WMA_LOGE("%s:Failed to setup install key buf",
1536 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301537 key_info->status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001538 goto out;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301539 } else if (status == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001540 WMA_LOGE("%s:Failed to send install key command",
1541 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301542 key_info->status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001543 goto out;
1544 }
1545 }
1546
1547 wma_handle->ibss_started++;
1548 /* TODO: Should we wait till we get HTT_T2H_MSG_TYPE_SEC_IND? */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301549 key_info->status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001550
1551out:
1552 wma_send_msg(wma_handle, WMA_SET_BSSKEY_RSP, (void *)key_info, 0);
1553}
1554
1555#ifdef QCA_IBSS_SUPPORT
1556/**
1557 * wma_calc_ibss_heart_beat_timer() - calculate IBSS heart beat timer
1558 * @peer_num: number of peers
1559 *
1560 * Return: heart beat timer value
1561 */
1562static uint16_t wma_calc_ibss_heart_beat_timer(int16_t peer_num)
1563{
1564 /* heart beat timer value look-up table */
1565 /* entry index : (the number of currently connected peers) - 1
1566 entry value : the heart time threshold value in seconds for
1567 detecting ibss peer departure */
1568 static const uint16_t heart_beat_timer[MAX_IBSS_PEERS] = {
1569 4, 4, 4, 4, 4, 4, 4, 4,
1570 8, 8, 8, 8, 8, 8, 8, 8,
1571 12, 12, 12, 12, 12, 12, 12, 12,
1572 16, 16, 16, 16, 16, 16, 16, 16
1573 };
1574
1575 if (peer_num < 1 || peer_num > MAX_IBSS_PEERS)
1576 return 0;
1577
1578 return heart_beat_timer[peer_num - 1];
1579
1580}
1581
1582/**
1583 * wma_adjust_ibss_heart_beat_timer() - set ibss heart beat timer in fw.
1584 * @wma: wma handle
1585 * @vdev_id: vdev id
1586 * @peer_num_delta: peer number delta value
1587 *
1588 * Return: none
1589 */
1590void wma_adjust_ibss_heart_beat_timer(tp_wma_handle wma,
1591 uint8_t vdev_id,
1592 int8_t peer_num_delta)
1593{
1594 ol_txrx_vdev_handle vdev;
1595 int16_t new_peer_num;
1596 uint16_t new_timer_value_sec;
1597 uint32_t new_timer_value_ms;
Govind Singhd76a5b02016-03-08 15:12:14 +05301598 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001599
1600 if (peer_num_delta != 1 && peer_num_delta != -1) {
1601 WMA_LOGE("Invalid peer_num_delta value %d", peer_num_delta);
1602 return;
1603 }
1604
1605 vdev = wma_find_vdev_by_id(wma, vdev_id);
1606 if (!vdev) {
1607 WMA_LOGE("vdev not found : vdev_id %d", vdev_id);
1608 return;
1609 }
1610
1611 new_peer_num = vdev->ibss_peer_num + peer_num_delta;
1612 if (new_peer_num > MAX_IBSS_PEERS || new_peer_num < 0) {
1613 WMA_LOGE("new peer num %d out of valid boundary", new_peer_num);
1614 return;
1615 }
1616
1617 /* adjust peer numbers */
1618 vdev->ibss_peer_num = new_peer_num;
1619
1620 /* reset timer value if all peers departed */
1621 if (new_peer_num == 0) {
1622 vdev->ibss_peer_heart_beat_timer = 0;
1623 return;
1624 }
1625
1626 /* calculate new timer value */
1627 new_timer_value_sec = wma_calc_ibss_heart_beat_timer(new_peer_num);
1628 if (new_timer_value_sec == 0) {
1629 WMA_LOGE("timer value %d is invalid for peer number %d",
1630 new_timer_value_sec, new_peer_num);
1631 return;
1632 }
1633 if (new_timer_value_sec == vdev->ibss_peer_heart_beat_timer) {
1634 WMA_LOGD("timer value %d stays same, no need to notify target",
1635 new_timer_value_sec);
1636 return;
1637 }
1638
1639 /* send new timer value to target */
1640 vdev->ibss_peer_heart_beat_timer = new_timer_value_sec;
1641
1642 new_timer_value_ms = ((uint32_t) new_timer_value_sec) * 1000;
1643
Govind Singhd76a5b02016-03-08 15:12:14 +05301644 status = wma_vdev_set_param(wma->wmi_handle, vdev_id,
1645 WMI_VDEV_PARAM_IBSS_MAX_BCN_LOST_MS,
1646 new_timer_value_ms);
1647 if (QDF_IS_STATUS_ERROR(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001648 WMA_LOGE("Failed to set IBSS link monitoring timer value");
1649 return;
1650 }
1651
1652 WMA_LOGD("Set IBSS link monitor timer: peer_num = %d timer_value = %d",
1653 new_peer_num, new_timer_value_ms);
1654}
1655
1656#endif /* QCA_IBSS_SUPPORT */
1657/**
1658 * wma_set_ibsskey_helper() - cached IBSS key in wma handle
1659 * @wma_handle: wma handle
1660 * @key_info: set bss key info
1661 * @peerMacAddr: peer mac address
1662 *
1663 * Return: none
1664 */
1665static void wma_set_ibsskey_helper(tp_wma_handle wma_handle,
1666 tpSetBssKeyParams key_info,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301667 struct qdf_mac_addr peer_macaddr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001668{
1669 struct wma_set_key_params key_params;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301670 QDF_STATUS status = QDF_STATUS_SUCCESS;
1671 uint32_t i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001672 uint32_t def_key_idx = 0;
1673 ol_txrx_vdev_handle txrx_vdev;
1674
1675 WMA_LOGD("BSS key setup for peer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001676 txrx_vdev = wma_find_vdev_by_id(wma_handle, key_info->smesessionId);
1677 if (!txrx_vdev) {
1678 WMA_LOGE("%s:Invalid vdev handle", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301679 key_info->status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001680 return;
1681 }
1682
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301683 qdf_mem_set(&key_params, sizeof(key_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001684 key_params.vdev_id = key_info->smesessionId;
1685 key_params.key_type = key_info->encType;
1686 key_params.singl_tid_rc = key_info->singleTidRc;
1687 key_params.unicast = false;
1688 ASSERT(wlan_op_mode_ibss == txrx_vdev->opmode);
1689
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301690 qdf_mem_copy(key_params.peer_mac, peer_macaddr.bytes,
Srinivas Girigowdad5965c42015-12-04 13:43:16 -08001691 IEEE80211_ADDR_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001692
1693 if (key_info->numKeys == 0 &&
1694 (key_info->encType == eSIR_ED_WEP40 ||
1695 key_info->encType == eSIR_ED_WEP104)) {
1696 wma_read_cfg_wepkey(wma_handle, key_info->key,
1697 &def_key_idx, &key_info->numKeys);
1698 }
1699
1700 for (i = 0; i < key_info->numKeys; i++) {
1701 if (key_params.key_type != eSIR_ED_NONE &&
1702 !key_info->key[i].keyLength)
1703 continue;
1704 key_params.key_idx = key_info->key[i].keyId;
1705 key_params.key_len = key_info->key[i].keyLength;
1706 if (key_info->encType == eSIR_ED_TKIP) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301707 qdf_mem_copy(key_params.key_data,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001708 key_info->key[i].key, 16);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301709 qdf_mem_copy(&key_params.key_data[16],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001710 &key_info->key[i].key[24], 8);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301711 qdf_mem_copy(&key_params.key_data[24],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001712 &key_info->key[i].key[16], 8);
1713 } else
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301714 qdf_mem_copy((void *)key_params.key_data,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001715 (const void *)key_info->key[i].key,
1716 key_info->key[i].keyLength);
1717
1718 WMA_LOGD("%s: peer bcast key[%d] length %d", __func__, i,
1719 key_info->key[i].keyLength);
1720
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301721 status = wma_setup_install_key_cmd(wma_handle, &key_params,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001722 txrx_vdev->opmode);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301723 if (status == QDF_STATUS_E_NOMEM) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001724 WMA_LOGE("%s:Failed to setup install key buf",
1725 __func__);
1726 return;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301727 } else if (status == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001728 WMA_LOGE("%s:Failed to send install key command",
1729 __func__);
1730 }
1731 }
1732}
1733
1734/**
1735 * wma_set_stakey() - set encryption key
1736 * @wma_handle: wma handle
1737 * @key_info: station key info
1738 *
1739 * This function sets encryption key for WEP/WPA/WPA2
1740 * encryption mode in firmware and send response to upper layer.
1741 *
1742 * Return: none
1743 */
1744void wma_set_stakey(tp_wma_handle wma_handle, tpSetStaKeyParams key_info)
1745{
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301746 int32_t i;
1747 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001748 ol_txrx_pdev_handle txrx_pdev;
1749 ol_txrx_vdev_handle txrx_vdev;
1750 struct ol_txrx_peer_t *peer;
1751 uint8_t num_keys = 0, peer_id;
1752 struct wma_set_key_params key_params;
1753 uint32_t def_key_idx = 0;
1754
1755 WMA_LOGD("STA key setup");
1756
1757 /* Get the txRx Pdev handle */
Anurag Chouhan6d760662016-02-20 16:05:43 +05301758 txrx_pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001759 if (!txrx_pdev) {
1760 WMA_LOGE("%s:Invalid txrx pdev handle", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301761 key_info->status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001762 goto out;
1763 }
1764
Srinivas Girigowdad5965c42015-12-04 13:43:16 -08001765 peer = ol_txrx_find_peer_by_addr(txrx_pdev,
1766 key_info->peer_macaddr.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001767 &peer_id);
1768 if (!peer) {
1769 WMA_LOGE("%s:Invalid peer for key setting", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301770 key_info->status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001771 goto out;
1772 }
1773
1774 txrx_vdev = wma_find_vdev_by_id(wma_handle, key_info->smesessionId);
1775 if (!txrx_vdev) {
1776 WMA_LOGE("%s:TxRx Vdev Handle is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301777 key_info->status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001778 goto out;
1779 }
1780
1781 if (key_info->defWEPIdx == WMA_INVALID_KEY_IDX &&
1782 (key_info->encType == eSIR_ED_WEP40 ||
1783 key_info->encType == eSIR_ED_WEP104) &&
1784 txrx_vdev->opmode != wlan_op_mode_ap) {
1785 wma_read_cfg_wepkey(wma_handle, key_info->key,
1786 &def_key_idx, &num_keys);
1787 key_info->defWEPIdx = def_key_idx;
1788 } else {
1789 num_keys = SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS;
1790 if (key_info->encType != eSIR_ED_NONE) {
1791 for (i = 0; i < num_keys; i++) {
1792 if (key_info->key[i].keyDirection ==
1793 eSIR_TX_DEFAULT) {
1794 key_info->defWEPIdx = i;
1795 break;
1796 }
1797 }
1798 }
1799 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301800 qdf_mem_set(&key_params, sizeof(key_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001801 key_params.vdev_id = key_info->smesessionId;
1802 key_params.key_type = key_info->encType;
1803 key_params.singl_tid_rc = key_info->singleTidRc;
1804 key_params.unicast = true;
1805 key_params.def_key_idx = key_info->defWEPIdx;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301806 qdf_mem_copy((void *)key_params.peer_mac,
Srinivas Girigowdad5965c42015-12-04 13:43:16 -08001807 (const void *)key_info->peer_macaddr.bytes,
1808 IEEE80211_ADDR_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001809 for (i = 0; i < num_keys; i++) {
1810 if (key_params.key_type != eSIR_ED_NONE &&
1811 !key_info->key[i].keyLength)
1812 continue;
1813 if (key_info->encType == eSIR_ED_TKIP) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301814 qdf_mem_copy(key_params.key_data,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001815 key_info->key[i].key, 16);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301816 qdf_mem_copy(&key_params.key_data[16],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001817 &key_info->key[i].key[24], 8);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301818 qdf_mem_copy(&key_params.key_data[24],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001819 &key_info->key[i].key[16], 8);
1820 } else
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301821 qdf_mem_copy(key_params.key_data, key_info->key[i].key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001822 key_info->key[i].keyLength);
1823 if (key_info->encType == eSIR_ED_WPI) {
1824 key_params.key_idx = key_info->key[i].keyId;
1825 key_params.def_key_idx = key_info->key[i].keyId;
1826 } else
1827 key_params.key_idx = i;
1828
1829 key_params.key_len = key_info->key[i].keyLength;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301830 status = wma_setup_install_key_cmd(wma_handle, &key_params,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001831 txrx_vdev->opmode);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301832 if (status == QDF_STATUS_E_NOMEM) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001833 WMA_LOGE("%s:Failed to setup install key buf",
1834 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301835 key_info->status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001836 goto out;
1837 }
1838
1839 WMA_LOGD("%s: peer unicast key[%d] %d ", __func__, i,
1840 key_info->key[i].keyLength);
1841
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301842 if (status == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001843 WMA_LOGE("%s:Failed to send install key command",
1844 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301845 key_info->status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001846 goto out;
1847 }
1848 }
1849
1850 /* In IBSS mode, set the BSS KEY for this peer
1851 * BSS key is supposed to be cache into wma_handle
1852 */
1853 if (wlan_op_mode_ibss == txrx_vdev->opmode) {
1854 wma_set_ibsskey_helper(wma_handle, &wma_handle->ibsskey_info,
Srinivas Girigowdad5965c42015-12-04 13:43:16 -08001855 key_info->peer_macaddr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001856 }
1857
1858 /* TODO: Should we wait till we get HTT_T2H_MSG_TYPE_SEC_IND? */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301859 key_info->status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001860out:
1861 if (key_info->sendRsp)
1862 wma_send_msg(wma_handle, WMA_SET_STAKEY_RSP, (void *)key_info,
1863 0);
1864}
1865
1866/**
1867 * wma_process_update_edca_param_req() - update EDCA params
1868 * @handle: wma handle
1869 * @edca_params: edca parameters
1870 *
1871 * This function updates EDCA parameters to the target
1872 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05301873 * Return: QDF Status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001874 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301875QDF_STATUS wma_process_update_edca_param_req(WMA_HANDLE handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001876 tEdcaParams *edca_params)
1877{
1878 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301879 wmi_wmm_vparams wmm_param[WME_NUM_AC];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001880 tSirMacEdcaParamRecord *edca_record;
1881 int ac;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001882 ol_txrx_pdev_handle pdev;
1883 struct ol_tx_wmm_param_t ol_tx_wmm_param;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301884 uint8_t vdev_id;
1885 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001886
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301887 vdev_id = edca_params->bssIdx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001888
1889 for (ac = 0; ac < WME_NUM_AC; ac++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001890 switch (ac) {
1891 case WME_AC_BE:
1892 edca_record = &edca_params->acbe;
1893 break;
1894 case WME_AC_BK:
1895 edca_record = &edca_params->acbk;
1896 break;
1897 case WME_AC_VI:
1898 edca_record = &edca_params->acvi;
1899 break;
1900 case WME_AC_VO:
1901 edca_record = &edca_params->acvo;
1902 break;
1903 default:
1904 goto fail;
1905 }
1906
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301907 wma_update_edca_params_for_ac(edca_record, &wmm_param[ac], ac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001908
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301909 ol_tx_wmm_param.ac[ac].aifs = wmm_param[ac].aifs;
1910 ol_tx_wmm_param.ac[ac].cwmin = wmm_param[ac].cwmin;
1911 ol_tx_wmm_param.ac[ac].cwmax = wmm_param[ac].cwmax;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001912 }
1913
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301914 status = wmi_unified_process_update_edca_param(wma_handle->wmi_handle,
1915 vdev_id, wmm_param);
1916 if (status == QDF_STATUS_E_NOMEM)
1917 return status;
1918 else if (status == QDF_STATUS_E_FAILURE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001919 goto fail;
1920
Anurag Chouhan6d760662016-02-20 16:05:43 +05301921 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Himanshu Agarwal94045e42015-10-19 19:16:19 +05301922 if (pdev)
1923 ol_txrx_set_wmm_param(pdev, ol_tx_wmm_param);
1924 else
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301925 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001926
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301927 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001928
1929fail:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001930 WMA_LOGE("%s: Failed to set WMM Paremeters", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301931 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001932}
1933
1934/**
1935 * wmi_unified_probe_rsp_tmpl_send() - send probe response template to fw
1936 * @wma: wma handle
1937 * @vdev_id: vdev id
1938 * @probe_rsp_info: probe response info
1939 *
1940 * Return: 0 for success or error code
1941 */
1942static int wmi_unified_probe_rsp_tmpl_send(tp_wma_handle wma,
1943 uint8_t vdev_id,
1944 tpSendProbeRespParams probe_rsp_info)
1945{
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301946 uint8_t *frm;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001947 uint64_t adjusted_tsf_le;
1948 struct ieee80211_frame *wh;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301949 struct wmi_probe_resp_params params;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001950
1951 WMA_LOGD(FL("Send probe response template for vdev %d"), vdev_id);
1952
1953 frm = probe_rsp_info->pProbeRespTemplate;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301954
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001955 /*
1956 * Make the TSF offset negative so probe response in the same
1957 * staggered batch have the same TSF.
1958 */
1959 adjusted_tsf_le = cpu_to_le64(0ULL -
1960 wma->interfaces[vdev_id].tsfadjust);
1961 /* Update the timstamp in the probe response buffer with adjusted TSF */
1962 wh = (struct ieee80211_frame *)frm;
1963 A_MEMCPY(&wh[1], &adjusted_tsf_le, sizeof(adjusted_tsf_le));
1964
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301965 params.pProbeRespTemplate = probe_rsp_info->pProbeRespTemplate;
1966 params.probeRespTemplateLen = probe_rsp_info->probeRespTemplateLen;
1967 qdf_mem_copy(params.bssId, probe_rsp_info->bssId,
1968 WMI_ETH_LEN);
1969 qdf_mem_copy(params.ucProxyProbeReqValidIEBmap,
1970 probe_rsp_info->ucProxyProbeReqValidIEBmap,
1971 8 * sizeof(uint32_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001972
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301973 return wmi_unified_probe_rsp_tmpl_send_cmd(wma->wmi_handle, vdev_id,
1974 &params, frm);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001975}
1976
1977/**
Govind Singh61ad2622016-02-22 17:25:02 +05301978 * wma_unified_bcn_tmpl_send() - send beacon template to fw
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001979 * @wma:wma handle
1980 * @vdev_id: vdev id
1981 * @bcn_info: beacon info
1982 * @bytes_to_strip: bytes to strip
1983 *
Govind Singh61ad2622016-02-22 17:25:02 +05301984 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001985 */
Govind Singh61ad2622016-02-22 17:25:02 +05301986static QDF_STATUS wma_unified_bcn_tmpl_send(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001987 uint8_t vdev_id,
Govind Singh61ad2622016-02-22 17:25:02 +05301988 const tpSendbeaconParams bcn_info,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001989 uint8_t bytes_to_strip)
1990{
Govind Singh61ad2622016-02-22 17:25:02 +05301991 struct beacon_params params = {0};
1992 uint32_t tmpl_len, tmpl_len_aligned;
1993 uint8_t *frm;
1994 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001995 uint8_t *p2p_ie;
1996 uint16_t p2p_ie_len = 0;
1997 uint64_t adjusted_tsf_le;
1998 struct ieee80211_frame *wh;
1999
2000 WMA_LOGD("Send beacon template for vdev %d", vdev_id);
2001
2002 if (bcn_info->p2pIeOffset) {
2003 p2p_ie = bcn_info->beacon + bcn_info->p2pIeOffset;
2004 p2p_ie_len = (uint16_t) p2p_ie[1] + 2;
2005 }
2006
2007 /*
2008 * XXX: The first byte of beacon buffer contains beacon length
2009 * only when UMAC in sending the beacon template. In othercases
2010 * (ex: from tbtt update) beacon length is read from beacon
2011 * information.
2012 */
2013 if (bytes_to_strip)
2014 tmpl_len = *(uint32_t *) &bcn_info->beacon[0];
2015 else
2016 tmpl_len = bcn_info->beaconLength;
2017 if (p2p_ie_len) {
2018 tmpl_len -= (uint32_t) p2p_ie_len;
2019 }
2020
2021 frm = bcn_info->beacon + bytes_to_strip;
2022 tmpl_len_aligned = roundup(tmpl_len, sizeof(A_UINT32));
2023 /*
2024 * Make the TSF offset negative so beacons in the same
2025 * staggered batch have the same TSF.
2026 */
2027 adjusted_tsf_le = cpu_to_le64(0ULL -
2028 wma->interfaces[vdev_id].tsfadjust);
2029 /* Update the timstamp in the beacon buffer with adjusted TSF */
2030 wh = (struct ieee80211_frame *)frm;
2031 A_MEMCPY(&wh[1], &adjusted_tsf_le, sizeof(adjusted_tsf_le));
2032
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002033
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002034
Govind Singh61ad2622016-02-22 17:25:02 +05302035 params.vdev_id = vdev_id;
2036 params.tim_ie_offset = bcn_info->timIeOffset - bytes_to_strip;
2037 params.tmpl_len = tmpl_len;
2038 params.frm = frm;
2039 params.tmpl_len_aligned = tmpl_len_aligned;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002040
Govind Singh61ad2622016-02-22 17:25:02 +05302041 ret = wmi_unified_beacon_send_cmd(wma->wmi_handle,
2042 &params);
2043 if (QDF_IS_STATUS_ERROR(ret)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002044 WMA_LOGE("%s: Failed to send bcn tmpl: %d", __func__, ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002045 }
2046
2047 return ret;
2048}
2049
2050/**
2051 * wma_store_bcn_tmpl() - store beacon template
2052 * @wma: wma handle
2053 * @vdev_id: vdev id
2054 * @bcn_info: beacon params
2055 *
2056 * This function stores beacon template locally.
2057 * This will send to target on the reception of
2058 * SWBA event.
2059 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302060 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002061 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302062QDF_STATUS wma_store_bcn_tmpl(tp_wma_handle wma, uint8_t vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002063 tpSendbeaconParams bcn_info)
2064{
2065 struct beacon_info *bcn;
2066 uint32_t len;
2067 uint8_t *bcn_payload;
2068 struct beacon_tim_ie *tim_ie;
2069
2070 bcn = wma->interfaces[vdev_id].beacon;
2071 if (!bcn || !bcn->buf) {
2072 WMA_LOGE("%s: Memory is not allocated to hold bcn template",
2073 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302074 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002075 }
2076
2077 len = *(u32 *) &bcn_info->beacon[0];
2078 if (len > WMA_BCN_BUF_MAX_SIZE) {
2079 WMA_LOGE("%s: Received beacon len %d exceeding max limit %d",
2080 __func__, len, WMA_BCN_BUF_MAX_SIZE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302081 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002082 }
2083 WMA_LOGD("%s: Storing received beacon template buf to local buffer",
2084 __func__);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302085 qdf_spin_lock_bh(&bcn->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002086
2087 /*
2088 * Copy received beacon template content in local buffer.
2089 * this will be send to target on the reception of SWBA
2090 * event from target.
2091 */
Nirav Shahcbc6d722016-03-01 16:24:53 +05302092 qdf_nbuf_trim_tail(bcn->buf, qdf_nbuf_len(bcn->buf));
2093 memcpy(qdf_nbuf_data(bcn->buf),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002094 bcn_info->beacon + 4 /* Exclude beacon length field */,
2095 len);
2096 if (bcn_info->timIeOffset > 3) {
2097 bcn->tim_ie_offset = bcn_info->timIeOffset - 4;
2098 } else {
2099 bcn->tim_ie_offset = bcn_info->timIeOffset;
2100 }
2101
2102 if (bcn_info->p2pIeOffset > 3) {
2103 bcn->p2p_ie_offset = bcn_info->p2pIeOffset - 4;
2104 } else {
2105 bcn->p2p_ie_offset = bcn_info->p2pIeOffset;
2106 }
Nirav Shahcbc6d722016-03-01 16:24:53 +05302107 bcn_payload = qdf_nbuf_data(bcn->buf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002108 if (bcn->tim_ie_offset) {
2109 tim_ie =
2110 (struct beacon_tim_ie *)(&bcn_payload[bcn->tim_ie_offset]);
2111 /*
2112 * Intial Value of bcn->dtim_count will be 0.
2113 * But if the beacon gets updated then current dtim
2114 * count will be restored
2115 */
2116 tim_ie->dtim_count = bcn->dtim_count;
2117 tim_ie->tim_bitctl = 0;
2118 }
2119
Nirav Shahcbc6d722016-03-01 16:24:53 +05302120 qdf_nbuf_put_tail(bcn->buf, len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002121 bcn->len = len;
2122
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302123 qdf_spin_unlock_bh(&bcn->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002124
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302125 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002126}
2127
2128/**
2129 * wma_tbttoffset_update_event_handler() - tbtt offset update handler
2130 * @handle: wma handle
2131 * @event: event buffer
2132 * @len: data length
2133 *
2134 * Return: 0 for success or error code
2135 */
2136int wma_tbttoffset_update_event_handler(void *handle, uint8_t *event,
2137 uint32_t len)
2138{
2139 tp_wma_handle wma = (tp_wma_handle) handle;
2140 WMI_TBTTOFFSET_UPDATE_EVENTID_param_tlvs *param_buf;
2141 wmi_tbtt_offset_event_fixed_param *tbtt_offset_event;
2142 struct wma_txrx_node *intf;
2143 struct beacon_info *bcn;
2144 tSendbeaconParams bcn_info;
2145 uint32_t *adjusted_tsf = NULL;
2146 uint32_t if_id = 0, vdev_map;
2147
2148 if (!wma) {
2149 WMA_LOGE("Invalid wma handle");
2150 return -EINVAL;
2151 }
2152
2153 param_buf = (WMI_TBTTOFFSET_UPDATE_EVENTID_param_tlvs *) event;
2154 if (!param_buf) {
2155 WMA_LOGE("Invalid tbtt update event buffer");
2156 return -EINVAL;
2157 }
2158
2159 tbtt_offset_event = param_buf->fixed_param;
2160 intf = wma->interfaces;
2161 vdev_map = tbtt_offset_event->vdev_map;
2162 adjusted_tsf = param_buf->tbttoffset_list;
2163 if (!adjusted_tsf) {
2164 WMA_LOGE("%s: Invalid adjusted_tsf", __func__);
2165 return -EINVAL;
2166 }
2167
2168 for (; (vdev_map); vdev_map >>= 1, if_id++) {
2169 if (!(vdev_map & 0x1) || (!(intf[if_id].handle)))
2170 continue;
2171
2172 bcn = intf[if_id].beacon;
2173 if (!bcn) {
2174 WMA_LOGE("%s: Invalid beacon", __func__);
2175 return -EINVAL;
2176 }
2177 if (!bcn->buf) {
2178 WMA_LOGE("%s: Invalid beacon buffer", __func__);
2179 return -EINVAL;
2180 }
2181 /* Save the adjusted TSF */
2182 intf[if_id].tsfadjust = adjusted_tsf[if_id];
2183
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302184 qdf_spin_lock_bh(&bcn->lock);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302185 qdf_mem_zero(&bcn_info, sizeof(bcn_info));
Nirav Shahcbc6d722016-03-01 16:24:53 +05302186 bcn_info.beacon = qdf_nbuf_data(bcn->buf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002187 bcn_info.p2pIeOffset = bcn->p2p_ie_offset;
2188 bcn_info.beaconLength = bcn->len;
2189 bcn_info.timIeOffset = bcn->tim_ie_offset;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302190 qdf_spin_unlock_bh(&bcn->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002191
2192 /* Update beacon template in firmware */
Govind Singh61ad2622016-02-22 17:25:02 +05302193 wma_unified_bcn_tmpl_send(wma, if_id, &bcn_info, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002194 }
2195 return 0;
2196}
2197
2198/**
2199 * wma_p2p_go_set_beacon_ie() - set beacon IE for p2p go
2200 * @wma_handle: wma handle
2201 * @vdev_id: vdev id
2202 * @p2pIe: p2p IE
2203 *
2204 * Return: 0 for success or error code
2205 */
2206static int wma_p2p_go_set_beacon_ie(t_wma_handle *wma_handle,
2207 A_UINT32 vdev_id, uint8_t *p2pIe)
2208{
Himanshu Agarwal009f1572016-03-09 17:26:02 +05302209 if (!wma_handle) {
2210 WMA_LOGE("%s: wma handle is NULL", __func__);
2211 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002212 }
2213
Himanshu Agarwal009f1572016-03-09 17:26:02 +05302214 return wmi_unified_p2p_go_set_beacon_ie_cmd(wma_handle->wmi_handle,
2215 vdev_id, p2pIe);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002216}
2217
2218/**
2219 * wma_send_probe_rsp_tmpl() - send probe resp template
2220 * @wma: wma handle
2221 * @probe_rsp_info: probe response info
2222 *
2223 * This funciton sends probe response template to fw which
2224 * firmware will use in case of probe response offload.
2225 *
2226 * Return: none
2227 */
2228void wma_send_probe_rsp_tmpl(tp_wma_handle wma,
2229 tpSendProbeRespParams probe_rsp_info)
2230{
2231 ol_txrx_vdev_handle vdev;
2232 uint8_t vdev_id;
2233 tpAniProbeRspStruct probe_rsp;
2234
2235 if (!probe_rsp_info) {
2236 WMA_LOGE(FL("probe_rsp_info is NULL"));
2237 return;
2238 }
2239
2240 probe_rsp = (tpAniProbeRspStruct) (probe_rsp_info->pProbeRespTemplate);
2241 if (!probe_rsp) {
2242 WMA_LOGE(FL("probe_rsp is NULL"));
2243 return;
2244 }
2245
2246 vdev = wma_find_vdev_by_addr(wma, probe_rsp->macHdr.sa, &vdev_id);
2247 if (!vdev) {
2248 WMA_LOGE(FL("failed to get vdev handle"));
2249 return;
2250 }
2251
2252 if (WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
2253 WMI_SERVICE_BEACON_OFFLOAD)) {
2254 WMA_LOGI("Beacon Offload Enabled Sending Unified command");
2255 if (wmi_unified_probe_rsp_tmpl_send(wma, vdev_id,
2256 probe_rsp_info) < 0) {
2257 WMA_LOGE(FL("wmi_unified_probe_rsp_tmpl_send Failed "));
2258 return;
2259 }
2260 }
2261}
2262
2263/**
2264 * wma_send_beacon() - send beacon template
2265 * @wma: wma handle
2266 * @bcn_info: beacon info
2267 *
2268 * This funciton store beacon template locally and
2269 * update keep alive parameters
2270 *
2271 * Return: none
2272 */
2273void wma_send_beacon(tp_wma_handle wma, tpSendbeaconParams bcn_info)
2274{
2275 ol_txrx_vdev_handle vdev;
2276 uint8_t vdev_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302277 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002278 uint8_t *p2p_ie;
2279 tpAniBeaconStruct beacon;
Govind Singhd76a5b02016-03-08 15:12:14 +05302280 struct vdev_up_params param = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002281
2282 beacon = (tpAniBeaconStruct) (bcn_info->beacon);
2283 vdev = wma_find_vdev_by_addr(wma, beacon->macHdr.sa, &vdev_id);
2284 if (!vdev) {
2285 WMA_LOGE("%s : failed to get vdev handle", __func__);
2286 return;
2287 }
2288
2289 if (WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
2290 WMI_SERVICE_BEACON_OFFLOAD)) {
2291 WMA_LOGI("Beacon Offload Enabled Sending Unified command");
Govind Singh61ad2622016-02-22 17:25:02 +05302292 status = wma_unified_bcn_tmpl_send(wma, vdev_id, bcn_info, 4);
2293 if (QDF_IS_STATUS_ERROR(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002294 WMA_LOGE("%s : wmi_unified_bcn_tmpl_send Failed ",
2295 __func__);
2296 return;
2297 }
2298
2299 if (bcn_info->p2pIeOffset) {
2300 p2p_ie = bcn_info->beacon + bcn_info->p2pIeOffset;
2301 WMA_LOGI
2302 (" %s: p2pIe is present - vdev_id %hu, p2p_ie = %p, p2p ie len = %hu",
2303 __func__, vdev_id, p2p_ie, p2p_ie[1]);
2304 if (wma_p2p_go_set_beacon_ie(wma, vdev_id, p2p_ie) < 0) {
2305 WMA_LOGE
2306 ("%s : wmi_unified_bcn_tmpl_send Failed ",
2307 __func__);
2308 return;
2309 }
2310 }
2311 }
2312 status = wma_store_bcn_tmpl(wma, vdev_id, bcn_info);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302313 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002314 WMA_LOGE("%s : wma_store_bcn_tmpl Failed", __func__);
2315 return;
2316 }
2317 if (!wma->interfaces[vdev_id].vdev_up) {
Govind Singhd76a5b02016-03-08 15:12:14 +05302318 param.vdev_id = vdev_id;
2319 param.assoc_id = 0;
2320 status = wmi_unified_vdev_up_send(wma->wmi_handle,
2321 bcn_info->bssId,
2322 &param);
2323 if (QDF_IS_STATUS_ERROR(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002324 WMA_LOGE("%s : failed to send vdev up", __func__);
2325 return;
2326 }
2327 wma->interfaces[vdev_id].vdev_up = true;
2328 wma_set_sap_keepalive(wma, vdev_id);
2329 }
2330}
2331
2332/**
2333 * wma_set_keepalive_req() - send keep alive request to fw
2334 * @wma: wma handle
2335 * @keepalive: keep alive parameters
2336 *
2337 * Return: none
2338 */
2339void wma_set_keepalive_req(tp_wma_handle wma,
2340 tSirKeepAliveReq *keepalive)
2341{
2342 WMA_LOGD("KEEPALIVE:PacketType:%d", keepalive->packetType);
2343 wma_set_sta_keep_alive(wma, keepalive->sessionId,
2344 keepalive->packetType,
2345 keepalive->timePeriod,
2346 keepalive->hostIpv4Addr,
Srinivas Girigowda9c330a92015-11-24 12:28:25 -08002347 keepalive->destIpv4Addr,
2348 keepalive->dest_macaddr.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002349
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302350 qdf_mem_free(keepalive);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002351}
2352
2353/**
2354 * wma_beacon_miss_handler() - beacon miss event handler
2355 * @wma: wma handle
2356 * @vdev_id: vdev id
2357 *
2358 * This function send beacon miss indication to upper layers.
2359 *
2360 * Return: none
2361 */
2362void wma_beacon_miss_handler(tp_wma_handle wma, uint32_t vdev_id)
2363{
2364 tSirSmeMissedBeaconInd *beacon_miss_ind;
2365
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302366 beacon_miss_ind = (tSirSmeMissedBeaconInd *) qdf_mem_malloc
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002367 (sizeof(tSirSmeMissedBeaconInd));
2368
2369 if (NULL == beacon_miss_ind) {
2370 WMA_LOGE("%s: Memory allocation failure", __func__);
2371 return;
2372 }
2373 beacon_miss_ind->messageType = WMA_MISSED_BEACON_IND;
2374 beacon_miss_ind->length = sizeof(tSirSmeMissedBeaconInd);
2375 beacon_miss_ind->bssIdx = vdev_id;
2376
2377 wma_send_msg(wma, WMA_MISSED_BEACON_IND, (void *)beacon_miss_ind, 0);
2378}
2379
2380/**
2381 * wma_mgmt_tx_completion_handler() - wma mgmt Tx completion event handler
2382 * @handle: wma handle
2383 * @cmpl_event_params: completion event handler data
2384 * @len: length of @cmpl_event_params
2385 *
2386 * Return: 0 on success; error number otherwise
2387 */
2388
2389int wma_mgmt_tx_completion_handler(void *handle, uint8_t *cmpl_event_params,
2390 uint32_t len)
2391{
2392 tp_wma_handle wma_handle = (tp_wma_handle)handle;
2393 WMI_MGMT_TX_COMPLETION_EVENTID_param_tlvs *param_buf;
2394 wmi_mgmt_tx_compl_event_fixed_param *cmpl_params;
2395 struct wmi_desc_t *wmi_desc;
2396
Anurag Chouhan6d760662016-02-20 16:05:43 +05302397 ol_txrx_pdev_handle pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002398
2399 param_buf = (WMI_MGMT_TX_COMPLETION_EVENTID_param_tlvs *)
2400 cmpl_event_params;
2401 if (!param_buf && !wma_handle) {
2402 WMA_LOGE("%s: Invalid mgmt Tx completion event", __func__);
2403 return -EINVAL;
2404 }
2405 cmpl_params = param_buf->fixed_param;
2406
2407 WMA_LOGI("%s: status:%d wmi_desc_id:%d", __func__, cmpl_params->status,
2408 cmpl_params->desc_id);
2409
2410 wmi_desc = (struct wmi_desc_t *)
2411 (&wma_handle->wmi_desc_pool.array[cmpl_params->desc_id]);
2412
2413 if (!wmi_desc) {
2414 WMA_LOGE("%s: Invalid wmi desc", __func__);
2415 return -EINVAL;
2416 }
2417
2418 if (wmi_desc->nbuf)
Nirav Shahcbc6d722016-03-01 16:24:53 +05302419 qdf_nbuf_unmap_single(pdev->osdev, wmi_desc->nbuf,
Anurag Chouhan6d760662016-02-20 16:05:43 +05302420 QDF_DMA_TO_DEVICE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002421 if (wmi_desc->tx_cmpl_cb)
2422 wmi_desc->tx_cmpl_cb(wma_handle->mac_context,
2423 wmi_desc->nbuf, 1);
2424
2425 if (wmi_desc->ota_post_proc_cb)
2426 wmi_desc->ota_post_proc_cb((tpAniSirGlobal)
2427 wma_handle->mac_context,
2428 cmpl_params->status);
2429
2430 wmi_desc_put(wma_handle, wmi_desc);
2431
2432 return 0;
2433}
2434
2435/**
2436 * wma_process_update_opmode() - process update VHT opmode cmd from UMAC
2437 * @wma_handle: wma handle
2438 * @update_vht_opmode: vht opmode
2439 *
2440 * Return: none
2441 */
2442void wma_process_update_opmode(tp_wma_handle wma_handle,
2443 tUpdateVHTOpMode *update_vht_opmode)
2444{
2445 WMA_LOGD("%s: opMode = %d", __func__, update_vht_opmode->opMode);
2446
2447 wma_set_peer_param(wma_handle, update_vht_opmode->peer_mac,
2448 WMI_PEER_CHWIDTH, update_vht_opmode->opMode,
2449 update_vht_opmode->smesessionId);
2450}
2451
2452/**
2453 * wma_process_update_rx_nss() - process update RX NSS cmd from UMAC
2454 * @wma_handle: wma handle
2455 * @update_rx_nss: rx nss value
2456 *
2457 * Return: none
2458 */
2459void wma_process_update_rx_nss(tp_wma_handle wma_handle,
2460 tUpdateRxNss *update_rx_nss)
2461{
2462 struct wma_txrx_node *intr =
2463 &wma_handle->interfaces[update_rx_nss->smesessionId];
2464 int rx_nss = update_rx_nss->rxNss;
2465
2466 wma_update_txrx_chainmask(wma_handle->num_rf_chains, &rx_nss);
2467
2468 intr->nss = (uint8_t)rx_nss;
2469 update_rx_nss->rxNss = (uint32_t)rx_nss;
2470
2471 WMA_LOGD("%s: Rx Nss = %d", __func__, update_rx_nss->rxNss);
2472
2473 wma_set_peer_param(wma_handle, update_rx_nss->peer_mac,
2474 WMI_PEER_NSS, update_rx_nss->rxNss,
2475 update_rx_nss->smesessionId);
2476}
2477
2478#ifdef WLAN_FEATURE_11AC
2479/**
2480 * wma_process_update_membership() - process update group membership cmd
2481 * @wma_handle: wma handle
2482 * @membership: group membership info
2483 *
2484 * Return: none
2485 */
2486void wma_process_update_membership(tp_wma_handle wma_handle,
2487 tUpdateMembership *membership)
2488{
2489 WMA_LOGD("%s: membership = %x ", __func__, membership->membership);
2490
2491 wma_set_peer_param(wma_handle, membership->peer_mac,
2492 WMI_PEER_MEMBERSHIP, membership->membership,
2493 membership->smesessionId);
2494}
2495
2496/**
2497 * wma_process_update_userpos() - process update user pos cmd from UMAC
2498 * @wma_handle: wma handle
2499 * @userpos: user pos value
2500 *
2501 * Return: none
2502 */
2503void wma_process_update_userpos(tp_wma_handle wma_handle,
2504 tUpdateUserPos *userpos)
2505{
2506 WMA_LOGD("%s: userPos = %x ", __func__, userpos->userPos);
2507
2508 wma_set_peer_param(wma_handle, userpos->peer_mac,
2509 WMI_PEER_USERPOS, userpos->userPos,
2510 userpos->smesessionId);
2511
2512 /* Now that membership/userpos is updated in fw,
2513 * enable GID PPS.
2514 */
2515 wma_set_ppsconfig(userpos->smesessionId, WMA_VHT_PPS_GID_MATCH, 1);
2516
2517}
2518#endif /* WLAN_FEATURE_11AC */
2519
2520/**
2521 * wma_set_htconfig() - set ht config parameters to target
2522 * @vdev_id: vdev id
2523 * @ht_capab: ht capablity
2524 * @value: value of ht param
2525 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302526 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002527 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302528QDF_STATUS wma_set_htconfig(uint8_t vdev_id, uint16_t ht_capab, int value)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002529{
Anurag Chouhan6d760662016-02-20 16:05:43 +05302530 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
Govind Singhd76a5b02016-03-08 15:12:14 +05302531 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002532
2533 if (NULL == wma) {
2534 WMA_LOGE("%s: Failed to get wma", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302535 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002536 }
2537
2538 switch (ht_capab) {
2539 case WNI_CFG_HT_CAP_INFO_ADVANCE_CODING:
Govind Singhd76a5b02016-03-08 15:12:14 +05302540 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002541 WMI_VDEV_PARAM_LDPC,
2542 value);
2543 break;
2544 case WNI_CFG_HT_CAP_INFO_TX_STBC:
Govind Singhd76a5b02016-03-08 15:12:14 +05302545 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002546 WMI_VDEV_PARAM_TX_STBC,
2547 value);
2548 break;
2549 case WNI_CFG_HT_CAP_INFO_RX_STBC:
Govind Singhd76a5b02016-03-08 15:12:14 +05302550 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002551 WMI_VDEV_PARAM_RX_STBC,
2552 value);
2553 break;
2554 case WNI_CFG_HT_CAP_INFO_SHORT_GI_20MHZ:
2555 case WNI_CFG_HT_CAP_INFO_SHORT_GI_40MHZ:
2556 WMA_LOGE("%s: ht_capab = %d, value = %d", __func__, ht_capab,
2557 value);
Govind Singhd76a5b02016-03-08 15:12:14 +05302558 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002559 WMI_VDEV_PARAM_SGI, value);
Govind Singhd76a5b02016-03-08 15:12:14 +05302560 if (ret == QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002561 wma->interfaces[vdev_id].config.shortgi = value;
2562 break;
2563 default:
2564 WMA_LOGE("%s:INVALID HT CONFIG", __func__);
2565 }
2566
Govind Singhd76a5b02016-03-08 15:12:14 +05302567 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002568}
2569
2570/**
2571 * wma_hidden_ssid_vdev_restart() - vdev restart for hidden ssid
2572 * @wma_handle: wma handle
2573 * @pReq: hidden ssid vdev restart request
2574 *
2575 * Return: none
2576 */
2577void wma_hidden_ssid_vdev_restart(tp_wma_handle wma_handle,
2578 tHalHiddenSsidVdevRestart *pReq)
2579{
2580 struct wma_txrx_node *intr = wma_handle->interfaces;
2581
2582 if ((pReq->sessionId !=
2583 intr[pReq->sessionId].vdev_restart_params.vdev_id)
2584 || !((intr[pReq->sessionId].type == WMI_VDEV_TYPE_AP)
2585 && (intr[pReq->sessionId].sub_type == 0))) {
2586 WMA_LOGE("%s : invalid session id", __func__);
2587 return;
2588 }
2589
2590 intr[pReq->sessionId].vdev_restart_params.ssidHidden = pReq->ssidHidden;
Anurag Chouhan8e0ccd32016-02-19 15:30:20 +05302591 qdf_atomic_set(&intr[pReq->sessionId].vdev_restart_params.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002592 hidden_ssid_restart_in_progress, 1);
2593
2594 /* vdev stop -> vdev restart -> vdev up */
2595 WMA_LOGD("%s, vdev_id: %d, pausing tx_ll_queue for VDEV_STOP",
2596 __func__, pReq->sessionId);
2597 ol_txrx_vdev_pause(wma_handle->interfaces[pReq->sessionId].handle,
2598 OL_TXQ_PAUSE_REASON_VDEV_STOP);
2599 wma_handle->interfaces[pReq->sessionId].pause_bitmap |=
2600 (1 << PAUSE_TYPE_HOST);
2601 if (wmi_unified_vdev_stop_send(wma_handle->wmi_handle, pReq->sessionId)) {
2602 WMA_LOGE("%s: %d Failed to send vdev stop", __func__, __LINE__);
Anurag Chouhan8e0ccd32016-02-19 15:30:20 +05302603 qdf_atomic_set(&intr[pReq->sessionId].vdev_restart_params.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002604 hidden_ssid_restart_in_progress, 0);
2605 return;
2606 }
2607}
2608
2609
2610#ifdef WLAN_FEATURE_11W
2611
2612/**
2613 * wma_extract_ccmp_pn() - extract 6 byte PN from the CCMP header
2614 * @ccmp_ptr: CCMP header
2615 *
2616 * Return: PN extracted from header.
2617 */
2618static uint64_t wma_extract_ccmp_pn(uint8_t *ccmp_ptr)
2619{
2620 uint8_t rsvd, key, pn[6];
2621 uint64_t new_pn;
2622
2623 /*
2624 * +-----+-----+------+----------+-----+-----+-----+-----+
2625 * | PN0 | PN1 | rsvd | rsvd/key | PN2 | PN3 | PN4 | PN5 |
2626 * +-----+-----+------+----------+-----+-----+-----+-----+
2627 * CCMP Header Format
2628 */
2629
2630 /* Extract individual bytes */
2631 pn[0] = (uint8_t) *ccmp_ptr;
2632 pn[1] = (uint8_t) *(ccmp_ptr + 1);
2633 rsvd = (uint8_t) *(ccmp_ptr + 2);
2634 key = (uint8_t) *(ccmp_ptr + 3);
2635 pn[2] = (uint8_t) *(ccmp_ptr + 4);
2636 pn[3] = (uint8_t) *(ccmp_ptr + 5);
2637 pn[4] = (uint8_t) *(ccmp_ptr + 6);
2638 pn[5] = (uint8_t) *(ccmp_ptr + 7);
2639
2640 /* Form 6 byte PN with 6 individual bytes of PN */
2641 new_pn = ((uint64_t) pn[5] << 40) |
2642 ((uint64_t) pn[4] << 32) |
2643 ((uint64_t) pn[3] << 24) |
2644 ((uint64_t) pn[2] << 16) |
2645 ((uint64_t) pn[1] << 8) | ((uint64_t) pn[0] << 0);
2646
2647 WMA_LOGE("PN of received packet is %llu", new_pn);
2648 return new_pn;
2649}
2650
2651/**
2652 * wma_is_ccmp_pn_replay_attack() - detect replay attacking using PN in CCMP
2653 * @cds_ctx: cds context
2654 * @wh: 802.11 frame header
2655 * @ccmp_ptr: CCMP frame header
2656 *
2657 * Return: true/false
2658 */
2659static bool
2660wma_is_ccmp_pn_replay_attack(void *cds_ctx, struct ieee80211_frame *wh,
2661 uint8_t *ccmp_ptr)
2662{
2663 ol_txrx_pdev_handle pdev;
2664 ol_txrx_vdev_handle vdev;
2665 ol_txrx_peer_handle peer;
2666 uint8_t vdev_id, peer_id;
2667 uint8_t *last_pn_valid;
2668 uint64_t *last_pn, new_pn;
2669 uint32_t *rmf_pn_replays;
2670
Anurag Chouhan6d760662016-02-20 16:05:43 +05302671 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002672 if (!pdev) {
2673 WMA_LOGE("%s: Failed to find pdev", __func__);
2674 return true;
2675 }
2676
Mukul Sharmaa748fbb2015-12-01 19:51:36 +05302677 vdev = wma_find_vdev_by_bssid(cds_ctx, wh->i_addr3, &vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002678 if (!vdev) {
2679 WMA_LOGE("%s: Failed to find vdev", __func__);
2680 return true;
2681 }
2682
2683 /* Retrieve the peer based on vdev and addr */
2684 peer = ol_txrx_find_peer_by_addr_and_vdev(pdev, vdev, wh->i_addr2,
2685 &peer_id);
2686
2687 if (NULL == peer) {
2688 WMA_LOGE("%s: Failed to find peer, Not able to validate PN",
2689 __func__);
2690 return true;
2691 }
2692
2693 new_pn = wma_extract_ccmp_pn(ccmp_ptr);
2694 last_pn_valid = &peer->last_rmf_pn_valid;
2695 last_pn = &peer->last_rmf_pn;
2696 rmf_pn_replays = &peer->rmf_pn_replays;
2697
2698 if (*last_pn_valid) {
2699 if (new_pn > *last_pn) {
2700 *last_pn = new_pn;
2701 WMA_LOGE("%s: PN validation successful", __func__);
2702 } else {
2703 WMA_LOGE("%s: PN Replay attack detected", __func__);
2704 /* per 11W amendment, keeping track of replay attacks */
2705 *rmf_pn_replays += 1;
2706 return true;
2707 }
2708 } else {
2709 *last_pn_valid = 1;
2710 *last_pn = new_pn;
2711 }
2712
2713 return false;
2714}
2715
2716/**
mukul sharma72c8b222015-09-04 17:02:01 +05302717 * wma_process_bip() - process mmie in rmf frame
2718 * @wma_handle: wma handle
2719 * @iface: txrx node
2720 * @wh: 80211 frame
2721 * @wbuf: Buffer
2722 *
2723 * Return: 0 for success or error code
2724 */
2725
2726static
2727int wma_process_bip(tp_wma_handle wma_handle,
2728 struct wma_txrx_node *iface,
2729 struct ieee80211_frame *wh,
Nirav Shahcbc6d722016-03-01 16:24:53 +05302730 qdf_nbuf_t wbuf
mukul sharma72c8b222015-09-04 17:02:01 +05302731)
2732{
2733 uint16_t key_id;
2734 uint8_t *efrm;
2735
Nirav Shahcbc6d722016-03-01 16:24:53 +05302736 efrm = qdf_nbuf_data(wbuf) + qdf_nbuf_len(wbuf);
mukul sharma72c8b222015-09-04 17:02:01 +05302737 key_id = (uint16_t)*(efrm - cds_get_mmie_size() + 2);
2738
2739 if (!((key_id == WMA_IGTK_KEY_INDEX_4)
2740 || (key_id == WMA_IGTK_KEY_INDEX_5))) {
2741 WMA_LOGE(FL("Invalid KeyID(%d) dropping the frame"), key_id);
2742 return -EINVAL;
2743 }
2744 if (WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap,
2745 WMI_SERVICE_STA_PMF_OFFLOAD)) {
2746 /*
2747 * if 11w offload is enabled then mmie validation is performed
2748 * in firmware, host just need to trim the mmie.
2749 */
Nirav Shahcbc6d722016-03-01 16:24:53 +05302750 qdf_nbuf_trim_tail(wbuf, cds_get_mmie_size());
mukul sharma72c8b222015-09-04 17:02:01 +05302751 } else {
2752 if (cds_is_mmie_valid(iface->key.key,
2753 iface->key.key_id[key_id - WMA_IGTK_KEY_INDEX_4].ipn,
2754 (uint8_t *) wh, efrm)) {
2755 WMA_LOGE(FL("Protected BC/MC frame MMIE validation successful"));
2756 /* Remove MMIE */
Nirav Shahcbc6d722016-03-01 16:24:53 +05302757 qdf_nbuf_trim_tail(wbuf, cds_get_mmie_size());
mukul sharma72c8b222015-09-04 17:02:01 +05302758 } else {
2759 WMA_LOGE(FL("BC/MC MIC error or MMIE not present, dropping the frame"));
2760 return -EINVAL;
2761 }
2762 }
2763 return 0;
2764}
2765
2766/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002767 * wma_process_rmf_frame() - process rmf frame
2768 * @wma_handle: wma handle
2769 * @iface: txrx node
2770 * @wh: 80211 frame
2771 * @rx_pkt: rx packet
2772 * @wbuf: Buffer
2773 *
2774 * Return: 0 for success or error code
2775 */
2776static
2777int wma_process_rmf_frame(tp_wma_handle wma_handle,
2778 struct wma_txrx_node *iface,
2779 struct ieee80211_frame *wh,
2780 cds_pkt_t *rx_pkt,
Nirav Shahcbc6d722016-03-01 16:24:53 +05302781 qdf_nbuf_t wbuf)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002782{
mukul sharma72c8b222015-09-04 17:02:01 +05302783 uint8_t *orig_hdr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002784 uint8_t *ccmp;
2785
2786 if ((wh)->i_fc[1] & IEEE80211_FC1_WEP) {
2787 if (IEEE80211_IS_BROADCAST(wh->i_addr1) ||
2788 IEEE80211_IS_MULTICAST(wh->i_addr1)) {
2789 WMA_LOGE("Encrypted BC/MC frame dropping the frame");
2790 cds_pkt_return_packet(rx_pkt);
2791 return -EINVAL;
2792 }
2793
Nirav Shahcbc6d722016-03-01 16:24:53 +05302794 orig_hdr = (uint8_t *) qdf_nbuf_data(wbuf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002795 /* Pointer to head of CCMP header */
2796 ccmp = orig_hdr + sizeof(*wh);
2797 if (wma_is_ccmp_pn_replay_attack(
2798 wma_handle, wh, ccmp)) {
2799 WMA_LOGE("Dropping the frame");
2800 cds_pkt_return_packet(rx_pkt);
2801 return -EINVAL;
2802 }
2803
2804 /* Strip privacy headers (and trailer)
2805 * for a received frame
2806 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302807 qdf_mem_move(orig_hdr +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002808 IEEE80211_CCMP_HEADERLEN, wh,
2809 sizeof(*wh));
Nirav Shahcbc6d722016-03-01 16:24:53 +05302810 qdf_nbuf_pull_head(wbuf,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002811 IEEE80211_CCMP_HEADERLEN);
Nirav Shahcbc6d722016-03-01 16:24:53 +05302812 qdf_nbuf_trim_tail(wbuf, IEEE80211_CCMP_MICLEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002813
2814 rx_pkt->pkt_meta.mpdu_hdr_ptr =
Nirav Shahcbc6d722016-03-01 16:24:53 +05302815 qdf_nbuf_data(wbuf);
2816 rx_pkt->pkt_meta.mpdu_len = qdf_nbuf_len(wbuf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002817 rx_pkt->pkt_meta.mpdu_data_len =
2818 rx_pkt->pkt_meta.mpdu_len -
2819 rx_pkt->pkt_meta.mpdu_hdr_len;
2820 rx_pkt->pkt_meta.mpdu_data_ptr =
2821 rx_pkt->pkt_meta.mpdu_hdr_ptr +
2822 rx_pkt->pkt_meta.mpdu_hdr_len;
2823 rx_pkt->pkt_meta.tsf_delta = rx_pkt->pkt_meta.tsf_delta;
2824 rx_pkt->pkt_buf = wbuf;
2825 WMA_LOGD(FL("BSSID: "MAC_ADDRESS_STR" tsf_delta: %u"),
2826 MAC_ADDR_ARRAY(wh->i_addr3), rx_pkt->pkt_meta.tsf_delta);
2827 } else {
2828 if (IEEE80211_IS_BROADCAST(wh->i_addr1) ||
2829 IEEE80211_IS_MULTICAST(wh->i_addr1)) {
mukul sharma72c8b222015-09-04 17:02:01 +05302830 if (0 != wma_process_bip(wma_handle, iface, wh, wbuf)) {
2831 cds_pkt_return_packet(rx_pkt);
2832 return -EINVAL;
Mukul Sharmaa748fbb2015-12-01 19:51:36 +05302833 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002834 } else {
2835 WMA_LOGE("Rx unprotected unicast mgmt frame");
2836 rx_pkt->pkt_meta.dpuFeedback =
2837 DPU_FEEDBACK_UNPROTECTED_ERROR;
2838 }
2839 }
2840 return 0;
2841}
2842#endif
2843
2844/**
2845 * wma_mgmt_rx_process() - process management rx frame.
2846 * @handle: wma handle
2847 * @data: rx data
2848 * @data_len: data length
2849 *
2850 * Return: 0 for success or error code
2851 */
2852static int wma_mgmt_rx_process(void *handle, uint8_t *data,
2853 uint32_t data_len)
2854{
2855 tp_wma_handle wma_handle = (tp_wma_handle) handle;
2856 WMI_MGMT_RX_EVENTID_param_tlvs *param_tlvs = NULL;
2857 wmi_mgmt_rx_hdr *hdr = NULL;
2858 struct wma_txrx_node *iface = NULL;
Mukul Sharmaa748fbb2015-12-01 19:51:36 +05302859 uint8_t vdev_id = WMA_INVALID_VDEV_ID;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002860 cds_pkt_t *rx_pkt;
Nirav Shahcbc6d722016-03-01 16:24:53 +05302861 qdf_nbuf_t wbuf;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002862 struct ieee80211_frame *wh;
2863 uint8_t mgt_type, mgt_subtype;
2864 int status;
2865
2866 if (!wma_handle) {
2867 WMA_LOGE("%s: Failed to get WMA context", __func__);
2868 return -EINVAL;
2869 }
2870
2871 param_tlvs = (WMI_MGMT_RX_EVENTID_param_tlvs *) data;
2872 if (!param_tlvs) {
2873 WMA_LOGE("Get NULL point message from FW");
2874 return -EINVAL;
2875 }
2876
2877 hdr = param_tlvs->hdr;
2878 if (!hdr) {
2879 WMA_LOGE("Rx event is NULL");
2880 return -EINVAL;
2881 }
2882
2883 if (hdr->buf_len < sizeof(struct ieee80211_frame)) {
2884 WMA_LOGE("Invalid rx mgmt packet");
2885 return -EINVAL;
2886 }
2887
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302888 rx_pkt = qdf_mem_malloc(sizeof(*rx_pkt));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002889 if (!rx_pkt) {
2890 WMA_LOGE("Failed to allocate rx packet");
2891 return -ENOMEM;
2892 }
2893
Rajeev Kumarfec3dbe2016-01-19 15:23:52 -08002894 if (cds_is_load_or_unload_in_progress()) {
Naveen Rawat10ccf872015-11-03 14:15:55 -08002895 WMA_LOGE("Load/Unload in progress");
2896 return -EINVAL;
2897 }
2898
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302899 qdf_mem_zero(rx_pkt, sizeof(*rx_pkt));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002900
2901 /*
2902 * Fill in meta information needed by pe/lim
2903 * TODO: Try to maintain rx metainfo as part of skb->data.
2904 */
2905 rx_pkt->pkt_meta.channel = hdr->channel;
2906 rx_pkt->pkt_meta.scan_src = hdr->flags;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -07002907
2908 /*
2909 * Get the rssi value from the current snr value
2910 * using standard noise floor of -96.
2911 */
2912 rx_pkt->pkt_meta.rssi = hdr->snr + WMA_NOISE_FLOOR_DBM_DEFAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002913 rx_pkt->pkt_meta.snr = hdr->snr;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -07002914
2915 /* If absolute rssi is available from firmware, use it */
2916 if (hdr->rssi != 0)
2917 rx_pkt->pkt_meta.rssi_raw = hdr->rssi;
2918 else
2919 rx_pkt->pkt_meta.rssi_raw = rx_pkt->pkt_meta.rssi;
2920
2921
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002922 /*
2923 * FIXME: Assigning the local timestamp as hw timestamp is not
2924 * available. Need to see if pe/lim really uses this data.
2925 */
2926 rx_pkt->pkt_meta.timestamp = (uint32_t) jiffies;
2927 rx_pkt->pkt_meta.mpdu_hdr_len = sizeof(struct ieee80211_frame);
2928 rx_pkt->pkt_meta.mpdu_len = hdr->buf_len;
2929 rx_pkt->pkt_meta.mpdu_data_len = hdr->buf_len -
2930 rx_pkt->pkt_meta.mpdu_hdr_len;
2931
2932 rx_pkt->pkt_meta.roamCandidateInd = 0;
2933
2934 /* Why not just use rx_event->hdr.buf_len? */
Nirav Shahcbc6d722016-03-01 16:24:53 +05302935 wbuf = qdf_nbuf_alloc(NULL, roundup(hdr->buf_len, 4), 0, 4, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002936 if (!wbuf) {
2937 WMA_LOGE("%s: Failed to allocate wbuf for mgmt rx len(%u)",
2938 __func__, hdr->buf_len);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302939 qdf_mem_free(rx_pkt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002940 return -ENOMEM;
2941 }
2942
Nirav Shahcbc6d722016-03-01 16:24:53 +05302943 qdf_nbuf_put_tail(wbuf, hdr->buf_len);
2944 qdf_nbuf_set_protocol(wbuf, ETH_P_CONTROL);
2945 wh = (struct ieee80211_frame *)qdf_nbuf_data(wbuf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002946
Nirav Shahcbc6d722016-03-01 16:24:53 +05302947 rx_pkt->pkt_meta.mpdu_hdr_ptr = qdf_nbuf_data(wbuf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002948 rx_pkt->pkt_meta.mpdu_data_ptr = rx_pkt->pkt_meta.mpdu_hdr_ptr +
2949 rx_pkt->pkt_meta.mpdu_hdr_len;
2950 rx_pkt->pkt_meta.tsf_delta = hdr->tsf_delta;
2951 rx_pkt->pkt_buf = wbuf;
2952
2953 WMA_LOGD(FL("BSSID: "MAC_ADDRESS_STR" tsf_delta: %u"),
2954 MAC_ADDR_ARRAY(wh->i_addr3), hdr->tsf_delta);
2955
2956#ifdef BIG_ENDIAN_HOST
2957 {
2958 /*
2959 * for big endian host, copy engine byte_swap is enabled
2960 * But the rx mgmt frame buffer content is in network byte order
2961 * Need to byte swap the mgmt frame buffer content - so when
2962 * copy engine does byte_swap - host gets buffer content in the
2963 * correct byte order.
2964 */
2965 int i;
2966 uint32_t *destp, *srcp;
2967 destp = (uint32_t *) wh;
2968 srcp = (uint32_t *) param_tlvs->bufp;
2969 for (i = 0;
2970 i < (roundup(hdr->buf_len, sizeof(uint32_t)) / 4); i++) {
2971 *destp = cpu_to_le32(*srcp);
2972 destp++;
2973 srcp++;
2974 }
2975 }
2976#else
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302977 qdf_mem_copy(wh, param_tlvs->bufp, hdr->buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002978#endif
2979
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -07002980 WMA_LOGD(
2981 FL("BSSID: "MAC_ADDRESS_STR" snr = %d, rssi = %d, rssi_raw = %d"),
2982 MAC_ADDR_ARRAY(wh->i_addr3),
2983 hdr->snr, rx_pkt->pkt_meta.rssi,
2984 rx_pkt->pkt_meta.rssi_raw);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002985 if (!wma_handle->mgmt_rx) {
2986 WMA_LOGE("Not registered for Mgmt rx, dropping the frame");
2987 cds_pkt_return_packet(rx_pkt);
2988 return -EINVAL;
2989 }
2990
2991 /* If it is a beacon/probe response, save it for future use */
2992 mgt_type = (wh)->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
2993 mgt_subtype = (wh)->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
2994
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002995#ifdef WLAN_FEATURE_11W
2996 if (mgt_type == IEEE80211_FC0_TYPE_MGT &&
2997 (mgt_subtype == IEEE80211_FC0_SUBTYPE_DISASSOC ||
2998 mgt_subtype == IEEE80211_FC0_SUBTYPE_DEAUTH ||
2999 mgt_subtype == IEEE80211_FC0_SUBTYPE_ACTION)) {
Mukul Sharmaa748fbb2015-12-01 19:51:36 +05303000 if (wma_find_vdev_by_bssid(
3001 wma_handle, wh->i_addr3, &vdev_id)) {
3002 iface = &(wma_handle->interfaces[vdev_id]);
3003 if (iface->rmfEnabled) {
3004 status = wma_process_rmf_frame(wma_handle,
3005 iface, wh, rx_pkt, wbuf);
3006 if (status != 0)
3007 return status;
3008 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003009 }
3010 }
3011#endif /* WLAN_FEATURE_11W */
Mukul Sharmaa748fbb2015-12-01 19:51:36 +05303012 rx_pkt->pkt_meta.sessionId =
3013 (vdev_id == WMA_INVALID_VDEV_ID ? 0 : vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003014 wma_handle->mgmt_rx(wma_handle, rx_pkt);
3015 return 0;
3016}
3017
3018/**
3019 * wma_de_register_mgmt_frm_client() - deregister management frame
3020 * @cds_ctx: cds context
3021 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303022 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003023 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303024QDF_STATUS wma_de_register_mgmt_frm_client(void *cds_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003025{
3026 tp_wma_handle wma_handle;
3027
3028#ifdef QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +05303029 if (cds_get_conparam() == QDF_GLOBAL_FTM_MODE)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303030 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003031#endif
3032
Anurag Chouhan6d760662016-02-20 16:05:43 +05303033 wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003034 if (!wma_handle) {
3035 WMA_LOGE("%s: Failed to get WMA context", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303036 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003037 }
3038
3039 if (wmi_unified_unregister_event_handler(wma_handle->wmi_handle,
3040 WMI_MGMT_RX_EVENTID) != 0) {
3041 WMA_LOGE("Failed to Unregister rx mgmt handler with wmi");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303042 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003043 }
3044 wma_handle->mgmt_rx = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303045 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003046}
3047
3048/**
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003049 * wma_register_roaming_callbacks() - Register roaming callbacks
3050 * @cds_ctx: CDS Context
3051 * @csr_roam_synch_cb: CSR roam synch callback routine pointer
3052 * @pe_roam_synch_cb: PE roam synch callback routine pointer
3053 *
3054 * Register the SME and PE callback routines with WMA for
3055 * handling roaming
3056 *
3057 * Return: Success or Failure Status
3058 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303059QDF_STATUS wma_register_roaming_callbacks(void *cds_ctx,
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003060 void (*csr_roam_synch_cb)(tpAniSirGlobal mac,
3061 roam_offload_synch_ind *roam_synch_data,
3062 tpSirBssDescription bss_desc_ptr, uint8_t reason),
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303063 QDF_STATUS (*pe_roam_synch_cb)(tpAniSirGlobal mac,
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003064 roam_offload_synch_ind *roam_synch_data,
3065 tpSirBssDescription bss_desc_ptr))
3066{
3067
Anurag Chouhan6d760662016-02-20 16:05:43 +05303068 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003069
3070 if (!wma) {
3071 WMA_LOGE("%s: Failed to get WMA context", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303072 return QDF_STATUS_E_FAILURE;
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003073 }
3074 wma->csr_roam_synch_cb = csr_roam_synch_cb;
3075 wma->pe_roam_synch_cb = pe_roam_synch_cb;
3076 WMA_LOGD("Registered roam synch callbacks with WMA successfully");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303077 return QDF_STATUS_SUCCESS;
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003078}
3079/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003080 * wma_register_mgmt_frm_client() - register management frame callback
3081 * @cds_ctx: cds context
3082 * @mgmt_frm_rx: management frame
3083 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303084 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003085 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303086QDF_STATUS wma_register_mgmt_frm_client(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003087 void *cds_ctx, wma_mgmt_frame_rx_callback mgmt_frm_rx)
3088{
Anurag Chouhan6d760662016-02-20 16:05:43 +05303089 tp_wma_handle wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003090
3091 if (!wma_handle) {
3092 WMA_LOGE("%s: Failed to get WMA context", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303093 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003094 }
3095
3096 if (wmi_unified_register_event_handler(wma_handle->wmi_handle,
3097 WMI_MGMT_RX_EVENTID,
Govind Singhd76a5b02016-03-08 15:12:14 +05303098 wma_mgmt_rx_process,
3099 WMA_RX_WORK_CTX) != 0) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003100 WMA_LOGE("Failed to register rx mgmt handler with wmi");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303101 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003102 }
3103 wma_handle->mgmt_rx = mgmt_frm_rx;
3104
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303105 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003106}