blob: 69c226ef65ad300f8813891597c94d8a36f6ec22 [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 */
Rajeev Kumar416b73f2017-01-21 16:45:21 -08001260void wma_update_cfg_params(tp_wma_handle wma, struct scheduler_msg *cfgParam)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001261{
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;
Himanshu Agarwalbb226bc2017-01-18 20:45:01 +05302505 tp_wma_packetdump_cb packetdump_cb;
Leo Chang96464902016-10-28 11:10:54 -07002506
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05302507 if (wma_handle == NULL) {
2508 WMA_LOGE("%s: wma handle is NULL", __func__);
Nirav Shah20489972016-06-16 19:20:28 +05302509 return -EINVAL;
2510 }
2511
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05302512 WMA_LOGI("%s: status:%d desc id:%d", __func__, status, desc_id);
Nirav Shah20489972016-06-16 19:20:28 +05302513
Nirav Shah20489972016-06-16 19:20:28 +05302514
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05302515 psoc = wma_handle->psoc;
2516 if (psoc == NULL) {
2517 WMA_LOGE("%s: psoc ptr is NULL", __func__);
Nirav Shah20489972016-06-16 19:20:28 +05302518 return -EINVAL;
2519 }
2520
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05302521 mgmt_txrx_rx_ops = &psoc->soc_cb.rx_ops.mgmt_txrx_rx_ops;
2522
2523 if (mgmt_txrx_rx_ops->mgmt_txrx_get_nbuf_from_desc_id)
2524 buf = mgmt_txrx_rx_ops->mgmt_txrx_get_nbuf_from_desc_id(
2525 psoc, desc_id);
2526
2527 if (mgmt_txrx_rx_ops->mgmt_txrx_get_vdev_id_from_desc_id)
2528 vdev_id = mgmt_txrx_rx_ops->mgmt_txrx_get_vdev_id_from_desc_id(
2529 psoc, desc_id);
2530 if (buf)
2531 qdf_nbuf_unmap_single(wma_handle->qdf_dev, buf,
Nirav Shah20489972016-06-16 19:20:28 +05302532 QDF_DMA_TO_DEVICE);
Himanshu Agarwalf65bd4c2016-12-05 17:21:12 +05302533
Himanshu Agarwalbb226bc2017-01-18 20:45:01 +05302534 packetdump_cb = wma_handle->wma_mgmt_tx_packetdump_cb;
2535 if (packetdump_cb)
2536 packetdump_cb(buf, QDF_STATUS_SUCCESS,
2537 vdev_id, TX_MGMT_PKT);
Himanshu Agarwalf65bd4c2016-12-05 17:21:12 +05302538
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05302539 if (!mgmt_txrx_rx_ops->mgmt_tx_completion_handler) {
2540 WMA_LOGE("%s: tx completion callback to mgmt txrx layer is NULL",
2541 __func__);
2542 return -EINVAL;
2543 }
2544 ret = mgmt_txrx_rx_ops->mgmt_tx_completion_handler(psoc, desc_id,
2545 status, NULL);
Nirav Shah20489972016-06-16 19:20:28 +05302546
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05302547 if (ret != QDF_STATUS_SUCCESS) {
2548 WMA_LOGE("%s: Failed to process mgmt tx completion", __func__);
2549 return -EINVAL;
2550 }
Nirav Shah20489972016-06-16 19:20:28 +05302551
Nirav Shah20489972016-06-16 19:20:28 +05302552 return 0;
2553}
2554
2555/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002556 * wma_mgmt_tx_completion_handler() - wma mgmt Tx completion event handler
2557 * @handle: wma handle
2558 * @cmpl_event_params: completion event handler data
2559 * @len: length of @cmpl_event_params
2560 *
2561 * Return: 0 on success; error number otherwise
2562 */
2563
2564int wma_mgmt_tx_completion_handler(void *handle, uint8_t *cmpl_event_params,
2565 uint32_t len)
2566{
2567 tp_wma_handle wma_handle = (tp_wma_handle)handle;
2568 WMI_MGMT_TX_COMPLETION_EVENTID_param_tlvs *param_buf;
2569 wmi_mgmt_tx_compl_event_fixed_param *cmpl_params;
Naveen Rawat35804772016-06-27 15:40:28 -07002570
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002571 param_buf = (WMI_MGMT_TX_COMPLETION_EVENTID_param_tlvs *)
2572 cmpl_event_params;
Naveen Rawat35804772016-06-27 15:40:28 -07002573 if (!param_buf || !wma_handle) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002574 WMA_LOGE("%s: Invalid mgmt Tx completion event", __func__);
2575 return -EINVAL;
2576 }
2577 cmpl_params = param_buf->fixed_param;
2578
Nirav Shah20489972016-06-16 19:20:28 +05302579 wma_process_mgmt_tx_completion(wma_handle,
2580 cmpl_params->desc_id, cmpl_params->status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002581
Nirav Shah20489972016-06-16 19:20:28 +05302582 return 0;
2583}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002584
Nirav Shah20489972016-06-16 19:20:28 +05302585/**
2586 * wma_mgmt_tx_bundle_completion_handler() - mgmt bundle comp handler
2587 * @handle: wma handle
2588 * @buf: buffer
2589 * @len: length
2590 *
2591 * Return: 0 for success or error code
2592 */
2593int wma_mgmt_tx_bundle_completion_handler(void *handle, uint8_t *buf,
2594 uint32_t len)
2595{
2596 tp_wma_handle wma_handle = (tp_wma_handle)handle;
2597 WMI_MGMT_TX_BUNDLE_COMPLETION_EVENTID_param_tlvs *param_buf;
2598 wmi_mgmt_tx_compl_bundle_event_fixed_param *cmpl_params;
2599 uint32_t num_reports;
2600 uint32_t *desc_ids;
2601 uint32_t *status;
2602 int i;
2603
2604 param_buf = (WMI_MGMT_TX_BUNDLE_COMPLETION_EVENTID_param_tlvs *)buf;
Arif Hussain31576d92016-10-25 14:32:12 -07002605 if (!param_buf || !wma_handle) {
Nirav Shah20489972016-06-16 19:20:28 +05302606 WMA_LOGE("%s: Invalid mgmt Tx completion event", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002607 return -EINVAL;
2608 }
Nirav Shah20489972016-06-16 19:20:28 +05302609 cmpl_params = param_buf->fixed_param;
2610 num_reports = cmpl_params->num_reports;
2611 desc_ids = (uint32_t *)(param_buf->desc_ids);
2612 status = (uint32_t *)(param_buf->status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002613
Nirav Shah20489972016-06-16 19:20:28 +05302614 for (i = 0; i < num_reports; i++)
2615 wma_process_mgmt_tx_completion(wma_handle,
2616 desc_ids[i], status[i]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002617 return 0;
2618}
2619
2620/**
2621 * wma_process_update_opmode() - process update VHT opmode cmd from UMAC
2622 * @wma_handle: wma handle
2623 * @update_vht_opmode: vht opmode
2624 *
2625 * Return: none
2626 */
2627void wma_process_update_opmode(tp_wma_handle wma_handle,
2628 tUpdateVHTOpMode *update_vht_opmode)
2629{
2630 WMA_LOGD("%s: opMode = %d", __func__, update_vht_opmode->opMode);
2631
2632 wma_set_peer_param(wma_handle, update_vht_opmode->peer_mac,
2633 WMI_PEER_CHWIDTH, update_vht_opmode->opMode,
2634 update_vht_opmode->smesessionId);
2635}
2636
2637/**
2638 * wma_process_update_rx_nss() - process update RX NSS cmd from UMAC
2639 * @wma_handle: wma handle
2640 * @update_rx_nss: rx nss value
2641 *
2642 * Return: none
2643 */
2644void wma_process_update_rx_nss(tp_wma_handle wma_handle,
2645 tUpdateRxNss *update_rx_nss)
2646{
2647 struct wma_txrx_node *intr =
2648 &wma_handle->interfaces[update_rx_nss->smesessionId];
2649 int rx_nss = update_rx_nss->rxNss;
2650
2651 wma_update_txrx_chainmask(wma_handle->num_rf_chains, &rx_nss);
2652
2653 intr->nss = (uint8_t)rx_nss;
2654 update_rx_nss->rxNss = (uint32_t)rx_nss;
2655
2656 WMA_LOGD("%s: Rx Nss = %d", __func__, update_rx_nss->rxNss);
2657
2658 wma_set_peer_param(wma_handle, update_rx_nss->peer_mac,
2659 WMI_PEER_NSS, update_rx_nss->rxNss,
2660 update_rx_nss->smesessionId);
2661}
2662
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002663/**
2664 * wma_process_update_membership() - process update group membership cmd
2665 * @wma_handle: wma handle
2666 * @membership: group membership info
2667 *
2668 * Return: none
2669 */
2670void wma_process_update_membership(tp_wma_handle wma_handle,
2671 tUpdateMembership *membership)
2672{
2673 WMA_LOGD("%s: membership = %x ", __func__, membership->membership);
2674
2675 wma_set_peer_param(wma_handle, membership->peer_mac,
2676 WMI_PEER_MEMBERSHIP, membership->membership,
2677 membership->smesessionId);
2678}
2679
2680/**
2681 * wma_process_update_userpos() - process update user pos cmd from UMAC
2682 * @wma_handle: wma handle
2683 * @userpos: user pos value
2684 *
2685 * Return: none
2686 */
2687void wma_process_update_userpos(tp_wma_handle wma_handle,
2688 tUpdateUserPos *userpos)
2689{
2690 WMA_LOGD("%s: userPos = %x ", __func__, userpos->userPos);
2691
2692 wma_set_peer_param(wma_handle, userpos->peer_mac,
2693 WMI_PEER_USERPOS, userpos->userPos,
2694 userpos->smesessionId);
2695
2696 /* Now that membership/userpos is updated in fw,
2697 * enable GID PPS.
2698 */
2699 wma_set_ppsconfig(userpos->smesessionId, WMA_VHT_PPS_GID_MATCH, 1);
2700
2701}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002702
Agrawal Ashishb2d1a452016-05-05 12:23:58 +05302703QDF_STATUS wma_set_cts2self_for_p2p_go(void *wma_handle,
2704 uint32_t cts2self_for_p2p_go)
2705{
2706 int32_t ret;
2707 tp_wma_handle wma = (tp_wma_handle)wma_handle;
2708 struct pdev_params pdevparam;
2709
2710 pdevparam.param_id = WMI_PDEV_PARAM_CTS2SELF_FOR_P2P_GO_CONFIG;
2711 pdevparam.param_value = cts2self_for_p2p_go;
2712
2713 ret = wmi_unified_pdev_param_send(wma->wmi_handle,
2714 &pdevparam,
2715 WMA_WILDCARD_PDEV_ID);
2716 if (ret) {
2717 WMA_LOGE("Fail to Set CTS2SELF for p2p GO %d",
2718 cts2self_for_p2p_go);
2719 return QDF_STATUS_E_FAILURE;
2720 }
2721
2722 WMA_LOGD("Successfully Set CTS2SELF for p2p GO %d",
2723 cts2self_for_p2p_go);
2724
2725 return QDF_STATUS_SUCCESS;
2726}
2727
2728
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002729/**
2730 * wma_set_htconfig() - set ht config parameters to target
2731 * @vdev_id: vdev id
2732 * @ht_capab: ht capablity
2733 * @value: value of ht param
2734 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302735 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002736 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302737QDF_STATUS wma_set_htconfig(uint8_t vdev_id, uint16_t ht_capab, int value)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002738{
Anurag Chouhan6d760662016-02-20 16:05:43 +05302739 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
Govind Singhd76a5b02016-03-08 15:12:14 +05302740 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002741
2742 if (NULL == wma) {
2743 WMA_LOGE("%s: Failed to get wma", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302744 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002745 }
2746
2747 switch (ht_capab) {
2748 case WNI_CFG_HT_CAP_INFO_ADVANCE_CODING:
Govind Singhd76a5b02016-03-08 15:12:14 +05302749 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002750 WMI_VDEV_PARAM_LDPC,
2751 value);
2752 break;
2753 case WNI_CFG_HT_CAP_INFO_TX_STBC:
Govind Singhd76a5b02016-03-08 15:12:14 +05302754 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002755 WMI_VDEV_PARAM_TX_STBC,
2756 value);
2757 break;
2758 case WNI_CFG_HT_CAP_INFO_RX_STBC:
Govind Singhd76a5b02016-03-08 15:12:14 +05302759 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002760 WMI_VDEV_PARAM_RX_STBC,
2761 value);
2762 break;
2763 case WNI_CFG_HT_CAP_INFO_SHORT_GI_20MHZ:
2764 case WNI_CFG_HT_CAP_INFO_SHORT_GI_40MHZ:
2765 WMA_LOGE("%s: ht_capab = %d, value = %d", __func__, ht_capab,
2766 value);
Govind Singhd76a5b02016-03-08 15:12:14 +05302767 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002768 WMI_VDEV_PARAM_SGI, value);
Govind Singhd76a5b02016-03-08 15:12:14 +05302769 if (ret == QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002770 wma->interfaces[vdev_id].config.shortgi = value;
2771 break;
2772 default:
2773 WMA_LOGE("%s:INVALID HT CONFIG", __func__);
2774 }
2775
Govind Singhd76a5b02016-03-08 15:12:14 +05302776 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002777}
2778
2779/**
2780 * wma_hidden_ssid_vdev_restart() - vdev restart for hidden ssid
2781 * @wma_handle: wma handle
2782 * @pReq: hidden ssid vdev restart request
2783 *
2784 * Return: none
2785 */
2786void wma_hidden_ssid_vdev_restart(tp_wma_handle wma_handle,
2787 tHalHiddenSsidVdevRestart *pReq)
2788{
2789 struct wma_txrx_node *intr = wma_handle->interfaces;
Selvaraj, Sridhara0083c42016-06-22 22:15:43 +05302790 struct wma_target_req *msg;
Leo Chang96464902016-10-28 11:10:54 -07002791 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002792
2793 if ((pReq->sessionId !=
2794 intr[pReq->sessionId].vdev_restart_params.vdev_id)
2795 || !((intr[pReq->sessionId].type == WMI_VDEV_TYPE_AP)
2796 && (intr[pReq->sessionId].sub_type == 0))) {
2797 WMA_LOGE("%s : invalid session id", __func__);
2798 return;
2799 }
2800
2801 intr[pReq->sessionId].vdev_restart_params.ssidHidden = pReq->ssidHidden;
Anurag Chouhan8e0ccd32016-02-19 15:30:20 +05302802 qdf_atomic_set(&intr[pReq->sessionId].vdev_restart_params.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002803 hidden_ssid_restart_in_progress, 1);
2804
Selvaraj, Sridhara0083c42016-06-22 22:15:43 +05302805 msg = wma_fill_vdev_req(wma_handle, pReq->sessionId,
2806 WMA_HIDDEN_SSID_VDEV_RESTART,
2807 WMA_TARGET_REQ_TYPE_VDEV_STOP, pReq,
2808 WMA_VDEV_STOP_REQUEST_TIMEOUT);
2809 if (!msg) {
2810 WMA_LOGE("%s: Failed to fill vdev restart request for vdev_id %d",
2811 __func__, pReq->sessionId);
2812 return;
2813 }
2814
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002815 /* vdev stop -> vdev restart -> vdev up */
2816 WMA_LOGD("%s, vdev_id: %d, pausing tx_ll_queue for VDEV_STOP",
2817 __func__, pReq->sessionId);
Leo Chang96464902016-10-28 11:10:54 -07002818 cdp_fc_vdev_pause(soc, wma_handle->interfaces[pReq->sessionId].handle,
2819 OL_TXQ_PAUSE_REASON_VDEV_STOP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002820 wma_handle->interfaces[pReq->sessionId].pause_bitmap |=
2821 (1 << PAUSE_TYPE_HOST);
2822 if (wmi_unified_vdev_stop_send(wma_handle->wmi_handle, pReq->sessionId)) {
2823 WMA_LOGE("%s: %d Failed to send vdev stop", __func__, __LINE__);
Anurag Chouhan8e0ccd32016-02-19 15:30:20 +05302824 qdf_atomic_set(&intr[pReq->sessionId].vdev_restart_params.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002825 hidden_ssid_restart_in_progress, 0);
Selvaraj, Sridhara0083c42016-06-22 22:15:43 +05302826 wma_remove_vdev_req(wma_handle, pReq->sessionId,
2827 WMA_TARGET_REQ_TYPE_VDEV_STOP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002828 return;
2829 }
2830}
2831
2832
2833#ifdef WLAN_FEATURE_11W
2834
2835/**
2836 * wma_extract_ccmp_pn() - extract 6 byte PN from the CCMP header
2837 * @ccmp_ptr: CCMP header
2838 *
2839 * Return: PN extracted from header.
2840 */
2841static uint64_t wma_extract_ccmp_pn(uint8_t *ccmp_ptr)
2842{
2843 uint8_t rsvd, key, pn[6];
2844 uint64_t new_pn;
2845
2846 /*
2847 * +-----+-----+------+----------+-----+-----+-----+-----+
2848 * | PN0 | PN1 | rsvd | rsvd/key | PN2 | PN3 | PN4 | PN5 |
2849 * +-----+-----+------+----------+-----+-----+-----+-----+
2850 * CCMP Header Format
2851 */
2852
2853 /* Extract individual bytes */
2854 pn[0] = (uint8_t) *ccmp_ptr;
2855 pn[1] = (uint8_t) *(ccmp_ptr + 1);
2856 rsvd = (uint8_t) *(ccmp_ptr + 2);
2857 key = (uint8_t) *(ccmp_ptr + 3);
2858 pn[2] = (uint8_t) *(ccmp_ptr + 4);
2859 pn[3] = (uint8_t) *(ccmp_ptr + 5);
2860 pn[4] = (uint8_t) *(ccmp_ptr + 6);
2861 pn[5] = (uint8_t) *(ccmp_ptr + 7);
2862
2863 /* Form 6 byte PN with 6 individual bytes of PN */
2864 new_pn = ((uint64_t) pn[5] << 40) |
2865 ((uint64_t) pn[4] << 32) |
2866 ((uint64_t) pn[3] << 24) |
2867 ((uint64_t) pn[2] << 16) |
2868 ((uint64_t) pn[1] << 8) | ((uint64_t) pn[0] << 0);
2869
2870 WMA_LOGE("PN of received packet is %llu", new_pn);
2871 return new_pn;
2872}
2873
2874/**
2875 * wma_is_ccmp_pn_replay_attack() - detect replay attacking using PN in CCMP
2876 * @cds_ctx: cds context
2877 * @wh: 802.11 frame header
2878 * @ccmp_ptr: CCMP frame header
2879 *
2880 * Return: true/false
2881 */
2882static bool
2883wma_is_ccmp_pn_replay_attack(void *cds_ctx, struct ieee80211_frame *wh,
2884 uint8_t *ccmp_ptr)
2885{
Leo Chang96464902016-10-28 11:10:54 -07002886 void *pdev;
2887 void *vdev;
2888 void *peer;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002889 uint8_t vdev_id, peer_id;
2890 uint8_t *last_pn_valid;
2891 uint64_t *last_pn, new_pn;
2892 uint32_t *rmf_pn_replays;
Leo Chang96464902016-10-28 11:10:54 -07002893 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002894
Anurag Chouhan6d760662016-02-20 16:05:43 +05302895 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002896 if (!pdev) {
2897 WMA_LOGE("%s: Failed to find pdev", __func__);
2898 return true;
2899 }
2900
Mukul Sharmaa748fbb2015-12-01 19:51:36 +05302901 vdev = wma_find_vdev_by_bssid(cds_ctx, wh->i_addr3, &vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002902 if (!vdev) {
2903 WMA_LOGE("%s: Failed to find vdev", __func__);
2904 return true;
2905 }
2906
2907 /* Retrieve the peer based on vdev and addr */
Leo Chang96464902016-10-28 11:10:54 -07002908 peer = cdp_peer_find_by_addr_and_vdev(soc, pdev, vdev, wh->i_addr2,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002909 &peer_id);
2910
2911 if (NULL == peer) {
2912 WMA_LOGE("%s: Failed to find peer, Not able to validate PN",
2913 __func__);
2914 return true;
2915 }
2916
2917 new_pn = wma_extract_ccmp_pn(ccmp_ptr);
Leo Chang96464902016-10-28 11:10:54 -07002918 cdp_get_pn_info(soc, peer, &last_pn_valid, &last_pn, &rmf_pn_replays);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002919
2920 if (*last_pn_valid) {
2921 if (new_pn > *last_pn) {
2922 *last_pn = new_pn;
2923 WMA_LOGE("%s: PN validation successful", __func__);
2924 } else {
2925 WMA_LOGE("%s: PN Replay attack detected", __func__);
2926 /* per 11W amendment, keeping track of replay attacks */
2927 *rmf_pn_replays += 1;
2928 return true;
2929 }
2930 } else {
2931 *last_pn_valid = 1;
2932 *last_pn = new_pn;
2933 }
2934
2935 return false;
2936}
2937
2938/**
mukul sharma72c8b222015-09-04 17:02:01 +05302939 * wma_process_bip() - process mmie in rmf frame
2940 * @wma_handle: wma handle
2941 * @iface: txrx node
2942 * @wh: 80211 frame
2943 * @wbuf: Buffer
2944 *
2945 * Return: 0 for success or error code
2946 */
2947
2948static
2949int wma_process_bip(tp_wma_handle wma_handle,
2950 struct wma_txrx_node *iface,
2951 struct ieee80211_frame *wh,
Nirav Shahcbc6d722016-03-01 16:24:53 +05302952 qdf_nbuf_t wbuf
mukul sharma72c8b222015-09-04 17:02:01 +05302953)
2954{
2955 uint16_t key_id;
2956 uint8_t *efrm;
2957
Nirav Shahcbc6d722016-03-01 16:24:53 +05302958 efrm = qdf_nbuf_data(wbuf) + qdf_nbuf_len(wbuf);
mukul sharma72c8b222015-09-04 17:02:01 +05302959 key_id = (uint16_t)*(efrm - cds_get_mmie_size() + 2);
2960
2961 if (!((key_id == WMA_IGTK_KEY_INDEX_4)
2962 || (key_id == WMA_IGTK_KEY_INDEX_5))) {
2963 WMA_LOGE(FL("Invalid KeyID(%d) dropping the frame"), key_id);
2964 return -EINVAL;
2965 }
2966 if (WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap,
2967 WMI_SERVICE_STA_PMF_OFFLOAD)) {
2968 /*
2969 * if 11w offload is enabled then mmie validation is performed
2970 * in firmware, host just need to trim the mmie.
2971 */
Nirav Shahcbc6d722016-03-01 16:24:53 +05302972 qdf_nbuf_trim_tail(wbuf, cds_get_mmie_size());
mukul sharma72c8b222015-09-04 17:02:01 +05302973 } else {
2974 if (cds_is_mmie_valid(iface->key.key,
2975 iface->key.key_id[key_id - WMA_IGTK_KEY_INDEX_4].ipn,
2976 (uint8_t *) wh, efrm)) {
2977 WMA_LOGE(FL("Protected BC/MC frame MMIE validation successful"));
2978 /* Remove MMIE */
Nirav Shahcbc6d722016-03-01 16:24:53 +05302979 qdf_nbuf_trim_tail(wbuf, cds_get_mmie_size());
mukul sharma72c8b222015-09-04 17:02:01 +05302980 } else {
2981 WMA_LOGE(FL("BC/MC MIC error or MMIE not present, dropping the frame"));
2982 return -EINVAL;
2983 }
2984 }
2985 return 0;
2986}
2987
2988/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002989 * wma_process_rmf_frame() - process rmf frame
2990 * @wma_handle: wma handle
2991 * @iface: txrx node
2992 * @wh: 80211 frame
2993 * @rx_pkt: rx packet
2994 * @wbuf: Buffer
2995 *
2996 * Return: 0 for success or error code
2997 */
2998static
2999int wma_process_rmf_frame(tp_wma_handle wma_handle,
3000 struct wma_txrx_node *iface,
3001 struct ieee80211_frame *wh,
3002 cds_pkt_t *rx_pkt,
Nirav Shahcbc6d722016-03-01 16:24:53 +05303003 qdf_nbuf_t wbuf)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003004{
mukul sharma72c8b222015-09-04 17:02:01 +05303005 uint8_t *orig_hdr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003006 uint8_t *ccmp;
3007
3008 if ((wh)->i_fc[1] & IEEE80211_FC1_WEP) {
3009 if (IEEE80211_IS_BROADCAST(wh->i_addr1) ||
3010 IEEE80211_IS_MULTICAST(wh->i_addr1)) {
3011 WMA_LOGE("Encrypted BC/MC frame dropping the frame");
3012 cds_pkt_return_packet(rx_pkt);
3013 return -EINVAL;
3014 }
3015
Nirav Shahcbc6d722016-03-01 16:24:53 +05303016 orig_hdr = (uint8_t *) qdf_nbuf_data(wbuf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003017 /* Pointer to head of CCMP header */
3018 ccmp = orig_hdr + sizeof(*wh);
3019 if (wma_is_ccmp_pn_replay_attack(
3020 wma_handle, wh, ccmp)) {
3021 WMA_LOGE("Dropping the frame");
3022 cds_pkt_return_packet(rx_pkt);
3023 return -EINVAL;
3024 }
3025
3026 /* Strip privacy headers (and trailer)
3027 * for a received frame
3028 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303029 qdf_mem_move(orig_hdr +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003030 IEEE80211_CCMP_HEADERLEN, wh,
3031 sizeof(*wh));
Nirav Shahcbc6d722016-03-01 16:24:53 +05303032 qdf_nbuf_pull_head(wbuf,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003033 IEEE80211_CCMP_HEADERLEN);
Krunal Soni54da0c62016-08-01 17:04:25 -07003034 qdf_nbuf_trim_tail(wbuf, IEEE80211_CCMP_MICLEN);
3035 /*
3036 * CCMP header has been pulled off
3037 * reinitialize the start pointer of mac header
3038 * to avoid accessing incorrect address
3039 */
3040 wh = (struct ieee80211_frame *) qdf_nbuf_data(wbuf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003041 rx_pkt->pkt_meta.mpdu_hdr_ptr =
Nirav Shahcbc6d722016-03-01 16:24:53 +05303042 qdf_nbuf_data(wbuf);
3043 rx_pkt->pkt_meta.mpdu_len = qdf_nbuf_len(wbuf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003044 rx_pkt->pkt_meta.mpdu_data_len =
3045 rx_pkt->pkt_meta.mpdu_len -
3046 rx_pkt->pkt_meta.mpdu_hdr_len;
3047 rx_pkt->pkt_meta.mpdu_data_ptr =
3048 rx_pkt->pkt_meta.mpdu_hdr_ptr +
3049 rx_pkt->pkt_meta.mpdu_hdr_len;
3050 rx_pkt->pkt_meta.tsf_delta = rx_pkt->pkt_meta.tsf_delta;
3051 rx_pkt->pkt_buf = wbuf;
3052 WMA_LOGD(FL("BSSID: "MAC_ADDRESS_STR" tsf_delta: %u"),
3053 MAC_ADDR_ARRAY(wh->i_addr3), rx_pkt->pkt_meta.tsf_delta);
3054 } else {
3055 if (IEEE80211_IS_BROADCAST(wh->i_addr1) ||
3056 IEEE80211_IS_MULTICAST(wh->i_addr1)) {
mukul sharma72c8b222015-09-04 17:02:01 +05303057 if (0 != wma_process_bip(wma_handle, iface, wh, wbuf)) {
3058 cds_pkt_return_packet(rx_pkt);
3059 return -EINVAL;
Mukul Sharmaa748fbb2015-12-01 19:51:36 +05303060 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003061 } else {
3062 WMA_LOGE("Rx unprotected unicast mgmt frame");
3063 rx_pkt->pkt_meta.dpuFeedback =
3064 DPU_FEEDBACK_UNPROTECTED_ERROR;
3065 }
3066 }
3067 return 0;
3068}
3069#endif
3070
3071/**
Krishna Kumaar Natarajanb7f9a352016-03-18 11:40:07 -07003072 * wma_is_pkt_drop_candidate() - check if the mgmt frame should be droppped
3073 * @wma_handle: wma handle
3074 * @peer_addr: peer MAC address
3075 * @subtype: Management frame subtype
3076 *
3077 * This function is used to decide if a particular management frame should be
3078 * dropped to prevent DOS attack. Timestamp is used to decide the DOS attack.
3079 *
3080 * Return: true if the packet should be dropped and false oterwise
3081 */
3082static bool wma_is_pkt_drop_candidate(tp_wma_handle wma_handle,
3083 uint8_t *peer_addr, uint8_t subtype)
3084{
Leo Chang96464902016-10-28 11:10:54 -07003085 void *peer;
3086 void *pdev_ctx;
Krishna Kumaar Natarajanb7f9a352016-03-18 11:40:07 -07003087 uint8_t peer_id;
3088 bool should_drop = false;
Nishank Aggarwal21282ec2016-12-01 17:41:33 +05303089 qdf_time_t *ptr;
Leo Chang96464902016-10-28 11:10:54 -07003090 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Krishna Kumaar Natarajanb7f9a352016-03-18 11:40:07 -07003091
3092 /*
3093 * Currently this function handles only Disassoc,
3094 * Deauth and Assoc req frames. Return false for
3095 * all other frames.
3096 */
3097 if (subtype != IEEE80211_FC0_SUBTYPE_DISASSOC &&
3098 subtype != IEEE80211_FC0_SUBTYPE_DEAUTH &&
3099 subtype != IEEE80211_FC0_SUBTYPE_ASSOC_REQ) {
3100 should_drop = false;
3101 goto end;
3102 }
3103
3104 pdev_ctx = cds_get_context(QDF_MODULE_ID_TXRX);
3105 if (!pdev_ctx) {
3106 WMA_LOGE(FL("Failed to get the context"));
3107 should_drop = true;
3108 goto end;
3109 }
3110
Leo Chang96464902016-10-28 11:10:54 -07003111 peer = cdp_peer_find_by_addr(soc, pdev_ctx, peer_addr, &peer_id);
Krishna Kumaar Natarajanb7f9a352016-03-18 11:40:07 -07003112 if (!peer) {
3113 if (SIR_MAC_MGMT_ASSOC_REQ != subtype) {
3114 WMA_LOGI(
3115 FL("Received mgmt frame: %0x from unknow peer: %pM"),
3116 subtype, peer_addr);
3117 should_drop = true;
3118 }
3119 goto end;
3120 }
3121
3122 switch (subtype) {
3123 case SIR_MAC_MGMT_ASSOC_REQ:
Nishank Aggarwal21282ec2016-12-01 17:41:33 +05303124 ptr = cdp_peer_last_assoc_received(soc, peer);
3125 if (ptr == NULL) {
3126 WMA_LOGE(FL("cdp_peer_last_assoc_received Failed"));
3127 should_drop = true;
3128 goto end;
3129 } else {
Leo Chang96464902016-10-28 11:10:54 -07003130 if ((qdf_get_system_timestamp() -
3131 *cdp_peer_last_assoc_received(soc, peer)) <
Krishna Kumaar Natarajanb7f9a352016-03-18 11:40:07 -07003132 WMA_MGMT_FRAME_DETECT_DOS_TIMER) {
3133 WMA_LOGI(FL("Dropping Assoc Req received"));
3134 should_drop = true;
3135 }
3136 }
Leo Chang96464902016-10-28 11:10:54 -07003137 *cdp_peer_last_assoc_received(soc, peer) =
3138 qdf_get_system_timestamp();
Krishna Kumaar Natarajanb7f9a352016-03-18 11:40:07 -07003139 break;
3140 case SIR_MAC_MGMT_DISASSOC:
Leo Chang96464902016-10-28 11:10:54 -07003141 if (*cdp_peer_last_disassoc_received(soc, peer)) {
3142 if ((qdf_get_system_timestamp() -
3143 *cdp_peer_last_disassoc_received(soc, peer)) <
Krishna Kumaar Natarajanb7f9a352016-03-18 11:40:07 -07003144 WMA_MGMT_FRAME_DETECT_DOS_TIMER) {
3145 WMA_LOGI(FL("Dropping DisAssoc received"));
3146 should_drop = true;
3147 }
3148 }
Leo Chang96464902016-10-28 11:10:54 -07003149 *cdp_peer_last_disassoc_received(soc, peer) =
3150 qdf_get_system_timestamp();
Krishna Kumaar Natarajanb7f9a352016-03-18 11:40:07 -07003151 break;
3152 case SIR_MAC_MGMT_DEAUTH:
Leo Chang96464902016-10-28 11:10:54 -07003153 if (*cdp_peer_last_deauth_received(soc, peer)) {
3154 if ((qdf_get_system_timestamp() -
3155 *cdp_peer_last_deauth_received(soc, peer)) <
Krishna Kumaar Natarajanb7f9a352016-03-18 11:40:07 -07003156 WMA_MGMT_FRAME_DETECT_DOS_TIMER) {
3157 WMA_LOGI(FL("Dropping Deauth received"));
3158 should_drop = true;
3159 }
3160 }
Leo Chang96464902016-10-28 11:10:54 -07003161 *cdp_peer_last_deauth_received(soc, peer) =
3162 qdf_get_system_timestamp();
Krishna Kumaar Natarajanb7f9a352016-03-18 11:40:07 -07003163 break;
3164 default:
3165 break;
3166 }
3167
3168end:
3169 return should_drop;
3170}
3171
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303172int wma_form_rx_packet(qdf_nbuf_t buf,
3173 void *params,
3174 cds_pkt_t *rx_pkt)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003175{
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303176 wmi_host_mgmt_rx_hdr *mgmt_rx_params =
3177 (wmi_host_mgmt_rx_hdr *)params;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003178 struct wma_txrx_node *iface = NULL;
Mukul Sharmaa748fbb2015-12-01 19:51:36 +05303179 uint8_t vdev_id = WMA_INVALID_VDEV_ID;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003180 struct ieee80211_frame *wh;
3181 uint8_t mgt_type, mgt_subtype;
3182 int status;
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303183 tp_wma_handle wma_handle = (tp_wma_handle)
3184 cds_get_context(QDF_MODULE_ID_WMA);
Himanshu Agarwalbb226bc2017-01-18 20:45:01 +05303185 tp_wma_packetdump_cb packetdump_cb;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003186
3187 if (!wma_handle) {
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303188 WMA_LOGE(FL("wma handle is NULL"));
3189 qdf_nbuf_free(buf);
3190 qdf_mem_free(rx_pkt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003191 return -EINVAL;
3192 }
3193
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303194 if (!mgmt_rx_params) {
3195 WMA_LOGE(FL("mgmt rx params is NULL"));
3196 qdf_nbuf_free(buf);
3197 qdf_mem_free(rx_pkt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003198 return -EINVAL;
3199 }
3200
Rajeev Kumarfec3dbe2016-01-19 15:23:52 -08003201 if (cds_is_load_or_unload_in_progress()) {
Krishna Kumaar Natarajan93c9de12016-06-16 17:04:30 -07003202 WMA_LOGW(FL("Load/Unload in progress"));
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303203 qdf_nbuf_free(buf);
3204 qdf_mem_free(rx_pkt);
Naveen Rawat10ccf872015-11-03 14:15:55 -08003205 return -EINVAL;
3206 }
3207
Mukul Sharma80edc782016-09-12 15:59:24 +05303208 if (cds_is_driver_recovering()) {
3209 WMA_LOGW(FL("Recovery in progress"));
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303210 qdf_nbuf_free(buf);
3211 qdf_mem_free(rx_pkt);
Mukul Sharma80edc782016-09-12 15:59:24 +05303212 return -EINVAL;
3213 }
3214
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003215 /*
3216 * Fill in meta information needed by pe/lim
3217 * TODO: Try to maintain rx metainfo as part of skb->data.
3218 */
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303219 rx_pkt->pkt_meta.channel = mgmt_rx_params->channel;
3220 rx_pkt->pkt_meta.scan_src = mgmt_rx_params->flags;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -07003221
3222 /*
3223 * Get the rssi value from the current snr value
3224 * using standard noise floor of -96.
3225 */
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303226 rx_pkt->pkt_meta.rssi = mgmt_rx_params->snr +
3227 WMA_NOISE_FLOOR_DBM_DEFAULT;
3228 rx_pkt->pkt_meta.snr = mgmt_rx_params->snr;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -07003229
3230 /* If absolute rssi is available from firmware, use it */
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303231 if (mgmt_rx_params->rssi != 0)
3232 rx_pkt->pkt_meta.rssi_raw = mgmt_rx_params->rssi;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -07003233 else
3234 rx_pkt->pkt_meta.rssi_raw = rx_pkt->pkt_meta.rssi;
3235
3236
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003237 /*
3238 * FIXME: Assigning the local timestamp as hw timestamp is not
3239 * available. Need to see if pe/lim really uses this data.
3240 */
3241 rx_pkt->pkt_meta.timestamp = (uint32_t) jiffies;
3242 rx_pkt->pkt_meta.mpdu_hdr_len = sizeof(struct ieee80211_frame);
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303243 rx_pkt->pkt_meta.mpdu_len = mgmt_rx_params->buf_len;
3244 rx_pkt->pkt_meta.mpdu_data_len = mgmt_rx_params->buf_len -
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003245 rx_pkt->pkt_meta.mpdu_hdr_len;
3246
3247 rx_pkt->pkt_meta.roamCandidateInd = 0;
3248
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303249 wh = (struct ieee80211_frame *)qdf_nbuf_data(buf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003250
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303251 rx_pkt->pkt_meta.mpdu_hdr_ptr = qdf_nbuf_data(buf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003252 rx_pkt->pkt_meta.mpdu_data_ptr = rx_pkt->pkt_meta.mpdu_hdr_ptr +
3253 rx_pkt->pkt_meta.mpdu_hdr_len;
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303254 rx_pkt->pkt_meta.tsf_delta = mgmt_rx_params->tsf_delta;
3255 rx_pkt->pkt_buf = buf;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003256
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -07003257 WMA_LOGD(
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303258 FL("BSSID: "MAC_ADDRESS_STR" snr = %d, rssi = %d, rssi_raw = %d tsf_delta: %u"),
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -07003259 MAC_ADDR_ARRAY(wh->i_addr3),
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303260 mgmt_rx_params->snr, rx_pkt->pkt_meta.rssi,
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303261 rx_pkt->pkt_meta.rssi_raw,
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303262 mgmt_rx_params->tsf_delta);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003263
3264 /* If it is a beacon/probe response, save it for future use */
3265 mgt_type = (wh)->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
3266 mgt_subtype = (wh)->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
3267
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003268#ifdef WLAN_FEATURE_11W
3269 if (mgt_type == IEEE80211_FC0_TYPE_MGT &&
3270 (mgt_subtype == IEEE80211_FC0_SUBTYPE_DISASSOC ||
3271 mgt_subtype == IEEE80211_FC0_SUBTYPE_DEAUTH ||
3272 mgt_subtype == IEEE80211_FC0_SUBTYPE_ACTION)) {
Mukul Sharmaa748fbb2015-12-01 19:51:36 +05303273 if (wma_find_vdev_by_bssid(
3274 wma_handle, wh->i_addr3, &vdev_id)) {
3275 iface = &(wma_handle->interfaces[vdev_id]);
3276 if (iface->rmfEnabled) {
3277 status = wma_process_rmf_frame(wma_handle,
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303278 iface, wh, rx_pkt, buf);
3279 if (status != 0)
3280 return status;
Krunal Soni54da0c62016-08-01 17:04:25 -07003281 /*
3282 * CCMP header might have been pulled off
3283 * reinitialize the start pointer of mac header
3284 */
3285 wh = (struct ieee80211_frame *)
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303286 qdf_nbuf_data(buf);
Mukul Sharmaa748fbb2015-12-01 19:51:36 +05303287 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003288 }
3289 }
3290#endif /* WLAN_FEATURE_11W */
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303291
Mukul Sharmaa748fbb2015-12-01 19:51:36 +05303292 rx_pkt->pkt_meta.sessionId =
3293 (vdev_id == WMA_INVALID_VDEV_ID ? 0 : vdev_id);
Krishna Kumaar Natarajanb7f9a352016-03-18 11:40:07 -07003294
3295 if (wma_is_pkt_drop_candidate(wma_handle, wh->i_addr2, mgt_subtype)) {
3296 cds_pkt_return_packet(rx_pkt);
3297 return -EINVAL;
3298 }
3299
Himanshu Agarwalbb226bc2017-01-18 20:45:01 +05303300 packetdump_cb = wma_handle->wma_mgmt_rx_packetdump_cb;
Himanshu Agarwalf65bd4c2016-12-05 17:21:12 +05303301 if ((mgt_type == IEEE80211_FC0_TYPE_MGT &&
3302 mgt_subtype != IEEE80211_FC0_SUBTYPE_BEACON) &&
Himanshu Agarwalbb226bc2017-01-18 20:45:01 +05303303 packetdump_cb)
3304 packetdump_cb(rx_pkt->pkt_buf, QDF_STATUS_SUCCESS,
3305 rx_pkt->pkt_meta.sessionId, RX_MGMT_PKT);
Himanshu Agarwalf65bd4c2016-12-05 17:21:12 +05303306
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303307 return 0;
3308}
3309
3310/**
3311 * wma_mem_endianness_based_copy() - does memory copy from src to dst
3312 * @dst: destination address
3313 * @src: source address
3314 * @size: size to be copied
3315 *
3316 * This function copies the memory of size passed from source
3317 * address to destination address.
3318 *
3319 * Return: Nothing
3320 */
3321#ifdef BIG_ENDIAN_HOST
3322static void wma_mem_endianness_based_copy(
3323 uint8_t *dst, uint8_t *src, uint32_t size)
3324{
3325 /*
3326 * For big endian host, copy engine byte_swap is enabled
3327 * But the rx mgmt frame buffer content is in network byte order
3328 * Need to byte swap the mgmt frame buffer content - so when
3329 * copy engine does byte_swap - host gets buffer content in the
3330 * correct byte order.
3331 */
3332
3333 uint32_t i;
3334 uint32_t *destp, *srcp;
3335
3336 destp = (uint32_t *) dst;
3337 srcp = (uint32_t *) src;
3338 for (i = 0; i < (roundup(size, sizeof(uint32_t)) / 4); i++) {
3339 *destp = cpu_to_le32(*srcp);
3340 destp++;
3341 srcp++;
3342 }
3343}
3344#else
3345static void wma_mem_endianness_based_copy(
3346 uint8_t *dst, uint8_t *src, uint32_t size)
3347{
3348 qdf_mem_copy(dst, src, size);
3349}
3350#endif
3351
3352/**
3353 * wma_mgmt_rx_process() - process management rx frame.
3354 * @handle: wma handle
3355 * @data: rx data
3356 * @data_len: data length
3357 *
3358 * Return: 0 for success or error code
3359 */
3360static int wma_mgmt_rx_process(void *handle, uint8_t *data,
3361 uint32_t data_len)
3362{
3363 tp_wma_handle wma_handle = (tp_wma_handle) handle;
3364 wmi_host_mgmt_rx_hdr *mgmt_rx_params;
3365 struct wlan_objmgr_psoc *psoc;
3366 uint8_t *bufp;
3367 qdf_nbuf_t wbuf;
3368 QDF_STATUS status;
3369
3370 if (!wma_handle) {
3371 WMA_LOGE("%s: Failed to get WMA context", __func__);
3372 return -EINVAL;
3373 }
3374
3375 mgmt_rx_params = qdf_mem_malloc(sizeof(*mgmt_rx_params));
3376 if (!mgmt_rx_params) {
3377 WMA_LOGE("%s: memory allocation failed", __func__);
3378 return -ENOMEM;
3379 }
3380
3381 if (wmi_extract_mgmt_rx_params(wma_handle->wmi_handle,
3382 data, mgmt_rx_params, &bufp) != QDF_STATUS_SUCCESS) {
3383 WMA_LOGE("%s: Extraction of mgmt rx params failed", __func__);
3384 qdf_mem_free(mgmt_rx_params);
3385 return -EINVAL;
3386 }
3387
3388 wbuf = qdf_nbuf_alloc(NULL, roundup(mgmt_rx_params->buf_len, 4),
3389 0, 4, false);
3390 if (!wbuf) {
3391 WMA_LOGE("%s: Failed to allocate wbuf for mgmt rx len(%u)",
3392 __func__, mgmt_rx_params->buf_len);
3393 qdf_mem_free(mgmt_rx_params);
3394 return -ENOMEM;
3395 }
3396
3397 qdf_nbuf_put_tail(wbuf, mgmt_rx_params->buf_len);
3398 qdf_nbuf_set_protocol(wbuf, ETH_P_CONTROL);
3399
3400 wma_mem_endianness_based_copy(qdf_nbuf_data(wbuf),
3401 bufp, mgmt_rx_params->buf_len);
3402
3403 psoc = (struct wlan_objmgr_psoc *)
3404 wma_handle->psoc;
3405 if (!psoc) {
3406 WMA_LOGE("%s: psoc ctx is NULL", __func__);
3407 qdf_nbuf_free(wbuf);
3408 qdf_mem_free(mgmt_rx_params);
3409 return -EINVAL;
3410 }
3411
3412 if (!psoc->soc_cb.rx_ops.mgmt_txrx_rx_ops.mgmt_rx_frame_handler) {
3413 WMA_LOGE("%s: rx callback to mgmt txrx layer is NULL",
3414 __func__);
3415 qdf_nbuf_free(wbuf);
3416 qdf_mem_free(mgmt_rx_params);
3417 return -EINVAL;
3418 }
3419
3420 status = psoc->soc_cb.rx_ops.mgmt_txrx_rx_ops.mgmt_rx_frame_handler(
3421 psoc, wbuf, mgmt_rx_params);
3422
3423 if (status != QDF_STATUS_SUCCESS) {
3424 WMA_LOGE("%s: Failed to process mgmt rx frame", __func__);
3425 qdf_mem_free(mgmt_rx_params);
3426 return -EINVAL;
3427 }
3428
3429 qdf_mem_free(mgmt_rx_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003430 return 0;
3431}
3432
3433/**
3434 * wma_de_register_mgmt_frm_client() - deregister management frame
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303435 *
3436 * This function deregisters the event handler registered for
3437 * WMI_MGMT_RX_EVENTID.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003438 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303439 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003440 */
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303441QDF_STATUS wma_de_register_mgmt_frm_client(void)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003442{
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303443 tp_wma_handle wma_handle = (tp_wma_handle)
3444 cds_get_context(QDF_MODULE_ID_WMA);
3445
3446 if (!wma_handle) {
3447 WMA_LOGE("%s: Failed to get WMA context", __func__);
3448 return QDF_STATUS_E_NULL_VALUE;
3449 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003450
3451#ifdef QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +05303452 if (cds_get_conparam() == QDF_GLOBAL_FTM_MODE)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303453 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003454#endif
3455
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003456 if (wmi_unified_unregister_event_handler(wma_handle->wmi_handle,
3457 WMI_MGMT_RX_EVENTID) != 0) {
3458 WMA_LOGE("Failed to Unregister rx mgmt handler with wmi");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303459 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003460 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303461 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003462}
3463
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003464#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003465/**
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003466 * wma_register_roaming_callbacks() - Register roaming callbacks
3467 * @cds_ctx: CDS Context
3468 * @csr_roam_synch_cb: CSR roam synch callback routine pointer
3469 * @pe_roam_synch_cb: PE roam synch callback routine pointer
3470 *
3471 * Register the SME and PE callback routines with WMA for
3472 * handling roaming
3473 *
3474 * Return: Success or Failure Status
3475 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303476QDF_STATUS wma_register_roaming_callbacks(void *cds_ctx,
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003477 void (*csr_roam_synch_cb)(tpAniSirGlobal mac,
3478 roam_offload_synch_ind *roam_synch_data,
Varun Reddy Yeturuf907f912016-03-21 15:06:22 -07003479 tpSirBssDescription bss_desc_ptr,
3480 enum sir_roam_op_code reason),
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303481 QDF_STATUS (*pe_roam_synch_cb)(tpAniSirGlobal mac,
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003482 roam_offload_synch_ind *roam_synch_data,
3483 tpSirBssDescription bss_desc_ptr))
3484{
3485
Anurag Chouhan6d760662016-02-20 16:05:43 +05303486 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003487
3488 if (!wma) {
3489 WMA_LOGE("%s: Failed to get WMA context", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303490 return QDF_STATUS_E_FAILURE;
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003491 }
3492 wma->csr_roam_synch_cb = csr_roam_synch_cb;
3493 wma->pe_roam_synch_cb = pe_roam_synch_cb;
3494 WMA_LOGD("Registered roam synch callbacks with WMA successfully");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303495 return QDF_STATUS_SUCCESS;
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003496}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003497#endif
3498
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003499/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003500 * wma_register_mgmt_frm_client() - register management frame callback
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303501 *
3502 * This function registers event handler for WMI_MGMT_RX_EVENTID.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003503 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303504 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003505 */
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303506QDF_STATUS wma_register_mgmt_frm_client(void)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003507{
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303508 tp_wma_handle wma_handle = (tp_wma_handle)
3509 cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003510
3511 if (!wma_handle) {
3512 WMA_LOGE("%s: Failed to get WMA context", __func__);
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303513 return QDF_STATUS_E_NULL_VALUE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003514 }
3515
3516 if (wmi_unified_register_event_handler(wma_handle->wmi_handle,
3517 WMI_MGMT_RX_EVENTID,
Govind Singhd76a5b02016-03-08 15:12:14 +05303518 wma_mgmt_rx_process,
3519 WMA_RX_WORK_CTX) != 0) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003520 WMA_LOGE("Failed to register rx mgmt handler with wmi");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303521 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003522 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003523
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303524 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003525}
Himanshu Agarwalf65bd4c2016-12-05 17:21:12 +05303526
3527/**
3528 * wma_register_packetdump_callback() - stores tx and rx mgmt packet dump
3529 * callback handler
3530 * @wma_mgmt_tx_packetdump_cb: tx mgmt packetdump cb
3531 * @wma_mgmt_rx_packetdump_cb: rx mgmt packetdump cb
3532 *
3533 * This function is used to store tx and rx mgmt. packet dump callback
3534 *
3535 * Return: None
3536 *
3537 */
3538void wma_register_packetdump_callback(
3539 tp_wma_packetdump_cb wma_mgmt_tx_packetdump_cb,
3540 tp_wma_packetdump_cb wma_mgmt_rx_packetdump_cb)
3541{
3542 tp_wma_handle wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
3543
3544 if (!wma_handle) {
3545 WMA_LOGE("wma handle is NULL");
3546 return;
3547 }
3548
3549 wma_handle->wma_mgmt_tx_packetdump_cb = wma_mgmt_tx_packetdump_cb;
3550 wma_handle->wma_mgmt_rx_packetdump_cb = wma_mgmt_rx_packetdump_cb;
3551}
3552
3553/**
3554 * wma_deregister_packetdump_callback() - removes tx and rx mgmt packet dump
3555 * callback handler
3556 *
3557 * This function is used to remove tx and rx mgmt. packet dump callback
3558 *
3559 * Return: None
3560 *
3561 */
3562void wma_deregister_packetdump_callback(void)
3563{
3564 tp_wma_handle wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
3565
3566 if (!wma_handle) {
3567 WMA_LOGE("wma handle is NULL");
3568 return;
3569 }
3570
3571 wma_handle->wma_mgmt_tx_packetdump_cb = NULL;
3572 wma_handle->wma_mgmt_rx_packetdump_cb = NULL;
3573}
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303574
3575QDF_STATUS wma_mgmt_unified_cmd_send(struct wlan_objmgr_vdev *vdev,
3576 qdf_nbuf_t buf, uint32_t desc_id,
3577 void *mgmt_tx_params)
3578{
3579 tp_wma_handle wma_handle;
3580 QDF_STATUS status;
3581 struct wmi_mgmt_params *mgmt_params =
3582 (struct wmi_mgmt_params *)mgmt_tx_params;
3583
3584 if (!mgmt_params) {
3585 WMA_LOGE("%s: mgmt_params ptr passed is NULL", __func__);
3586 return QDF_STATUS_E_INVAL;
3587 }
3588 mgmt_params->desc_id = desc_id;
3589
3590 if (!vdev) {
3591 WMA_LOGE("%s: vdev ptr passed is NULL", __func__);
3592 return QDF_STATUS_E_INVAL;
3593 }
3594
3595 wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
3596 if (!wma_handle) {
3597 WMA_LOGE("%s: wma handle is NULL", __func__);
3598 return QDF_STATUS_E_INVAL;
3599 }
3600
3601 status = wmi_mgmt_unified_cmd_send(wma_handle->wmi_handle,
3602 mgmt_params);
3603 if (status != QDF_STATUS_SUCCESS) {
3604 WMA_LOGE("%s: mgmt tx failed", __func__);
3605 return status;
3606 }
3607
3608 return QDF_STATUS_SUCCESS;
3609}
3610