blob: cfd8de71ed14f64f6bb04525cc8085a5fe14db5c [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
Naveen Rawat9801ac02016-06-22 11:02:50 -0700349 del_sta_ctx->is_tdls = true;
350 del_sta_ctx->vdev_id = vdev_id;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800351 del_sta_ctx->staId = peer_id;
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530352 qdf_mem_copy(del_sta_ctx->addr2, macaddr, IEEE80211_ADDR_LEN);
353 qdf_mem_copy(del_sta_ctx->bssId, wma->interfaces[vdev_id].bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800354 IEEE80211_ADDR_LEN);
355 del_sta_ctx->reasonCode = HAL_DEL_STA_REASON_CODE_KEEP_ALIVE;
356 wma_send_msg(wma, SIR_LIM_DELETE_STA_CONTEXT_IND,
357 (void *)del_sta_ctx, 0);
358 goto exit_handler;
359 break;
360#endif /* FEATURE_WLAN_TDLS */
361
362 case WMI_PEER_STA_KICKOUT_REASON_XRETRY:
363 if (wma->interfaces[vdev_id].type == WMI_VDEV_TYPE_STA &&
364 (wma->interfaces[vdev_id].sub_type == 0 ||
365 wma->interfaces[vdev_id].sub_type ==
366 WMI_UNIFIED_VDEV_SUBTYPE_P2P_CLIENT) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530367 !qdf_mem_cmp(wma->interfaces[vdev_id].bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800368 macaddr, IEEE80211_ADDR_LEN)) {
369 /*
370 * KICKOUT event is for current station-AP connection.
371 * Treat it like final beacon miss. Station may not have
372 * missed beacons but not able to transmit frames to AP
373 * for a long time. Must disconnect to get out of
374 * this sticky situation.
375 * In future implementation, roaming module will also
376 * handle this event and perform a scan.
377 */
378 WMA_LOGW("%s: WMI_PEER_STA_KICKOUT_REASON_XRETRY event for STA",
379 __func__);
380 wma_beacon_miss_handler(wma, vdev_id);
381 goto exit_handler;
382 }
383 break;
384
385 case WMI_PEER_STA_KICKOUT_REASON_UNSPECIFIED:
386 /*
387 * Default legacy value used by original firmware implementation.
388 */
389 if (wma->interfaces[vdev_id].type == WMI_VDEV_TYPE_STA &&
390 (wma->interfaces[vdev_id].sub_type == 0 ||
391 wma->interfaces[vdev_id].sub_type ==
392 WMI_UNIFIED_VDEV_SUBTYPE_P2P_CLIENT) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530393 !qdf_mem_cmp(wma->interfaces[vdev_id].bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800394 macaddr, IEEE80211_ADDR_LEN)) {
395 /*
396 * KICKOUT event is for current station-AP connection.
397 * Treat it like final beacon miss. Station may not have
398 * missed beacons but not able to transmit frames to AP
399 * for a long time. Must disconnect to get out of
400 * this sticky situation.
401 * In future implementation, roaming module will also
402 * handle this event and perform a scan.
403 */
404 WMA_LOGW("%s: WMI_PEER_STA_KICKOUT_REASON_UNSPECIFIED event for STA",
405 __func__);
406 wma_beacon_miss_handler(wma, vdev_id);
407 goto exit_handler;
408 }
409 break;
410
411 case WMI_PEER_STA_KICKOUT_REASON_INACTIVITY:
Naveen Rawat9801ac02016-06-22 11:02:50 -0700412 /*
413 * Handle SA query kickout is same as inactivity kickout.
414 * This could be for STA or SAP role
415 */
mukul sharma72c8b222015-09-04 17:02:01 +0530416 case WMI_PEER_STA_KICKOUT_REASON_SA_QUERY_TIMEOUT:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800417 default:
418 break;
419 }
420
421 /*
422 * default action is to send delete station context indication to LIM
423 */
424 del_sta_ctx =
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530425 (tpDeleteStaContext) qdf_mem_malloc(sizeof(tDeleteStaContext));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800426 if (!del_sta_ctx) {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530427 WMA_LOGE("QDF MEM Alloc Failed for tDeleteStaContext");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800428 return -ENOMEM;
429 }
430
Naveen Rawat9801ac02016-06-22 11:02:50 -0700431 del_sta_ctx->is_tdls = false;
432 del_sta_ctx->vdev_id = vdev_id;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800433 del_sta_ctx->staId = peer_id;
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530434 qdf_mem_copy(del_sta_ctx->addr2, macaddr, IEEE80211_ADDR_LEN);
435 qdf_mem_copy(del_sta_ctx->bssId, wma->interfaces[vdev_id].addr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800436 IEEE80211_ADDR_LEN);
437 del_sta_ctx->reasonCode = HAL_DEL_STA_REASON_CODE_KEEP_ALIVE;
Kiran Kumar Lokere37d3aa22015-11-03 14:58:26 -0800438 del_sta_ctx->rssi = kickout_event->rssi + WMA_TGT_NOISE_FLOOR_DBM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800439 wma_send_msg(wma, SIR_LIM_DELETE_STA_CONTEXT_IND, (void *)del_sta_ctx,
440 0);
441
442exit_handler:
443 WMA_LOGD("%s: Exit", __func__);
444 return 0;
445}
446
447/**
448 * wma_unified_bcntx_status_event_handler() - beacon tx status event handler
449 * @handle: wma handle
450 * @cmd_param_info: event data
451 * @len: data length
452 *
453 * WMI Handler for WMI_OFFLOAD_BCN_TX_STATUS_EVENTID event from firmware.
454 * This event is generated by FW when the beacon transmission is offloaded
455 * and the host performs beacon template modification using WMI_BCN_TMPL_CMDID
456 * The FW generates this event when the first successful beacon transmission
457 * after template update
458 *
459 * Return: 0 for success or error code
460 */
461int wma_unified_bcntx_status_event_handler(void *handle,
462 uint8_t *cmd_param_info,
463 uint32_t len)
464{
465 tp_wma_handle wma = (tp_wma_handle) handle;
466 WMI_OFFLOAD_BCN_TX_STATUS_EVENTID_param_tlvs *param_buf;
467 wmi_offload_bcn_tx_status_event_fixed_param *resp_event;
468 tSirFirstBeaconTxCompleteInd *beacon_tx_complete_ind;
469
470 param_buf =
471 (WMI_OFFLOAD_BCN_TX_STATUS_EVENTID_param_tlvs *) cmd_param_info;
472 if (!param_buf) {
473 WMA_LOGE("Invalid bcn tx response event buffer");
474 return -EINVAL;
475 }
476
477 resp_event = param_buf->fixed_param;
478
Chandrasekaran, Manishekarce2172e2016-02-18 16:12:43 +0530479 WMA_LOGD("%s", __func__);
480
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800481 /* Check for valid handle to ensure session is not
482 * deleted in any race
483 */
484 if (!wma->interfaces[resp_event->vdev_id].handle) {
485 WMA_LOGE("%s: The session does not exist", __func__);
486 return -EINVAL;
487 }
488
489 /* Beacon Tx Indication supports only AP mode. Ignore in other modes */
490 if (wma_is_vdev_in_ap_mode(wma, resp_event->vdev_id) == false) {
491 WMA_LOGI("%s: Beacon Tx Indication does not support type %d and sub_type %d",
492 __func__, wma->interfaces[resp_event->vdev_id].type,
493 wma->interfaces[resp_event->vdev_id].sub_type);
494 return 0;
495 }
496
497 beacon_tx_complete_ind = (tSirFirstBeaconTxCompleteInd *)
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530498 qdf_mem_malloc(sizeof(tSirFirstBeaconTxCompleteInd));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800499 if (!beacon_tx_complete_ind) {
500 WMA_LOGE("%s: Failed to alloc beacon_tx_complete_ind",
501 __func__);
502 return -ENOMEM;
503 }
504
505 beacon_tx_complete_ind->messageType = WMA_DFS_BEACON_TX_SUCCESS_IND;
506 beacon_tx_complete_ind->length = sizeof(tSirFirstBeaconTxCompleteInd);
507 beacon_tx_complete_ind->bssIdx = resp_event->vdev_id;
508
509 wma_send_msg(wma, WMA_DFS_BEACON_TX_SUCCESS_IND,
510 (void *)beacon_tx_complete_ind, 0);
511 return 0;
512}
513
514/**
515 * wma_get_link_probe_timeout() - get link timeout based on sub type
516 * @mac: UMAC handler
517 * @sub_type: vdev syb type
518 * @max_inactive_time: return max inactive time
519 * @max_unresponsive_time: return max unresponsive time
520 *
521 * Return: none
522 */
523static inline void wma_get_link_probe_timeout(struct sAniSirGlobal *mac,
524 uint32_t sub_type,
525 uint32_t *max_inactive_time,
526 uint32_t *max_unresponsive_time)
527{
528 uint32_t keep_alive;
529 uint16_t lm_id, ka_id;
530
531 switch (sub_type) {
532 case WMI_UNIFIED_VDEV_SUBTYPE_P2P_GO:
533 lm_id = WNI_CFG_GO_LINK_MONITOR_TIMEOUT;
534 ka_id = WNI_CFG_GO_KEEP_ALIVE_TIMEOUT;
535 break;
536 default:
537 /*For softAp the subtype value will be zero */
538 lm_id = WNI_CFG_AP_LINK_MONITOR_TIMEOUT;
539 ka_id = WNI_CFG_AP_KEEP_ALIVE_TIMEOUT;
540 }
541
542 if (wlan_cfg_get_int(mac, lm_id, max_inactive_time) != eSIR_SUCCESS) {
543 WMA_LOGE("Failed to read link monitor for subtype %d",
544 sub_type);
545 *max_inactive_time = WMA_LINK_MONITOR_DEFAULT_TIME_SECS;
546 }
547
548 if (wlan_cfg_get_int(mac, ka_id, &keep_alive) != eSIR_SUCCESS) {
549 WMA_LOGE("Failed to read keep alive for subtype %d", sub_type);
550 keep_alive = WMA_KEEP_ALIVE_DEFAULT_TIME_SECS;
551 }
552 *max_unresponsive_time = *max_inactive_time + keep_alive;
553}
554
555/**
556 * wma_set_sap_keepalive() - set SAP keep alive parameters to fw
557 * @wma: wma handle
558 * @vdev_id: vdev id
559 *
560 * Return: none
561 */
562void wma_set_sap_keepalive(tp_wma_handle wma, uint8_t vdev_id)
563{
564 uint32_t min_inactive_time, max_inactive_time, max_unresponsive_time;
Anurag Chouhan6d760662016-02-20 16:05:43 +0530565 struct sAniSirGlobal *mac = cds_get_context(QDF_MODULE_ID_PE);
Govind Singhd76a5b02016-03-08 15:12:14 +0530566 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800567
568 if (NULL == mac) {
569 WMA_LOGE("%s: Failed to get mac", __func__);
570 return;
571 }
572
573 wma_get_link_probe_timeout(mac, wma->interfaces[vdev_id].sub_type,
574 &max_inactive_time, &max_unresponsive_time);
575
576 min_inactive_time = max_inactive_time / 2;
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_MIN_IDLE_INACTIVE_TIME_SECS,
581 min_inactive_time);
582 if (QDF_IS_STATUS_ERROR(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800583 WMA_LOGE("Failed to Set AP MIN 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_IDLE_INACTIVE_TIME_SECS,
588 max_inactive_time);
589 if (QDF_IS_STATUS_ERROR(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800590 WMA_LOGE("Failed to Set AP MAX IDLE INACTIVE TIME");
591
Govind Singhd76a5b02016-03-08 15:12:14 +0530592 status = wma_vdev_set_param(wma->wmi_handle,
593 vdev_id,
594 WMI_VDEV_PARAM_AP_KEEPALIVE_MAX_UNRESPONSIVE_TIME_SECS,
595 max_unresponsive_time);
596 if (QDF_IS_STATUS_ERROR(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800597 WMA_LOGE("Failed to Set MAX UNRESPONSIVE TIME");
598
599 WMA_LOGD("%s:vdev_id:%d min_inactive_time: %u max_inactive_time: %u"
600 " max_unresponsive_time: %u", __func__, vdev_id,
601 min_inactive_time, max_inactive_time, max_unresponsive_time);
602}
603
604/**
mukul sharma72c8b222015-09-04 17:02:01 +0530605 * wma_set_sta_sa_query_param() - set sta sa query parameters
606 * @wma: wma handle
607 * @vdev_id: vdev id
608
609 * This function sets sta query related parameters in fw.
610 *
611 * Return: none
612 */
613
614void wma_set_sta_sa_query_param(tp_wma_handle wma,
615 uint8_t vdev_id)
616{
Anurag Chouhan6d760662016-02-20 16:05:43 +0530617 struct sAniSirGlobal *mac = cds_get_context(QDF_MODULE_ID_PE);
mukul sharma72c8b222015-09-04 17:02:01 +0530618 uint32_t max_retries, retry_interval;
mukul sharma72c8b222015-09-04 17:02:01 +0530619
620 WMA_LOGD(FL("Enter:"));
mukul sharma72c8b222015-09-04 17:02:01 +0530621
622 if (wlan_cfg_get_int
623 (mac, WNI_CFG_PMF_SA_QUERY_MAX_RETRIES,
624 &max_retries) != eSIR_SUCCESS) {
625 max_retries = DEFAULT_STA_SA_QUERY_MAX_RETRIES_COUNT;
626 WMA_LOGE(FL("Failed to get value for WNI_CFG_PMF_SA_QUERY_MAX_RETRIES"));
627 }
628 if (wlan_cfg_get_int
629 (mac, WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL,
630 &retry_interval) != eSIR_SUCCESS) {
631 retry_interval = DEFAULT_STA_SA_QUERY_RETRY_INTERVAL;
632 WMA_LOGE(FL("Failed to get value for WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL"));
633 }
634
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530635 wmi_unified_set_sta_sa_query_param_cmd(wma->wmi_handle,
636 vdev_id,
637 max_retries,
638 retry_interval);
mukul sharma72c8b222015-09-04 17:02:01 +0530639
640 WMA_LOGD(FL("Exit :"));
641 return;
642}
643
644/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800645 * wma_set_sta_keep_alive() - set sta keep alive parameters
646 * @wma: wma handle
647 * @vdev_id: vdev id
648 * @method: method for keep alive
649 * @timeperiod: time period
650 * @hostv4addr: host ipv4 address
651 * @destv4addr: dst ipv4 address
652 * @destmac: destination mac
653 *
654 * This function sets keep alive related parameters in fw.
655 *
656 * Return: none
657 */
658void wma_set_sta_keep_alive(tp_wma_handle wma, uint8_t vdev_id,
659 uint32_t method, uint32_t timeperiod,
660 uint8_t *hostv4addr, uint8_t *destv4addr,
661 uint8_t *destmac)
662{
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530663 struct sta_params params;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800664
665 WMA_LOGD("%s: Enter", __func__);
666
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530667 if (!wma) {
668 WMA_LOGE("%s: wma handle is NULL", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800669 return;
670 }
671
Govind Singhfe9ab252016-06-21 14:35:35 +0530672 if (timeperiod > WNI_CFG_INFRA_STA_KEEP_ALIVE_PERIOD_STAMAX) {
673 WMI_LOGE("Invalid period %d Max limit %d", timeperiod,
674 WNI_CFG_INFRA_STA_KEEP_ALIVE_PERIOD_STAMAX);
675 return;
676 }
677
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530678 params.vdev_id = vdev_id;
679 params.method = method;
680 params.timeperiod = timeperiod;
681 params.hostv4addr = hostv4addr;
682 params.destv4addr = destv4addr;
683 params.destmac = destmac;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800684
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530685 wmi_unified_set_sta_keep_alive_cmd(wma->wmi_handle,
686 &params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800687
688 WMA_LOGD("%s: Exit", __func__);
689 return;
690}
691
692/**
693 * wma_vdev_install_key_complete_event_handler() - install key complete handler
694 * @handle: wma handle
695 * @event: event data
696 * @len: data length
697 *
698 * This event is sent by fw once WPA/WPA2 keys are installed in fw.
699 *
700 * Return: 0 for success or error code
701 */
702int wma_vdev_install_key_complete_event_handler(void *handle,
703 uint8_t *event,
704 uint32_t len)
705{
706 WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID_param_tlvs *param_buf = NULL;
707 wmi_vdev_install_key_complete_event_fixed_param *key_fp = NULL;
708
709 if (!event) {
710 WMA_LOGE("%s: event param null", __func__);
711 return -EINVAL;
712 }
713
714 param_buf = (WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID_param_tlvs *) event;
715 if (!param_buf) {
716 WMA_LOGE("%s: received null buf from target", __func__);
717 return -EINVAL;
718 }
719
720 key_fp = param_buf->fixed_param;
721 if (!key_fp) {
722 WMA_LOGE("%s: received null event data from target", __func__);
723 return -EINVAL;
724 }
725 /*
726 * Do nothing for now. Completion of set key is already indicated to lim
727 */
728 WMA_LOGI("%s: WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID", __func__);
729 return 0;
730}
731/*
732 * 802.11n D2.0 defined values for "Minimum MPDU Start Spacing":
733 * 0 for no restriction
734 * 1 for 1/4 us - Our lower layer calculations limit our precision to 1 msec
735 * 2 for 1/2 us - Our lower layer calculations limit our precision to 1 msec
736 * 3 for 1 us
737 * 4 for 2 us
738 * 5 for 4 us
739 * 6 for 8 us
740 * 7 for 16 us
741 */
742static const uint8_t wma_mpdu_spacing[] = { 0, 1, 1, 1, 2, 4, 8, 16 };
743
744/**
745 * wma_parse_mpdudensity() - give mpdu spacing from mpdu density
746 * @mpdudensity: mpdu density
747 *
748 * Return: mpdu spacing or 0 for error
749 */
750static inline uint8_t wma_parse_mpdudensity(uint8_t mpdudensity)
751{
752 if (mpdudensity < sizeof(wma_mpdu_spacing))
753 return wma_mpdu_spacing[mpdudensity];
754 else
755 return 0;
756}
757
Poddar, Siddarth5a91f5b2016-04-28 12:24:10 +0530758#if defined(CONFIG_HL_SUPPORT) && defined(FEATURE_WLAN_TDLS)
759
760/**
761 * wma_unified_peer_state_update() - update peer state
762 * @pdev: pdev handle
763 * @sta_mac: pointer to sta mac addr
764 * @bss_addr: bss address
765 * @sta_type: sta entry type
766 *
767 *
768 * Return: None
769 */
770static void
771wma_unified_peer_state_update(
772 struct ol_txrx_pdev_t *pdev,
773 uint8_t *sta_mac,
774 uint8_t *bss_addr,
775 uint8_t sta_type)
776{
777 if (STA_ENTRY_TDLS_PEER == sta_type)
778 ol_txrx_peer_state_update(pdev, sta_mac,
779 OL_TXRX_PEER_STATE_AUTH);
780 else
781 ol_txrx_peer_state_update(pdev, bss_addr,
782 OL_TXRX_PEER_STATE_AUTH);
783}
784#else
785
786static inline void
787wma_unified_peer_state_update(
788 struct ol_txrx_pdev_t *pdev,
789 uint8_t *sta_mac,
790 uint8_t *bss_addr,
791 uint8_t sta_type)
792{
793 ol_txrx_peer_state_update(pdev, bss_addr, OL_TXRX_PEER_STATE_AUTH);
794}
795#endif
796
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800797/**
798 * wmi_unified_send_peer_assoc() - send peer assoc command to fw
799 * @wma: wma handle
800 * @nw_type: nw type
801 * @params: add sta params
802 *
803 * This function send peer assoc command to firmware with
804 * different parameters.
805 *
Govind Singhb30d4c02016-03-24 11:01:23 +0530806 * Return: QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800807 */
Govind Singhb30d4c02016-03-24 11:01:23 +0530808QDF_STATUS wma_send_peer_assoc(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800809 tSirNwType nw_type,
810 tpAddStaParams params)
811{
812 ol_txrx_pdev_handle pdev;
Govind Singhb30d4c02016-03-24 11:01:23 +0530813 struct peer_assoc_params *cmd;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800814 int32_t ret, max_rates, i;
815 uint8_t rx_stbc, tx_stbc;
Govind Singhb30d4c02016-03-24 11:01:23 +0530816 uint8_t *rate_pos;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800817 wmi_rate_set peer_legacy_rates, peer_ht_rates;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800818 uint32_t num_peer_11b_rates = 0;
819 uint32_t num_peer_11a_rates = 0;
820 uint32_t phymode;
821 uint32_t peer_nss = 1;
822 struct wma_txrx_node *intr = NULL;
Govind Singhb30d4c02016-03-24 11:01:23 +0530823 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800824
Govind Singhb30d4c02016-03-24 11:01:23 +0530825 cmd = qdf_mem_malloc(sizeof(struct peer_assoc_params));
826 if (!cmd) {
827 WMA_LOGE("Failed to allocate peer_assoc_params param");
828 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800829 }
Govind Singhb30d4c02016-03-24 11:01:23 +0530830
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800831 intr = &wma->interfaces[params->smesessionId];
832
Anurag Chouhan6d760662016-02-20 16:05:43 +0530833 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800834
835 if (NULL == pdev) {
836 WMA_LOGE("%s: Failed to get pdev", __func__);
Govind Singhb30d4c02016-03-24 11:01:23 +0530837 qdf_mem_free(cmd);
838 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800839 }
840
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530841 qdf_mem_zero(&peer_legacy_rates, sizeof(wmi_rate_set));
842 qdf_mem_zero(&peer_ht_rates, sizeof(wmi_rate_set));
Govind Singhb30d4c02016-03-24 11:01:23 +0530843 qdf_mem_zero(cmd, sizeof(struct peer_assoc_params));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800844
845 phymode = wma_peer_phymode(nw_type, params->staType,
846 params->htCapable,
847 params->ch_width,
848 params->vhtCapable);
849
850 /* Legacy Rateset */
851 rate_pos = (uint8_t *) peer_legacy_rates.rates;
852 for (i = 0; i < SIR_NUM_11B_RATES; i++) {
853 if (!params->supportedRates.llbRates[i])
854 continue;
855 rate_pos[peer_legacy_rates.num_rates++] =
856 params->supportedRates.llbRates[i];
857 num_peer_11b_rates++;
858 }
859 for (i = 0; i < SIR_NUM_11A_RATES; i++) {
860 if (!params->supportedRates.llaRates[i])
861 continue;
862 rate_pos[peer_legacy_rates.num_rates++] =
863 params->supportedRates.llaRates[i];
864 num_peer_11a_rates++;
865 }
866
867 if ((phymode == MODE_11A && num_peer_11a_rates == 0) ||
868 (phymode == MODE_11B && num_peer_11b_rates == 0)) {
869 WMA_LOGW("%s: Invalid phy rates. phymode 0x%x, 11b_rates %d, 11a_rates %d",
870 __func__, phymode, num_peer_11b_rates, num_peer_11a_rates);
Govind Singhb30d4c02016-03-24 11:01:23 +0530871 qdf_mem_free(cmd);
872 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800873 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800874
875 /* HT Rateset */
876 max_rates = sizeof(peer_ht_rates.rates) /
877 sizeof(peer_ht_rates.rates[0]);
878 rate_pos = (uint8_t *) peer_ht_rates.rates;
879 for (i = 0; i < MAX_SUPPORTED_RATES; i++) {
880 if (params->supportedRates.supportedMCSSet[i / 8] &
881 (1 << (i % 8))) {
882 rate_pos[peer_ht_rates.num_rates++] = i;
883 if (i >= 8) {
884 /* MCS8 or higher rate is present, must be 2x2 */
885 peer_nss = 2;
886 }
887 }
888 if (peer_ht_rates.num_rates == max_rates)
889 break;
890 }
891
892 if (params->htCapable && !peer_ht_rates.num_rates) {
893 uint8_t temp_ni_rates[8] = { 0x0, 0x1, 0x2, 0x3,
894 0x4, 0x5, 0x6, 0x7};
895 /*
896 * Workaround for EV 116382: The peer is marked HT but with
897 * supported rx mcs set is set to 0. 11n spec mandates MCS0-7
898 * for a HT STA. So forcing the supported rx mcs rate to
899 * MCS 0-7. This workaround will be removed once we get
900 * clarification from WFA regarding this STA behavior.
901 */
902
903 /* TODO: Do we really need this? */
904 WMA_LOGW("Peer is marked as HT capable but supported mcs rate is 0");
905 peer_ht_rates.num_rates = sizeof(temp_ni_rates);
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530906 qdf_mem_copy((uint8_t *) peer_ht_rates.rates, temp_ni_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800907 peer_ht_rates.num_rates);
908 }
909
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800910 /* in ap/ibss mode and for tdls peer, use mac address of the peer in
911 * the other end as the new peer address; in sta mode, use bss id to
912 * be the new peer address
913 */
914 if ((wma_is_vdev_in_ap_mode(wma, params->smesessionId))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800915 || (wma_is_vdev_in_ibss_mode(wma, params->smesessionId))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800916#ifdef FEATURE_WLAN_TDLS
917 || (STA_ENTRY_TDLS_PEER == params->staType)
918#endif /* FEATURE_WLAN_TDLS */
919 )
920 WMI_CHAR_ARRAY_TO_MAC_ADDR(params->staMac, &cmd->peer_macaddr);
921 else
922 WMI_CHAR_ARRAY_TO_MAC_ADDR(params->bssId, &cmd->peer_macaddr);
923 cmd->vdev_id = params->smesessionId;
924 cmd->peer_new_assoc = 1;
925 cmd->peer_associd = params->assocId;
926
927 /*
928 * The target only needs a subset of the flags maintained in the host.
929 * Just populate those flags and send it down
930 */
931 cmd->peer_flags = 0;
932
933 if (params->wmmEnabled)
934 cmd->peer_flags |= WMI_PEER_QOS;
935
936 if (params->uAPSD) {
937 cmd->peer_flags |= WMI_PEER_APSD;
938 WMA_LOGD("Set WMI_PEER_APSD: uapsd Mask %d", params->uAPSD);
939 }
940
941 if (params->htCapable) {
942 cmd->peer_flags |= (WMI_PEER_HT | WMI_PEER_QOS);
943 cmd->peer_rate_caps |= WMI_RC_HT_FLAG;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800944
Krishna Kumaar Natarajan59f546c2016-02-16 10:31:55 -0800945 if (params->ch_width) {
946 cmd->peer_flags |= WMI_PEER_40MHZ;
947 cmd->peer_rate_caps |= WMI_RC_CW40_FLAG;
948 if (params->fShortGI40Mhz)
949 cmd->peer_rate_caps |= WMI_RC_SGI_FLAG;
950 } else if (params->fShortGI20Mhz) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800951 cmd->peer_rate_caps |= WMI_RC_SGI_FLAG;
Krishna Kumaar Natarajan59f546c2016-02-16 10:31:55 -0800952 }
953 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800954
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800955 if (params->vhtCapable) {
956 cmd->peer_flags |= (WMI_PEER_HT | WMI_PEER_VHT | WMI_PEER_QOS);
957 cmd->peer_rate_caps |= WMI_RC_HT_FLAG;
958 }
959
960 if (params->ch_width == CH_WIDTH_80MHZ)
961 cmd->peer_flags |= WMI_PEER_80MHZ;
962 else if (params->ch_width == CH_WIDTH_160MHZ)
963 cmd->peer_flags |= WMI_PEER_160MHZ;
964 else if (params->ch_width == CH_WIDTH_80P80MHZ)
965 cmd->peer_flags |= WMI_PEER_160MHZ;
966
967 cmd->peer_vht_caps = params->vht_caps;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800968
969 if (params->rmfEnabled)
970 cmd->peer_flags |= WMI_PEER_PMF;
971
972 rx_stbc = (params->ht_caps & IEEE80211_HTCAP_C_RXSTBC) >>
973 IEEE80211_HTCAP_C_RXSTBC_S;
974 if (rx_stbc) {
975 cmd->peer_flags |= WMI_PEER_STBC;
976 cmd->peer_rate_caps |= (rx_stbc << WMI_RC_RX_STBC_FLAG_S);
977 }
978
979 tx_stbc = (params->ht_caps & IEEE80211_HTCAP_C_TXSTBC) >>
980 IEEE80211_HTCAP_C_TXSTBC_S;
981 if (tx_stbc) {
982 cmd->peer_flags |= WMI_PEER_STBC;
983 cmd->peer_rate_caps |= (tx_stbc << WMI_RC_TX_STBC_FLAG_S);
984 }
985
986 if (params->htLdpcCapable || params->vhtLdpcCapable)
987 cmd->peer_flags |= WMI_PEER_LDPC;
988
989 switch (params->mimoPS) {
990 case eSIR_HT_MIMO_PS_STATIC:
991 cmd->peer_flags |= WMI_PEER_STATIC_MIMOPS;
992 break;
993 case eSIR_HT_MIMO_PS_DYNAMIC:
994 cmd->peer_flags |= WMI_PEER_DYN_MIMOPS;
995 break;
996 case eSIR_HT_MIMO_PS_NO_LIMIT:
997 cmd->peer_flags |= WMI_PEER_SPATIAL_MUX;
998 break;
999 default:
1000 break;
1001 }
1002
1003#ifdef FEATURE_WLAN_TDLS
1004 if (STA_ENTRY_TDLS_PEER == params->staType)
1005 cmd->peer_flags |= WMI_PEER_AUTH;
1006#endif /* FEATURE_WLAN_TDLS */
1007
1008 if (params->wpa_rsn
1009#ifdef FEATURE_WLAN_WAPI
1010 || params->encryptType == eSIR_ED_WPI
1011#endif /* FEATURE_WLAN_WAPI */
1012 )
1013 cmd->peer_flags |= WMI_PEER_NEED_PTK_4_WAY;
1014 if (params->wpa_rsn >> 1)
1015 cmd->peer_flags |= WMI_PEER_NEED_GTK_2_WAY;
1016
Poddar, Siddarth5a91f5b2016-04-28 12:24:10 +05301017 wma_unified_peer_state_update(pdev, params->staMac,
1018 params->bssId, params->staType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001019
1020#ifdef FEATURE_WLAN_WAPI
1021 if (params->encryptType == eSIR_ED_WPI) {
Govind Singhd76a5b02016-03-08 15:12:14 +05301022 ret = wma_vdev_set_param(wma->wmi_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001023 params->smesessionId,
1024 WMI_VDEV_PARAM_DROP_UNENCRY,
1025 false);
1026 if (ret) {
1027 WMA_LOGE
1028 ("Set WMI_VDEV_PARAM_DROP_UNENCRY Param status:%d\n",
1029 ret);
Govind Singhb30d4c02016-03-24 11:01:23 +05301030 qdf_mem_free(cmd);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001031 return ret;
1032 }
1033 }
1034#endif /* FEATURE_WLAN_WAPI */
1035
1036 cmd->peer_caps = params->capab_info;
1037 cmd->peer_listen_intval = params->listenInterval;
1038 cmd->peer_ht_caps = params->ht_caps;
1039 cmd->peer_max_mpdu = (1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR +
1040 params->maxAmpduSize)) - 1;
1041 cmd->peer_mpdu_density = wma_parse_mpdudensity(params->maxAmpduDensity);
1042
1043 if (params->supportedRates.supportedMCSSet[1] &&
1044 params->supportedRates.supportedMCSSet[2])
1045 cmd->peer_rate_caps |= WMI_RC_TS_FLAG;
1046 else if (params->supportedRates.supportedMCSSet[1])
1047 cmd->peer_rate_caps |= WMI_RC_DS_FLAG;
1048
1049 /* Update peer legacy rate information */
Govind Singhb30d4c02016-03-24 11:01:23 +05301050 cmd->peer_legacy_rates.num_rates = peer_legacy_rates.num_rates;
1051 qdf_mem_copy(cmd->peer_legacy_rates.rates, peer_legacy_rates.rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001052 peer_legacy_rates.num_rates);
1053
1054 /* Update peer HT rate information */
Govind Singhb30d4c02016-03-24 11:01:23 +05301055 cmd->peer_ht_rates.num_rates = peer_ht_rates.num_rates;
1056 qdf_mem_copy(cmd->peer_ht_rates.rates, peer_ht_rates.rates,
1057 peer_ht_rates.num_rates);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001058
1059 /* VHT Rates */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001060
1061 cmd->peer_nss = peer_nss;
Naveen Rawatb14cab32015-11-02 17:01:51 -08001062 /*
1063 * Because of DBS a vdev may come up in any of the two MACs with
1064 * different capabilities. STBC capab should be fetched for given
1065 * hard_mode->MAC_id combo. It is planned that firmware should provide
1066 * these dev capabilities. But for now number of tx streams can be used
1067 * to identify if Tx STBC needs to be disabled.
1068 */
1069 if (intr->tx_streams < 2) {
1070 cmd->peer_vht_caps &= ~(1 << SIR_MAC_VHT_CAP_TXSTBC);
1071 WMA_LOGD("Num tx_streams: %d, Disabled txSTBC",
1072 intr->tx_streams);
1073 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001074 WMA_LOGD("peer_nss %d peer_ht_rates.num_rates %d ", cmd->peer_nss,
1075 peer_ht_rates.num_rates);
1076
Govind Singhb30d4c02016-03-24 11:01:23 +05301077 cmd->vht_capable = params->vhtCapable;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001078 if (params->vhtCapable) {
1079#define VHT2x2MCSMASK 0xc
Govind Singhb30d4c02016-03-24 11:01:23 +05301080 cmd->rx_max_rate = params->supportedRates.vhtRxHighestDataRate;
1081 cmd->rx_mcs_set = params->supportedRates.vhtRxMCSMap;
1082 cmd->tx_max_rate = params->supportedRates.vhtTxHighestDataRate;
1083 cmd->tx_mcs_set = params->supportedRates.vhtTxMCSMap;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001084
1085 if (params->vhtSupportedRxNss) {
1086 cmd->peer_nss = params->vhtSupportedRxNss;
1087 } else {
Govind Singhb30d4c02016-03-24 11:01:23 +05301088 cmd->peer_nss = ((cmd->rx_mcs_set & VHT2x2MCSMASK)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001089 == VHT2x2MCSMASK) ? 1 : 2;
1090 }
1091 }
1092
1093 /*
1094 * Limit nss to max number of rf chain supported by target
1095 * Otherwise Fw will crash
1096 */
1097 wma_update_txrx_chainmask(wma->num_rf_chains, &cmd->peer_nss);
1098
1099 intr->nss = cmd->peer_nss;
1100 cmd->peer_phymode = phymode;
1101 WMA_LOGD("%s: vdev_id %d associd %d peer_flags %x rate_caps %x "
1102 "peer_caps %x listen_intval %d ht_caps %x max_mpdu %d "
1103 "nss %d phymode %d peer_mpdu_density %d encr_type %d "
1104 "cmd->peer_vht_caps %x", __func__,
1105 cmd->vdev_id, cmd->peer_associd, cmd->peer_flags,
1106 cmd->peer_rate_caps, cmd->peer_caps,
1107 cmd->peer_listen_intval, cmd->peer_ht_caps,
1108 cmd->peer_max_mpdu, cmd->peer_nss, cmd->peer_phymode,
1109 cmd->peer_mpdu_density, params->encryptType,
1110 cmd->peer_vht_caps);
1111
Govind Singhb30d4c02016-03-24 11:01:23 +05301112 status = wmi_unified_peer_assoc_send(wma->wmi_handle,
1113 cmd);
1114 if (QDF_IS_STATUS_ERROR(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001115 WMA_LOGP("%s: Failed to send peer assoc command ret = %d",
1116 __func__, ret);
Govind Singhb30d4c02016-03-24 11:01:23 +05301117 qdf_mem_free(cmd);
1118
1119 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001120}
1121
1122/**
1123 * wmi_unified_vdev_set_gtx_cfg_send() - set GTX params
1124 * @wmi_handle: wmi handle
1125 * @if_id: vdev id
1126 * @gtx_info: GTX config params
1127 *
1128 * This function set GTX related params in firmware.
1129 *
1130 * Return: 0 for success or error code
1131 */
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301132QDF_STATUS wmi_unified_vdev_set_gtx_cfg_send(wmi_unified_t wmi_handle,
1133 uint32_t if_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001134 gtx_config_t *gtx_info)
1135{
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301136 struct wmi_gtx_config params;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001137
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301138 params.gtx_rt_mask[0] = gtx_info->gtxRTMask[0];
1139 params.gtx_rt_mask[1] = gtx_info->gtxRTMask[1];
1140 params.gtx_usrcfg = gtx_info->gtxUsrcfg;
1141 params.gtx_threshold = gtx_info->gtxPERThreshold;
1142 params.gtx_margin = gtx_info->gtxPERMargin;
1143 params.gtx_tpcstep = gtx_info->gtxTPCstep;
1144 params.gtx_tpcmin = gtx_info->gtxTPCMin;
1145 params.gtx_bwmask = gtx_info->gtxBWMask;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001146
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301147 return wmi_unified_vdev_set_gtx_cfg_cmd(wmi_handle,
1148 if_id, &params);
1149
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001150}
1151
1152/**
1153 * wma_update_protection_mode() - update protection mode
1154 * @wma: wma handle
1155 * @vdev_id: vdev id
1156 * @llbcoexist: protection mode info
1157 *
1158 * This function set protection mode(RTS/CTS) to fw for passed vdev id.
1159 *
1160 * Return: none
1161 */
1162void wma_update_protection_mode(tp_wma_handle wma, uint8_t vdev_id,
1163 uint8_t llbcoexist)
1164{
Govind Singhd76a5b02016-03-08 15:12:14 +05301165 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001166 enum ieee80211_protmode prot_mode;
1167
1168 prot_mode = llbcoexist ? IEEE80211_PROT_CTSONLY : IEEE80211_PROT_NONE;
1169
Govind Singhd76a5b02016-03-08 15:12:14 +05301170 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001171 WMI_VDEV_PARAM_PROTECTION_MODE,
1172 prot_mode);
1173
Govind Singhd76a5b02016-03-08 15:12:14 +05301174 if (QDF_IS_STATUS_ERROR(ret))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001175 WMA_LOGE("Failed to send wmi protection mode cmd");
1176 else
1177 WMA_LOGD("Updated protection mode %d to target", prot_mode);
1178}
1179
1180/**
1181 * wma_update_beacon_interval() - update beacon interval in fw
1182 * @wma: wma handle
1183 * @vdev_id: vdev id
1184 * @beaconInterval: becon interval
1185 *
1186 * Return: none
1187 */
1188static void
1189wma_update_beacon_interval(tp_wma_handle wma, uint8_t vdev_id,
1190 uint16_t beaconInterval)
1191{
Govind Singhd76a5b02016-03-08 15:12:14 +05301192 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001193
Govind Singhd76a5b02016-03-08 15:12:14 +05301194 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001195 WMI_VDEV_PARAM_BEACON_INTERVAL,
1196 beaconInterval);
1197
Govind Singhd76a5b02016-03-08 15:12:14 +05301198 if (QDF_IS_STATUS_ERROR(ret))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001199 WMA_LOGE("Failed to update beacon interval");
1200 else
1201 WMA_LOGI("Updated beacon interval %d for vdev %d",
1202 beaconInterval, vdev_id);
1203}
1204
1205/**
1206 * wma_process_update_beacon_params() - update beacon parameters to target
1207 * @wma: wma handle
1208 * @bcn_params: beacon parameters
1209 *
1210 * Return: none
1211 */
1212void
1213wma_process_update_beacon_params(tp_wma_handle wma,
1214 tUpdateBeaconParams *bcn_params)
1215{
1216 if (!bcn_params) {
1217 WMA_LOGE("bcn_params NULL");
1218 return;
1219 }
1220
1221 if (bcn_params->smeSessionId >= wma->max_bssid) {
1222 WMA_LOGE("Invalid vdev id %d", bcn_params->smeSessionId);
1223 return;
1224 }
1225
1226 if (bcn_params->paramChangeBitmap & PARAM_BCN_INTERVAL_CHANGED) {
1227 wma_update_beacon_interval(wma, bcn_params->smeSessionId,
1228 bcn_params->beaconInterval);
1229 }
1230
1231 if (bcn_params->paramChangeBitmap & PARAM_llBCOEXIST_CHANGED)
1232 wma_update_protection_mode(wma, bcn_params->smeSessionId,
1233 bcn_params->llbCoexist);
1234}
1235
1236/**
1237 * wma_update_cfg_params() - update cfg parameters to target
1238 * @wma: wma handle
1239 * @cfgParam: cfg parameter
1240 *
1241 * Return: none
1242 */
1243void wma_update_cfg_params(tp_wma_handle wma, tSirMsgQ *cfgParam)
1244{
1245 uint8_t vdev_id;
1246 uint32_t param_id;
1247 uint32_t cfg_val;
Govind Singhd76a5b02016-03-08 15:12:14 +05301248 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001249 /* get mac to acess CFG data base */
1250 struct sAniSirGlobal *pmac;
1251
1252 switch (cfgParam->bodyval) {
1253 case WNI_CFG_RTS_THRESHOLD:
1254 param_id = WMI_VDEV_PARAM_RTS_THRESHOLD;
1255 break;
1256 case WNI_CFG_FRAGMENTATION_THRESHOLD:
1257 param_id = WMI_VDEV_PARAM_FRAGMENTATION_THRESHOLD;
1258 break;
1259 default:
1260 WMA_LOGD("Unhandled cfg parameter %d", cfgParam->bodyval);
1261 return;
1262 }
1263
Anurag Chouhan6d760662016-02-20 16:05:43 +05301264 pmac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001265
1266 if (NULL == pmac) {
1267 WMA_LOGE("%s: Failed to get pmac", __func__);
1268 return;
1269 }
1270
1271 if (wlan_cfg_get_int(pmac, (uint16_t) cfgParam->bodyval,
1272 &cfg_val) != eSIR_SUCCESS) {
1273 WMA_LOGE("Failed to get value for CFG PARAMS %d. returning without updating",
1274 cfgParam->bodyval);
1275 return;
1276 }
1277
1278 for (vdev_id = 0; vdev_id < wma->max_bssid; vdev_id++) {
1279 if (wma->interfaces[vdev_id].handle != 0) {
Govind Singhd76a5b02016-03-08 15:12:14 +05301280 ret = wma_vdev_set_param(wma->wmi_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001281 vdev_id, param_id,
1282 cfg_val);
Govind Singhd76a5b02016-03-08 15:12:14 +05301283 if (QDF_IS_STATUS_ERROR(ret))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001284 WMA_LOGE("Update cfg params failed for vdevId %d",
1285 vdev_id);
1286 }
1287 }
1288}
1289
1290/**
1291 * wma_read_cfg_wepkey() - fill key_info for WEP key
1292 * @wma_handle: wma handle
1293 * @key_info: key_info ptr
1294 * @def_key_idx: default key index
1295 * @num_keys: number of keys
1296 *
1297 * This function reads WEP keys from cfg and fills
1298 * up key_info.
1299 *
1300 * Return: none
1301 */
1302static void wma_read_cfg_wepkey(tp_wma_handle wma_handle,
1303 tSirKeys *key_info, uint32_t *def_key_idx,
1304 uint8_t *num_keys)
1305{
1306 tSirRetStatus status;
1307 uint32_t val = SIR_MAC_KEY_LENGTH;
1308 uint8_t i, j;
1309
1310 WMA_LOGD("Reading WEP keys from cfg");
1311 /* NOTE:def_key_idx is initialized to 0 by the caller */
1312 status = wlan_cfg_get_int(wma_handle->mac_context,
1313 WNI_CFG_WEP_DEFAULT_KEYID, def_key_idx);
1314 if (status != eSIR_SUCCESS)
1315 WMA_LOGE("Unable to read default id, defaulting to 0");
1316
1317 for (i = 0, j = 0; i < SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS; i++) {
1318 status = wlan_cfg_get_str(wma_handle->mac_context,
1319 (uint16_t) WNI_CFG_WEP_DEFAULT_KEY_1 +
1320 i, key_info[j].key, &val);
1321 if (status != eSIR_SUCCESS) {
1322 WMA_LOGE("WEP key is not configured at :%d", i);
1323 } else {
1324 key_info[j].keyId = i;
1325 key_info[j].keyLength = (uint16_t) val;
1326 j++;
1327 }
1328 }
1329 *num_keys = j;
1330}
1331
1332/**
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301333 * wma_setup_install_key_cmd() - set key parameters
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001334 * @wma_handle: wma handle
1335 * @key_params: key parameters
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001336 * @mode: op mode
1337 *
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301338 * This function fills structure from information
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001339 * passed in key_params.
1340 *
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301341 * Return: QDF_STATUS_SUCCESS - success
1342 QDF_STATUS_E_FAILURE - failure
1343 QDF_STATUS_E_NOMEM - invalid request
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001344 */
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301345static QDF_STATUS wma_setup_install_key_cmd(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001346 struct wma_set_key_params
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301347 *key_params, uint8_t mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001348{
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301349 struct set_key_params params;
1350 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001351#ifdef WLAN_FEATURE_11W
1352 struct wma_txrx_node *iface = NULL;
1353#endif /* WLAN_FEATURE_11W */
1354 if ((key_params->key_type == eSIR_ED_NONE &&
1355 key_params->key_len) || (key_params->key_type != eSIR_ED_NONE &&
1356 !key_params->key_len)) {
1357 WMA_LOGE("%s:Invalid set key request", __func__);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301358 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001359 }
1360
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301361 params.vdev_id = key_params->vdev_id;
1362 params.key_idx = key_params->key_idx;
1363 qdf_mem_copy(params.peer_mac, key_params->peer_mac, IEEE80211_ADDR_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001364
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301365#ifdef FEATURE_WLAN_WAPI
1366 qdf_mem_set(params.tx_iv, 16, 0);
1367 qdf_mem_set(params.rx_iv, 16, 0);
1368#endif
1369 params.key_txmic_len = 0;
1370 params.key_rxmic_len = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001371
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301372 params.key_flags = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001373 if (key_params->unicast)
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301374 params.key_flags |= PAIRWISE_USAGE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001375 else
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301376 params.key_flags |= GROUP_USAGE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001377
1378 switch (key_params->key_type) {
1379 case eSIR_ED_NONE:
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301380 params.key_cipher = WMI_CIPHER_NONE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001381 break;
1382 case eSIR_ED_WEP40:
1383 case eSIR_ED_WEP104:
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301384 params.key_cipher = WMI_CIPHER_WEP;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001385 if (key_params->unicast &&
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301386 params.key_idx == key_params->def_key_idx) {
Ganesh Kondabattini59a4a952015-11-30 11:55:40 +05301387 WMA_LOGD("STA Mode: cmd->key_flags |= TX_USAGE");
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301388 params.key_flags |= TX_USAGE;
Ganesh Kondabattini59a4a952015-11-30 11:55:40 +05301389 } else if ((mode == wlan_op_mode_ap) &&
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301390 (params.key_idx == key_params->def_key_idx)) {
Ganesh Kondabattini59a4a952015-11-30 11:55:40 +05301391 WMA_LOGD("AP Mode: cmd->key_flags |= TX_USAGE");
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301392 params.key_flags |= TX_USAGE;
Ganesh Kondabattini59a4a952015-11-30 11:55:40 +05301393 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001394 break;
1395 case eSIR_ED_TKIP:
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301396 params.key_txmic_len = WMA_TXMIC_LEN;
1397 params.key_rxmic_len = WMA_RXMIC_LEN;
1398 params.key_cipher = WMI_CIPHER_TKIP;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001399 break;
1400#ifdef FEATURE_WLAN_WAPI
1401#define WPI_IV_LEN 16
1402 case eSIR_ED_WPI:
1403 {
1404 /*initialize receive and transmit IV with default values */
1405 /* **Note: tx_iv must be sent in reverse** */
1406 unsigned char tx_iv[16] = { 0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c,
1407 0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c,
1408 0x36, 0x5c, 0x36, 0x5c};
1409 unsigned char rx_iv[16] = { 0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36,
1410 0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36,
1411 0x5c, 0x36, 0x5c, 0x37};
1412 if (mode == wlan_op_mode_ap) {
1413 /* Authenticator initializes the value of PN as
1414 * 0x5C365C365C365C365C365C365C365C36 for MCastkey Update
1415 */
1416 if (key_params->unicast)
1417 tx_iv[0] = 0x37;
1418
1419 rx_iv[WPI_IV_LEN - 1] = 0x36;
1420 } else {
1421 if (!key_params->unicast)
1422 rx_iv[WPI_IV_LEN - 1] = 0x36;
1423 }
1424
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301425 params.key_txmic_len = WMA_TXMIC_LEN;
1426 params.key_rxmic_len = WMA_RXMIC_LEN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001427
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301428 qdf_mem_copy(&params.rx_iv, &rx_iv,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001429 WPI_IV_LEN);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301430 qdf_mem_copy(&params.tx_iv, &tx_iv,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001431 WPI_IV_LEN);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301432 params.key_cipher = WMI_CIPHER_WAPI;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001433 break;
1434 }
1435#endif /* FEATURE_WLAN_WAPI */
1436 case eSIR_ED_CCMP:
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301437 params.key_cipher = WMI_CIPHER_AES_CCM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001438 break;
1439#ifdef WLAN_FEATURE_11W
1440 case eSIR_ED_AES_128_CMAC:
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301441 params.key_cipher = WMI_CIPHER_AES_CMAC;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001442 break;
1443#endif /* WLAN_FEATURE_11W */
1444 default:
1445 /* TODO: MFP ? */
1446 WMA_LOGE("%s:Invalid encryption type:%d", __func__,
1447 key_params->key_type);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301448 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001449 }
1450
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001451#ifdef BIG_ENDIAN_HOST
1452 {
1453 /* for big endian host, copy engine byte_swap is enabled
1454 * But the key data content is in network byte order
1455 * Need to byte swap the key data content - so when copy engine
1456 * does byte_swap - target gets key_data content in the correct
1457 * order.
1458 */
1459 int8_t i;
1460 uint32_t *destp, *srcp;
1461
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301462 destp = (uint32_t *) params.key_data;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001463 srcp = (uint32_t *) key_params->key_data;
1464 for (i = 0;
1465 i < roundup(key_params->key_len, sizeof(uint32_t)) / 4;
1466 i++) {
1467 *destp = le32_to_cpu(*srcp);
1468 destp++;
1469 srcp++;
1470 }
1471 }
1472#else
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301473 qdf_mem_copy((void *)params.key_data,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001474 (const void *)key_params->key_data, key_params->key_len);
1475#endif /* BIG_ENDIAN_HOST */
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301476 params.key_len = key_params->key_len;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001477
1478#ifdef WLAN_FEATURE_11W
1479 if (key_params->key_type == eSIR_ED_AES_128_CMAC) {
1480 iface = &wma_handle->interfaces[key_params->vdev_id];
1481 if (iface) {
1482 iface->key.key_length = key_params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301483 qdf_mem_copy(iface->key.key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001484 (const void *)key_params->key_data,
1485 iface->key.key_length);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301486 if ((params.key_idx == WMA_IGTK_KEY_INDEX_4) ||
1487 (params.key_idx == WMA_IGTK_KEY_INDEX_5))
1488 qdf_mem_zero(iface->key.key_id[params.key_idx -
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001489 WMA_IGTK_KEY_INDEX_4].ipn,
1490 CMAC_IPN_LEN);
1491 }
1492 }
1493#endif /* WLAN_FEATURE_11W */
1494
1495 WMA_LOGD("Key setup : vdev_id %d key_idx %d key_type %d key_len %d"
1496 " unicast %d peer_mac %pM def_key_idx %d", key_params->vdev_id,
1497 key_params->key_idx, key_params->key_type, key_params->key_len,
1498 key_params->unicast, key_params->peer_mac,
1499 key_params->def_key_idx);
1500
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301501 status = wmi_unified_setup_install_key_cmd(wma_handle->wmi_handle,
1502 &params);
1503
1504 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001505}
1506
1507/**
1508 * wma_set_bsskey() - set encryption key to fw.
1509 * @wma_handle: wma handle
1510 * @key_info: key info
1511 *
1512 * Return: none
1513 */
1514void wma_set_bsskey(tp_wma_handle wma_handle, tpSetBssKeyParams key_info)
1515{
1516 struct wma_set_key_params key_params;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301517 QDF_STATUS status = QDF_STATUS_SUCCESS;
1518 uint32_t i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001519 uint32_t def_key_idx = 0;
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001520 uint32_t wlan_opmode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001521 ol_txrx_vdev_handle txrx_vdev;
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001522 uint8_t *mac_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001523
1524 WMA_LOGD("BSS key setup");
1525 txrx_vdev = wma_find_vdev_by_id(wma_handle, key_info->smesessionId);
1526 if (!txrx_vdev) {
1527 WMA_LOGE("%s:Invalid vdev handle", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301528 key_info->status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001529 goto out;
1530 }
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001531 wlan_opmode = ol_txrx_get_opmode(txrx_vdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001532
1533 /*
1534 * For IBSS, WMI expects the BSS key to be set per peer key
1535 * So cache the BSS key in the wma_handle and re-use it when the
1536 * STA key is been setup for a peer
1537 */
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001538 if (wlan_op_mode_ibss == wlan_opmode) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301539 key_info->status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001540 if (wma_handle->ibss_started > 0)
1541 goto out;
1542 WMA_LOGD("Caching IBSS Key");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301543 qdf_mem_copy(&wma_handle->ibsskey_info, key_info,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001544 sizeof(tSetBssKeyParams));
1545 }
1546
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301547 qdf_mem_set(&key_params, sizeof(key_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001548 key_params.vdev_id = key_info->smesessionId;
1549 key_params.key_type = key_info->encType;
1550 key_params.singl_tid_rc = key_info->singleTidRc;
1551 key_params.unicast = false;
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001552 if (wlan_opmode == wlan_op_mode_sta) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301553 qdf_mem_copy(key_params.peer_mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001554 wma_handle->interfaces[key_info->smesessionId].bssid,
1555 IEEE80211_ADDR_LEN);
1556 } else {
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001557 mac_addr = ol_txrx_get_vdev_mac_addr(txrx_vdev);
1558 if (mac_addr == NULL) {
1559 WMA_LOGE("%s: mac_addr is NULL for vdev with id %d",
1560 __func__, key_info->smesessionId);
1561 goto out;
1562 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001563 /* vdev mac address will be passed for all other modes */
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001564 qdf_mem_copy(key_params.peer_mac, mac_addr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001565 IEEE80211_ADDR_LEN);
1566 WMA_LOGA("BSS Key setup with vdev_mac %pM\n",
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001567 mac_addr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001568 }
1569
1570 if (key_info->numKeys == 0 &&
1571 (key_info->encType == eSIR_ED_WEP40 ||
1572 key_info->encType == eSIR_ED_WEP104)) {
1573 wma_read_cfg_wepkey(wma_handle, key_info->key,
1574 &def_key_idx, &key_info->numKeys);
1575 }
1576
1577 for (i = 0; i < key_info->numKeys; i++) {
1578 if (key_params.key_type != eSIR_ED_NONE &&
1579 !key_info->key[i].keyLength)
1580 continue;
1581 if (key_info->encType == eSIR_ED_WPI) {
1582 key_params.key_idx = key_info->key[i].keyId;
1583 key_params.def_key_idx = key_info->key[i].keyId;
1584 } else
1585 key_params.key_idx = key_info->key[i].keyId;
1586
1587 key_params.key_len = key_info->key[i].keyLength;
1588 if (key_info->encType == eSIR_ED_TKIP) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301589 qdf_mem_copy(key_params.key_data,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001590 key_info->key[i].key, 16);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301591 qdf_mem_copy(&key_params.key_data[16],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001592 &key_info->key[i].key[24], 8);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301593 qdf_mem_copy(&key_params.key_data[24],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001594 &key_info->key[i].key[16], 8);
1595 } else
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301596 qdf_mem_copy((void *)key_params.key_data,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001597 (const void *)key_info->key[i].key,
1598 key_info->key[i].keyLength);
1599
1600 WMA_LOGD("%s: bss key[%d] length %d", __func__, i,
1601 key_info->key[i].keyLength);
1602
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301603 status = wma_setup_install_key_cmd(wma_handle, &key_params,
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001604 wlan_opmode);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301605 if (status == QDF_STATUS_E_NOMEM) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001606 WMA_LOGE("%s:Failed to setup install key buf",
1607 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301608 key_info->status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001609 goto out;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301610 } else if (status == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001611 WMA_LOGE("%s:Failed to send install key command",
1612 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301613 key_info->status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001614 goto out;
1615 }
1616 }
1617
1618 wma_handle->ibss_started++;
1619 /* TODO: Should we wait till we get HTT_T2H_MSG_TYPE_SEC_IND? */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301620 key_info->status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001621
1622out:
1623 wma_send_msg(wma_handle, WMA_SET_BSSKEY_RSP, (void *)key_info, 0);
1624}
1625
1626#ifdef QCA_IBSS_SUPPORT
1627/**
1628 * wma_calc_ibss_heart_beat_timer() - calculate IBSS heart beat timer
1629 * @peer_num: number of peers
1630 *
1631 * Return: heart beat timer value
1632 */
1633static uint16_t wma_calc_ibss_heart_beat_timer(int16_t peer_num)
1634{
1635 /* heart beat timer value look-up table */
1636 /* entry index : (the number of currently connected peers) - 1
1637 entry value : the heart time threshold value in seconds for
1638 detecting ibss peer departure */
1639 static const uint16_t heart_beat_timer[MAX_IBSS_PEERS] = {
1640 4, 4, 4, 4, 4, 4, 4, 4,
1641 8, 8, 8, 8, 8, 8, 8, 8,
1642 12, 12, 12, 12, 12, 12, 12, 12,
1643 16, 16, 16, 16, 16, 16, 16, 16
1644 };
1645
1646 if (peer_num < 1 || peer_num > MAX_IBSS_PEERS)
1647 return 0;
1648
1649 return heart_beat_timer[peer_num - 1];
1650
1651}
1652
1653/**
1654 * wma_adjust_ibss_heart_beat_timer() - set ibss heart beat timer in fw.
1655 * @wma: wma handle
1656 * @vdev_id: vdev id
1657 * @peer_num_delta: peer number delta value
1658 *
1659 * Return: none
1660 */
1661void wma_adjust_ibss_heart_beat_timer(tp_wma_handle wma,
1662 uint8_t vdev_id,
1663 int8_t peer_num_delta)
1664{
1665 ol_txrx_vdev_handle vdev;
1666 int16_t new_peer_num;
1667 uint16_t new_timer_value_sec;
1668 uint32_t new_timer_value_ms;
Govind Singhd76a5b02016-03-08 15:12:14 +05301669 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001670
1671 if (peer_num_delta != 1 && peer_num_delta != -1) {
1672 WMA_LOGE("Invalid peer_num_delta value %d", peer_num_delta);
1673 return;
1674 }
1675
1676 vdev = wma_find_vdev_by_id(wma, vdev_id);
1677 if (!vdev) {
1678 WMA_LOGE("vdev not found : vdev_id %d", vdev_id);
1679 return;
1680 }
1681
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001682 /* adjust peer numbers */
1683 new_peer_num = ol_txrx_update_ibss_add_peer_num_of_vdev(vdev,
1684 peer_num_delta);
1685 if (OL_TXRX_INVALID_NUM_PEERS == new_peer_num) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001686 WMA_LOGE("new peer num %d out of valid boundary", new_peer_num);
1687 return;
1688 }
1689
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001690 /* reset timer value if all peers departed */
1691 if (new_peer_num == 0) {
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001692 ol_txrx_set_ibss_vdev_heart_beat_timer(vdev, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001693 return;
1694 }
1695
1696 /* calculate new timer value */
1697 new_timer_value_sec = wma_calc_ibss_heart_beat_timer(new_peer_num);
1698 if (new_timer_value_sec == 0) {
1699 WMA_LOGE("timer value %d is invalid for peer number %d",
1700 new_timer_value_sec, new_peer_num);
1701 return;
1702 }
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001703 if (new_timer_value_sec ==
1704 ol_txrx_set_ibss_vdev_heart_beat_timer(vdev, new_timer_value_sec)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001705 WMA_LOGD("timer value %d stays same, no need to notify target",
1706 new_timer_value_sec);
1707 return;
1708 }
1709
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001710 new_timer_value_ms = ((uint32_t) new_timer_value_sec) * 1000;
1711
Govind Singhd76a5b02016-03-08 15:12:14 +05301712 status = wma_vdev_set_param(wma->wmi_handle, vdev_id,
1713 WMI_VDEV_PARAM_IBSS_MAX_BCN_LOST_MS,
1714 new_timer_value_ms);
1715 if (QDF_IS_STATUS_ERROR(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001716 WMA_LOGE("Failed to set IBSS link monitoring timer value");
1717 return;
1718 }
1719
1720 WMA_LOGD("Set IBSS link monitor timer: peer_num = %d timer_value = %d",
1721 new_peer_num, new_timer_value_ms);
1722}
1723
1724#endif /* QCA_IBSS_SUPPORT */
1725/**
1726 * wma_set_ibsskey_helper() - cached IBSS key in wma handle
1727 * @wma_handle: wma handle
1728 * @key_info: set bss key info
1729 * @peerMacAddr: peer mac address
1730 *
1731 * Return: none
1732 */
1733static void wma_set_ibsskey_helper(tp_wma_handle wma_handle,
1734 tpSetBssKeyParams key_info,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301735 struct qdf_mac_addr peer_macaddr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001736{
1737 struct wma_set_key_params key_params;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301738 QDF_STATUS status = QDF_STATUS_SUCCESS;
1739 uint32_t i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001740 uint32_t def_key_idx = 0;
1741 ol_txrx_vdev_handle txrx_vdev;
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001742 int opmode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001743
1744 WMA_LOGD("BSS key setup for peer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001745 txrx_vdev = wma_find_vdev_by_id(wma_handle, key_info->smesessionId);
1746 if (!txrx_vdev) {
1747 WMA_LOGE("%s:Invalid vdev handle", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301748 key_info->status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001749 return;
1750 }
1751
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301752 qdf_mem_set(&key_params, sizeof(key_params), 0);
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001753 opmode = ol_txrx_get_opmode(txrx_vdev);
1754 qdf_mem_set(&key_params, sizeof(key_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001755 key_params.vdev_id = key_info->smesessionId;
1756 key_params.key_type = key_info->encType;
1757 key_params.singl_tid_rc = key_info->singleTidRc;
1758 key_params.unicast = false;
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001759 ASSERT(wlan_op_mode_ibss == opmode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001760
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301761 qdf_mem_copy(key_params.peer_mac, peer_macaddr.bytes,
Srinivas Girigowdad5965c42015-12-04 13:43:16 -08001762 IEEE80211_ADDR_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001763
1764 if (key_info->numKeys == 0 &&
1765 (key_info->encType == eSIR_ED_WEP40 ||
1766 key_info->encType == eSIR_ED_WEP104)) {
1767 wma_read_cfg_wepkey(wma_handle, key_info->key,
1768 &def_key_idx, &key_info->numKeys);
1769 }
1770
1771 for (i = 0; i < key_info->numKeys; i++) {
1772 if (key_params.key_type != eSIR_ED_NONE &&
1773 !key_info->key[i].keyLength)
1774 continue;
1775 key_params.key_idx = key_info->key[i].keyId;
1776 key_params.key_len = key_info->key[i].keyLength;
1777 if (key_info->encType == eSIR_ED_TKIP) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301778 qdf_mem_copy(key_params.key_data,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001779 key_info->key[i].key, 16);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301780 qdf_mem_copy(&key_params.key_data[16],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001781 &key_info->key[i].key[24], 8);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301782 qdf_mem_copy(&key_params.key_data[24],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001783 &key_info->key[i].key[16], 8);
1784 } else
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301785 qdf_mem_copy((void *)key_params.key_data,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001786 (const void *)key_info->key[i].key,
1787 key_info->key[i].keyLength);
1788
1789 WMA_LOGD("%s: peer bcast key[%d] length %d", __func__, i,
1790 key_info->key[i].keyLength);
1791
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301792 status = wma_setup_install_key_cmd(wma_handle, &key_params,
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001793 opmode);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301794 if (status == QDF_STATUS_E_NOMEM) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001795 WMA_LOGE("%s:Failed to setup install key buf",
1796 __func__);
1797 return;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301798 } else if (status == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001799 WMA_LOGE("%s:Failed to send install key command",
1800 __func__);
1801 }
1802 }
1803}
1804
1805/**
1806 * wma_set_stakey() - set encryption key
1807 * @wma_handle: wma handle
1808 * @key_info: station key info
1809 *
1810 * This function sets encryption key for WEP/WPA/WPA2
1811 * encryption mode in firmware and send response to upper layer.
1812 *
1813 * Return: none
1814 */
1815void wma_set_stakey(tp_wma_handle wma_handle, tpSetStaKeyParams key_info)
1816{
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301817 int32_t i;
1818 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001819 ol_txrx_pdev_handle txrx_pdev;
1820 ol_txrx_vdev_handle txrx_vdev;
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001821 ol_txrx_peer_handle peer;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001822 uint8_t num_keys = 0, peer_id;
1823 struct wma_set_key_params key_params;
1824 uint32_t def_key_idx = 0;
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001825 int opmode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001826
1827 WMA_LOGD("STA key setup");
1828
1829 /* Get the txRx Pdev handle */
Anurag Chouhan6d760662016-02-20 16:05:43 +05301830 txrx_pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001831 if (!txrx_pdev) {
1832 WMA_LOGE("%s:Invalid txrx pdev handle", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301833 key_info->status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001834 goto out;
1835 }
1836
Srinivas Girigowdad5965c42015-12-04 13:43:16 -08001837 peer = ol_txrx_find_peer_by_addr(txrx_pdev,
1838 key_info->peer_macaddr.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001839 &peer_id);
1840 if (!peer) {
1841 WMA_LOGE("%s:Invalid peer for key setting", __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 }
1845
1846 txrx_vdev = wma_find_vdev_by_id(wma_handle, key_info->smesessionId);
1847 if (!txrx_vdev) {
1848 WMA_LOGE("%s:TxRx Vdev Handle is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301849 key_info->status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001850 goto out;
1851 }
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001852 opmode = ol_txrx_get_opmode(txrx_vdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001853
1854 if (key_info->defWEPIdx == WMA_INVALID_KEY_IDX &&
1855 (key_info->encType == eSIR_ED_WEP40 ||
1856 key_info->encType == eSIR_ED_WEP104) &&
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001857 opmode != wlan_op_mode_ap) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001858 wma_read_cfg_wepkey(wma_handle, key_info->key,
1859 &def_key_idx, &num_keys);
1860 key_info->defWEPIdx = def_key_idx;
1861 } else {
1862 num_keys = SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS;
1863 if (key_info->encType != eSIR_ED_NONE) {
1864 for (i = 0; i < num_keys; i++) {
1865 if (key_info->key[i].keyDirection ==
1866 eSIR_TX_DEFAULT) {
1867 key_info->defWEPIdx = i;
1868 break;
1869 }
1870 }
1871 }
1872 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301873 qdf_mem_set(&key_params, sizeof(key_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001874 key_params.vdev_id = key_info->smesessionId;
1875 key_params.key_type = key_info->encType;
1876 key_params.singl_tid_rc = key_info->singleTidRc;
1877 key_params.unicast = true;
1878 key_params.def_key_idx = key_info->defWEPIdx;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301879 qdf_mem_copy((void *)key_params.peer_mac,
Srinivas Girigowdad5965c42015-12-04 13:43:16 -08001880 (const void *)key_info->peer_macaddr.bytes,
1881 IEEE80211_ADDR_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001882 for (i = 0; i < num_keys; i++) {
1883 if (key_params.key_type != eSIR_ED_NONE &&
1884 !key_info->key[i].keyLength)
1885 continue;
1886 if (key_info->encType == eSIR_ED_TKIP) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301887 qdf_mem_copy(key_params.key_data,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001888 key_info->key[i].key, 16);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301889 qdf_mem_copy(&key_params.key_data[16],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001890 &key_info->key[i].key[24], 8);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301891 qdf_mem_copy(&key_params.key_data[24],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001892 &key_info->key[i].key[16], 8);
1893 } else
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301894 qdf_mem_copy(key_params.key_data, key_info->key[i].key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001895 key_info->key[i].keyLength);
1896 if (key_info->encType == eSIR_ED_WPI) {
1897 key_params.key_idx = key_info->key[i].keyId;
1898 key_params.def_key_idx = key_info->key[i].keyId;
1899 } else
1900 key_params.key_idx = i;
1901
1902 key_params.key_len = key_info->key[i].keyLength;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301903 status = wma_setup_install_key_cmd(wma_handle, &key_params,
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001904 opmode);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301905 if (status == QDF_STATUS_E_NOMEM) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001906 WMA_LOGE("%s:Failed to setup install key buf",
1907 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301908 key_info->status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001909 goto out;
1910 }
1911
1912 WMA_LOGD("%s: peer unicast key[%d] %d ", __func__, i,
1913 key_info->key[i].keyLength);
1914
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301915 if (status == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001916 WMA_LOGE("%s:Failed to send install key command",
1917 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301918 key_info->status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001919 goto out;
1920 }
1921 }
1922
1923 /* In IBSS mode, set the BSS KEY for this peer
1924 * BSS key is supposed to be cache into wma_handle
1925 */
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001926 if (wlan_op_mode_ibss == opmode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001927 wma_set_ibsskey_helper(wma_handle, &wma_handle->ibsskey_info,
Srinivas Girigowdad5965c42015-12-04 13:43:16 -08001928 key_info->peer_macaddr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001929 }
1930
1931 /* TODO: Should we wait till we get HTT_T2H_MSG_TYPE_SEC_IND? */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301932 key_info->status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001933out:
1934 if (key_info->sendRsp)
1935 wma_send_msg(wma_handle, WMA_SET_STAKEY_RSP, (void *)key_info,
1936 0);
1937}
1938
1939/**
1940 * wma_process_update_edca_param_req() - update EDCA params
1941 * @handle: wma handle
1942 * @edca_params: edca parameters
1943 *
1944 * This function updates EDCA parameters to the target
1945 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05301946 * Return: QDF Status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001947 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301948QDF_STATUS wma_process_update_edca_param_req(WMA_HANDLE handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001949 tEdcaParams *edca_params)
1950{
1951 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301952 wmi_wmm_vparams wmm_param[WME_NUM_AC];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001953 tSirMacEdcaParamRecord *edca_record;
1954 int ac;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001955 ol_txrx_pdev_handle pdev;
1956 struct ol_tx_wmm_param_t ol_tx_wmm_param;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301957 uint8_t vdev_id;
1958 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001959
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301960 vdev_id = edca_params->bssIdx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001961
1962 for (ac = 0; ac < WME_NUM_AC; ac++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001963 switch (ac) {
1964 case WME_AC_BE:
1965 edca_record = &edca_params->acbe;
1966 break;
1967 case WME_AC_BK:
1968 edca_record = &edca_params->acbk;
1969 break;
1970 case WME_AC_VI:
1971 edca_record = &edca_params->acvi;
1972 break;
1973 case WME_AC_VO:
1974 edca_record = &edca_params->acvo;
1975 break;
1976 default:
1977 goto fail;
1978 }
1979
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301980 wma_update_edca_params_for_ac(edca_record, &wmm_param[ac], ac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001981
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301982 ol_tx_wmm_param.ac[ac].aifs = wmm_param[ac].aifs;
1983 ol_tx_wmm_param.ac[ac].cwmin = wmm_param[ac].cwmin;
1984 ol_tx_wmm_param.ac[ac].cwmax = wmm_param[ac].cwmax;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001985 }
1986
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301987 status = wmi_unified_process_update_edca_param(wma_handle->wmi_handle,
1988 vdev_id, wmm_param);
1989 if (status == QDF_STATUS_E_NOMEM)
1990 return status;
1991 else if (status == QDF_STATUS_E_FAILURE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001992 goto fail;
1993
Anurag Chouhan6d760662016-02-20 16:05:43 +05301994 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Himanshu Agarwal94045e42015-10-19 19:16:19 +05301995 if (pdev)
1996 ol_txrx_set_wmm_param(pdev, ol_tx_wmm_param);
1997 else
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301998 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001999
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302000 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002001
2002fail:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002003 WMA_LOGE("%s: Failed to set WMM Paremeters", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302004 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002005}
2006
2007/**
2008 * wmi_unified_probe_rsp_tmpl_send() - send probe response template to fw
2009 * @wma: wma handle
2010 * @vdev_id: vdev id
2011 * @probe_rsp_info: probe response info
2012 *
2013 * Return: 0 for success or error code
2014 */
2015static int wmi_unified_probe_rsp_tmpl_send(tp_wma_handle wma,
2016 uint8_t vdev_id,
2017 tpSendProbeRespParams probe_rsp_info)
2018{
Himanshu Agarwal009f1572016-03-09 17:26:02 +05302019 uint8_t *frm;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002020 uint64_t adjusted_tsf_le;
2021 struct ieee80211_frame *wh;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05302022 struct wmi_probe_resp_params params;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002023
2024 WMA_LOGD(FL("Send probe response template for vdev %d"), vdev_id);
2025
2026 frm = probe_rsp_info->pProbeRespTemplate;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05302027
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002028 /*
2029 * Make the TSF offset negative so probe response in the same
2030 * staggered batch have the same TSF.
2031 */
2032 adjusted_tsf_le = cpu_to_le64(0ULL -
2033 wma->interfaces[vdev_id].tsfadjust);
2034 /* Update the timstamp in the probe response buffer with adjusted TSF */
2035 wh = (struct ieee80211_frame *)frm;
2036 A_MEMCPY(&wh[1], &adjusted_tsf_le, sizeof(adjusted_tsf_le));
2037
Himanshu Agarwal009f1572016-03-09 17:26:02 +05302038 params.pProbeRespTemplate = probe_rsp_info->pProbeRespTemplate;
2039 params.probeRespTemplateLen = probe_rsp_info->probeRespTemplateLen;
2040 qdf_mem_copy(params.bssId, probe_rsp_info->bssId,
Krunal Soniab793342016-04-22 18:43:20 -07002041 IEEE80211_ADDR_LEN);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05302042 qdf_mem_copy(params.ucProxyProbeReqValidIEBmap,
2043 probe_rsp_info->ucProxyProbeReqValidIEBmap,
2044 8 * sizeof(uint32_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002045
Himanshu Agarwal009f1572016-03-09 17:26:02 +05302046 return wmi_unified_probe_rsp_tmpl_send_cmd(wma->wmi_handle, vdev_id,
2047 &params, frm);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002048}
2049
2050/**
Govind Singh61ad2622016-02-22 17:25:02 +05302051 * wma_unified_bcn_tmpl_send() - send beacon template to fw
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002052 * @wma:wma handle
2053 * @vdev_id: vdev id
2054 * @bcn_info: beacon info
2055 * @bytes_to_strip: bytes to strip
2056 *
Govind Singh61ad2622016-02-22 17:25:02 +05302057 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002058 */
Govind Singh61ad2622016-02-22 17:25:02 +05302059static QDF_STATUS wma_unified_bcn_tmpl_send(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002060 uint8_t vdev_id,
Govind Singh61ad2622016-02-22 17:25:02 +05302061 const tpSendbeaconParams bcn_info,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002062 uint8_t bytes_to_strip)
2063{
Govind Singh61ad2622016-02-22 17:25:02 +05302064 struct beacon_params params = {0};
2065 uint32_t tmpl_len, tmpl_len_aligned;
2066 uint8_t *frm;
2067 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002068 uint8_t *p2p_ie;
2069 uint16_t p2p_ie_len = 0;
2070 uint64_t adjusted_tsf_le;
2071 struct ieee80211_frame *wh;
2072
2073 WMA_LOGD("Send beacon template for vdev %d", vdev_id);
2074
2075 if (bcn_info->p2pIeOffset) {
2076 p2p_ie = bcn_info->beacon + bcn_info->p2pIeOffset;
2077 p2p_ie_len = (uint16_t) p2p_ie[1] + 2;
2078 }
2079
2080 /*
2081 * XXX: The first byte of beacon buffer contains beacon length
2082 * only when UMAC in sending the beacon template. In othercases
2083 * (ex: from tbtt update) beacon length is read from beacon
2084 * information.
2085 */
2086 if (bytes_to_strip)
2087 tmpl_len = *(uint32_t *) &bcn_info->beacon[0];
2088 else
2089 tmpl_len = bcn_info->beaconLength;
2090 if (p2p_ie_len) {
2091 tmpl_len -= (uint32_t) p2p_ie_len;
2092 }
2093
2094 frm = bcn_info->beacon + bytes_to_strip;
2095 tmpl_len_aligned = roundup(tmpl_len, sizeof(A_UINT32));
2096 /*
2097 * Make the TSF offset negative so beacons in the same
2098 * staggered batch have the same TSF.
2099 */
2100 adjusted_tsf_le = cpu_to_le64(0ULL -
2101 wma->interfaces[vdev_id].tsfadjust);
2102 /* Update the timstamp in the beacon buffer with adjusted TSF */
2103 wh = (struct ieee80211_frame *)frm;
2104 A_MEMCPY(&wh[1], &adjusted_tsf_le, sizeof(adjusted_tsf_le));
2105
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002106
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002107
Govind Singh61ad2622016-02-22 17:25:02 +05302108 params.vdev_id = vdev_id;
2109 params.tim_ie_offset = bcn_info->timIeOffset - bytes_to_strip;
2110 params.tmpl_len = tmpl_len;
2111 params.frm = frm;
2112 params.tmpl_len_aligned = tmpl_len_aligned;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002113
Govind Singh61ad2622016-02-22 17:25:02 +05302114 ret = wmi_unified_beacon_send_cmd(wma->wmi_handle,
2115 &params);
2116 if (QDF_IS_STATUS_ERROR(ret)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002117 WMA_LOGE("%s: Failed to send bcn tmpl: %d", __func__, ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002118 }
2119
2120 return ret;
2121}
2122
2123/**
2124 * wma_store_bcn_tmpl() - store beacon template
2125 * @wma: wma handle
2126 * @vdev_id: vdev id
2127 * @bcn_info: beacon params
2128 *
2129 * This function stores beacon template locally.
2130 * This will send to target on the reception of
2131 * SWBA event.
2132 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302133 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002134 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302135QDF_STATUS wma_store_bcn_tmpl(tp_wma_handle wma, uint8_t vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002136 tpSendbeaconParams bcn_info)
2137{
2138 struct beacon_info *bcn;
2139 uint32_t len;
2140 uint8_t *bcn_payload;
2141 struct beacon_tim_ie *tim_ie;
2142
2143 bcn = wma->interfaces[vdev_id].beacon;
2144 if (!bcn || !bcn->buf) {
2145 WMA_LOGE("%s: Memory is not allocated to hold bcn template",
2146 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302147 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002148 }
2149
2150 len = *(u32 *) &bcn_info->beacon[0];
2151 if (len > WMA_BCN_BUF_MAX_SIZE) {
2152 WMA_LOGE("%s: Received beacon len %d exceeding max limit %d",
2153 __func__, len, WMA_BCN_BUF_MAX_SIZE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302154 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002155 }
2156 WMA_LOGD("%s: Storing received beacon template buf to local buffer",
2157 __func__);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302158 qdf_spin_lock_bh(&bcn->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002159
2160 /*
2161 * Copy received beacon template content in local buffer.
2162 * this will be send to target on the reception of SWBA
2163 * event from target.
2164 */
Nirav Shahcbc6d722016-03-01 16:24:53 +05302165 qdf_nbuf_trim_tail(bcn->buf, qdf_nbuf_len(bcn->buf));
2166 memcpy(qdf_nbuf_data(bcn->buf),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002167 bcn_info->beacon + 4 /* Exclude beacon length field */,
2168 len);
2169 if (bcn_info->timIeOffset > 3) {
2170 bcn->tim_ie_offset = bcn_info->timIeOffset - 4;
2171 } else {
2172 bcn->tim_ie_offset = bcn_info->timIeOffset;
2173 }
2174
2175 if (bcn_info->p2pIeOffset > 3) {
2176 bcn->p2p_ie_offset = bcn_info->p2pIeOffset - 4;
2177 } else {
2178 bcn->p2p_ie_offset = bcn_info->p2pIeOffset;
2179 }
Nirav Shahcbc6d722016-03-01 16:24:53 +05302180 bcn_payload = qdf_nbuf_data(bcn->buf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002181 if (bcn->tim_ie_offset) {
2182 tim_ie =
2183 (struct beacon_tim_ie *)(&bcn_payload[bcn->tim_ie_offset]);
2184 /*
2185 * Intial Value of bcn->dtim_count will be 0.
2186 * But if the beacon gets updated then current dtim
2187 * count will be restored
2188 */
2189 tim_ie->dtim_count = bcn->dtim_count;
2190 tim_ie->tim_bitctl = 0;
2191 }
2192
Nirav Shahcbc6d722016-03-01 16:24:53 +05302193 qdf_nbuf_put_tail(bcn->buf, len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002194 bcn->len = len;
2195
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302196 qdf_spin_unlock_bh(&bcn->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002197
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302198 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002199}
2200
2201/**
2202 * wma_tbttoffset_update_event_handler() - tbtt offset update handler
2203 * @handle: wma handle
2204 * @event: event buffer
2205 * @len: data length
2206 *
2207 * Return: 0 for success or error code
2208 */
2209int wma_tbttoffset_update_event_handler(void *handle, uint8_t *event,
2210 uint32_t len)
2211{
2212 tp_wma_handle wma = (tp_wma_handle) handle;
2213 WMI_TBTTOFFSET_UPDATE_EVENTID_param_tlvs *param_buf;
2214 wmi_tbtt_offset_event_fixed_param *tbtt_offset_event;
2215 struct wma_txrx_node *intf;
2216 struct beacon_info *bcn;
2217 tSendbeaconParams bcn_info;
2218 uint32_t *adjusted_tsf = NULL;
2219 uint32_t if_id = 0, vdev_map;
2220
2221 if (!wma) {
2222 WMA_LOGE("Invalid wma handle");
2223 return -EINVAL;
2224 }
2225
2226 param_buf = (WMI_TBTTOFFSET_UPDATE_EVENTID_param_tlvs *) event;
2227 if (!param_buf) {
2228 WMA_LOGE("Invalid tbtt update event buffer");
2229 return -EINVAL;
2230 }
2231
2232 tbtt_offset_event = param_buf->fixed_param;
2233 intf = wma->interfaces;
2234 vdev_map = tbtt_offset_event->vdev_map;
2235 adjusted_tsf = param_buf->tbttoffset_list;
2236 if (!adjusted_tsf) {
2237 WMA_LOGE("%s: Invalid adjusted_tsf", __func__);
2238 return -EINVAL;
2239 }
2240
2241 for (; (vdev_map); vdev_map >>= 1, if_id++) {
2242 if (!(vdev_map & 0x1) || (!(intf[if_id].handle)))
2243 continue;
2244
2245 bcn = intf[if_id].beacon;
2246 if (!bcn) {
2247 WMA_LOGE("%s: Invalid beacon", __func__);
2248 return -EINVAL;
2249 }
2250 if (!bcn->buf) {
2251 WMA_LOGE("%s: Invalid beacon buffer", __func__);
2252 return -EINVAL;
2253 }
2254 /* Save the adjusted TSF */
2255 intf[if_id].tsfadjust = adjusted_tsf[if_id];
2256
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302257 qdf_spin_lock_bh(&bcn->lock);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302258 qdf_mem_zero(&bcn_info, sizeof(bcn_info));
Nirav Shahcbc6d722016-03-01 16:24:53 +05302259 bcn_info.beacon = qdf_nbuf_data(bcn->buf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002260 bcn_info.p2pIeOffset = bcn->p2p_ie_offset;
2261 bcn_info.beaconLength = bcn->len;
2262 bcn_info.timIeOffset = bcn->tim_ie_offset;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302263 qdf_spin_unlock_bh(&bcn->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002264
2265 /* Update beacon template in firmware */
Govind Singh61ad2622016-02-22 17:25:02 +05302266 wma_unified_bcn_tmpl_send(wma, if_id, &bcn_info, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002267 }
2268 return 0;
2269}
2270
2271/**
2272 * wma_p2p_go_set_beacon_ie() - set beacon IE for p2p go
2273 * @wma_handle: wma handle
2274 * @vdev_id: vdev id
2275 * @p2pIe: p2p IE
2276 *
2277 * Return: 0 for success or error code
2278 */
2279static int wma_p2p_go_set_beacon_ie(t_wma_handle *wma_handle,
2280 A_UINT32 vdev_id, uint8_t *p2pIe)
2281{
Himanshu Agarwal009f1572016-03-09 17:26:02 +05302282 if (!wma_handle) {
2283 WMA_LOGE("%s: wma handle is NULL", __func__);
2284 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002285 }
2286
Himanshu Agarwal009f1572016-03-09 17:26:02 +05302287 return wmi_unified_p2p_go_set_beacon_ie_cmd(wma_handle->wmi_handle,
2288 vdev_id, p2pIe);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002289}
2290
2291/**
2292 * wma_send_probe_rsp_tmpl() - send probe resp template
2293 * @wma: wma handle
2294 * @probe_rsp_info: probe response info
2295 *
2296 * This funciton sends probe response template to fw which
2297 * firmware will use in case of probe response offload.
2298 *
2299 * Return: none
2300 */
2301void wma_send_probe_rsp_tmpl(tp_wma_handle wma,
2302 tpSendProbeRespParams probe_rsp_info)
2303{
2304 ol_txrx_vdev_handle vdev;
2305 uint8_t vdev_id;
2306 tpAniProbeRspStruct probe_rsp;
2307
2308 if (!probe_rsp_info) {
2309 WMA_LOGE(FL("probe_rsp_info is NULL"));
2310 return;
2311 }
2312
2313 probe_rsp = (tpAniProbeRspStruct) (probe_rsp_info->pProbeRespTemplate);
2314 if (!probe_rsp) {
2315 WMA_LOGE(FL("probe_rsp is NULL"));
2316 return;
2317 }
2318
2319 vdev = wma_find_vdev_by_addr(wma, probe_rsp->macHdr.sa, &vdev_id);
2320 if (!vdev) {
2321 WMA_LOGE(FL("failed to get vdev handle"));
2322 return;
2323 }
2324
2325 if (WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
2326 WMI_SERVICE_BEACON_OFFLOAD)) {
2327 WMA_LOGI("Beacon Offload Enabled Sending Unified command");
2328 if (wmi_unified_probe_rsp_tmpl_send(wma, vdev_id,
2329 probe_rsp_info) < 0) {
2330 WMA_LOGE(FL("wmi_unified_probe_rsp_tmpl_send Failed "));
2331 return;
2332 }
2333 }
2334}
2335
2336/**
2337 * wma_send_beacon() - send beacon template
2338 * @wma: wma handle
2339 * @bcn_info: beacon info
2340 *
2341 * This funciton store beacon template locally and
2342 * update keep alive parameters
2343 *
2344 * Return: none
2345 */
2346void wma_send_beacon(tp_wma_handle wma, tpSendbeaconParams bcn_info)
2347{
2348 ol_txrx_vdev_handle vdev;
2349 uint8_t vdev_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302350 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002351 uint8_t *p2p_ie;
2352 tpAniBeaconStruct beacon;
Govind Singhd76a5b02016-03-08 15:12:14 +05302353 struct vdev_up_params param = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002354
2355 beacon = (tpAniBeaconStruct) (bcn_info->beacon);
2356 vdev = wma_find_vdev_by_addr(wma, beacon->macHdr.sa, &vdev_id);
2357 if (!vdev) {
2358 WMA_LOGE("%s : failed to get vdev handle", __func__);
2359 return;
2360 }
2361
2362 if (WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
2363 WMI_SERVICE_BEACON_OFFLOAD)) {
2364 WMA_LOGI("Beacon Offload Enabled Sending Unified command");
Govind Singh61ad2622016-02-22 17:25:02 +05302365 status = wma_unified_bcn_tmpl_send(wma, vdev_id, bcn_info, 4);
2366 if (QDF_IS_STATUS_ERROR(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002367 WMA_LOGE("%s : wmi_unified_bcn_tmpl_send Failed ",
2368 __func__);
2369 return;
2370 }
2371
2372 if (bcn_info->p2pIeOffset) {
2373 p2p_ie = bcn_info->beacon + bcn_info->p2pIeOffset;
2374 WMA_LOGI
2375 (" %s: p2pIe is present - vdev_id %hu, p2p_ie = %p, p2p ie len = %hu",
2376 __func__, vdev_id, p2p_ie, p2p_ie[1]);
2377 if (wma_p2p_go_set_beacon_ie(wma, vdev_id, p2p_ie) < 0) {
2378 WMA_LOGE
2379 ("%s : wmi_unified_bcn_tmpl_send Failed ",
2380 __func__);
2381 return;
2382 }
2383 }
2384 }
2385 status = wma_store_bcn_tmpl(wma, vdev_id, bcn_info);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302386 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002387 WMA_LOGE("%s : wma_store_bcn_tmpl Failed", __func__);
2388 return;
2389 }
2390 if (!wma->interfaces[vdev_id].vdev_up) {
Govind Singhd76a5b02016-03-08 15:12:14 +05302391 param.vdev_id = vdev_id;
2392 param.assoc_id = 0;
2393 status = wmi_unified_vdev_up_send(wma->wmi_handle,
2394 bcn_info->bssId,
2395 &param);
2396 if (QDF_IS_STATUS_ERROR(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002397 WMA_LOGE("%s : failed to send vdev up", __func__);
Manishekar Chandrasekarancb052172016-04-22 12:19:04 +05302398 cds_set_do_hw_mode_change_flag(false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002399 return;
2400 }
2401 wma->interfaces[vdev_id].vdev_up = true;
2402 wma_set_sap_keepalive(wma, vdev_id);
2403 }
2404}
2405
2406/**
2407 * wma_set_keepalive_req() - send keep alive request to fw
2408 * @wma: wma handle
2409 * @keepalive: keep alive parameters
2410 *
2411 * Return: none
2412 */
2413void wma_set_keepalive_req(tp_wma_handle wma,
2414 tSirKeepAliveReq *keepalive)
2415{
2416 WMA_LOGD("KEEPALIVE:PacketType:%d", keepalive->packetType);
2417 wma_set_sta_keep_alive(wma, keepalive->sessionId,
2418 keepalive->packetType,
2419 keepalive->timePeriod,
2420 keepalive->hostIpv4Addr,
Srinivas Girigowda9c330a92015-11-24 12:28:25 -08002421 keepalive->destIpv4Addr,
2422 keepalive->dest_macaddr.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002423
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302424 qdf_mem_free(keepalive);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002425}
2426
2427/**
2428 * wma_beacon_miss_handler() - beacon miss event handler
2429 * @wma: wma handle
2430 * @vdev_id: vdev id
2431 *
2432 * This function send beacon miss indication to upper layers.
2433 *
2434 * Return: none
2435 */
2436void wma_beacon_miss_handler(tp_wma_handle wma, uint32_t vdev_id)
2437{
2438 tSirSmeMissedBeaconInd *beacon_miss_ind;
2439
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302440 beacon_miss_ind = (tSirSmeMissedBeaconInd *) qdf_mem_malloc
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002441 (sizeof(tSirSmeMissedBeaconInd));
2442
2443 if (NULL == beacon_miss_ind) {
2444 WMA_LOGE("%s: Memory allocation failure", __func__);
2445 return;
2446 }
2447 beacon_miss_ind->messageType = WMA_MISSED_BEACON_IND;
2448 beacon_miss_ind->length = sizeof(tSirSmeMissedBeaconInd);
2449 beacon_miss_ind->bssIdx = vdev_id;
2450
2451 wma_send_msg(wma, WMA_MISSED_BEACON_IND, (void *)beacon_miss_ind, 0);
2452}
2453
2454/**
2455 * wma_mgmt_tx_completion_handler() - wma mgmt Tx completion event handler
2456 * @handle: wma handle
2457 * @cmpl_event_params: completion event handler data
2458 * @len: length of @cmpl_event_params
2459 *
2460 * Return: 0 on success; error number otherwise
2461 */
2462
2463int wma_mgmt_tx_completion_handler(void *handle, uint8_t *cmpl_event_params,
2464 uint32_t len)
2465{
2466 tp_wma_handle wma_handle = (tp_wma_handle)handle;
2467 WMI_MGMT_TX_COMPLETION_EVENTID_param_tlvs *param_buf;
2468 wmi_mgmt_tx_compl_event_fixed_param *cmpl_params;
2469 struct wmi_desc_t *wmi_desc;
2470
Anurag Chouhan6d760662016-02-20 16:05:43 +05302471 ol_txrx_pdev_handle pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002472
Naveen Rawat35804772016-06-27 15:40:28 -07002473 if (pdev == NULL) {
2474 WMA_LOGE("%s: NULL pdev pointer", __func__);
2475 return -EINVAL;
2476 }
2477
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002478 param_buf = (WMI_MGMT_TX_COMPLETION_EVENTID_param_tlvs *)
2479 cmpl_event_params;
Naveen Rawat35804772016-06-27 15:40:28 -07002480 if (!param_buf || !wma_handle) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002481 WMA_LOGE("%s: Invalid mgmt Tx completion event", __func__);
2482 return -EINVAL;
2483 }
2484 cmpl_params = param_buf->fixed_param;
2485
2486 WMA_LOGI("%s: status:%d wmi_desc_id:%d", __func__, cmpl_params->status,
2487 cmpl_params->desc_id);
2488
2489 wmi_desc = (struct wmi_desc_t *)
2490 (&wma_handle->wmi_desc_pool.array[cmpl_params->desc_id]);
2491
2492 if (!wmi_desc) {
2493 WMA_LOGE("%s: Invalid wmi desc", __func__);
2494 return -EINVAL;
2495 }
2496
2497 if (wmi_desc->nbuf)
Nirav Shahcbc6d722016-03-01 16:24:53 +05302498 qdf_nbuf_unmap_single(pdev->osdev, wmi_desc->nbuf,
Anurag Chouhan6d760662016-02-20 16:05:43 +05302499 QDF_DMA_TO_DEVICE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002500 if (wmi_desc->tx_cmpl_cb)
2501 wmi_desc->tx_cmpl_cb(wma_handle->mac_context,
2502 wmi_desc->nbuf, 1);
2503
2504 if (wmi_desc->ota_post_proc_cb)
2505 wmi_desc->ota_post_proc_cb((tpAniSirGlobal)
2506 wma_handle->mac_context,
2507 cmpl_params->status);
2508
2509 wmi_desc_put(wma_handle, wmi_desc);
2510
2511 return 0;
2512}
2513
2514/**
2515 * wma_process_update_opmode() - process update VHT opmode cmd from UMAC
2516 * @wma_handle: wma handle
2517 * @update_vht_opmode: vht opmode
2518 *
2519 * Return: none
2520 */
2521void wma_process_update_opmode(tp_wma_handle wma_handle,
2522 tUpdateVHTOpMode *update_vht_opmode)
2523{
2524 WMA_LOGD("%s: opMode = %d", __func__, update_vht_opmode->opMode);
2525
2526 wma_set_peer_param(wma_handle, update_vht_opmode->peer_mac,
2527 WMI_PEER_CHWIDTH, update_vht_opmode->opMode,
2528 update_vht_opmode->smesessionId);
2529}
2530
2531/**
2532 * wma_process_update_rx_nss() - process update RX NSS cmd from UMAC
2533 * @wma_handle: wma handle
2534 * @update_rx_nss: rx nss value
2535 *
2536 * Return: none
2537 */
2538void wma_process_update_rx_nss(tp_wma_handle wma_handle,
2539 tUpdateRxNss *update_rx_nss)
2540{
2541 struct wma_txrx_node *intr =
2542 &wma_handle->interfaces[update_rx_nss->smesessionId];
2543 int rx_nss = update_rx_nss->rxNss;
2544
2545 wma_update_txrx_chainmask(wma_handle->num_rf_chains, &rx_nss);
2546
2547 intr->nss = (uint8_t)rx_nss;
2548 update_rx_nss->rxNss = (uint32_t)rx_nss;
2549
2550 WMA_LOGD("%s: Rx Nss = %d", __func__, update_rx_nss->rxNss);
2551
2552 wma_set_peer_param(wma_handle, update_rx_nss->peer_mac,
2553 WMI_PEER_NSS, update_rx_nss->rxNss,
2554 update_rx_nss->smesessionId);
2555}
2556
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002557/**
2558 * wma_process_update_membership() - process update group membership cmd
2559 * @wma_handle: wma handle
2560 * @membership: group membership info
2561 *
2562 * Return: none
2563 */
2564void wma_process_update_membership(tp_wma_handle wma_handle,
2565 tUpdateMembership *membership)
2566{
2567 WMA_LOGD("%s: membership = %x ", __func__, membership->membership);
2568
2569 wma_set_peer_param(wma_handle, membership->peer_mac,
2570 WMI_PEER_MEMBERSHIP, membership->membership,
2571 membership->smesessionId);
2572}
2573
2574/**
2575 * wma_process_update_userpos() - process update user pos cmd from UMAC
2576 * @wma_handle: wma handle
2577 * @userpos: user pos value
2578 *
2579 * Return: none
2580 */
2581void wma_process_update_userpos(tp_wma_handle wma_handle,
2582 tUpdateUserPos *userpos)
2583{
2584 WMA_LOGD("%s: userPos = %x ", __func__, userpos->userPos);
2585
2586 wma_set_peer_param(wma_handle, userpos->peer_mac,
2587 WMI_PEER_USERPOS, userpos->userPos,
2588 userpos->smesessionId);
2589
2590 /* Now that membership/userpos is updated in fw,
2591 * enable GID PPS.
2592 */
2593 wma_set_ppsconfig(userpos->smesessionId, WMA_VHT_PPS_GID_MATCH, 1);
2594
2595}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002596
2597/**
2598 * wma_set_htconfig() - set ht config parameters to target
2599 * @vdev_id: vdev id
2600 * @ht_capab: ht capablity
2601 * @value: value of ht param
2602 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302603 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002604 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302605QDF_STATUS wma_set_htconfig(uint8_t vdev_id, uint16_t ht_capab, int value)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002606{
Anurag Chouhan6d760662016-02-20 16:05:43 +05302607 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
Govind Singhd76a5b02016-03-08 15:12:14 +05302608 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002609
2610 if (NULL == wma) {
2611 WMA_LOGE("%s: Failed to get wma", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302612 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002613 }
2614
2615 switch (ht_capab) {
2616 case WNI_CFG_HT_CAP_INFO_ADVANCE_CODING:
Govind Singhd76a5b02016-03-08 15:12:14 +05302617 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002618 WMI_VDEV_PARAM_LDPC,
2619 value);
2620 break;
2621 case WNI_CFG_HT_CAP_INFO_TX_STBC:
Govind Singhd76a5b02016-03-08 15:12:14 +05302622 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002623 WMI_VDEV_PARAM_TX_STBC,
2624 value);
2625 break;
2626 case WNI_CFG_HT_CAP_INFO_RX_STBC:
Govind Singhd76a5b02016-03-08 15:12:14 +05302627 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002628 WMI_VDEV_PARAM_RX_STBC,
2629 value);
2630 break;
2631 case WNI_CFG_HT_CAP_INFO_SHORT_GI_20MHZ:
2632 case WNI_CFG_HT_CAP_INFO_SHORT_GI_40MHZ:
2633 WMA_LOGE("%s: ht_capab = %d, value = %d", __func__, ht_capab,
2634 value);
Govind Singhd76a5b02016-03-08 15:12:14 +05302635 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002636 WMI_VDEV_PARAM_SGI, value);
Govind Singhd76a5b02016-03-08 15:12:14 +05302637 if (ret == QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002638 wma->interfaces[vdev_id].config.shortgi = value;
2639 break;
2640 default:
2641 WMA_LOGE("%s:INVALID HT CONFIG", __func__);
2642 }
2643
Govind Singhd76a5b02016-03-08 15:12:14 +05302644 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002645}
2646
2647/**
2648 * wma_hidden_ssid_vdev_restart() - vdev restart for hidden ssid
2649 * @wma_handle: wma handle
2650 * @pReq: hidden ssid vdev restart request
2651 *
2652 * Return: none
2653 */
2654void wma_hidden_ssid_vdev_restart(tp_wma_handle wma_handle,
2655 tHalHiddenSsidVdevRestart *pReq)
2656{
2657 struct wma_txrx_node *intr = wma_handle->interfaces;
2658
2659 if ((pReq->sessionId !=
2660 intr[pReq->sessionId].vdev_restart_params.vdev_id)
2661 || !((intr[pReq->sessionId].type == WMI_VDEV_TYPE_AP)
2662 && (intr[pReq->sessionId].sub_type == 0))) {
2663 WMA_LOGE("%s : invalid session id", __func__);
2664 return;
2665 }
2666
2667 intr[pReq->sessionId].vdev_restart_params.ssidHidden = pReq->ssidHidden;
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, 1);
2670
2671 /* vdev stop -> vdev restart -> vdev up */
2672 WMA_LOGD("%s, vdev_id: %d, pausing tx_ll_queue for VDEV_STOP",
2673 __func__, pReq->sessionId);
2674 ol_txrx_vdev_pause(wma_handle->interfaces[pReq->sessionId].handle,
2675 OL_TXQ_PAUSE_REASON_VDEV_STOP);
2676 wma_handle->interfaces[pReq->sessionId].pause_bitmap |=
2677 (1 << PAUSE_TYPE_HOST);
2678 if (wmi_unified_vdev_stop_send(wma_handle->wmi_handle, pReq->sessionId)) {
2679 WMA_LOGE("%s: %d Failed to send vdev stop", __func__, __LINE__);
Anurag Chouhan8e0ccd32016-02-19 15:30:20 +05302680 qdf_atomic_set(&intr[pReq->sessionId].vdev_restart_params.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002681 hidden_ssid_restart_in_progress, 0);
2682 return;
2683 }
2684}
2685
2686
2687#ifdef WLAN_FEATURE_11W
2688
2689/**
2690 * wma_extract_ccmp_pn() - extract 6 byte PN from the CCMP header
2691 * @ccmp_ptr: CCMP header
2692 *
2693 * Return: PN extracted from header.
2694 */
2695static uint64_t wma_extract_ccmp_pn(uint8_t *ccmp_ptr)
2696{
2697 uint8_t rsvd, key, pn[6];
2698 uint64_t new_pn;
2699
2700 /*
2701 * +-----+-----+------+----------+-----+-----+-----+-----+
2702 * | PN0 | PN1 | rsvd | rsvd/key | PN2 | PN3 | PN4 | PN5 |
2703 * +-----+-----+------+----------+-----+-----+-----+-----+
2704 * CCMP Header Format
2705 */
2706
2707 /* Extract individual bytes */
2708 pn[0] = (uint8_t) *ccmp_ptr;
2709 pn[1] = (uint8_t) *(ccmp_ptr + 1);
2710 rsvd = (uint8_t) *(ccmp_ptr + 2);
2711 key = (uint8_t) *(ccmp_ptr + 3);
2712 pn[2] = (uint8_t) *(ccmp_ptr + 4);
2713 pn[3] = (uint8_t) *(ccmp_ptr + 5);
2714 pn[4] = (uint8_t) *(ccmp_ptr + 6);
2715 pn[5] = (uint8_t) *(ccmp_ptr + 7);
2716
2717 /* Form 6 byte PN with 6 individual bytes of PN */
2718 new_pn = ((uint64_t) pn[5] << 40) |
2719 ((uint64_t) pn[4] << 32) |
2720 ((uint64_t) pn[3] << 24) |
2721 ((uint64_t) pn[2] << 16) |
2722 ((uint64_t) pn[1] << 8) | ((uint64_t) pn[0] << 0);
2723
2724 WMA_LOGE("PN of received packet is %llu", new_pn);
2725 return new_pn;
2726}
2727
2728/**
2729 * wma_is_ccmp_pn_replay_attack() - detect replay attacking using PN in CCMP
2730 * @cds_ctx: cds context
2731 * @wh: 802.11 frame header
2732 * @ccmp_ptr: CCMP frame header
2733 *
2734 * Return: true/false
2735 */
2736static bool
2737wma_is_ccmp_pn_replay_attack(void *cds_ctx, struct ieee80211_frame *wh,
2738 uint8_t *ccmp_ptr)
2739{
2740 ol_txrx_pdev_handle pdev;
2741 ol_txrx_vdev_handle vdev;
2742 ol_txrx_peer_handle peer;
2743 uint8_t vdev_id, peer_id;
2744 uint8_t *last_pn_valid;
2745 uint64_t *last_pn, new_pn;
2746 uint32_t *rmf_pn_replays;
2747
Anurag Chouhan6d760662016-02-20 16:05:43 +05302748 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002749 if (!pdev) {
2750 WMA_LOGE("%s: Failed to find pdev", __func__);
2751 return true;
2752 }
2753
Mukul Sharmaa748fbb2015-12-01 19:51:36 +05302754 vdev = wma_find_vdev_by_bssid(cds_ctx, wh->i_addr3, &vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002755 if (!vdev) {
2756 WMA_LOGE("%s: Failed to find vdev", __func__);
2757 return true;
2758 }
2759
2760 /* Retrieve the peer based on vdev and addr */
2761 peer = ol_txrx_find_peer_by_addr_and_vdev(pdev, vdev, wh->i_addr2,
2762 &peer_id);
2763
2764 if (NULL == peer) {
2765 WMA_LOGE("%s: Failed to find peer, Not able to validate PN",
2766 __func__);
2767 return true;
2768 }
2769
2770 new_pn = wma_extract_ccmp_pn(ccmp_ptr);
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07002771 ol_txrx_get_pn_info(peer, &last_pn_valid, &last_pn, &rmf_pn_replays);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002772
2773 if (*last_pn_valid) {
2774 if (new_pn > *last_pn) {
2775 *last_pn = new_pn;
2776 WMA_LOGE("%s: PN validation successful", __func__);
2777 } else {
2778 WMA_LOGE("%s: PN Replay attack detected", __func__);
2779 /* per 11W amendment, keeping track of replay attacks */
2780 *rmf_pn_replays += 1;
2781 return true;
2782 }
2783 } else {
2784 *last_pn_valid = 1;
2785 *last_pn = new_pn;
2786 }
2787
2788 return false;
2789}
2790
2791/**
mukul sharma72c8b222015-09-04 17:02:01 +05302792 * wma_process_bip() - process mmie in rmf frame
2793 * @wma_handle: wma handle
2794 * @iface: txrx node
2795 * @wh: 80211 frame
2796 * @wbuf: Buffer
2797 *
2798 * Return: 0 for success or error code
2799 */
2800
2801static
2802int wma_process_bip(tp_wma_handle wma_handle,
2803 struct wma_txrx_node *iface,
2804 struct ieee80211_frame *wh,
Nirav Shahcbc6d722016-03-01 16:24:53 +05302805 qdf_nbuf_t wbuf
mukul sharma72c8b222015-09-04 17:02:01 +05302806)
2807{
2808 uint16_t key_id;
2809 uint8_t *efrm;
2810
Nirav Shahcbc6d722016-03-01 16:24:53 +05302811 efrm = qdf_nbuf_data(wbuf) + qdf_nbuf_len(wbuf);
mukul sharma72c8b222015-09-04 17:02:01 +05302812 key_id = (uint16_t)*(efrm - cds_get_mmie_size() + 2);
2813
2814 if (!((key_id == WMA_IGTK_KEY_INDEX_4)
2815 || (key_id == WMA_IGTK_KEY_INDEX_5))) {
2816 WMA_LOGE(FL("Invalid KeyID(%d) dropping the frame"), key_id);
2817 return -EINVAL;
2818 }
2819 if (WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap,
2820 WMI_SERVICE_STA_PMF_OFFLOAD)) {
2821 /*
2822 * if 11w offload is enabled then mmie validation is performed
2823 * in firmware, host just need to trim the mmie.
2824 */
Nirav Shahcbc6d722016-03-01 16:24:53 +05302825 qdf_nbuf_trim_tail(wbuf, cds_get_mmie_size());
mukul sharma72c8b222015-09-04 17:02:01 +05302826 } else {
2827 if (cds_is_mmie_valid(iface->key.key,
2828 iface->key.key_id[key_id - WMA_IGTK_KEY_INDEX_4].ipn,
2829 (uint8_t *) wh, efrm)) {
2830 WMA_LOGE(FL("Protected BC/MC frame MMIE validation successful"));
2831 /* Remove MMIE */
Nirav Shahcbc6d722016-03-01 16:24:53 +05302832 qdf_nbuf_trim_tail(wbuf, cds_get_mmie_size());
mukul sharma72c8b222015-09-04 17:02:01 +05302833 } else {
2834 WMA_LOGE(FL("BC/MC MIC error or MMIE not present, dropping the frame"));
2835 return -EINVAL;
2836 }
2837 }
2838 return 0;
2839}
2840
2841/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002842 * wma_process_rmf_frame() - process rmf frame
2843 * @wma_handle: wma handle
2844 * @iface: txrx node
2845 * @wh: 80211 frame
2846 * @rx_pkt: rx packet
2847 * @wbuf: Buffer
2848 *
2849 * Return: 0 for success or error code
2850 */
2851static
2852int wma_process_rmf_frame(tp_wma_handle wma_handle,
2853 struct wma_txrx_node *iface,
2854 struct ieee80211_frame *wh,
2855 cds_pkt_t *rx_pkt,
Nirav Shahcbc6d722016-03-01 16:24:53 +05302856 qdf_nbuf_t wbuf)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002857{
mukul sharma72c8b222015-09-04 17:02:01 +05302858 uint8_t *orig_hdr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002859 uint8_t *ccmp;
2860
2861 if ((wh)->i_fc[1] & IEEE80211_FC1_WEP) {
2862 if (IEEE80211_IS_BROADCAST(wh->i_addr1) ||
2863 IEEE80211_IS_MULTICAST(wh->i_addr1)) {
2864 WMA_LOGE("Encrypted BC/MC frame dropping the frame");
2865 cds_pkt_return_packet(rx_pkt);
2866 return -EINVAL;
2867 }
2868
Nirav Shahcbc6d722016-03-01 16:24:53 +05302869 orig_hdr = (uint8_t *) qdf_nbuf_data(wbuf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002870 /* Pointer to head of CCMP header */
2871 ccmp = orig_hdr + sizeof(*wh);
2872 if (wma_is_ccmp_pn_replay_attack(
2873 wma_handle, wh, ccmp)) {
2874 WMA_LOGE("Dropping the frame");
2875 cds_pkt_return_packet(rx_pkt);
2876 return -EINVAL;
2877 }
2878
2879 /* Strip privacy headers (and trailer)
2880 * for a received frame
2881 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302882 qdf_mem_move(orig_hdr +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002883 IEEE80211_CCMP_HEADERLEN, wh,
2884 sizeof(*wh));
Nirav Shahcbc6d722016-03-01 16:24:53 +05302885 qdf_nbuf_pull_head(wbuf,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002886 IEEE80211_CCMP_HEADERLEN);
Nirav Shahcbc6d722016-03-01 16:24:53 +05302887 qdf_nbuf_trim_tail(wbuf, IEEE80211_CCMP_MICLEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002888
2889 rx_pkt->pkt_meta.mpdu_hdr_ptr =
Nirav Shahcbc6d722016-03-01 16:24:53 +05302890 qdf_nbuf_data(wbuf);
2891 rx_pkt->pkt_meta.mpdu_len = qdf_nbuf_len(wbuf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002892 rx_pkt->pkt_meta.mpdu_data_len =
2893 rx_pkt->pkt_meta.mpdu_len -
2894 rx_pkt->pkt_meta.mpdu_hdr_len;
2895 rx_pkt->pkt_meta.mpdu_data_ptr =
2896 rx_pkt->pkt_meta.mpdu_hdr_ptr +
2897 rx_pkt->pkt_meta.mpdu_hdr_len;
2898 rx_pkt->pkt_meta.tsf_delta = rx_pkt->pkt_meta.tsf_delta;
2899 rx_pkt->pkt_buf = wbuf;
2900 WMA_LOGD(FL("BSSID: "MAC_ADDRESS_STR" tsf_delta: %u"),
2901 MAC_ADDR_ARRAY(wh->i_addr3), rx_pkt->pkt_meta.tsf_delta);
2902 } else {
2903 if (IEEE80211_IS_BROADCAST(wh->i_addr1) ||
2904 IEEE80211_IS_MULTICAST(wh->i_addr1)) {
mukul sharma72c8b222015-09-04 17:02:01 +05302905 if (0 != wma_process_bip(wma_handle, iface, wh, wbuf)) {
2906 cds_pkt_return_packet(rx_pkt);
2907 return -EINVAL;
Mukul Sharmaa748fbb2015-12-01 19:51:36 +05302908 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002909 } else {
2910 WMA_LOGE("Rx unprotected unicast mgmt frame");
2911 rx_pkt->pkt_meta.dpuFeedback =
2912 DPU_FEEDBACK_UNPROTECTED_ERROR;
2913 }
2914 }
2915 return 0;
2916}
2917#endif
2918
2919/**
Krishna Kumaar Natarajanb7f9a352016-03-18 11:40:07 -07002920 * wma_is_pkt_drop_candidate() - check if the mgmt frame should be droppped
2921 * @wma_handle: wma handle
2922 * @peer_addr: peer MAC address
2923 * @subtype: Management frame subtype
2924 *
2925 * This function is used to decide if a particular management frame should be
2926 * dropped to prevent DOS attack. Timestamp is used to decide the DOS attack.
2927 *
2928 * Return: true if the packet should be dropped and false oterwise
2929 */
2930static bool wma_is_pkt_drop_candidate(tp_wma_handle wma_handle,
2931 uint8_t *peer_addr, uint8_t subtype)
2932{
2933 struct ol_txrx_peer_t *peer;
2934 struct ol_txrx_pdev_t *pdev_ctx;
2935 uint8_t peer_id;
2936 bool should_drop = false;
2937
2938 /*
2939 * Currently this function handles only Disassoc,
2940 * Deauth and Assoc req frames. Return false for
2941 * all other frames.
2942 */
2943 if (subtype != IEEE80211_FC0_SUBTYPE_DISASSOC &&
2944 subtype != IEEE80211_FC0_SUBTYPE_DEAUTH &&
2945 subtype != IEEE80211_FC0_SUBTYPE_ASSOC_REQ) {
2946 should_drop = false;
2947 goto end;
2948 }
2949
2950 pdev_ctx = cds_get_context(QDF_MODULE_ID_TXRX);
2951 if (!pdev_ctx) {
2952 WMA_LOGE(FL("Failed to get the context"));
2953 should_drop = true;
2954 goto end;
2955 }
2956
2957 peer = ol_txrx_find_peer_by_addr(pdev_ctx, peer_addr, &peer_id);
2958 if (!peer) {
2959 if (SIR_MAC_MGMT_ASSOC_REQ != subtype) {
2960 WMA_LOGI(
2961 FL("Received mgmt frame: %0x from unknow peer: %pM"),
2962 subtype, peer_addr);
2963 should_drop = true;
2964 }
2965 goto end;
2966 }
2967
2968 switch (subtype) {
2969 case SIR_MAC_MGMT_ASSOC_REQ:
2970 if (peer->last_assoc_rcvd) {
2971 if (qdf_get_system_timestamp() - peer->last_assoc_rcvd <
2972 WMA_MGMT_FRAME_DETECT_DOS_TIMER) {
2973 WMA_LOGI(FL("Dropping Assoc Req received"));
2974 should_drop = true;
2975 }
2976 }
2977 peer->last_assoc_rcvd = qdf_get_system_timestamp();
2978 break;
2979 case SIR_MAC_MGMT_DISASSOC:
2980 if (peer->last_disassoc_rcvd) {
2981 if (qdf_get_system_timestamp() -
2982 peer->last_disassoc_rcvd <
2983 WMA_MGMT_FRAME_DETECT_DOS_TIMER) {
2984 WMA_LOGI(FL("Dropping DisAssoc received"));
2985 should_drop = true;
2986 }
2987 }
2988 peer->last_disassoc_rcvd = qdf_get_system_timestamp();
2989 break;
2990 case SIR_MAC_MGMT_DEAUTH:
2991 if (peer->last_deauth_rcvd) {
2992 if (qdf_get_system_timestamp() -
2993 peer->last_deauth_rcvd <
2994 WMA_MGMT_FRAME_DETECT_DOS_TIMER) {
2995 WMA_LOGI(FL("Dropping Deauth received"));
2996 should_drop = true;
2997 }
2998 }
2999 peer->last_deauth_rcvd = qdf_get_system_timestamp();
3000 break;
3001 default:
3002 break;
3003 }
3004
3005end:
3006 return should_drop;
3007}
3008
3009/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003010 * wma_mgmt_rx_process() - process management rx frame.
3011 * @handle: wma handle
3012 * @data: rx data
3013 * @data_len: data length
3014 *
3015 * Return: 0 for success or error code
3016 */
3017static int wma_mgmt_rx_process(void *handle, uint8_t *data,
3018 uint32_t data_len)
3019{
3020 tp_wma_handle wma_handle = (tp_wma_handle) handle;
3021 WMI_MGMT_RX_EVENTID_param_tlvs *param_tlvs = NULL;
3022 wmi_mgmt_rx_hdr *hdr = NULL;
3023 struct wma_txrx_node *iface = NULL;
Mukul Sharmaa748fbb2015-12-01 19:51:36 +05303024 uint8_t vdev_id = WMA_INVALID_VDEV_ID;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003025 cds_pkt_t *rx_pkt;
Nirav Shahcbc6d722016-03-01 16:24:53 +05303026 qdf_nbuf_t wbuf;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003027 struct ieee80211_frame *wh;
3028 uint8_t mgt_type, mgt_subtype;
3029 int status;
3030
3031 if (!wma_handle) {
3032 WMA_LOGE("%s: Failed to get WMA context", __func__);
3033 return -EINVAL;
3034 }
3035
3036 param_tlvs = (WMI_MGMT_RX_EVENTID_param_tlvs *) data;
3037 if (!param_tlvs) {
3038 WMA_LOGE("Get NULL point message from FW");
3039 return -EINVAL;
3040 }
3041
3042 hdr = param_tlvs->hdr;
3043 if (!hdr) {
3044 WMA_LOGE("Rx event is NULL");
3045 return -EINVAL;
3046 }
3047
3048 if (hdr->buf_len < sizeof(struct ieee80211_frame)) {
3049 WMA_LOGE("Invalid rx mgmt packet");
3050 return -EINVAL;
3051 }
3052
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303053 rx_pkt = qdf_mem_malloc(sizeof(*rx_pkt));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003054 if (!rx_pkt) {
3055 WMA_LOGE("Failed to allocate rx packet");
3056 return -ENOMEM;
3057 }
3058
Rajeev Kumarfec3dbe2016-01-19 15:23:52 -08003059 if (cds_is_load_or_unload_in_progress()) {
Krishna Kumaar Natarajan93c9de12016-06-16 17:04:30 -07003060 WMA_LOGW(FL("Load/Unload in progress"));
Naveen Rawat10ccf872015-11-03 14:15:55 -08003061 return -EINVAL;
3062 }
3063
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303064 qdf_mem_zero(rx_pkt, sizeof(*rx_pkt));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003065
3066 /*
3067 * Fill in meta information needed by pe/lim
3068 * TODO: Try to maintain rx metainfo as part of skb->data.
3069 */
3070 rx_pkt->pkt_meta.channel = hdr->channel;
3071 rx_pkt->pkt_meta.scan_src = hdr->flags;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -07003072
3073 /*
3074 * Get the rssi value from the current snr value
3075 * using standard noise floor of -96.
3076 */
3077 rx_pkt->pkt_meta.rssi = hdr->snr + WMA_NOISE_FLOOR_DBM_DEFAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003078 rx_pkt->pkt_meta.snr = hdr->snr;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -07003079
3080 /* If absolute rssi is available from firmware, use it */
3081 if (hdr->rssi != 0)
3082 rx_pkt->pkt_meta.rssi_raw = hdr->rssi;
3083 else
3084 rx_pkt->pkt_meta.rssi_raw = rx_pkt->pkt_meta.rssi;
3085
3086
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003087 /*
3088 * FIXME: Assigning the local timestamp as hw timestamp is not
3089 * available. Need to see if pe/lim really uses this data.
3090 */
3091 rx_pkt->pkt_meta.timestamp = (uint32_t) jiffies;
3092 rx_pkt->pkt_meta.mpdu_hdr_len = sizeof(struct ieee80211_frame);
3093 rx_pkt->pkt_meta.mpdu_len = hdr->buf_len;
3094 rx_pkt->pkt_meta.mpdu_data_len = hdr->buf_len -
3095 rx_pkt->pkt_meta.mpdu_hdr_len;
3096
3097 rx_pkt->pkt_meta.roamCandidateInd = 0;
3098
3099 /* Why not just use rx_event->hdr.buf_len? */
Nirav Shahcbc6d722016-03-01 16:24:53 +05303100 wbuf = qdf_nbuf_alloc(NULL, roundup(hdr->buf_len, 4), 0, 4, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003101 if (!wbuf) {
3102 WMA_LOGE("%s: Failed to allocate wbuf for mgmt rx len(%u)",
3103 __func__, hdr->buf_len);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303104 qdf_mem_free(rx_pkt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003105 return -ENOMEM;
3106 }
3107
Nirav Shahcbc6d722016-03-01 16:24:53 +05303108 qdf_nbuf_put_tail(wbuf, hdr->buf_len);
3109 qdf_nbuf_set_protocol(wbuf, ETH_P_CONTROL);
3110 wh = (struct ieee80211_frame *)qdf_nbuf_data(wbuf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003111
Nirav Shahcbc6d722016-03-01 16:24:53 +05303112 rx_pkt->pkt_meta.mpdu_hdr_ptr = qdf_nbuf_data(wbuf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003113 rx_pkt->pkt_meta.mpdu_data_ptr = rx_pkt->pkt_meta.mpdu_hdr_ptr +
3114 rx_pkt->pkt_meta.mpdu_hdr_len;
3115 rx_pkt->pkt_meta.tsf_delta = hdr->tsf_delta;
3116 rx_pkt->pkt_buf = wbuf;
3117
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003118#ifdef BIG_ENDIAN_HOST
3119 {
3120 /*
3121 * for big endian host, copy engine byte_swap is enabled
3122 * But the rx mgmt frame buffer content is in network byte order
3123 * Need to byte swap the mgmt frame buffer content - so when
3124 * copy engine does byte_swap - host gets buffer content in the
3125 * correct byte order.
3126 */
3127 int i;
3128 uint32_t *destp, *srcp;
3129 destp = (uint32_t *) wh;
3130 srcp = (uint32_t *) param_tlvs->bufp;
3131 for (i = 0;
3132 i < (roundup(hdr->buf_len, sizeof(uint32_t)) / 4); i++) {
3133 *destp = cpu_to_le32(*srcp);
3134 destp++;
3135 srcp++;
3136 }
3137 }
3138#else
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303139 qdf_mem_copy(wh, param_tlvs->bufp, hdr->buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003140#endif
3141
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -07003142 WMA_LOGD(
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303143 FL("BSSID: "MAC_ADDRESS_STR" snr = %d, rssi = %d, rssi_raw = %d tsf_delta: %u"),
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -07003144 MAC_ADDR_ARRAY(wh->i_addr3),
3145 hdr->snr, rx_pkt->pkt_meta.rssi,
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303146 rx_pkt->pkt_meta.rssi_raw,
3147 hdr->tsf_delta);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003148 if (!wma_handle->mgmt_rx) {
3149 WMA_LOGE("Not registered for Mgmt rx, dropping the frame");
3150 cds_pkt_return_packet(rx_pkt);
3151 return -EINVAL;
3152 }
3153
3154 /* If it is a beacon/probe response, save it for future use */
3155 mgt_type = (wh)->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
3156 mgt_subtype = (wh)->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
3157
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003158#ifdef WLAN_FEATURE_11W
3159 if (mgt_type == IEEE80211_FC0_TYPE_MGT &&
3160 (mgt_subtype == IEEE80211_FC0_SUBTYPE_DISASSOC ||
3161 mgt_subtype == IEEE80211_FC0_SUBTYPE_DEAUTH ||
3162 mgt_subtype == IEEE80211_FC0_SUBTYPE_ACTION)) {
Mukul Sharmaa748fbb2015-12-01 19:51:36 +05303163 if (wma_find_vdev_by_bssid(
3164 wma_handle, wh->i_addr3, &vdev_id)) {
3165 iface = &(wma_handle->interfaces[vdev_id]);
3166 if (iface->rmfEnabled) {
3167 status = wma_process_rmf_frame(wma_handle,
3168 iface, wh, rx_pkt, wbuf);
3169 if (status != 0)
3170 return status;
3171 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003172 }
3173 }
3174#endif /* WLAN_FEATURE_11W */
Mukul Sharmaa748fbb2015-12-01 19:51:36 +05303175 rx_pkt->pkt_meta.sessionId =
3176 (vdev_id == WMA_INVALID_VDEV_ID ? 0 : vdev_id);
Krishna Kumaar Natarajanb7f9a352016-03-18 11:40:07 -07003177
3178 if (wma_is_pkt_drop_candidate(wma_handle, wh->i_addr2, mgt_subtype)) {
3179 cds_pkt_return_packet(rx_pkt);
3180 return -EINVAL;
3181 }
3182
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003183 wma_handle->mgmt_rx(wma_handle, rx_pkt);
3184 return 0;
3185}
3186
3187/**
3188 * wma_de_register_mgmt_frm_client() - deregister management frame
3189 * @cds_ctx: cds context
3190 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303191 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003192 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303193QDF_STATUS wma_de_register_mgmt_frm_client(void *cds_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003194{
3195 tp_wma_handle wma_handle;
3196
3197#ifdef QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +05303198 if (cds_get_conparam() == QDF_GLOBAL_FTM_MODE)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303199 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003200#endif
3201
Anurag Chouhan6d760662016-02-20 16:05:43 +05303202 wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003203 if (!wma_handle) {
3204 WMA_LOGE("%s: Failed to get WMA context", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303205 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003206 }
3207
3208 if (wmi_unified_unregister_event_handler(wma_handle->wmi_handle,
3209 WMI_MGMT_RX_EVENTID) != 0) {
3210 WMA_LOGE("Failed to Unregister rx mgmt handler with wmi");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303211 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003212 }
3213 wma_handle->mgmt_rx = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303214 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003215}
3216
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003217#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003218/**
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003219 * wma_register_roaming_callbacks() - Register roaming callbacks
3220 * @cds_ctx: CDS Context
3221 * @csr_roam_synch_cb: CSR roam synch callback routine pointer
3222 * @pe_roam_synch_cb: PE roam synch callback routine pointer
3223 *
3224 * Register the SME and PE callback routines with WMA for
3225 * handling roaming
3226 *
3227 * Return: Success or Failure Status
3228 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303229QDF_STATUS wma_register_roaming_callbacks(void *cds_ctx,
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003230 void (*csr_roam_synch_cb)(tpAniSirGlobal mac,
3231 roam_offload_synch_ind *roam_synch_data,
Varun Reddy Yeturuf907f912016-03-21 15:06:22 -07003232 tpSirBssDescription bss_desc_ptr,
3233 enum sir_roam_op_code reason),
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303234 QDF_STATUS (*pe_roam_synch_cb)(tpAniSirGlobal mac,
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003235 roam_offload_synch_ind *roam_synch_data,
3236 tpSirBssDescription bss_desc_ptr))
3237{
3238
Anurag Chouhan6d760662016-02-20 16:05:43 +05303239 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003240
3241 if (!wma) {
3242 WMA_LOGE("%s: Failed to get WMA context", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303243 return QDF_STATUS_E_FAILURE;
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003244 }
3245 wma->csr_roam_synch_cb = csr_roam_synch_cb;
3246 wma->pe_roam_synch_cb = pe_roam_synch_cb;
3247 WMA_LOGD("Registered roam synch callbacks with WMA successfully");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303248 return QDF_STATUS_SUCCESS;
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003249}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003250#endif
3251
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003252/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003253 * wma_register_mgmt_frm_client() - register management frame callback
3254 * @cds_ctx: cds context
3255 * @mgmt_frm_rx: management frame
3256 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303257 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003258 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303259QDF_STATUS wma_register_mgmt_frm_client(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003260 void *cds_ctx, wma_mgmt_frame_rx_callback mgmt_frm_rx)
3261{
Anurag Chouhan6d760662016-02-20 16:05:43 +05303262 tp_wma_handle wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003263
3264 if (!wma_handle) {
3265 WMA_LOGE("%s: Failed to get WMA context", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303266 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003267 }
3268
3269 if (wmi_unified_register_event_handler(wma_handle->wmi_handle,
3270 WMI_MGMT_RX_EVENTID,
Govind Singhd76a5b02016-03-08 15:12:14 +05303271 wma_mgmt_rx_process,
3272 WMA_RX_WORK_CTX) != 0) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003273 WMA_LOGE("Failed to register rx mgmt handler with wmi");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303274 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003275 }
3276 wma_handle->mgmt_rx = mgmt_frm_rx;
3277
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303278 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003279}