blob: 38dcfaf93b31e4f605004b651cf83bbaf57d6b52 [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"
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -070070#include <cdp_txrx_peer_ops.h>
71#include <cdp_txrx_pmf.h>
72#include <cdp_txrx_cfg.h>
73#include <cdp_txrx_cmn.h>
74#include <cdp_txrx_misc.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080075
76/**
77 * wma_send_bcn_buf_ll() - prepare and send beacon buffer to fw for LL
78 * @wma: wma handle
79 * @pdev: txrx pdev
80 * @vdev_id: vdev id
81 * @param_buf: SWBA parameters
82 *
83 * Return: none
84 */
85static void wma_send_bcn_buf_ll(tp_wma_handle wma,
86 ol_txrx_pdev_handle pdev,
87 uint8_t vdev_id,
88 WMI_HOST_SWBA_EVENTID_param_tlvs *param_buf)
89{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080090 struct ieee80211_frame *wh;
91 struct beacon_info *bcn;
92 wmi_tim_info *tim_info = param_buf->tim_info;
93 uint8_t *bcn_payload;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053094 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080095 struct beacon_tim_ie *tim_ie;
96 wmi_p2p_noa_info *p2p_noa_info = param_buf->p2p_noa_info;
97 struct p2p_sub_element_noa noa_ie;
Himanshu Agarwal009f1572016-03-09 17:26:02 +053098 struct wmi_bcn_send_from_host params;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080099 uint8_t i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800100
101 bcn = wma->interfaces[vdev_id].beacon;
102 if (!bcn->buf) {
103 WMA_LOGE("%s: Invalid beacon buffer", __func__);
104 return;
105 }
106
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530107 qdf_spin_lock_bh(&bcn->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800108
Nirav Shahcbc6d722016-03-01 16:24:53 +0530109 bcn_payload = qdf_nbuf_data(bcn->buf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800110
111 tim_ie = (struct beacon_tim_ie *)(&bcn_payload[bcn->tim_ie_offset]);
112
113 if (tim_info->tim_changed) {
114 if (tim_info->tim_num_ps_pending)
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530115 qdf_mem_copy(&tim_ie->tim_bitmap, tim_info->tim_bitmap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800116 WMA_TIM_SUPPORTED_PVB_LENGTH);
117 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530118 qdf_mem_zero(&tim_ie->tim_bitmap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800119 WMA_TIM_SUPPORTED_PVB_LENGTH);
120 /*
121 * Currently we support fixed number of
122 * peers as limited by HAL_NUM_STA.
123 * tim offset is always 0
124 */
125 tim_ie->tim_bitctl = 0;
126 }
127
128 /* Update DTIM Count */
129 if (tim_ie->dtim_count == 0)
130 tim_ie->dtim_count = tim_ie->dtim_period - 1;
131 else
132 tim_ie->dtim_count--;
133
134 /*
135 * DTIM count needs to be backedup so that
136 * when umac updates the beacon template
137 * current dtim count can be updated properly
138 */
139 bcn->dtim_count = tim_ie->dtim_count;
140
141 /* update state for buffered multicast frames on DTIM */
142 if (tim_info->tim_mcast && (tim_ie->dtim_count == 0 ||
143 tim_ie->dtim_period == 1))
144 tim_ie->tim_bitctl |= 1;
145 else
146 tim_ie->tim_bitctl &= ~1;
147
148 /* To avoid sw generated frame sequence the same as H/W generated frame,
149 * the value lower than min_sw_seq is reserved for HW generated frame */
150 if ((bcn->seq_no & IEEE80211_SEQ_MASK) < MIN_SW_SEQ)
151 bcn->seq_no = MIN_SW_SEQ;
152
153 wh = (struct ieee80211_frame *)bcn_payload;
154 *(uint16_t *) &wh->i_seq[0] = htole16(bcn->seq_no
155 << IEEE80211_SEQ_SEQ_SHIFT);
156 bcn->seq_no++;
157
158 if (WMI_UNIFIED_NOA_ATTR_IS_MODIFIED(p2p_noa_info)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530159 qdf_mem_zero(&noa_ie, sizeof(noa_ie));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800160
161 noa_ie.index =
162 (uint8_t) WMI_UNIFIED_NOA_ATTR_INDEX_GET(p2p_noa_info);
163 noa_ie.oppPS =
164 (uint8_t) WMI_UNIFIED_NOA_ATTR_OPP_PS_GET(p2p_noa_info);
165 noa_ie.ctwindow =
166 (uint8_t) WMI_UNIFIED_NOA_ATTR_CTWIN_GET(p2p_noa_info);
167 noa_ie.num_descriptors =
168 (uint8_t) WMI_UNIFIED_NOA_ATTR_NUM_DESC_GET(p2p_noa_info);
169 WMA_LOGI("%s: index %u, oppPs %u, ctwindow %u, "
170 "num_descriptors = %u", __func__, noa_ie.index,
171 noa_ie.oppPS, noa_ie.ctwindow, noa_ie.num_descriptors);
172 for (i = 0; i < noa_ie.num_descriptors; i++) {
173 noa_ie.noa_descriptors[i].type_count =
174 (uint8_t) p2p_noa_info->noa_descriptors[i].
175 type_count;
176 noa_ie.noa_descriptors[i].duration =
177 p2p_noa_info->noa_descriptors[i].duration;
178 noa_ie.noa_descriptors[i].interval =
179 p2p_noa_info->noa_descriptors[i].interval;
180 noa_ie.noa_descriptors[i].start_time =
181 p2p_noa_info->noa_descriptors[i].start_time;
182 WMA_LOGI("%s: NoA descriptor[%d] type_count %u, "
183 "duration %u, interval %u, start_time = %u",
184 __func__, i,
185 noa_ie.noa_descriptors[i].type_count,
186 noa_ie.noa_descriptors[i].duration,
187 noa_ie.noa_descriptors[i].interval,
188 noa_ie.noa_descriptors[i].start_time);
189 }
190 wma_update_noa(bcn, &noa_ie);
191
192 /* Send a msg to LIM to update the NoA IE in probe response
193 * frames transmitted by the host */
194 wma_update_probe_resp_noa(wma, &noa_ie);
195 }
196
197 if (bcn->dma_mapped) {
Nirav Shahcbc6d722016-03-01 16:24:53 +0530198 qdf_nbuf_unmap_single(pdev->osdev, bcn->buf, QDF_DMA_TO_DEVICE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800199 bcn->dma_mapped = 0;
200 }
Nirav Shahcbc6d722016-03-01 16:24:53 +0530201 ret = qdf_nbuf_map_single(pdev->osdev, bcn->buf, QDF_DMA_TO_DEVICE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530202 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800203 WMA_LOGE("%s: failed map beacon buf to DMA region", __func__);
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530204 qdf_spin_unlock_bh(&bcn->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800205 return;
206 }
207
208 bcn->dma_mapped = 1;
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530209 params.vdev_id = vdev_id;
210 params.data_len = bcn->len;
211 params.frame_ctrl = *((A_UINT16 *) wh->i_fc);
212 params.frag_ptr = qdf_nbuf_get_frag_paddr(bcn->buf, 0);
213 params.dtim_flag = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800214 /* notify Firmware of DTM and mcast/bcast traffic */
215 if (tim_ie->dtim_count == 0) {
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530216 params.dtim_flag |= WMI_BCN_SEND_DTIM_ZERO;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800217 /* deliver mcast/bcast traffic in next DTIM beacon */
218 if (tim_ie->tim_bitctl & 0x01)
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530219 params.dtim_flag |= WMI_BCN_SEND_DTIM_BITCTL_SET;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800220 }
221
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530222 wmi_unified_bcn_buf_ll_cmd(wma->wmi_handle,
223 &params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800224
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530225 qdf_spin_unlock_bh(&bcn->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800226}
227
228/**
229 * wma_beacon_swba_handler() - swba event handler
230 * @handle: wma handle
231 * @event: event data
232 * @len: data length
233 *
234 * SWBA event is alert event to Host requesting host to Queue a beacon
235 * for transmission use only in host beacon mode
236 *
237 * Return: 0 for success or error code
238 */
239int wma_beacon_swba_handler(void *handle, uint8_t *event, uint32_t len)
240{
241 tp_wma_handle wma = (tp_wma_handle) handle;
242 WMI_HOST_SWBA_EVENTID_param_tlvs *param_buf;
243 wmi_host_swba_event_fixed_param *swba_event;
244 uint32_t vdev_map;
245 ol_txrx_pdev_handle pdev;
246 uint8_t vdev_id = 0;
247
248 param_buf = (WMI_HOST_SWBA_EVENTID_param_tlvs *) event;
249 if (!param_buf) {
250 WMA_LOGE("Invalid swba event buffer");
251 return -EINVAL;
252 }
253 swba_event = param_buf->fixed_param;
254 vdev_map = swba_event->vdev_map;
255
Anurag Chouhan6d760662016-02-20 16:05:43 +0530256 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800257 if (!pdev) {
258 WMA_LOGE("%s: pdev is NULL", __func__);
259 return -EINVAL;
260 }
261
262 for (; vdev_map; vdev_id++, vdev_map >>= 1) {
263 if (!(vdev_map & 0x1))
264 continue;
265 if (!ol_cfg_is_high_latency(pdev->ctrl_pdev))
266 wma_send_bcn_buf_ll(wma, pdev, vdev_id, param_buf);
267 break;
268 }
269 return 0;
270}
271
272/**
273 * wma_peer_sta_kickout_event_handler() - kickout event handler
274 * @handle: wma handle
275 * @event: event data
276 * @len: data length
277 *
278 * Kickout event is received from firmware on observing beacon miss
279 * It handles kickout event for different modes and indicate to
280 * upper layers.
281 *
282 * Return: 0 for success or error code
283 */
284int wma_peer_sta_kickout_event_handler(void *handle, u8 *event, u32 len)
285{
286 tp_wma_handle wma = (tp_wma_handle) handle;
287 WMI_PEER_STA_KICKOUT_EVENTID_param_tlvs *param_buf = NULL;
288 wmi_peer_sta_kickout_event_fixed_param *kickout_event = NULL;
289 uint8_t vdev_id, peer_id, macaddr[IEEE80211_ADDR_LEN];
290 ol_txrx_peer_handle peer;
291 ol_txrx_pdev_handle pdev;
292 tpDeleteStaContext del_sta_ctx;
293 tpSirIbssPeerInactivityInd p_inactivity;
294
295 WMA_LOGD("%s: Enter", __func__);
296 param_buf = (WMI_PEER_STA_KICKOUT_EVENTID_param_tlvs *) event;
297 kickout_event = param_buf->fixed_param;
Anurag Chouhan6d760662016-02-20 16:05:43 +0530298 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800299 if (!pdev) {
300 WMA_LOGE("%s: pdev is NULL", __func__);
301 return -EINVAL;
302 }
303 WMI_MAC_ADDR_TO_CHAR_ARRAY(&kickout_event->peer_macaddr, macaddr);
304 peer = ol_txrx_find_peer_by_addr(pdev, macaddr, &peer_id);
305 if (!peer) {
306 WMA_LOGE("PEER [%pM] not found", macaddr);
307 return -EINVAL;
308 }
309
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530310 if (ol_txrx_get_vdevid(peer, &vdev_id) != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800311 WMA_LOGE("Not able to find BSSID for peer [%pM]", macaddr);
312 return -EINVAL;
313 }
314
315 WMA_LOGA("%s: PEER:[%pM], ADDR:[%pN], INTERFACE:%d, peer_id:%d, reason:%d",
316 __func__, macaddr, wma->interfaces[vdev_id].addr, vdev_id,
317 peer_id, kickout_event->reason);
Varun Reddy Yeturu30bc42c2016-02-04 10:07:30 -0800318 if (wma->interfaces[vdev_id].roaming_in_progress) {
319 WMA_LOGE("Ignore STA kick out since roaming is in progress");
320 return -EINVAL;
321 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800322
323 switch (kickout_event->reason) {
324 case WMI_PEER_STA_KICKOUT_REASON_IBSS_DISCONNECT:
325 p_inactivity = (tpSirIbssPeerInactivityInd)
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530326 qdf_mem_malloc(sizeof(tSirIbssPeerInactivityInd));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800327 if (!p_inactivity) {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530328 WMA_LOGE("QDF MEM Alloc Failed for tSirIbssPeerInactivity");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800329 return -ENOMEM;
330 }
331
332 p_inactivity->staIdx = peer_id;
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530333 qdf_mem_copy(p_inactivity->peer_addr.bytes, macaddr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800334 IEEE80211_ADDR_LEN);
335 wma_send_msg(wma, WMA_IBSS_PEER_INACTIVITY_IND,
336 (void *)p_inactivity, 0);
337 goto exit_handler;
338 break;
339
340#ifdef FEATURE_WLAN_TDLS
341 case WMI_PEER_STA_KICKOUT_REASON_TDLS_DISCONNECT:
342 del_sta_ctx = (tpDeleteStaContext)
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530343 qdf_mem_malloc(sizeof(tDeleteStaContext));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800344 if (!del_sta_ctx) {
345 WMA_LOGE("%s: mem alloc failed for tDeleteStaContext for TDLS peer: %pM",
346 __func__, macaddr);
347 return -ENOMEM;
348 }
349
350 del_sta_ctx->staId = peer_id;
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530351 qdf_mem_copy(del_sta_ctx->addr2, macaddr, IEEE80211_ADDR_LEN);
352 qdf_mem_copy(del_sta_ctx->bssId, wma->interfaces[vdev_id].bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800353 IEEE80211_ADDR_LEN);
354 del_sta_ctx->reasonCode = HAL_DEL_STA_REASON_CODE_KEEP_ALIVE;
355 wma_send_msg(wma, SIR_LIM_DELETE_STA_CONTEXT_IND,
356 (void *)del_sta_ctx, 0);
357 goto exit_handler;
358 break;
359#endif /* FEATURE_WLAN_TDLS */
360
361 case WMI_PEER_STA_KICKOUT_REASON_XRETRY:
362 if (wma->interfaces[vdev_id].type == WMI_VDEV_TYPE_STA &&
363 (wma->interfaces[vdev_id].sub_type == 0 ||
364 wma->interfaces[vdev_id].sub_type ==
365 WMI_UNIFIED_VDEV_SUBTYPE_P2P_CLIENT) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530366 !qdf_mem_cmp(wma->interfaces[vdev_id].bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800367 macaddr, IEEE80211_ADDR_LEN)) {
368 /*
369 * KICKOUT event is for current station-AP connection.
370 * Treat it like final beacon miss. Station may not have
371 * missed beacons but not able to transmit frames to AP
372 * for a long time. Must disconnect to get out of
373 * this sticky situation.
374 * In future implementation, roaming module will also
375 * handle this event and perform a scan.
376 */
377 WMA_LOGW("%s: WMI_PEER_STA_KICKOUT_REASON_XRETRY event for STA",
378 __func__);
379 wma_beacon_miss_handler(wma, vdev_id);
380 goto exit_handler;
381 }
382 break;
383
384 case WMI_PEER_STA_KICKOUT_REASON_UNSPECIFIED:
385 /*
386 * Default legacy value used by original firmware implementation.
387 */
388 if (wma->interfaces[vdev_id].type == WMI_VDEV_TYPE_STA &&
389 (wma->interfaces[vdev_id].sub_type == 0 ||
390 wma->interfaces[vdev_id].sub_type ==
391 WMI_UNIFIED_VDEV_SUBTYPE_P2P_CLIENT) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530392 !qdf_mem_cmp(wma->interfaces[vdev_id].bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800393 macaddr, IEEE80211_ADDR_LEN)) {
394 /*
395 * KICKOUT event is for current station-AP connection.
396 * Treat it like final beacon miss. Station may not have
397 * missed beacons but not able to transmit frames to AP
398 * for a long time. Must disconnect to get out of
399 * this sticky situation.
400 * In future implementation, roaming module will also
401 * handle this event and perform a scan.
402 */
403 WMA_LOGW("%s: WMI_PEER_STA_KICKOUT_REASON_UNSPECIFIED event for STA",
404 __func__);
405 wma_beacon_miss_handler(wma, vdev_id);
406 goto exit_handler;
407 }
408 break;
409
410 case WMI_PEER_STA_KICKOUT_REASON_INACTIVITY:
mukul sharma72c8b222015-09-04 17:02:01 +0530411 /* Handle SA query kickout is same as inactivity kickout */
412 case WMI_PEER_STA_KICKOUT_REASON_SA_QUERY_TIMEOUT:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800413 default:
414 break;
415 }
416
417 /*
418 * default action is to send delete station context indication to LIM
419 */
420 del_sta_ctx =
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530421 (tpDeleteStaContext) qdf_mem_malloc(sizeof(tDeleteStaContext));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800422 if (!del_sta_ctx) {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530423 WMA_LOGE("QDF MEM Alloc Failed for tDeleteStaContext");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800424 return -ENOMEM;
425 }
426
427 del_sta_ctx->staId = peer_id;
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530428 qdf_mem_copy(del_sta_ctx->addr2, macaddr, IEEE80211_ADDR_LEN);
429 qdf_mem_copy(del_sta_ctx->bssId, wma->interfaces[vdev_id].addr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800430 IEEE80211_ADDR_LEN);
431 del_sta_ctx->reasonCode = HAL_DEL_STA_REASON_CODE_KEEP_ALIVE;
Kiran Kumar Lokere37d3aa22015-11-03 14:58:26 -0800432 del_sta_ctx->rssi = kickout_event->rssi + WMA_TGT_NOISE_FLOOR_DBM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800433 wma_send_msg(wma, SIR_LIM_DELETE_STA_CONTEXT_IND, (void *)del_sta_ctx,
434 0);
435
436exit_handler:
437 WMA_LOGD("%s: Exit", __func__);
438 return 0;
439}
440
441/**
442 * wma_unified_bcntx_status_event_handler() - beacon tx status event handler
443 * @handle: wma handle
444 * @cmd_param_info: event data
445 * @len: data length
446 *
447 * WMI Handler for WMI_OFFLOAD_BCN_TX_STATUS_EVENTID event from firmware.
448 * This event is generated by FW when the beacon transmission is offloaded
449 * and the host performs beacon template modification using WMI_BCN_TMPL_CMDID
450 * The FW generates this event when the first successful beacon transmission
451 * after template update
452 *
453 * Return: 0 for success or error code
454 */
455int wma_unified_bcntx_status_event_handler(void *handle,
456 uint8_t *cmd_param_info,
457 uint32_t len)
458{
459 tp_wma_handle wma = (tp_wma_handle) handle;
460 WMI_OFFLOAD_BCN_TX_STATUS_EVENTID_param_tlvs *param_buf;
461 wmi_offload_bcn_tx_status_event_fixed_param *resp_event;
462 tSirFirstBeaconTxCompleteInd *beacon_tx_complete_ind;
463
464 param_buf =
465 (WMI_OFFLOAD_BCN_TX_STATUS_EVENTID_param_tlvs *) cmd_param_info;
466 if (!param_buf) {
467 WMA_LOGE("Invalid bcn tx response event buffer");
468 return -EINVAL;
469 }
470
471 resp_event = param_buf->fixed_param;
472
Chandrasekaran, Manishekarce2172e2016-02-18 16:12:43 +0530473 WMA_LOGD("%s", __func__);
474
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800475 /* Check for valid handle to ensure session is not
476 * deleted in any race
477 */
478 if (!wma->interfaces[resp_event->vdev_id].handle) {
479 WMA_LOGE("%s: The session does not exist", __func__);
480 return -EINVAL;
481 }
482
483 /* Beacon Tx Indication supports only AP mode. Ignore in other modes */
484 if (wma_is_vdev_in_ap_mode(wma, resp_event->vdev_id) == false) {
485 WMA_LOGI("%s: Beacon Tx Indication does not support type %d and sub_type %d",
486 __func__, wma->interfaces[resp_event->vdev_id].type,
487 wma->interfaces[resp_event->vdev_id].sub_type);
488 return 0;
489 }
490
491 beacon_tx_complete_ind = (tSirFirstBeaconTxCompleteInd *)
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530492 qdf_mem_malloc(sizeof(tSirFirstBeaconTxCompleteInd));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800493 if (!beacon_tx_complete_ind) {
494 WMA_LOGE("%s: Failed to alloc beacon_tx_complete_ind",
495 __func__);
496 return -ENOMEM;
497 }
498
499 beacon_tx_complete_ind->messageType = WMA_DFS_BEACON_TX_SUCCESS_IND;
500 beacon_tx_complete_ind->length = sizeof(tSirFirstBeaconTxCompleteInd);
501 beacon_tx_complete_ind->bssIdx = resp_event->vdev_id;
502
503 wma_send_msg(wma, WMA_DFS_BEACON_TX_SUCCESS_IND,
504 (void *)beacon_tx_complete_ind, 0);
505 return 0;
506}
507
508/**
509 * wma_get_link_probe_timeout() - get link timeout based on sub type
510 * @mac: UMAC handler
511 * @sub_type: vdev syb type
512 * @max_inactive_time: return max inactive time
513 * @max_unresponsive_time: return max unresponsive time
514 *
515 * Return: none
516 */
517static inline void wma_get_link_probe_timeout(struct sAniSirGlobal *mac,
518 uint32_t sub_type,
519 uint32_t *max_inactive_time,
520 uint32_t *max_unresponsive_time)
521{
522 uint32_t keep_alive;
523 uint16_t lm_id, ka_id;
524
525 switch (sub_type) {
526 case WMI_UNIFIED_VDEV_SUBTYPE_P2P_GO:
527 lm_id = WNI_CFG_GO_LINK_MONITOR_TIMEOUT;
528 ka_id = WNI_CFG_GO_KEEP_ALIVE_TIMEOUT;
529 break;
530 default:
531 /*For softAp the subtype value will be zero */
532 lm_id = WNI_CFG_AP_LINK_MONITOR_TIMEOUT;
533 ka_id = WNI_CFG_AP_KEEP_ALIVE_TIMEOUT;
534 }
535
536 if (wlan_cfg_get_int(mac, lm_id, max_inactive_time) != eSIR_SUCCESS) {
537 WMA_LOGE("Failed to read link monitor for subtype %d",
538 sub_type);
539 *max_inactive_time = WMA_LINK_MONITOR_DEFAULT_TIME_SECS;
540 }
541
542 if (wlan_cfg_get_int(mac, ka_id, &keep_alive) != eSIR_SUCCESS) {
543 WMA_LOGE("Failed to read keep alive for subtype %d", sub_type);
544 keep_alive = WMA_KEEP_ALIVE_DEFAULT_TIME_SECS;
545 }
546 *max_unresponsive_time = *max_inactive_time + keep_alive;
547}
548
549/**
550 * wma_set_sap_keepalive() - set SAP keep alive parameters to fw
551 * @wma: wma handle
552 * @vdev_id: vdev id
553 *
554 * Return: none
555 */
556void wma_set_sap_keepalive(tp_wma_handle wma, uint8_t vdev_id)
557{
558 uint32_t min_inactive_time, max_inactive_time, max_unresponsive_time;
Anurag Chouhan6d760662016-02-20 16:05:43 +0530559 struct sAniSirGlobal *mac = cds_get_context(QDF_MODULE_ID_PE);
Govind Singhd76a5b02016-03-08 15:12:14 +0530560 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800561
562 if (NULL == mac) {
563 WMA_LOGE("%s: Failed to get mac", __func__);
564 return;
565 }
566
567 wma_get_link_probe_timeout(mac, wma->interfaces[vdev_id].sub_type,
568 &max_inactive_time, &max_unresponsive_time);
569
570 min_inactive_time = max_inactive_time / 2;
571
Govind Singhd76a5b02016-03-08 15:12:14 +0530572 status = wma_vdev_set_param(wma->wmi_handle,
573 vdev_id,
574 WMI_VDEV_PARAM_AP_KEEPALIVE_MIN_IDLE_INACTIVE_TIME_SECS,
575 min_inactive_time);
576 if (QDF_IS_STATUS_ERROR(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800577 WMA_LOGE("Failed to Set AP MIN IDLE INACTIVE TIME");
578
Govind Singhd76a5b02016-03-08 15:12:14 +0530579 status = wma_vdev_set_param(wma->wmi_handle,
580 vdev_id,
581 WMI_VDEV_PARAM_AP_KEEPALIVE_MAX_IDLE_INACTIVE_TIME_SECS,
582 max_inactive_time);
583 if (QDF_IS_STATUS_ERROR(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800584 WMA_LOGE("Failed to Set AP MAX IDLE INACTIVE TIME");
585
Govind Singhd76a5b02016-03-08 15:12:14 +0530586 status = wma_vdev_set_param(wma->wmi_handle,
587 vdev_id,
588 WMI_VDEV_PARAM_AP_KEEPALIVE_MAX_UNRESPONSIVE_TIME_SECS,
589 max_unresponsive_time);
590 if (QDF_IS_STATUS_ERROR(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800591 WMA_LOGE("Failed to Set MAX UNRESPONSIVE TIME");
592
593 WMA_LOGD("%s:vdev_id:%d min_inactive_time: %u max_inactive_time: %u"
594 " max_unresponsive_time: %u", __func__, vdev_id,
595 min_inactive_time, max_inactive_time, max_unresponsive_time);
596}
597
598/**
mukul sharma72c8b222015-09-04 17:02:01 +0530599 * wma_set_sta_sa_query_param() - set sta sa query parameters
600 * @wma: wma handle
601 * @vdev_id: vdev id
602
603 * This function sets sta query related parameters in fw.
604 *
605 * Return: none
606 */
607
608void wma_set_sta_sa_query_param(tp_wma_handle wma,
609 uint8_t vdev_id)
610{
Anurag Chouhan6d760662016-02-20 16:05:43 +0530611 struct sAniSirGlobal *mac = cds_get_context(QDF_MODULE_ID_PE);
mukul sharma72c8b222015-09-04 17:02:01 +0530612 uint32_t max_retries, retry_interval;
mukul sharma72c8b222015-09-04 17:02:01 +0530613
614 WMA_LOGD(FL("Enter:"));
mukul sharma72c8b222015-09-04 17:02:01 +0530615
616 if (wlan_cfg_get_int
617 (mac, WNI_CFG_PMF_SA_QUERY_MAX_RETRIES,
618 &max_retries) != eSIR_SUCCESS) {
619 max_retries = DEFAULT_STA_SA_QUERY_MAX_RETRIES_COUNT;
620 WMA_LOGE(FL("Failed to get value for WNI_CFG_PMF_SA_QUERY_MAX_RETRIES"));
621 }
622 if (wlan_cfg_get_int
623 (mac, WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL,
624 &retry_interval) != eSIR_SUCCESS) {
625 retry_interval = DEFAULT_STA_SA_QUERY_RETRY_INTERVAL;
626 WMA_LOGE(FL("Failed to get value for WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL"));
627 }
628
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530629 wmi_unified_set_sta_sa_query_param_cmd(wma->wmi_handle,
630 vdev_id,
631 max_retries,
632 retry_interval);
mukul sharma72c8b222015-09-04 17:02:01 +0530633
634 WMA_LOGD(FL("Exit :"));
635 return;
636}
637
638/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800639 * wma_set_sta_keep_alive() - set sta keep alive parameters
640 * @wma: wma handle
641 * @vdev_id: vdev id
642 * @method: method for keep alive
643 * @timeperiod: time period
644 * @hostv4addr: host ipv4 address
645 * @destv4addr: dst ipv4 address
646 * @destmac: destination mac
647 *
648 * This function sets keep alive related parameters in fw.
649 *
650 * Return: none
651 */
652void wma_set_sta_keep_alive(tp_wma_handle wma, uint8_t vdev_id,
653 uint32_t method, uint32_t timeperiod,
654 uint8_t *hostv4addr, uint8_t *destv4addr,
655 uint8_t *destmac)
656{
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530657 struct sta_params params;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800658
659 WMA_LOGD("%s: Enter", __func__);
660
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530661 if (!wma) {
662 WMA_LOGE("%s: wma handle is NULL", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800663 return;
664 }
665
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530666 params.vdev_id = vdev_id;
667 params.method = method;
668 params.timeperiod = timeperiod;
669 params.hostv4addr = hostv4addr;
670 params.destv4addr = destv4addr;
671 params.destmac = destmac;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800672
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530673 wmi_unified_set_sta_keep_alive_cmd(wma->wmi_handle,
674 &params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800675
676 WMA_LOGD("%s: Exit", __func__);
677 return;
678}
679
680/**
681 * wma_vdev_install_key_complete_event_handler() - install key complete handler
682 * @handle: wma handle
683 * @event: event data
684 * @len: data length
685 *
686 * This event is sent by fw once WPA/WPA2 keys are installed in fw.
687 *
688 * Return: 0 for success or error code
689 */
690int wma_vdev_install_key_complete_event_handler(void *handle,
691 uint8_t *event,
692 uint32_t len)
693{
694 WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID_param_tlvs *param_buf = NULL;
695 wmi_vdev_install_key_complete_event_fixed_param *key_fp = NULL;
696
697 if (!event) {
698 WMA_LOGE("%s: event param null", __func__);
699 return -EINVAL;
700 }
701
702 param_buf = (WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID_param_tlvs *) event;
703 if (!param_buf) {
704 WMA_LOGE("%s: received null buf from target", __func__);
705 return -EINVAL;
706 }
707
708 key_fp = param_buf->fixed_param;
709 if (!key_fp) {
710 WMA_LOGE("%s: received null event data from target", __func__);
711 return -EINVAL;
712 }
713 /*
714 * Do nothing for now. Completion of set key is already indicated to lim
715 */
716 WMA_LOGI("%s: WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID", __func__);
717 return 0;
718}
719/*
720 * 802.11n D2.0 defined values for "Minimum MPDU Start Spacing":
721 * 0 for no restriction
722 * 1 for 1/4 us - Our lower layer calculations limit our precision to 1 msec
723 * 2 for 1/2 us - Our lower layer calculations limit our precision to 1 msec
724 * 3 for 1 us
725 * 4 for 2 us
726 * 5 for 4 us
727 * 6 for 8 us
728 * 7 for 16 us
729 */
730static const uint8_t wma_mpdu_spacing[] = { 0, 1, 1, 1, 2, 4, 8, 16 };
731
732/**
733 * wma_parse_mpdudensity() - give mpdu spacing from mpdu density
734 * @mpdudensity: mpdu density
735 *
736 * Return: mpdu spacing or 0 for error
737 */
738static inline uint8_t wma_parse_mpdudensity(uint8_t mpdudensity)
739{
740 if (mpdudensity < sizeof(wma_mpdu_spacing))
741 return wma_mpdu_spacing[mpdudensity];
742 else
743 return 0;
744}
745
746/**
747 * wmi_unified_send_peer_assoc() - send peer assoc command to fw
748 * @wma: wma handle
749 * @nw_type: nw type
750 * @params: add sta params
751 *
752 * This function send peer assoc command to firmware with
753 * different parameters.
754 *
Govind Singhb30d4c02016-03-24 11:01:23 +0530755 * Return: QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800756 */
Govind Singhb30d4c02016-03-24 11:01:23 +0530757QDF_STATUS wma_send_peer_assoc(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800758 tSirNwType nw_type,
759 tpAddStaParams params)
760{
761 ol_txrx_pdev_handle pdev;
Govind Singhb30d4c02016-03-24 11:01:23 +0530762 struct peer_assoc_params *cmd;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800763 int32_t ret, max_rates, i;
764 uint8_t rx_stbc, tx_stbc;
Govind Singhb30d4c02016-03-24 11:01:23 +0530765 uint8_t *rate_pos;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800766 wmi_rate_set peer_legacy_rates, peer_ht_rates;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800767 uint32_t num_peer_11b_rates = 0;
768 uint32_t num_peer_11a_rates = 0;
769 uint32_t phymode;
770 uint32_t peer_nss = 1;
771 struct wma_txrx_node *intr = NULL;
Govind Singhb30d4c02016-03-24 11:01:23 +0530772 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800773
Govind Singhb30d4c02016-03-24 11:01:23 +0530774 cmd = qdf_mem_malloc(sizeof(struct peer_assoc_params));
775 if (!cmd) {
776 WMA_LOGE("Failed to allocate peer_assoc_params param");
777 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800778 }
Govind Singhb30d4c02016-03-24 11:01:23 +0530779
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800780 intr = &wma->interfaces[params->smesessionId];
781
Anurag Chouhan6d760662016-02-20 16:05:43 +0530782 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800783
784 if (NULL == pdev) {
785 WMA_LOGE("%s: Failed to get pdev", __func__);
Govind Singhb30d4c02016-03-24 11:01:23 +0530786 qdf_mem_free(cmd);
787 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800788 }
789
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530790 qdf_mem_zero(&peer_legacy_rates, sizeof(wmi_rate_set));
791 qdf_mem_zero(&peer_ht_rates, sizeof(wmi_rate_set));
Govind Singhb30d4c02016-03-24 11:01:23 +0530792 qdf_mem_zero(cmd, sizeof(struct peer_assoc_params));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800793
794 phymode = wma_peer_phymode(nw_type, params->staType,
795 params->htCapable,
796 params->ch_width,
797 params->vhtCapable);
798
799 /* Legacy Rateset */
800 rate_pos = (uint8_t *) peer_legacy_rates.rates;
801 for (i = 0; i < SIR_NUM_11B_RATES; i++) {
802 if (!params->supportedRates.llbRates[i])
803 continue;
804 rate_pos[peer_legacy_rates.num_rates++] =
805 params->supportedRates.llbRates[i];
806 num_peer_11b_rates++;
807 }
808 for (i = 0; i < SIR_NUM_11A_RATES; i++) {
809 if (!params->supportedRates.llaRates[i])
810 continue;
811 rate_pos[peer_legacy_rates.num_rates++] =
812 params->supportedRates.llaRates[i];
813 num_peer_11a_rates++;
814 }
815
816 if ((phymode == MODE_11A && num_peer_11a_rates == 0) ||
817 (phymode == MODE_11B && num_peer_11b_rates == 0)) {
818 WMA_LOGW("%s: Invalid phy rates. phymode 0x%x, 11b_rates %d, 11a_rates %d",
819 __func__, phymode, num_peer_11b_rates, num_peer_11a_rates);
Govind Singhb30d4c02016-03-24 11:01:23 +0530820 qdf_mem_free(cmd);
821 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800822 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800823
824 /* HT Rateset */
825 max_rates = sizeof(peer_ht_rates.rates) /
826 sizeof(peer_ht_rates.rates[0]);
827 rate_pos = (uint8_t *) peer_ht_rates.rates;
828 for (i = 0; i < MAX_SUPPORTED_RATES; i++) {
829 if (params->supportedRates.supportedMCSSet[i / 8] &
830 (1 << (i % 8))) {
831 rate_pos[peer_ht_rates.num_rates++] = i;
832 if (i >= 8) {
833 /* MCS8 or higher rate is present, must be 2x2 */
834 peer_nss = 2;
835 }
836 }
837 if (peer_ht_rates.num_rates == max_rates)
838 break;
839 }
840
841 if (params->htCapable && !peer_ht_rates.num_rates) {
842 uint8_t temp_ni_rates[8] = { 0x0, 0x1, 0x2, 0x3,
843 0x4, 0x5, 0x6, 0x7};
844 /*
845 * Workaround for EV 116382: The peer is marked HT but with
846 * supported rx mcs set is set to 0. 11n spec mandates MCS0-7
847 * for a HT STA. So forcing the supported rx mcs rate to
848 * MCS 0-7. This workaround will be removed once we get
849 * clarification from WFA regarding this STA behavior.
850 */
851
852 /* TODO: Do we really need this? */
853 WMA_LOGW("Peer is marked as HT capable but supported mcs rate is 0");
854 peer_ht_rates.num_rates = sizeof(temp_ni_rates);
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530855 qdf_mem_copy((uint8_t *) peer_ht_rates.rates, temp_ni_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800856 peer_ht_rates.num_rates);
857 }
858
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800859 /* in ap/ibss mode and for tdls peer, use mac address of the peer in
860 * the other end as the new peer address; in sta mode, use bss id to
861 * be the new peer address
862 */
863 if ((wma_is_vdev_in_ap_mode(wma, params->smesessionId))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800864 || (wma_is_vdev_in_ibss_mode(wma, params->smesessionId))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800865#ifdef FEATURE_WLAN_TDLS
866 || (STA_ENTRY_TDLS_PEER == params->staType)
867#endif /* FEATURE_WLAN_TDLS */
868 )
869 WMI_CHAR_ARRAY_TO_MAC_ADDR(params->staMac, &cmd->peer_macaddr);
870 else
871 WMI_CHAR_ARRAY_TO_MAC_ADDR(params->bssId, &cmd->peer_macaddr);
872 cmd->vdev_id = params->smesessionId;
873 cmd->peer_new_assoc = 1;
874 cmd->peer_associd = params->assocId;
875
876 /*
877 * The target only needs a subset of the flags maintained in the host.
878 * Just populate those flags and send it down
879 */
880 cmd->peer_flags = 0;
881
882 if (params->wmmEnabled)
883 cmd->peer_flags |= WMI_PEER_QOS;
884
885 if (params->uAPSD) {
886 cmd->peer_flags |= WMI_PEER_APSD;
887 WMA_LOGD("Set WMI_PEER_APSD: uapsd Mask %d", params->uAPSD);
888 }
889
890 if (params->htCapable) {
891 cmd->peer_flags |= (WMI_PEER_HT | WMI_PEER_QOS);
892 cmd->peer_rate_caps |= WMI_RC_HT_FLAG;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800893
Krishna Kumaar Natarajan59f546c2016-02-16 10:31:55 -0800894 if (params->ch_width) {
895 cmd->peer_flags |= WMI_PEER_40MHZ;
896 cmd->peer_rate_caps |= WMI_RC_CW40_FLAG;
897 if (params->fShortGI40Mhz)
898 cmd->peer_rate_caps |= WMI_RC_SGI_FLAG;
899 } else if (params->fShortGI20Mhz) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800900 cmd->peer_rate_caps |= WMI_RC_SGI_FLAG;
Krishna Kumaar Natarajan59f546c2016-02-16 10:31:55 -0800901 }
902 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800903
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800904 if (params->vhtCapable) {
905 cmd->peer_flags |= (WMI_PEER_HT | WMI_PEER_VHT | WMI_PEER_QOS);
906 cmd->peer_rate_caps |= WMI_RC_HT_FLAG;
907 }
908
909 if (params->ch_width == CH_WIDTH_80MHZ)
910 cmd->peer_flags |= WMI_PEER_80MHZ;
911 else if (params->ch_width == CH_WIDTH_160MHZ)
912 cmd->peer_flags |= WMI_PEER_160MHZ;
913 else if (params->ch_width == CH_WIDTH_80P80MHZ)
914 cmd->peer_flags |= WMI_PEER_160MHZ;
915
916 cmd->peer_vht_caps = params->vht_caps;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800917
918 if (params->rmfEnabled)
919 cmd->peer_flags |= WMI_PEER_PMF;
920
921 rx_stbc = (params->ht_caps & IEEE80211_HTCAP_C_RXSTBC) >>
922 IEEE80211_HTCAP_C_RXSTBC_S;
923 if (rx_stbc) {
924 cmd->peer_flags |= WMI_PEER_STBC;
925 cmd->peer_rate_caps |= (rx_stbc << WMI_RC_RX_STBC_FLAG_S);
926 }
927
928 tx_stbc = (params->ht_caps & IEEE80211_HTCAP_C_TXSTBC) >>
929 IEEE80211_HTCAP_C_TXSTBC_S;
930 if (tx_stbc) {
931 cmd->peer_flags |= WMI_PEER_STBC;
932 cmd->peer_rate_caps |= (tx_stbc << WMI_RC_TX_STBC_FLAG_S);
933 }
934
935 if (params->htLdpcCapable || params->vhtLdpcCapable)
936 cmd->peer_flags |= WMI_PEER_LDPC;
937
938 switch (params->mimoPS) {
939 case eSIR_HT_MIMO_PS_STATIC:
940 cmd->peer_flags |= WMI_PEER_STATIC_MIMOPS;
941 break;
942 case eSIR_HT_MIMO_PS_DYNAMIC:
943 cmd->peer_flags |= WMI_PEER_DYN_MIMOPS;
944 break;
945 case eSIR_HT_MIMO_PS_NO_LIMIT:
946 cmd->peer_flags |= WMI_PEER_SPATIAL_MUX;
947 break;
948 default:
949 break;
950 }
951
952#ifdef FEATURE_WLAN_TDLS
953 if (STA_ENTRY_TDLS_PEER == params->staType)
954 cmd->peer_flags |= WMI_PEER_AUTH;
955#endif /* FEATURE_WLAN_TDLS */
956
957 if (params->wpa_rsn
958#ifdef FEATURE_WLAN_WAPI
959 || params->encryptType == eSIR_ED_WPI
960#endif /* FEATURE_WLAN_WAPI */
961 )
962 cmd->peer_flags |= WMI_PEER_NEED_PTK_4_WAY;
963 if (params->wpa_rsn >> 1)
964 cmd->peer_flags |= WMI_PEER_NEED_GTK_2_WAY;
965
Dhanashri Atreb08959a2016-03-01 17:28:03 -0800966 ol_txrx_peer_state_update(pdev, params->bssId, OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800967
968#ifdef FEATURE_WLAN_WAPI
969 if (params->encryptType == eSIR_ED_WPI) {
Govind Singhd76a5b02016-03-08 15:12:14 +0530970 ret = wma_vdev_set_param(wma->wmi_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800971 params->smesessionId,
972 WMI_VDEV_PARAM_DROP_UNENCRY,
973 false);
974 if (ret) {
975 WMA_LOGE
976 ("Set WMI_VDEV_PARAM_DROP_UNENCRY Param status:%d\n",
977 ret);
Govind Singhb30d4c02016-03-24 11:01:23 +0530978 qdf_mem_free(cmd);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800979 return ret;
980 }
981 }
982#endif /* FEATURE_WLAN_WAPI */
983
984 cmd->peer_caps = params->capab_info;
985 cmd->peer_listen_intval = params->listenInterval;
986 cmd->peer_ht_caps = params->ht_caps;
987 cmd->peer_max_mpdu = (1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR +
988 params->maxAmpduSize)) - 1;
989 cmd->peer_mpdu_density = wma_parse_mpdudensity(params->maxAmpduDensity);
990
991 if (params->supportedRates.supportedMCSSet[1] &&
992 params->supportedRates.supportedMCSSet[2])
993 cmd->peer_rate_caps |= WMI_RC_TS_FLAG;
994 else if (params->supportedRates.supportedMCSSet[1])
995 cmd->peer_rate_caps |= WMI_RC_DS_FLAG;
996
997 /* Update peer legacy rate information */
Govind Singhb30d4c02016-03-24 11:01:23 +0530998 cmd->peer_legacy_rates.num_rates = peer_legacy_rates.num_rates;
999 qdf_mem_copy(cmd->peer_legacy_rates.rates, peer_legacy_rates.rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001000 peer_legacy_rates.num_rates);
1001
1002 /* Update peer HT rate information */
Govind Singhb30d4c02016-03-24 11:01:23 +05301003 cmd->peer_ht_rates.num_rates = peer_ht_rates.num_rates;
1004 qdf_mem_copy(cmd->peer_ht_rates.rates, peer_ht_rates.rates,
1005 peer_ht_rates.num_rates);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001006
1007 /* VHT Rates */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001008
1009 cmd->peer_nss = peer_nss;
Naveen Rawatb14cab32015-11-02 17:01:51 -08001010 /*
1011 * Because of DBS a vdev may come up in any of the two MACs with
1012 * different capabilities. STBC capab should be fetched for given
1013 * hard_mode->MAC_id combo. It is planned that firmware should provide
1014 * these dev capabilities. But for now number of tx streams can be used
1015 * to identify if Tx STBC needs to be disabled.
1016 */
1017 if (intr->tx_streams < 2) {
1018 cmd->peer_vht_caps &= ~(1 << SIR_MAC_VHT_CAP_TXSTBC);
1019 WMA_LOGD("Num tx_streams: %d, Disabled txSTBC",
1020 intr->tx_streams);
1021 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001022 WMA_LOGD("peer_nss %d peer_ht_rates.num_rates %d ", cmd->peer_nss,
1023 peer_ht_rates.num_rates);
1024
Govind Singhb30d4c02016-03-24 11:01:23 +05301025 cmd->vht_capable = params->vhtCapable;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001026 if (params->vhtCapable) {
1027#define VHT2x2MCSMASK 0xc
Govind Singhb30d4c02016-03-24 11:01:23 +05301028 cmd->rx_max_rate = params->supportedRates.vhtRxHighestDataRate;
1029 cmd->rx_mcs_set = params->supportedRates.vhtRxMCSMap;
1030 cmd->tx_max_rate = params->supportedRates.vhtTxHighestDataRate;
1031 cmd->tx_mcs_set = params->supportedRates.vhtTxMCSMap;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001032
1033 if (params->vhtSupportedRxNss) {
1034 cmd->peer_nss = params->vhtSupportedRxNss;
1035 } else {
Govind Singhb30d4c02016-03-24 11:01:23 +05301036 cmd->peer_nss = ((cmd->rx_mcs_set & VHT2x2MCSMASK)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001037 == VHT2x2MCSMASK) ? 1 : 2;
1038 }
1039 }
1040
1041 /*
1042 * Limit nss to max number of rf chain supported by target
1043 * Otherwise Fw will crash
1044 */
1045 wma_update_txrx_chainmask(wma->num_rf_chains, &cmd->peer_nss);
1046
1047 intr->nss = cmd->peer_nss;
1048 cmd->peer_phymode = phymode;
1049 WMA_LOGD("%s: vdev_id %d associd %d peer_flags %x rate_caps %x "
1050 "peer_caps %x listen_intval %d ht_caps %x max_mpdu %d "
1051 "nss %d phymode %d peer_mpdu_density %d encr_type %d "
1052 "cmd->peer_vht_caps %x", __func__,
1053 cmd->vdev_id, cmd->peer_associd, cmd->peer_flags,
1054 cmd->peer_rate_caps, cmd->peer_caps,
1055 cmd->peer_listen_intval, cmd->peer_ht_caps,
1056 cmd->peer_max_mpdu, cmd->peer_nss, cmd->peer_phymode,
1057 cmd->peer_mpdu_density, params->encryptType,
1058 cmd->peer_vht_caps);
1059
Govind Singhb30d4c02016-03-24 11:01:23 +05301060 status = wmi_unified_peer_assoc_send(wma->wmi_handle,
1061 cmd);
1062 if (QDF_IS_STATUS_ERROR(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001063 WMA_LOGP("%s: Failed to send peer assoc command ret = %d",
1064 __func__, ret);
Govind Singhb30d4c02016-03-24 11:01:23 +05301065 qdf_mem_free(cmd);
1066
1067 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001068}
1069
1070/**
1071 * wmi_unified_vdev_set_gtx_cfg_send() - set GTX params
1072 * @wmi_handle: wmi handle
1073 * @if_id: vdev id
1074 * @gtx_info: GTX config params
1075 *
1076 * This function set GTX related params in firmware.
1077 *
1078 * Return: 0 for success or error code
1079 */
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301080QDF_STATUS wmi_unified_vdev_set_gtx_cfg_send(wmi_unified_t wmi_handle,
1081 uint32_t if_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001082 gtx_config_t *gtx_info)
1083{
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301084 struct wmi_gtx_config params;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001085
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301086 params.gtx_rt_mask[0] = gtx_info->gtxRTMask[0];
1087 params.gtx_rt_mask[1] = gtx_info->gtxRTMask[1];
1088 params.gtx_usrcfg = gtx_info->gtxUsrcfg;
1089 params.gtx_threshold = gtx_info->gtxPERThreshold;
1090 params.gtx_margin = gtx_info->gtxPERMargin;
1091 params.gtx_tpcstep = gtx_info->gtxTPCstep;
1092 params.gtx_tpcmin = gtx_info->gtxTPCMin;
1093 params.gtx_bwmask = gtx_info->gtxBWMask;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001094
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301095 return wmi_unified_vdev_set_gtx_cfg_cmd(wmi_handle,
1096 if_id, &params);
1097
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001098}
1099
1100/**
1101 * wma_update_protection_mode() - update protection mode
1102 * @wma: wma handle
1103 * @vdev_id: vdev id
1104 * @llbcoexist: protection mode info
1105 *
1106 * This function set protection mode(RTS/CTS) to fw for passed vdev id.
1107 *
1108 * Return: none
1109 */
1110void wma_update_protection_mode(tp_wma_handle wma, uint8_t vdev_id,
1111 uint8_t llbcoexist)
1112{
Govind Singhd76a5b02016-03-08 15:12:14 +05301113 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001114 enum ieee80211_protmode prot_mode;
1115
1116 prot_mode = llbcoexist ? IEEE80211_PROT_CTSONLY : IEEE80211_PROT_NONE;
1117
Govind Singhd76a5b02016-03-08 15:12:14 +05301118 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001119 WMI_VDEV_PARAM_PROTECTION_MODE,
1120 prot_mode);
1121
Govind Singhd76a5b02016-03-08 15:12:14 +05301122 if (QDF_IS_STATUS_ERROR(ret))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001123 WMA_LOGE("Failed to send wmi protection mode cmd");
1124 else
1125 WMA_LOGD("Updated protection mode %d to target", prot_mode);
1126}
1127
1128/**
1129 * wma_update_beacon_interval() - update beacon interval in fw
1130 * @wma: wma handle
1131 * @vdev_id: vdev id
1132 * @beaconInterval: becon interval
1133 *
1134 * Return: none
1135 */
1136static void
1137wma_update_beacon_interval(tp_wma_handle wma, uint8_t vdev_id,
1138 uint16_t beaconInterval)
1139{
Govind Singhd76a5b02016-03-08 15:12:14 +05301140 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001141
Govind Singhd76a5b02016-03-08 15:12:14 +05301142 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001143 WMI_VDEV_PARAM_BEACON_INTERVAL,
1144 beaconInterval);
1145
Govind Singhd76a5b02016-03-08 15:12:14 +05301146 if (QDF_IS_STATUS_ERROR(ret))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001147 WMA_LOGE("Failed to update beacon interval");
1148 else
1149 WMA_LOGI("Updated beacon interval %d for vdev %d",
1150 beaconInterval, vdev_id);
1151}
1152
1153/**
1154 * wma_process_update_beacon_params() - update beacon parameters to target
1155 * @wma: wma handle
1156 * @bcn_params: beacon parameters
1157 *
1158 * Return: none
1159 */
1160void
1161wma_process_update_beacon_params(tp_wma_handle wma,
1162 tUpdateBeaconParams *bcn_params)
1163{
1164 if (!bcn_params) {
1165 WMA_LOGE("bcn_params NULL");
1166 return;
1167 }
1168
1169 if (bcn_params->smeSessionId >= wma->max_bssid) {
1170 WMA_LOGE("Invalid vdev id %d", bcn_params->smeSessionId);
1171 return;
1172 }
1173
1174 if (bcn_params->paramChangeBitmap & PARAM_BCN_INTERVAL_CHANGED) {
1175 wma_update_beacon_interval(wma, bcn_params->smeSessionId,
1176 bcn_params->beaconInterval);
1177 }
1178
1179 if (bcn_params->paramChangeBitmap & PARAM_llBCOEXIST_CHANGED)
1180 wma_update_protection_mode(wma, bcn_params->smeSessionId,
1181 bcn_params->llbCoexist);
1182}
1183
1184/**
1185 * wma_update_cfg_params() - update cfg parameters to target
1186 * @wma: wma handle
1187 * @cfgParam: cfg parameter
1188 *
1189 * Return: none
1190 */
1191void wma_update_cfg_params(tp_wma_handle wma, tSirMsgQ *cfgParam)
1192{
1193 uint8_t vdev_id;
1194 uint32_t param_id;
1195 uint32_t cfg_val;
Govind Singhd76a5b02016-03-08 15:12:14 +05301196 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001197 /* get mac to acess CFG data base */
1198 struct sAniSirGlobal *pmac;
1199
1200 switch (cfgParam->bodyval) {
1201 case WNI_CFG_RTS_THRESHOLD:
1202 param_id = WMI_VDEV_PARAM_RTS_THRESHOLD;
1203 break;
1204 case WNI_CFG_FRAGMENTATION_THRESHOLD:
1205 param_id = WMI_VDEV_PARAM_FRAGMENTATION_THRESHOLD;
1206 break;
1207 default:
1208 WMA_LOGD("Unhandled cfg parameter %d", cfgParam->bodyval);
1209 return;
1210 }
1211
Anurag Chouhan6d760662016-02-20 16:05:43 +05301212 pmac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001213
1214 if (NULL == pmac) {
1215 WMA_LOGE("%s: Failed to get pmac", __func__);
1216 return;
1217 }
1218
1219 if (wlan_cfg_get_int(pmac, (uint16_t) cfgParam->bodyval,
1220 &cfg_val) != eSIR_SUCCESS) {
1221 WMA_LOGE("Failed to get value for CFG PARAMS %d. returning without updating",
1222 cfgParam->bodyval);
1223 return;
1224 }
1225
1226 for (vdev_id = 0; vdev_id < wma->max_bssid; vdev_id++) {
1227 if (wma->interfaces[vdev_id].handle != 0) {
Govind Singhd76a5b02016-03-08 15:12:14 +05301228 ret = wma_vdev_set_param(wma->wmi_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001229 vdev_id, param_id,
1230 cfg_val);
Govind Singhd76a5b02016-03-08 15:12:14 +05301231 if (QDF_IS_STATUS_ERROR(ret))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001232 WMA_LOGE("Update cfg params failed for vdevId %d",
1233 vdev_id);
1234 }
1235 }
1236}
1237
1238/**
1239 * wma_read_cfg_wepkey() - fill key_info for WEP key
1240 * @wma_handle: wma handle
1241 * @key_info: key_info ptr
1242 * @def_key_idx: default key index
1243 * @num_keys: number of keys
1244 *
1245 * This function reads WEP keys from cfg and fills
1246 * up key_info.
1247 *
1248 * Return: none
1249 */
1250static void wma_read_cfg_wepkey(tp_wma_handle wma_handle,
1251 tSirKeys *key_info, uint32_t *def_key_idx,
1252 uint8_t *num_keys)
1253{
1254 tSirRetStatus status;
1255 uint32_t val = SIR_MAC_KEY_LENGTH;
1256 uint8_t i, j;
1257
1258 WMA_LOGD("Reading WEP keys from cfg");
1259 /* NOTE:def_key_idx is initialized to 0 by the caller */
1260 status = wlan_cfg_get_int(wma_handle->mac_context,
1261 WNI_CFG_WEP_DEFAULT_KEYID, def_key_idx);
1262 if (status != eSIR_SUCCESS)
1263 WMA_LOGE("Unable to read default id, defaulting to 0");
1264
1265 for (i = 0, j = 0; i < SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS; i++) {
1266 status = wlan_cfg_get_str(wma_handle->mac_context,
1267 (uint16_t) WNI_CFG_WEP_DEFAULT_KEY_1 +
1268 i, key_info[j].key, &val);
1269 if (status != eSIR_SUCCESS) {
1270 WMA_LOGE("WEP key is not configured at :%d", i);
1271 } else {
1272 key_info[j].keyId = i;
1273 key_info[j].keyLength = (uint16_t) val;
1274 j++;
1275 }
1276 }
1277 *num_keys = j;
1278}
1279
1280/**
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301281 * wma_setup_install_key_cmd() - set key parameters
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001282 * @wma_handle: wma handle
1283 * @key_params: key parameters
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001284 * @mode: op mode
1285 *
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301286 * This function fills structure from information
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001287 * passed in key_params.
1288 *
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301289 * Return: QDF_STATUS_SUCCESS - success
1290 QDF_STATUS_E_FAILURE - failure
1291 QDF_STATUS_E_NOMEM - invalid request
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001292 */
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301293static QDF_STATUS wma_setup_install_key_cmd(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001294 struct wma_set_key_params
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301295 *key_params, uint8_t mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001296{
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301297 struct set_key_params params;
1298 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001299#ifdef WLAN_FEATURE_11W
1300 struct wma_txrx_node *iface = NULL;
1301#endif /* WLAN_FEATURE_11W */
1302 if ((key_params->key_type == eSIR_ED_NONE &&
1303 key_params->key_len) || (key_params->key_type != eSIR_ED_NONE &&
1304 !key_params->key_len)) {
1305 WMA_LOGE("%s:Invalid set key request", __func__);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301306 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001307 }
1308
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301309 params.vdev_id = key_params->vdev_id;
1310 params.key_idx = key_params->key_idx;
1311 qdf_mem_copy(params.peer_mac, key_params->peer_mac, IEEE80211_ADDR_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001312
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301313#ifdef FEATURE_WLAN_WAPI
1314 qdf_mem_set(params.tx_iv, 16, 0);
1315 qdf_mem_set(params.rx_iv, 16, 0);
1316#endif
1317 params.key_txmic_len = 0;
1318 params.key_rxmic_len = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001319
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301320 params.key_flags = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001321 if (key_params->unicast)
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301322 params.key_flags |= PAIRWISE_USAGE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001323 else
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301324 params.key_flags |= GROUP_USAGE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001325
1326 switch (key_params->key_type) {
1327 case eSIR_ED_NONE:
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301328 params.key_cipher = WMI_CIPHER_NONE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001329 break;
1330 case eSIR_ED_WEP40:
1331 case eSIR_ED_WEP104:
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301332 params.key_cipher = WMI_CIPHER_WEP;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001333 if (key_params->unicast &&
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301334 params.key_idx == key_params->def_key_idx) {
Ganesh Kondabattini59a4a952015-11-30 11:55:40 +05301335 WMA_LOGD("STA Mode: cmd->key_flags |= TX_USAGE");
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301336 params.key_flags |= TX_USAGE;
Ganesh Kondabattini59a4a952015-11-30 11:55:40 +05301337 } else if ((mode == wlan_op_mode_ap) &&
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301338 (params.key_idx == key_params->def_key_idx)) {
Ganesh Kondabattini59a4a952015-11-30 11:55:40 +05301339 WMA_LOGD("AP Mode: cmd->key_flags |= TX_USAGE");
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301340 params.key_flags |= TX_USAGE;
Ganesh Kondabattini59a4a952015-11-30 11:55:40 +05301341 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001342 break;
1343 case eSIR_ED_TKIP:
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301344 params.key_txmic_len = WMA_TXMIC_LEN;
1345 params.key_rxmic_len = WMA_RXMIC_LEN;
1346 params.key_cipher = WMI_CIPHER_TKIP;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001347 break;
1348#ifdef FEATURE_WLAN_WAPI
1349#define WPI_IV_LEN 16
1350 case eSIR_ED_WPI:
1351 {
1352 /*initialize receive and transmit IV with default values */
1353 /* **Note: tx_iv must be sent in reverse** */
1354 unsigned char tx_iv[16] = { 0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c,
1355 0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c,
1356 0x36, 0x5c, 0x36, 0x5c};
1357 unsigned char rx_iv[16] = { 0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36,
1358 0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36,
1359 0x5c, 0x36, 0x5c, 0x37};
1360 if (mode == wlan_op_mode_ap) {
1361 /* Authenticator initializes the value of PN as
1362 * 0x5C365C365C365C365C365C365C365C36 for MCastkey Update
1363 */
1364 if (key_params->unicast)
1365 tx_iv[0] = 0x37;
1366
1367 rx_iv[WPI_IV_LEN - 1] = 0x36;
1368 } else {
1369 if (!key_params->unicast)
1370 rx_iv[WPI_IV_LEN - 1] = 0x36;
1371 }
1372
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301373 params.key_txmic_len = WMA_TXMIC_LEN;
1374 params.key_rxmic_len = WMA_RXMIC_LEN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001375
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301376 qdf_mem_copy(&params.rx_iv, &rx_iv,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001377 WPI_IV_LEN);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301378 qdf_mem_copy(&params.tx_iv, &tx_iv,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001379 WPI_IV_LEN);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301380 params.key_cipher = WMI_CIPHER_WAPI;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001381 break;
1382 }
1383#endif /* FEATURE_WLAN_WAPI */
1384 case eSIR_ED_CCMP:
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301385 params.key_cipher = WMI_CIPHER_AES_CCM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001386 break;
1387#ifdef WLAN_FEATURE_11W
1388 case eSIR_ED_AES_128_CMAC:
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301389 params.key_cipher = WMI_CIPHER_AES_CMAC;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001390 break;
1391#endif /* WLAN_FEATURE_11W */
1392 default:
1393 /* TODO: MFP ? */
1394 WMA_LOGE("%s:Invalid encryption type:%d", __func__,
1395 key_params->key_type);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301396 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001397 }
1398
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001399#ifdef BIG_ENDIAN_HOST
1400 {
1401 /* for big endian host, copy engine byte_swap is enabled
1402 * But the key data content is in network byte order
1403 * Need to byte swap the key data content - so when copy engine
1404 * does byte_swap - target gets key_data content in the correct
1405 * order.
1406 */
1407 int8_t i;
1408 uint32_t *destp, *srcp;
1409
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301410 destp = (uint32_t *) params.key_data;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001411 srcp = (uint32_t *) key_params->key_data;
1412 for (i = 0;
1413 i < roundup(key_params->key_len, sizeof(uint32_t)) / 4;
1414 i++) {
1415 *destp = le32_to_cpu(*srcp);
1416 destp++;
1417 srcp++;
1418 }
1419 }
1420#else
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301421 qdf_mem_copy((void *)params.key_data,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001422 (const void *)key_params->key_data, key_params->key_len);
1423#endif /* BIG_ENDIAN_HOST */
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301424 params.key_len = key_params->key_len;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001425
1426#ifdef WLAN_FEATURE_11W
1427 if (key_params->key_type == eSIR_ED_AES_128_CMAC) {
1428 iface = &wma_handle->interfaces[key_params->vdev_id];
1429 if (iface) {
1430 iface->key.key_length = key_params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301431 qdf_mem_copy(iface->key.key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001432 (const void *)key_params->key_data,
1433 iface->key.key_length);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301434 if ((params.key_idx == WMA_IGTK_KEY_INDEX_4) ||
1435 (params.key_idx == WMA_IGTK_KEY_INDEX_5))
1436 qdf_mem_zero(iface->key.key_id[params.key_idx -
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001437 WMA_IGTK_KEY_INDEX_4].ipn,
1438 CMAC_IPN_LEN);
1439 }
1440 }
1441#endif /* WLAN_FEATURE_11W */
1442
1443 WMA_LOGD("Key setup : vdev_id %d key_idx %d key_type %d key_len %d"
1444 " unicast %d peer_mac %pM def_key_idx %d", key_params->vdev_id,
1445 key_params->key_idx, key_params->key_type, key_params->key_len,
1446 key_params->unicast, key_params->peer_mac,
1447 key_params->def_key_idx);
1448
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301449 status = wmi_unified_setup_install_key_cmd(wma_handle->wmi_handle,
1450 &params);
1451
1452 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001453}
1454
1455/**
1456 * wma_set_bsskey() - set encryption key to fw.
1457 * @wma_handle: wma handle
1458 * @key_info: key info
1459 *
1460 * Return: none
1461 */
1462void wma_set_bsskey(tp_wma_handle wma_handle, tpSetBssKeyParams key_info)
1463{
1464 struct wma_set_key_params key_params;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301465 QDF_STATUS status = QDF_STATUS_SUCCESS;
1466 uint32_t i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001467 uint32_t def_key_idx = 0;
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001468 uint32_t wlan_opmode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001469 ol_txrx_vdev_handle txrx_vdev;
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001470 uint8_t *mac_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001471
1472 WMA_LOGD("BSS key setup");
1473 txrx_vdev = wma_find_vdev_by_id(wma_handle, key_info->smesessionId);
1474 if (!txrx_vdev) {
1475 WMA_LOGE("%s:Invalid vdev handle", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301476 key_info->status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001477 goto out;
1478 }
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001479 wlan_opmode = ol_txrx_get_opmode(txrx_vdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001480
1481 /*
1482 * For IBSS, WMI expects the BSS key to be set per peer key
1483 * So cache the BSS key in the wma_handle and re-use it when the
1484 * STA key is been setup for a peer
1485 */
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001486 if (wlan_op_mode_ibss == wlan_opmode) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301487 key_info->status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001488 if (wma_handle->ibss_started > 0)
1489 goto out;
1490 WMA_LOGD("Caching IBSS Key");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301491 qdf_mem_copy(&wma_handle->ibsskey_info, key_info,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001492 sizeof(tSetBssKeyParams));
1493 }
1494
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301495 qdf_mem_set(&key_params, sizeof(key_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001496 key_params.vdev_id = key_info->smesessionId;
1497 key_params.key_type = key_info->encType;
1498 key_params.singl_tid_rc = key_info->singleTidRc;
1499 key_params.unicast = false;
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001500 if (wlan_opmode == wlan_op_mode_sta) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301501 qdf_mem_copy(key_params.peer_mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001502 wma_handle->interfaces[key_info->smesessionId].bssid,
1503 IEEE80211_ADDR_LEN);
1504 } else {
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001505 mac_addr = ol_txrx_get_vdev_mac_addr(txrx_vdev);
1506 if (mac_addr == NULL) {
1507 WMA_LOGE("%s: mac_addr is NULL for vdev with id %d",
1508 __func__, key_info->smesessionId);
1509 goto out;
1510 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001511 /* vdev mac address will be passed for all other modes */
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001512 qdf_mem_copy(key_params.peer_mac, mac_addr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001513 IEEE80211_ADDR_LEN);
1514 WMA_LOGA("BSS Key setup with vdev_mac %pM\n",
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001515 mac_addr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001516 }
1517
1518 if (key_info->numKeys == 0 &&
1519 (key_info->encType == eSIR_ED_WEP40 ||
1520 key_info->encType == eSIR_ED_WEP104)) {
1521 wma_read_cfg_wepkey(wma_handle, key_info->key,
1522 &def_key_idx, &key_info->numKeys);
1523 }
1524
1525 for (i = 0; i < key_info->numKeys; i++) {
1526 if (key_params.key_type != eSIR_ED_NONE &&
1527 !key_info->key[i].keyLength)
1528 continue;
1529 if (key_info->encType == eSIR_ED_WPI) {
1530 key_params.key_idx = key_info->key[i].keyId;
1531 key_params.def_key_idx = key_info->key[i].keyId;
1532 } else
1533 key_params.key_idx = key_info->key[i].keyId;
1534
1535 key_params.key_len = key_info->key[i].keyLength;
1536 if (key_info->encType == eSIR_ED_TKIP) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301537 qdf_mem_copy(key_params.key_data,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001538 key_info->key[i].key, 16);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301539 qdf_mem_copy(&key_params.key_data[16],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001540 &key_info->key[i].key[24], 8);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301541 qdf_mem_copy(&key_params.key_data[24],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001542 &key_info->key[i].key[16], 8);
1543 } else
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301544 qdf_mem_copy((void *)key_params.key_data,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001545 (const void *)key_info->key[i].key,
1546 key_info->key[i].keyLength);
1547
1548 WMA_LOGD("%s: bss key[%d] length %d", __func__, i,
1549 key_info->key[i].keyLength);
1550
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301551 status = wma_setup_install_key_cmd(wma_handle, &key_params,
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001552 wlan_opmode);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301553 if (status == QDF_STATUS_E_NOMEM) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001554 WMA_LOGE("%s:Failed to setup install key buf",
1555 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301556 key_info->status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001557 goto out;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301558 } else if (status == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001559 WMA_LOGE("%s:Failed to send install key command",
1560 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301561 key_info->status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001562 goto out;
1563 }
1564 }
1565
1566 wma_handle->ibss_started++;
1567 /* TODO: Should we wait till we get HTT_T2H_MSG_TYPE_SEC_IND? */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301568 key_info->status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001569
1570out:
1571 wma_send_msg(wma_handle, WMA_SET_BSSKEY_RSP, (void *)key_info, 0);
1572}
1573
1574#ifdef QCA_IBSS_SUPPORT
1575/**
1576 * wma_calc_ibss_heart_beat_timer() - calculate IBSS heart beat timer
1577 * @peer_num: number of peers
1578 *
1579 * Return: heart beat timer value
1580 */
1581static uint16_t wma_calc_ibss_heart_beat_timer(int16_t peer_num)
1582{
1583 /* heart beat timer value look-up table */
1584 /* entry index : (the number of currently connected peers) - 1
1585 entry value : the heart time threshold value in seconds for
1586 detecting ibss peer departure */
1587 static const uint16_t heart_beat_timer[MAX_IBSS_PEERS] = {
1588 4, 4, 4, 4, 4, 4, 4, 4,
1589 8, 8, 8, 8, 8, 8, 8, 8,
1590 12, 12, 12, 12, 12, 12, 12, 12,
1591 16, 16, 16, 16, 16, 16, 16, 16
1592 };
1593
1594 if (peer_num < 1 || peer_num > MAX_IBSS_PEERS)
1595 return 0;
1596
1597 return heart_beat_timer[peer_num - 1];
1598
1599}
1600
1601/**
1602 * wma_adjust_ibss_heart_beat_timer() - set ibss heart beat timer in fw.
1603 * @wma: wma handle
1604 * @vdev_id: vdev id
1605 * @peer_num_delta: peer number delta value
1606 *
1607 * Return: none
1608 */
1609void wma_adjust_ibss_heart_beat_timer(tp_wma_handle wma,
1610 uint8_t vdev_id,
1611 int8_t peer_num_delta)
1612{
1613 ol_txrx_vdev_handle vdev;
1614 int16_t new_peer_num;
1615 uint16_t new_timer_value_sec;
1616 uint32_t new_timer_value_ms;
Govind Singhd76a5b02016-03-08 15:12:14 +05301617 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001618
1619 if (peer_num_delta != 1 && peer_num_delta != -1) {
1620 WMA_LOGE("Invalid peer_num_delta value %d", peer_num_delta);
1621 return;
1622 }
1623
1624 vdev = wma_find_vdev_by_id(wma, vdev_id);
1625 if (!vdev) {
1626 WMA_LOGE("vdev not found : vdev_id %d", vdev_id);
1627 return;
1628 }
1629
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001630 /* adjust peer numbers */
1631 new_peer_num = ol_txrx_update_ibss_add_peer_num_of_vdev(vdev,
1632 peer_num_delta);
1633 if (OL_TXRX_INVALID_NUM_PEERS == new_peer_num) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001634 WMA_LOGE("new peer num %d out of valid boundary", new_peer_num);
1635 return;
1636 }
1637
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001638 /* reset timer value if all peers departed */
1639 if (new_peer_num == 0) {
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001640 ol_txrx_set_ibss_vdev_heart_beat_timer(vdev, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001641 return;
1642 }
1643
1644 /* calculate new timer value */
1645 new_timer_value_sec = wma_calc_ibss_heart_beat_timer(new_peer_num);
1646 if (new_timer_value_sec == 0) {
1647 WMA_LOGE("timer value %d is invalid for peer number %d",
1648 new_timer_value_sec, new_peer_num);
1649 return;
1650 }
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001651 if (new_timer_value_sec ==
1652 ol_txrx_set_ibss_vdev_heart_beat_timer(vdev, new_timer_value_sec)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001653 WMA_LOGD("timer value %d stays same, no need to notify target",
1654 new_timer_value_sec);
1655 return;
1656 }
1657
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001658 new_timer_value_ms = ((uint32_t) new_timer_value_sec) * 1000;
1659
Govind Singhd76a5b02016-03-08 15:12:14 +05301660 status = wma_vdev_set_param(wma->wmi_handle, vdev_id,
1661 WMI_VDEV_PARAM_IBSS_MAX_BCN_LOST_MS,
1662 new_timer_value_ms);
1663 if (QDF_IS_STATUS_ERROR(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001664 WMA_LOGE("Failed to set IBSS link monitoring timer value");
1665 return;
1666 }
1667
1668 WMA_LOGD("Set IBSS link monitor timer: peer_num = %d timer_value = %d",
1669 new_peer_num, new_timer_value_ms);
1670}
1671
1672#endif /* QCA_IBSS_SUPPORT */
1673/**
1674 * wma_set_ibsskey_helper() - cached IBSS key in wma handle
1675 * @wma_handle: wma handle
1676 * @key_info: set bss key info
1677 * @peerMacAddr: peer mac address
1678 *
1679 * Return: none
1680 */
1681static void wma_set_ibsskey_helper(tp_wma_handle wma_handle,
1682 tpSetBssKeyParams key_info,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301683 struct qdf_mac_addr peer_macaddr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001684{
1685 struct wma_set_key_params key_params;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301686 QDF_STATUS status = QDF_STATUS_SUCCESS;
1687 uint32_t i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001688 uint32_t def_key_idx = 0;
1689 ol_txrx_vdev_handle txrx_vdev;
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001690 int opmode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001691
1692 WMA_LOGD("BSS key setup for peer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001693 txrx_vdev = wma_find_vdev_by_id(wma_handle, key_info->smesessionId);
1694 if (!txrx_vdev) {
1695 WMA_LOGE("%s:Invalid vdev handle", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301696 key_info->status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001697 return;
1698 }
1699
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301700 qdf_mem_set(&key_params, sizeof(key_params), 0);
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001701 opmode = ol_txrx_get_opmode(txrx_vdev);
1702 qdf_mem_set(&key_params, sizeof(key_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001703 key_params.vdev_id = key_info->smesessionId;
1704 key_params.key_type = key_info->encType;
1705 key_params.singl_tid_rc = key_info->singleTidRc;
1706 key_params.unicast = false;
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001707 ASSERT(wlan_op_mode_ibss == opmode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001708
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301709 qdf_mem_copy(key_params.peer_mac, peer_macaddr.bytes,
Srinivas Girigowdad5965c42015-12-04 13:43:16 -08001710 IEEE80211_ADDR_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001711
1712 if (key_info->numKeys == 0 &&
1713 (key_info->encType == eSIR_ED_WEP40 ||
1714 key_info->encType == eSIR_ED_WEP104)) {
1715 wma_read_cfg_wepkey(wma_handle, key_info->key,
1716 &def_key_idx, &key_info->numKeys);
1717 }
1718
1719 for (i = 0; i < key_info->numKeys; i++) {
1720 if (key_params.key_type != eSIR_ED_NONE &&
1721 !key_info->key[i].keyLength)
1722 continue;
1723 key_params.key_idx = key_info->key[i].keyId;
1724 key_params.key_len = key_info->key[i].keyLength;
1725 if (key_info->encType == eSIR_ED_TKIP) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301726 qdf_mem_copy(key_params.key_data,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001727 key_info->key[i].key, 16);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301728 qdf_mem_copy(&key_params.key_data[16],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001729 &key_info->key[i].key[24], 8);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301730 qdf_mem_copy(&key_params.key_data[24],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001731 &key_info->key[i].key[16], 8);
1732 } else
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301733 qdf_mem_copy((void *)key_params.key_data,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001734 (const void *)key_info->key[i].key,
1735 key_info->key[i].keyLength);
1736
1737 WMA_LOGD("%s: peer bcast key[%d] length %d", __func__, i,
1738 key_info->key[i].keyLength);
1739
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301740 status = wma_setup_install_key_cmd(wma_handle, &key_params,
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001741 opmode);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301742 if (status == QDF_STATUS_E_NOMEM) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001743 WMA_LOGE("%s:Failed to setup install key buf",
1744 __func__);
1745 return;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301746 } else if (status == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001747 WMA_LOGE("%s:Failed to send install key command",
1748 __func__);
1749 }
1750 }
1751}
1752
1753/**
1754 * wma_set_stakey() - set encryption key
1755 * @wma_handle: wma handle
1756 * @key_info: station key info
1757 *
1758 * This function sets encryption key for WEP/WPA/WPA2
1759 * encryption mode in firmware and send response to upper layer.
1760 *
1761 * Return: none
1762 */
1763void wma_set_stakey(tp_wma_handle wma_handle, tpSetStaKeyParams key_info)
1764{
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301765 int32_t i;
1766 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001767 ol_txrx_pdev_handle txrx_pdev;
1768 ol_txrx_vdev_handle txrx_vdev;
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001769 ol_txrx_peer_handle peer;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001770 uint8_t num_keys = 0, peer_id;
1771 struct wma_set_key_params key_params;
1772 uint32_t def_key_idx = 0;
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001773 int opmode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001774
1775 WMA_LOGD("STA key setup");
1776
1777 /* Get the txRx Pdev handle */
Anurag Chouhan6d760662016-02-20 16:05:43 +05301778 txrx_pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001779 if (!txrx_pdev) {
1780 WMA_LOGE("%s:Invalid txrx pdev handle", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301781 key_info->status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001782 goto out;
1783 }
1784
Srinivas Girigowdad5965c42015-12-04 13:43:16 -08001785 peer = ol_txrx_find_peer_by_addr(txrx_pdev,
1786 key_info->peer_macaddr.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001787 &peer_id);
1788 if (!peer) {
1789 WMA_LOGE("%s:Invalid peer for key setting", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301790 key_info->status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001791 goto out;
1792 }
1793
1794 txrx_vdev = wma_find_vdev_by_id(wma_handle, key_info->smesessionId);
1795 if (!txrx_vdev) {
1796 WMA_LOGE("%s:TxRx Vdev Handle is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301797 key_info->status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001798 goto out;
1799 }
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001800 opmode = ol_txrx_get_opmode(txrx_vdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001801
1802 if (key_info->defWEPIdx == WMA_INVALID_KEY_IDX &&
1803 (key_info->encType == eSIR_ED_WEP40 ||
1804 key_info->encType == eSIR_ED_WEP104) &&
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001805 opmode != wlan_op_mode_ap) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001806 wma_read_cfg_wepkey(wma_handle, key_info->key,
1807 &def_key_idx, &num_keys);
1808 key_info->defWEPIdx = def_key_idx;
1809 } else {
1810 num_keys = SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS;
1811 if (key_info->encType != eSIR_ED_NONE) {
1812 for (i = 0; i < num_keys; i++) {
1813 if (key_info->key[i].keyDirection ==
1814 eSIR_TX_DEFAULT) {
1815 key_info->defWEPIdx = i;
1816 break;
1817 }
1818 }
1819 }
1820 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301821 qdf_mem_set(&key_params, sizeof(key_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001822 key_params.vdev_id = key_info->smesessionId;
1823 key_params.key_type = key_info->encType;
1824 key_params.singl_tid_rc = key_info->singleTidRc;
1825 key_params.unicast = true;
1826 key_params.def_key_idx = key_info->defWEPIdx;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301827 qdf_mem_copy((void *)key_params.peer_mac,
Srinivas Girigowdad5965c42015-12-04 13:43:16 -08001828 (const void *)key_info->peer_macaddr.bytes,
1829 IEEE80211_ADDR_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001830 for (i = 0; i < num_keys; i++) {
1831 if (key_params.key_type != eSIR_ED_NONE &&
1832 !key_info->key[i].keyLength)
1833 continue;
1834 if (key_info->encType == eSIR_ED_TKIP) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301835 qdf_mem_copy(key_params.key_data,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001836 key_info->key[i].key, 16);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301837 qdf_mem_copy(&key_params.key_data[16],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001838 &key_info->key[i].key[24], 8);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301839 qdf_mem_copy(&key_params.key_data[24],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001840 &key_info->key[i].key[16], 8);
1841 } else
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301842 qdf_mem_copy(key_params.key_data, key_info->key[i].key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001843 key_info->key[i].keyLength);
1844 if (key_info->encType == eSIR_ED_WPI) {
1845 key_params.key_idx = key_info->key[i].keyId;
1846 key_params.def_key_idx = key_info->key[i].keyId;
1847 } else
1848 key_params.key_idx = i;
1849
1850 key_params.key_len = key_info->key[i].keyLength;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301851 status = wma_setup_install_key_cmd(wma_handle, &key_params,
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001852 opmode);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301853 if (status == QDF_STATUS_E_NOMEM) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001854 WMA_LOGE("%s:Failed to setup install key buf",
1855 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301856 key_info->status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001857 goto out;
1858 }
1859
1860 WMA_LOGD("%s: peer unicast key[%d] %d ", __func__, i,
1861 key_info->key[i].keyLength);
1862
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301863 if (status == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001864 WMA_LOGE("%s:Failed to send install key command",
1865 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301866 key_info->status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001867 goto out;
1868 }
1869 }
1870
1871 /* In IBSS mode, set the BSS KEY for this peer
1872 * BSS key is supposed to be cache into wma_handle
1873 */
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001874 if (wlan_op_mode_ibss == opmode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001875 wma_set_ibsskey_helper(wma_handle, &wma_handle->ibsskey_info,
Srinivas Girigowdad5965c42015-12-04 13:43:16 -08001876 key_info->peer_macaddr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001877 }
1878
1879 /* TODO: Should we wait till we get HTT_T2H_MSG_TYPE_SEC_IND? */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301880 key_info->status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001881out:
1882 if (key_info->sendRsp)
1883 wma_send_msg(wma_handle, WMA_SET_STAKEY_RSP, (void *)key_info,
1884 0);
1885}
1886
1887/**
1888 * wma_process_update_edca_param_req() - update EDCA params
1889 * @handle: wma handle
1890 * @edca_params: edca parameters
1891 *
1892 * This function updates EDCA parameters to the target
1893 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05301894 * Return: QDF Status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001895 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301896QDF_STATUS wma_process_update_edca_param_req(WMA_HANDLE handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001897 tEdcaParams *edca_params)
1898{
1899 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301900 wmi_wmm_vparams wmm_param[WME_NUM_AC];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001901 tSirMacEdcaParamRecord *edca_record;
1902 int ac;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001903 ol_txrx_pdev_handle pdev;
1904 struct ol_tx_wmm_param_t ol_tx_wmm_param;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301905 uint8_t vdev_id;
1906 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001907
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301908 vdev_id = edca_params->bssIdx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001909
1910 for (ac = 0; ac < WME_NUM_AC; ac++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001911 switch (ac) {
1912 case WME_AC_BE:
1913 edca_record = &edca_params->acbe;
1914 break;
1915 case WME_AC_BK:
1916 edca_record = &edca_params->acbk;
1917 break;
1918 case WME_AC_VI:
1919 edca_record = &edca_params->acvi;
1920 break;
1921 case WME_AC_VO:
1922 edca_record = &edca_params->acvo;
1923 break;
1924 default:
1925 goto fail;
1926 }
1927
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301928 wma_update_edca_params_for_ac(edca_record, &wmm_param[ac], ac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001929
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301930 ol_tx_wmm_param.ac[ac].aifs = wmm_param[ac].aifs;
1931 ol_tx_wmm_param.ac[ac].cwmin = wmm_param[ac].cwmin;
1932 ol_tx_wmm_param.ac[ac].cwmax = wmm_param[ac].cwmax;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001933 }
1934
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301935 status = wmi_unified_process_update_edca_param(wma_handle->wmi_handle,
1936 vdev_id, wmm_param);
1937 if (status == QDF_STATUS_E_NOMEM)
1938 return status;
1939 else if (status == QDF_STATUS_E_FAILURE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001940 goto fail;
1941
Anurag Chouhan6d760662016-02-20 16:05:43 +05301942 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Himanshu Agarwal94045e42015-10-19 19:16:19 +05301943 if (pdev)
1944 ol_txrx_set_wmm_param(pdev, ol_tx_wmm_param);
1945 else
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301946 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001947
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301948 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001949
1950fail:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001951 WMA_LOGE("%s: Failed to set WMM Paremeters", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301952 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001953}
1954
1955/**
1956 * wmi_unified_probe_rsp_tmpl_send() - send probe response template to fw
1957 * @wma: wma handle
1958 * @vdev_id: vdev id
1959 * @probe_rsp_info: probe response info
1960 *
1961 * Return: 0 for success or error code
1962 */
1963static int wmi_unified_probe_rsp_tmpl_send(tp_wma_handle wma,
1964 uint8_t vdev_id,
1965 tpSendProbeRespParams probe_rsp_info)
1966{
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301967 uint8_t *frm;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001968 uint64_t adjusted_tsf_le;
1969 struct ieee80211_frame *wh;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301970 struct wmi_probe_resp_params params;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001971
1972 WMA_LOGD(FL("Send probe response template for vdev %d"), vdev_id);
1973
1974 frm = probe_rsp_info->pProbeRespTemplate;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301975
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001976 /*
1977 * Make the TSF offset negative so probe response in the same
1978 * staggered batch have the same TSF.
1979 */
1980 adjusted_tsf_le = cpu_to_le64(0ULL -
1981 wma->interfaces[vdev_id].tsfadjust);
1982 /* Update the timstamp in the probe response buffer with adjusted TSF */
1983 wh = (struct ieee80211_frame *)frm;
1984 A_MEMCPY(&wh[1], &adjusted_tsf_le, sizeof(adjusted_tsf_le));
1985
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301986 params.pProbeRespTemplate = probe_rsp_info->pProbeRespTemplate;
1987 params.probeRespTemplateLen = probe_rsp_info->probeRespTemplateLen;
1988 qdf_mem_copy(params.bssId, probe_rsp_info->bssId,
1989 WMI_ETH_LEN);
1990 qdf_mem_copy(params.ucProxyProbeReqValidIEBmap,
1991 probe_rsp_info->ucProxyProbeReqValidIEBmap,
1992 8 * sizeof(uint32_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001993
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301994 return wmi_unified_probe_rsp_tmpl_send_cmd(wma->wmi_handle, vdev_id,
1995 &params, frm);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001996}
1997
1998/**
Govind Singh61ad2622016-02-22 17:25:02 +05301999 * wma_unified_bcn_tmpl_send() - send beacon template to fw
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002000 * @wma:wma handle
2001 * @vdev_id: vdev id
2002 * @bcn_info: beacon info
2003 * @bytes_to_strip: bytes to strip
2004 *
Govind Singh61ad2622016-02-22 17:25:02 +05302005 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002006 */
Govind Singh61ad2622016-02-22 17:25:02 +05302007static QDF_STATUS wma_unified_bcn_tmpl_send(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002008 uint8_t vdev_id,
Govind Singh61ad2622016-02-22 17:25:02 +05302009 const tpSendbeaconParams bcn_info,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002010 uint8_t bytes_to_strip)
2011{
Govind Singh61ad2622016-02-22 17:25:02 +05302012 struct beacon_params params = {0};
2013 uint32_t tmpl_len, tmpl_len_aligned;
2014 uint8_t *frm;
2015 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002016 uint8_t *p2p_ie;
2017 uint16_t p2p_ie_len = 0;
2018 uint64_t adjusted_tsf_le;
2019 struct ieee80211_frame *wh;
2020
2021 WMA_LOGD("Send beacon template for vdev %d", vdev_id);
2022
2023 if (bcn_info->p2pIeOffset) {
2024 p2p_ie = bcn_info->beacon + bcn_info->p2pIeOffset;
2025 p2p_ie_len = (uint16_t) p2p_ie[1] + 2;
2026 }
2027
2028 /*
2029 * XXX: The first byte of beacon buffer contains beacon length
2030 * only when UMAC in sending the beacon template. In othercases
2031 * (ex: from tbtt update) beacon length is read from beacon
2032 * information.
2033 */
2034 if (bytes_to_strip)
2035 tmpl_len = *(uint32_t *) &bcn_info->beacon[0];
2036 else
2037 tmpl_len = bcn_info->beaconLength;
2038 if (p2p_ie_len) {
2039 tmpl_len -= (uint32_t) p2p_ie_len;
2040 }
2041
2042 frm = bcn_info->beacon + bytes_to_strip;
2043 tmpl_len_aligned = roundup(tmpl_len, sizeof(A_UINT32));
2044 /*
2045 * Make the TSF offset negative so beacons in the same
2046 * staggered batch have the same TSF.
2047 */
2048 adjusted_tsf_le = cpu_to_le64(0ULL -
2049 wma->interfaces[vdev_id].tsfadjust);
2050 /* Update the timstamp in the beacon buffer with adjusted TSF */
2051 wh = (struct ieee80211_frame *)frm;
2052 A_MEMCPY(&wh[1], &adjusted_tsf_le, sizeof(adjusted_tsf_le));
2053
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002054
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002055
Govind Singh61ad2622016-02-22 17:25:02 +05302056 params.vdev_id = vdev_id;
2057 params.tim_ie_offset = bcn_info->timIeOffset - bytes_to_strip;
2058 params.tmpl_len = tmpl_len;
2059 params.frm = frm;
2060 params.tmpl_len_aligned = tmpl_len_aligned;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002061
Govind Singh61ad2622016-02-22 17:25:02 +05302062 ret = wmi_unified_beacon_send_cmd(wma->wmi_handle,
2063 &params);
2064 if (QDF_IS_STATUS_ERROR(ret)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002065 WMA_LOGE("%s: Failed to send bcn tmpl: %d", __func__, ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002066 }
2067
2068 return ret;
2069}
2070
2071/**
2072 * wma_store_bcn_tmpl() - store beacon template
2073 * @wma: wma handle
2074 * @vdev_id: vdev id
2075 * @bcn_info: beacon params
2076 *
2077 * This function stores beacon template locally.
2078 * This will send to target on the reception of
2079 * SWBA event.
2080 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302081 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002082 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302083QDF_STATUS wma_store_bcn_tmpl(tp_wma_handle wma, uint8_t vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002084 tpSendbeaconParams bcn_info)
2085{
2086 struct beacon_info *bcn;
2087 uint32_t len;
2088 uint8_t *bcn_payload;
2089 struct beacon_tim_ie *tim_ie;
2090
2091 bcn = wma->interfaces[vdev_id].beacon;
2092 if (!bcn || !bcn->buf) {
2093 WMA_LOGE("%s: Memory is not allocated to hold bcn template",
2094 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302095 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002096 }
2097
2098 len = *(u32 *) &bcn_info->beacon[0];
2099 if (len > WMA_BCN_BUF_MAX_SIZE) {
2100 WMA_LOGE("%s: Received beacon len %d exceeding max limit %d",
2101 __func__, len, WMA_BCN_BUF_MAX_SIZE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302102 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002103 }
2104 WMA_LOGD("%s: Storing received beacon template buf to local buffer",
2105 __func__);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302106 qdf_spin_lock_bh(&bcn->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002107
2108 /*
2109 * Copy received beacon template content in local buffer.
2110 * this will be send to target on the reception of SWBA
2111 * event from target.
2112 */
Nirav Shahcbc6d722016-03-01 16:24:53 +05302113 qdf_nbuf_trim_tail(bcn->buf, qdf_nbuf_len(bcn->buf));
2114 memcpy(qdf_nbuf_data(bcn->buf),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002115 bcn_info->beacon + 4 /* Exclude beacon length field */,
2116 len);
2117 if (bcn_info->timIeOffset > 3) {
2118 bcn->tim_ie_offset = bcn_info->timIeOffset - 4;
2119 } else {
2120 bcn->tim_ie_offset = bcn_info->timIeOffset;
2121 }
2122
2123 if (bcn_info->p2pIeOffset > 3) {
2124 bcn->p2p_ie_offset = bcn_info->p2pIeOffset - 4;
2125 } else {
2126 bcn->p2p_ie_offset = bcn_info->p2pIeOffset;
2127 }
Nirav Shahcbc6d722016-03-01 16:24:53 +05302128 bcn_payload = qdf_nbuf_data(bcn->buf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002129 if (bcn->tim_ie_offset) {
2130 tim_ie =
2131 (struct beacon_tim_ie *)(&bcn_payload[bcn->tim_ie_offset]);
2132 /*
2133 * Intial Value of bcn->dtim_count will be 0.
2134 * But if the beacon gets updated then current dtim
2135 * count will be restored
2136 */
2137 tim_ie->dtim_count = bcn->dtim_count;
2138 tim_ie->tim_bitctl = 0;
2139 }
2140
Nirav Shahcbc6d722016-03-01 16:24:53 +05302141 qdf_nbuf_put_tail(bcn->buf, len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002142 bcn->len = len;
2143
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302144 qdf_spin_unlock_bh(&bcn->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002145
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302146 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002147}
2148
2149/**
2150 * wma_tbttoffset_update_event_handler() - tbtt offset update handler
2151 * @handle: wma handle
2152 * @event: event buffer
2153 * @len: data length
2154 *
2155 * Return: 0 for success or error code
2156 */
2157int wma_tbttoffset_update_event_handler(void *handle, uint8_t *event,
2158 uint32_t len)
2159{
2160 tp_wma_handle wma = (tp_wma_handle) handle;
2161 WMI_TBTTOFFSET_UPDATE_EVENTID_param_tlvs *param_buf;
2162 wmi_tbtt_offset_event_fixed_param *tbtt_offset_event;
2163 struct wma_txrx_node *intf;
2164 struct beacon_info *bcn;
2165 tSendbeaconParams bcn_info;
2166 uint32_t *adjusted_tsf = NULL;
2167 uint32_t if_id = 0, vdev_map;
2168
2169 if (!wma) {
2170 WMA_LOGE("Invalid wma handle");
2171 return -EINVAL;
2172 }
2173
2174 param_buf = (WMI_TBTTOFFSET_UPDATE_EVENTID_param_tlvs *) event;
2175 if (!param_buf) {
2176 WMA_LOGE("Invalid tbtt update event buffer");
2177 return -EINVAL;
2178 }
2179
2180 tbtt_offset_event = param_buf->fixed_param;
2181 intf = wma->interfaces;
2182 vdev_map = tbtt_offset_event->vdev_map;
2183 adjusted_tsf = param_buf->tbttoffset_list;
2184 if (!adjusted_tsf) {
2185 WMA_LOGE("%s: Invalid adjusted_tsf", __func__);
2186 return -EINVAL;
2187 }
2188
2189 for (; (vdev_map); vdev_map >>= 1, if_id++) {
2190 if (!(vdev_map & 0x1) || (!(intf[if_id].handle)))
2191 continue;
2192
2193 bcn = intf[if_id].beacon;
2194 if (!bcn) {
2195 WMA_LOGE("%s: Invalid beacon", __func__);
2196 return -EINVAL;
2197 }
2198 if (!bcn->buf) {
2199 WMA_LOGE("%s: Invalid beacon buffer", __func__);
2200 return -EINVAL;
2201 }
2202 /* Save the adjusted TSF */
2203 intf[if_id].tsfadjust = adjusted_tsf[if_id];
2204
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302205 qdf_spin_lock_bh(&bcn->lock);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302206 qdf_mem_zero(&bcn_info, sizeof(bcn_info));
Nirav Shahcbc6d722016-03-01 16:24:53 +05302207 bcn_info.beacon = qdf_nbuf_data(bcn->buf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002208 bcn_info.p2pIeOffset = bcn->p2p_ie_offset;
2209 bcn_info.beaconLength = bcn->len;
2210 bcn_info.timIeOffset = bcn->tim_ie_offset;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302211 qdf_spin_unlock_bh(&bcn->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002212
2213 /* Update beacon template in firmware */
Govind Singh61ad2622016-02-22 17:25:02 +05302214 wma_unified_bcn_tmpl_send(wma, if_id, &bcn_info, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002215 }
2216 return 0;
2217}
2218
2219/**
2220 * wma_p2p_go_set_beacon_ie() - set beacon IE for p2p go
2221 * @wma_handle: wma handle
2222 * @vdev_id: vdev id
2223 * @p2pIe: p2p IE
2224 *
2225 * Return: 0 for success or error code
2226 */
2227static int wma_p2p_go_set_beacon_ie(t_wma_handle *wma_handle,
2228 A_UINT32 vdev_id, uint8_t *p2pIe)
2229{
Himanshu Agarwal009f1572016-03-09 17:26:02 +05302230 if (!wma_handle) {
2231 WMA_LOGE("%s: wma handle is NULL", __func__);
2232 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002233 }
2234
Himanshu Agarwal009f1572016-03-09 17:26:02 +05302235 return wmi_unified_p2p_go_set_beacon_ie_cmd(wma_handle->wmi_handle,
2236 vdev_id, p2pIe);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002237}
2238
2239/**
2240 * wma_send_probe_rsp_tmpl() - send probe resp template
2241 * @wma: wma handle
2242 * @probe_rsp_info: probe response info
2243 *
2244 * This funciton sends probe response template to fw which
2245 * firmware will use in case of probe response offload.
2246 *
2247 * Return: none
2248 */
2249void wma_send_probe_rsp_tmpl(tp_wma_handle wma,
2250 tpSendProbeRespParams probe_rsp_info)
2251{
2252 ol_txrx_vdev_handle vdev;
2253 uint8_t vdev_id;
2254 tpAniProbeRspStruct probe_rsp;
2255
2256 if (!probe_rsp_info) {
2257 WMA_LOGE(FL("probe_rsp_info is NULL"));
2258 return;
2259 }
2260
2261 probe_rsp = (tpAniProbeRspStruct) (probe_rsp_info->pProbeRespTemplate);
2262 if (!probe_rsp) {
2263 WMA_LOGE(FL("probe_rsp is NULL"));
2264 return;
2265 }
2266
2267 vdev = wma_find_vdev_by_addr(wma, probe_rsp->macHdr.sa, &vdev_id);
2268 if (!vdev) {
2269 WMA_LOGE(FL("failed to get vdev handle"));
2270 return;
2271 }
2272
2273 if (WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
2274 WMI_SERVICE_BEACON_OFFLOAD)) {
2275 WMA_LOGI("Beacon Offload Enabled Sending Unified command");
2276 if (wmi_unified_probe_rsp_tmpl_send(wma, vdev_id,
2277 probe_rsp_info) < 0) {
2278 WMA_LOGE(FL("wmi_unified_probe_rsp_tmpl_send Failed "));
2279 return;
2280 }
2281 }
2282}
2283
2284/**
2285 * wma_send_beacon() - send beacon template
2286 * @wma: wma handle
2287 * @bcn_info: beacon info
2288 *
2289 * This funciton store beacon template locally and
2290 * update keep alive parameters
2291 *
2292 * Return: none
2293 */
2294void wma_send_beacon(tp_wma_handle wma, tpSendbeaconParams bcn_info)
2295{
2296 ol_txrx_vdev_handle vdev;
2297 uint8_t vdev_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302298 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002299 uint8_t *p2p_ie;
2300 tpAniBeaconStruct beacon;
Govind Singhd76a5b02016-03-08 15:12:14 +05302301 struct vdev_up_params param = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002302
2303 beacon = (tpAniBeaconStruct) (bcn_info->beacon);
2304 vdev = wma_find_vdev_by_addr(wma, beacon->macHdr.sa, &vdev_id);
2305 if (!vdev) {
2306 WMA_LOGE("%s : failed to get vdev handle", __func__);
2307 return;
2308 }
2309
2310 if (WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
2311 WMI_SERVICE_BEACON_OFFLOAD)) {
2312 WMA_LOGI("Beacon Offload Enabled Sending Unified command");
Govind Singh61ad2622016-02-22 17:25:02 +05302313 status = wma_unified_bcn_tmpl_send(wma, vdev_id, bcn_info, 4);
2314 if (QDF_IS_STATUS_ERROR(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002315 WMA_LOGE("%s : wmi_unified_bcn_tmpl_send Failed ",
2316 __func__);
2317 return;
2318 }
2319
2320 if (bcn_info->p2pIeOffset) {
2321 p2p_ie = bcn_info->beacon + bcn_info->p2pIeOffset;
2322 WMA_LOGI
2323 (" %s: p2pIe is present - vdev_id %hu, p2p_ie = %p, p2p ie len = %hu",
2324 __func__, vdev_id, p2p_ie, p2p_ie[1]);
2325 if (wma_p2p_go_set_beacon_ie(wma, vdev_id, p2p_ie) < 0) {
2326 WMA_LOGE
2327 ("%s : wmi_unified_bcn_tmpl_send Failed ",
2328 __func__);
2329 return;
2330 }
2331 }
2332 }
2333 status = wma_store_bcn_tmpl(wma, vdev_id, bcn_info);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302334 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002335 WMA_LOGE("%s : wma_store_bcn_tmpl Failed", __func__);
2336 return;
2337 }
2338 if (!wma->interfaces[vdev_id].vdev_up) {
Govind Singhd76a5b02016-03-08 15:12:14 +05302339 param.vdev_id = vdev_id;
2340 param.assoc_id = 0;
2341 status = wmi_unified_vdev_up_send(wma->wmi_handle,
2342 bcn_info->bssId,
2343 &param);
2344 if (QDF_IS_STATUS_ERROR(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002345 WMA_LOGE("%s : failed to send vdev up", __func__);
2346 return;
2347 }
2348 wma->interfaces[vdev_id].vdev_up = true;
2349 wma_set_sap_keepalive(wma, vdev_id);
2350 }
2351}
2352
2353/**
2354 * wma_set_keepalive_req() - send keep alive request to fw
2355 * @wma: wma handle
2356 * @keepalive: keep alive parameters
2357 *
2358 * Return: none
2359 */
2360void wma_set_keepalive_req(tp_wma_handle wma,
2361 tSirKeepAliveReq *keepalive)
2362{
2363 WMA_LOGD("KEEPALIVE:PacketType:%d", keepalive->packetType);
2364 wma_set_sta_keep_alive(wma, keepalive->sessionId,
2365 keepalive->packetType,
2366 keepalive->timePeriod,
2367 keepalive->hostIpv4Addr,
Srinivas Girigowda9c330a92015-11-24 12:28:25 -08002368 keepalive->destIpv4Addr,
2369 keepalive->dest_macaddr.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002370
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302371 qdf_mem_free(keepalive);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002372}
2373
2374/**
2375 * wma_beacon_miss_handler() - beacon miss event handler
2376 * @wma: wma handle
2377 * @vdev_id: vdev id
2378 *
2379 * This function send beacon miss indication to upper layers.
2380 *
2381 * Return: none
2382 */
2383void wma_beacon_miss_handler(tp_wma_handle wma, uint32_t vdev_id)
2384{
2385 tSirSmeMissedBeaconInd *beacon_miss_ind;
2386
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302387 beacon_miss_ind = (tSirSmeMissedBeaconInd *) qdf_mem_malloc
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002388 (sizeof(tSirSmeMissedBeaconInd));
2389
2390 if (NULL == beacon_miss_ind) {
2391 WMA_LOGE("%s: Memory allocation failure", __func__);
2392 return;
2393 }
2394 beacon_miss_ind->messageType = WMA_MISSED_BEACON_IND;
2395 beacon_miss_ind->length = sizeof(tSirSmeMissedBeaconInd);
2396 beacon_miss_ind->bssIdx = vdev_id;
2397
2398 wma_send_msg(wma, WMA_MISSED_BEACON_IND, (void *)beacon_miss_ind, 0);
2399}
2400
2401/**
2402 * wma_mgmt_tx_completion_handler() - wma mgmt Tx completion event handler
2403 * @handle: wma handle
2404 * @cmpl_event_params: completion event handler data
2405 * @len: length of @cmpl_event_params
2406 *
2407 * Return: 0 on success; error number otherwise
2408 */
2409
2410int wma_mgmt_tx_completion_handler(void *handle, uint8_t *cmpl_event_params,
2411 uint32_t len)
2412{
2413 tp_wma_handle wma_handle = (tp_wma_handle)handle;
2414 WMI_MGMT_TX_COMPLETION_EVENTID_param_tlvs *param_buf;
2415 wmi_mgmt_tx_compl_event_fixed_param *cmpl_params;
2416 struct wmi_desc_t *wmi_desc;
2417
Anurag Chouhan6d760662016-02-20 16:05:43 +05302418 ol_txrx_pdev_handle pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002419
2420 param_buf = (WMI_MGMT_TX_COMPLETION_EVENTID_param_tlvs *)
2421 cmpl_event_params;
2422 if (!param_buf && !wma_handle) {
2423 WMA_LOGE("%s: Invalid mgmt Tx completion event", __func__);
2424 return -EINVAL;
2425 }
2426 cmpl_params = param_buf->fixed_param;
2427
2428 WMA_LOGI("%s: status:%d wmi_desc_id:%d", __func__, cmpl_params->status,
2429 cmpl_params->desc_id);
2430
2431 wmi_desc = (struct wmi_desc_t *)
2432 (&wma_handle->wmi_desc_pool.array[cmpl_params->desc_id]);
2433
2434 if (!wmi_desc) {
2435 WMA_LOGE("%s: Invalid wmi desc", __func__);
2436 return -EINVAL;
2437 }
2438
2439 if (wmi_desc->nbuf)
Nirav Shahcbc6d722016-03-01 16:24:53 +05302440 qdf_nbuf_unmap_single(pdev->osdev, wmi_desc->nbuf,
Anurag Chouhan6d760662016-02-20 16:05:43 +05302441 QDF_DMA_TO_DEVICE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002442 if (wmi_desc->tx_cmpl_cb)
2443 wmi_desc->tx_cmpl_cb(wma_handle->mac_context,
2444 wmi_desc->nbuf, 1);
2445
2446 if (wmi_desc->ota_post_proc_cb)
2447 wmi_desc->ota_post_proc_cb((tpAniSirGlobal)
2448 wma_handle->mac_context,
2449 cmpl_params->status);
2450
2451 wmi_desc_put(wma_handle, wmi_desc);
2452
2453 return 0;
2454}
2455
2456/**
2457 * wma_process_update_opmode() - process update VHT opmode cmd from UMAC
2458 * @wma_handle: wma handle
2459 * @update_vht_opmode: vht opmode
2460 *
2461 * Return: none
2462 */
2463void wma_process_update_opmode(tp_wma_handle wma_handle,
2464 tUpdateVHTOpMode *update_vht_opmode)
2465{
2466 WMA_LOGD("%s: opMode = %d", __func__, update_vht_opmode->opMode);
2467
2468 wma_set_peer_param(wma_handle, update_vht_opmode->peer_mac,
2469 WMI_PEER_CHWIDTH, update_vht_opmode->opMode,
2470 update_vht_opmode->smesessionId);
2471}
2472
2473/**
2474 * wma_process_update_rx_nss() - process update RX NSS cmd from UMAC
2475 * @wma_handle: wma handle
2476 * @update_rx_nss: rx nss value
2477 *
2478 * Return: none
2479 */
2480void wma_process_update_rx_nss(tp_wma_handle wma_handle,
2481 tUpdateRxNss *update_rx_nss)
2482{
2483 struct wma_txrx_node *intr =
2484 &wma_handle->interfaces[update_rx_nss->smesessionId];
2485 int rx_nss = update_rx_nss->rxNss;
2486
2487 wma_update_txrx_chainmask(wma_handle->num_rf_chains, &rx_nss);
2488
2489 intr->nss = (uint8_t)rx_nss;
2490 update_rx_nss->rxNss = (uint32_t)rx_nss;
2491
2492 WMA_LOGD("%s: Rx Nss = %d", __func__, update_rx_nss->rxNss);
2493
2494 wma_set_peer_param(wma_handle, update_rx_nss->peer_mac,
2495 WMI_PEER_NSS, update_rx_nss->rxNss,
2496 update_rx_nss->smesessionId);
2497}
2498
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002499/**
2500 * wma_process_update_membership() - process update group membership cmd
2501 * @wma_handle: wma handle
2502 * @membership: group membership info
2503 *
2504 * Return: none
2505 */
2506void wma_process_update_membership(tp_wma_handle wma_handle,
2507 tUpdateMembership *membership)
2508{
2509 WMA_LOGD("%s: membership = %x ", __func__, membership->membership);
2510
2511 wma_set_peer_param(wma_handle, membership->peer_mac,
2512 WMI_PEER_MEMBERSHIP, membership->membership,
2513 membership->smesessionId);
2514}
2515
2516/**
2517 * wma_process_update_userpos() - process update user pos cmd from UMAC
2518 * @wma_handle: wma handle
2519 * @userpos: user pos value
2520 *
2521 * Return: none
2522 */
2523void wma_process_update_userpos(tp_wma_handle wma_handle,
2524 tUpdateUserPos *userpos)
2525{
2526 WMA_LOGD("%s: userPos = %x ", __func__, userpos->userPos);
2527
2528 wma_set_peer_param(wma_handle, userpos->peer_mac,
2529 WMI_PEER_USERPOS, userpos->userPos,
2530 userpos->smesessionId);
2531
2532 /* Now that membership/userpos is updated in fw,
2533 * enable GID PPS.
2534 */
2535 wma_set_ppsconfig(userpos->smesessionId, WMA_VHT_PPS_GID_MATCH, 1);
2536
2537}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002538
2539/**
2540 * wma_set_htconfig() - set ht config parameters to target
2541 * @vdev_id: vdev id
2542 * @ht_capab: ht capablity
2543 * @value: value of ht param
2544 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302545 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002546 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302547QDF_STATUS wma_set_htconfig(uint8_t vdev_id, uint16_t ht_capab, int value)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002548{
Anurag Chouhan6d760662016-02-20 16:05:43 +05302549 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
Govind Singhd76a5b02016-03-08 15:12:14 +05302550 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002551
2552 if (NULL == wma) {
2553 WMA_LOGE("%s: Failed to get wma", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302554 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002555 }
2556
2557 switch (ht_capab) {
2558 case WNI_CFG_HT_CAP_INFO_ADVANCE_CODING:
Govind Singhd76a5b02016-03-08 15:12:14 +05302559 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002560 WMI_VDEV_PARAM_LDPC,
2561 value);
2562 break;
2563 case WNI_CFG_HT_CAP_INFO_TX_STBC:
Govind Singhd76a5b02016-03-08 15:12:14 +05302564 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002565 WMI_VDEV_PARAM_TX_STBC,
2566 value);
2567 break;
2568 case WNI_CFG_HT_CAP_INFO_RX_STBC:
Govind Singhd76a5b02016-03-08 15:12:14 +05302569 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002570 WMI_VDEV_PARAM_RX_STBC,
2571 value);
2572 break;
2573 case WNI_CFG_HT_CAP_INFO_SHORT_GI_20MHZ:
2574 case WNI_CFG_HT_CAP_INFO_SHORT_GI_40MHZ:
2575 WMA_LOGE("%s: ht_capab = %d, value = %d", __func__, ht_capab,
2576 value);
Govind Singhd76a5b02016-03-08 15:12:14 +05302577 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002578 WMI_VDEV_PARAM_SGI, value);
Govind Singhd76a5b02016-03-08 15:12:14 +05302579 if (ret == QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002580 wma->interfaces[vdev_id].config.shortgi = value;
2581 break;
2582 default:
2583 WMA_LOGE("%s:INVALID HT CONFIG", __func__);
2584 }
2585
Govind Singhd76a5b02016-03-08 15:12:14 +05302586 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002587}
2588
2589/**
2590 * wma_hidden_ssid_vdev_restart() - vdev restart for hidden ssid
2591 * @wma_handle: wma handle
2592 * @pReq: hidden ssid vdev restart request
2593 *
2594 * Return: none
2595 */
2596void wma_hidden_ssid_vdev_restart(tp_wma_handle wma_handle,
2597 tHalHiddenSsidVdevRestart *pReq)
2598{
2599 struct wma_txrx_node *intr = wma_handle->interfaces;
2600
2601 if ((pReq->sessionId !=
2602 intr[pReq->sessionId].vdev_restart_params.vdev_id)
2603 || !((intr[pReq->sessionId].type == WMI_VDEV_TYPE_AP)
2604 && (intr[pReq->sessionId].sub_type == 0))) {
2605 WMA_LOGE("%s : invalid session id", __func__);
2606 return;
2607 }
2608
2609 intr[pReq->sessionId].vdev_restart_params.ssidHidden = pReq->ssidHidden;
Anurag Chouhan8e0ccd32016-02-19 15:30:20 +05302610 qdf_atomic_set(&intr[pReq->sessionId].vdev_restart_params.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002611 hidden_ssid_restart_in_progress, 1);
2612
2613 /* vdev stop -> vdev restart -> vdev up */
2614 WMA_LOGD("%s, vdev_id: %d, pausing tx_ll_queue for VDEV_STOP",
2615 __func__, pReq->sessionId);
2616 ol_txrx_vdev_pause(wma_handle->interfaces[pReq->sessionId].handle,
2617 OL_TXQ_PAUSE_REASON_VDEV_STOP);
2618 wma_handle->interfaces[pReq->sessionId].pause_bitmap |=
2619 (1 << PAUSE_TYPE_HOST);
2620 if (wmi_unified_vdev_stop_send(wma_handle->wmi_handle, pReq->sessionId)) {
2621 WMA_LOGE("%s: %d Failed to send vdev stop", __func__, __LINE__);
Anurag Chouhan8e0ccd32016-02-19 15:30:20 +05302622 qdf_atomic_set(&intr[pReq->sessionId].vdev_restart_params.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002623 hidden_ssid_restart_in_progress, 0);
2624 return;
2625 }
2626}
2627
2628
2629#ifdef WLAN_FEATURE_11W
2630
2631/**
2632 * wma_extract_ccmp_pn() - extract 6 byte PN from the CCMP header
2633 * @ccmp_ptr: CCMP header
2634 *
2635 * Return: PN extracted from header.
2636 */
2637static uint64_t wma_extract_ccmp_pn(uint8_t *ccmp_ptr)
2638{
2639 uint8_t rsvd, key, pn[6];
2640 uint64_t new_pn;
2641
2642 /*
2643 * +-----+-----+------+----------+-----+-----+-----+-----+
2644 * | PN0 | PN1 | rsvd | rsvd/key | PN2 | PN3 | PN4 | PN5 |
2645 * +-----+-----+------+----------+-----+-----+-----+-----+
2646 * CCMP Header Format
2647 */
2648
2649 /* Extract individual bytes */
2650 pn[0] = (uint8_t) *ccmp_ptr;
2651 pn[1] = (uint8_t) *(ccmp_ptr + 1);
2652 rsvd = (uint8_t) *(ccmp_ptr + 2);
2653 key = (uint8_t) *(ccmp_ptr + 3);
2654 pn[2] = (uint8_t) *(ccmp_ptr + 4);
2655 pn[3] = (uint8_t) *(ccmp_ptr + 5);
2656 pn[4] = (uint8_t) *(ccmp_ptr + 6);
2657 pn[5] = (uint8_t) *(ccmp_ptr + 7);
2658
2659 /* Form 6 byte PN with 6 individual bytes of PN */
2660 new_pn = ((uint64_t) pn[5] << 40) |
2661 ((uint64_t) pn[4] << 32) |
2662 ((uint64_t) pn[3] << 24) |
2663 ((uint64_t) pn[2] << 16) |
2664 ((uint64_t) pn[1] << 8) | ((uint64_t) pn[0] << 0);
2665
2666 WMA_LOGE("PN of received packet is %llu", new_pn);
2667 return new_pn;
2668}
2669
2670/**
2671 * wma_is_ccmp_pn_replay_attack() - detect replay attacking using PN in CCMP
2672 * @cds_ctx: cds context
2673 * @wh: 802.11 frame header
2674 * @ccmp_ptr: CCMP frame header
2675 *
2676 * Return: true/false
2677 */
2678static bool
2679wma_is_ccmp_pn_replay_attack(void *cds_ctx, struct ieee80211_frame *wh,
2680 uint8_t *ccmp_ptr)
2681{
2682 ol_txrx_pdev_handle pdev;
2683 ol_txrx_vdev_handle vdev;
2684 ol_txrx_peer_handle peer;
2685 uint8_t vdev_id, peer_id;
2686 uint8_t *last_pn_valid;
2687 uint64_t *last_pn, new_pn;
2688 uint32_t *rmf_pn_replays;
2689
Anurag Chouhan6d760662016-02-20 16:05:43 +05302690 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002691 if (!pdev) {
2692 WMA_LOGE("%s: Failed to find pdev", __func__);
2693 return true;
2694 }
2695
Mukul Sharmaa748fbb2015-12-01 19:51:36 +05302696 vdev = wma_find_vdev_by_bssid(cds_ctx, wh->i_addr3, &vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002697 if (!vdev) {
2698 WMA_LOGE("%s: Failed to find vdev", __func__);
2699 return true;
2700 }
2701
2702 /* Retrieve the peer based on vdev and addr */
2703 peer = ol_txrx_find_peer_by_addr_and_vdev(pdev, vdev, wh->i_addr2,
2704 &peer_id);
2705
2706 if (NULL == peer) {
2707 WMA_LOGE("%s: Failed to find peer, Not able to validate PN",
2708 __func__);
2709 return true;
2710 }
2711
2712 new_pn = wma_extract_ccmp_pn(ccmp_ptr);
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07002713 ol_txrx_get_pn_info(peer, &last_pn_valid, &last_pn, &rmf_pn_replays);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002714
2715 if (*last_pn_valid) {
2716 if (new_pn > *last_pn) {
2717 *last_pn = new_pn;
2718 WMA_LOGE("%s: PN validation successful", __func__);
2719 } else {
2720 WMA_LOGE("%s: PN Replay attack detected", __func__);
2721 /* per 11W amendment, keeping track of replay attacks */
2722 *rmf_pn_replays += 1;
2723 return true;
2724 }
2725 } else {
2726 *last_pn_valid = 1;
2727 *last_pn = new_pn;
2728 }
2729
2730 return false;
2731}
2732
2733/**
mukul sharma72c8b222015-09-04 17:02:01 +05302734 * wma_process_bip() - process mmie in rmf frame
2735 * @wma_handle: wma handle
2736 * @iface: txrx node
2737 * @wh: 80211 frame
2738 * @wbuf: Buffer
2739 *
2740 * Return: 0 for success or error code
2741 */
2742
2743static
2744int wma_process_bip(tp_wma_handle wma_handle,
2745 struct wma_txrx_node *iface,
2746 struct ieee80211_frame *wh,
Nirav Shahcbc6d722016-03-01 16:24:53 +05302747 qdf_nbuf_t wbuf
mukul sharma72c8b222015-09-04 17:02:01 +05302748)
2749{
2750 uint16_t key_id;
2751 uint8_t *efrm;
2752
Nirav Shahcbc6d722016-03-01 16:24:53 +05302753 efrm = qdf_nbuf_data(wbuf) + qdf_nbuf_len(wbuf);
mukul sharma72c8b222015-09-04 17:02:01 +05302754 key_id = (uint16_t)*(efrm - cds_get_mmie_size() + 2);
2755
2756 if (!((key_id == WMA_IGTK_KEY_INDEX_4)
2757 || (key_id == WMA_IGTK_KEY_INDEX_5))) {
2758 WMA_LOGE(FL("Invalid KeyID(%d) dropping the frame"), key_id);
2759 return -EINVAL;
2760 }
2761 if (WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap,
2762 WMI_SERVICE_STA_PMF_OFFLOAD)) {
2763 /*
2764 * if 11w offload is enabled then mmie validation is performed
2765 * in firmware, host just need to trim the mmie.
2766 */
Nirav Shahcbc6d722016-03-01 16:24:53 +05302767 qdf_nbuf_trim_tail(wbuf, cds_get_mmie_size());
mukul sharma72c8b222015-09-04 17:02:01 +05302768 } else {
2769 if (cds_is_mmie_valid(iface->key.key,
2770 iface->key.key_id[key_id - WMA_IGTK_KEY_INDEX_4].ipn,
2771 (uint8_t *) wh, efrm)) {
2772 WMA_LOGE(FL("Protected BC/MC frame MMIE validation successful"));
2773 /* Remove MMIE */
Nirav Shahcbc6d722016-03-01 16:24:53 +05302774 qdf_nbuf_trim_tail(wbuf, cds_get_mmie_size());
mukul sharma72c8b222015-09-04 17:02:01 +05302775 } else {
2776 WMA_LOGE(FL("BC/MC MIC error or MMIE not present, dropping the frame"));
2777 return -EINVAL;
2778 }
2779 }
2780 return 0;
2781}
2782
2783/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002784 * wma_process_rmf_frame() - process rmf frame
2785 * @wma_handle: wma handle
2786 * @iface: txrx node
2787 * @wh: 80211 frame
2788 * @rx_pkt: rx packet
2789 * @wbuf: Buffer
2790 *
2791 * Return: 0 for success or error code
2792 */
2793static
2794int wma_process_rmf_frame(tp_wma_handle wma_handle,
2795 struct wma_txrx_node *iface,
2796 struct ieee80211_frame *wh,
2797 cds_pkt_t *rx_pkt,
Nirav Shahcbc6d722016-03-01 16:24:53 +05302798 qdf_nbuf_t wbuf)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002799{
mukul sharma72c8b222015-09-04 17:02:01 +05302800 uint8_t *orig_hdr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002801 uint8_t *ccmp;
2802
2803 if ((wh)->i_fc[1] & IEEE80211_FC1_WEP) {
2804 if (IEEE80211_IS_BROADCAST(wh->i_addr1) ||
2805 IEEE80211_IS_MULTICAST(wh->i_addr1)) {
2806 WMA_LOGE("Encrypted BC/MC frame dropping the frame");
2807 cds_pkt_return_packet(rx_pkt);
2808 return -EINVAL;
2809 }
2810
Nirav Shahcbc6d722016-03-01 16:24:53 +05302811 orig_hdr = (uint8_t *) qdf_nbuf_data(wbuf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002812 /* Pointer to head of CCMP header */
2813 ccmp = orig_hdr + sizeof(*wh);
2814 if (wma_is_ccmp_pn_replay_attack(
2815 wma_handle, wh, ccmp)) {
2816 WMA_LOGE("Dropping the frame");
2817 cds_pkt_return_packet(rx_pkt);
2818 return -EINVAL;
2819 }
2820
2821 /* Strip privacy headers (and trailer)
2822 * for a received frame
2823 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302824 qdf_mem_move(orig_hdr +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002825 IEEE80211_CCMP_HEADERLEN, wh,
2826 sizeof(*wh));
Nirav Shahcbc6d722016-03-01 16:24:53 +05302827 qdf_nbuf_pull_head(wbuf,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002828 IEEE80211_CCMP_HEADERLEN);
Nirav Shahcbc6d722016-03-01 16:24:53 +05302829 qdf_nbuf_trim_tail(wbuf, IEEE80211_CCMP_MICLEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002830
2831 rx_pkt->pkt_meta.mpdu_hdr_ptr =
Nirav Shahcbc6d722016-03-01 16:24:53 +05302832 qdf_nbuf_data(wbuf);
2833 rx_pkt->pkt_meta.mpdu_len = qdf_nbuf_len(wbuf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002834 rx_pkt->pkt_meta.mpdu_data_len =
2835 rx_pkt->pkt_meta.mpdu_len -
2836 rx_pkt->pkt_meta.mpdu_hdr_len;
2837 rx_pkt->pkt_meta.mpdu_data_ptr =
2838 rx_pkt->pkt_meta.mpdu_hdr_ptr +
2839 rx_pkt->pkt_meta.mpdu_hdr_len;
2840 rx_pkt->pkt_meta.tsf_delta = rx_pkt->pkt_meta.tsf_delta;
2841 rx_pkt->pkt_buf = wbuf;
2842 WMA_LOGD(FL("BSSID: "MAC_ADDRESS_STR" tsf_delta: %u"),
2843 MAC_ADDR_ARRAY(wh->i_addr3), rx_pkt->pkt_meta.tsf_delta);
2844 } else {
2845 if (IEEE80211_IS_BROADCAST(wh->i_addr1) ||
2846 IEEE80211_IS_MULTICAST(wh->i_addr1)) {
mukul sharma72c8b222015-09-04 17:02:01 +05302847 if (0 != wma_process_bip(wma_handle, iface, wh, wbuf)) {
2848 cds_pkt_return_packet(rx_pkt);
2849 return -EINVAL;
Mukul Sharmaa748fbb2015-12-01 19:51:36 +05302850 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002851 } else {
2852 WMA_LOGE("Rx unprotected unicast mgmt frame");
2853 rx_pkt->pkt_meta.dpuFeedback =
2854 DPU_FEEDBACK_UNPROTECTED_ERROR;
2855 }
2856 }
2857 return 0;
2858}
2859#endif
2860
2861/**
2862 * wma_mgmt_rx_process() - process management rx frame.
2863 * @handle: wma handle
2864 * @data: rx data
2865 * @data_len: data length
2866 *
2867 * Return: 0 for success or error code
2868 */
2869static int wma_mgmt_rx_process(void *handle, uint8_t *data,
2870 uint32_t data_len)
2871{
2872 tp_wma_handle wma_handle = (tp_wma_handle) handle;
2873 WMI_MGMT_RX_EVENTID_param_tlvs *param_tlvs = NULL;
2874 wmi_mgmt_rx_hdr *hdr = NULL;
2875 struct wma_txrx_node *iface = NULL;
Mukul Sharmaa748fbb2015-12-01 19:51:36 +05302876 uint8_t vdev_id = WMA_INVALID_VDEV_ID;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002877 cds_pkt_t *rx_pkt;
Nirav Shahcbc6d722016-03-01 16:24:53 +05302878 qdf_nbuf_t wbuf;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002879 struct ieee80211_frame *wh;
2880 uint8_t mgt_type, mgt_subtype;
2881 int status;
2882
2883 if (!wma_handle) {
2884 WMA_LOGE("%s: Failed to get WMA context", __func__);
2885 return -EINVAL;
2886 }
2887
2888 param_tlvs = (WMI_MGMT_RX_EVENTID_param_tlvs *) data;
2889 if (!param_tlvs) {
2890 WMA_LOGE("Get NULL point message from FW");
2891 return -EINVAL;
2892 }
2893
2894 hdr = param_tlvs->hdr;
2895 if (!hdr) {
2896 WMA_LOGE("Rx event is NULL");
2897 return -EINVAL;
2898 }
2899
2900 if (hdr->buf_len < sizeof(struct ieee80211_frame)) {
2901 WMA_LOGE("Invalid rx mgmt packet");
2902 return -EINVAL;
2903 }
2904
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302905 rx_pkt = qdf_mem_malloc(sizeof(*rx_pkt));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002906 if (!rx_pkt) {
2907 WMA_LOGE("Failed to allocate rx packet");
2908 return -ENOMEM;
2909 }
2910
Rajeev Kumarfec3dbe2016-01-19 15:23:52 -08002911 if (cds_is_load_or_unload_in_progress()) {
Naveen Rawat10ccf872015-11-03 14:15:55 -08002912 WMA_LOGE("Load/Unload in progress");
2913 return -EINVAL;
2914 }
2915
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302916 qdf_mem_zero(rx_pkt, sizeof(*rx_pkt));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002917
2918 /*
2919 * Fill in meta information needed by pe/lim
2920 * TODO: Try to maintain rx metainfo as part of skb->data.
2921 */
2922 rx_pkt->pkt_meta.channel = hdr->channel;
2923 rx_pkt->pkt_meta.scan_src = hdr->flags;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -07002924
2925 /*
2926 * Get the rssi value from the current snr value
2927 * using standard noise floor of -96.
2928 */
2929 rx_pkt->pkt_meta.rssi = hdr->snr + WMA_NOISE_FLOOR_DBM_DEFAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002930 rx_pkt->pkt_meta.snr = hdr->snr;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -07002931
2932 /* If absolute rssi is available from firmware, use it */
2933 if (hdr->rssi != 0)
2934 rx_pkt->pkt_meta.rssi_raw = hdr->rssi;
2935 else
2936 rx_pkt->pkt_meta.rssi_raw = rx_pkt->pkt_meta.rssi;
2937
2938
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002939 /*
2940 * FIXME: Assigning the local timestamp as hw timestamp is not
2941 * available. Need to see if pe/lim really uses this data.
2942 */
2943 rx_pkt->pkt_meta.timestamp = (uint32_t) jiffies;
2944 rx_pkt->pkt_meta.mpdu_hdr_len = sizeof(struct ieee80211_frame);
2945 rx_pkt->pkt_meta.mpdu_len = hdr->buf_len;
2946 rx_pkt->pkt_meta.mpdu_data_len = hdr->buf_len -
2947 rx_pkt->pkt_meta.mpdu_hdr_len;
2948
2949 rx_pkt->pkt_meta.roamCandidateInd = 0;
2950
2951 /* Why not just use rx_event->hdr.buf_len? */
Nirav Shahcbc6d722016-03-01 16:24:53 +05302952 wbuf = qdf_nbuf_alloc(NULL, roundup(hdr->buf_len, 4), 0, 4, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002953 if (!wbuf) {
2954 WMA_LOGE("%s: Failed to allocate wbuf for mgmt rx len(%u)",
2955 __func__, hdr->buf_len);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302956 qdf_mem_free(rx_pkt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002957 return -ENOMEM;
2958 }
2959
Nirav Shahcbc6d722016-03-01 16:24:53 +05302960 qdf_nbuf_put_tail(wbuf, hdr->buf_len);
2961 qdf_nbuf_set_protocol(wbuf, ETH_P_CONTROL);
2962 wh = (struct ieee80211_frame *)qdf_nbuf_data(wbuf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002963
Nirav Shahcbc6d722016-03-01 16:24:53 +05302964 rx_pkt->pkt_meta.mpdu_hdr_ptr = qdf_nbuf_data(wbuf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002965 rx_pkt->pkt_meta.mpdu_data_ptr = rx_pkt->pkt_meta.mpdu_hdr_ptr +
2966 rx_pkt->pkt_meta.mpdu_hdr_len;
2967 rx_pkt->pkt_meta.tsf_delta = hdr->tsf_delta;
2968 rx_pkt->pkt_buf = wbuf;
2969
2970 WMA_LOGD(FL("BSSID: "MAC_ADDRESS_STR" tsf_delta: %u"),
2971 MAC_ADDR_ARRAY(wh->i_addr3), hdr->tsf_delta);
2972
2973#ifdef BIG_ENDIAN_HOST
2974 {
2975 /*
2976 * for big endian host, copy engine byte_swap is enabled
2977 * But the rx mgmt frame buffer content is in network byte order
2978 * Need to byte swap the mgmt frame buffer content - so when
2979 * copy engine does byte_swap - host gets buffer content in the
2980 * correct byte order.
2981 */
2982 int i;
2983 uint32_t *destp, *srcp;
2984 destp = (uint32_t *) wh;
2985 srcp = (uint32_t *) param_tlvs->bufp;
2986 for (i = 0;
2987 i < (roundup(hdr->buf_len, sizeof(uint32_t)) / 4); i++) {
2988 *destp = cpu_to_le32(*srcp);
2989 destp++;
2990 srcp++;
2991 }
2992 }
2993#else
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302994 qdf_mem_copy(wh, param_tlvs->bufp, hdr->buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002995#endif
2996
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -07002997 WMA_LOGD(
2998 FL("BSSID: "MAC_ADDRESS_STR" snr = %d, rssi = %d, rssi_raw = %d"),
2999 MAC_ADDR_ARRAY(wh->i_addr3),
3000 hdr->snr, rx_pkt->pkt_meta.rssi,
3001 rx_pkt->pkt_meta.rssi_raw);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003002 if (!wma_handle->mgmt_rx) {
3003 WMA_LOGE("Not registered for Mgmt rx, dropping the frame");
3004 cds_pkt_return_packet(rx_pkt);
3005 return -EINVAL;
3006 }
3007
3008 /* If it is a beacon/probe response, save it for future use */
3009 mgt_type = (wh)->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
3010 mgt_subtype = (wh)->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
3011
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003012#ifdef WLAN_FEATURE_11W
3013 if (mgt_type == IEEE80211_FC0_TYPE_MGT &&
3014 (mgt_subtype == IEEE80211_FC0_SUBTYPE_DISASSOC ||
3015 mgt_subtype == IEEE80211_FC0_SUBTYPE_DEAUTH ||
3016 mgt_subtype == IEEE80211_FC0_SUBTYPE_ACTION)) {
Mukul Sharmaa748fbb2015-12-01 19:51:36 +05303017 if (wma_find_vdev_by_bssid(
3018 wma_handle, wh->i_addr3, &vdev_id)) {
3019 iface = &(wma_handle->interfaces[vdev_id]);
3020 if (iface->rmfEnabled) {
3021 status = wma_process_rmf_frame(wma_handle,
3022 iface, wh, rx_pkt, wbuf);
3023 if (status != 0)
3024 return status;
3025 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003026 }
3027 }
3028#endif /* WLAN_FEATURE_11W */
Mukul Sharmaa748fbb2015-12-01 19:51:36 +05303029 rx_pkt->pkt_meta.sessionId =
3030 (vdev_id == WMA_INVALID_VDEV_ID ? 0 : vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003031 wma_handle->mgmt_rx(wma_handle, rx_pkt);
3032 return 0;
3033}
3034
3035/**
3036 * wma_de_register_mgmt_frm_client() - deregister management frame
3037 * @cds_ctx: cds context
3038 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303039 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003040 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303041QDF_STATUS wma_de_register_mgmt_frm_client(void *cds_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003042{
3043 tp_wma_handle wma_handle;
3044
3045#ifdef QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +05303046 if (cds_get_conparam() == QDF_GLOBAL_FTM_MODE)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303047 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003048#endif
3049
Anurag Chouhan6d760662016-02-20 16:05:43 +05303050 wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003051 if (!wma_handle) {
3052 WMA_LOGE("%s: Failed to get WMA context", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303053 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003054 }
3055
3056 if (wmi_unified_unregister_event_handler(wma_handle->wmi_handle,
3057 WMI_MGMT_RX_EVENTID) != 0) {
3058 WMA_LOGE("Failed to Unregister rx mgmt handler with wmi");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303059 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003060 }
3061 wma_handle->mgmt_rx = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303062 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003063}
3064
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003065#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003066/**
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003067 * wma_register_roaming_callbacks() - Register roaming callbacks
3068 * @cds_ctx: CDS Context
3069 * @csr_roam_synch_cb: CSR roam synch callback routine pointer
3070 * @pe_roam_synch_cb: PE roam synch callback routine pointer
3071 *
3072 * Register the SME and PE callback routines with WMA for
3073 * handling roaming
3074 *
3075 * Return: Success or Failure Status
3076 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303077QDF_STATUS wma_register_roaming_callbacks(void *cds_ctx,
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003078 void (*csr_roam_synch_cb)(tpAniSirGlobal mac,
3079 roam_offload_synch_ind *roam_synch_data,
3080 tpSirBssDescription bss_desc_ptr, uint8_t reason),
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303081 QDF_STATUS (*pe_roam_synch_cb)(tpAniSirGlobal mac,
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003082 roam_offload_synch_ind *roam_synch_data,
3083 tpSirBssDescription bss_desc_ptr))
3084{
3085
Anurag Chouhan6d760662016-02-20 16:05:43 +05303086 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003087
3088 if (!wma) {
3089 WMA_LOGE("%s: Failed to get WMA context", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303090 return QDF_STATUS_E_FAILURE;
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003091 }
3092 wma->csr_roam_synch_cb = csr_roam_synch_cb;
3093 wma->pe_roam_synch_cb = pe_roam_synch_cb;
3094 WMA_LOGD("Registered roam synch callbacks with WMA successfully");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303095 return QDF_STATUS_SUCCESS;
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003096}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003097#endif
3098
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003099/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003100 * wma_register_mgmt_frm_client() - register management frame callback
3101 * @cds_ctx: cds context
3102 * @mgmt_frm_rx: management frame
3103 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303104 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003105 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303106QDF_STATUS wma_register_mgmt_frm_client(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003107 void *cds_ctx, wma_mgmt_frame_rx_callback mgmt_frm_rx)
3108{
Anurag Chouhan6d760662016-02-20 16:05:43 +05303109 tp_wma_handle wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003110
3111 if (!wma_handle) {
3112 WMA_LOGE("%s: Failed to get WMA context", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303113 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003114 }
3115
3116 if (wmi_unified_register_event_handler(wma_handle->wmi_handle,
3117 WMI_MGMT_RX_EVENTID,
Govind Singhd76a5b02016-03-08 15:12:14 +05303118 wma_mgmt_rx_process,
3119 WMA_RX_WORK_CTX) != 0) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003120 WMA_LOGE("Failed to register rx mgmt handler with wmi");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303121 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003122 }
3123 wma_handle->mgmt_rx = mgmt_frm_rx;
3124
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303125 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003126}