blob: 0a47e035d2bd8dc325358d280cf0084ccfff77ee [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05302 * Copyright (c) 2013-2017 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
51#include "wma_types.h"
52#include "lim_api.h"
53#include "lim_session_utils.h"
54
55#include "cds_utils.h"
56
57#if !defined(REMOVE_PKT_LOG)
58#include "pktlog_ac.h"
59#endif /* REMOVE_PKT_LOG */
60
61#include "dbglog_host.h"
62#include "csr_api.h"
63#include "ol_fw.h"
64#include "dfs.h"
65#include "wma_internal.h"
Chandrasekaran, Manishekar0d814c72015-11-05 10:42:48 +053066#include "cds_concurrency.h"
Dhanashri Atreb08959a2016-03-01 17:28:03 -080067#include "cdp_txrx_flow_ctrl_legacy.h"
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -070068#include <cdp_txrx_peer_ops.h>
69#include <cdp_txrx_pmf.h>
70#include <cdp_txrx_cfg.h>
71#include <cdp_txrx_cmn.h>
72#include <cdp_txrx_misc.h>
Leo Chang96464902016-10-28 11:10:54 -070073#include <cdp_txrx_misc.h>
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +053074#include "wlan_mgmt_txrx_tgt_api.h"
75#include "wlan_objmgr_psoc_obj.h"
76#include "wlan_objmgr_pdev_obj.h"
77#include "wlan_objmgr_vdev_obj.h"
78
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080079
80/**
81 * wma_send_bcn_buf_ll() - prepare and send beacon buffer to fw for LL
82 * @wma: wma handle
83 * @pdev: txrx pdev
84 * @vdev_id: vdev id
85 * @param_buf: SWBA parameters
86 *
87 * Return: none
88 */
89static void wma_send_bcn_buf_ll(tp_wma_handle wma,
Leo Chang96464902016-10-28 11:10:54 -070090 void *pdev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080091 uint8_t vdev_id,
92 WMI_HOST_SWBA_EVENTID_param_tlvs *param_buf)
93{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080094 struct ieee80211_frame *wh;
95 struct beacon_info *bcn;
96 wmi_tim_info *tim_info = param_buf->tim_info;
97 uint8_t *bcn_payload;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053098 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080099 struct beacon_tim_ie *tim_ie;
100 wmi_p2p_noa_info *p2p_noa_info = param_buf->p2p_noa_info;
101 struct p2p_sub_element_noa noa_ie;
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530102 struct wmi_bcn_send_from_host params;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800103 uint8_t i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800104
105 bcn = wma->interfaces[vdev_id].beacon;
106 if (!bcn->buf) {
107 WMA_LOGE("%s: Invalid beacon buffer", __func__);
108 return;
109 }
110
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530111 qdf_spin_lock_bh(&bcn->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800112
Nirav Shahcbc6d722016-03-01 16:24:53 +0530113 bcn_payload = qdf_nbuf_data(bcn->buf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800114
115 tim_ie = (struct beacon_tim_ie *)(&bcn_payload[bcn->tim_ie_offset]);
116
117 if (tim_info->tim_changed) {
118 if (tim_info->tim_num_ps_pending)
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530119 qdf_mem_copy(&tim_ie->tim_bitmap, tim_info->tim_bitmap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800120 WMA_TIM_SUPPORTED_PVB_LENGTH);
121 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530122 qdf_mem_zero(&tim_ie->tim_bitmap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800123 WMA_TIM_SUPPORTED_PVB_LENGTH);
124 /*
125 * Currently we support fixed number of
126 * peers as limited by HAL_NUM_STA.
127 * tim offset is always 0
128 */
129 tim_ie->tim_bitctl = 0;
130 }
131
132 /* Update DTIM Count */
133 if (tim_ie->dtim_count == 0)
134 tim_ie->dtim_count = tim_ie->dtim_period - 1;
135 else
136 tim_ie->dtim_count--;
137
138 /*
139 * DTIM count needs to be backedup so that
140 * when umac updates the beacon template
141 * current dtim count can be updated properly
142 */
143 bcn->dtim_count = tim_ie->dtim_count;
144
145 /* update state for buffered multicast frames on DTIM */
146 if (tim_info->tim_mcast && (tim_ie->dtim_count == 0 ||
147 tim_ie->dtim_period == 1))
148 tim_ie->tim_bitctl |= 1;
149 else
150 tim_ie->tim_bitctl &= ~1;
151
152 /* To avoid sw generated frame sequence the same as H/W generated frame,
153 * the value lower than min_sw_seq is reserved for HW generated frame */
154 if ((bcn->seq_no & IEEE80211_SEQ_MASK) < MIN_SW_SEQ)
155 bcn->seq_no = MIN_SW_SEQ;
156
157 wh = (struct ieee80211_frame *)bcn_payload;
158 *(uint16_t *) &wh->i_seq[0] = htole16(bcn->seq_no
159 << IEEE80211_SEQ_SEQ_SHIFT);
160 bcn->seq_no++;
161
162 if (WMI_UNIFIED_NOA_ATTR_IS_MODIFIED(p2p_noa_info)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530163 qdf_mem_zero(&noa_ie, sizeof(noa_ie));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800164
165 noa_ie.index =
166 (uint8_t) WMI_UNIFIED_NOA_ATTR_INDEX_GET(p2p_noa_info);
167 noa_ie.oppPS =
168 (uint8_t) WMI_UNIFIED_NOA_ATTR_OPP_PS_GET(p2p_noa_info);
169 noa_ie.ctwindow =
170 (uint8_t) WMI_UNIFIED_NOA_ATTR_CTWIN_GET(p2p_noa_info);
171 noa_ie.num_descriptors =
172 (uint8_t) WMI_UNIFIED_NOA_ATTR_NUM_DESC_GET(p2p_noa_info);
173 WMA_LOGI("%s: index %u, oppPs %u, ctwindow %u, "
174 "num_descriptors = %u", __func__, noa_ie.index,
175 noa_ie.oppPS, noa_ie.ctwindow, noa_ie.num_descriptors);
176 for (i = 0; i < noa_ie.num_descriptors; i++) {
177 noa_ie.noa_descriptors[i].type_count =
178 (uint8_t) p2p_noa_info->noa_descriptors[i].
179 type_count;
180 noa_ie.noa_descriptors[i].duration =
181 p2p_noa_info->noa_descriptors[i].duration;
182 noa_ie.noa_descriptors[i].interval =
183 p2p_noa_info->noa_descriptors[i].interval;
184 noa_ie.noa_descriptors[i].start_time =
185 p2p_noa_info->noa_descriptors[i].start_time;
186 WMA_LOGI("%s: NoA descriptor[%d] type_count %u, "
187 "duration %u, interval %u, start_time = %u",
188 __func__, i,
189 noa_ie.noa_descriptors[i].type_count,
190 noa_ie.noa_descriptors[i].duration,
191 noa_ie.noa_descriptors[i].interval,
192 noa_ie.noa_descriptors[i].start_time);
193 }
194 wma_update_noa(bcn, &noa_ie);
195
196 /* Send a msg to LIM to update the NoA IE in probe response
197 * frames transmitted by the host */
198 wma_update_probe_resp_noa(wma, &noa_ie);
199 }
200
201 if (bcn->dma_mapped) {
Leo Chang96464902016-10-28 11:10:54 -0700202 qdf_nbuf_unmap_single(wma->qdf_dev, bcn->buf, QDF_DMA_TO_DEVICE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800203 bcn->dma_mapped = 0;
204 }
Leo Chang96464902016-10-28 11:10:54 -0700205 ret = qdf_nbuf_map_single(wma->qdf_dev, bcn->buf, QDF_DMA_TO_DEVICE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530206 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800207 WMA_LOGE("%s: failed map beacon buf to DMA region", __func__);
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530208 qdf_spin_unlock_bh(&bcn->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800209 return;
210 }
211
212 bcn->dma_mapped = 1;
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530213 params.vdev_id = vdev_id;
214 params.data_len = bcn->len;
215 params.frame_ctrl = *((A_UINT16 *) wh->i_fc);
216 params.frag_ptr = qdf_nbuf_get_frag_paddr(bcn->buf, 0);
217 params.dtim_flag = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800218 /* notify Firmware of DTM and mcast/bcast traffic */
219 if (tim_ie->dtim_count == 0) {
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530220 params.dtim_flag |= WMI_BCN_SEND_DTIM_ZERO;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800221 /* deliver mcast/bcast traffic in next DTIM beacon */
222 if (tim_ie->tim_bitctl & 0x01)
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530223 params.dtim_flag |= WMI_BCN_SEND_DTIM_BITCTL_SET;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800224 }
225
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530226 wmi_unified_bcn_buf_ll_cmd(wma->wmi_handle,
227 &params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800228
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530229 qdf_spin_unlock_bh(&bcn->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800230}
231
232/**
233 * wma_beacon_swba_handler() - swba event handler
234 * @handle: wma handle
235 * @event: event data
236 * @len: data length
237 *
238 * SWBA event is alert event to Host requesting host to Queue a beacon
239 * for transmission use only in host beacon mode
240 *
241 * Return: 0 for success or error code
242 */
243int wma_beacon_swba_handler(void *handle, uint8_t *event, uint32_t len)
244{
245 tp_wma_handle wma = (tp_wma_handle) handle;
246 WMI_HOST_SWBA_EVENTID_param_tlvs *param_buf;
247 wmi_host_swba_event_fixed_param *swba_event;
248 uint32_t vdev_map;
Leo Chang96464902016-10-28 11:10:54 -0700249 void *pdev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800250 uint8_t vdev_id = 0;
Leo Chang96464902016-10-28 11:10:54 -0700251 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800252
253 param_buf = (WMI_HOST_SWBA_EVENTID_param_tlvs *) event;
254 if (!param_buf) {
255 WMA_LOGE("Invalid swba event buffer");
256 return -EINVAL;
257 }
258 swba_event = param_buf->fixed_param;
259 vdev_map = swba_event->vdev_map;
260
Anurag Chouhan6d760662016-02-20 16:05:43 +0530261 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800262 if (!pdev) {
263 WMA_LOGE("%s: pdev is NULL", __func__);
264 return -EINVAL;
265 }
266
267 for (; vdev_map; vdev_id++, vdev_map >>= 1) {
268 if (!(vdev_map & 0x1))
269 continue;
Leo Chang96464902016-10-28 11:10:54 -0700270 if (!cdp_cfg_is_high_latency(soc,
271 cds_get_context(QDF_MODULE_ID_CFG)))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800272 wma_send_bcn_buf_ll(wma, pdev, vdev_id, param_buf);
273 break;
274 }
275 return 0;
276}
277
278/**
279 * wma_peer_sta_kickout_event_handler() - kickout event handler
280 * @handle: wma handle
281 * @event: event data
282 * @len: data length
283 *
284 * Kickout event is received from firmware on observing beacon miss
285 * It handles kickout event for different modes and indicate to
286 * upper layers.
287 *
288 * Return: 0 for success or error code
289 */
290int wma_peer_sta_kickout_event_handler(void *handle, u8 *event, u32 len)
291{
292 tp_wma_handle wma = (tp_wma_handle) handle;
293 WMI_PEER_STA_KICKOUT_EVENTID_param_tlvs *param_buf = NULL;
294 wmi_peer_sta_kickout_event_fixed_param *kickout_event = NULL;
295 uint8_t vdev_id, peer_id, macaddr[IEEE80211_ADDR_LEN];
Leo Chang96464902016-10-28 11:10:54 -0700296 void *peer;
297 void *pdev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800298 tpDeleteStaContext del_sta_ctx;
299 tpSirIbssPeerInactivityInd p_inactivity;
Leo Chang96464902016-10-28 11:10:54 -0700300 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800301
302 WMA_LOGD("%s: Enter", __func__);
303 param_buf = (WMI_PEER_STA_KICKOUT_EVENTID_param_tlvs *) event;
304 kickout_event = param_buf->fixed_param;
Anurag Chouhan6d760662016-02-20 16:05:43 +0530305 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800306 if (!pdev) {
307 WMA_LOGE("%s: pdev is NULL", __func__);
308 return -EINVAL;
309 }
310 WMI_MAC_ADDR_TO_CHAR_ARRAY(&kickout_event->peer_macaddr, macaddr);
Leo Chang96464902016-10-28 11:10:54 -0700311 peer = cdp_peer_find_by_addr(soc, pdev, macaddr, &peer_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800312 if (!peer) {
313 WMA_LOGE("PEER [%pM] not found", macaddr);
314 return -EINVAL;
315 }
316
Leo Chang96464902016-10-28 11:10:54 -0700317 if (cdp_peer_get_vdevid(soc, peer, &vdev_id) != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800318 WMA_LOGE("Not able to find BSSID for peer [%pM]", macaddr);
319 return -EINVAL;
320 }
321
322 WMA_LOGA("%s: PEER:[%pM], ADDR:[%pN], INTERFACE:%d, peer_id:%d, reason:%d",
323 __func__, macaddr, wma->interfaces[vdev_id].addr, vdev_id,
324 peer_id, kickout_event->reason);
Varun Reddy Yeturu30bc42c2016-02-04 10:07:30 -0800325 if (wma->interfaces[vdev_id].roaming_in_progress) {
326 WMA_LOGE("Ignore STA kick out since roaming is in progress");
327 return -EINVAL;
328 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800329
330 switch (kickout_event->reason) {
331 case WMI_PEER_STA_KICKOUT_REASON_IBSS_DISCONNECT:
332 p_inactivity = (tpSirIbssPeerInactivityInd)
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530333 qdf_mem_malloc(sizeof(tSirIbssPeerInactivityInd));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800334 if (!p_inactivity) {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530335 WMA_LOGE("QDF MEM Alloc Failed for tSirIbssPeerInactivity");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800336 return -ENOMEM;
337 }
338
339 p_inactivity->staIdx = peer_id;
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530340 qdf_mem_copy(p_inactivity->peer_addr.bytes, macaddr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800341 IEEE80211_ADDR_LEN);
342 wma_send_msg(wma, WMA_IBSS_PEER_INACTIVITY_IND,
343 (void *)p_inactivity, 0);
344 goto exit_handler;
345 break;
346
347#ifdef FEATURE_WLAN_TDLS
348 case WMI_PEER_STA_KICKOUT_REASON_TDLS_DISCONNECT:
349 del_sta_ctx = (tpDeleteStaContext)
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530350 qdf_mem_malloc(sizeof(tDeleteStaContext));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800351 if (!del_sta_ctx) {
352 WMA_LOGE("%s: mem alloc failed for tDeleteStaContext for TDLS peer: %pM",
353 __func__, macaddr);
354 return -ENOMEM;
355 }
356
Naveen Rawat9801ac02016-06-22 11:02:50 -0700357 del_sta_ctx->is_tdls = true;
358 del_sta_ctx->vdev_id = vdev_id;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800359 del_sta_ctx->staId = peer_id;
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530360 qdf_mem_copy(del_sta_ctx->addr2, macaddr, IEEE80211_ADDR_LEN);
361 qdf_mem_copy(del_sta_ctx->bssId, wma->interfaces[vdev_id].bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800362 IEEE80211_ADDR_LEN);
363 del_sta_ctx->reasonCode = HAL_DEL_STA_REASON_CODE_KEEP_ALIVE;
364 wma_send_msg(wma, SIR_LIM_DELETE_STA_CONTEXT_IND,
365 (void *)del_sta_ctx, 0);
366 goto exit_handler;
367 break;
368#endif /* FEATURE_WLAN_TDLS */
369
370 case WMI_PEER_STA_KICKOUT_REASON_XRETRY:
371 if (wma->interfaces[vdev_id].type == WMI_VDEV_TYPE_STA &&
372 (wma->interfaces[vdev_id].sub_type == 0 ||
373 wma->interfaces[vdev_id].sub_type ==
374 WMI_UNIFIED_VDEV_SUBTYPE_P2P_CLIENT) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530375 !qdf_mem_cmp(wma->interfaces[vdev_id].bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800376 macaddr, IEEE80211_ADDR_LEN)) {
377 /*
378 * KICKOUT event is for current station-AP connection.
379 * Treat it like final beacon miss. Station may not have
380 * missed beacons but not able to transmit frames to AP
381 * for a long time. Must disconnect to get out of
382 * this sticky situation.
383 * In future implementation, roaming module will also
384 * handle this event and perform a scan.
385 */
386 WMA_LOGW("%s: WMI_PEER_STA_KICKOUT_REASON_XRETRY event for STA",
387 __func__);
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +0530388 wma_beacon_miss_handler(wma, vdev_id,
389 kickout_event->rssi);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800390 goto exit_handler;
391 }
392 break;
393
394 case WMI_PEER_STA_KICKOUT_REASON_UNSPECIFIED:
395 /*
396 * Default legacy value used by original firmware implementation.
397 */
398 if (wma->interfaces[vdev_id].type == WMI_VDEV_TYPE_STA &&
399 (wma->interfaces[vdev_id].sub_type == 0 ||
400 wma->interfaces[vdev_id].sub_type ==
401 WMI_UNIFIED_VDEV_SUBTYPE_P2P_CLIENT) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530402 !qdf_mem_cmp(wma->interfaces[vdev_id].bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800403 macaddr, IEEE80211_ADDR_LEN)) {
404 /*
405 * KICKOUT event is for current station-AP connection.
406 * Treat it like final beacon miss. Station may not have
407 * missed beacons but not able to transmit frames to AP
408 * for a long time. Must disconnect to get out of
409 * this sticky situation.
410 * In future implementation, roaming module will also
411 * handle this event and perform a scan.
412 */
413 WMA_LOGW("%s: WMI_PEER_STA_KICKOUT_REASON_UNSPECIFIED event for STA",
414 __func__);
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +0530415 wma_beacon_miss_handler(wma, vdev_id,
416 kickout_event->rssi);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800417 goto exit_handler;
418 }
419 break;
420
421 case WMI_PEER_STA_KICKOUT_REASON_INACTIVITY:
Naveen Rawat9801ac02016-06-22 11:02:50 -0700422 /*
423 * Handle SA query kickout is same as inactivity kickout.
424 * This could be for STA or SAP role
425 */
mukul sharma72c8b222015-09-04 17:02:01 +0530426 case WMI_PEER_STA_KICKOUT_REASON_SA_QUERY_TIMEOUT:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800427 default:
428 break;
429 }
430
431 /*
432 * default action is to send delete station context indication to LIM
433 */
434 del_sta_ctx =
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530435 (tpDeleteStaContext) qdf_mem_malloc(sizeof(tDeleteStaContext));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800436 if (!del_sta_ctx) {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530437 WMA_LOGE("QDF MEM Alloc Failed for tDeleteStaContext");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800438 return -ENOMEM;
439 }
440
Naveen Rawat9801ac02016-06-22 11:02:50 -0700441 del_sta_ctx->is_tdls = false;
442 del_sta_ctx->vdev_id = vdev_id;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800443 del_sta_ctx->staId = peer_id;
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530444 qdf_mem_copy(del_sta_ctx->addr2, macaddr, IEEE80211_ADDR_LEN);
445 qdf_mem_copy(del_sta_ctx->bssId, wma->interfaces[vdev_id].addr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800446 IEEE80211_ADDR_LEN);
447 del_sta_ctx->reasonCode = HAL_DEL_STA_REASON_CODE_KEEP_ALIVE;
Kiran Kumar Lokere37d3aa22015-11-03 14:58:26 -0800448 del_sta_ctx->rssi = kickout_event->rssi + WMA_TGT_NOISE_FLOOR_DBM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800449 wma_send_msg(wma, SIR_LIM_DELETE_STA_CONTEXT_IND, (void *)del_sta_ctx,
450 0);
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +0530451 wma_lost_link_info_handler(wma, vdev_id, kickout_event->rssi +
452 WMA_TGT_NOISE_FLOOR_DBM);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800453exit_handler:
454 WMA_LOGD("%s: Exit", __func__);
455 return 0;
456}
457
458/**
459 * wma_unified_bcntx_status_event_handler() - beacon tx status event handler
460 * @handle: wma handle
461 * @cmd_param_info: event data
462 * @len: data length
463 *
464 * WMI Handler for WMI_OFFLOAD_BCN_TX_STATUS_EVENTID event from firmware.
465 * This event is generated by FW when the beacon transmission is offloaded
466 * and the host performs beacon template modification using WMI_BCN_TMPL_CMDID
467 * The FW generates this event when the first successful beacon transmission
468 * after template update
469 *
470 * Return: 0 for success or error code
471 */
472int wma_unified_bcntx_status_event_handler(void *handle,
473 uint8_t *cmd_param_info,
474 uint32_t len)
475{
476 tp_wma_handle wma = (tp_wma_handle) handle;
477 WMI_OFFLOAD_BCN_TX_STATUS_EVENTID_param_tlvs *param_buf;
478 wmi_offload_bcn_tx_status_event_fixed_param *resp_event;
479 tSirFirstBeaconTxCompleteInd *beacon_tx_complete_ind;
480
481 param_buf =
482 (WMI_OFFLOAD_BCN_TX_STATUS_EVENTID_param_tlvs *) cmd_param_info;
483 if (!param_buf) {
484 WMA_LOGE("Invalid bcn tx response event buffer");
485 return -EINVAL;
486 }
487
488 resp_event = param_buf->fixed_param;
489
Chandrasekaran, Manishekarce2172e2016-02-18 16:12:43 +0530490 WMA_LOGD("%s", __func__);
491
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800492 /* Check for valid handle to ensure session is not
493 * deleted in any race
494 */
495 if (!wma->interfaces[resp_event->vdev_id].handle) {
496 WMA_LOGE("%s: The session does not exist", __func__);
497 return -EINVAL;
498 }
499
500 /* Beacon Tx Indication supports only AP mode. Ignore in other modes */
501 if (wma_is_vdev_in_ap_mode(wma, resp_event->vdev_id) == false) {
502 WMA_LOGI("%s: Beacon Tx Indication does not support type %d and sub_type %d",
503 __func__, wma->interfaces[resp_event->vdev_id].type,
504 wma->interfaces[resp_event->vdev_id].sub_type);
505 return 0;
506 }
507
508 beacon_tx_complete_ind = (tSirFirstBeaconTxCompleteInd *)
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530509 qdf_mem_malloc(sizeof(tSirFirstBeaconTxCompleteInd));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800510 if (!beacon_tx_complete_ind) {
511 WMA_LOGE("%s: Failed to alloc beacon_tx_complete_ind",
512 __func__);
513 return -ENOMEM;
514 }
515
516 beacon_tx_complete_ind->messageType = WMA_DFS_BEACON_TX_SUCCESS_IND;
517 beacon_tx_complete_ind->length = sizeof(tSirFirstBeaconTxCompleteInd);
518 beacon_tx_complete_ind->bssIdx = resp_event->vdev_id;
519
520 wma_send_msg(wma, WMA_DFS_BEACON_TX_SUCCESS_IND,
521 (void *)beacon_tx_complete_ind, 0);
522 return 0;
523}
524
525/**
526 * wma_get_link_probe_timeout() - get link timeout based on sub type
527 * @mac: UMAC handler
528 * @sub_type: vdev syb type
529 * @max_inactive_time: return max inactive time
530 * @max_unresponsive_time: return max unresponsive time
531 *
532 * Return: none
533 */
534static inline void wma_get_link_probe_timeout(struct sAniSirGlobal *mac,
535 uint32_t sub_type,
536 uint32_t *max_inactive_time,
537 uint32_t *max_unresponsive_time)
538{
539 uint32_t keep_alive;
540 uint16_t lm_id, ka_id;
541
542 switch (sub_type) {
543 case WMI_UNIFIED_VDEV_SUBTYPE_P2P_GO:
544 lm_id = WNI_CFG_GO_LINK_MONITOR_TIMEOUT;
545 ka_id = WNI_CFG_GO_KEEP_ALIVE_TIMEOUT;
546 break;
547 default:
548 /*For softAp the subtype value will be zero */
549 lm_id = WNI_CFG_AP_LINK_MONITOR_TIMEOUT;
550 ka_id = WNI_CFG_AP_KEEP_ALIVE_TIMEOUT;
551 }
552
553 if (wlan_cfg_get_int(mac, lm_id, max_inactive_time) != eSIR_SUCCESS) {
554 WMA_LOGE("Failed to read link monitor for subtype %d",
555 sub_type);
556 *max_inactive_time = WMA_LINK_MONITOR_DEFAULT_TIME_SECS;
557 }
558
559 if (wlan_cfg_get_int(mac, ka_id, &keep_alive) != eSIR_SUCCESS) {
560 WMA_LOGE("Failed to read keep alive for subtype %d", sub_type);
561 keep_alive = WMA_KEEP_ALIVE_DEFAULT_TIME_SECS;
562 }
563 *max_unresponsive_time = *max_inactive_time + keep_alive;
564}
565
566/**
567 * wma_set_sap_keepalive() - set SAP keep alive parameters to fw
568 * @wma: wma handle
569 * @vdev_id: vdev id
570 *
571 * Return: none
572 */
573void wma_set_sap_keepalive(tp_wma_handle wma, uint8_t vdev_id)
574{
575 uint32_t min_inactive_time, max_inactive_time, max_unresponsive_time;
Anurag Chouhan6d760662016-02-20 16:05:43 +0530576 struct sAniSirGlobal *mac = cds_get_context(QDF_MODULE_ID_PE);
Govind Singhd76a5b02016-03-08 15:12:14 +0530577 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800578
579 if (NULL == mac) {
580 WMA_LOGE("%s: Failed to get mac", __func__);
581 return;
582 }
583
584 wma_get_link_probe_timeout(mac, wma->interfaces[vdev_id].sub_type,
585 &max_inactive_time, &max_unresponsive_time);
586
587 min_inactive_time = max_inactive_time / 2;
588
Govind Singhd76a5b02016-03-08 15:12:14 +0530589 status = wma_vdev_set_param(wma->wmi_handle,
590 vdev_id,
591 WMI_VDEV_PARAM_AP_KEEPALIVE_MIN_IDLE_INACTIVE_TIME_SECS,
592 min_inactive_time);
593 if (QDF_IS_STATUS_ERROR(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800594 WMA_LOGE("Failed to Set AP MIN IDLE INACTIVE TIME");
595
Govind Singhd76a5b02016-03-08 15:12:14 +0530596 status = wma_vdev_set_param(wma->wmi_handle,
597 vdev_id,
598 WMI_VDEV_PARAM_AP_KEEPALIVE_MAX_IDLE_INACTIVE_TIME_SECS,
599 max_inactive_time);
600 if (QDF_IS_STATUS_ERROR(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800601 WMA_LOGE("Failed to Set AP MAX IDLE INACTIVE TIME");
602
Govind Singhd76a5b02016-03-08 15:12:14 +0530603 status = wma_vdev_set_param(wma->wmi_handle,
604 vdev_id,
605 WMI_VDEV_PARAM_AP_KEEPALIVE_MAX_UNRESPONSIVE_TIME_SECS,
606 max_unresponsive_time);
607 if (QDF_IS_STATUS_ERROR(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800608 WMA_LOGE("Failed to Set MAX UNRESPONSIVE TIME");
609
610 WMA_LOGD("%s:vdev_id:%d min_inactive_time: %u max_inactive_time: %u"
611 " max_unresponsive_time: %u", __func__, vdev_id,
612 min_inactive_time, max_inactive_time, max_unresponsive_time);
613}
614
615/**
mukul sharma72c8b222015-09-04 17:02:01 +0530616 * wma_set_sta_sa_query_param() - set sta sa query parameters
617 * @wma: wma handle
618 * @vdev_id: vdev id
619
620 * This function sets sta query related parameters in fw.
621 *
622 * Return: none
623 */
624
625void wma_set_sta_sa_query_param(tp_wma_handle wma,
626 uint8_t vdev_id)
627{
Anurag Chouhan6d760662016-02-20 16:05:43 +0530628 struct sAniSirGlobal *mac = cds_get_context(QDF_MODULE_ID_PE);
mukul sharma72c8b222015-09-04 17:02:01 +0530629 uint32_t max_retries, retry_interval;
mukul sharma72c8b222015-09-04 17:02:01 +0530630
631 WMA_LOGD(FL("Enter:"));
mukul sharma72c8b222015-09-04 17:02:01 +0530632
633 if (wlan_cfg_get_int
634 (mac, WNI_CFG_PMF_SA_QUERY_MAX_RETRIES,
635 &max_retries) != eSIR_SUCCESS) {
636 max_retries = DEFAULT_STA_SA_QUERY_MAX_RETRIES_COUNT;
637 WMA_LOGE(FL("Failed to get value for WNI_CFG_PMF_SA_QUERY_MAX_RETRIES"));
638 }
639 if (wlan_cfg_get_int
640 (mac, WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL,
641 &retry_interval) != eSIR_SUCCESS) {
642 retry_interval = DEFAULT_STA_SA_QUERY_RETRY_INTERVAL;
643 WMA_LOGE(FL("Failed to get value for WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL"));
644 }
645
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530646 wmi_unified_set_sta_sa_query_param_cmd(wma->wmi_handle,
647 vdev_id,
648 max_retries,
649 retry_interval);
mukul sharma72c8b222015-09-04 17:02:01 +0530650
651 WMA_LOGD(FL("Exit :"));
652 return;
653}
654
655/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800656 * wma_set_sta_keep_alive() - set sta keep alive parameters
657 * @wma: wma handle
658 * @vdev_id: vdev id
659 * @method: method for keep alive
660 * @timeperiod: time period
661 * @hostv4addr: host ipv4 address
662 * @destv4addr: dst ipv4 address
663 * @destmac: destination mac
664 *
665 * This function sets keep alive related parameters in fw.
666 *
667 * Return: none
668 */
669void wma_set_sta_keep_alive(tp_wma_handle wma, uint8_t vdev_id,
670 uint32_t method, uint32_t timeperiod,
671 uint8_t *hostv4addr, uint8_t *destv4addr,
672 uint8_t *destmac)
673{
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530674 struct sta_params params;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800675
676 WMA_LOGD("%s: Enter", __func__);
677
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530678 if (!wma) {
679 WMA_LOGE("%s: wma handle is NULL", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800680 return;
681 }
682
Govind Singhfe9ab252016-06-21 14:35:35 +0530683 if (timeperiod > WNI_CFG_INFRA_STA_KEEP_ALIVE_PERIOD_STAMAX) {
684 WMI_LOGE("Invalid period %d Max limit %d", timeperiod,
685 WNI_CFG_INFRA_STA_KEEP_ALIVE_PERIOD_STAMAX);
686 return;
687 }
688
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530689 params.vdev_id = vdev_id;
690 params.method = method;
691 params.timeperiod = timeperiod;
692 params.hostv4addr = hostv4addr;
693 params.destv4addr = destv4addr;
694 params.destmac = destmac;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800695
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530696 wmi_unified_set_sta_keep_alive_cmd(wma->wmi_handle,
697 &params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800698
699 WMA_LOGD("%s: Exit", __func__);
700 return;
701}
702
703/**
704 * wma_vdev_install_key_complete_event_handler() - install key complete handler
705 * @handle: wma handle
706 * @event: event data
707 * @len: data length
708 *
709 * This event is sent by fw once WPA/WPA2 keys are installed in fw.
710 *
711 * Return: 0 for success or error code
712 */
713int wma_vdev_install_key_complete_event_handler(void *handle,
714 uint8_t *event,
715 uint32_t len)
716{
717 WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID_param_tlvs *param_buf = NULL;
718 wmi_vdev_install_key_complete_event_fixed_param *key_fp = NULL;
719
720 if (!event) {
721 WMA_LOGE("%s: event param null", __func__);
722 return -EINVAL;
723 }
724
725 param_buf = (WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID_param_tlvs *) event;
726 if (!param_buf) {
727 WMA_LOGE("%s: received null buf from target", __func__);
728 return -EINVAL;
729 }
730
731 key_fp = param_buf->fixed_param;
732 if (!key_fp) {
733 WMA_LOGE("%s: received null event data from target", __func__);
734 return -EINVAL;
735 }
736 /*
737 * Do nothing for now. Completion of set key is already indicated to lim
738 */
739 WMA_LOGI("%s: WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID", __func__);
740 return 0;
741}
742/*
743 * 802.11n D2.0 defined values for "Minimum MPDU Start Spacing":
744 * 0 for no restriction
745 * 1 for 1/4 us - Our lower layer calculations limit our precision to 1 msec
746 * 2 for 1/2 us - Our lower layer calculations limit our precision to 1 msec
747 * 3 for 1 us
748 * 4 for 2 us
749 * 5 for 4 us
750 * 6 for 8 us
751 * 7 for 16 us
752 */
753static const uint8_t wma_mpdu_spacing[] = { 0, 1, 1, 1, 2, 4, 8, 16 };
754
755/**
756 * wma_parse_mpdudensity() - give mpdu spacing from mpdu density
757 * @mpdudensity: mpdu density
758 *
759 * Return: mpdu spacing or 0 for error
760 */
761static inline uint8_t wma_parse_mpdudensity(uint8_t mpdudensity)
762{
763 if (mpdudensity < sizeof(wma_mpdu_spacing))
764 return wma_mpdu_spacing[mpdudensity];
765 else
766 return 0;
767}
768
Poddar, Siddarth5a91f5b2016-04-28 12:24:10 +0530769#if defined(CONFIG_HL_SUPPORT) && defined(FEATURE_WLAN_TDLS)
770
771/**
772 * wma_unified_peer_state_update() - update peer state
773 * @pdev: pdev handle
774 * @sta_mac: pointer to sta mac addr
775 * @bss_addr: bss address
776 * @sta_type: sta entry type
777 *
778 *
779 * Return: None
780 */
781static void
782wma_unified_peer_state_update(
Leo Chang96464902016-10-28 11:10:54 -0700783 void *pdev,
Poddar, Siddarth5a91f5b2016-04-28 12:24:10 +0530784 uint8_t *sta_mac,
785 uint8_t *bss_addr,
786 uint8_t sta_type)
787{
Leo Chang96464902016-10-28 11:10:54 -0700788 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
789
Poddar, Siddarth5a91f5b2016-04-28 12:24:10 +0530790 if (STA_ENTRY_TDLS_PEER == sta_type)
Leo Chang96464902016-10-28 11:10:54 -0700791 cdp_peer_state_update(soc, pdev, sta_mac,
Poddar, Siddarth5a91f5b2016-04-28 12:24:10 +0530792 OL_TXRX_PEER_STATE_AUTH);
793 else
Leo Chang96464902016-10-28 11:10:54 -0700794 cdp_peer_state_update(soc, pdev, bss_addr,
Poddar, Siddarth5a91f5b2016-04-28 12:24:10 +0530795 OL_TXRX_PEER_STATE_AUTH);
796}
797#else
798
799static inline void
800wma_unified_peer_state_update(
Leo Chang96464902016-10-28 11:10:54 -0700801 void *pdev,
Poddar, Siddarth5a91f5b2016-04-28 12:24:10 +0530802 uint8_t *sta_mac,
803 uint8_t *bss_addr,
804 uint8_t sta_type)
805{
Leo Chang96464902016-10-28 11:10:54 -0700806 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
807
808 cdp_peer_state_update(soc, pdev, bss_addr, OL_TXRX_PEER_STATE_AUTH);
Poddar, Siddarth5a91f5b2016-04-28 12:24:10 +0530809}
810#endif
811
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800812/**
813 * wmi_unified_send_peer_assoc() - send peer assoc command to fw
814 * @wma: wma handle
815 * @nw_type: nw type
816 * @params: add sta params
817 *
818 * This function send peer assoc command to firmware with
819 * different parameters.
820 *
Govind Singhb30d4c02016-03-24 11:01:23 +0530821 * Return: QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800822 */
Govind Singhb30d4c02016-03-24 11:01:23 +0530823QDF_STATUS wma_send_peer_assoc(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800824 tSirNwType nw_type,
825 tpAddStaParams params)
826{
Leo Chang96464902016-10-28 11:10:54 -0700827 void *pdev;
Govind Singhb30d4c02016-03-24 11:01:23 +0530828 struct peer_assoc_params *cmd;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800829 int32_t ret, max_rates, i;
830 uint8_t rx_stbc, tx_stbc;
Govind Singhb30d4c02016-03-24 11:01:23 +0530831 uint8_t *rate_pos;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800832 wmi_rate_set peer_legacy_rates, peer_ht_rates;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800833 uint32_t num_peer_11b_rates = 0;
834 uint32_t num_peer_11a_rates = 0;
835 uint32_t phymode;
836 uint32_t peer_nss = 1;
837 struct wma_txrx_node *intr = NULL;
Govind Singhb30d4c02016-03-24 11:01:23 +0530838 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800839
Govind Singhb30d4c02016-03-24 11:01:23 +0530840 cmd = qdf_mem_malloc(sizeof(struct peer_assoc_params));
841 if (!cmd) {
842 WMA_LOGE("Failed to allocate peer_assoc_params param");
843 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800844 }
Govind Singhb30d4c02016-03-24 11:01:23 +0530845
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800846 intr = &wma->interfaces[params->smesessionId];
847
Anurag Chouhan6d760662016-02-20 16:05:43 +0530848 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800849
850 if (NULL == pdev) {
851 WMA_LOGE("%s: Failed to get pdev", __func__);
Govind Singhb30d4c02016-03-24 11:01:23 +0530852 qdf_mem_free(cmd);
853 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800854 }
855
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530856 qdf_mem_zero(&peer_legacy_rates, sizeof(wmi_rate_set));
857 qdf_mem_zero(&peer_ht_rates, sizeof(wmi_rate_set));
Govind Singhb30d4c02016-03-24 11:01:23 +0530858 qdf_mem_zero(cmd, sizeof(struct peer_assoc_params));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800859
860 phymode = wma_peer_phymode(nw_type, params->staType,
861 params->htCapable,
862 params->ch_width,
863 params->vhtCapable);
864
865 /* Legacy Rateset */
866 rate_pos = (uint8_t *) peer_legacy_rates.rates;
867 for (i = 0; i < SIR_NUM_11B_RATES; i++) {
868 if (!params->supportedRates.llbRates[i])
869 continue;
870 rate_pos[peer_legacy_rates.num_rates++] =
871 params->supportedRates.llbRates[i];
872 num_peer_11b_rates++;
873 }
874 for (i = 0; i < SIR_NUM_11A_RATES; i++) {
875 if (!params->supportedRates.llaRates[i])
876 continue;
877 rate_pos[peer_legacy_rates.num_rates++] =
878 params->supportedRates.llaRates[i];
879 num_peer_11a_rates++;
880 }
881
882 if ((phymode == MODE_11A && num_peer_11a_rates == 0) ||
883 (phymode == MODE_11B && num_peer_11b_rates == 0)) {
884 WMA_LOGW("%s: Invalid phy rates. phymode 0x%x, 11b_rates %d, 11a_rates %d",
885 __func__, phymode, num_peer_11b_rates, num_peer_11a_rates);
Govind Singhb30d4c02016-03-24 11:01:23 +0530886 qdf_mem_free(cmd);
887 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800888 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800889
890 /* HT Rateset */
891 max_rates = sizeof(peer_ht_rates.rates) /
892 sizeof(peer_ht_rates.rates[0]);
893 rate_pos = (uint8_t *) peer_ht_rates.rates;
894 for (i = 0; i < MAX_SUPPORTED_RATES; i++) {
895 if (params->supportedRates.supportedMCSSet[i / 8] &
896 (1 << (i % 8))) {
897 rate_pos[peer_ht_rates.num_rates++] = i;
898 if (i >= 8) {
899 /* MCS8 or higher rate is present, must be 2x2 */
900 peer_nss = 2;
901 }
902 }
903 if (peer_ht_rates.num_rates == max_rates)
904 break;
905 }
906
907 if (params->htCapable && !peer_ht_rates.num_rates) {
908 uint8_t temp_ni_rates[8] = { 0x0, 0x1, 0x2, 0x3,
909 0x4, 0x5, 0x6, 0x7};
910 /*
911 * Workaround for EV 116382: The peer is marked HT but with
912 * supported rx mcs set is set to 0. 11n spec mandates MCS0-7
913 * for a HT STA. So forcing the supported rx mcs rate to
914 * MCS 0-7. This workaround will be removed once we get
915 * clarification from WFA regarding this STA behavior.
916 */
917
918 /* TODO: Do we really need this? */
919 WMA_LOGW("Peer is marked as HT capable but supported mcs rate is 0");
920 peer_ht_rates.num_rates = sizeof(temp_ni_rates);
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530921 qdf_mem_copy((uint8_t *) peer_ht_rates.rates, temp_ni_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800922 peer_ht_rates.num_rates);
923 }
924
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800925 /* in ap/ibss mode and for tdls peer, use mac address of the peer in
926 * the other end as the new peer address; in sta mode, use bss id to
927 * be the new peer address
928 */
929 if ((wma_is_vdev_in_ap_mode(wma, params->smesessionId))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800930 || (wma_is_vdev_in_ibss_mode(wma, params->smesessionId))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800931#ifdef FEATURE_WLAN_TDLS
932 || (STA_ENTRY_TDLS_PEER == params->staType)
933#endif /* FEATURE_WLAN_TDLS */
934 )
935 WMI_CHAR_ARRAY_TO_MAC_ADDR(params->staMac, &cmd->peer_macaddr);
936 else
937 WMI_CHAR_ARRAY_TO_MAC_ADDR(params->bssId, &cmd->peer_macaddr);
938 cmd->vdev_id = params->smesessionId;
939 cmd->peer_new_assoc = 1;
940 cmd->peer_associd = params->assocId;
941
942 /*
943 * The target only needs a subset of the flags maintained in the host.
944 * Just populate those flags and send it down
945 */
946 cmd->peer_flags = 0;
947
948 if (params->wmmEnabled)
949 cmd->peer_flags |= WMI_PEER_QOS;
950
951 if (params->uAPSD) {
952 cmd->peer_flags |= WMI_PEER_APSD;
953 WMA_LOGD("Set WMI_PEER_APSD: uapsd Mask %d", params->uAPSD);
954 }
955
956 if (params->htCapable) {
957 cmd->peer_flags |= (WMI_PEER_HT | WMI_PEER_QOS);
958 cmd->peer_rate_caps |= WMI_RC_HT_FLAG;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800959
Krishna Kumaar Natarajan59f546c2016-02-16 10:31:55 -0800960 if (params->ch_width) {
961 cmd->peer_flags |= WMI_PEER_40MHZ;
962 cmd->peer_rate_caps |= WMI_RC_CW40_FLAG;
963 if (params->fShortGI40Mhz)
964 cmd->peer_rate_caps |= WMI_RC_SGI_FLAG;
965 } else if (params->fShortGI20Mhz) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800966 cmd->peer_rate_caps |= WMI_RC_SGI_FLAG;
Krishna Kumaar Natarajan59f546c2016-02-16 10:31:55 -0800967 }
968 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800969
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800970 if (params->vhtCapable) {
971 cmd->peer_flags |= (WMI_PEER_HT | WMI_PEER_VHT | WMI_PEER_QOS);
972 cmd->peer_rate_caps |= WMI_RC_HT_FLAG;
973 }
974
975 if (params->ch_width == CH_WIDTH_80MHZ)
976 cmd->peer_flags |= WMI_PEER_80MHZ;
977 else if (params->ch_width == CH_WIDTH_160MHZ)
978 cmd->peer_flags |= WMI_PEER_160MHZ;
979 else if (params->ch_width == CH_WIDTH_80P80MHZ)
980 cmd->peer_flags |= WMI_PEER_160MHZ;
981
982 cmd->peer_vht_caps = params->vht_caps;
Agrawal Ashishb2d1a452016-05-05 12:23:58 +0530983 if (params->p2pCapableSta)
984 cmd->peer_flags |= WMI_PEER_IS_P2P_CAPABLE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800985
986 if (params->rmfEnabled)
987 cmd->peer_flags |= WMI_PEER_PMF;
988
989 rx_stbc = (params->ht_caps & IEEE80211_HTCAP_C_RXSTBC) >>
990 IEEE80211_HTCAP_C_RXSTBC_S;
991 if (rx_stbc) {
992 cmd->peer_flags |= WMI_PEER_STBC;
993 cmd->peer_rate_caps |= (rx_stbc << WMI_RC_RX_STBC_FLAG_S);
994 }
995
996 tx_stbc = (params->ht_caps & IEEE80211_HTCAP_C_TXSTBC) >>
997 IEEE80211_HTCAP_C_TXSTBC_S;
998 if (tx_stbc) {
999 cmd->peer_flags |= WMI_PEER_STBC;
1000 cmd->peer_rate_caps |= (tx_stbc << WMI_RC_TX_STBC_FLAG_S);
1001 }
1002
1003 if (params->htLdpcCapable || params->vhtLdpcCapable)
1004 cmd->peer_flags |= WMI_PEER_LDPC;
1005
1006 switch (params->mimoPS) {
1007 case eSIR_HT_MIMO_PS_STATIC:
1008 cmd->peer_flags |= WMI_PEER_STATIC_MIMOPS;
1009 break;
1010 case eSIR_HT_MIMO_PS_DYNAMIC:
1011 cmd->peer_flags |= WMI_PEER_DYN_MIMOPS;
1012 break;
1013 case eSIR_HT_MIMO_PS_NO_LIMIT:
1014 cmd->peer_flags |= WMI_PEER_SPATIAL_MUX;
1015 break;
1016 default:
1017 break;
1018 }
1019
1020#ifdef FEATURE_WLAN_TDLS
1021 if (STA_ENTRY_TDLS_PEER == params->staType)
1022 cmd->peer_flags |= WMI_PEER_AUTH;
1023#endif /* FEATURE_WLAN_TDLS */
1024
1025 if (params->wpa_rsn
1026#ifdef FEATURE_WLAN_WAPI
1027 || params->encryptType == eSIR_ED_WPI
1028#endif /* FEATURE_WLAN_WAPI */
1029 )
1030 cmd->peer_flags |= WMI_PEER_NEED_PTK_4_WAY;
1031 if (params->wpa_rsn >> 1)
1032 cmd->peer_flags |= WMI_PEER_NEED_GTK_2_WAY;
1033
Poddar, Siddarth5a91f5b2016-04-28 12:24:10 +05301034 wma_unified_peer_state_update(pdev, params->staMac,
1035 params->bssId, params->staType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001036
1037#ifdef FEATURE_WLAN_WAPI
1038 if (params->encryptType == eSIR_ED_WPI) {
Govind Singhd76a5b02016-03-08 15:12:14 +05301039 ret = wma_vdev_set_param(wma->wmi_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001040 params->smesessionId,
1041 WMI_VDEV_PARAM_DROP_UNENCRY,
1042 false);
1043 if (ret) {
1044 WMA_LOGE
1045 ("Set WMI_VDEV_PARAM_DROP_UNENCRY Param status:%d\n",
1046 ret);
Govind Singhb30d4c02016-03-24 11:01:23 +05301047 qdf_mem_free(cmd);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001048 return ret;
1049 }
1050 }
1051#endif /* FEATURE_WLAN_WAPI */
1052
1053 cmd->peer_caps = params->capab_info;
1054 cmd->peer_listen_intval = params->listenInterval;
1055 cmd->peer_ht_caps = params->ht_caps;
1056 cmd->peer_max_mpdu = (1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR +
1057 params->maxAmpduSize)) - 1;
1058 cmd->peer_mpdu_density = wma_parse_mpdudensity(params->maxAmpduDensity);
1059
1060 if (params->supportedRates.supportedMCSSet[1] &&
1061 params->supportedRates.supportedMCSSet[2])
1062 cmd->peer_rate_caps |= WMI_RC_TS_FLAG;
1063 else if (params->supportedRates.supportedMCSSet[1])
1064 cmd->peer_rate_caps |= WMI_RC_DS_FLAG;
1065
1066 /* Update peer legacy rate information */
Govind Singhb30d4c02016-03-24 11:01:23 +05301067 cmd->peer_legacy_rates.num_rates = peer_legacy_rates.num_rates;
1068 qdf_mem_copy(cmd->peer_legacy_rates.rates, peer_legacy_rates.rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001069 peer_legacy_rates.num_rates);
1070
1071 /* Update peer HT rate information */
Govind Singhb30d4c02016-03-24 11:01:23 +05301072 cmd->peer_ht_rates.num_rates = peer_ht_rates.num_rates;
1073 qdf_mem_copy(cmd->peer_ht_rates.rates, peer_ht_rates.rates,
1074 peer_ht_rates.num_rates);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001075
1076 /* VHT Rates */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001077
1078 cmd->peer_nss = peer_nss;
Naveen Rawatb14cab32015-11-02 17:01:51 -08001079 /*
1080 * Because of DBS a vdev may come up in any of the two MACs with
1081 * different capabilities. STBC capab should be fetched for given
1082 * hard_mode->MAC_id combo. It is planned that firmware should provide
1083 * these dev capabilities. But for now number of tx streams can be used
1084 * to identify if Tx STBC needs to be disabled.
1085 */
1086 if (intr->tx_streams < 2) {
1087 cmd->peer_vht_caps &= ~(1 << SIR_MAC_VHT_CAP_TXSTBC);
1088 WMA_LOGD("Num tx_streams: %d, Disabled txSTBC",
1089 intr->tx_streams);
1090 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001091 WMA_LOGD("peer_nss %d peer_ht_rates.num_rates %d ", cmd->peer_nss,
1092 peer_ht_rates.num_rates);
1093
Govind Singhb30d4c02016-03-24 11:01:23 +05301094 cmd->vht_capable = params->vhtCapable;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001095 if (params->vhtCapable) {
1096#define VHT2x2MCSMASK 0xc
Govind Singhb30d4c02016-03-24 11:01:23 +05301097 cmd->rx_max_rate = params->supportedRates.vhtRxHighestDataRate;
1098 cmd->rx_mcs_set = params->supportedRates.vhtRxMCSMap;
1099 cmd->tx_max_rate = params->supportedRates.vhtTxHighestDataRate;
1100 cmd->tx_mcs_set = params->supportedRates.vhtTxMCSMap;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001101
1102 if (params->vhtSupportedRxNss) {
1103 cmd->peer_nss = params->vhtSupportedRxNss;
1104 } else {
Govind Singhb30d4c02016-03-24 11:01:23 +05301105 cmd->peer_nss = ((cmd->rx_mcs_set & VHT2x2MCSMASK)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001106 == VHT2x2MCSMASK) ? 1 : 2;
1107 }
1108 }
1109
1110 /*
1111 * Limit nss to max number of rf chain supported by target
1112 * Otherwise Fw will crash
1113 */
1114 wma_update_txrx_chainmask(wma->num_rf_chains, &cmd->peer_nss);
1115
1116 intr->nss = cmd->peer_nss;
1117 cmd->peer_phymode = phymode;
1118 WMA_LOGD("%s: vdev_id %d associd %d peer_flags %x rate_caps %x "
1119 "peer_caps %x listen_intval %d ht_caps %x max_mpdu %d "
1120 "nss %d phymode %d peer_mpdu_density %d encr_type %d "
1121 "cmd->peer_vht_caps %x", __func__,
1122 cmd->vdev_id, cmd->peer_associd, cmd->peer_flags,
1123 cmd->peer_rate_caps, cmd->peer_caps,
1124 cmd->peer_listen_intval, cmd->peer_ht_caps,
1125 cmd->peer_max_mpdu, cmd->peer_nss, cmd->peer_phymode,
1126 cmd->peer_mpdu_density, params->encryptType,
1127 cmd->peer_vht_caps);
1128
Govind Singhb30d4c02016-03-24 11:01:23 +05301129 status = wmi_unified_peer_assoc_send(wma->wmi_handle,
1130 cmd);
1131 if (QDF_IS_STATUS_ERROR(status))
Arif Hussain49a5ffc2016-07-19 10:11:58 -07001132 WMA_LOGP(FL("Failed to send peer assoc command status = %d"),
1133 status);
Govind Singhb30d4c02016-03-24 11:01:23 +05301134 qdf_mem_free(cmd);
1135
1136 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001137}
1138
1139/**
1140 * wmi_unified_vdev_set_gtx_cfg_send() - set GTX params
1141 * @wmi_handle: wmi handle
1142 * @if_id: vdev id
1143 * @gtx_info: GTX config params
1144 *
1145 * This function set GTX related params in firmware.
1146 *
1147 * Return: 0 for success or error code
1148 */
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301149QDF_STATUS wmi_unified_vdev_set_gtx_cfg_send(wmi_unified_t wmi_handle,
1150 uint32_t if_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001151 gtx_config_t *gtx_info)
1152{
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301153 struct wmi_gtx_config params;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001154
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301155 params.gtx_rt_mask[0] = gtx_info->gtxRTMask[0];
1156 params.gtx_rt_mask[1] = gtx_info->gtxRTMask[1];
1157 params.gtx_usrcfg = gtx_info->gtxUsrcfg;
1158 params.gtx_threshold = gtx_info->gtxPERThreshold;
1159 params.gtx_margin = gtx_info->gtxPERMargin;
1160 params.gtx_tpcstep = gtx_info->gtxTPCstep;
1161 params.gtx_tpcmin = gtx_info->gtxTPCMin;
1162 params.gtx_bwmask = gtx_info->gtxBWMask;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001163
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301164 return wmi_unified_vdev_set_gtx_cfg_cmd(wmi_handle,
1165 if_id, &params);
1166
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001167}
1168
1169/**
1170 * wma_update_protection_mode() - update protection mode
1171 * @wma: wma handle
1172 * @vdev_id: vdev id
1173 * @llbcoexist: protection mode info
1174 *
1175 * This function set protection mode(RTS/CTS) to fw for passed vdev id.
1176 *
1177 * Return: none
1178 */
1179void wma_update_protection_mode(tp_wma_handle wma, uint8_t vdev_id,
1180 uint8_t llbcoexist)
1181{
Govind Singhd76a5b02016-03-08 15:12:14 +05301182 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001183 enum ieee80211_protmode prot_mode;
1184
1185 prot_mode = llbcoexist ? IEEE80211_PROT_CTSONLY : IEEE80211_PROT_NONE;
1186
Govind Singhd76a5b02016-03-08 15:12:14 +05301187 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001188 WMI_VDEV_PARAM_PROTECTION_MODE,
1189 prot_mode);
1190
Govind Singhd76a5b02016-03-08 15:12:14 +05301191 if (QDF_IS_STATUS_ERROR(ret))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001192 WMA_LOGE("Failed to send wmi protection mode cmd");
1193 else
1194 WMA_LOGD("Updated protection mode %d to target", prot_mode);
1195}
1196
1197/**
1198 * wma_update_beacon_interval() - update beacon interval in fw
1199 * @wma: wma handle
1200 * @vdev_id: vdev id
1201 * @beaconInterval: becon interval
1202 *
1203 * Return: none
1204 */
1205static void
1206wma_update_beacon_interval(tp_wma_handle wma, uint8_t vdev_id,
1207 uint16_t beaconInterval)
1208{
Govind Singhd76a5b02016-03-08 15:12:14 +05301209 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001210
Govind Singhd76a5b02016-03-08 15:12:14 +05301211 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001212 WMI_VDEV_PARAM_BEACON_INTERVAL,
1213 beaconInterval);
1214
Govind Singhd76a5b02016-03-08 15:12:14 +05301215 if (QDF_IS_STATUS_ERROR(ret))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001216 WMA_LOGE("Failed to update beacon interval");
1217 else
1218 WMA_LOGI("Updated beacon interval %d for vdev %d",
1219 beaconInterval, vdev_id);
1220}
1221
1222/**
1223 * wma_process_update_beacon_params() - update beacon parameters to target
1224 * @wma: wma handle
1225 * @bcn_params: beacon parameters
1226 *
1227 * Return: none
1228 */
1229void
1230wma_process_update_beacon_params(tp_wma_handle wma,
1231 tUpdateBeaconParams *bcn_params)
1232{
1233 if (!bcn_params) {
1234 WMA_LOGE("bcn_params NULL");
1235 return;
1236 }
1237
1238 if (bcn_params->smeSessionId >= wma->max_bssid) {
1239 WMA_LOGE("Invalid vdev id %d", bcn_params->smeSessionId);
1240 return;
1241 }
1242
1243 if (bcn_params->paramChangeBitmap & PARAM_BCN_INTERVAL_CHANGED) {
1244 wma_update_beacon_interval(wma, bcn_params->smeSessionId,
1245 bcn_params->beaconInterval);
1246 }
1247
1248 if (bcn_params->paramChangeBitmap & PARAM_llBCOEXIST_CHANGED)
1249 wma_update_protection_mode(wma, bcn_params->smeSessionId,
1250 bcn_params->llbCoexist);
1251}
1252
1253/**
1254 * wma_update_cfg_params() - update cfg parameters to target
1255 * @wma: wma handle
1256 * @cfgParam: cfg parameter
1257 *
1258 * Return: none
1259 */
1260void wma_update_cfg_params(tp_wma_handle wma, tSirMsgQ *cfgParam)
1261{
1262 uint8_t vdev_id;
1263 uint32_t param_id;
1264 uint32_t cfg_val;
Govind Singhd76a5b02016-03-08 15:12:14 +05301265 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001266 /* get mac to acess CFG data base */
1267 struct sAniSirGlobal *pmac;
1268
1269 switch (cfgParam->bodyval) {
1270 case WNI_CFG_RTS_THRESHOLD:
1271 param_id = WMI_VDEV_PARAM_RTS_THRESHOLD;
1272 break;
1273 case WNI_CFG_FRAGMENTATION_THRESHOLD:
1274 param_id = WMI_VDEV_PARAM_FRAGMENTATION_THRESHOLD;
1275 break;
1276 default:
1277 WMA_LOGD("Unhandled cfg parameter %d", cfgParam->bodyval);
1278 return;
1279 }
1280
Anurag Chouhan6d760662016-02-20 16:05:43 +05301281 pmac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001282
1283 if (NULL == pmac) {
1284 WMA_LOGE("%s: Failed to get pmac", __func__);
1285 return;
1286 }
1287
1288 if (wlan_cfg_get_int(pmac, (uint16_t) cfgParam->bodyval,
1289 &cfg_val) != eSIR_SUCCESS) {
1290 WMA_LOGE("Failed to get value for CFG PARAMS %d. returning without updating",
1291 cfgParam->bodyval);
1292 return;
1293 }
1294
1295 for (vdev_id = 0; vdev_id < wma->max_bssid; vdev_id++) {
1296 if (wma->interfaces[vdev_id].handle != 0) {
Govind Singhd76a5b02016-03-08 15:12:14 +05301297 ret = wma_vdev_set_param(wma->wmi_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001298 vdev_id, param_id,
1299 cfg_val);
Govind Singhd76a5b02016-03-08 15:12:14 +05301300 if (QDF_IS_STATUS_ERROR(ret))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001301 WMA_LOGE("Update cfg params failed for vdevId %d",
1302 vdev_id);
1303 }
1304 }
1305}
1306
1307/**
1308 * wma_read_cfg_wepkey() - fill key_info for WEP key
1309 * @wma_handle: wma handle
1310 * @key_info: key_info ptr
1311 * @def_key_idx: default key index
1312 * @num_keys: number of keys
1313 *
1314 * This function reads WEP keys from cfg and fills
1315 * up key_info.
1316 *
1317 * Return: none
1318 */
1319static void wma_read_cfg_wepkey(tp_wma_handle wma_handle,
1320 tSirKeys *key_info, uint32_t *def_key_idx,
1321 uint8_t *num_keys)
1322{
1323 tSirRetStatus status;
1324 uint32_t val = SIR_MAC_KEY_LENGTH;
1325 uint8_t i, j;
1326
1327 WMA_LOGD("Reading WEP keys from cfg");
1328 /* NOTE:def_key_idx is initialized to 0 by the caller */
1329 status = wlan_cfg_get_int(wma_handle->mac_context,
1330 WNI_CFG_WEP_DEFAULT_KEYID, def_key_idx);
1331 if (status != eSIR_SUCCESS)
1332 WMA_LOGE("Unable to read default id, defaulting to 0");
1333
1334 for (i = 0, j = 0; i < SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS; i++) {
1335 status = wlan_cfg_get_str(wma_handle->mac_context,
1336 (uint16_t) WNI_CFG_WEP_DEFAULT_KEY_1 +
1337 i, key_info[j].key, &val);
1338 if (status != eSIR_SUCCESS) {
1339 WMA_LOGE("WEP key is not configured at :%d", i);
1340 } else {
1341 key_info[j].keyId = i;
1342 key_info[j].keyLength = (uint16_t) val;
1343 j++;
1344 }
1345 }
1346 *num_keys = j;
1347}
1348
1349/**
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301350 * wma_setup_install_key_cmd() - set key parameters
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001351 * @wma_handle: wma handle
1352 * @key_params: key parameters
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001353 * @mode: op mode
1354 *
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301355 * This function fills structure from information
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001356 * passed in key_params.
1357 *
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301358 * Return: QDF_STATUS_SUCCESS - success
1359 QDF_STATUS_E_FAILURE - failure
1360 QDF_STATUS_E_NOMEM - invalid request
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001361 */
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301362static QDF_STATUS wma_setup_install_key_cmd(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001363 struct wma_set_key_params
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301364 *key_params, uint8_t mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001365{
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301366 struct set_key_params params;
1367 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001368#ifdef WLAN_FEATURE_11W
1369 struct wma_txrx_node *iface = NULL;
1370#endif /* WLAN_FEATURE_11W */
1371 if ((key_params->key_type == eSIR_ED_NONE &&
1372 key_params->key_len) || (key_params->key_type != eSIR_ED_NONE &&
1373 !key_params->key_len)) {
1374 WMA_LOGE("%s:Invalid set key request", __func__);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301375 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001376 }
1377
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301378 params.vdev_id = key_params->vdev_id;
1379 params.key_idx = key_params->key_idx;
1380 qdf_mem_copy(params.peer_mac, key_params->peer_mac, IEEE80211_ADDR_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001381
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301382#ifdef FEATURE_WLAN_WAPI
1383 qdf_mem_set(params.tx_iv, 16, 0);
1384 qdf_mem_set(params.rx_iv, 16, 0);
1385#endif
1386 params.key_txmic_len = 0;
1387 params.key_rxmic_len = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001388
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301389 params.key_flags = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001390 if (key_params->unicast)
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301391 params.key_flags |= PAIRWISE_USAGE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001392 else
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301393 params.key_flags |= GROUP_USAGE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001394
1395 switch (key_params->key_type) {
1396 case eSIR_ED_NONE:
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301397 params.key_cipher = WMI_CIPHER_NONE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001398 break;
1399 case eSIR_ED_WEP40:
1400 case eSIR_ED_WEP104:
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301401 params.key_cipher = WMI_CIPHER_WEP;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001402 if (key_params->unicast &&
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301403 params.key_idx == key_params->def_key_idx) {
Ganesh Kondabattini59a4a952015-11-30 11:55:40 +05301404 WMA_LOGD("STA Mode: cmd->key_flags |= TX_USAGE");
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301405 params.key_flags |= TX_USAGE;
Ganesh Kondabattini59a4a952015-11-30 11:55:40 +05301406 } else if ((mode == wlan_op_mode_ap) &&
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301407 (params.key_idx == key_params->def_key_idx)) {
Ganesh Kondabattini59a4a952015-11-30 11:55:40 +05301408 WMA_LOGD("AP Mode: cmd->key_flags |= TX_USAGE");
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301409 params.key_flags |= TX_USAGE;
Ganesh Kondabattini59a4a952015-11-30 11:55:40 +05301410 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001411 break;
1412 case eSIR_ED_TKIP:
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301413 params.key_txmic_len = WMA_TXMIC_LEN;
1414 params.key_rxmic_len = WMA_RXMIC_LEN;
1415 params.key_cipher = WMI_CIPHER_TKIP;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001416 break;
1417#ifdef FEATURE_WLAN_WAPI
1418#define WPI_IV_LEN 16
1419 case eSIR_ED_WPI:
1420 {
1421 /*initialize receive and transmit IV with default values */
1422 /* **Note: tx_iv must be sent in reverse** */
1423 unsigned char tx_iv[16] = { 0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c,
1424 0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c,
1425 0x36, 0x5c, 0x36, 0x5c};
1426 unsigned char rx_iv[16] = { 0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36,
1427 0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36,
1428 0x5c, 0x36, 0x5c, 0x37};
1429 if (mode == wlan_op_mode_ap) {
1430 /* Authenticator initializes the value of PN as
1431 * 0x5C365C365C365C365C365C365C365C36 for MCastkey Update
1432 */
1433 if (key_params->unicast)
1434 tx_iv[0] = 0x37;
1435
1436 rx_iv[WPI_IV_LEN - 1] = 0x36;
1437 } else {
1438 if (!key_params->unicast)
1439 rx_iv[WPI_IV_LEN - 1] = 0x36;
1440 }
1441
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301442 params.key_txmic_len = WMA_TXMIC_LEN;
1443 params.key_rxmic_len = WMA_RXMIC_LEN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001444
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301445 qdf_mem_copy(&params.rx_iv, &rx_iv,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001446 WPI_IV_LEN);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301447 qdf_mem_copy(&params.tx_iv, &tx_iv,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001448 WPI_IV_LEN);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301449 params.key_cipher = WMI_CIPHER_WAPI;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001450 break;
1451 }
1452#endif /* FEATURE_WLAN_WAPI */
1453 case eSIR_ED_CCMP:
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301454 params.key_cipher = WMI_CIPHER_AES_CCM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001455 break;
1456#ifdef WLAN_FEATURE_11W
1457 case eSIR_ED_AES_128_CMAC:
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301458 params.key_cipher = WMI_CIPHER_AES_CMAC;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001459 break;
1460#endif /* WLAN_FEATURE_11W */
1461 default:
1462 /* TODO: MFP ? */
1463 WMA_LOGE("%s:Invalid encryption type:%d", __func__,
1464 key_params->key_type);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301465 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001466 }
1467
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001468#ifdef BIG_ENDIAN_HOST
1469 {
1470 /* for big endian host, copy engine byte_swap is enabled
1471 * But the key data content is in network byte order
1472 * Need to byte swap the key data content - so when copy engine
1473 * does byte_swap - target gets key_data content in the correct
1474 * order.
1475 */
1476 int8_t i;
1477 uint32_t *destp, *srcp;
1478
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301479 destp = (uint32_t *) params.key_data;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001480 srcp = (uint32_t *) key_params->key_data;
1481 for (i = 0;
1482 i < roundup(key_params->key_len, sizeof(uint32_t)) / 4;
1483 i++) {
1484 *destp = le32_to_cpu(*srcp);
1485 destp++;
1486 srcp++;
1487 }
1488 }
1489#else
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301490 qdf_mem_copy((void *)params.key_data,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001491 (const void *)key_params->key_data, key_params->key_len);
1492#endif /* BIG_ENDIAN_HOST */
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301493 params.key_len = key_params->key_len;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001494
1495#ifdef WLAN_FEATURE_11W
1496 if (key_params->key_type == eSIR_ED_AES_128_CMAC) {
1497 iface = &wma_handle->interfaces[key_params->vdev_id];
1498 if (iface) {
1499 iface->key.key_length = key_params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301500 qdf_mem_copy(iface->key.key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001501 (const void *)key_params->key_data,
1502 iface->key.key_length);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301503 if ((params.key_idx == WMA_IGTK_KEY_INDEX_4) ||
1504 (params.key_idx == WMA_IGTK_KEY_INDEX_5))
1505 qdf_mem_zero(iface->key.key_id[params.key_idx -
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001506 WMA_IGTK_KEY_INDEX_4].ipn,
1507 CMAC_IPN_LEN);
1508 }
1509 }
1510#endif /* WLAN_FEATURE_11W */
1511
1512 WMA_LOGD("Key setup : vdev_id %d key_idx %d key_type %d key_len %d"
1513 " unicast %d peer_mac %pM def_key_idx %d", key_params->vdev_id,
1514 key_params->key_idx, key_params->key_type, key_params->key_len,
1515 key_params->unicast, key_params->peer_mac,
1516 key_params->def_key_idx);
1517
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301518 status = wmi_unified_setup_install_key_cmd(wma_handle->wmi_handle,
1519 &params);
1520
1521 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001522}
1523
1524/**
1525 * wma_set_bsskey() - set encryption key to fw.
1526 * @wma_handle: wma handle
1527 * @key_info: key info
1528 *
1529 * Return: none
1530 */
1531void wma_set_bsskey(tp_wma_handle wma_handle, tpSetBssKeyParams key_info)
1532{
1533 struct wma_set_key_params key_params;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301534 QDF_STATUS status = QDF_STATUS_SUCCESS;
1535 uint32_t i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001536 uint32_t def_key_idx = 0;
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001537 uint32_t wlan_opmode;
Leo Chang96464902016-10-28 11:10:54 -07001538 void *txrx_vdev;
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001539 uint8_t *mac_addr;
Leo Chang96464902016-10-28 11:10:54 -07001540 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001541
1542 WMA_LOGD("BSS key setup");
1543 txrx_vdev = wma_find_vdev_by_id(wma_handle, key_info->smesessionId);
1544 if (!txrx_vdev) {
1545 WMA_LOGE("%s:Invalid vdev handle", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301546 key_info->status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001547 goto out;
1548 }
Leo Chang96464902016-10-28 11:10:54 -07001549 wlan_opmode = cdp_get_opmode(soc, txrx_vdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001550
1551 /*
1552 * For IBSS, WMI expects the BSS key to be set per peer key
1553 * So cache the BSS key in the wma_handle and re-use it when the
1554 * STA key is been setup for a peer
1555 */
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001556 if (wlan_op_mode_ibss == wlan_opmode) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301557 key_info->status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001558 if (wma_handle->ibss_started > 0)
1559 goto out;
1560 WMA_LOGD("Caching IBSS Key");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301561 qdf_mem_copy(&wma_handle->ibsskey_info, key_info,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001562 sizeof(tSetBssKeyParams));
1563 }
1564
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301565 qdf_mem_set(&key_params, sizeof(key_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001566 key_params.vdev_id = key_info->smesessionId;
1567 key_params.key_type = key_info->encType;
1568 key_params.singl_tid_rc = key_info->singleTidRc;
1569 key_params.unicast = false;
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001570 if (wlan_opmode == wlan_op_mode_sta) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301571 qdf_mem_copy(key_params.peer_mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001572 wma_handle->interfaces[key_info->smesessionId].bssid,
1573 IEEE80211_ADDR_LEN);
1574 } else {
Leo Chang96464902016-10-28 11:10:54 -07001575 mac_addr = cdp_get_vdev_mac_addr(soc, txrx_vdev);
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001576 if (mac_addr == NULL) {
1577 WMA_LOGE("%s: mac_addr is NULL for vdev with id %d",
1578 __func__, key_info->smesessionId);
1579 goto out;
1580 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001581 /* vdev mac address will be passed for all other modes */
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001582 qdf_mem_copy(key_params.peer_mac, mac_addr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001583 IEEE80211_ADDR_LEN);
1584 WMA_LOGA("BSS Key setup with vdev_mac %pM\n",
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001585 mac_addr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001586 }
1587
1588 if (key_info->numKeys == 0 &&
1589 (key_info->encType == eSIR_ED_WEP40 ||
1590 key_info->encType == eSIR_ED_WEP104)) {
1591 wma_read_cfg_wepkey(wma_handle, key_info->key,
1592 &def_key_idx, &key_info->numKeys);
1593 }
1594
1595 for (i = 0; i < key_info->numKeys; i++) {
1596 if (key_params.key_type != eSIR_ED_NONE &&
1597 !key_info->key[i].keyLength)
1598 continue;
1599 if (key_info->encType == eSIR_ED_WPI) {
1600 key_params.key_idx = key_info->key[i].keyId;
1601 key_params.def_key_idx = key_info->key[i].keyId;
1602 } else
1603 key_params.key_idx = key_info->key[i].keyId;
1604
1605 key_params.key_len = key_info->key[i].keyLength;
1606 if (key_info->encType == eSIR_ED_TKIP) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301607 qdf_mem_copy(key_params.key_data,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001608 key_info->key[i].key, 16);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301609 qdf_mem_copy(&key_params.key_data[16],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001610 &key_info->key[i].key[24], 8);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301611 qdf_mem_copy(&key_params.key_data[24],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001612 &key_info->key[i].key[16], 8);
1613 } else
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301614 qdf_mem_copy((void *)key_params.key_data,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001615 (const void *)key_info->key[i].key,
1616 key_info->key[i].keyLength);
1617
1618 WMA_LOGD("%s: bss key[%d] length %d", __func__, i,
1619 key_info->key[i].keyLength);
1620
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301621 status = wma_setup_install_key_cmd(wma_handle, &key_params,
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001622 wlan_opmode);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301623 if (status == QDF_STATUS_E_NOMEM) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001624 WMA_LOGE("%s:Failed to setup install key buf",
1625 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301626 key_info->status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001627 goto out;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301628 } else if (status == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001629 WMA_LOGE("%s:Failed to send install key command",
1630 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301631 key_info->status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001632 goto out;
1633 }
1634 }
1635
1636 wma_handle->ibss_started++;
1637 /* TODO: Should we wait till we get HTT_T2H_MSG_TYPE_SEC_IND? */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301638 key_info->status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001639
1640out:
1641 wma_send_msg(wma_handle, WMA_SET_BSSKEY_RSP, (void *)key_info, 0);
1642}
1643
1644#ifdef QCA_IBSS_SUPPORT
1645/**
1646 * wma_calc_ibss_heart_beat_timer() - calculate IBSS heart beat timer
1647 * @peer_num: number of peers
1648 *
1649 * Return: heart beat timer value
1650 */
1651static uint16_t wma_calc_ibss_heart_beat_timer(int16_t peer_num)
1652{
1653 /* heart beat timer value look-up table */
1654 /* entry index : (the number of currently connected peers) - 1
1655 entry value : the heart time threshold value in seconds for
1656 detecting ibss peer departure */
Naveen Rawatc45d1622016-07-05 12:20:09 -07001657 static const uint16_t heart_beat_timer[MAX_PEERS] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001658 4, 4, 4, 4, 4, 4, 4, 4,
1659 8, 8, 8, 8, 8, 8, 8, 8,
1660 12, 12, 12, 12, 12, 12, 12, 12,
1661 16, 16, 16, 16, 16, 16, 16, 16
1662 };
1663
Naveen Rawatc45d1622016-07-05 12:20:09 -07001664 if (peer_num < 1 || peer_num > MAX_PEERS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001665 return 0;
1666
1667 return heart_beat_timer[peer_num - 1];
1668
1669}
1670
1671/**
1672 * wma_adjust_ibss_heart_beat_timer() - set ibss heart beat timer in fw.
1673 * @wma: wma handle
1674 * @vdev_id: vdev id
1675 * @peer_num_delta: peer number delta value
1676 *
1677 * Return: none
1678 */
1679void wma_adjust_ibss_heart_beat_timer(tp_wma_handle wma,
1680 uint8_t vdev_id,
1681 int8_t peer_num_delta)
1682{
Leo Chang96464902016-10-28 11:10:54 -07001683 void *vdev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001684 int16_t new_peer_num;
1685 uint16_t new_timer_value_sec;
1686 uint32_t new_timer_value_ms;
Govind Singhd76a5b02016-03-08 15:12:14 +05301687 QDF_STATUS status;
Leo Chang96464902016-10-28 11:10:54 -07001688 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001689
1690 if (peer_num_delta != 1 && peer_num_delta != -1) {
1691 WMA_LOGE("Invalid peer_num_delta value %d", peer_num_delta);
1692 return;
1693 }
1694
1695 vdev = wma_find_vdev_by_id(wma, vdev_id);
1696 if (!vdev) {
1697 WMA_LOGE("vdev not found : vdev_id %d", vdev_id);
1698 return;
1699 }
1700
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001701 /* adjust peer numbers */
Leo Chang96464902016-10-28 11:10:54 -07001702 new_peer_num = cdp_peer_update_ibss_add_peer_num_of_vdev(soc, vdev,
1703 peer_num_delta);
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001704 if (OL_TXRX_INVALID_NUM_PEERS == new_peer_num) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001705 WMA_LOGE("new peer num %d out of valid boundary", new_peer_num);
1706 return;
1707 }
1708
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001709 /* reset timer value if all peers departed */
1710 if (new_peer_num == 0) {
Leo Chang96464902016-10-28 11:10:54 -07001711 cdp_set_ibss_vdev_heart_beat_timer(soc, vdev, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001712 return;
1713 }
1714
1715 /* calculate new timer value */
1716 new_timer_value_sec = wma_calc_ibss_heart_beat_timer(new_peer_num);
1717 if (new_timer_value_sec == 0) {
1718 WMA_LOGE("timer value %d is invalid for peer number %d",
1719 new_timer_value_sec, new_peer_num);
1720 return;
1721 }
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001722 if (new_timer_value_sec ==
Leo Chang96464902016-10-28 11:10:54 -07001723 cdp_set_ibss_vdev_heart_beat_timer(soc, vdev, new_timer_value_sec)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001724 WMA_LOGD("timer value %d stays same, no need to notify target",
1725 new_timer_value_sec);
1726 return;
1727 }
1728
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001729 new_timer_value_ms = ((uint32_t) new_timer_value_sec) * 1000;
1730
Govind Singhd76a5b02016-03-08 15:12:14 +05301731 status = wma_vdev_set_param(wma->wmi_handle, vdev_id,
1732 WMI_VDEV_PARAM_IBSS_MAX_BCN_LOST_MS,
1733 new_timer_value_ms);
1734 if (QDF_IS_STATUS_ERROR(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001735 WMA_LOGE("Failed to set IBSS link monitoring timer value");
1736 return;
1737 }
1738
1739 WMA_LOGD("Set IBSS link monitor timer: peer_num = %d timer_value = %d",
1740 new_peer_num, new_timer_value_ms);
1741}
1742
1743#endif /* QCA_IBSS_SUPPORT */
1744/**
1745 * wma_set_ibsskey_helper() - cached IBSS key in wma handle
1746 * @wma_handle: wma handle
1747 * @key_info: set bss key info
1748 * @peerMacAddr: peer mac address
1749 *
1750 * Return: none
1751 */
1752static void wma_set_ibsskey_helper(tp_wma_handle wma_handle,
1753 tpSetBssKeyParams key_info,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301754 struct qdf_mac_addr peer_macaddr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001755{
1756 struct wma_set_key_params key_params;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301757 QDF_STATUS status = QDF_STATUS_SUCCESS;
1758 uint32_t i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001759 uint32_t def_key_idx = 0;
Leo Chang96464902016-10-28 11:10:54 -07001760 void *txrx_vdev;
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001761 int opmode;
Leo Chang96464902016-10-28 11:10:54 -07001762 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001763
1764 WMA_LOGD("BSS key setup for peer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001765 txrx_vdev = wma_find_vdev_by_id(wma_handle, key_info->smesessionId);
1766 if (!txrx_vdev) {
1767 WMA_LOGE("%s:Invalid vdev handle", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301768 key_info->status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001769 return;
1770 }
1771
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301772 qdf_mem_set(&key_params, sizeof(key_params), 0);
Leo Chang96464902016-10-28 11:10:54 -07001773 opmode = cdp_get_opmode(soc, txrx_vdev);
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001774 qdf_mem_set(&key_params, sizeof(key_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001775 key_params.vdev_id = key_info->smesessionId;
1776 key_params.key_type = key_info->encType;
1777 key_params.singl_tid_rc = key_info->singleTidRc;
1778 key_params.unicast = false;
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001779 ASSERT(wlan_op_mode_ibss == opmode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001780
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301781 qdf_mem_copy(key_params.peer_mac, peer_macaddr.bytes,
Srinivas Girigowdad5965c42015-12-04 13:43:16 -08001782 IEEE80211_ADDR_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001783
1784 if (key_info->numKeys == 0 &&
1785 (key_info->encType == eSIR_ED_WEP40 ||
1786 key_info->encType == eSIR_ED_WEP104)) {
1787 wma_read_cfg_wepkey(wma_handle, key_info->key,
1788 &def_key_idx, &key_info->numKeys);
Masti, Narayanraddiab712a72016-08-04 11:59:11 +05301789 } else if ((key_info->encType == eSIR_ED_WEP40) ||
1790 (key_info->encType == eSIR_ED_WEP104)) {
1791 struct wma_txrx_node *intf =
1792 &wma_handle->interfaces[key_info->smesessionId];
1793 key_params.def_key_idx = intf->wep_default_key_idx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001794 }
1795
1796 for (i = 0; i < key_info->numKeys; i++) {
1797 if (key_params.key_type != eSIR_ED_NONE &&
1798 !key_info->key[i].keyLength)
1799 continue;
1800 key_params.key_idx = key_info->key[i].keyId;
1801 key_params.key_len = key_info->key[i].keyLength;
1802 if (key_info->encType == eSIR_ED_TKIP) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301803 qdf_mem_copy(key_params.key_data,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001804 key_info->key[i].key, 16);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301805 qdf_mem_copy(&key_params.key_data[16],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001806 &key_info->key[i].key[24], 8);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301807 qdf_mem_copy(&key_params.key_data[24],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001808 &key_info->key[i].key[16], 8);
1809 } else
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301810 qdf_mem_copy((void *)key_params.key_data,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001811 (const void *)key_info->key[i].key,
1812 key_info->key[i].keyLength);
1813
1814 WMA_LOGD("%s: peer bcast key[%d] length %d", __func__, i,
1815 key_info->key[i].keyLength);
1816
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301817 status = wma_setup_install_key_cmd(wma_handle, &key_params,
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001818 opmode);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301819 if (status == QDF_STATUS_E_NOMEM) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001820 WMA_LOGE("%s:Failed to setup install key buf",
1821 __func__);
1822 return;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301823 } else if (status == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001824 WMA_LOGE("%s:Failed to send install key command",
1825 __func__);
1826 }
1827 }
1828}
1829
1830/**
1831 * wma_set_stakey() - set encryption key
1832 * @wma_handle: wma handle
1833 * @key_info: station key info
1834 *
1835 * This function sets encryption key for WEP/WPA/WPA2
1836 * encryption mode in firmware and send response to upper layer.
1837 *
1838 * Return: none
1839 */
1840void wma_set_stakey(tp_wma_handle wma_handle, tpSetStaKeyParams key_info)
1841{
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301842 int32_t i;
1843 QDF_STATUS status = QDF_STATUS_SUCCESS;
Leo Chang96464902016-10-28 11:10:54 -07001844 void *txrx_pdev;
1845 void *txrx_vdev;
1846 void *peer;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001847 uint8_t num_keys = 0, peer_id;
1848 struct wma_set_key_params key_params;
1849 uint32_t def_key_idx = 0;
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001850 int opmode;
Leo Chang96464902016-10-28 11:10:54 -07001851 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001852
1853 WMA_LOGD("STA key setup");
1854
1855 /* Get the txRx Pdev handle */
Anurag Chouhan6d760662016-02-20 16:05:43 +05301856 txrx_pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001857 if (!txrx_pdev) {
1858 WMA_LOGE("%s:Invalid txrx pdev handle", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301859 key_info->status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001860 goto out;
1861 }
1862
Leo Chang96464902016-10-28 11:10:54 -07001863 peer = cdp_peer_find_by_addr(soc, txrx_pdev,
Srinivas Girigowdad5965c42015-12-04 13:43:16 -08001864 key_info->peer_macaddr.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001865 &peer_id);
1866 if (!peer) {
1867 WMA_LOGE("%s:Invalid peer for key setting", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301868 key_info->status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001869 goto out;
1870 }
1871
1872 txrx_vdev = wma_find_vdev_by_id(wma_handle, key_info->smesessionId);
1873 if (!txrx_vdev) {
1874 WMA_LOGE("%s:TxRx Vdev Handle is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301875 key_info->status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001876 goto out;
1877 }
Leo Chang96464902016-10-28 11:10:54 -07001878 opmode = cdp_get_opmode(soc, txrx_vdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001879
1880 if (key_info->defWEPIdx == WMA_INVALID_KEY_IDX &&
1881 (key_info->encType == eSIR_ED_WEP40 ||
1882 key_info->encType == eSIR_ED_WEP104) &&
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001883 opmode != wlan_op_mode_ap) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001884 wma_read_cfg_wepkey(wma_handle, key_info->key,
1885 &def_key_idx, &num_keys);
1886 key_info->defWEPIdx = def_key_idx;
1887 } else {
1888 num_keys = SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS;
1889 if (key_info->encType != eSIR_ED_NONE) {
1890 for (i = 0; i < num_keys; i++) {
1891 if (key_info->key[i].keyDirection ==
1892 eSIR_TX_DEFAULT) {
1893 key_info->defWEPIdx = i;
1894 break;
1895 }
1896 }
1897 }
1898 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301899 qdf_mem_set(&key_params, sizeof(key_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001900 key_params.vdev_id = key_info->smesessionId;
1901 key_params.key_type = key_info->encType;
1902 key_params.singl_tid_rc = key_info->singleTidRc;
1903 key_params.unicast = true;
1904 key_params.def_key_idx = key_info->defWEPIdx;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301905 qdf_mem_copy((void *)key_params.peer_mac,
Srinivas Girigowdad5965c42015-12-04 13:43:16 -08001906 (const void *)key_info->peer_macaddr.bytes,
1907 IEEE80211_ADDR_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001908 for (i = 0; i < num_keys; i++) {
1909 if (key_params.key_type != eSIR_ED_NONE &&
1910 !key_info->key[i].keyLength)
1911 continue;
1912 if (key_info->encType == eSIR_ED_TKIP) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301913 qdf_mem_copy(key_params.key_data,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001914 key_info->key[i].key, 16);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301915 qdf_mem_copy(&key_params.key_data[16],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001916 &key_info->key[i].key[24], 8);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301917 qdf_mem_copy(&key_params.key_data[24],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001918 &key_info->key[i].key[16], 8);
1919 } else
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301920 qdf_mem_copy(key_params.key_data, key_info->key[i].key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001921 key_info->key[i].keyLength);
1922 if (key_info->encType == eSIR_ED_WPI) {
1923 key_params.key_idx = key_info->key[i].keyId;
1924 key_params.def_key_idx = key_info->key[i].keyId;
1925 } else
1926 key_params.key_idx = i;
1927
1928 key_params.key_len = key_info->key[i].keyLength;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301929 status = wma_setup_install_key_cmd(wma_handle, &key_params,
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001930 opmode);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301931 if (status == QDF_STATUS_E_NOMEM) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001932 WMA_LOGE("%s:Failed to setup install key buf",
1933 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301934 key_info->status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001935 goto out;
1936 }
1937
1938 WMA_LOGD("%s: peer unicast key[%d] %d ", __func__, i,
1939 key_info->key[i].keyLength);
1940
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301941 if (status == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001942 WMA_LOGE("%s:Failed to send install key command",
1943 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301944 key_info->status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001945 goto out;
1946 }
1947 }
1948
1949 /* In IBSS mode, set the BSS KEY for this peer
1950 * BSS key is supposed to be cache into wma_handle
1951 */
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001952 if (wlan_op_mode_ibss == opmode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001953 wma_set_ibsskey_helper(wma_handle, &wma_handle->ibsskey_info,
Srinivas Girigowdad5965c42015-12-04 13:43:16 -08001954 key_info->peer_macaddr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001955 }
1956
1957 /* TODO: Should we wait till we get HTT_T2H_MSG_TYPE_SEC_IND? */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301958 key_info->status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001959out:
1960 if (key_info->sendRsp)
1961 wma_send_msg(wma_handle, WMA_SET_STAKEY_RSP, (void *)key_info,
1962 0);
1963}
1964
1965/**
1966 * wma_process_update_edca_param_req() - update EDCA params
1967 * @handle: wma handle
1968 * @edca_params: edca parameters
1969 *
1970 * This function updates EDCA parameters to the target
1971 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05301972 * Return: QDF Status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001973 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301974QDF_STATUS wma_process_update_edca_param_req(WMA_HANDLE handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001975 tEdcaParams *edca_params)
1976{
1977 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301978 wmi_wmm_vparams wmm_param[WME_NUM_AC];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001979 tSirMacEdcaParamRecord *edca_record;
1980 int ac;
Leo Chang96464902016-10-28 11:10:54 -07001981 void *pdev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001982 struct ol_tx_wmm_param_t ol_tx_wmm_param;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301983 uint8_t vdev_id;
1984 QDF_STATUS status;
Leo Chang96464902016-10-28 11:10:54 -07001985 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301986 vdev_id = edca_params->bssIdx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001987
1988 for (ac = 0; ac < WME_NUM_AC; ac++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001989 switch (ac) {
1990 case WME_AC_BE:
1991 edca_record = &edca_params->acbe;
1992 break;
1993 case WME_AC_BK:
1994 edca_record = &edca_params->acbk;
1995 break;
1996 case WME_AC_VI:
1997 edca_record = &edca_params->acvi;
1998 break;
1999 case WME_AC_VO:
2000 edca_record = &edca_params->acvo;
2001 break;
2002 default:
2003 goto fail;
2004 }
2005
Himanshu Agarwal009f1572016-03-09 17:26:02 +05302006 wma_update_edca_params_for_ac(edca_record, &wmm_param[ac], ac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002007
Himanshu Agarwal009f1572016-03-09 17:26:02 +05302008 ol_tx_wmm_param.ac[ac].aifs = wmm_param[ac].aifs;
2009 ol_tx_wmm_param.ac[ac].cwmin = wmm_param[ac].cwmin;
2010 ol_tx_wmm_param.ac[ac].cwmax = wmm_param[ac].cwmax;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002011 }
2012
Himanshu Agarwal009f1572016-03-09 17:26:02 +05302013 status = wmi_unified_process_update_edca_param(wma_handle->wmi_handle,
2014 vdev_id, wmm_param);
2015 if (status == QDF_STATUS_E_NOMEM)
2016 return status;
2017 else if (status == QDF_STATUS_E_FAILURE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002018 goto fail;
2019
Anurag Chouhan6d760662016-02-20 16:05:43 +05302020 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Himanshu Agarwal94045e42015-10-19 19:16:19 +05302021 if (pdev)
Leo Chang96464902016-10-28 11:10:54 -07002022 cdp_set_wmm_param(soc, pdev, ol_tx_wmm_param);
Himanshu Agarwal94045e42015-10-19 19:16:19 +05302023 else
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302024 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002025
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302026 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002027
2028fail:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002029 WMA_LOGE("%s: Failed to set WMM Paremeters", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302030 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002031}
2032
2033/**
2034 * wmi_unified_probe_rsp_tmpl_send() - send probe response template to fw
2035 * @wma: wma handle
2036 * @vdev_id: vdev id
2037 * @probe_rsp_info: probe response info
2038 *
2039 * Return: 0 for success or error code
2040 */
2041static int wmi_unified_probe_rsp_tmpl_send(tp_wma_handle wma,
2042 uint8_t vdev_id,
2043 tpSendProbeRespParams probe_rsp_info)
2044{
Himanshu Agarwal009f1572016-03-09 17:26:02 +05302045 uint8_t *frm;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002046 uint64_t adjusted_tsf_le;
2047 struct ieee80211_frame *wh;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05302048 struct wmi_probe_resp_params params;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002049
2050 WMA_LOGD(FL("Send probe response template for vdev %d"), vdev_id);
2051
2052 frm = probe_rsp_info->pProbeRespTemplate;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05302053
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002054 /*
2055 * Make the TSF offset negative so probe response in the same
2056 * staggered batch have the same TSF.
2057 */
2058 adjusted_tsf_le = cpu_to_le64(0ULL -
2059 wma->interfaces[vdev_id].tsfadjust);
2060 /* Update the timstamp in the probe response buffer with adjusted TSF */
2061 wh = (struct ieee80211_frame *)frm;
2062 A_MEMCPY(&wh[1], &adjusted_tsf_le, sizeof(adjusted_tsf_le));
2063
Himanshu Agarwal009f1572016-03-09 17:26:02 +05302064 params.pProbeRespTemplate = probe_rsp_info->pProbeRespTemplate;
2065 params.probeRespTemplateLen = probe_rsp_info->probeRespTemplateLen;
2066 qdf_mem_copy(params.bssId, probe_rsp_info->bssId,
Krunal Soniab793342016-04-22 18:43:20 -07002067 IEEE80211_ADDR_LEN);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05302068 qdf_mem_copy(params.ucProxyProbeReqValidIEBmap,
2069 probe_rsp_info->ucProxyProbeReqValidIEBmap,
2070 8 * sizeof(uint32_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002071
Himanshu Agarwal009f1572016-03-09 17:26:02 +05302072 return wmi_unified_probe_rsp_tmpl_send_cmd(wma->wmi_handle, vdev_id,
2073 &params, frm);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002074}
2075
2076/**
Govind Singh61ad2622016-02-22 17:25:02 +05302077 * wma_unified_bcn_tmpl_send() - send beacon template to fw
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002078 * @wma:wma handle
2079 * @vdev_id: vdev id
2080 * @bcn_info: beacon info
2081 * @bytes_to_strip: bytes to strip
2082 *
Govind Singh61ad2622016-02-22 17:25:02 +05302083 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002084 */
Govind Singh61ad2622016-02-22 17:25:02 +05302085static QDF_STATUS wma_unified_bcn_tmpl_send(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002086 uint8_t vdev_id,
Govind Singh61ad2622016-02-22 17:25:02 +05302087 const tpSendbeaconParams bcn_info,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002088 uint8_t bytes_to_strip)
2089{
Govind Singh61ad2622016-02-22 17:25:02 +05302090 struct beacon_params params = {0};
2091 uint32_t tmpl_len, tmpl_len_aligned;
2092 uint8_t *frm;
2093 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002094 uint8_t *p2p_ie;
2095 uint16_t p2p_ie_len = 0;
2096 uint64_t adjusted_tsf_le;
2097 struct ieee80211_frame *wh;
2098
2099 WMA_LOGD("Send beacon template for vdev %d", vdev_id);
2100
2101 if (bcn_info->p2pIeOffset) {
2102 p2p_ie = bcn_info->beacon + bcn_info->p2pIeOffset;
2103 p2p_ie_len = (uint16_t) p2p_ie[1] + 2;
2104 }
2105
2106 /*
2107 * XXX: The first byte of beacon buffer contains beacon length
2108 * only when UMAC in sending the beacon template. In othercases
2109 * (ex: from tbtt update) beacon length is read from beacon
2110 * information.
2111 */
2112 if (bytes_to_strip)
2113 tmpl_len = *(uint32_t *) &bcn_info->beacon[0];
2114 else
2115 tmpl_len = bcn_info->beaconLength;
2116 if (p2p_ie_len) {
2117 tmpl_len -= (uint32_t) p2p_ie_len;
2118 }
2119
2120 frm = bcn_info->beacon + bytes_to_strip;
2121 tmpl_len_aligned = roundup(tmpl_len, sizeof(A_UINT32));
2122 /*
2123 * Make the TSF offset negative so beacons in the same
2124 * staggered batch have the same TSF.
2125 */
2126 adjusted_tsf_le = cpu_to_le64(0ULL -
2127 wma->interfaces[vdev_id].tsfadjust);
2128 /* Update the timstamp in the beacon buffer with adjusted TSF */
2129 wh = (struct ieee80211_frame *)frm;
2130 A_MEMCPY(&wh[1], &adjusted_tsf_le, sizeof(adjusted_tsf_le));
2131
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002132
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002133
Govind Singh61ad2622016-02-22 17:25:02 +05302134 params.vdev_id = vdev_id;
2135 params.tim_ie_offset = bcn_info->timIeOffset - bytes_to_strip;
2136 params.tmpl_len = tmpl_len;
2137 params.frm = frm;
2138 params.tmpl_len_aligned = tmpl_len_aligned;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002139
Govind Singh61ad2622016-02-22 17:25:02 +05302140 ret = wmi_unified_beacon_send_cmd(wma->wmi_handle,
2141 &params);
2142 if (QDF_IS_STATUS_ERROR(ret)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002143 WMA_LOGE("%s: Failed to send bcn tmpl: %d", __func__, ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002144 }
2145
2146 return ret;
2147}
2148
2149/**
2150 * wma_store_bcn_tmpl() - store beacon template
2151 * @wma: wma handle
2152 * @vdev_id: vdev id
2153 * @bcn_info: beacon params
2154 *
2155 * This function stores beacon template locally.
2156 * This will send to target on the reception of
2157 * SWBA event.
2158 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302159 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002160 */
Jeff Johnsonc4b47a92016-10-07 12:34:41 -07002161static QDF_STATUS wma_store_bcn_tmpl(tp_wma_handle wma, uint8_t vdev_id,
2162 tpSendbeaconParams bcn_info)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002163{
2164 struct beacon_info *bcn;
2165 uint32_t len;
2166 uint8_t *bcn_payload;
2167 struct beacon_tim_ie *tim_ie;
2168
2169 bcn = wma->interfaces[vdev_id].beacon;
2170 if (!bcn || !bcn->buf) {
2171 WMA_LOGE("%s: Memory is not allocated to hold bcn template",
2172 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302173 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002174 }
2175
2176 len = *(u32 *) &bcn_info->beacon[0];
2177 if (len > WMA_BCN_BUF_MAX_SIZE) {
2178 WMA_LOGE("%s: Received beacon len %d exceeding max limit %d",
2179 __func__, len, WMA_BCN_BUF_MAX_SIZE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302180 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002181 }
2182 WMA_LOGD("%s: Storing received beacon template buf to local buffer",
2183 __func__);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302184 qdf_spin_lock_bh(&bcn->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002185
2186 /*
2187 * Copy received beacon template content in local buffer.
2188 * this will be send to target on the reception of SWBA
2189 * event from target.
2190 */
Nirav Shahcbc6d722016-03-01 16:24:53 +05302191 qdf_nbuf_trim_tail(bcn->buf, qdf_nbuf_len(bcn->buf));
2192 memcpy(qdf_nbuf_data(bcn->buf),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002193 bcn_info->beacon + 4 /* Exclude beacon length field */,
2194 len);
2195 if (bcn_info->timIeOffset > 3) {
2196 bcn->tim_ie_offset = bcn_info->timIeOffset - 4;
2197 } else {
2198 bcn->tim_ie_offset = bcn_info->timIeOffset;
2199 }
2200
2201 if (bcn_info->p2pIeOffset > 3) {
2202 bcn->p2p_ie_offset = bcn_info->p2pIeOffset - 4;
2203 } else {
2204 bcn->p2p_ie_offset = bcn_info->p2pIeOffset;
2205 }
Nirav Shahcbc6d722016-03-01 16:24:53 +05302206 bcn_payload = qdf_nbuf_data(bcn->buf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002207 if (bcn->tim_ie_offset) {
2208 tim_ie =
2209 (struct beacon_tim_ie *)(&bcn_payload[bcn->tim_ie_offset]);
2210 /*
2211 * Intial Value of bcn->dtim_count will be 0.
2212 * But if the beacon gets updated then current dtim
2213 * count will be restored
2214 */
2215 tim_ie->dtim_count = bcn->dtim_count;
2216 tim_ie->tim_bitctl = 0;
2217 }
2218
Nirav Shahcbc6d722016-03-01 16:24:53 +05302219 qdf_nbuf_put_tail(bcn->buf, len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002220 bcn->len = len;
2221
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302222 qdf_spin_unlock_bh(&bcn->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002223
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302224 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002225}
2226
2227/**
2228 * wma_tbttoffset_update_event_handler() - tbtt offset update handler
2229 * @handle: wma handle
2230 * @event: event buffer
2231 * @len: data length
2232 *
2233 * Return: 0 for success or error code
2234 */
2235int wma_tbttoffset_update_event_handler(void *handle, uint8_t *event,
2236 uint32_t len)
2237{
2238 tp_wma_handle wma = (tp_wma_handle) handle;
2239 WMI_TBTTOFFSET_UPDATE_EVENTID_param_tlvs *param_buf;
2240 wmi_tbtt_offset_event_fixed_param *tbtt_offset_event;
2241 struct wma_txrx_node *intf;
2242 struct beacon_info *bcn;
2243 tSendbeaconParams bcn_info;
2244 uint32_t *adjusted_tsf = NULL;
2245 uint32_t if_id = 0, vdev_map;
2246
2247 if (!wma) {
2248 WMA_LOGE("Invalid wma handle");
2249 return -EINVAL;
2250 }
2251
2252 param_buf = (WMI_TBTTOFFSET_UPDATE_EVENTID_param_tlvs *) event;
2253 if (!param_buf) {
2254 WMA_LOGE("Invalid tbtt update event buffer");
2255 return -EINVAL;
2256 }
2257
2258 tbtt_offset_event = param_buf->fixed_param;
2259 intf = wma->interfaces;
2260 vdev_map = tbtt_offset_event->vdev_map;
2261 adjusted_tsf = param_buf->tbttoffset_list;
2262 if (!adjusted_tsf) {
2263 WMA_LOGE("%s: Invalid adjusted_tsf", __func__);
2264 return -EINVAL;
2265 }
2266
2267 for (; (vdev_map); vdev_map >>= 1, if_id++) {
2268 if (!(vdev_map & 0x1) || (!(intf[if_id].handle)))
2269 continue;
2270
2271 bcn = intf[if_id].beacon;
2272 if (!bcn) {
2273 WMA_LOGE("%s: Invalid beacon", __func__);
2274 return -EINVAL;
2275 }
2276 if (!bcn->buf) {
2277 WMA_LOGE("%s: Invalid beacon buffer", __func__);
2278 return -EINVAL;
2279 }
2280 /* Save the adjusted TSF */
2281 intf[if_id].tsfadjust = adjusted_tsf[if_id];
2282
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302283 qdf_spin_lock_bh(&bcn->lock);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302284 qdf_mem_zero(&bcn_info, sizeof(bcn_info));
Nirav Shahcbc6d722016-03-01 16:24:53 +05302285 bcn_info.beacon = qdf_nbuf_data(bcn->buf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002286 bcn_info.p2pIeOffset = bcn->p2p_ie_offset;
2287 bcn_info.beaconLength = bcn->len;
2288 bcn_info.timIeOffset = bcn->tim_ie_offset;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302289 qdf_spin_unlock_bh(&bcn->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002290
2291 /* Update beacon template in firmware */
Govind Singh61ad2622016-02-22 17:25:02 +05302292 wma_unified_bcn_tmpl_send(wma, if_id, &bcn_info, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002293 }
2294 return 0;
2295}
2296
2297/**
2298 * wma_p2p_go_set_beacon_ie() - set beacon IE for p2p go
2299 * @wma_handle: wma handle
2300 * @vdev_id: vdev id
2301 * @p2pIe: p2p IE
2302 *
2303 * Return: 0 for success or error code
2304 */
2305static int wma_p2p_go_set_beacon_ie(t_wma_handle *wma_handle,
2306 A_UINT32 vdev_id, uint8_t *p2pIe)
2307{
Himanshu Agarwal009f1572016-03-09 17:26:02 +05302308 if (!wma_handle) {
2309 WMA_LOGE("%s: wma handle is NULL", __func__);
2310 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002311 }
2312
Himanshu Agarwal009f1572016-03-09 17:26:02 +05302313 return wmi_unified_p2p_go_set_beacon_ie_cmd(wma_handle->wmi_handle,
2314 vdev_id, p2pIe);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002315}
2316
2317/**
2318 * wma_send_probe_rsp_tmpl() - send probe resp template
2319 * @wma: wma handle
2320 * @probe_rsp_info: probe response info
2321 *
2322 * This funciton sends probe response template to fw which
2323 * firmware will use in case of probe response offload.
2324 *
2325 * Return: none
2326 */
2327void wma_send_probe_rsp_tmpl(tp_wma_handle wma,
2328 tpSendProbeRespParams probe_rsp_info)
2329{
Leo Chang96464902016-10-28 11:10:54 -07002330 void *vdev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002331 uint8_t vdev_id;
2332 tpAniProbeRspStruct probe_rsp;
2333
2334 if (!probe_rsp_info) {
2335 WMA_LOGE(FL("probe_rsp_info is NULL"));
2336 return;
2337 }
2338
2339 probe_rsp = (tpAniProbeRspStruct) (probe_rsp_info->pProbeRespTemplate);
2340 if (!probe_rsp) {
2341 WMA_LOGE(FL("probe_rsp is NULL"));
2342 return;
2343 }
2344
2345 vdev = wma_find_vdev_by_addr(wma, probe_rsp->macHdr.sa, &vdev_id);
2346 if (!vdev) {
2347 WMA_LOGE(FL("failed to get vdev handle"));
2348 return;
2349 }
2350
2351 if (WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
2352 WMI_SERVICE_BEACON_OFFLOAD)) {
2353 WMA_LOGI("Beacon Offload Enabled Sending Unified command");
2354 if (wmi_unified_probe_rsp_tmpl_send(wma, vdev_id,
2355 probe_rsp_info) < 0) {
2356 WMA_LOGE(FL("wmi_unified_probe_rsp_tmpl_send Failed "));
2357 return;
2358 }
2359 }
2360}
2361
2362/**
2363 * wma_send_beacon() - send beacon template
2364 * @wma: wma handle
2365 * @bcn_info: beacon info
2366 *
2367 * This funciton store beacon template locally and
2368 * update keep alive parameters
2369 *
2370 * Return: none
2371 */
2372void wma_send_beacon(tp_wma_handle wma, tpSendbeaconParams bcn_info)
2373{
Leo Chang96464902016-10-28 11:10:54 -07002374 void *vdev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002375 uint8_t vdev_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302376 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002377 uint8_t *p2p_ie;
2378 tpAniBeaconStruct beacon;
Govind Singhd76a5b02016-03-08 15:12:14 +05302379 struct vdev_up_params param = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002380
2381 beacon = (tpAniBeaconStruct) (bcn_info->beacon);
2382 vdev = wma_find_vdev_by_addr(wma, beacon->macHdr.sa, &vdev_id);
2383 if (!vdev) {
2384 WMA_LOGE("%s : failed to get vdev handle", __func__);
2385 return;
2386 }
2387
2388 if (WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
2389 WMI_SERVICE_BEACON_OFFLOAD)) {
2390 WMA_LOGI("Beacon Offload Enabled Sending Unified command");
Govind Singh61ad2622016-02-22 17:25:02 +05302391 status = wma_unified_bcn_tmpl_send(wma, vdev_id, bcn_info, 4);
2392 if (QDF_IS_STATUS_ERROR(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002393 WMA_LOGE("%s : wmi_unified_bcn_tmpl_send Failed ",
2394 __func__);
2395 return;
2396 }
2397
2398 if (bcn_info->p2pIeOffset) {
2399 p2p_ie = bcn_info->beacon + bcn_info->p2pIeOffset;
2400 WMA_LOGI
2401 (" %s: p2pIe is present - vdev_id %hu, p2p_ie = %p, p2p ie len = %hu",
2402 __func__, vdev_id, p2p_ie, p2p_ie[1]);
2403 if (wma_p2p_go_set_beacon_ie(wma, vdev_id, p2p_ie) < 0) {
2404 WMA_LOGE
2405 ("%s : wmi_unified_bcn_tmpl_send Failed ",
2406 __func__);
2407 return;
2408 }
2409 }
2410 }
2411 status = wma_store_bcn_tmpl(wma, vdev_id, bcn_info);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302412 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002413 WMA_LOGE("%s : wma_store_bcn_tmpl Failed", __func__);
2414 return;
2415 }
Agrawal Ashish7dd7c592016-02-22 14:25:11 +05302416 if (!((qdf_atomic_read(
2417 &wma->interfaces[vdev_id].vdev_restart_params.
2418 hidden_ssid_restart_in_progress)) ||
2419 (wma->interfaces[vdev_id].is_channel_switch))) {
2420 if (!wma->interfaces[vdev_id].vdev_up) {
2421 param.vdev_id = vdev_id;
2422 param.assoc_id = 0;
2423 status = wmi_unified_vdev_up_send(wma->wmi_handle,
2424 bcn_info->bssId,
2425 &param);
2426 if (QDF_IS_STATUS_ERROR(status)) {
2427 WMA_LOGE(FL("failed to send vdev up"));
2428 cds_set_do_hw_mode_change_flag(false);
2429 return;
2430 }
2431 wma->interfaces[vdev_id].vdev_up = true;
2432 wma_set_sap_keepalive(wma, vdev_id);
2433
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002434 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002435 }
2436}
2437
2438/**
2439 * wma_set_keepalive_req() - send keep alive request to fw
2440 * @wma: wma handle
2441 * @keepalive: keep alive parameters
2442 *
2443 * Return: none
2444 */
2445void wma_set_keepalive_req(tp_wma_handle wma,
2446 tSirKeepAliveReq *keepalive)
2447{
2448 WMA_LOGD("KEEPALIVE:PacketType:%d", keepalive->packetType);
2449 wma_set_sta_keep_alive(wma, keepalive->sessionId,
2450 keepalive->packetType,
2451 keepalive->timePeriod,
2452 keepalive->hostIpv4Addr,
Srinivas Girigowda9c330a92015-11-24 12:28:25 -08002453 keepalive->destIpv4Addr,
2454 keepalive->dest_macaddr.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002455
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302456 qdf_mem_free(keepalive);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002457}
2458
2459/**
2460 * wma_beacon_miss_handler() - beacon miss event handler
2461 * @wma: wma handle
2462 * @vdev_id: vdev id
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05302463 * @riis: rssi value
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002464 *
2465 * This function send beacon miss indication to upper layers.
2466 *
2467 * Return: none
2468 */
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05302469void wma_beacon_miss_handler(tp_wma_handle wma, uint32_t vdev_id, int32_t rssi)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002470{
2471 tSirSmeMissedBeaconInd *beacon_miss_ind;
2472
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302473 beacon_miss_ind = (tSirSmeMissedBeaconInd *) qdf_mem_malloc
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002474 (sizeof(tSirSmeMissedBeaconInd));
2475
2476 if (NULL == beacon_miss_ind) {
2477 WMA_LOGE("%s: Memory allocation failure", __func__);
2478 return;
2479 }
2480 beacon_miss_ind->messageType = WMA_MISSED_BEACON_IND;
2481 beacon_miss_ind->length = sizeof(tSirSmeMissedBeaconInd);
2482 beacon_miss_ind->bssIdx = vdev_id;
2483
2484 wma_send_msg(wma, WMA_MISSED_BEACON_IND, (void *)beacon_miss_ind, 0);
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05302485 wma_lost_link_info_handler(wma, vdev_id, rssi +
2486 WMA_TGT_NOISE_FLOOR_DBM);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002487}
2488
2489/**
Nirav Shah20489972016-06-16 19:20:28 +05302490 * wma_process_mgmt_tx_completion() - process mgmt completion
2491 * @wma_handle: wma handle
2492 * @desc_id: descriptor id
2493 * @status: status
2494 *
2495 * Return: 0 for success or error code
2496 */
Jeff Johnsonc4b47a92016-10-07 12:34:41 -07002497static int wma_process_mgmt_tx_completion(tp_wma_handle wma_handle,
2498 uint32_t desc_id, uint32_t status)
Nirav Shah20489972016-06-16 19:20:28 +05302499{
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05302500 struct wlan_objmgr_psoc *psoc;
2501 qdf_nbuf_t buf = NULL;
2502 uint8_t vdev_id = 0;
2503 QDF_STATUS ret;
2504 struct wlan_lmac_if_mgmt_txrx_rx_ops *mgmt_txrx_rx_ops;
Leo Chang96464902016-10-28 11:10:54 -07002505
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05302506 if (wma_handle == NULL) {
2507 WMA_LOGE("%s: wma handle is NULL", __func__);
Nirav Shah20489972016-06-16 19:20:28 +05302508 return -EINVAL;
2509 }
2510
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05302511 WMA_LOGI("%s: status:%d desc id:%d", __func__, status, desc_id);
Nirav Shah20489972016-06-16 19:20:28 +05302512
Nirav Shah20489972016-06-16 19:20:28 +05302513
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05302514 psoc = wma_handle->psoc;
2515 if (psoc == NULL) {
2516 WMA_LOGE("%s: psoc ptr is NULL", __func__);
Nirav Shah20489972016-06-16 19:20:28 +05302517 return -EINVAL;
2518 }
2519
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05302520 mgmt_txrx_rx_ops = &psoc->soc_cb.rx_ops.mgmt_txrx_rx_ops;
2521
2522 if (mgmt_txrx_rx_ops->mgmt_txrx_get_nbuf_from_desc_id)
2523 buf = mgmt_txrx_rx_ops->mgmt_txrx_get_nbuf_from_desc_id(
2524 psoc, desc_id);
2525
2526 if (mgmt_txrx_rx_ops->mgmt_txrx_get_vdev_id_from_desc_id)
2527 vdev_id = mgmt_txrx_rx_ops->mgmt_txrx_get_vdev_id_from_desc_id(
2528 psoc, desc_id);
2529 if (buf)
2530 qdf_nbuf_unmap_single(wma_handle->qdf_dev, buf,
Nirav Shah20489972016-06-16 19:20:28 +05302531 QDF_DMA_TO_DEVICE);
Himanshu Agarwalf65bd4c2016-12-05 17:21:12 +05302532
2533 if (wma_handle->wma_mgmt_tx_packetdump_cb)
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05302534 wma_handle->wma_mgmt_tx_packetdump_cb(buf,
2535 QDF_STATUS_SUCCESS, vdev_id, TX_MGMT_PKT);
Himanshu Agarwalf65bd4c2016-12-05 17:21:12 +05302536
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05302537 if (!mgmt_txrx_rx_ops->mgmt_tx_completion_handler) {
2538 WMA_LOGE("%s: tx completion callback to mgmt txrx layer is NULL",
2539 __func__);
2540 return -EINVAL;
2541 }
2542 ret = mgmt_txrx_rx_ops->mgmt_tx_completion_handler(psoc, desc_id,
2543 status, NULL);
Nirav Shah20489972016-06-16 19:20:28 +05302544
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05302545 if (ret != QDF_STATUS_SUCCESS) {
2546 WMA_LOGE("%s: Failed to process mgmt tx completion", __func__);
2547 return -EINVAL;
2548 }
Nirav Shah20489972016-06-16 19:20:28 +05302549
Nirav Shah20489972016-06-16 19:20:28 +05302550 return 0;
2551}
2552
2553/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002554 * wma_mgmt_tx_completion_handler() - wma mgmt Tx completion event handler
2555 * @handle: wma handle
2556 * @cmpl_event_params: completion event handler data
2557 * @len: length of @cmpl_event_params
2558 *
2559 * Return: 0 on success; error number otherwise
2560 */
2561
2562int wma_mgmt_tx_completion_handler(void *handle, uint8_t *cmpl_event_params,
2563 uint32_t len)
2564{
2565 tp_wma_handle wma_handle = (tp_wma_handle)handle;
2566 WMI_MGMT_TX_COMPLETION_EVENTID_param_tlvs *param_buf;
2567 wmi_mgmt_tx_compl_event_fixed_param *cmpl_params;
Naveen Rawat35804772016-06-27 15:40:28 -07002568
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002569 param_buf = (WMI_MGMT_TX_COMPLETION_EVENTID_param_tlvs *)
2570 cmpl_event_params;
Naveen Rawat35804772016-06-27 15:40:28 -07002571 if (!param_buf || !wma_handle) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002572 WMA_LOGE("%s: Invalid mgmt Tx completion event", __func__);
2573 return -EINVAL;
2574 }
2575 cmpl_params = param_buf->fixed_param;
2576
Nirav Shah20489972016-06-16 19:20:28 +05302577 wma_process_mgmt_tx_completion(wma_handle,
2578 cmpl_params->desc_id, cmpl_params->status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002579
Nirav Shah20489972016-06-16 19:20:28 +05302580 return 0;
2581}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002582
Nirav Shah20489972016-06-16 19:20:28 +05302583/**
2584 * wma_mgmt_tx_bundle_completion_handler() - mgmt bundle comp handler
2585 * @handle: wma handle
2586 * @buf: buffer
2587 * @len: length
2588 *
2589 * Return: 0 for success or error code
2590 */
2591int wma_mgmt_tx_bundle_completion_handler(void *handle, uint8_t *buf,
2592 uint32_t len)
2593{
2594 tp_wma_handle wma_handle = (tp_wma_handle)handle;
2595 WMI_MGMT_TX_BUNDLE_COMPLETION_EVENTID_param_tlvs *param_buf;
2596 wmi_mgmt_tx_compl_bundle_event_fixed_param *cmpl_params;
2597 uint32_t num_reports;
2598 uint32_t *desc_ids;
2599 uint32_t *status;
2600 int i;
2601
2602 param_buf = (WMI_MGMT_TX_BUNDLE_COMPLETION_EVENTID_param_tlvs *)buf;
Arif Hussain31576d92016-10-25 14:32:12 -07002603 if (!param_buf || !wma_handle) {
Nirav Shah20489972016-06-16 19:20:28 +05302604 WMA_LOGE("%s: Invalid mgmt Tx completion event", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002605 return -EINVAL;
2606 }
Nirav Shah20489972016-06-16 19:20:28 +05302607 cmpl_params = param_buf->fixed_param;
2608 num_reports = cmpl_params->num_reports;
2609 desc_ids = (uint32_t *)(param_buf->desc_ids);
2610 status = (uint32_t *)(param_buf->status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002611
Nirav Shah20489972016-06-16 19:20:28 +05302612 for (i = 0; i < num_reports; i++)
2613 wma_process_mgmt_tx_completion(wma_handle,
2614 desc_ids[i], status[i]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002615 return 0;
2616}
2617
2618/**
2619 * wma_process_update_opmode() - process update VHT opmode cmd from UMAC
2620 * @wma_handle: wma handle
2621 * @update_vht_opmode: vht opmode
2622 *
2623 * Return: none
2624 */
2625void wma_process_update_opmode(tp_wma_handle wma_handle,
2626 tUpdateVHTOpMode *update_vht_opmode)
2627{
2628 WMA_LOGD("%s: opMode = %d", __func__, update_vht_opmode->opMode);
2629
2630 wma_set_peer_param(wma_handle, update_vht_opmode->peer_mac,
2631 WMI_PEER_CHWIDTH, update_vht_opmode->opMode,
2632 update_vht_opmode->smesessionId);
2633}
2634
2635/**
2636 * wma_process_update_rx_nss() - process update RX NSS cmd from UMAC
2637 * @wma_handle: wma handle
2638 * @update_rx_nss: rx nss value
2639 *
2640 * Return: none
2641 */
2642void wma_process_update_rx_nss(tp_wma_handle wma_handle,
2643 tUpdateRxNss *update_rx_nss)
2644{
2645 struct wma_txrx_node *intr =
2646 &wma_handle->interfaces[update_rx_nss->smesessionId];
2647 int rx_nss = update_rx_nss->rxNss;
2648
2649 wma_update_txrx_chainmask(wma_handle->num_rf_chains, &rx_nss);
2650
2651 intr->nss = (uint8_t)rx_nss;
2652 update_rx_nss->rxNss = (uint32_t)rx_nss;
2653
2654 WMA_LOGD("%s: Rx Nss = %d", __func__, update_rx_nss->rxNss);
2655
2656 wma_set_peer_param(wma_handle, update_rx_nss->peer_mac,
2657 WMI_PEER_NSS, update_rx_nss->rxNss,
2658 update_rx_nss->smesessionId);
2659}
2660
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002661/**
2662 * wma_process_update_membership() - process update group membership cmd
2663 * @wma_handle: wma handle
2664 * @membership: group membership info
2665 *
2666 * Return: none
2667 */
2668void wma_process_update_membership(tp_wma_handle wma_handle,
2669 tUpdateMembership *membership)
2670{
2671 WMA_LOGD("%s: membership = %x ", __func__, membership->membership);
2672
2673 wma_set_peer_param(wma_handle, membership->peer_mac,
2674 WMI_PEER_MEMBERSHIP, membership->membership,
2675 membership->smesessionId);
2676}
2677
2678/**
2679 * wma_process_update_userpos() - process update user pos cmd from UMAC
2680 * @wma_handle: wma handle
2681 * @userpos: user pos value
2682 *
2683 * Return: none
2684 */
2685void wma_process_update_userpos(tp_wma_handle wma_handle,
2686 tUpdateUserPos *userpos)
2687{
2688 WMA_LOGD("%s: userPos = %x ", __func__, userpos->userPos);
2689
2690 wma_set_peer_param(wma_handle, userpos->peer_mac,
2691 WMI_PEER_USERPOS, userpos->userPos,
2692 userpos->smesessionId);
2693
2694 /* Now that membership/userpos is updated in fw,
2695 * enable GID PPS.
2696 */
2697 wma_set_ppsconfig(userpos->smesessionId, WMA_VHT_PPS_GID_MATCH, 1);
2698
2699}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002700
Agrawal Ashishb2d1a452016-05-05 12:23:58 +05302701QDF_STATUS wma_set_cts2self_for_p2p_go(void *wma_handle,
2702 uint32_t cts2self_for_p2p_go)
2703{
2704 int32_t ret;
2705 tp_wma_handle wma = (tp_wma_handle)wma_handle;
2706 struct pdev_params pdevparam;
2707
2708 pdevparam.param_id = WMI_PDEV_PARAM_CTS2SELF_FOR_P2P_GO_CONFIG;
2709 pdevparam.param_value = cts2self_for_p2p_go;
2710
2711 ret = wmi_unified_pdev_param_send(wma->wmi_handle,
2712 &pdevparam,
2713 WMA_WILDCARD_PDEV_ID);
2714 if (ret) {
2715 WMA_LOGE("Fail to Set CTS2SELF for p2p GO %d",
2716 cts2self_for_p2p_go);
2717 return QDF_STATUS_E_FAILURE;
2718 }
2719
2720 WMA_LOGD("Successfully Set CTS2SELF for p2p GO %d",
2721 cts2self_for_p2p_go);
2722
2723 return QDF_STATUS_SUCCESS;
2724}
2725
2726
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002727/**
2728 * wma_set_htconfig() - set ht config parameters to target
2729 * @vdev_id: vdev id
2730 * @ht_capab: ht capablity
2731 * @value: value of ht param
2732 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302733 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002734 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302735QDF_STATUS wma_set_htconfig(uint8_t vdev_id, uint16_t ht_capab, int value)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002736{
Anurag Chouhan6d760662016-02-20 16:05:43 +05302737 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
Govind Singhd76a5b02016-03-08 15:12:14 +05302738 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002739
2740 if (NULL == wma) {
2741 WMA_LOGE("%s: Failed to get wma", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302742 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002743 }
2744
2745 switch (ht_capab) {
2746 case WNI_CFG_HT_CAP_INFO_ADVANCE_CODING:
Govind Singhd76a5b02016-03-08 15:12:14 +05302747 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002748 WMI_VDEV_PARAM_LDPC,
2749 value);
2750 break;
2751 case WNI_CFG_HT_CAP_INFO_TX_STBC:
Govind Singhd76a5b02016-03-08 15:12:14 +05302752 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002753 WMI_VDEV_PARAM_TX_STBC,
2754 value);
2755 break;
2756 case WNI_CFG_HT_CAP_INFO_RX_STBC:
Govind Singhd76a5b02016-03-08 15:12:14 +05302757 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002758 WMI_VDEV_PARAM_RX_STBC,
2759 value);
2760 break;
2761 case WNI_CFG_HT_CAP_INFO_SHORT_GI_20MHZ:
2762 case WNI_CFG_HT_CAP_INFO_SHORT_GI_40MHZ:
2763 WMA_LOGE("%s: ht_capab = %d, value = %d", __func__, ht_capab,
2764 value);
Govind Singhd76a5b02016-03-08 15:12:14 +05302765 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002766 WMI_VDEV_PARAM_SGI, value);
Govind Singhd76a5b02016-03-08 15:12:14 +05302767 if (ret == QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002768 wma->interfaces[vdev_id].config.shortgi = value;
2769 break;
2770 default:
2771 WMA_LOGE("%s:INVALID HT CONFIG", __func__);
2772 }
2773
Govind Singhd76a5b02016-03-08 15:12:14 +05302774 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002775}
2776
2777/**
2778 * wma_hidden_ssid_vdev_restart() - vdev restart for hidden ssid
2779 * @wma_handle: wma handle
2780 * @pReq: hidden ssid vdev restart request
2781 *
2782 * Return: none
2783 */
2784void wma_hidden_ssid_vdev_restart(tp_wma_handle wma_handle,
2785 tHalHiddenSsidVdevRestart *pReq)
2786{
2787 struct wma_txrx_node *intr = wma_handle->interfaces;
Selvaraj, Sridhara0083c42016-06-22 22:15:43 +05302788 struct wma_target_req *msg;
Leo Chang96464902016-10-28 11:10:54 -07002789 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002790
2791 if ((pReq->sessionId !=
2792 intr[pReq->sessionId].vdev_restart_params.vdev_id)
2793 || !((intr[pReq->sessionId].type == WMI_VDEV_TYPE_AP)
2794 && (intr[pReq->sessionId].sub_type == 0))) {
2795 WMA_LOGE("%s : invalid session id", __func__);
2796 return;
2797 }
2798
2799 intr[pReq->sessionId].vdev_restart_params.ssidHidden = pReq->ssidHidden;
Anurag Chouhan8e0ccd32016-02-19 15:30:20 +05302800 qdf_atomic_set(&intr[pReq->sessionId].vdev_restart_params.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002801 hidden_ssid_restart_in_progress, 1);
2802
Selvaraj, Sridhara0083c42016-06-22 22:15:43 +05302803 msg = wma_fill_vdev_req(wma_handle, pReq->sessionId,
2804 WMA_HIDDEN_SSID_VDEV_RESTART,
2805 WMA_TARGET_REQ_TYPE_VDEV_STOP, pReq,
2806 WMA_VDEV_STOP_REQUEST_TIMEOUT);
2807 if (!msg) {
2808 WMA_LOGE("%s: Failed to fill vdev restart request for vdev_id %d",
2809 __func__, pReq->sessionId);
2810 return;
2811 }
2812
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002813 /* vdev stop -> vdev restart -> vdev up */
2814 WMA_LOGD("%s, vdev_id: %d, pausing tx_ll_queue for VDEV_STOP",
2815 __func__, pReq->sessionId);
Leo Chang96464902016-10-28 11:10:54 -07002816 cdp_fc_vdev_pause(soc, wma_handle->interfaces[pReq->sessionId].handle,
2817 OL_TXQ_PAUSE_REASON_VDEV_STOP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002818 wma_handle->interfaces[pReq->sessionId].pause_bitmap |=
2819 (1 << PAUSE_TYPE_HOST);
2820 if (wmi_unified_vdev_stop_send(wma_handle->wmi_handle, pReq->sessionId)) {
2821 WMA_LOGE("%s: %d Failed to send vdev stop", __func__, __LINE__);
Anurag Chouhan8e0ccd32016-02-19 15:30:20 +05302822 qdf_atomic_set(&intr[pReq->sessionId].vdev_restart_params.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002823 hidden_ssid_restart_in_progress, 0);
Selvaraj, Sridhara0083c42016-06-22 22:15:43 +05302824 wma_remove_vdev_req(wma_handle, pReq->sessionId,
2825 WMA_TARGET_REQ_TYPE_VDEV_STOP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002826 return;
2827 }
2828}
2829
2830
2831#ifdef WLAN_FEATURE_11W
2832
2833/**
2834 * wma_extract_ccmp_pn() - extract 6 byte PN from the CCMP header
2835 * @ccmp_ptr: CCMP header
2836 *
2837 * Return: PN extracted from header.
2838 */
2839static uint64_t wma_extract_ccmp_pn(uint8_t *ccmp_ptr)
2840{
2841 uint8_t rsvd, key, pn[6];
2842 uint64_t new_pn;
2843
2844 /*
2845 * +-----+-----+------+----------+-----+-----+-----+-----+
2846 * | PN0 | PN1 | rsvd | rsvd/key | PN2 | PN3 | PN4 | PN5 |
2847 * +-----+-----+------+----------+-----+-----+-----+-----+
2848 * CCMP Header Format
2849 */
2850
2851 /* Extract individual bytes */
2852 pn[0] = (uint8_t) *ccmp_ptr;
2853 pn[1] = (uint8_t) *(ccmp_ptr + 1);
2854 rsvd = (uint8_t) *(ccmp_ptr + 2);
2855 key = (uint8_t) *(ccmp_ptr + 3);
2856 pn[2] = (uint8_t) *(ccmp_ptr + 4);
2857 pn[3] = (uint8_t) *(ccmp_ptr + 5);
2858 pn[4] = (uint8_t) *(ccmp_ptr + 6);
2859 pn[5] = (uint8_t) *(ccmp_ptr + 7);
2860
2861 /* Form 6 byte PN with 6 individual bytes of PN */
2862 new_pn = ((uint64_t) pn[5] << 40) |
2863 ((uint64_t) pn[4] << 32) |
2864 ((uint64_t) pn[3] << 24) |
2865 ((uint64_t) pn[2] << 16) |
2866 ((uint64_t) pn[1] << 8) | ((uint64_t) pn[0] << 0);
2867
2868 WMA_LOGE("PN of received packet is %llu", new_pn);
2869 return new_pn;
2870}
2871
2872/**
2873 * wma_is_ccmp_pn_replay_attack() - detect replay attacking using PN in CCMP
2874 * @cds_ctx: cds context
2875 * @wh: 802.11 frame header
2876 * @ccmp_ptr: CCMP frame header
2877 *
2878 * Return: true/false
2879 */
2880static bool
2881wma_is_ccmp_pn_replay_attack(void *cds_ctx, struct ieee80211_frame *wh,
2882 uint8_t *ccmp_ptr)
2883{
Leo Chang96464902016-10-28 11:10:54 -07002884 void *pdev;
2885 void *vdev;
2886 void *peer;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002887 uint8_t vdev_id, peer_id;
2888 uint8_t *last_pn_valid;
2889 uint64_t *last_pn, new_pn;
2890 uint32_t *rmf_pn_replays;
Leo Chang96464902016-10-28 11:10:54 -07002891 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002892
Anurag Chouhan6d760662016-02-20 16:05:43 +05302893 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002894 if (!pdev) {
2895 WMA_LOGE("%s: Failed to find pdev", __func__);
2896 return true;
2897 }
2898
Mukul Sharmaa748fbb2015-12-01 19:51:36 +05302899 vdev = wma_find_vdev_by_bssid(cds_ctx, wh->i_addr3, &vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002900 if (!vdev) {
2901 WMA_LOGE("%s: Failed to find vdev", __func__);
2902 return true;
2903 }
2904
2905 /* Retrieve the peer based on vdev and addr */
Leo Chang96464902016-10-28 11:10:54 -07002906 peer = cdp_peer_find_by_addr_and_vdev(soc, pdev, vdev, wh->i_addr2,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002907 &peer_id);
2908
2909 if (NULL == peer) {
2910 WMA_LOGE("%s: Failed to find peer, Not able to validate PN",
2911 __func__);
2912 return true;
2913 }
2914
2915 new_pn = wma_extract_ccmp_pn(ccmp_ptr);
Leo Chang96464902016-10-28 11:10:54 -07002916 cdp_get_pn_info(soc, peer, &last_pn_valid, &last_pn, &rmf_pn_replays);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002917
2918 if (*last_pn_valid) {
2919 if (new_pn > *last_pn) {
2920 *last_pn = new_pn;
2921 WMA_LOGE("%s: PN validation successful", __func__);
2922 } else {
2923 WMA_LOGE("%s: PN Replay attack detected", __func__);
2924 /* per 11W amendment, keeping track of replay attacks */
2925 *rmf_pn_replays += 1;
2926 return true;
2927 }
2928 } else {
2929 *last_pn_valid = 1;
2930 *last_pn = new_pn;
2931 }
2932
2933 return false;
2934}
2935
2936/**
mukul sharma72c8b222015-09-04 17:02:01 +05302937 * wma_process_bip() - process mmie in rmf frame
2938 * @wma_handle: wma handle
2939 * @iface: txrx node
2940 * @wh: 80211 frame
2941 * @wbuf: Buffer
2942 *
2943 * Return: 0 for success or error code
2944 */
2945
2946static
2947int wma_process_bip(tp_wma_handle wma_handle,
2948 struct wma_txrx_node *iface,
2949 struct ieee80211_frame *wh,
Nirav Shahcbc6d722016-03-01 16:24:53 +05302950 qdf_nbuf_t wbuf
mukul sharma72c8b222015-09-04 17:02:01 +05302951)
2952{
2953 uint16_t key_id;
2954 uint8_t *efrm;
2955
Nirav Shahcbc6d722016-03-01 16:24:53 +05302956 efrm = qdf_nbuf_data(wbuf) + qdf_nbuf_len(wbuf);
mukul sharma72c8b222015-09-04 17:02:01 +05302957 key_id = (uint16_t)*(efrm - cds_get_mmie_size() + 2);
2958
2959 if (!((key_id == WMA_IGTK_KEY_INDEX_4)
2960 || (key_id == WMA_IGTK_KEY_INDEX_5))) {
2961 WMA_LOGE(FL("Invalid KeyID(%d) dropping the frame"), key_id);
2962 return -EINVAL;
2963 }
2964 if (WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap,
2965 WMI_SERVICE_STA_PMF_OFFLOAD)) {
2966 /*
2967 * if 11w offload is enabled then mmie validation is performed
2968 * in firmware, host just need to trim the mmie.
2969 */
Nirav Shahcbc6d722016-03-01 16:24:53 +05302970 qdf_nbuf_trim_tail(wbuf, cds_get_mmie_size());
mukul sharma72c8b222015-09-04 17:02:01 +05302971 } else {
2972 if (cds_is_mmie_valid(iface->key.key,
2973 iface->key.key_id[key_id - WMA_IGTK_KEY_INDEX_4].ipn,
2974 (uint8_t *) wh, efrm)) {
2975 WMA_LOGE(FL("Protected BC/MC frame MMIE validation successful"));
2976 /* Remove MMIE */
Nirav Shahcbc6d722016-03-01 16:24:53 +05302977 qdf_nbuf_trim_tail(wbuf, cds_get_mmie_size());
mukul sharma72c8b222015-09-04 17:02:01 +05302978 } else {
2979 WMA_LOGE(FL("BC/MC MIC error or MMIE not present, dropping the frame"));
2980 return -EINVAL;
2981 }
2982 }
2983 return 0;
2984}
2985
2986/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002987 * wma_process_rmf_frame() - process rmf frame
2988 * @wma_handle: wma handle
2989 * @iface: txrx node
2990 * @wh: 80211 frame
2991 * @rx_pkt: rx packet
2992 * @wbuf: Buffer
2993 *
2994 * Return: 0 for success or error code
2995 */
2996static
2997int wma_process_rmf_frame(tp_wma_handle wma_handle,
2998 struct wma_txrx_node *iface,
2999 struct ieee80211_frame *wh,
3000 cds_pkt_t *rx_pkt,
Nirav Shahcbc6d722016-03-01 16:24:53 +05303001 qdf_nbuf_t wbuf)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003002{
mukul sharma72c8b222015-09-04 17:02:01 +05303003 uint8_t *orig_hdr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003004 uint8_t *ccmp;
3005
3006 if ((wh)->i_fc[1] & IEEE80211_FC1_WEP) {
3007 if (IEEE80211_IS_BROADCAST(wh->i_addr1) ||
3008 IEEE80211_IS_MULTICAST(wh->i_addr1)) {
3009 WMA_LOGE("Encrypted BC/MC frame dropping the frame");
3010 cds_pkt_return_packet(rx_pkt);
3011 return -EINVAL;
3012 }
3013
Nirav Shahcbc6d722016-03-01 16:24:53 +05303014 orig_hdr = (uint8_t *) qdf_nbuf_data(wbuf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003015 /* Pointer to head of CCMP header */
3016 ccmp = orig_hdr + sizeof(*wh);
3017 if (wma_is_ccmp_pn_replay_attack(
3018 wma_handle, wh, ccmp)) {
3019 WMA_LOGE("Dropping the frame");
3020 cds_pkt_return_packet(rx_pkt);
3021 return -EINVAL;
3022 }
3023
3024 /* Strip privacy headers (and trailer)
3025 * for a received frame
3026 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303027 qdf_mem_move(orig_hdr +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003028 IEEE80211_CCMP_HEADERLEN, wh,
3029 sizeof(*wh));
Nirav Shahcbc6d722016-03-01 16:24:53 +05303030 qdf_nbuf_pull_head(wbuf,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003031 IEEE80211_CCMP_HEADERLEN);
Krunal Soni54da0c62016-08-01 17:04:25 -07003032 qdf_nbuf_trim_tail(wbuf, IEEE80211_CCMP_MICLEN);
3033 /*
3034 * CCMP header has been pulled off
3035 * reinitialize the start pointer of mac header
3036 * to avoid accessing incorrect address
3037 */
3038 wh = (struct ieee80211_frame *) qdf_nbuf_data(wbuf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003039 rx_pkt->pkt_meta.mpdu_hdr_ptr =
Nirav Shahcbc6d722016-03-01 16:24:53 +05303040 qdf_nbuf_data(wbuf);
3041 rx_pkt->pkt_meta.mpdu_len = qdf_nbuf_len(wbuf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003042 rx_pkt->pkt_meta.mpdu_data_len =
3043 rx_pkt->pkt_meta.mpdu_len -
3044 rx_pkt->pkt_meta.mpdu_hdr_len;
3045 rx_pkt->pkt_meta.mpdu_data_ptr =
3046 rx_pkt->pkt_meta.mpdu_hdr_ptr +
3047 rx_pkt->pkt_meta.mpdu_hdr_len;
3048 rx_pkt->pkt_meta.tsf_delta = rx_pkt->pkt_meta.tsf_delta;
3049 rx_pkt->pkt_buf = wbuf;
3050 WMA_LOGD(FL("BSSID: "MAC_ADDRESS_STR" tsf_delta: %u"),
3051 MAC_ADDR_ARRAY(wh->i_addr3), rx_pkt->pkt_meta.tsf_delta);
3052 } else {
3053 if (IEEE80211_IS_BROADCAST(wh->i_addr1) ||
3054 IEEE80211_IS_MULTICAST(wh->i_addr1)) {
mukul sharma72c8b222015-09-04 17:02:01 +05303055 if (0 != wma_process_bip(wma_handle, iface, wh, wbuf)) {
3056 cds_pkt_return_packet(rx_pkt);
3057 return -EINVAL;
Mukul Sharmaa748fbb2015-12-01 19:51:36 +05303058 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003059 } else {
3060 WMA_LOGE("Rx unprotected unicast mgmt frame");
3061 rx_pkt->pkt_meta.dpuFeedback =
3062 DPU_FEEDBACK_UNPROTECTED_ERROR;
3063 }
3064 }
3065 return 0;
3066}
3067#endif
3068
3069/**
Krishna Kumaar Natarajanb7f9a352016-03-18 11:40:07 -07003070 * wma_is_pkt_drop_candidate() - check if the mgmt frame should be droppped
3071 * @wma_handle: wma handle
3072 * @peer_addr: peer MAC address
3073 * @subtype: Management frame subtype
3074 *
3075 * This function is used to decide if a particular management frame should be
3076 * dropped to prevent DOS attack. Timestamp is used to decide the DOS attack.
3077 *
3078 * Return: true if the packet should be dropped and false oterwise
3079 */
3080static bool wma_is_pkt_drop_candidate(tp_wma_handle wma_handle,
3081 uint8_t *peer_addr, uint8_t subtype)
3082{
Leo Chang96464902016-10-28 11:10:54 -07003083 void *peer;
3084 void *pdev_ctx;
Krishna Kumaar Natarajanb7f9a352016-03-18 11:40:07 -07003085 uint8_t peer_id;
3086 bool should_drop = false;
Nishank Aggarwal21282ec2016-12-01 17:41:33 +05303087 qdf_time_t *ptr;
Leo Chang96464902016-10-28 11:10:54 -07003088 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Krishna Kumaar Natarajanb7f9a352016-03-18 11:40:07 -07003089
3090 /*
3091 * Currently this function handles only Disassoc,
3092 * Deauth and Assoc req frames. Return false for
3093 * all other frames.
3094 */
3095 if (subtype != IEEE80211_FC0_SUBTYPE_DISASSOC &&
3096 subtype != IEEE80211_FC0_SUBTYPE_DEAUTH &&
3097 subtype != IEEE80211_FC0_SUBTYPE_ASSOC_REQ) {
3098 should_drop = false;
3099 goto end;
3100 }
3101
3102 pdev_ctx = cds_get_context(QDF_MODULE_ID_TXRX);
3103 if (!pdev_ctx) {
3104 WMA_LOGE(FL("Failed to get the context"));
3105 should_drop = true;
3106 goto end;
3107 }
3108
Leo Chang96464902016-10-28 11:10:54 -07003109 peer = cdp_peer_find_by_addr(soc, pdev_ctx, peer_addr, &peer_id);
Krishna Kumaar Natarajanb7f9a352016-03-18 11:40:07 -07003110 if (!peer) {
3111 if (SIR_MAC_MGMT_ASSOC_REQ != subtype) {
3112 WMA_LOGI(
3113 FL("Received mgmt frame: %0x from unknow peer: %pM"),
3114 subtype, peer_addr);
3115 should_drop = true;
3116 }
3117 goto end;
3118 }
3119
3120 switch (subtype) {
3121 case SIR_MAC_MGMT_ASSOC_REQ:
Nishank Aggarwal21282ec2016-12-01 17:41:33 +05303122 ptr = cdp_peer_last_assoc_received(soc, peer);
3123 if (ptr == NULL) {
3124 WMA_LOGE(FL("cdp_peer_last_assoc_received Failed"));
3125 should_drop = true;
3126 goto end;
3127 } else {
Leo Chang96464902016-10-28 11:10:54 -07003128 if ((qdf_get_system_timestamp() -
3129 *cdp_peer_last_assoc_received(soc, peer)) <
Krishna Kumaar Natarajanb7f9a352016-03-18 11:40:07 -07003130 WMA_MGMT_FRAME_DETECT_DOS_TIMER) {
3131 WMA_LOGI(FL("Dropping Assoc Req received"));
3132 should_drop = true;
3133 }
3134 }
Leo Chang96464902016-10-28 11:10:54 -07003135 *cdp_peer_last_assoc_received(soc, peer) =
3136 qdf_get_system_timestamp();
Krishna Kumaar Natarajanb7f9a352016-03-18 11:40:07 -07003137 break;
3138 case SIR_MAC_MGMT_DISASSOC:
Leo Chang96464902016-10-28 11:10:54 -07003139 if (*cdp_peer_last_disassoc_received(soc, peer)) {
3140 if ((qdf_get_system_timestamp() -
3141 *cdp_peer_last_disassoc_received(soc, peer)) <
Krishna Kumaar Natarajanb7f9a352016-03-18 11:40:07 -07003142 WMA_MGMT_FRAME_DETECT_DOS_TIMER) {
3143 WMA_LOGI(FL("Dropping DisAssoc received"));
3144 should_drop = true;
3145 }
3146 }
Leo Chang96464902016-10-28 11:10:54 -07003147 *cdp_peer_last_disassoc_received(soc, peer) =
3148 qdf_get_system_timestamp();
Krishna Kumaar Natarajanb7f9a352016-03-18 11:40:07 -07003149 break;
3150 case SIR_MAC_MGMT_DEAUTH:
Leo Chang96464902016-10-28 11:10:54 -07003151 if (*cdp_peer_last_deauth_received(soc, peer)) {
3152 if ((qdf_get_system_timestamp() -
3153 *cdp_peer_last_deauth_received(soc, peer)) <
Krishna Kumaar Natarajanb7f9a352016-03-18 11:40:07 -07003154 WMA_MGMT_FRAME_DETECT_DOS_TIMER) {
3155 WMA_LOGI(FL("Dropping Deauth received"));
3156 should_drop = true;
3157 }
3158 }
Leo Chang96464902016-10-28 11:10:54 -07003159 *cdp_peer_last_deauth_received(soc, peer) =
3160 qdf_get_system_timestamp();
Krishna Kumaar Natarajanb7f9a352016-03-18 11:40:07 -07003161 break;
3162 default:
3163 break;
3164 }
3165
3166end:
3167 return should_drop;
3168}
3169
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303170int wma_form_rx_packet(qdf_nbuf_t buf,
3171 void *params,
3172 cds_pkt_t *rx_pkt)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003173{
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303174 wmi_host_mgmt_rx_hdr *mgmt_rx_params =
3175 (wmi_host_mgmt_rx_hdr *)params;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003176 struct wma_txrx_node *iface = NULL;
Mukul Sharmaa748fbb2015-12-01 19:51:36 +05303177 uint8_t vdev_id = WMA_INVALID_VDEV_ID;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003178 struct ieee80211_frame *wh;
3179 uint8_t mgt_type, mgt_subtype;
3180 int status;
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303181 tp_wma_handle wma_handle = (tp_wma_handle)
3182 cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003183
3184 if (!wma_handle) {
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303185 WMA_LOGE(FL("wma handle is NULL"));
3186 qdf_nbuf_free(buf);
3187 qdf_mem_free(rx_pkt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003188 return -EINVAL;
3189 }
3190
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303191 if (!mgmt_rx_params) {
3192 WMA_LOGE(FL("mgmt rx params is NULL"));
3193 qdf_nbuf_free(buf);
3194 qdf_mem_free(rx_pkt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003195 return -EINVAL;
3196 }
3197
Rajeev Kumarfec3dbe2016-01-19 15:23:52 -08003198 if (cds_is_load_or_unload_in_progress()) {
Krishna Kumaar Natarajan93c9de12016-06-16 17:04:30 -07003199 WMA_LOGW(FL("Load/Unload in progress"));
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303200 qdf_nbuf_free(buf);
3201 qdf_mem_free(rx_pkt);
Naveen Rawat10ccf872015-11-03 14:15:55 -08003202 return -EINVAL;
3203 }
3204
Mukul Sharma80edc782016-09-12 15:59:24 +05303205 if (cds_is_driver_recovering()) {
3206 WMA_LOGW(FL("Recovery in progress"));
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303207 qdf_nbuf_free(buf);
3208 qdf_mem_free(rx_pkt);
Mukul Sharma80edc782016-09-12 15:59:24 +05303209 return -EINVAL;
3210 }
3211
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003212 /*
3213 * Fill in meta information needed by pe/lim
3214 * TODO: Try to maintain rx metainfo as part of skb->data.
3215 */
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303216 rx_pkt->pkt_meta.channel = mgmt_rx_params->channel;
3217 rx_pkt->pkt_meta.scan_src = mgmt_rx_params->flags;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -07003218
3219 /*
3220 * Get the rssi value from the current snr value
3221 * using standard noise floor of -96.
3222 */
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303223 rx_pkt->pkt_meta.rssi = mgmt_rx_params->snr +
3224 WMA_NOISE_FLOOR_DBM_DEFAULT;
3225 rx_pkt->pkt_meta.snr = mgmt_rx_params->snr;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -07003226
3227 /* If absolute rssi is available from firmware, use it */
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303228 if (mgmt_rx_params->rssi != 0)
3229 rx_pkt->pkt_meta.rssi_raw = mgmt_rx_params->rssi;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -07003230 else
3231 rx_pkt->pkt_meta.rssi_raw = rx_pkt->pkt_meta.rssi;
3232
3233
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003234 /*
3235 * FIXME: Assigning the local timestamp as hw timestamp is not
3236 * available. Need to see if pe/lim really uses this data.
3237 */
3238 rx_pkt->pkt_meta.timestamp = (uint32_t) jiffies;
3239 rx_pkt->pkt_meta.mpdu_hdr_len = sizeof(struct ieee80211_frame);
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303240 rx_pkt->pkt_meta.mpdu_len = mgmt_rx_params->buf_len;
3241 rx_pkt->pkt_meta.mpdu_data_len = mgmt_rx_params->buf_len -
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003242 rx_pkt->pkt_meta.mpdu_hdr_len;
3243
3244 rx_pkt->pkt_meta.roamCandidateInd = 0;
3245
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303246 wh = (struct ieee80211_frame *)qdf_nbuf_data(buf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003247
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303248 rx_pkt->pkt_meta.mpdu_hdr_ptr = qdf_nbuf_data(buf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003249 rx_pkt->pkt_meta.mpdu_data_ptr = rx_pkt->pkt_meta.mpdu_hdr_ptr +
3250 rx_pkt->pkt_meta.mpdu_hdr_len;
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303251 rx_pkt->pkt_meta.tsf_delta = mgmt_rx_params->tsf_delta;
3252 rx_pkt->pkt_buf = buf;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003253
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -07003254 WMA_LOGD(
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303255 FL("BSSID: "MAC_ADDRESS_STR" snr = %d, rssi = %d, rssi_raw = %d tsf_delta: %u"),
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -07003256 MAC_ADDR_ARRAY(wh->i_addr3),
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303257 mgmt_rx_params->snr, rx_pkt->pkt_meta.rssi,
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303258 rx_pkt->pkt_meta.rssi_raw,
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303259 mgmt_rx_params->tsf_delta);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003260
3261 /* If it is a beacon/probe response, save it for future use */
3262 mgt_type = (wh)->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
3263 mgt_subtype = (wh)->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
3264
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003265#ifdef WLAN_FEATURE_11W
3266 if (mgt_type == IEEE80211_FC0_TYPE_MGT &&
3267 (mgt_subtype == IEEE80211_FC0_SUBTYPE_DISASSOC ||
3268 mgt_subtype == IEEE80211_FC0_SUBTYPE_DEAUTH ||
3269 mgt_subtype == IEEE80211_FC0_SUBTYPE_ACTION)) {
Mukul Sharmaa748fbb2015-12-01 19:51:36 +05303270 if (wma_find_vdev_by_bssid(
3271 wma_handle, wh->i_addr3, &vdev_id)) {
3272 iface = &(wma_handle->interfaces[vdev_id]);
3273 if (iface->rmfEnabled) {
3274 status = wma_process_rmf_frame(wma_handle,
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303275 iface, wh, rx_pkt, buf);
3276 if (status != 0)
3277 return status;
Krunal Soni54da0c62016-08-01 17:04:25 -07003278 /*
3279 * CCMP header might have been pulled off
3280 * reinitialize the start pointer of mac header
3281 */
3282 wh = (struct ieee80211_frame *)
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303283 qdf_nbuf_data(buf);
Mukul Sharmaa748fbb2015-12-01 19:51:36 +05303284 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003285 }
3286 }
3287#endif /* WLAN_FEATURE_11W */
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303288
Mukul Sharmaa748fbb2015-12-01 19:51:36 +05303289 rx_pkt->pkt_meta.sessionId =
3290 (vdev_id == WMA_INVALID_VDEV_ID ? 0 : vdev_id);
Krishna Kumaar Natarajanb7f9a352016-03-18 11:40:07 -07003291
3292 if (wma_is_pkt_drop_candidate(wma_handle, wh->i_addr2, mgt_subtype)) {
3293 cds_pkt_return_packet(rx_pkt);
3294 return -EINVAL;
3295 }
3296
Himanshu Agarwalf65bd4c2016-12-05 17:21:12 +05303297 if ((mgt_type == IEEE80211_FC0_TYPE_MGT &&
3298 mgt_subtype != IEEE80211_FC0_SUBTYPE_BEACON) &&
3299 wma_handle->wma_mgmt_rx_packetdump_cb)
3300 wma_handle->wma_mgmt_rx_packetdump_cb(rx_pkt->pkt_buf,
3301 QDF_STATUS_SUCCESS, rx_pkt->pkt_meta.sessionId,
3302 RX_MGMT_PKT);
3303
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303304 return 0;
3305}
3306
3307/**
3308 * wma_mem_endianness_based_copy() - does memory copy from src to dst
3309 * @dst: destination address
3310 * @src: source address
3311 * @size: size to be copied
3312 *
3313 * This function copies the memory of size passed from source
3314 * address to destination address.
3315 *
3316 * Return: Nothing
3317 */
3318#ifdef BIG_ENDIAN_HOST
3319static void wma_mem_endianness_based_copy(
3320 uint8_t *dst, uint8_t *src, uint32_t size)
3321{
3322 /*
3323 * For big endian host, copy engine byte_swap is enabled
3324 * But the rx mgmt frame buffer content is in network byte order
3325 * Need to byte swap the mgmt frame buffer content - so when
3326 * copy engine does byte_swap - host gets buffer content in the
3327 * correct byte order.
3328 */
3329
3330 uint32_t i;
3331 uint32_t *destp, *srcp;
3332
3333 destp = (uint32_t *) dst;
3334 srcp = (uint32_t *) src;
3335 for (i = 0; i < (roundup(size, sizeof(uint32_t)) / 4); i++) {
3336 *destp = cpu_to_le32(*srcp);
3337 destp++;
3338 srcp++;
3339 }
3340}
3341#else
3342static void wma_mem_endianness_based_copy(
3343 uint8_t *dst, uint8_t *src, uint32_t size)
3344{
3345 qdf_mem_copy(dst, src, size);
3346}
3347#endif
3348
3349/**
3350 * wma_mgmt_rx_process() - process management rx frame.
3351 * @handle: wma handle
3352 * @data: rx data
3353 * @data_len: data length
3354 *
3355 * Return: 0 for success or error code
3356 */
3357static int wma_mgmt_rx_process(void *handle, uint8_t *data,
3358 uint32_t data_len)
3359{
3360 tp_wma_handle wma_handle = (tp_wma_handle) handle;
3361 wmi_host_mgmt_rx_hdr *mgmt_rx_params;
3362 struct wlan_objmgr_psoc *psoc;
3363 uint8_t *bufp;
3364 qdf_nbuf_t wbuf;
3365 QDF_STATUS status;
3366
3367 if (!wma_handle) {
3368 WMA_LOGE("%s: Failed to get WMA context", __func__);
3369 return -EINVAL;
3370 }
3371
3372 mgmt_rx_params = qdf_mem_malloc(sizeof(*mgmt_rx_params));
3373 if (!mgmt_rx_params) {
3374 WMA_LOGE("%s: memory allocation failed", __func__);
3375 return -ENOMEM;
3376 }
3377
3378 if (wmi_extract_mgmt_rx_params(wma_handle->wmi_handle,
3379 data, mgmt_rx_params, &bufp) != QDF_STATUS_SUCCESS) {
3380 WMA_LOGE("%s: Extraction of mgmt rx params failed", __func__);
3381 qdf_mem_free(mgmt_rx_params);
3382 return -EINVAL;
3383 }
3384
3385 wbuf = qdf_nbuf_alloc(NULL, roundup(mgmt_rx_params->buf_len, 4),
3386 0, 4, false);
3387 if (!wbuf) {
3388 WMA_LOGE("%s: Failed to allocate wbuf for mgmt rx len(%u)",
3389 __func__, mgmt_rx_params->buf_len);
3390 qdf_mem_free(mgmt_rx_params);
3391 return -ENOMEM;
3392 }
3393
3394 qdf_nbuf_put_tail(wbuf, mgmt_rx_params->buf_len);
3395 qdf_nbuf_set_protocol(wbuf, ETH_P_CONTROL);
3396
3397 wma_mem_endianness_based_copy(qdf_nbuf_data(wbuf),
3398 bufp, mgmt_rx_params->buf_len);
3399
3400 psoc = (struct wlan_objmgr_psoc *)
3401 wma_handle->psoc;
3402 if (!psoc) {
3403 WMA_LOGE("%s: psoc ctx is NULL", __func__);
3404 qdf_nbuf_free(wbuf);
3405 qdf_mem_free(mgmt_rx_params);
3406 return -EINVAL;
3407 }
3408
3409 if (!psoc->soc_cb.rx_ops.mgmt_txrx_rx_ops.mgmt_rx_frame_handler) {
3410 WMA_LOGE("%s: rx callback to mgmt txrx layer is NULL",
3411 __func__);
3412 qdf_nbuf_free(wbuf);
3413 qdf_mem_free(mgmt_rx_params);
3414 return -EINVAL;
3415 }
3416
3417 status = psoc->soc_cb.rx_ops.mgmt_txrx_rx_ops.mgmt_rx_frame_handler(
3418 psoc, wbuf, mgmt_rx_params);
3419
3420 if (status != QDF_STATUS_SUCCESS) {
3421 WMA_LOGE("%s: Failed to process mgmt rx frame", __func__);
3422 qdf_mem_free(mgmt_rx_params);
3423 return -EINVAL;
3424 }
3425
3426 qdf_mem_free(mgmt_rx_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003427 return 0;
3428}
3429
3430/**
3431 * wma_de_register_mgmt_frm_client() - deregister management frame
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303432 *
3433 * This function deregisters the event handler registered for
3434 * WMI_MGMT_RX_EVENTID.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003435 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303436 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003437 */
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303438QDF_STATUS wma_de_register_mgmt_frm_client(void)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003439{
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303440 tp_wma_handle wma_handle = (tp_wma_handle)
3441 cds_get_context(QDF_MODULE_ID_WMA);
3442
3443 if (!wma_handle) {
3444 WMA_LOGE("%s: Failed to get WMA context", __func__);
3445 return QDF_STATUS_E_NULL_VALUE;
3446 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003447
3448#ifdef QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +05303449 if (cds_get_conparam() == QDF_GLOBAL_FTM_MODE)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303450 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003451#endif
3452
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003453 if (wmi_unified_unregister_event_handler(wma_handle->wmi_handle,
3454 WMI_MGMT_RX_EVENTID) != 0) {
3455 WMA_LOGE("Failed to Unregister rx mgmt handler with wmi");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303456 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003457 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303458 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003459}
3460
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003461#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003462/**
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003463 * wma_register_roaming_callbacks() - Register roaming callbacks
3464 * @cds_ctx: CDS Context
3465 * @csr_roam_synch_cb: CSR roam synch callback routine pointer
3466 * @pe_roam_synch_cb: PE roam synch callback routine pointer
3467 *
3468 * Register the SME and PE callback routines with WMA for
3469 * handling roaming
3470 *
3471 * Return: Success or Failure Status
3472 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303473QDF_STATUS wma_register_roaming_callbacks(void *cds_ctx,
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003474 void (*csr_roam_synch_cb)(tpAniSirGlobal mac,
3475 roam_offload_synch_ind *roam_synch_data,
Varun Reddy Yeturuf907f912016-03-21 15:06:22 -07003476 tpSirBssDescription bss_desc_ptr,
3477 enum sir_roam_op_code reason),
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303478 QDF_STATUS (*pe_roam_synch_cb)(tpAniSirGlobal mac,
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003479 roam_offload_synch_ind *roam_synch_data,
3480 tpSirBssDescription bss_desc_ptr))
3481{
3482
Anurag Chouhan6d760662016-02-20 16:05:43 +05303483 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003484
3485 if (!wma) {
3486 WMA_LOGE("%s: Failed to get WMA context", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303487 return QDF_STATUS_E_FAILURE;
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003488 }
3489 wma->csr_roam_synch_cb = csr_roam_synch_cb;
3490 wma->pe_roam_synch_cb = pe_roam_synch_cb;
3491 WMA_LOGD("Registered roam synch callbacks with WMA successfully");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303492 return QDF_STATUS_SUCCESS;
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003493}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003494#endif
3495
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003496/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003497 * wma_register_mgmt_frm_client() - register management frame callback
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303498 *
3499 * This function registers event handler for WMI_MGMT_RX_EVENTID.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003500 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303501 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003502 */
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303503QDF_STATUS wma_register_mgmt_frm_client(void)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003504{
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303505 tp_wma_handle wma_handle = (tp_wma_handle)
3506 cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003507
3508 if (!wma_handle) {
3509 WMA_LOGE("%s: Failed to get WMA context", __func__);
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303510 return QDF_STATUS_E_NULL_VALUE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003511 }
3512
3513 if (wmi_unified_register_event_handler(wma_handle->wmi_handle,
3514 WMI_MGMT_RX_EVENTID,
Govind Singhd76a5b02016-03-08 15:12:14 +05303515 wma_mgmt_rx_process,
3516 WMA_RX_WORK_CTX) != 0) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003517 WMA_LOGE("Failed to register rx mgmt handler with wmi");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303518 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003519 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003520
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303521 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003522}
Himanshu Agarwalf65bd4c2016-12-05 17:21:12 +05303523
3524/**
3525 * wma_register_packetdump_callback() - stores tx and rx mgmt packet dump
3526 * callback handler
3527 * @wma_mgmt_tx_packetdump_cb: tx mgmt packetdump cb
3528 * @wma_mgmt_rx_packetdump_cb: rx mgmt packetdump cb
3529 *
3530 * This function is used to store tx and rx mgmt. packet dump callback
3531 *
3532 * Return: None
3533 *
3534 */
3535void wma_register_packetdump_callback(
3536 tp_wma_packetdump_cb wma_mgmt_tx_packetdump_cb,
3537 tp_wma_packetdump_cb wma_mgmt_rx_packetdump_cb)
3538{
3539 tp_wma_handle wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
3540
3541 if (!wma_handle) {
3542 WMA_LOGE("wma handle is NULL");
3543 return;
3544 }
3545
3546 wma_handle->wma_mgmt_tx_packetdump_cb = wma_mgmt_tx_packetdump_cb;
3547 wma_handle->wma_mgmt_rx_packetdump_cb = wma_mgmt_rx_packetdump_cb;
3548}
3549
3550/**
3551 * wma_deregister_packetdump_callback() - removes tx and rx mgmt packet dump
3552 * callback handler
3553 *
3554 * This function is used to remove tx and rx mgmt. packet dump callback
3555 *
3556 * Return: None
3557 *
3558 */
3559void wma_deregister_packetdump_callback(void)
3560{
3561 tp_wma_handle wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
3562
3563 if (!wma_handle) {
3564 WMA_LOGE("wma handle is NULL");
3565 return;
3566 }
3567
3568 wma_handle->wma_mgmt_tx_packetdump_cb = NULL;
3569 wma_handle->wma_mgmt_rx_packetdump_cb = NULL;
3570}
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303571
3572QDF_STATUS wma_mgmt_unified_cmd_send(struct wlan_objmgr_vdev *vdev,
3573 qdf_nbuf_t buf, uint32_t desc_id,
3574 void *mgmt_tx_params)
3575{
3576 tp_wma_handle wma_handle;
3577 QDF_STATUS status;
3578 struct wmi_mgmt_params *mgmt_params =
3579 (struct wmi_mgmt_params *)mgmt_tx_params;
3580
3581 if (!mgmt_params) {
3582 WMA_LOGE("%s: mgmt_params ptr passed is NULL", __func__);
3583 return QDF_STATUS_E_INVAL;
3584 }
3585 mgmt_params->desc_id = desc_id;
3586
3587 if (!vdev) {
3588 WMA_LOGE("%s: vdev ptr passed is NULL", __func__);
3589 return QDF_STATUS_E_INVAL;
3590 }
3591
3592 wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
3593 if (!wma_handle) {
3594 WMA_LOGE("%s: wma handle is NULL", __func__);
3595 return QDF_STATUS_E_INVAL;
3596 }
3597
3598 status = wmi_mgmt_unified_cmd_send(wma_handle->wmi_handle,
3599 mgmt_params);
3600 if (status != QDF_STATUS_SUCCESS) {
3601 WMA_LOGE("%s: mgmt tx failed", __func__);
3602 return status;
3603 }
3604
3605 return QDF_STATUS_SUCCESS;
3606}
3607