blob: 5d0020e45235baea967953b635b2cbf06ea832a5 [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
Nirav Shahcbc6d722016-03-01 16:24:53 +053047#include "qdf_nbuf.h"
Anurag Chouhan6d760662016-02-20 16:05:43 +053048#include "qdf_types.h"
Anurag Chouhan600c3a02016-03-01 10:33:54 +053049#include "qdf_mem.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080050#include "ol_txrx_peer_find.h"
51
52#include "wma_types.h"
53#include "lim_api.h"
54#include "lim_session_utils.h"
55
56#include "cds_utils.h"
57
58#if !defined(REMOVE_PKT_LOG)
59#include "pktlog_ac.h"
60#endif /* REMOVE_PKT_LOG */
61
62#include "dbglog_host.h"
63#include "csr_api.h"
64#include "ol_fw.h"
65#include "dfs.h"
66#include "wma_internal.h"
Chandrasekaran, Manishekar0d814c72015-11-05 10:42:48 +053067#include "cds_concurrency.h"
Dhanashri Atreb08959a2016-03-01 17:28:03 -080068#include "cdp_txrx_flow_ctrl_legacy.h"
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -070069#include <cdp_txrx_peer_ops.h>
70#include <cdp_txrx_pmf.h>
71#include <cdp_txrx_cfg.h>
72#include <cdp_txrx_cmn.h>
73#include <cdp_txrx_misc.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080074
75/**
76 * wma_send_bcn_buf_ll() - prepare and send beacon buffer to fw for LL
77 * @wma: wma handle
78 * @pdev: txrx pdev
79 * @vdev_id: vdev id
80 * @param_buf: SWBA parameters
81 *
82 * Return: none
83 */
84static void wma_send_bcn_buf_ll(tp_wma_handle wma,
85 ol_txrx_pdev_handle pdev,
86 uint8_t vdev_id,
87 WMI_HOST_SWBA_EVENTID_param_tlvs *param_buf)
88{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080089 struct ieee80211_frame *wh;
90 struct beacon_info *bcn;
91 wmi_tim_info *tim_info = param_buf->tim_info;
92 uint8_t *bcn_payload;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053093 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080094 struct beacon_tim_ie *tim_ie;
95 wmi_p2p_noa_info *p2p_noa_info = param_buf->p2p_noa_info;
96 struct p2p_sub_element_noa noa_ie;
Himanshu Agarwal009f1572016-03-09 17:26:02 +053097 struct wmi_bcn_send_from_host params;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080098 uint8_t i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080099
100 bcn = wma->interfaces[vdev_id].beacon;
101 if (!bcn->buf) {
102 WMA_LOGE("%s: Invalid beacon buffer", __func__);
103 return;
104 }
105
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530106 qdf_spin_lock_bh(&bcn->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800107
Nirav Shahcbc6d722016-03-01 16:24:53 +0530108 bcn_payload = qdf_nbuf_data(bcn->buf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800109
110 tim_ie = (struct beacon_tim_ie *)(&bcn_payload[bcn->tim_ie_offset]);
111
112 if (tim_info->tim_changed) {
113 if (tim_info->tim_num_ps_pending)
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530114 qdf_mem_copy(&tim_ie->tim_bitmap, tim_info->tim_bitmap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800115 WMA_TIM_SUPPORTED_PVB_LENGTH);
116 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530117 qdf_mem_zero(&tim_ie->tim_bitmap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800118 WMA_TIM_SUPPORTED_PVB_LENGTH);
119 /*
120 * Currently we support fixed number of
121 * peers as limited by HAL_NUM_STA.
122 * tim offset is always 0
123 */
124 tim_ie->tim_bitctl = 0;
125 }
126
127 /* Update DTIM Count */
128 if (tim_ie->dtim_count == 0)
129 tim_ie->dtim_count = tim_ie->dtim_period - 1;
130 else
131 tim_ie->dtim_count--;
132
133 /*
134 * DTIM count needs to be backedup so that
135 * when umac updates the beacon template
136 * current dtim count can be updated properly
137 */
138 bcn->dtim_count = tim_ie->dtim_count;
139
140 /* update state for buffered multicast frames on DTIM */
141 if (tim_info->tim_mcast && (tim_ie->dtim_count == 0 ||
142 tim_ie->dtim_period == 1))
143 tim_ie->tim_bitctl |= 1;
144 else
145 tim_ie->tim_bitctl &= ~1;
146
147 /* To avoid sw generated frame sequence the same as H/W generated frame,
148 * the value lower than min_sw_seq is reserved for HW generated frame */
149 if ((bcn->seq_no & IEEE80211_SEQ_MASK) < MIN_SW_SEQ)
150 bcn->seq_no = MIN_SW_SEQ;
151
152 wh = (struct ieee80211_frame *)bcn_payload;
153 *(uint16_t *) &wh->i_seq[0] = htole16(bcn->seq_no
154 << IEEE80211_SEQ_SEQ_SHIFT);
155 bcn->seq_no++;
156
157 if (WMI_UNIFIED_NOA_ATTR_IS_MODIFIED(p2p_noa_info)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530158 qdf_mem_zero(&noa_ie, sizeof(noa_ie));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800159
160 noa_ie.index =
161 (uint8_t) WMI_UNIFIED_NOA_ATTR_INDEX_GET(p2p_noa_info);
162 noa_ie.oppPS =
163 (uint8_t) WMI_UNIFIED_NOA_ATTR_OPP_PS_GET(p2p_noa_info);
164 noa_ie.ctwindow =
165 (uint8_t) WMI_UNIFIED_NOA_ATTR_CTWIN_GET(p2p_noa_info);
166 noa_ie.num_descriptors =
167 (uint8_t) WMI_UNIFIED_NOA_ATTR_NUM_DESC_GET(p2p_noa_info);
168 WMA_LOGI("%s: index %u, oppPs %u, ctwindow %u, "
169 "num_descriptors = %u", __func__, noa_ie.index,
170 noa_ie.oppPS, noa_ie.ctwindow, noa_ie.num_descriptors);
171 for (i = 0; i < noa_ie.num_descriptors; i++) {
172 noa_ie.noa_descriptors[i].type_count =
173 (uint8_t) p2p_noa_info->noa_descriptors[i].
174 type_count;
175 noa_ie.noa_descriptors[i].duration =
176 p2p_noa_info->noa_descriptors[i].duration;
177 noa_ie.noa_descriptors[i].interval =
178 p2p_noa_info->noa_descriptors[i].interval;
179 noa_ie.noa_descriptors[i].start_time =
180 p2p_noa_info->noa_descriptors[i].start_time;
181 WMA_LOGI("%s: NoA descriptor[%d] type_count %u, "
182 "duration %u, interval %u, start_time = %u",
183 __func__, i,
184 noa_ie.noa_descriptors[i].type_count,
185 noa_ie.noa_descriptors[i].duration,
186 noa_ie.noa_descriptors[i].interval,
187 noa_ie.noa_descriptors[i].start_time);
188 }
189 wma_update_noa(bcn, &noa_ie);
190
191 /* Send a msg to LIM to update the NoA IE in probe response
192 * frames transmitted by the host */
193 wma_update_probe_resp_noa(wma, &noa_ie);
194 }
195
196 if (bcn->dma_mapped) {
Nirav Shahcbc6d722016-03-01 16:24:53 +0530197 qdf_nbuf_unmap_single(pdev->osdev, bcn->buf, QDF_DMA_TO_DEVICE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800198 bcn->dma_mapped = 0;
199 }
Nirav Shahcbc6d722016-03-01 16:24:53 +0530200 ret = qdf_nbuf_map_single(pdev->osdev, bcn->buf, QDF_DMA_TO_DEVICE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530201 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800202 WMA_LOGE("%s: failed map beacon buf to DMA region", __func__);
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530203 qdf_spin_unlock_bh(&bcn->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800204 return;
205 }
206
207 bcn->dma_mapped = 1;
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530208 params.vdev_id = vdev_id;
209 params.data_len = bcn->len;
210 params.frame_ctrl = *((A_UINT16 *) wh->i_fc);
211 params.frag_ptr = qdf_nbuf_get_frag_paddr(bcn->buf, 0);
212 params.dtim_flag = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800213 /* notify Firmware of DTM and mcast/bcast traffic */
214 if (tim_ie->dtim_count == 0) {
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530215 params.dtim_flag |= WMI_BCN_SEND_DTIM_ZERO;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800216 /* deliver mcast/bcast traffic in next DTIM beacon */
217 if (tim_ie->tim_bitctl & 0x01)
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530218 params.dtim_flag |= WMI_BCN_SEND_DTIM_BITCTL_SET;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800219 }
220
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530221 wmi_unified_bcn_buf_ll_cmd(wma->wmi_handle,
222 &params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800223
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530224 qdf_spin_unlock_bh(&bcn->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800225}
226
227/**
228 * wma_beacon_swba_handler() - swba event handler
229 * @handle: wma handle
230 * @event: event data
231 * @len: data length
232 *
233 * SWBA event is alert event to Host requesting host to Queue a beacon
234 * for transmission use only in host beacon mode
235 *
236 * Return: 0 for success or error code
237 */
238int wma_beacon_swba_handler(void *handle, uint8_t *event, uint32_t len)
239{
240 tp_wma_handle wma = (tp_wma_handle) handle;
241 WMI_HOST_SWBA_EVENTID_param_tlvs *param_buf;
242 wmi_host_swba_event_fixed_param *swba_event;
243 uint32_t vdev_map;
244 ol_txrx_pdev_handle pdev;
245 uint8_t vdev_id = 0;
246
247 param_buf = (WMI_HOST_SWBA_EVENTID_param_tlvs *) event;
248 if (!param_buf) {
249 WMA_LOGE("Invalid swba event buffer");
250 return -EINVAL;
251 }
252 swba_event = param_buf->fixed_param;
253 vdev_map = swba_event->vdev_map;
254
Anurag Chouhan6d760662016-02-20 16:05:43 +0530255 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800256 if (!pdev) {
257 WMA_LOGE("%s: pdev is NULL", __func__);
258 return -EINVAL;
259 }
260
261 for (; vdev_map; vdev_id++, vdev_map >>= 1) {
262 if (!(vdev_map & 0x1))
263 continue;
264 if (!ol_cfg_is_high_latency(pdev->ctrl_pdev))
265 wma_send_bcn_buf_ll(wma, pdev, vdev_id, param_buf);
266 break;
267 }
268 return 0;
269}
270
271/**
272 * wma_peer_sta_kickout_event_handler() - kickout event handler
273 * @handle: wma handle
274 * @event: event data
275 * @len: data length
276 *
277 * Kickout event is received from firmware on observing beacon miss
278 * It handles kickout event for different modes and indicate to
279 * upper layers.
280 *
281 * Return: 0 for success or error code
282 */
283int wma_peer_sta_kickout_event_handler(void *handle, u8 *event, u32 len)
284{
285 tp_wma_handle wma = (tp_wma_handle) handle;
286 WMI_PEER_STA_KICKOUT_EVENTID_param_tlvs *param_buf = NULL;
287 wmi_peer_sta_kickout_event_fixed_param *kickout_event = NULL;
288 uint8_t vdev_id, peer_id, macaddr[IEEE80211_ADDR_LEN];
289 ol_txrx_peer_handle peer;
290 ol_txrx_pdev_handle pdev;
291 tpDeleteStaContext del_sta_ctx;
292 tpSirIbssPeerInactivityInd p_inactivity;
293
294 WMA_LOGD("%s: Enter", __func__);
295 param_buf = (WMI_PEER_STA_KICKOUT_EVENTID_param_tlvs *) event;
296 kickout_event = param_buf->fixed_param;
Anurag Chouhan6d760662016-02-20 16:05:43 +0530297 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800298 if (!pdev) {
299 WMA_LOGE("%s: pdev is NULL", __func__);
300 return -EINVAL;
301 }
302 WMI_MAC_ADDR_TO_CHAR_ARRAY(&kickout_event->peer_macaddr, macaddr);
303 peer = ol_txrx_find_peer_by_addr(pdev, macaddr, &peer_id);
304 if (!peer) {
305 WMA_LOGE("PEER [%pM] not found", macaddr);
306 return -EINVAL;
307 }
308
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530309 if (ol_txrx_get_vdevid(peer, &vdev_id) != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800310 WMA_LOGE("Not able to find BSSID for peer [%pM]", macaddr);
311 return -EINVAL;
312 }
313
314 WMA_LOGA("%s: PEER:[%pM], ADDR:[%pN], INTERFACE:%d, peer_id:%d, reason:%d",
315 __func__, macaddr, wma->interfaces[vdev_id].addr, vdev_id,
316 peer_id, kickout_event->reason);
Varun Reddy Yeturu30bc42c2016-02-04 10:07:30 -0800317 if (wma->interfaces[vdev_id].roaming_in_progress) {
318 WMA_LOGE("Ignore STA kick out since roaming is in progress");
319 return -EINVAL;
320 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800321
322 switch (kickout_event->reason) {
323 case WMI_PEER_STA_KICKOUT_REASON_IBSS_DISCONNECT:
324 p_inactivity = (tpSirIbssPeerInactivityInd)
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530325 qdf_mem_malloc(sizeof(tSirIbssPeerInactivityInd));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800326 if (!p_inactivity) {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530327 WMA_LOGE("QDF MEM Alloc Failed for tSirIbssPeerInactivity");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800328 return -ENOMEM;
329 }
330
331 p_inactivity->staIdx = peer_id;
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530332 qdf_mem_copy(p_inactivity->peer_addr.bytes, macaddr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800333 IEEE80211_ADDR_LEN);
334 wma_send_msg(wma, WMA_IBSS_PEER_INACTIVITY_IND,
335 (void *)p_inactivity, 0);
336 goto exit_handler;
337 break;
338
339#ifdef FEATURE_WLAN_TDLS
340 case WMI_PEER_STA_KICKOUT_REASON_TDLS_DISCONNECT:
341 del_sta_ctx = (tpDeleteStaContext)
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530342 qdf_mem_malloc(sizeof(tDeleteStaContext));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800343 if (!del_sta_ctx) {
344 WMA_LOGE("%s: mem alloc failed for tDeleteStaContext for TDLS peer: %pM",
345 __func__, macaddr);
346 return -ENOMEM;
347 }
348
349 del_sta_ctx->staId = peer_id;
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530350 qdf_mem_copy(del_sta_ctx->addr2, macaddr, IEEE80211_ADDR_LEN);
351 qdf_mem_copy(del_sta_ctx->bssId, wma->interfaces[vdev_id].bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800352 IEEE80211_ADDR_LEN);
353 del_sta_ctx->reasonCode = HAL_DEL_STA_REASON_CODE_KEEP_ALIVE;
354 wma_send_msg(wma, SIR_LIM_DELETE_STA_CONTEXT_IND,
355 (void *)del_sta_ctx, 0);
356 goto exit_handler;
357 break;
358#endif /* FEATURE_WLAN_TDLS */
359
360 case WMI_PEER_STA_KICKOUT_REASON_XRETRY:
361 if (wma->interfaces[vdev_id].type == WMI_VDEV_TYPE_STA &&
362 (wma->interfaces[vdev_id].sub_type == 0 ||
363 wma->interfaces[vdev_id].sub_type ==
364 WMI_UNIFIED_VDEV_SUBTYPE_P2P_CLIENT) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530365 !qdf_mem_cmp(wma->interfaces[vdev_id].bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800366 macaddr, IEEE80211_ADDR_LEN)) {
367 /*
368 * KICKOUT event is for current station-AP connection.
369 * Treat it like final beacon miss. Station may not have
370 * missed beacons but not able to transmit frames to AP
371 * for a long time. Must disconnect to get out of
372 * this sticky situation.
373 * In future implementation, roaming module will also
374 * handle this event and perform a scan.
375 */
376 WMA_LOGW("%s: WMI_PEER_STA_KICKOUT_REASON_XRETRY event for STA",
377 __func__);
378 wma_beacon_miss_handler(wma, vdev_id);
379 goto exit_handler;
380 }
381 break;
382
383 case WMI_PEER_STA_KICKOUT_REASON_UNSPECIFIED:
384 /*
385 * Default legacy value used by original firmware implementation.
386 */
387 if (wma->interfaces[vdev_id].type == WMI_VDEV_TYPE_STA &&
388 (wma->interfaces[vdev_id].sub_type == 0 ||
389 wma->interfaces[vdev_id].sub_type ==
390 WMI_UNIFIED_VDEV_SUBTYPE_P2P_CLIENT) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530391 !qdf_mem_cmp(wma->interfaces[vdev_id].bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800392 macaddr, IEEE80211_ADDR_LEN)) {
393 /*
394 * KICKOUT event is for current station-AP connection.
395 * Treat it like final beacon miss. Station may not have
396 * missed beacons but not able to transmit frames to AP
397 * for a long time. Must disconnect to get out of
398 * this sticky situation.
399 * In future implementation, roaming module will also
400 * handle this event and perform a scan.
401 */
402 WMA_LOGW("%s: WMI_PEER_STA_KICKOUT_REASON_UNSPECIFIED event for STA",
403 __func__);
404 wma_beacon_miss_handler(wma, vdev_id);
405 goto exit_handler;
406 }
407 break;
408
409 case WMI_PEER_STA_KICKOUT_REASON_INACTIVITY:
mukul sharma72c8b222015-09-04 17:02:01 +0530410 /* Handle SA query kickout is same as inactivity kickout */
411 case WMI_PEER_STA_KICKOUT_REASON_SA_QUERY_TIMEOUT:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800412 default:
413 break;
414 }
415
416 /*
417 * default action is to send delete station context indication to LIM
418 */
419 del_sta_ctx =
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530420 (tpDeleteStaContext) qdf_mem_malloc(sizeof(tDeleteStaContext));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800421 if (!del_sta_ctx) {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530422 WMA_LOGE("QDF MEM Alloc Failed for tDeleteStaContext");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800423 return -ENOMEM;
424 }
425
426 del_sta_ctx->staId = peer_id;
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530427 qdf_mem_copy(del_sta_ctx->addr2, macaddr, IEEE80211_ADDR_LEN);
428 qdf_mem_copy(del_sta_ctx->bssId, wma->interfaces[vdev_id].addr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800429 IEEE80211_ADDR_LEN);
430 del_sta_ctx->reasonCode = HAL_DEL_STA_REASON_CODE_KEEP_ALIVE;
Kiran Kumar Lokere37d3aa22015-11-03 14:58:26 -0800431 del_sta_ctx->rssi = kickout_event->rssi + WMA_TGT_NOISE_FLOOR_DBM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800432 wma_send_msg(wma, SIR_LIM_DELETE_STA_CONTEXT_IND, (void *)del_sta_ctx,
433 0);
434
435exit_handler:
436 WMA_LOGD("%s: Exit", __func__);
437 return 0;
438}
439
440/**
441 * wma_unified_bcntx_status_event_handler() - beacon tx status event handler
442 * @handle: wma handle
443 * @cmd_param_info: event data
444 * @len: data length
445 *
446 * WMI Handler for WMI_OFFLOAD_BCN_TX_STATUS_EVENTID event from firmware.
447 * This event is generated by FW when the beacon transmission is offloaded
448 * and the host performs beacon template modification using WMI_BCN_TMPL_CMDID
449 * The FW generates this event when the first successful beacon transmission
450 * after template update
451 *
452 * Return: 0 for success or error code
453 */
454int wma_unified_bcntx_status_event_handler(void *handle,
455 uint8_t *cmd_param_info,
456 uint32_t len)
457{
458 tp_wma_handle wma = (tp_wma_handle) handle;
459 WMI_OFFLOAD_BCN_TX_STATUS_EVENTID_param_tlvs *param_buf;
460 wmi_offload_bcn_tx_status_event_fixed_param *resp_event;
461 tSirFirstBeaconTxCompleteInd *beacon_tx_complete_ind;
462
463 param_buf =
464 (WMI_OFFLOAD_BCN_TX_STATUS_EVENTID_param_tlvs *) cmd_param_info;
465 if (!param_buf) {
466 WMA_LOGE("Invalid bcn tx response event buffer");
467 return -EINVAL;
468 }
469
470 resp_event = param_buf->fixed_param;
471
Chandrasekaran, Manishekarce2172e2016-02-18 16:12:43 +0530472 WMA_LOGD("%s", __func__);
473
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800474 /* Check for valid handle to ensure session is not
475 * deleted in any race
476 */
477 if (!wma->interfaces[resp_event->vdev_id].handle) {
478 WMA_LOGE("%s: The session does not exist", __func__);
479 return -EINVAL;
480 }
481
482 /* Beacon Tx Indication supports only AP mode. Ignore in other modes */
483 if (wma_is_vdev_in_ap_mode(wma, resp_event->vdev_id) == false) {
484 WMA_LOGI("%s: Beacon Tx Indication does not support type %d and sub_type %d",
485 __func__, wma->interfaces[resp_event->vdev_id].type,
486 wma->interfaces[resp_event->vdev_id].sub_type);
487 return 0;
488 }
489
490 beacon_tx_complete_ind = (tSirFirstBeaconTxCompleteInd *)
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530491 qdf_mem_malloc(sizeof(tSirFirstBeaconTxCompleteInd));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800492 if (!beacon_tx_complete_ind) {
493 WMA_LOGE("%s: Failed to alloc beacon_tx_complete_ind",
494 __func__);
495 return -ENOMEM;
496 }
497
498 beacon_tx_complete_ind->messageType = WMA_DFS_BEACON_TX_SUCCESS_IND;
499 beacon_tx_complete_ind->length = sizeof(tSirFirstBeaconTxCompleteInd);
500 beacon_tx_complete_ind->bssIdx = resp_event->vdev_id;
501
502 wma_send_msg(wma, WMA_DFS_BEACON_TX_SUCCESS_IND,
503 (void *)beacon_tx_complete_ind, 0);
504 return 0;
505}
506
507/**
508 * wma_get_link_probe_timeout() - get link timeout based on sub type
509 * @mac: UMAC handler
510 * @sub_type: vdev syb type
511 * @max_inactive_time: return max inactive time
512 * @max_unresponsive_time: return max unresponsive time
513 *
514 * Return: none
515 */
516static inline void wma_get_link_probe_timeout(struct sAniSirGlobal *mac,
517 uint32_t sub_type,
518 uint32_t *max_inactive_time,
519 uint32_t *max_unresponsive_time)
520{
521 uint32_t keep_alive;
522 uint16_t lm_id, ka_id;
523
524 switch (sub_type) {
525 case WMI_UNIFIED_VDEV_SUBTYPE_P2P_GO:
526 lm_id = WNI_CFG_GO_LINK_MONITOR_TIMEOUT;
527 ka_id = WNI_CFG_GO_KEEP_ALIVE_TIMEOUT;
528 break;
529 default:
530 /*For softAp the subtype value will be zero */
531 lm_id = WNI_CFG_AP_LINK_MONITOR_TIMEOUT;
532 ka_id = WNI_CFG_AP_KEEP_ALIVE_TIMEOUT;
533 }
534
535 if (wlan_cfg_get_int(mac, lm_id, max_inactive_time) != eSIR_SUCCESS) {
536 WMA_LOGE("Failed to read link monitor for subtype %d",
537 sub_type);
538 *max_inactive_time = WMA_LINK_MONITOR_DEFAULT_TIME_SECS;
539 }
540
541 if (wlan_cfg_get_int(mac, ka_id, &keep_alive) != eSIR_SUCCESS) {
542 WMA_LOGE("Failed to read keep alive for subtype %d", sub_type);
543 keep_alive = WMA_KEEP_ALIVE_DEFAULT_TIME_SECS;
544 }
545 *max_unresponsive_time = *max_inactive_time + keep_alive;
546}
547
548/**
549 * wma_set_sap_keepalive() - set SAP keep alive parameters to fw
550 * @wma: wma handle
551 * @vdev_id: vdev id
552 *
553 * Return: none
554 */
555void wma_set_sap_keepalive(tp_wma_handle wma, uint8_t vdev_id)
556{
557 uint32_t min_inactive_time, max_inactive_time, max_unresponsive_time;
Anurag Chouhan6d760662016-02-20 16:05:43 +0530558 struct sAniSirGlobal *mac = cds_get_context(QDF_MODULE_ID_PE);
Govind Singhd76a5b02016-03-08 15:12:14 +0530559 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800560
561 if (NULL == mac) {
562 WMA_LOGE("%s: Failed to get mac", __func__);
563 return;
564 }
565
566 wma_get_link_probe_timeout(mac, wma->interfaces[vdev_id].sub_type,
567 &max_inactive_time, &max_unresponsive_time);
568
569 min_inactive_time = max_inactive_time / 2;
570
Govind Singhd76a5b02016-03-08 15:12:14 +0530571 status = wma_vdev_set_param(wma->wmi_handle,
572 vdev_id,
573 WMI_VDEV_PARAM_AP_KEEPALIVE_MIN_IDLE_INACTIVE_TIME_SECS,
574 min_inactive_time);
575 if (QDF_IS_STATUS_ERROR(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800576 WMA_LOGE("Failed to Set AP MIN IDLE INACTIVE TIME");
577
Govind Singhd76a5b02016-03-08 15:12:14 +0530578 status = wma_vdev_set_param(wma->wmi_handle,
579 vdev_id,
580 WMI_VDEV_PARAM_AP_KEEPALIVE_MAX_IDLE_INACTIVE_TIME_SECS,
581 max_inactive_time);
582 if (QDF_IS_STATUS_ERROR(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800583 WMA_LOGE("Failed to Set AP MAX IDLE INACTIVE TIME");
584
Govind Singhd76a5b02016-03-08 15:12:14 +0530585 status = wma_vdev_set_param(wma->wmi_handle,
586 vdev_id,
587 WMI_VDEV_PARAM_AP_KEEPALIVE_MAX_UNRESPONSIVE_TIME_SECS,
588 max_unresponsive_time);
589 if (QDF_IS_STATUS_ERROR(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800590 WMA_LOGE("Failed to Set MAX UNRESPONSIVE TIME");
591
592 WMA_LOGD("%s:vdev_id:%d min_inactive_time: %u max_inactive_time: %u"
593 " max_unresponsive_time: %u", __func__, vdev_id,
594 min_inactive_time, max_inactive_time, max_unresponsive_time);
595}
596
597/**
mukul sharma72c8b222015-09-04 17:02:01 +0530598 * wma_set_sta_sa_query_param() - set sta sa query parameters
599 * @wma: wma handle
600 * @vdev_id: vdev id
601
602 * This function sets sta query related parameters in fw.
603 *
604 * Return: none
605 */
606
607void wma_set_sta_sa_query_param(tp_wma_handle wma,
608 uint8_t vdev_id)
609{
Anurag Chouhan6d760662016-02-20 16:05:43 +0530610 struct sAniSirGlobal *mac = cds_get_context(QDF_MODULE_ID_PE);
mukul sharma72c8b222015-09-04 17:02:01 +0530611 uint32_t max_retries, retry_interval;
mukul sharma72c8b222015-09-04 17:02:01 +0530612
613 WMA_LOGD(FL("Enter:"));
mukul sharma72c8b222015-09-04 17:02:01 +0530614
615 if (wlan_cfg_get_int
616 (mac, WNI_CFG_PMF_SA_QUERY_MAX_RETRIES,
617 &max_retries) != eSIR_SUCCESS) {
618 max_retries = DEFAULT_STA_SA_QUERY_MAX_RETRIES_COUNT;
619 WMA_LOGE(FL("Failed to get value for WNI_CFG_PMF_SA_QUERY_MAX_RETRIES"));
620 }
621 if (wlan_cfg_get_int
622 (mac, WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL,
623 &retry_interval) != eSIR_SUCCESS) {
624 retry_interval = DEFAULT_STA_SA_QUERY_RETRY_INTERVAL;
625 WMA_LOGE(FL("Failed to get value for WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL"));
626 }
627
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530628 wmi_unified_set_sta_sa_query_param_cmd(wma->wmi_handle,
629 vdev_id,
630 max_retries,
631 retry_interval);
mukul sharma72c8b222015-09-04 17:02:01 +0530632
633 WMA_LOGD(FL("Exit :"));
634 return;
635}
636
637/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800638 * wma_set_sta_keep_alive() - set sta keep alive parameters
639 * @wma: wma handle
640 * @vdev_id: vdev id
641 * @method: method for keep alive
642 * @timeperiod: time period
643 * @hostv4addr: host ipv4 address
644 * @destv4addr: dst ipv4 address
645 * @destmac: destination mac
646 *
647 * This function sets keep alive related parameters in fw.
648 *
649 * Return: none
650 */
651void wma_set_sta_keep_alive(tp_wma_handle wma, uint8_t vdev_id,
652 uint32_t method, uint32_t timeperiod,
653 uint8_t *hostv4addr, uint8_t *destv4addr,
654 uint8_t *destmac)
655{
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530656 struct sta_params params;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800657
658 WMA_LOGD("%s: Enter", __func__);
659
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530660 if (!wma) {
661 WMA_LOGE("%s: wma handle is NULL", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800662 return;
663 }
664
Govind Singhfe9ab252016-06-21 14:35:35 +0530665 if (timeperiod > WNI_CFG_INFRA_STA_KEEP_ALIVE_PERIOD_STAMAX) {
666 WMI_LOGE("Invalid period %d Max limit %d", timeperiod,
667 WNI_CFG_INFRA_STA_KEEP_ALIVE_PERIOD_STAMAX);
668 return;
669 }
670
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530671 params.vdev_id = vdev_id;
672 params.method = method;
673 params.timeperiod = timeperiod;
674 params.hostv4addr = hostv4addr;
675 params.destv4addr = destv4addr;
676 params.destmac = destmac;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800677
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530678 wmi_unified_set_sta_keep_alive_cmd(wma->wmi_handle,
679 &params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800680
681 WMA_LOGD("%s: Exit", __func__);
682 return;
683}
684
685/**
686 * wma_vdev_install_key_complete_event_handler() - install key complete handler
687 * @handle: wma handle
688 * @event: event data
689 * @len: data length
690 *
691 * This event is sent by fw once WPA/WPA2 keys are installed in fw.
692 *
693 * Return: 0 for success or error code
694 */
695int wma_vdev_install_key_complete_event_handler(void *handle,
696 uint8_t *event,
697 uint32_t len)
698{
699 WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID_param_tlvs *param_buf = NULL;
700 wmi_vdev_install_key_complete_event_fixed_param *key_fp = NULL;
701
702 if (!event) {
703 WMA_LOGE("%s: event param null", __func__);
704 return -EINVAL;
705 }
706
707 param_buf = (WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID_param_tlvs *) event;
708 if (!param_buf) {
709 WMA_LOGE("%s: received null buf from target", __func__);
710 return -EINVAL;
711 }
712
713 key_fp = param_buf->fixed_param;
714 if (!key_fp) {
715 WMA_LOGE("%s: received null event data from target", __func__);
716 return -EINVAL;
717 }
718 /*
719 * Do nothing for now. Completion of set key is already indicated to lim
720 */
721 WMA_LOGI("%s: WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID", __func__);
722 return 0;
723}
724/*
725 * 802.11n D2.0 defined values for "Minimum MPDU Start Spacing":
726 * 0 for no restriction
727 * 1 for 1/4 us - Our lower layer calculations limit our precision to 1 msec
728 * 2 for 1/2 us - Our lower layer calculations limit our precision to 1 msec
729 * 3 for 1 us
730 * 4 for 2 us
731 * 5 for 4 us
732 * 6 for 8 us
733 * 7 for 16 us
734 */
735static const uint8_t wma_mpdu_spacing[] = { 0, 1, 1, 1, 2, 4, 8, 16 };
736
737/**
738 * wma_parse_mpdudensity() - give mpdu spacing from mpdu density
739 * @mpdudensity: mpdu density
740 *
741 * Return: mpdu spacing or 0 for error
742 */
743static inline uint8_t wma_parse_mpdudensity(uint8_t mpdudensity)
744{
745 if (mpdudensity < sizeof(wma_mpdu_spacing))
746 return wma_mpdu_spacing[mpdudensity];
747 else
748 return 0;
749}
750
Poddar, Siddarth5a91f5b2016-04-28 12:24:10 +0530751#if defined(CONFIG_HL_SUPPORT) && defined(FEATURE_WLAN_TDLS)
752
753/**
754 * wma_unified_peer_state_update() - update peer state
755 * @pdev: pdev handle
756 * @sta_mac: pointer to sta mac addr
757 * @bss_addr: bss address
758 * @sta_type: sta entry type
759 *
760 *
761 * Return: None
762 */
763static void
764wma_unified_peer_state_update(
765 struct ol_txrx_pdev_t *pdev,
766 uint8_t *sta_mac,
767 uint8_t *bss_addr,
768 uint8_t sta_type)
769{
770 if (STA_ENTRY_TDLS_PEER == sta_type)
771 ol_txrx_peer_state_update(pdev, sta_mac,
772 OL_TXRX_PEER_STATE_AUTH);
773 else
774 ol_txrx_peer_state_update(pdev, bss_addr,
775 OL_TXRX_PEER_STATE_AUTH);
776}
777#else
778
779static inline void
780wma_unified_peer_state_update(
781 struct ol_txrx_pdev_t *pdev,
782 uint8_t *sta_mac,
783 uint8_t *bss_addr,
784 uint8_t sta_type)
785{
786 ol_txrx_peer_state_update(pdev, bss_addr, OL_TXRX_PEER_STATE_AUTH);
787}
788#endif
789
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800790/**
791 * wmi_unified_send_peer_assoc() - send peer assoc command to fw
792 * @wma: wma handle
793 * @nw_type: nw type
794 * @params: add sta params
795 *
796 * This function send peer assoc command to firmware with
797 * different parameters.
798 *
Govind Singhb30d4c02016-03-24 11:01:23 +0530799 * Return: QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800800 */
Govind Singhb30d4c02016-03-24 11:01:23 +0530801QDF_STATUS wma_send_peer_assoc(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800802 tSirNwType nw_type,
803 tpAddStaParams params)
804{
805 ol_txrx_pdev_handle pdev;
Govind Singhb30d4c02016-03-24 11:01:23 +0530806 struct peer_assoc_params *cmd;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800807 int32_t ret, max_rates, i;
808 uint8_t rx_stbc, tx_stbc;
Govind Singhb30d4c02016-03-24 11:01:23 +0530809 uint8_t *rate_pos;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800810 wmi_rate_set peer_legacy_rates, peer_ht_rates;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800811 uint32_t num_peer_11b_rates = 0;
812 uint32_t num_peer_11a_rates = 0;
813 uint32_t phymode;
814 uint32_t peer_nss = 1;
815 struct wma_txrx_node *intr = NULL;
Govind Singhb30d4c02016-03-24 11:01:23 +0530816 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800817
Govind Singhb30d4c02016-03-24 11:01:23 +0530818 cmd = qdf_mem_malloc(sizeof(struct peer_assoc_params));
819 if (!cmd) {
820 WMA_LOGE("Failed to allocate peer_assoc_params param");
821 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800822 }
Govind Singhb30d4c02016-03-24 11:01:23 +0530823
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800824 intr = &wma->interfaces[params->smesessionId];
825
Anurag Chouhan6d760662016-02-20 16:05:43 +0530826 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800827
828 if (NULL == pdev) {
829 WMA_LOGE("%s: Failed to get pdev", __func__);
Govind Singhb30d4c02016-03-24 11:01:23 +0530830 qdf_mem_free(cmd);
831 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800832 }
833
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530834 qdf_mem_zero(&peer_legacy_rates, sizeof(wmi_rate_set));
835 qdf_mem_zero(&peer_ht_rates, sizeof(wmi_rate_set));
Govind Singhb30d4c02016-03-24 11:01:23 +0530836 qdf_mem_zero(cmd, sizeof(struct peer_assoc_params));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800837
838 phymode = wma_peer_phymode(nw_type, params->staType,
839 params->htCapable,
840 params->ch_width,
841 params->vhtCapable);
842
843 /* Legacy Rateset */
844 rate_pos = (uint8_t *) peer_legacy_rates.rates;
845 for (i = 0; i < SIR_NUM_11B_RATES; i++) {
846 if (!params->supportedRates.llbRates[i])
847 continue;
848 rate_pos[peer_legacy_rates.num_rates++] =
849 params->supportedRates.llbRates[i];
850 num_peer_11b_rates++;
851 }
852 for (i = 0; i < SIR_NUM_11A_RATES; i++) {
853 if (!params->supportedRates.llaRates[i])
854 continue;
855 rate_pos[peer_legacy_rates.num_rates++] =
856 params->supportedRates.llaRates[i];
857 num_peer_11a_rates++;
858 }
859
860 if ((phymode == MODE_11A && num_peer_11a_rates == 0) ||
861 (phymode == MODE_11B && num_peer_11b_rates == 0)) {
862 WMA_LOGW("%s: Invalid phy rates. phymode 0x%x, 11b_rates %d, 11a_rates %d",
863 __func__, phymode, num_peer_11b_rates, num_peer_11a_rates);
Govind Singhb30d4c02016-03-24 11:01:23 +0530864 qdf_mem_free(cmd);
865 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800866 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800867
868 /* HT Rateset */
869 max_rates = sizeof(peer_ht_rates.rates) /
870 sizeof(peer_ht_rates.rates[0]);
871 rate_pos = (uint8_t *) peer_ht_rates.rates;
872 for (i = 0; i < MAX_SUPPORTED_RATES; i++) {
873 if (params->supportedRates.supportedMCSSet[i / 8] &
874 (1 << (i % 8))) {
875 rate_pos[peer_ht_rates.num_rates++] = i;
876 if (i >= 8) {
877 /* MCS8 or higher rate is present, must be 2x2 */
878 peer_nss = 2;
879 }
880 }
881 if (peer_ht_rates.num_rates == max_rates)
882 break;
883 }
884
885 if (params->htCapable && !peer_ht_rates.num_rates) {
886 uint8_t temp_ni_rates[8] = { 0x0, 0x1, 0x2, 0x3,
887 0x4, 0x5, 0x6, 0x7};
888 /*
889 * Workaround for EV 116382: The peer is marked HT but with
890 * supported rx mcs set is set to 0. 11n spec mandates MCS0-7
891 * for a HT STA. So forcing the supported rx mcs rate to
892 * MCS 0-7. This workaround will be removed once we get
893 * clarification from WFA regarding this STA behavior.
894 */
895
896 /* TODO: Do we really need this? */
897 WMA_LOGW("Peer is marked as HT capable but supported mcs rate is 0");
898 peer_ht_rates.num_rates = sizeof(temp_ni_rates);
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530899 qdf_mem_copy((uint8_t *) peer_ht_rates.rates, temp_ni_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800900 peer_ht_rates.num_rates);
901 }
902
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800903 /* in ap/ibss mode and for tdls peer, use mac address of the peer in
904 * the other end as the new peer address; in sta mode, use bss id to
905 * be the new peer address
906 */
907 if ((wma_is_vdev_in_ap_mode(wma, params->smesessionId))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800908 || (wma_is_vdev_in_ibss_mode(wma, params->smesessionId))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800909#ifdef FEATURE_WLAN_TDLS
910 || (STA_ENTRY_TDLS_PEER == params->staType)
911#endif /* FEATURE_WLAN_TDLS */
912 )
913 WMI_CHAR_ARRAY_TO_MAC_ADDR(params->staMac, &cmd->peer_macaddr);
914 else
915 WMI_CHAR_ARRAY_TO_MAC_ADDR(params->bssId, &cmd->peer_macaddr);
916 cmd->vdev_id = params->smesessionId;
917 cmd->peer_new_assoc = 1;
918 cmd->peer_associd = params->assocId;
919
920 /*
921 * The target only needs a subset of the flags maintained in the host.
922 * Just populate those flags and send it down
923 */
924 cmd->peer_flags = 0;
925
926 if (params->wmmEnabled)
927 cmd->peer_flags |= WMI_PEER_QOS;
928
929 if (params->uAPSD) {
930 cmd->peer_flags |= WMI_PEER_APSD;
931 WMA_LOGD("Set WMI_PEER_APSD: uapsd Mask %d", params->uAPSD);
932 }
933
934 if (params->htCapable) {
935 cmd->peer_flags |= (WMI_PEER_HT | WMI_PEER_QOS);
936 cmd->peer_rate_caps |= WMI_RC_HT_FLAG;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800937
Krishna Kumaar Natarajan59f546c2016-02-16 10:31:55 -0800938 if (params->ch_width) {
939 cmd->peer_flags |= WMI_PEER_40MHZ;
940 cmd->peer_rate_caps |= WMI_RC_CW40_FLAG;
941 if (params->fShortGI40Mhz)
942 cmd->peer_rate_caps |= WMI_RC_SGI_FLAG;
943 } else if (params->fShortGI20Mhz) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800944 cmd->peer_rate_caps |= WMI_RC_SGI_FLAG;
Krishna Kumaar Natarajan59f546c2016-02-16 10:31:55 -0800945 }
946 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800947
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800948 if (params->vhtCapable) {
949 cmd->peer_flags |= (WMI_PEER_HT | WMI_PEER_VHT | WMI_PEER_QOS);
950 cmd->peer_rate_caps |= WMI_RC_HT_FLAG;
951 }
952
953 if (params->ch_width == CH_WIDTH_80MHZ)
954 cmd->peer_flags |= WMI_PEER_80MHZ;
955 else if (params->ch_width == CH_WIDTH_160MHZ)
956 cmd->peer_flags |= WMI_PEER_160MHZ;
957 else if (params->ch_width == CH_WIDTH_80P80MHZ)
958 cmd->peer_flags |= WMI_PEER_160MHZ;
959
960 cmd->peer_vht_caps = params->vht_caps;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800961
962 if (params->rmfEnabled)
963 cmd->peer_flags |= WMI_PEER_PMF;
964
965 rx_stbc = (params->ht_caps & IEEE80211_HTCAP_C_RXSTBC) >>
966 IEEE80211_HTCAP_C_RXSTBC_S;
967 if (rx_stbc) {
968 cmd->peer_flags |= WMI_PEER_STBC;
969 cmd->peer_rate_caps |= (rx_stbc << WMI_RC_RX_STBC_FLAG_S);
970 }
971
972 tx_stbc = (params->ht_caps & IEEE80211_HTCAP_C_TXSTBC) >>
973 IEEE80211_HTCAP_C_TXSTBC_S;
974 if (tx_stbc) {
975 cmd->peer_flags |= WMI_PEER_STBC;
976 cmd->peer_rate_caps |= (tx_stbc << WMI_RC_TX_STBC_FLAG_S);
977 }
978
979 if (params->htLdpcCapable || params->vhtLdpcCapable)
980 cmd->peer_flags |= WMI_PEER_LDPC;
981
982 switch (params->mimoPS) {
983 case eSIR_HT_MIMO_PS_STATIC:
984 cmd->peer_flags |= WMI_PEER_STATIC_MIMOPS;
985 break;
986 case eSIR_HT_MIMO_PS_DYNAMIC:
987 cmd->peer_flags |= WMI_PEER_DYN_MIMOPS;
988 break;
989 case eSIR_HT_MIMO_PS_NO_LIMIT:
990 cmd->peer_flags |= WMI_PEER_SPATIAL_MUX;
991 break;
992 default:
993 break;
994 }
995
996#ifdef FEATURE_WLAN_TDLS
997 if (STA_ENTRY_TDLS_PEER == params->staType)
998 cmd->peer_flags |= WMI_PEER_AUTH;
999#endif /* FEATURE_WLAN_TDLS */
1000
1001 if (params->wpa_rsn
1002#ifdef FEATURE_WLAN_WAPI
1003 || params->encryptType == eSIR_ED_WPI
1004#endif /* FEATURE_WLAN_WAPI */
1005 )
1006 cmd->peer_flags |= WMI_PEER_NEED_PTK_4_WAY;
1007 if (params->wpa_rsn >> 1)
1008 cmd->peer_flags |= WMI_PEER_NEED_GTK_2_WAY;
1009
Poddar, Siddarth5a91f5b2016-04-28 12:24:10 +05301010 wma_unified_peer_state_update(pdev, params->staMac,
1011 params->bssId, params->staType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001012
1013#ifdef FEATURE_WLAN_WAPI
1014 if (params->encryptType == eSIR_ED_WPI) {
Govind Singhd76a5b02016-03-08 15:12:14 +05301015 ret = wma_vdev_set_param(wma->wmi_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001016 params->smesessionId,
1017 WMI_VDEV_PARAM_DROP_UNENCRY,
1018 false);
1019 if (ret) {
1020 WMA_LOGE
1021 ("Set WMI_VDEV_PARAM_DROP_UNENCRY Param status:%d\n",
1022 ret);
Govind Singhb30d4c02016-03-24 11:01:23 +05301023 qdf_mem_free(cmd);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001024 return ret;
1025 }
1026 }
1027#endif /* FEATURE_WLAN_WAPI */
1028
1029 cmd->peer_caps = params->capab_info;
1030 cmd->peer_listen_intval = params->listenInterval;
1031 cmd->peer_ht_caps = params->ht_caps;
1032 cmd->peer_max_mpdu = (1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR +
1033 params->maxAmpduSize)) - 1;
1034 cmd->peer_mpdu_density = wma_parse_mpdudensity(params->maxAmpduDensity);
1035
1036 if (params->supportedRates.supportedMCSSet[1] &&
1037 params->supportedRates.supportedMCSSet[2])
1038 cmd->peer_rate_caps |= WMI_RC_TS_FLAG;
1039 else if (params->supportedRates.supportedMCSSet[1])
1040 cmd->peer_rate_caps |= WMI_RC_DS_FLAG;
1041
1042 /* Update peer legacy rate information */
Govind Singhb30d4c02016-03-24 11:01:23 +05301043 cmd->peer_legacy_rates.num_rates = peer_legacy_rates.num_rates;
1044 qdf_mem_copy(cmd->peer_legacy_rates.rates, peer_legacy_rates.rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001045 peer_legacy_rates.num_rates);
1046
1047 /* Update peer HT rate information */
Govind Singhb30d4c02016-03-24 11:01:23 +05301048 cmd->peer_ht_rates.num_rates = peer_ht_rates.num_rates;
1049 qdf_mem_copy(cmd->peer_ht_rates.rates, peer_ht_rates.rates,
1050 peer_ht_rates.num_rates);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001051
1052 /* VHT Rates */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001053
1054 cmd->peer_nss = peer_nss;
Naveen Rawatb14cab32015-11-02 17:01:51 -08001055 /*
1056 * Because of DBS a vdev may come up in any of the two MACs with
1057 * different capabilities. STBC capab should be fetched for given
1058 * hard_mode->MAC_id combo. It is planned that firmware should provide
1059 * these dev capabilities. But for now number of tx streams can be used
1060 * to identify if Tx STBC needs to be disabled.
1061 */
1062 if (intr->tx_streams < 2) {
1063 cmd->peer_vht_caps &= ~(1 << SIR_MAC_VHT_CAP_TXSTBC);
1064 WMA_LOGD("Num tx_streams: %d, Disabled txSTBC",
1065 intr->tx_streams);
1066 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001067 WMA_LOGD("peer_nss %d peer_ht_rates.num_rates %d ", cmd->peer_nss,
1068 peer_ht_rates.num_rates);
1069
Govind Singhb30d4c02016-03-24 11:01:23 +05301070 cmd->vht_capable = params->vhtCapable;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001071 if (params->vhtCapable) {
1072#define VHT2x2MCSMASK 0xc
Govind Singhb30d4c02016-03-24 11:01:23 +05301073 cmd->rx_max_rate = params->supportedRates.vhtRxHighestDataRate;
1074 cmd->rx_mcs_set = params->supportedRates.vhtRxMCSMap;
1075 cmd->tx_max_rate = params->supportedRates.vhtTxHighestDataRate;
1076 cmd->tx_mcs_set = params->supportedRates.vhtTxMCSMap;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001077
1078 if (params->vhtSupportedRxNss) {
1079 cmd->peer_nss = params->vhtSupportedRxNss;
1080 } else {
Govind Singhb30d4c02016-03-24 11:01:23 +05301081 cmd->peer_nss = ((cmd->rx_mcs_set & VHT2x2MCSMASK)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001082 == VHT2x2MCSMASK) ? 1 : 2;
1083 }
1084 }
1085
1086 /*
1087 * Limit nss to max number of rf chain supported by target
1088 * Otherwise Fw will crash
1089 */
1090 wma_update_txrx_chainmask(wma->num_rf_chains, &cmd->peer_nss);
1091
1092 intr->nss = cmd->peer_nss;
1093 cmd->peer_phymode = phymode;
1094 WMA_LOGD("%s: vdev_id %d associd %d peer_flags %x rate_caps %x "
1095 "peer_caps %x listen_intval %d ht_caps %x max_mpdu %d "
1096 "nss %d phymode %d peer_mpdu_density %d encr_type %d "
1097 "cmd->peer_vht_caps %x", __func__,
1098 cmd->vdev_id, cmd->peer_associd, cmd->peer_flags,
1099 cmd->peer_rate_caps, cmd->peer_caps,
1100 cmd->peer_listen_intval, cmd->peer_ht_caps,
1101 cmd->peer_max_mpdu, cmd->peer_nss, cmd->peer_phymode,
1102 cmd->peer_mpdu_density, params->encryptType,
1103 cmd->peer_vht_caps);
1104
Govind Singhb30d4c02016-03-24 11:01:23 +05301105 status = wmi_unified_peer_assoc_send(wma->wmi_handle,
1106 cmd);
1107 if (QDF_IS_STATUS_ERROR(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001108 WMA_LOGP("%s: Failed to send peer assoc command ret = %d",
1109 __func__, ret);
Govind Singhb30d4c02016-03-24 11:01:23 +05301110 qdf_mem_free(cmd);
1111
1112 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001113}
1114
1115/**
1116 * wmi_unified_vdev_set_gtx_cfg_send() - set GTX params
1117 * @wmi_handle: wmi handle
1118 * @if_id: vdev id
1119 * @gtx_info: GTX config params
1120 *
1121 * This function set GTX related params in firmware.
1122 *
1123 * Return: 0 for success or error code
1124 */
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301125QDF_STATUS wmi_unified_vdev_set_gtx_cfg_send(wmi_unified_t wmi_handle,
1126 uint32_t if_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001127 gtx_config_t *gtx_info)
1128{
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301129 struct wmi_gtx_config params;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001130
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301131 params.gtx_rt_mask[0] = gtx_info->gtxRTMask[0];
1132 params.gtx_rt_mask[1] = gtx_info->gtxRTMask[1];
1133 params.gtx_usrcfg = gtx_info->gtxUsrcfg;
1134 params.gtx_threshold = gtx_info->gtxPERThreshold;
1135 params.gtx_margin = gtx_info->gtxPERMargin;
1136 params.gtx_tpcstep = gtx_info->gtxTPCstep;
1137 params.gtx_tpcmin = gtx_info->gtxTPCMin;
1138 params.gtx_bwmask = gtx_info->gtxBWMask;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001139
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301140 return wmi_unified_vdev_set_gtx_cfg_cmd(wmi_handle,
1141 if_id, &params);
1142
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001143}
1144
1145/**
1146 * wma_update_protection_mode() - update protection mode
1147 * @wma: wma handle
1148 * @vdev_id: vdev id
1149 * @llbcoexist: protection mode info
1150 *
1151 * This function set protection mode(RTS/CTS) to fw for passed vdev id.
1152 *
1153 * Return: none
1154 */
1155void wma_update_protection_mode(tp_wma_handle wma, uint8_t vdev_id,
1156 uint8_t llbcoexist)
1157{
Govind Singhd76a5b02016-03-08 15:12:14 +05301158 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001159 enum ieee80211_protmode prot_mode;
1160
1161 prot_mode = llbcoexist ? IEEE80211_PROT_CTSONLY : IEEE80211_PROT_NONE;
1162
Govind Singhd76a5b02016-03-08 15:12:14 +05301163 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001164 WMI_VDEV_PARAM_PROTECTION_MODE,
1165 prot_mode);
1166
Govind Singhd76a5b02016-03-08 15:12:14 +05301167 if (QDF_IS_STATUS_ERROR(ret))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001168 WMA_LOGE("Failed to send wmi protection mode cmd");
1169 else
1170 WMA_LOGD("Updated protection mode %d to target", prot_mode);
1171}
1172
1173/**
1174 * wma_update_beacon_interval() - update beacon interval in fw
1175 * @wma: wma handle
1176 * @vdev_id: vdev id
1177 * @beaconInterval: becon interval
1178 *
1179 * Return: none
1180 */
1181static void
1182wma_update_beacon_interval(tp_wma_handle wma, uint8_t vdev_id,
1183 uint16_t beaconInterval)
1184{
Govind Singhd76a5b02016-03-08 15:12:14 +05301185 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001186
Govind Singhd76a5b02016-03-08 15:12:14 +05301187 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001188 WMI_VDEV_PARAM_BEACON_INTERVAL,
1189 beaconInterval);
1190
Govind Singhd76a5b02016-03-08 15:12:14 +05301191 if (QDF_IS_STATUS_ERROR(ret))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001192 WMA_LOGE("Failed to update beacon interval");
1193 else
1194 WMA_LOGI("Updated beacon interval %d for vdev %d",
1195 beaconInterval, vdev_id);
1196}
1197
1198/**
1199 * wma_process_update_beacon_params() - update beacon parameters to target
1200 * @wma: wma handle
1201 * @bcn_params: beacon parameters
1202 *
1203 * Return: none
1204 */
1205void
1206wma_process_update_beacon_params(tp_wma_handle wma,
1207 tUpdateBeaconParams *bcn_params)
1208{
1209 if (!bcn_params) {
1210 WMA_LOGE("bcn_params NULL");
1211 return;
1212 }
1213
1214 if (bcn_params->smeSessionId >= wma->max_bssid) {
1215 WMA_LOGE("Invalid vdev id %d", bcn_params->smeSessionId);
1216 return;
1217 }
1218
1219 if (bcn_params->paramChangeBitmap & PARAM_BCN_INTERVAL_CHANGED) {
1220 wma_update_beacon_interval(wma, bcn_params->smeSessionId,
1221 bcn_params->beaconInterval);
1222 }
1223
1224 if (bcn_params->paramChangeBitmap & PARAM_llBCOEXIST_CHANGED)
1225 wma_update_protection_mode(wma, bcn_params->smeSessionId,
1226 bcn_params->llbCoexist);
1227}
1228
1229/**
1230 * wma_update_cfg_params() - update cfg parameters to target
1231 * @wma: wma handle
1232 * @cfgParam: cfg parameter
1233 *
1234 * Return: none
1235 */
1236void wma_update_cfg_params(tp_wma_handle wma, tSirMsgQ *cfgParam)
1237{
1238 uint8_t vdev_id;
1239 uint32_t param_id;
1240 uint32_t cfg_val;
Govind Singhd76a5b02016-03-08 15:12:14 +05301241 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001242 /* get mac to acess CFG data base */
1243 struct sAniSirGlobal *pmac;
1244
1245 switch (cfgParam->bodyval) {
1246 case WNI_CFG_RTS_THRESHOLD:
1247 param_id = WMI_VDEV_PARAM_RTS_THRESHOLD;
1248 break;
1249 case WNI_CFG_FRAGMENTATION_THRESHOLD:
1250 param_id = WMI_VDEV_PARAM_FRAGMENTATION_THRESHOLD;
1251 break;
1252 default:
1253 WMA_LOGD("Unhandled cfg parameter %d", cfgParam->bodyval);
1254 return;
1255 }
1256
Anurag Chouhan6d760662016-02-20 16:05:43 +05301257 pmac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001258
1259 if (NULL == pmac) {
1260 WMA_LOGE("%s: Failed to get pmac", __func__);
1261 return;
1262 }
1263
1264 if (wlan_cfg_get_int(pmac, (uint16_t) cfgParam->bodyval,
1265 &cfg_val) != eSIR_SUCCESS) {
1266 WMA_LOGE("Failed to get value for CFG PARAMS %d. returning without updating",
1267 cfgParam->bodyval);
1268 return;
1269 }
1270
1271 for (vdev_id = 0; vdev_id < wma->max_bssid; vdev_id++) {
1272 if (wma->interfaces[vdev_id].handle != 0) {
Govind Singhd76a5b02016-03-08 15:12:14 +05301273 ret = wma_vdev_set_param(wma->wmi_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001274 vdev_id, param_id,
1275 cfg_val);
Govind Singhd76a5b02016-03-08 15:12:14 +05301276 if (QDF_IS_STATUS_ERROR(ret))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001277 WMA_LOGE("Update cfg params failed for vdevId %d",
1278 vdev_id);
1279 }
1280 }
1281}
1282
1283/**
1284 * wma_read_cfg_wepkey() - fill key_info for WEP key
1285 * @wma_handle: wma handle
1286 * @key_info: key_info ptr
1287 * @def_key_idx: default key index
1288 * @num_keys: number of keys
1289 *
1290 * This function reads WEP keys from cfg and fills
1291 * up key_info.
1292 *
1293 * Return: none
1294 */
1295static void wma_read_cfg_wepkey(tp_wma_handle wma_handle,
1296 tSirKeys *key_info, uint32_t *def_key_idx,
1297 uint8_t *num_keys)
1298{
1299 tSirRetStatus status;
1300 uint32_t val = SIR_MAC_KEY_LENGTH;
1301 uint8_t i, j;
1302
1303 WMA_LOGD("Reading WEP keys from cfg");
1304 /* NOTE:def_key_idx is initialized to 0 by the caller */
1305 status = wlan_cfg_get_int(wma_handle->mac_context,
1306 WNI_CFG_WEP_DEFAULT_KEYID, def_key_idx);
1307 if (status != eSIR_SUCCESS)
1308 WMA_LOGE("Unable to read default id, defaulting to 0");
1309
1310 for (i = 0, j = 0; i < SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS; i++) {
1311 status = wlan_cfg_get_str(wma_handle->mac_context,
1312 (uint16_t) WNI_CFG_WEP_DEFAULT_KEY_1 +
1313 i, key_info[j].key, &val);
1314 if (status != eSIR_SUCCESS) {
1315 WMA_LOGE("WEP key is not configured at :%d", i);
1316 } else {
1317 key_info[j].keyId = i;
1318 key_info[j].keyLength = (uint16_t) val;
1319 j++;
1320 }
1321 }
1322 *num_keys = j;
1323}
1324
1325/**
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301326 * wma_setup_install_key_cmd() - set key parameters
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001327 * @wma_handle: wma handle
1328 * @key_params: key parameters
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001329 * @mode: op mode
1330 *
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301331 * This function fills structure from information
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001332 * passed in key_params.
1333 *
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301334 * Return: QDF_STATUS_SUCCESS - success
1335 QDF_STATUS_E_FAILURE - failure
1336 QDF_STATUS_E_NOMEM - invalid request
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001337 */
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301338static QDF_STATUS wma_setup_install_key_cmd(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001339 struct wma_set_key_params
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301340 *key_params, uint8_t mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001341{
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301342 struct set_key_params params;
1343 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001344#ifdef WLAN_FEATURE_11W
1345 struct wma_txrx_node *iface = NULL;
1346#endif /* WLAN_FEATURE_11W */
1347 if ((key_params->key_type == eSIR_ED_NONE &&
1348 key_params->key_len) || (key_params->key_type != eSIR_ED_NONE &&
1349 !key_params->key_len)) {
1350 WMA_LOGE("%s:Invalid set key request", __func__);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301351 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001352 }
1353
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301354 params.vdev_id = key_params->vdev_id;
1355 params.key_idx = key_params->key_idx;
1356 qdf_mem_copy(params.peer_mac, key_params->peer_mac, IEEE80211_ADDR_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001357
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301358#ifdef FEATURE_WLAN_WAPI
1359 qdf_mem_set(params.tx_iv, 16, 0);
1360 qdf_mem_set(params.rx_iv, 16, 0);
1361#endif
1362 params.key_txmic_len = 0;
1363 params.key_rxmic_len = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001364
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301365 params.key_flags = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001366 if (key_params->unicast)
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301367 params.key_flags |= PAIRWISE_USAGE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001368 else
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301369 params.key_flags |= GROUP_USAGE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001370
1371 switch (key_params->key_type) {
1372 case eSIR_ED_NONE:
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301373 params.key_cipher = WMI_CIPHER_NONE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001374 break;
1375 case eSIR_ED_WEP40:
1376 case eSIR_ED_WEP104:
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301377 params.key_cipher = WMI_CIPHER_WEP;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001378 if (key_params->unicast &&
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301379 params.key_idx == key_params->def_key_idx) {
Ganesh Kondabattini59a4a952015-11-30 11:55:40 +05301380 WMA_LOGD("STA Mode: cmd->key_flags |= TX_USAGE");
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301381 params.key_flags |= TX_USAGE;
Ganesh Kondabattini59a4a952015-11-30 11:55:40 +05301382 } else if ((mode == wlan_op_mode_ap) &&
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301383 (params.key_idx == key_params->def_key_idx)) {
Ganesh Kondabattini59a4a952015-11-30 11:55:40 +05301384 WMA_LOGD("AP Mode: cmd->key_flags |= TX_USAGE");
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301385 params.key_flags |= TX_USAGE;
Ganesh Kondabattini59a4a952015-11-30 11:55:40 +05301386 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001387 break;
1388 case eSIR_ED_TKIP:
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301389 params.key_txmic_len = WMA_TXMIC_LEN;
1390 params.key_rxmic_len = WMA_RXMIC_LEN;
1391 params.key_cipher = WMI_CIPHER_TKIP;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001392 break;
1393#ifdef FEATURE_WLAN_WAPI
1394#define WPI_IV_LEN 16
1395 case eSIR_ED_WPI:
1396 {
1397 /*initialize receive and transmit IV with default values */
1398 /* **Note: tx_iv must be sent in reverse** */
1399 unsigned char tx_iv[16] = { 0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c,
1400 0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c,
1401 0x36, 0x5c, 0x36, 0x5c};
1402 unsigned char rx_iv[16] = { 0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36,
1403 0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36,
1404 0x5c, 0x36, 0x5c, 0x37};
1405 if (mode == wlan_op_mode_ap) {
1406 /* Authenticator initializes the value of PN as
1407 * 0x5C365C365C365C365C365C365C365C36 for MCastkey Update
1408 */
1409 if (key_params->unicast)
1410 tx_iv[0] = 0x37;
1411
1412 rx_iv[WPI_IV_LEN - 1] = 0x36;
1413 } else {
1414 if (!key_params->unicast)
1415 rx_iv[WPI_IV_LEN - 1] = 0x36;
1416 }
1417
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301418 params.key_txmic_len = WMA_TXMIC_LEN;
1419 params.key_rxmic_len = WMA_RXMIC_LEN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001420
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301421 qdf_mem_copy(&params.rx_iv, &rx_iv,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001422 WPI_IV_LEN);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301423 qdf_mem_copy(&params.tx_iv, &tx_iv,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001424 WPI_IV_LEN);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301425 params.key_cipher = WMI_CIPHER_WAPI;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001426 break;
1427 }
1428#endif /* FEATURE_WLAN_WAPI */
1429 case eSIR_ED_CCMP:
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301430 params.key_cipher = WMI_CIPHER_AES_CCM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001431 break;
1432#ifdef WLAN_FEATURE_11W
1433 case eSIR_ED_AES_128_CMAC:
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301434 params.key_cipher = WMI_CIPHER_AES_CMAC;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001435 break;
1436#endif /* WLAN_FEATURE_11W */
1437 default:
1438 /* TODO: MFP ? */
1439 WMA_LOGE("%s:Invalid encryption type:%d", __func__,
1440 key_params->key_type);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301441 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001442 }
1443
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001444#ifdef BIG_ENDIAN_HOST
1445 {
1446 /* for big endian host, copy engine byte_swap is enabled
1447 * But the key data content is in network byte order
1448 * Need to byte swap the key data content - so when copy engine
1449 * does byte_swap - target gets key_data content in the correct
1450 * order.
1451 */
1452 int8_t i;
1453 uint32_t *destp, *srcp;
1454
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301455 destp = (uint32_t *) params.key_data;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001456 srcp = (uint32_t *) key_params->key_data;
1457 for (i = 0;
1458 i < roundup(key_params->key_len, sizeof(uint32_t)) / 4;
1459 i++) {
1460 *destp = le32_to_cpu(*srcp);
1461 destp++;
1462 srcp++;
1463 }
1464 }
1465#else
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301466 qdf_mem_copy((void *)params.key_data,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001467 (const void *)key_params->key_data, key_params->key_len);
1468#endif /* BIG_ENDIAN_HOST */
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301469 params.key_len = key_params->key_len;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001470
1471#ifdef WLAN_FEATURE_11W
1472 if (key_params->key_type == eSIR_ED_AES_128_CMAC) {
1473 iface = &wma_handle->interfaces[key_params->vdev_id];
1474 if (iface) {
1475 iface->key.key_length = key_params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301476 qdf_mem_copy(iface->key.key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001477 (const void *)key_params->key_data,
1478 iface->key.key_length);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301479 if ((params.key_idx == WMA_IGTK_KEY_INDEX_4) ||
1480 (params.key_idx == WMA_IGTK_KEY_INDEX_5))
1481 qdf_mem_zero(iface->key.key_id[params.key_idx -
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001482 WMA_IGTK_KEY_INDEX_4].ipn,
1483 CMAC_IPN_LEN);
1484 }
1485 }
1486#endif /* WLAN_FEATURE_11W */
1487
1488 WMA_LOGD("Key setup : vdev_id %d key_idx %d key_type %d key_len %d"
1489 " unicast %d peer_mac %pM def_key_idx %d", key_params->vdev_id,
1490 key_params->key_idx, key_params->key_type, key_params->key_len,
1491 key_params->unicast, key_params->peer_mac,
1492 key_params->def_key_idx);
1493
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301494 status = wmi_unified_setup_install_key_cmd(wma_handle->wmi_handle,
1495 &params);
1496
1497 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001498}
1499
1500/**
1501 * wma_set_bsskey() - set encryption key to fw.
1502 * @wma_handle: wma handle
1503 * @key_info: key info
1504 *
1505 * Return: none
1506 */
1507void wma_set_bsskey(tp_wma_handle wma_handle, tpSetBssKeyParams key_info)
1508{
1509 struct wma_set_key_params key_params;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301510 QDF_STATUS status = QDF_STATUS_SUCCESS;
1511 uint32_t i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001512 uint32_t def_key_idx = 0;
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001513 uint32_t wlan_opmode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001514 ol_txrx_vdev_handle txrx_vdev;
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001515 uint8_t *mac_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001516
1517 WMA_LOGD("BSS key setup");
1518 txrx_vdev = wma_find_vdev_by_id(wma_handle, key_info->smesessionId);
1519 if (!txrx_vdev) {
1520 WMA_LOGE("%s:Invalid vdev handle", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301521 key_info->status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001522 goto out;
1523 }
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001524 wlan_opmode = ol_txrx_get_opmode(txrx_vdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001525
1526 /*
1527 * For IBSS, WMI expects the BSS key to be set per peer key
1528 * So cache the BSS key in the wma_handle and re-use it when the
1529 * STA key is been setup for a peer
1530 */
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001531 if (wlan_op_mode_ibss == wlan_opmode) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301532 key_info->status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001533 if (wma_handle->ibss_started > 0)
1534 goto out;
1535 WMA_LOGD("Caching IBSS Key");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301536 qdf_mem_copy(&wma_handle->ibsskey_info, key_info,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001537 sizeof(tSetBssKeyParams));
1538 }
1539
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301540 qdf_mem_set(&key_params, sizeof(key_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001541 key_params.vdev_id = key_info->smesessionId;
1542 key_params.key_type = key_info->encType;
1543 key_params.singl_tid_rc = key_info->singleTidRc;
1544 key_params.unicast = false;
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001545 if (wlan_opmode == wlan_op_mode_sta) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301546 qdf_mem_copy(key_params.peer_mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001547 wma_handle->interfaces[key_info->smesessionId].bssid,
1548 IEEE80211_ADDR_LEN);
1549 } else {
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001550 mac_addr = ol_txrx_get_vdev_mac_addr(txrx_vdev);
1551 if (mac_addr == NULL) {
1552 WMA_LOGE("%s: mac_addr is NULL for vdev with id %d",
1553 __func__, key_info->smesessionId);
1554 goto out;
1555 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001556 /* vdev mac address will be passed for all other modes */
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001557 qdf_mem_copy(key_params.peer_mac, mac_addr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001558 IEEE80211_ADDR_LEN);
1559 WMA_LOGA("BSS Key setup with vdev_mac %pM\n",
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001560 mac_addr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001561 }
1562
1563 if (key_info->numKeys == 0 &&
1564 (key_info->encType == eSIR_ED_WEP40 ||
1565 key_info->encType == eSIR_ED_WEP104)) {
1566 wma_read_cfg_wepkey(wma_handle, key_info->key,
1567 &def_key_idx, &key_info->numKeys);
1568 }
1569
1570 for (i = 0; i < key_info->numKeys; i++) {
1571 if (key_params.key_type != eSIR_ED_NONE &&
1572 !key_info->key[i].keyLength)
1573 continue;
1574 if (key_info->encType == eSIR_ED_WPI) {
1575 key_params.key_idx = key_info->key[i].keyId;
1576 key_params.def_key_idx = key_info->key[i].keyId;
1577 } else
1578 key_params.key_idx = key_info->key[i].keyId;
1579
1580 key_params.key_len = key_info->key[i].keyLength;
1581 if (key_info->encType == eSIR_ED_TKIP) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301582 qdf_mem_copy(key_params.key_data,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001583 key_info->key[i].key, 16);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301584 qdf_mem_copy(&key_params.key_data[16],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001585 &key_info->key[i].key[24], 8);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301586 qdf_mem_copy(&key_params.key_data[24],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001587 &key_info->key[i].key[16], 8);
1588 } else
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301589 qdf_mem_copy((void *)key_params.key_data,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001590 (const void *)key_info->key[i].key,
1591 key_info->key[i].keyLength);
1592
1593 WMA_LOGD("%s: bss key[%d] length %d", __func__, i,
1594 key_info->key[i].keyLength);
1595
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301596 status = wma_setup_install_key_cmd(wma_handle, &key_params,
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001597 wlan_opmode);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301598 if (status == QDF_STATUS_E_NOMEM) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001599 WMA_LOGE("%s:Failed to setup install key buf",
1600 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301601 key_info->status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001602 goto out;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301603 } else if (status == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001604 WMA_LOGE("%s:Failed to send install key command",
1605 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301606 key_info->status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001607 goto out;
1608 }
1609 }
1610
1611 wma_handle->ibss_started++;
1612 /* TODO: Should we wait till we get HTT_T2H_MSG_TYPE_SEC_IND? */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301613 key_info->status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001614
1615out:
1616 wma_send_msg(wma_handle, WMA_SET_BSSKEY_RSP, (void *)key_info, 0);
1617}
1618
1619#ifdef QCA_IBSS_SUPPORT
1620/**
1621 * wma_calc_ibss_heart_beat_timer() - calculate IBSS heart beat timer
1622 * @peer_num: number of peers
1623 *
1624 * Return: heart beat timer value
1625 */
1626static uint16_t wma_calc_ibss_heart_beat_timer(int16_t peer_num)
1627{
1628 /* heart beat timer value look-up table */
1629 /* entry index : (the number of currently connected peers) - 1
1630 entry value : the heart time threshold value in seconds for
1631 detecting ibss peer departure */
1632 static const uint16_t heart_beat_timer[MAX_IBSS_PEERS] = {
1633 4, 4, 4, 4, 4, 4, 4, 4,
1634 8, 8, 8, 8, 8, 8, 8, 8,
1635 12, 12, 12, 12, 12, 12, 12, 12,
1636 16, 16, 16, 16, 16, 16, 16, 16
1637 };
1638
1639 if (peer_num < 1 || peer_num > MAX_IBSS_PEERS)
1640 return 0;
1641
1642 return heart_beat_timer[peer_num - 1];
1643
1644}
1645
1646/**
1647 * wma_adjust_ibss_heart_beat_timer() - set ibss heart beat timer in fw.
1648 * @wma: wma handle
1649 * @vdev_id: vdev id
1650 * @peer_num_delta: peer number delta value
1651 *
1652 * Return: none
1653 */
1654void wma_adjust_ibss_heart_beat_timer(tp_wma_handle wma,
1655 uint8_t vdev_id,
1656 int8_t peer_num_delta)
1657{
1658 ol_txrx_vdev_handle vdev;
1659 int16_t new_peer_num;
1660 uint16_t new_timer_value_sec;
1661 uint32_t new_timer_value_ms;
Govind Singhd76a5b02016-03-08 15:12:14 +05301662 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001663
1664 if (peer_num_delta != 1 && peer_num_delta != -1) {
1665 WMA_LOGE("Invalid peer_num_delta value %d", peer_num_delta);
1666 return;
1667 }
1668
1669 vdev = wma_find_vdev_by_id(wma, vdev_id);
1670 if (!vdev) {
1671 WMA_LOGE("vdev not found : vdev_id %d", vdev_id);
1672 return;
1673 }
1674
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001675 /* adjust peer numbers */
1676 new_peer_num = ol_txrx_update_ibss_add_peer_num_of_vdev(vdev,
1677 peer_num_delta);
1678 if (OL_TXRX_INVALID_NUM_PEERS == new_peer_num) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001679 WMA_LOGE("new peer num %d out of valid boundary", new_peer_num);
1680 return;
1681 }
1682
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001683 /* reset timer value if all peers departed */
1684 if (new_peer_num == 0) {
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001685 ol_txrx_set_ibss_vdev_heart_beat_timer(vdev, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001686 return;
1687 }
1688
1689 /* calculate new timer value */
1690 new_timer_value_sec = wma_calc_ibss_heart_beat_timer(new_peer_num);
1691 if (new_timer_value_sec == 0) {
1692 WMA_LOGE("timer value %d is invalid for peer number %d",
1693 new_timer_value_sec, new_peer_num);
1694 return;
1695 }
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001696 if (new_timer_value_sec ==
1697 ol_txrx_set_ibss_vdev_heart_beat_timer(vdev, new_timer_value_sec)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001698 WMA_LOGD("timer value %d stays same, no need to notify target",
1699 new_timer_value_sec);
1700 return;
1701 }
1702
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001703 new_timer_value_ms = ((uint32_t) new_timer_value_sec) * 1000;
1704
Govind Singhd76a5b02016-03-08 15:12:14 +05301705 status = wma_vdev_set_param(wma->wmi_handle, vdev_id,
1706 WMI_VDEV_PARAM_IBSS_MAX_BCN_LOST_MS,
1707 new_timer_value_ms);
1708 if (QDF_IS_STATUS_ERROR(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001709 WMA_LOGE("Failed to set IBSS link monitoring timer value");
1710 return;
1711 }
1712
1713 WMA_LOGD("Set IBSS link monitor timer: peer_num = %d timer_value = %d",
1714 new_peer_num, new_timer_value_ms);
1715}
1716
1717#endif /* QCA_IBSS_SUPPORT */
1718/**
1719 * wma_set_ibsskey_helper() - cached IBSS key in wma handle
1720 * @wma_handle: wma handle
1721 * @key_info: set bss key info
1722 * @peerMacAddr: peer mac address
1723 *
1724 * Return: none
1725 */
1726static void wma_set_ibsskey_helper(tp_wma_handle wma_handle,
1727 tpSetBssKeyParams key_info,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301728 struct qdf_mac_addr peer_macaddr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001729{
1730 struct wma_set_key_params key_params;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301731 QDF_STATUS status = QDF_STATUS_SUCCESS;
1732 uint32_t i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001733 uint32_t def_key_idx = 0;
1734 ol_txrx_vdev_handle txrx_vdev;
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001735 int opmode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001736
1737 WMA_LOGD("BSS key setup for peer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001738 txrx_vdev = wma_find_vdev_by_id(wma_handle, key_info->smesessionId);
1739 if (!txrx_vdev) {
1740 WMA_LOGE("%s:Invalid vdev handle", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301741 key_info->status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001742 return;
1743 }
1744
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301745 qdf_mem_set(&key_params, sizeof(key_params), 0);
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001746 opmode = ol_txrx_get_opmode(txrx_vdev);
1747 qdf_mem_set(&key_params, sizeof(key_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001748 key_params.vdev_id = key_info->smesessionId;
1749 key_params.key_type = key_info->encType;
1750 key_params.singl_tid_rc = key_info->singleTidRc;
1751 key_params.unicast = false;
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001752 ASSERT(wlan_op_mode_ibss == opmode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001753
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301754 qdf_mem_copy(key_params.peer_mac, peer_macaddr.bytes,
Srinivas Girigowdad5965c42015-12-04 13:43:16 -08001755 IEEE80211_ADDR_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001756
1757 if (key_info->numKeys == 0 &&
1758 (key_info->encType == eSIR_ED_WEP40 ||
1759 key_info->encType == eSIR_ED_WEP104)) {
1760 wma_read_cfg_wepkey(wma_handle, key_info->key,
1761 &def_key_idx, &key_info->numKeys);
1762 }
1763
1764 for (i = 0; i < key_info->numKeys; i++) {
1765 if (key_params.key_type != eSIR_ED_NONE &&
1766 !key_info->key[i].keyLength)
1767 continue;
1768 key_params.key_idx = key_info->key[i].keyId;
1769 key_params.key_len = key_info->key[i].keyLength;
1770 if (key_info->encType == eSIR_ED_TKIP) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301771 qdf_mem_copy(key_params.key_data,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001772 key_info->key[i].key, 16);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301773 qdf_mem_copy(&key_params.key_data[16],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001774 &key_info->key[i].key[24], 8);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301775 qdf_mem_copy(&key_params.key_data[24],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001776 &key_info->key[i].key[16], 8);
1777 } else
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301778 qdf_mem_copy((void *)key_params.key_data,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001779 (const void *)key_info->key[i].key,
1780 key_info->key[i].keyLength);
1781
1782 WMA_LOGD("%s: peer bcast key[%d] length %d", __func__, i,
1783 key_info->key[i].keyLength);
1784
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301785 status = wma_setup_install_key_cmd(wma_handle, &key_params,
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001786 opmode);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301787 if (status == QDF_STATUS_E_NOMEM) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001788 WMA_LOGE("%s:Failed to setup install key buf",
1789 __func__);
1790 return;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301791 } else if (status == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001792 WMA_LOGE("%s:Failed to send install key command",
1793 __func__);
1794 }
1795 }
1796}
1797
1798/**
1799 * wma_set_stakey() - set encryption key
1800 * @wma_handle: wma handle
1801 * @key_info: station key info
1802 *
1803 * This function sets encryption key for WEP/WPA/WPA2
1804 * encryption mode in firmware and send response to upper layer.
1805 *
1806 * Return: none
1807 */
1808void wma_set_stakey(tp_wma_handle wma_handle, tpSetStaKeyParams key_info)
1809{
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301810 int32_t i;
1811 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001812 ol_txrx_pdev_handle txrx_pdev;
1813 ol_txrx_vdev_handle txrx_vdev;
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001814 ol_txrx_peer_handle peer;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001815 uint8_t num_keys = 0, peer_id;
1816 struct wma_set_key_params key_params;
1817 uint32_t def_key_idx = 0;
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001818 int opmode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001819
1820 WMA_LOGD("STA key setup");
1821
1822 /* Get the txRx Pdev handle */
Anurag Chouhan6d760662016-02-20 16:05:43 +05301823 txrx_pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001824 if (!txrx_pdev) {
1825 WMA_LOGE("%s:Invalid txrx pdev handle", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301826 key_info->status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001827 goto out;
1828 }
1829
Srinivas Girigowdad5965c42015-12-04 13:43:16 -08001830 peer = ol_txrx_find_peer_by_addr(txrx_pdev,
1831 key_info->peer_macaddr.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001832 &peer_id);
1833 if (!peer) {
1834 WMA_LOGE("%s:Invalid peer for key setting", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301835 key_info->status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001836 goto out;
1837 }
1838
1839 txrx_vdev = wma_find_vdev_by_id(wma_handle, key_info->smesessionId);
1840 if (!txrx_vdev) {
1841 WMA_LOGE("%s:TxRx Vdev Handle is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301842 key_info->status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001843 goto out;
1844 }
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001845 opmode = ol_txrx_get_opmode(txrx_vdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001846
1847 if (key_info->defWEPIdx == WMA_INVALID_KEY_IDX &&
1848 (key_info->encType == eSIR_ED_WEP40 ||
1849 key_info->encType == eSIR_ED_WEP104) &&
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001850 opmode != wlan_op_mode_ap) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001851 wma_read_cfg_wepkey(wma_handle, key_info->key,
1852 &def_key_idx, &num_keys);
1853 key_info->defWEPIdx = def_key_idx;
1854 } else {
1855 num_keys = SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS;
1856 if (key_info->encType != eSIR_ED_NONE) {
1857 for (i = 0; i < num_keys; i++) {
1858 if (key_info->key[i].keyDirection ==
1859 eSIR_TX_DEFAULT) {
1860 key_info->defWEPIdx = i;
1861 break;
1862 }
1863 }
1864 }
1865 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301866 qdf_mem_set(&key_params, sizeof(key_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001867 key_params.vdev_id = key_info->smesessionId;
1868 key_params.key_type = key_info->encType;
1869 key_params.singl_tid_rc = key_info->singleTidRc;
1870 key_params.unicast = true;
1871 key_params.def_key_idx = key_info->defWEPIdx;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301872 qdf_mem_copy((void *)key_params.peer_mac,
Srinivas Girigowdad5965c42015-12-04 13:43:16 -08001873 (const void *)key_info->peer_macaddr.bytes,
1874 IEEE80211_ADDR_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001875 for (i = 0; i < num_keys; i++) {
1876 if (key_params.key_type != eSIR_ED_NONE &&
1877 !key_info->key[i].keyLength)
1878 continue;
1879 if (key_info->encType == eSIR_ED_TKIP) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301880 qdf_mem_copy(key_params.key_data,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001881 key_info->key[i].key, 16);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301882 qdf_mem_copy(&key_params.key_data[16],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001883 &key_info->key[i].key[24], 8);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301884 qdf_mem_copy(&key_params.key_data[24],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001885 &key_info->key[i].key[16], 8);
1886 } else
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301887 qdf_mem_copy(key_params.key_data, key_info->key[i].key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001888 key_info->key[i].keyLength);
1889 if (key_info->encType == eSIR_ED_WPI) {
1890 key_params.key_idx = key_info->key[i].keyId;
1891 key_params.def_key_idx = key_info->key[i].keyId;
1892 } else
1893 key_params.key_idx = i;
1894
1895 key_params.key_len = key_info->key[i].keyLength;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301896 status = wma_setup_install_key_cmd(wma_handle, &key_params,
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001897 opmode);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301898 if (status == QDF_STATUS_E_NOMEM) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001899 WMA_LOGE("%s:Failed to setup install key buf",
1900 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301901 key_info->status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001902 goto out;
1903 }
1904
1905 WMA_LOGD("%s: peer unicast key[%d] %d ", __func__, i,
1906 key_info->key[i].keyLength);
1907
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301908 if (status == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001909 WMA_LOGE("%s:Failed to send install key command",
1910 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301911 key_info->status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001912 goto out;
1913 }
1914 }
1915
1916 /* In IBSS mode, set the BSS KEY for this peer
1917 * BSS key is supposed to be cache into wma_handle
1918 */
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001919 if (wlan_op_mode_ibss == opmode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001920 wma_set_ibsskey_helper(wma_handle, &wma_handle->ibsskey_info,
Srinivas Girigowdad5965c42015-12-04 13:43:16 -08001921 key_info->peer_macaddr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001922 }
1923
1924 /* TODO: Should we wait till we get HTT_T2H_MSG_TYPE_SEC_IND? */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301925 key_info->status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001926out:
1927 if (key_info->sendRsp)
1928 wma_send_msg(wma_handle, WMA_SET_STAKEY_RSP, (void *)key_info,
1929 0);
1930}
1931
1932/**
1933 * wma_process_update_edca_param_req() - update EDCA params
1934 * @handle: wma handle
1935 * @edca_params: edca parameters
1936 *
1937 * This function updates EDCA parameters to the target
1938 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05301939 * Return: QDF Status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001940 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301941QDF_STATUS wma_process_update_edca_param_req(WMA_HANDLE handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001942 tEdcaParams *edca_params)
1943{
1944 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301945 wmi_wmm_vparams wmm_param[WME_NUM_AC];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001946 tSirMacEdcaParamRecord *edca_record;
1947 int ac;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001948 ol_txrx_pdev_handle pdev;
1949 struct ol_tx_wmm_param_t ol_tx_wmm_param;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301950 uint8_t vdev_id;
1951 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001952
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301953 vdev_id = edca_params->bssIdx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001954
1955 for (ac = 0; ac < WME_NUM_AC; ac++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001956 switch (ac) {
1957 case WME_AC_BE:
1958 edca_record = &edca_params->acbe;
1959 break;
1960 case WME_AC_BK:
1961 edca_record = &edca_params->acbk;
1962 break;
1963 case WME_AC_VI:
1964 edca_record = &edca_params->acvi;
1965 break;
1966 case WME_AC_VO:
1967 edca_record = &edca_params->acvo;
1968 break;
1969 default:
1970 goto fail;
1971 }
1972
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301973 wma_update_edca_params_for_ac(edca_record, &wmm_param[ac], ac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001974
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301975 ol_tx_wmm_param.ac[ac].aifs = wmm_param[ac].aifs;
1976 ol_tx_wmm_param.ac[ac].cwmin = wmm_param[ac].cwmin;
1977 ol_tx_wmm_param.ac[ac].cwmax = wmm_param[ac].cwmax;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001978 }
1979
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301980 status = wmi_unified_process_update_edca_param(wma_handle->wmi_handle,
1981 vdev_id, wmm_param);
1982 if (status == QDF_STATUS_E_NOMEM)
1983 return status;
1984 else if (status == QDF_STATUS_E_FAILURE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001985 goto fail;
1986
Anurag Chouhan6d760662016-02-20 16:05:43 +05301987 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Himanshu Agarwal94045e42015-10-19 19:16:19 +05301988 if (pdev)
1989 ol_txrx_set_wmm_param(pdev, ol_tx_wmm_param);
1990 else
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301991 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001992
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301993 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001994
1995fail:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001996 WMA_LOGE("%s: Failed to set WMM Paremeters", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301997 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001998}
1999
2000/**
2001 * wmi_unified_probe_rsp_tmpl_send() - send probe response template to fw
2002 * @wma: wma handle
2003 * @vdev_id: vdev id
2004 * @probe_rsp_info: probe response info
2005 *
2006 * Return: 0 for success or error code
2007 */
2008static int wmi_unified_probe_rsp_tmpl_send(tp_wma_handle wma,
2009 uint8_t vdev_id,
2010 tpSendProbeRespParams probe_rsp_info)
2011{
Himanshu Agarwal009f1572016-03-09 17:26:02 +05302012 uint8_t *frm;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002013 uint64_t adjusted_tsf_le;
2014 struct ieee80211_frame *wh;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05302015 struct wmi_probe_resp_params params;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002016
2017 WMA_LOGD(FL("Send probe response template for vdev %d"), vdev_id);
2018
2019 frm = probe_rsp_info->pProbeRespTemplate;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05302020
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002021 /*
2022 * Make the TSF offset negative so probe response in the same
2023 * staggered batch have the same TSF.
2024 */
2025 adjusted_tsf_le = cpu_to_le64(0ULL -
2026 wma->interfaces[vdev_id].tsfadjust);
2027 /* Update the timstamp in the probe response buffer with adjusted TSF */
2028 wh = (struct ieee80211_frame *)frm;
2029 A_MEMCPY(&wh[1], &adjusted_tsf_le, sizeof(adjusted_tsf_le));
2030
Himanshu Agarwal009f1572016-03-09 17:26:02 +05302031 params.pProbeRespTemplate = probe_rsp_info->pProbeRespTemplate;
2032 params.probeRespTemplateLen = probe_rsp_info->probeRespTemplateLen;
2033 qdf_mem_copy(params.bssId, probe_rsp_info->bssId,
Krunal Soniab793342016-04-22 18:43:20 -07002034 IEEE80211_ADDR_LEN);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05302035 qdf_mem_copy(params.ucProxyProbeReqValidIEBmap,
2036 probe_rsp_info->ucProxyProbeReqValidIEBmap,
2037 8 * sizeof(uint32_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002038
Himanshu Agarwal009f1572016-03-09 17:26:02 +05302039 return wmi_unified_probe_rsp_tmpl_send_cmd(wma->wmi_handle, vdev_id,
2040 &params, frm);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002041}
2042
2043/**
Govind Singh61ad2622016-02-22 17:25:02 +05302044 * wma_unified_bcn_tmpl_send() - send beacon template to fw
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002045 * @wma:wma handle
2046 * @vdev_id: vdev id
2047 * @bcn_info: beacon info
2048 * @bytes_to_strip: bytes to strip
2049 *
Govind Singh61ad2622016-02-22 17:25:02 +05302050 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002051 */
Govind Singh61ad2622016-02-22 17:25:02 +05302052static QDF_STATUS wma_unified_bcn_tmpl_send(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002053 uint8_t vdev_id,
Govind Singh61ad2622016-02-22 17:25:02 +05302054 const tpSendbeaconParams bcn_info,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002055 uint8_t bytes_to_strip)
2056{
Govind Singh61ad2622016-02-22 17:25:02 +05302057 struct beacon_params params = {0};
2058 uint32_t tmpl_len, tmpl_len_aligned;
2059 uint8_t *frm;
2060 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002061 uint8_t *p2p_ie;
2062 uint16_t p2p_ie_len = 0;
2063 uint64_t adjusted_tsf_le;
2064 struct ieee80211_frame *wh;
2065
2066 WMA_LOGD("Send beacon template for vdev %d", vdev_id);
2067
2068 if (bcn_info->p2pIeOffset) {
2069 p2p_ie = bcn_info->beacon + bcn_info->p2pIeOffset;
2070 p2p_ie_len = (uint16_t) p2p_ie[1] + 2;
2071 }
2072
2073 /*
2074 * XXX: The first byte of beacon buffer contains beacon length
2075 * only when UMAC in sending the beacon template. In othercases
2076 * (ex: from tbtt update) beacon length is read from beacon
2077 * information.
2078 */
2079 if (bytes_to_strip)
2080 tmpl_len = *(uint32_t *) &bcn_info->beacon[0];
2081 else
2082 tmpl_len = bcn_info->beaconLength;
2083 if (p2p_ie_len) {
2084 tmpl_len -= (uint32_t) p2p_ie_len;
2085 }
2086
2087 frm = bcn_info->beacon + bytes_to_strip;
2088 tmpl_len_aligned = roundup(tmpl_len, sizeof(A_UINT32));
2089 /*
2090 * Make the TSF offset negative so beacons in the same
2091 * staggered batch have the same TSF.
2092 */
2093 adjusted_tsf_le = cpu_to_le64(0ULL -
2094 wma->interfaces[vdev_id].tsfadjust);
2095 /* Update the timstamp in the beacon buffer with adjusted TSF */
2096 wh = (struct ieee80211_frame *)frm;
2097 A_MEMCPY(&wh[1], &adjusted_tsf_le, sizeof(adjusted_tsf_le));
2098
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002099
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002100
Govind Singh61ad2622016-02-22 17:25:02 +05302101 params.vdev_id = vdev_id;
2102 params.tim_ie_offset = bcn_info->timIeOffset - bytes_to_strip;
2103 params.tmpl_len = tmpl_len;
2104 params.frm = frm;
2105 params.tmpl_len_aligned = tmpl_len_aligned;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002106
Govind Singh61ad2622016-02-22 17:25:02 +05302107 ret = wmi_unified_beacon_send_cmd(wma->wmi_handle,
2108 &params);
2109 if (QDF_IS_STATUS_ERROR(ret)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002110 WMA_LOGE("%s: Failed to send bcn tmpl: %d", __func__, ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002111 }
2112
2113 return ret;
2114}
2115
2116/**
2117 * wma_store_bcn_tmpl() - store beacon template
2118 * @wma: wma handle
2119 * @vdev_id: vdev id
2120 * @bcn_info: beacon params
2121 *
2122 * This function stores beacon template locally.
2123 * This will send to target on the reception of
2124 * SWBA event.
2125 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302126 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002127 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302128QDF_STATUS wma_store_bcn_tmpl(tp_wma_handle wma, uint8_t vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002129 tpSendbeaconParams bcn_info)
2130{
2131 struct beacon_info *bcn;
2132 uint32_t len;
2133 uint8_t *bcn_payload;
2134 struct beacon_tim_ie *tim_ie;
2135
2136 bcn = wma->interfaces[vdev_id].beacon;
2137 if (!bcn || !bcn->buf) {
2138 WMA_LOGE("%s: Memory is not allocated to hold bcn template",
2139 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302140 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002141 }
2142
2143 len = *(u32 *) &bcn_info->beacon[0];
2144 if (len > WMA_BCN_BUF_MAX_SIZE) {
2145 WMA_LOGE("%s: Received beacon len %d exceeding max limit %d",
2146 __func__, len, WMA_BCN_BUF_MAX_SIZE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302147 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002148 }
2149 WMA_LOGD("%s: Storing received beacon template buf to local buffer",
2150 __func__);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302151 qdf_spin_lock_bh(&bcn->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002152
2153 /*
2154 * Copy received beacon template content in local buffer.
2155 * this will be send to target on the reception of SWBA
2156 * event from target.
2157 */
Nirav Shahcbc6d722016-03-01 16:24:53 +05302158 qdf_nbuf_trim_tail(bcn->buf, qdf_nbuf_len(bcn->buf));
2159 memcpy(qdf_nbuf_data(bcn->buf),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002160 bcn_info->beacon + 4 /* Exclude beacon length field */,
2161 len);
2162 if (bcn_info->timIeOffset > 3) {
2163 bcn->tim_ie_offset = bcn_info->timIeOffset - 4;
2164 } else {
2165 bcn->tim_ie_offset = bcn_info->timIeOffset;
2166 }
2167
2168 if (bcn_info->p2pIeOffset > 3) {
2169 bcn->p2p_ie_offset = bcn_info->p2pIeOffset - 4;
2170 } else {
2171 bcn->p2p_ie_offset = bcn_info->p2pIeOffset;
2172 }
Nirav Shahcbc6d722016-03-01 16:24:53 +05302173 bcn_payload = qdf_nbuf_data(bcn->buf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002174 if (bcn->tim_ie_offset) {
2175 tim_ie =
2176 (struct beacon_tim_ie *)(&bcn_payload[bcn->tim_ie_offset]);
2177 /*
2178 * Intial Value of bcn->dtim_count will be 0.
2179 * But if the beacon gets updated then current dtim
2180 * count will be restored
2181 */
2182 tim_ie->dtim_count = bcn->dtim_count;
2183 tim_ie->tim_bitctl = 0;
2184 }
2185
Nirav Shahcbc6d722016-03-01 16:24:53 +05302186 qdf_nbuf_put_tail(bcn->buf, len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002187 bcn->len = len;
2188
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302189 qdf_spin_unlock_bh(&bcn->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002190
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302191 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002192}
2193
2194/**
2195 * wma_tbttoffset_update_event_handler() - tbtt offset update handler
2196 * @handle: wma handle
2197 * @event: event buffer
2198 * @len: data length
2199 *
2200 * Return: 0 for success or error code
2201 */
2202int wma_tbttoffset_update_event_handler(void *handle, uint8_t *event,
2203 uint32_t len)
2204{
2205 tp_wma_handle wma = (tp_wma_handle) handle;
2206 WMI_TBTTOFFSET_UPDATE_EVENTID_param_tlvs *param_buf;
2207 wmi_tbtt_offset_event_fixed_param *tbtt_offset_event;
2208 struct wma_txrx_node *intf;
2209 struct beacon_info *bcn;
2210 tSendbeaconParams bcn_info;
2211 uint32_t *adjusted_tsf = NULL;
2212 uint32_t if_id = 0, vdev_map;
2213
2214 if (!wma) {
2215 WMA_LOGE("Invalid wma handle");
2216 return -EINVAL;
2217 }
2218
2219 param_buf = (WMI_TBTTOFFSET_UPDATE_EVENTID_param_tlvs *) event;
2220 if (!param_buf) {
2221 WMA_LOGE("Invalid tbtt update event buffer");
2222 return -EINVAL;
2223 }
2224
2225 tbtt_offset_event = param_buf->fixed_param;
2226 intf = wma->interfaces;
2227 vdev_map = tbtt_offset_event->vdev_map;
2228 adjusted_tsf = param_buf->tbttoffset_list;
2229 if (!adjusted_tsf) {
2230 WMA_LOGE("%s: Invalid adjusted_tsf", __func__);
2231 return -EINVAL;
2232 }
2233
2234 for (; (vdev_map); vdev_map >>= 1, if_id++) {
2235 if (!(vdev_map & 0x1) || (!(intf[if_id].handle)))
2236 continue;
2237
2238 bcn = intf[if_id].beacon;
2239 if (!bcn) {
2240 WMA_LOGE("%s: Invalid beacon", __func__);
2241 return -EINVAL;
2242 }
2243 if (!bcn->buf) {
2244 WMA_LOGE("%s: Invalid beacon buffer", __func__);
2245 return -EINVAL;
2246 }
2247 /* Save the adjusted TSF */
2248 intf[if_id].tsfadjust = adjusted_tsf[if_id];
2249
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302250 qdf_spin_lock_bh(&bcn->lock);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302251 qdf_mem_zero(&bcn_info, sizeof(bcn_info));
Nirav Shahcbc6d722016-03-01 16:24:53 +05302252 bcn_info.beacon = qdf_nbuf_data(bcn->buf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002253 bcn_info.p2pIeOffset = bcn->p2p_ie_offset;
2254 bcn_info.beaconLength = bcn->len;
2255 bcn_info.timIeOffset = bcn->tim_ie_offset;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302256 qdf_spin_unlock_bh(&bcn->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002257
2258 /* Update beacon template in firmware */
Govind Singh61ad2622016-02-22 17:25:02 +05302259 wma_unified_bcn_tmpl_send(wma, if_id, &bcn_info, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002260 }
2261 return 0;
2262}
2263
2264/**
2265 * wma_p2p_go_set_beacon_ie() - set beacon IE for p2p go
2266 * @wma_handle: wma handle
2267 * @vdev_id: vdev id
2268 * @p2pIe: p2p IE
2269 *
2270 * Return: 0 for success or error code
2271 */
2272static int wma_p2p_go_set_beacon_ie(t_wma_handle *wma_handle,
2273 A_UINT32 vdev_id, uint8_t *p2pIe)
2274{
Himanshu Agarwal009f1572016-03-09 17:26:02 +05302275 if (!wma_handle) {
2276 WMA_LOGE("%s: wma handle is NULL", __func__);
2277 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002278 }
2279
Himanshu Agarwal009f1572016-03-09 17:26:02 +05302280 return wmi_unified_p2p_go_set_beacon_ie_cmd(wma_handle->wmi_handle,
2281 vdev_id, p2pIe);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002282}
2283
2284/**
2285 * wma_send_probe_rsp_tmpl() - send probe resp template
2286 * @wma: wma handle
2287 * @probe_rsp_info: probe response info
2288 *
2289 * This funciton sends probe response template to fw which
2290 * firmware will use in case of probe response offload.
2291 *
2292 * Return: none
2293 */
2294void wma_send_probe_rsp_tmpl(tp_wma_handle wma,
2295 tpSendProbeRespParams probe_rsp_info)
2296{
2297 ol_txrx_vdev_handle vdev;
2298 uint8_t vdev_id;
2299 tpAniProbeRspStruct probe_rsp;
2300
2301 if (!probe_rsp_info) {
2302 WMA_LOGE(FL("probe_rsp_info is NULL"));
2303 return;
2304 }
2305
2306 probe_rsp = (tpAniProbeRspStruct) (probe_rsp_info->pProbeRespTemplate);
2307 if (!probe_rsp) {
2308 WMA_LOGE(FL("probe_rsp is NULL"));
2309 return;
2310 }
2311
2312 vdev = wma_find_vdev_by_addr(wma, probe_rsp->macHdr.sa, &vdev_id);
2313 if (!vdev) {
2314 WMA_LOGE(FL("failed to get vdev handle"));
2315 return;
2316 }
2317
2318 if (WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
2319 WMI_SERVICE_BEACON_OFFLOAD)) {
2320 WMA_LOGI("Beacon Offload Enabled Sending Unified command");
2321 if (wmi_unified_probe_rsp_tmpl_send(wma, vdev_id,
2322 probe_rsp_info) < 0) {
2323 WMA_LOGE(FL("wmi_unified_probe_rsp_tmpl_send Failed "));
2324 return;
2325 }
2326 }
2327}
2328
2329/**
2330 * wma_send_beacon() - send beacon template
2331 * @wma: wma handle
2332 * @bcn_info: beacon info
2333 *
2334 * This funciton store beacon template locally and
2335 * update keep alive parameters
2336 *
2337 * Return: none
2338 */
2339void wma_send_beacon(tp_wma_handle wma, tpSendbeaconParams bcn_info)
2340{
2341 ol_txrx_vdev_handle vdev;
2342 uint8_t vdev_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302343 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002344 uint8_t *p2p_ie;
2345 tpAniBeaconStruct beacon;
Govind Singhd76a5b02016-03-08 15:12:14 +05302346 struct vdev_up_params param = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002347
2348 beacon = (tpAniBeaconStruct) (bcn_info->beacon);
2349 vdev = wma_find_vdev_by_addr(wma, beacon->macHdr.sa, &vdev_id);
2350 if (!vdev) {
2351 WMA_LOGE("%s : failed to get vdev handle", __func__);
2352 return;
2353 }
2354
2355 if (WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
2356 WMI_SERVICE_BEACON_OFFLOAD)) {
2357 WMA_LOGI("Beacon Offload Enabled Sending Unified command");
Govind Singh61ad2622016-02-22 17:25:02 +05302358 status = wma_unified_bcn_tmpl_send(wma, vdev_id, bcn_info, 4);
2359 if (QDF_IS_STATUS_ERROR(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002360 WMA_LOGE("%s : wmi_unified_bcn_tmpl_send Failed ",
2361 __func__);
2362 return;
2363 }
2364
2365 if (bcn_info->p2pIeOffset) {
2366 p2p_ie = bcn_info->beacon + bcn_info->p2pIeOffset;
2367 WMA_LOGI
2368 (" %s: p2pIe is present - vdev_id %hu, p2p_ie = %p, p2p ie len = %hu",
2369 __func__, vdev_id, p2p_ie, p2p_ie[1]);
2370 if (wma_p2p_go_set_beacon_ie(wma, vdev_id, p2p_ie) < 0) {
2371 WMA_LOGE
2372 ("%s : wmi_unified_bcn_tmpl_send Failed ",
2373 __func__);
2374 return;
2375 }
2376 }
2377 }
2378 status = wma_store_bcn_tmpl(wma, vdev_id, bcn_info);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302379 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002380 WMA_LOGE("%s : wma_store_bcn_tmpl Failed", __func__);
2381 return;
2382 }
2383 if (!wma->interfaces[vdev_id].vdev_up) {
Govind Singhd76a5b02016-03-08 15:12:14 +05302384 param.vdev_id = vdev_id;
2385 param.assoc_id = 0;
2386 status = wmi_unified_vdev_up_send(wma->wmi_handle,
2387 bcn_info->bssId,
2388 &param);
2389 if (QDF_IS_STATUS_ERROR(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002390 WMA_LOGE("%s : failed to send vdev up", __func__);
Manishekar Chandrasekarancb052172016-04-22 12:19:04 +05302391 cds_set_do_hw_mode_change_flag(false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002392 return;
2393 }
2394 wma->interfaces[vdev_id].vdev_up = true;
2395 wma_set_sap_keepalive(wma, vdev_id);
2396 }
2397}
2398
2399/**
2400 * wma_set_keepalive_req() - send keep alive request to fw
2401 * @wma: wma handle
2402 * @keepalive: keep alive parameters
2403 *
2404 * Return: none
2405 */
2406void wma_set_keepalive_req(tp_wma_handle wma,
2407 tSirKeepAliveReq *keepalive)
2408{
2409 WMA_LOGD("KEEPALIVE:PacketType:%d", keepalive->packetType);
2410 wma_set_sta_keep_alive(wma, keepalive->sessionId,
2411 keepalive->packetType,
2412 keepalive->timePeriod,
2413 keepalive->hostIpv4Addr,
Srinivas Girigowda9c330a92015-11-24 12:28:25 -08002414 keepalive->destIpv4Addr,
2415 keepalive->dest_macaddr.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002416
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302417 qdf_mem_free(keepalive);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002418}
2419
2420/**
2421 * wma_beacon_miss_handler() - beacon miss event handler
2422 * @wma: wma handle
2423 * @vdev_id: vdev id
2424 *
2425 * This function send beacon miss indication to upper layers.
2426 *
2427 * Return: none
2428 */
2429void wma_beacon_miss_handler(tp_wma_handle wma, uint32_t vdev_id)
2430{
2431 tSirSmeMissedBeaconInd *beacon_miss_ind;
2432
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302433 beacon_miss_ind = (tSirSmeMissedBeaconInd *) qdf_mem_malloc
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002434 (sizeof(tSirSmeMissedBeaconInd));
2435
2436 if (NULL == beacon_miss_ind) {
2437 WMA_LOGE("%s: Memory allocation failure", __func__);
2438 return;
2439 }
2440 beacon_miss_ind->messageType = WMA_MISSED_BEACON_IND;
2441 beacon_miss_ind->length = sizeof(tSirSmeMissedBeaconInd);
2442 beacon_miss_ind->bssIdx = vdev_id;
2443
2444 wma_send_msg(wma, WMA_MISSED_BEACON_IND, (void *)beacon_miss_ind, 0);
2445}
2446
2447/**
2448 * wma_mgmt_tx_completion_handler() - wma mgmt Tx completion event handler
2449 * @handle: wma handle
2450 * @cmpl_event_params: completion event handler data
2451 * @len: length of @cmpl_event_params
2452 *
2453 * Return: 0 on success; error number otherwise
2454 */
2455
2456int wma_mgmt_tx_completion_handler(void *handle, uint8_t *cmpl_event_params,
2457 uint32_t len)
2458{
2459 tp_wma_handle wma_handle = (tp_wma_handle)handle;
2460 WMI_MGMT_TX_COMPLETION_EVENTID_param_tlvs *param_buf;
2461 wmi_mgmt_tx_compl_event_fixed_param *cmpl_params;
2462 struct wmi_desc_t *wmi_desc;
2463
Anurag Chouhan6d760662016-02-20 16:05:43 +05302464 ol_txrx_pdev_handle pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002465
2466 param_buf = (WMI_MGMT_TX_COMPLETION_EVENTID_param_tlvs *)
2467 cmpl_event_params;
2468 if (!param_buf && !wma_handle) {
2469 WMA_LOGE("%s: Invalid mgmt Tx completion event", __func__);
2470 return -EINVAL;
2471 }
2472 cmpl_params = param_buf->fixed_param;
2473
2474 WMA_LOGI("%s: status:%d wmi_desc_id:%d", __func__, cmpl_params->status,
2475 cmpl_params->desc_id);
2476
2477 wmi_desc = (struct wmi_desc_t *)
2478 (&wma_handle->wmi_desc_pool.array[cmpl_params->desc_id]);
2479
2480 if (!wmi_desc) {
2481 WMA_LOGE("%s: Invalid wmi desc", __func__);
2482 return -EINVAL;
2483 }
2484
2485 if (wmi_desc->nbuf)
Nirav Shahcbc6d722016-03-01 16:24:53 +05302486 qdf_nbuf_unmap_single(pdev->osdev, wmi_desc->nbuf,
Anurag Chouhan6d760662016-02-20 16:05:43 +05302487 QDF_DMA_TO_DEVICE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002488 if (wmi_desc->tx_cmpl_cb)
2489 wmi_desc->tx_cmpl_cb(wma_handle->mac_context,
2490 wmi_desc->nbuf, 1);
2491
2492 if (wmi_desc->ota_post_proc_cb)
2493 wmi_desc->ota_post_proc_cb((tpAniSirGlobal)
2494 wma_handle->mac_context,
2495 cmpl_params->status);
2496
2497 wmi_desc_put(wma_handle, wmi_desc);
2498
2499 return 0;
2500}
2501
2502/**
2503 * wma_process_update_opmode() - process update VHT opmode cmd from UMAC
2504 * @wma_handle: wma handle
2505 * @update_vht_opmode: vht opmode
2506 *
2507 * Return: none
2508 */
2509void wma_process_update_opmode(tp_wma_handle wma_handle,
2510 tUpdateVHTOpMode *update_vht_opmode)
2511{
2512 WMA_LOGD("%s: opMode = %d", __func__, update_vht_opmode->opMode);
2513
2514 wma_set_peer_param(wma_handle, update_vht_opmode->peer_mac,
2515 WMI_PEER_CHWIDTH, update_vht_opmode->opMode,
2516 update_vht_opmode->smesessionId);
2517}
2518
2519/**
2520 * wma_process_update_rx_nss() - process update RX NSS cmd from UMAC
2521 * @wma_handle: wma handle
2522 * @update_rx_nss: rx nss value
2523 *
2524 * Return: none
2525 */
2526void wma_process_update_rx_nss(tp_wma_handle wma_handle,
2527 tUpdateRxNss *update_rx_nss)
2528{
2529 struct wma_txrx_node *intr =
2530 &wma_handle->interfaces[update_rx_nss->smesessionId];
2531 int rx_nss = update_rx_nss->rxNss;
2532
2533 wma_update_txrx_chainmask(wma_handle->num_rf_chains, &rx_nss);
2534
2535 intr->nss = (uint8_t)rx_nss;
2536 update_rx_nss->rxNss = (uint32_t)rx_nss;
2537
2538 WMA_LOGD("%s: Rx Nss = %d", __func__, update_rx_nss->rxNss);
2539
2540 wma_set_peer_param(wma_handle, update_rx_nss->peer_mac,
2541 WMI_PEER_NSS, update_rx_nss->rxNss,
2542 update_rx_nss->smesessionId);
2543}
2544
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002545/**
2546 * wma_process_update_membership() - process update group membership cmd
2547 * @wma_handle: wma handle
2548 * @membership: group membership info
2549 *
2550 * Return: none
2551 */
2552void wma_process_update_membership(tp_wma_handle wma_handle,
2553 tUpdateMembership *membership)
2554{
2555 WMA_LOGD("%s: membership = %x ", __func__, membership->membership);
2556
2557 wma_set_peer_param(wma_handle, membership->peer_mac,
2558 WMI_PEER_MEMBERSHIP, membership->membership,
2559 membership->smesessionId);
2560}
2561
2562/**
2563 * wma_process_update_userpos() - process update user pos cmd from UMAC
2564 * @wma_handle: wma handle
2565 * @userpos: user pos value
2566 *
2567 * Return: none
2568 */
2569void wma_process_update_userpos(tp_wma_handle wma_handle,
2570 tUpdateUserPos *userpos)
2571{
2572 WMA_LOGD("%s: userPos = %x ", __func__, userpos->userPos);
2573
2574 wma_set_peer_param(wma_handle, userpos->peer_mac,
2575 WMI_PEER_USERPOS, userpos->userPos,
2576 userpos->smesessionId);
2577
2578 /* Now that membership/userpos is updated in fw,
2579 * enable GID PPS.
2580 */
2581 wma_set_ppsconfig(userpos->smesessionId, WMA_VHT_PPS_GID_MATCH, 1);
2582
2583}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002584
2585/**
2586 * wma_set_htconfig() - set ht config parameters to target
2587 * @vdev_id: vdev id
2588 * @ht_capab: ht capablity
2589 * @value: value of ht param
2590 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302591 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002592 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302593QDF_STATUS wma_set_htconfig(uint8_t vdev_id, uint16_t ht_capab, int value)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002594{
Anurag Chouhan6d760662016-02-20 16:05:43 +05302595 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
Govind Singhd76a5b02016-03-08 15:12:14 +05302596 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002597
2598 if (NULL == wma) {
2599 WMA_LOGE("%s: Failed to get wma", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302600 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002601 }
2602
2603 switch (ht_capab) {
2604 case WNI_CFG_HT_CAP_INFO_ADVANCE_CODING:
Govind Singhd76a5b02016-03-08 15:12:14 +05302605 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002606 WMI_VDEV_PARAM_LDPC,
2607 value);
2608 break;
2609 case WNI_CFG_HT_CAP_INFO_TX_STBC:
Govind Singhd76a5b02016-03-08 15:12:14 +05302610 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002611 WMI_VDEV_PARAM_TX_STBC,
2612 value);
2613 break;
2614 case WNI_CFG_HT_CAP_INFO_RX_STBC:
Govind Singhd76a5b02016-03-08 15:12:14 +05302615 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002616 WMI_VDEV_PARAM_RX_STBC,
2617 value);
2618 break;
2619 case WNI_CFG_HT_CAP_INFO_SHORT_GI_20MHZ:
2620 case WNI_CFG_HT_CAP_INFO_SHORT_GI_40MHZ:
2621 WMA_LOGE("%s: ht_capab = %d, value = %d", __func__, ht_capab,
2622 value);
Govind Singhd76a5b02016-03-08 15:12:14 +05302623 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002624 WMI_VDEV_PARAM_SGI, value);
Govind Singhd76a5b02016-03-08 15:12:14 +05302625 if (ret == QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002626 wma->interfaces[vdev_id].config.shortgi = value;
2627 break;
2628 default:
2629 WMA_LOGE("%s:INVALID HT CONFIG", __func__);
2630 }
2631
Govind Singhd76a5b02016-03-08 15:12:14 +05302632 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002633}
2634
2635/**
2636 * wma_hidden_ssid_vdev_restart() - vdev restart for hidden ssid
2637 * @wma_handle: wma handle
2638 * @pReq: hidden ssid vdev restart request
2639 *
2640 * Return: none
2641 */
2642void wma_hidden_ssid_vdev_restart(tp_wma_handle wma_handle,
2643 tHalHiddenSsidVdevRestart *pReq)
2644{
2645 struct wma_txrx_node *intr = wma_handle->interfaces;
2646
2647 if ((pReq->sessionId !=
2648 intr[pReq->sessionId].vdev_restart_params.vdev_id)
2649 || !((intr[pReq->sessionId].type == WMI_VDEV_TYPE_AP)
2650 && (intr[pReq->sessionId].sub_type == 0))) {
2651 WMA_LOGE("%s : invalid session id", __func__);
2652 return;
2653 }
2654
2655 intr[pReq->sessionId].vdev_restart_params.ssidHidden = pReq->ssidHidden;
Anurag Chouhan8e0ccd32016-02-19 15:30:20 +05302656 qdf_atomic_set(&intr[pReq->sessionId].vdev_restart_params.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002657 hidden_ssid_restart_in_progress, 1);
2658
2659 /* vdev stop -> vdev restart -> vdev up */
2660 WMA_LOGD("%s, vdev_id: %d, pausing tx_ll_queue for VDEV_STOP",
2661 __func__, pReq->sessionId);
2662 ol_txrx_vdev_pause(wma_handle->interfaces[pReq->sessionId].handle,
2663 OL_TXQ_PAUSE_REASON_VDEV_STOP);
2664 wma_handle->interfaces[pReq->sessionId].pause_bitmap |=
2665 (1 << PAUSE_TYPE_HOST);
2666 if (wmi_unified_vdev_stop_send(wma_handle->wmi_handle, pReq->sessionId)) {
2667 WMA_LOGE("%s: %d Failed to send vdev stop", __func__, __LINE__);
Anurag Chouhan8e0ccd32016-02-19 15:30:20 +05302668 qdf_atomic_set(&intr[pReq->sessionId].vdev_restart_params.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002669 hidden_ssid_restart_in_progress, 0);
2670 return;
2671 }
2672}
2673
2674
2675#ifdef WLAN_FEATURE_11W
2676
2677/**
2678 * wma_extract_ccmp_pn() - extract 6 byte PN from the CCMP header
2679 * @ccmp_ptr: CCMP header
2680 *
2681 * Return: PN extracted from header.
2682 */
2683static uint64_t wma_extract_ccmp_pn(uint8_t *ccmp_ptr)
2684{
2685 uint8_t rsvd, key, pn[6];
2686 uint64_t new_pn;
2687
2688 /*
2689 * +-----+-----+------+----------+-----+-----+-----+-----+
2690 * | PN0 | PN1 | rsvd | rsvd/key | PN2 | PN3 | PN4 | PN5 |
2691 * +-----+-----+------+----------+-----+-----+-----+-----+
2692 * CCMP Header Format
2693 */
2694
2695 /* Extract individual bytes */
2696 pn[0] = (uint8_t) *ccmp_ptr;
2697 pn[1] = (uint8_t) *(ccmp_ptr + 1);
2698 rsvd = (uint8_t) *(ccmp_ptr + 2);
2699 key = (uint8_t) *(ccmp_ptr + 3);
2700 pn[2] = (uint8_t) *(ccmp_ptr + 4);
2701 pn[3] = (uint8_t) *(ccmp_ptr + 5);
2702 pn[4] = (uint8_t) *(ccmp_ptr + 6);
2703 pn[5] = (uint8_t) *(ccmp_ptr + 7);
2704
2705 /* Form 6 byte PN with 6 individual bytes of PN */
2706 new_pn = ((uint64_t) pn[5] << 40) |
2707 ((uint64_t) pn[4] << 32) |
2708 ((uint64_t) pn[3] << 24) |
2709 ((uint64_t) pn[2] << 16) |
2710 ((uint64_t) pn[1] << 8) | ((uint64_t) pn[0] << 0);
2711
2712 WMA_LOGE("PN of received packet is %llu", new_pn);
2713 return new_pn;
2714}
2715
2716/**
2717 * wma_is_ccmp_pn_replay_attack() - detect replay attacking using PN in CCMP
2718 * @cds_ctx: cds context
2719 * @wh: 802.11 frame header
2720 * @ccmp_ptr: CCMP frame header
2721 *
2722 * Return: true/false
2723 */
2724static bool
2725wma_is_ccmp_pn_replay_attack(void *cds_ctx, struct ieee80211_frame *wh,
2726 uint8_t *ccmp_ptr)
2727{
2728 ol_txrx_pdev_handle pdev;
2729 ol_txrx_vdev_handle vdev;
2730 ol_txrx_peer_handle peer;
2731 uint8_t vdev_id, peer_id;
2732 uint8_t *last_pn_valid;
2733 uint64_t *last_pn, new_pn;
2734 uint32_t *rmf_pn_replays;
2735
Anurag Chouhan6d760662016-02-20 16:05:43 +05302736 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002737 if (!pdev) {
2738 WMA_LOGE("%s: Failed to find pdev", __func__);
2739 return true;
2740 }
2741
Mukul Sharmaa748fbb2015-12-01 19:51:36 +05302742 vdev = wma_find_vdev_by_bssid(cds_ctx, wh->i_addr3, &vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002743 if (!vdev) {
2744 WMA_LOGE("%s: Failed to find vdev", __func__);
2745 return true;
2746 }
2747
2748 /* Retrieve the peer based on vdev and addr */
2749 peer = ol_txrx_find_peer_by_addr_and_vdev(pdev, vdev, wh->i_addr2,
2750 &peer_id);
2751
2752 if (NULL == peer) {
2753 WMA_LOGE("%s: Failed to find peer, Not able to validate PN",
2754 __func__);
2755 return true;
2756 }
2757
2758 new_pn = wma_extract_ccmp_pn(ccmp_ptr);
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07002759 ol_txrx_get_pn_info(peer, &last_pn_valid, &last_pn, &rmf_pn_replays);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002760
2761 if (*last_pn_valid) {
2762 if (new_pn > *last_pn) {
2763 *last_pn = new_pn;
2764 WMA_LOGE("%s: PN validation successful", __func__);
2765 } else {
2766 WMA_LOGE("%s: PN Replay attack detected", __func__);
2767 /* per 11W amendment, keeping track of replay attacks */
2768 *rmf_pn_replays += 1;
2769 return true;
2770 }
2771 } else {
2772 *last_pn_valid = 1;
2773 *last_pn = new_pn;
2774 }
2775
2776 return false;
2777}
2778
2779/**
mukul sharma72c8b222015-09-04 17:02:01 +05302780 * wma_process_bip() - process mmie in rmf frame
2781 * @wma_handle: wma handle
2782 * @iface: txrx node
2783 * @wh: 80211 frame
2784 * @wbuf: Buffer
2785 *
2786 * Return: 0 for success or error code
2787 */
2788
2789static
2790int wma_process_bip(tp_wma_handle wma_handle,
2791 struct wma_txrx_node *iface,
2792 struct ieee80211_frame *wh,
Nirav Shahcbc6d722016-03-01 16:24:53 +05302793 qdf_nbuf_t wbuf
mukul sharma72c8b222015-09-04 17:02:01 +05302794)
2795{
2796 uint16_t key_id;
2797 uint8_t *efrm;
2798
Nirav Shahcbc6d722016-03-01 16:24:53 +05302799 efrm = qdf_nbuf_data(wbuf) + qdf_nbuf_len(wbuf);
mukul sharma72c8b222015-09-04 17:02:01 +05302800 key_id = (uint16_t)*(efrm - cds_get_mmie_size() + 2);
2801
2802 if (!((key_id == WMA_IGTK_KEY_INDEX_4)
2803 || (key_id == WMA_IGTK_KEY_INDEX_5))) {
2804 WMA_LOGE(FL("Invalid KeyID(%d) dropping the frame"), key_id);
2805 return -EINVAL;
2806 }
2807 if (WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap,
2808 WMI_SERVICE_STA_PMF_OFFLOAD)) {
2809 /*
2810 * if 11w offload is enabled then mmie validation is performed
2811 * in firmware, host just need to trim the mmie.
2812 */
Nirav Shahcbc6d722016-03-01 16:24:53 +05302813 qdf_nbuf_trim_tail(wbuf, cds_get_mmie_size());
mukul sharma72c8b222015-09-04 17:02:01 +05302814 } else {
2815 if (cds_is_mmie_valid(iface->key.key,
2816 iface->key.key_id[key_id - WMA_IGTK_KEY_INDEX_4].ipn,
2817 (uint8_t *) wh, efrm)) {
2818 WMA_LOGE(FL("Protected BC/MC frame MMIE validation successful"));
2819 /* Remove MMIE */
Nirav Shahcbc6d722016-03-01 16:24:53 +05302820 qdf_nbuf_trim_tail(wbuf, cds_get_mmie_size());
mukul sharma72c8b222015-09-04 17:02:01 +05302821 } else {
2822 WMA_LOGE(FL("BC/MC MIC error or MMIE not present, dropping the frame"));
2823 return -EINVAL;
2824 }
2825 }
2826 return 0;
2827}
2828
2829/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002830 * wma_process_rmf_frame() - process rmf frame
2831 * @wma_handle: wma handle
2832 * @iface: txrx node
2833 * @wh: 80211 frame
2834 * @rx_pkt: rx packet
2835 * @wbuf: Buffer
2836 *
2837 * Return: 0 for success or error code
2838 */
2839static
2840int wma_process_rmf_frame(tp_wma_handle wma_handle,
2841 struct wma_txrx_node *iface,
2842 struct ieee80211_frame *wh,
2843 cds_pkt_t *rx_pkt,
Nirav Shahcbc6d722016-03-01 16:24:53 +05302844 qdf_nbuf_t wbuf)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002845{
mukul sharma72c8b222015-09-04 17:02:01 +05302846 uint8_t *orig_hdr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002847 uint8_t *ccmp;
2848
2849 if ((wh)->i_fc[1] & IEEE80211_FC1_WEP) {
2850 if (IEEE80211_IS_BROADCAST(wh->i_addr1) ||
2851 IEEE80211_IS_MULTICAST(wh->i_addr1)) {
2852 WMA_LOGE("Encrypted BC/MC frame dropping the frame");
2853 cds_pkt_return_packet(rx_pkt);
2854 return -EINVAL;
2855 }
2856
Nirav Shahcbc6d722016-03-01 16:24:53 +05302857 orig_hdr = (uint8_t *) qdf_nbuf_data(wbuf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002858 /* Pointer to head of CCMP header */
2859 ccmp = orig_hdr + sizeof(*wh);
2860 if (wma_is_ccmp_pn_replay_attack(
2861 wma_handle, wh, ccmp)) {
2862 WMA_LOGE("Dropping the frame");
2863 cds_pkt_return_packet(rx_pkt);
2864 return -EINVAL;
2865 }
2866
2867 /* Strip privacy headers (and trailer)
2868 * for a received frame
2869 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302870 qdf_mem_move(orig_hdr +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002871 IEEE80211_CCMP_HEADERLEN, wh,
2872 sizeof(*wh));
Nirav Shahcbc6d722016-03-01 16:24:53 +05302873 qdf_nbuf_pull_head(wbuf,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002874 IEEE80211_CCMP_HEADERLEN);
Nirav Shahcbc6d722016-03-01 16:24:53 +05302875 qdf_nbuf_trim_tail(wbuf, IEEE80211_CCMP_MICLEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002876
2877 rx_pkt->pkt_meta.mpdu_hdr_ptr =
Nirav Shahcbc6d722016-03-01 16:24:53 +05302878 qdf_nbuf_data(wbuf);
2879 rx_pkt->pkt_meta.mpdu_len = qdf_nbuf_len(wbuf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002880 rx_pkt->pkt_meta.mpdu_data_len =
2881 rx_pkt->pkt_meta.mpdu_len -
2882 rx_pkt->pkt_meta.mpdu_hdr_len;
2883 rx_pkt->pkt_meta.mpdu_data_ptr =
2884 rx_pkt->pkt_meta.mpdu_hdr_ptr +
2885 rx_pkt->pkt_meta.mpdu_hdr_len;
2886 rx_pkt->pkt_meta.tsf_delta = rx_pkt->pkt_meta.tsf_delta;
2887 rx_pkt->pkt_buf = wbuf;
2888 WMA_LOGD(FL("BSSID: "MAC_ADDRESS_STR" tsf_delta: %u"),
2889 MAC_ADDR_ARRAY(wh->i_addr3), rx_pkt->pkt_meta.tsf_delta);
2890 } else {
2891 if (IEEE80211_IS_BROADCAST(wh->i_addr1) ||
2892 IEEE80211_IS_MULTICAST(wh->i_addr1)) {
mukul sharma72c8b222015-09-04 17:02:01 +05302893 if (0 != wma_process_bip(wma_handle, iface, wh, wbuf)) {
2894 cds_pkt_return_packet(rx_pkt);
2895 return -EINVAL;
Mukul Sharmaa748fbb2015-12-01 19:51:36 +05302896 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002897 } else {
2898 WMA_LOGE("Rx unprotected unicast mgmt frame");
2899 rx_pkt->pkt_meta.dpuFeedback =
2900 DPU_FEEDBACK_UNPROTECTED_ERROR;
2901 }
2902 }
2903 return 0;
2904}
2905#endif
2906
2907/**
Krishna Kumaar Natarajanb7f9a352016-03-18 11:40:07 -07002908 * wma_is_pkt_drop_candidate() - check if the mgmt frame should be droppped
2909 * @wma_handle: wma handle
2910 * @peer_addr: peer MAC address
2911 * @subtype: Management frame subtype
2912 *
2913 * This function is used to decide if a particular management frame should be
2914 * dropped to prevent DOS attack. Timestamp is used to decide the DOS attack.
2915 *
2916 * Return: true if the packet should be dropped and false oterwise
2917 */
2918static bool wma_is_pkt_drop_candidate(tp_wma_handle wma_handle,
2919 uint8_t *peer_addr, uint8_t subtype)
2920{
2921 struct ol_txrx_peer_t *peer;
2922 struct ol_txrx_pdev_t *pdev_ctx;
2923 uint8_t peer_id;
2924 bool should_drop = false;
2925
2926 /*
2927 * Currently this function handles only Disassoc,
2928 * Deauth and Assoc req frames. Return false for
2929 * all other frames.
2930 */
2931 if (subtype != IEEE80211_FC0_SUBTYPE_DISASSOC &&
2932 subtype != IEEE80211_FC0_SUBTYPE_DEAUTH &&
2933 subtype != IEEE80211_FC0_SUBTYPE_ASSOC_REQ) {
2934 should_drop = false;
2935 goto end;
2936 }
2937
2938 pdev_ctx = cds_get_context(QDF_MODULE_ID_TXRX);
2939 if (!pdev_ctx) {
2940 WMA_LOGE(FL("Failed to get the context"));
2941 should_drop = true;
2942 goto end;
2943 }
2944
2945 peer = ol_txrx_find_peer_by_addr(pdev_ctx, peer_addr, &peer_id);
2946 if (!peer) {
2947 if (SIR_MAC_MGMT_ASSOC_REQ != subtype) {
2948 WMA_LOGI(
2949 FL("Received mgmt frame: %0x from unknow peer: %pM"),
2950 subtype, peer_addr);
2951 should_drop = true;
2952 }
2953 goto end;
2954 }
2955
2956 switch (subtype) {
2957 case SIR_MAC_MGMT_ASSOC_REQ:
2958 if (peer->last_assoc_rcvd) {
2959 if (qdf_get_system_timestamp() - peer->last_assoc_rcvd <
2960 WMA_MGMT_FRAME_DETECT_DOS_TIMER) {
2961 WMA_LOGI(FL("Dropping Assoc Req received"));
2962 should_drop = true;
2963 }
2964 }
2965 peer->last_assoc_rcvd = qdf_get_system_timestamp();
2966 break;
2967 case SIR_MAC_MGMT_DISASSOC:
2968 if (peer->last_disassoc_rcvd) {
2969 if (qdf_get_system_timestamp() -
2970 peer->last_disassoc_rcvd <
2971 WMA_MGMT_FRAME_DETECT_DOS_TIMER) {
2972 WMA_LOGI(FL("Dropping DisAssoc received"));
2973 should_drop = true;
2974 }
2975 }
2976 peer->last_disassoc_rcvd = qdf_get_system_timestamp();
2977 break;
2978 case SIR_MAC_MGMT_DEAUTH:
2979 if (peer->last_deauth_rcvd) {
2980 if (qdf_get_system_timestamp() -
2981 peer->last_deauth_rcvd <
2982 WMA_MGMT_FRAME_DETECT_DOS_TIMER) {
2983 WMA_LOGI(FL("Dropping Deauth received"));
2984 should_drop = true;
2985 }
2986 }
2987 peer->last_deauth_rcvd = qdf_get_system_timestamp();
2988 break;
2989 default:
2990 break;
2991 }
2992
2993end:
2994 return should_drop;
2995}
2996
2997/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002998 * wma_mgmt_rx_process() - process management rx frame.
2999 * @handle: wma handle
3000 * @data: rx data
3001 * @data_len: data length
3002 *
3003 * Return: 0 for success or error code
3004 */
3005static int wma_mgmt_rx_process(void *handle, uint8_t *data,
3006 uint32_t data_len)
3007{
3008 tp_wma_handle wma_handle = (tp_wma_handle) handle;
3009 WMI_MGMT_RX_EVENTID_param_tlvs *param_tlvs = NULL;
3010 wmi_mgmt_rx_hdr *hdr = NULL;
3011 struct wma_txrx_node *iface = NULL;
Mukul Sharmaa748fbb2015-12-01 19:51:36 +05303012 uint8_t vdev_id = WMA_INVALID_VDEV_ID;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003013 cds_pkt_t *rx_pkt;
Nirav Shahcbc6d722016-03-01 16:24:53 +05303014 qdf_nbuf_t wbuf;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003015 struct ieee80211_frame *wh;
3016 uint8_t mgt_type, mgt_subtype;
3017 int status;
3018
3019 if (!wma_handle) {
3020 WMA_LOGE("%s: Failed to get WMA context", __func__);
3021 return -EINVAL;
3022 }
3023
3024 param_tlvs = (WMI_MGMT_RX_EVENTID_param_tlvs *) data;
3025 if (!param_tlvs) {
3026 WMA_LOGE("Get NULL point message from FW");
3027 return -EINVAL;
3028 }
3029
3030 hdr = param_tlvs->hdr;
3031 if (!hdr) {
3032 WMA_LOGE("Rx event is NULL");
3033 return -EINVAL;
3034 }
3035
3036 if (hdr->buf_len < sizeof(struct ieee80211_frame)) {
3037 WMA_LOGE("Invalid rx mgmt packet");
3038 return -EINVAL;
3039 }
3040
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303041 rx_pkt = qdf_mem_malloc(sizeof(*rx_pkt));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003042 if (!rx_pkt) {
3043 WMA_LOGE("Failed to allocate rx packet");
3044 return -ENOMEM;
3045 }
3046
Rajeev Kumarfec3dbe2016-01-19 15:23:52 -08003047 if (cds_is_load_or_unload_in_progress()) {
Naveen Rawat10ccf872015-11-03 14:15:55 -08003048 WMA_LOGE("Load/Unload in progress");
3049 return -EINVAL;
3050 }
3051
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303052 qdf_mem_zero(rx_pkt, sizeof(*rx_pkt));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003053
3054 /*
3055 * Fill in meta information needed by pe/lim
3056 * TODO: Try to maintain rx metainfo as part of skb->data.
3057 */
3058 rx_pkt->pkt_meta.channel = hdr->channel;
3059 rx_pkt->pkt_meta.scan_src = hdr->flags;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -07003060
3061 /*
3062 * Get the rssi value from the current snr value
3063 * using standard noise floor of -96.
3064 */
3065 rx_pkt->pkt_meta.rssi = hdr->snr + WMA_NOISE_FLOOR_DBM_DEFAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003066 rx_pkt->pkt_meta.snr = hdr->snr;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -07003067
3068 /* If absolute rssi is available from firmware, use it */
3069 if (hdr->rssi != 0)
3070 rx_pkt->pkt_meta.rssi_raw = hdr->rssi;
3071 else
3072 rx_pkt->pkt_meta.rssi_raw = rx_pkt->pkt_meta.rssi;
3073
3074
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003075 /*
3076 * FIXME: Assigning the local timestamp as hw timestamp is not
3077 * available. Need to see if pe/lim really uses this data.
3078 */
3079 rx_pkt->pkt_meta.timestamp = (uint32_t) jiffies;
3080 rx_pkt->pkt_meta.mpdu_hdr_len = sizeof(struct ieee80211_frame);
3081 rx_pkt->pkt_meta.mpdu_len = hdr->buf_len;
3082 rx_pkt->pkt_meta.mpdu_data_len = hdr->buf_len -
3083 rx_pkt->pkt_meta.mpdu_hdr_len;
3084
3085 rx_pkt->pkt_meta.roamCandidateInd = 0;
3086
3087 /* Why not just use rx_event->hdr.buf_len? */
Nirav Shahcbc6d722016-03-01 16:24:53 +05303088 wbuf = qdf_nbuf_alloc(NULL, roundup(hdr->buf_len, 4), 0, 4, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003089 if (!wbuf) {
3090 WMA_LOGE("%s: Failed to allocate wbuf for mgmt rx len(%u)",
3091 __func__, hdr->buf_len);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303092 qdf_mem_free(rx_pkt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003093 return -ENOMEM;
3094 }
3095
Nirav Shahcbc6d722016-03-01 16:24:53 +05303096 qdf_nbuf_put_tail(wbuf, hdr->buf_len);
3097 qdf_nbuf_set_protocol(wbuf, ETH_P_CONTROL);
3098 wh = (struct ieee80211_frame *)qdf_nbuf_data(wbuf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003099
Nirav Shahcbc6d722016-03-01 16:24:53 +05303100 rx_pkt->pkt_meta.mpdu_hdr_ptr = qdf_nbuf_data(wbuf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003101 rx_pkt->pkt_meta.mpdu_data_ptr = rx_pkt->pkt_meta.mpdu_hdr_ptr +
3102 rx_pkt->pkt_meta.mpdu_hdr_len;
3103 rx_pkt->pkt_meta.tsf_delta = hdr->tsf_delta;
3104 rx_pkt->pkt_buf = wbuf;
3105
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003106#ifdef BIG_ENDIAN_HOST
3107 {
3108 /*
3109 * for big endian host, copy engine byte_swap is enabled
3110 * But the rx mgmt frame buffer content is in network byte order
3111 * Need to byte swap the mgmt frame buffer content - so when
3112 * copy engine does byte_swap - host gets buffer content in the
3113 * correct byte order.
3114 */
3115 int i;
3116 uint32_t *destp, *srcp;
3117 destp = (uint32_t *) wh;
3118 srcp = (uint32_t *) param_tlvs->bufp;
3119 for (i = 0;
3120 i < (roundup(hdr->buf_len, sizeof(uint32_t)) / 4); i++) {
3121 *destp = cpu_to_le32(*srcp);
3122 destp++;
3123 srcp++;
3124 }
3125 }
3126#else
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303127 qdf_mem_copy(wh, param_tlvs->bufp, hdr->buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003128#endif
3129
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -07003130 WMA_LOGD(
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303131 FL("BSSID: "MAC_ADDRESS_STR" snr = %d, rssi = %d, rssi_raw = %d tsf_delta: %u"),
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -07003132 MAC_ADDR_ARRAY(wh->i_addr3),
3133 hdr->snr, rx_pkt->pkt_meta.rssi,
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303134 rx_pkt->pkt_meta.rssi_raw,
3135 hdr->tsf_delta);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003136 if (!wma_handle->mgmt_rx) {
3137 WMA_LOGE("Not registered for Mgmt rx, dropping the frame");
3138 cds_pkt_return_packet(rx_pkt);
3139 return -EINVAL;
3140 }
3141
3142 /* If it is a beacon/probe response, save it for future use */
3143 mgt_type = (wh)->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
3144 mgt_subtype = (wh)->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
3145
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003146#ifdef WLAN_FEATURE_11W
3147 if (mgt_type == IEEE80211_FC0_TYPE_MGT &&
3148 (mgt_subtype == IEEE80211_FC0_SUBTYPE_DISASSOC ||
3149 mgt_subtype == IEEE80211_FC0_SUBTYPE_DEAUTH ||
3150 mgt_subtype == IEEE80211_FC0_SUBTYPE_ACTION)) {
Mukul Sharmaa748fbb2015-12-01 19:51:36 +05303151 if (wma_find_vdev_by_bssid(
3152 wma_handle, wh->i_addr3, &vdev_id)) {
3153 iface = &(wma_handle->interfaces[vdev_id]);
3154 if (iface->rmfEnabled) {
3155 status = wma_process_rmf_frame(wma_handle,
3156 iface, wh, rx_pkt, wbuf);
3157 if (status != 0)
3158 return status;
3159 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003160 }
3161 }
3162#endif /* WLAN_FEATURE_11W */
Mukul Sharmaa748fbb2015-12-01 19:51:36 +05303163 rx_pkt->pkt_meta.sessionId =
3164 (vdev_id == WMA_INVALID_VDEV_ID ? 0 : vdev_id);
Krishna Kumaar Natarajanb7f9a352016-03-18 11:40:07 -07003165
3166 if (wma_is_pkt_drop_candidate(wma_handle, wh->i_addr2, mgt_subtype)) {
3167 cds_pkt_return_packet(rx_pkt);
3168 return -EINVAL;
3169 }
3170
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003171 wma_handle->mgmt_rx(wma_handle, rx_pkt);
3172 return 0;
3173}
3174
3175/**
3176 * wma_de_register_mgmt_frm_client() - deregister management frame
3177 * @cds_ctx: cds context
3178 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303179 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003180 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303181QDF_STATUS wma_de_register_mgmt_frm_client(void *cds_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003182{
3183 tp_wma_handle wma_handle;
3184
3185#ifdef QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +05303186 if (cds_get_conparam() == QDF_GLOBAL_FTM_MODE)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303187 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003188#endif
3189
Anurag Chouhan6d760662016-02-20 16:05:43 +05303190 wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003191 if (!wma_handle) {
3192 WMA_LOGE("%s: Failed to get WMA context", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303193 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003194 }
3195
3196 if (wmi_unified_unregister_event_handler(wma_handle->wmi_handle,
3197 WMI_MGMT_RX_EVENTID) != 0) {
3198 WMA_LOGE("Failed to Unregister rx mgmt handler with wmi");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303199 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003200 }
3201 wma_handle->mgmt_rx = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303202 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003203}
3204
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003205#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003206/**
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003207 * wma_register_roaming_callbacks() - Register roaming callbacks
3208 * @cds_ctx: CDS Context
3209 * @csr_roam_synch_cb: CSR roam synch callback routine pointer
3210 * @pe_roam_synch_cb: PE roam synch callback routine pointer
3211 *
3212 * Register the SME and PE callback routines with WMA for
3213 * handling roaming
3214 *
3215 * Return: Success or Failure Status
3216 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303217QDF_STATUS wma_register_roaming_callbacks(void *cds_ctx,
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003218 void (*csr_roam_synch_cb)(tpAniSirGlobal mac,
3219 roam_offload_synch_ind *roam_synch_data,
Varun Reddy Yeturuf907f912016-03-21 15:06:22 -07003220 tpSirBssDescription bss_desc_ptr,
3221 enum sir_roam_op_code reason),
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303222 QDF_STATUS (*pe_roam_synch_cb)(tpAniSirGlobal mac,
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003223 roam_offload_synch_ind *roam_synch_data,
3224 tpSirBssDescription bss_desc_ptr))
3225{
3226
Anurag Chouhan6d760662016-02-20 16:05:43 +05303227 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003228
3229 if (!wma) {
3230 WMA_LOGE("%s: Failed to get WMA context", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303231 return QDF_STATUS_E_FAILURE;
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003232 }
3233 wma->csr_roam_synch_cb = csr_roam_synch_cb;
3234 wma->pe_roam_synch_cb = pe_roam_synch_cb;
3235 WMA_LOGD("Registered roam synch callbacks with WMA successfully");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303236 return QDF_STATUS_SUCCESS;
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003237}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003238#endif
3239
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003240/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003241 * wma_register_mgmt_frm_client() - register management frame callback
3242 * @cds_ctx: cds context
3243 * @mgmt_frm_rx: management frame
3244 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303245 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003246 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303247QDF_STATUS wma_register_mgmt_frm_client(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003248 void *cds_ctx, wma_mgmt_frame_rx_callback mgmt_frm_rx)
3249{
Anurag Chouhan6d760662016-02-20 16:05:43 +05303250 tp_wma_handle wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003251
3252 if (!wma_handle) {
3253 WMA_LOGE("%s: Failed to get WMA context", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303254 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003255 }
3256
3257 if (wmi_unified_register_event_handler(wma_handle->wmi_handle,
3258 WMI_MGMT_RX_EVENTID,
Govind Singhd76a5b02016-03-08 15:12:14 +05303259 wma_mgmt_rx_process,
3260 WMA_RX_WORK_CTX) != 0) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003261 WMA_LOGE("Failed to register rx mgmt handler with wmi");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303262 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003263 }
3264 wma_handle->mgmt_rx = mgmt_frm_rx;
3265
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303266 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003267}