blob: 0193a693dae402bc8d37d2822b2509d9fe689fc7 [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"
Himanshu Agarwal795b7f72017-01-17 21:19:43 +053078#include "wlan_lmac_if_api.h"
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +053079
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080080
81/**
82 * wma_send_bcn_buf_ll() - prepare and send beacon buffer to fw for LL
83 * @wma: wma handle
84 * @pdev: txrx pdev
85 * @vdev_id: vdev id
86 * @param_buf: SWBA parameters
87 *
88 * Return: none
89 */
90static void wma_send_bcn_buf_ll(tp_wma_handle wma,
Leo Chang96464902016-10-28 11:10:54 -070091 void *pdev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080092 uint8_t vdev_id,
93 WMI_HOST_SWBA_EVENTID_param_tlvs *param_buf)
94{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080095 struct ieee80211_frame *wh;
96 struct beacon_info *bcn;
97 wmi_tim_info *tim_info = param_buf->tim_info;
98 uint8_t *bcn_payload;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053099 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800100 struct beacon_tim_ie *tim_ie;
101 wmi_p2p_noa_info *p2p_noa_info = param_buf->p2p_noa_info;
102 struct p2p_sub_element_noa noa_ie;
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530103 struct wmi_bcn_send_from_host params;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800104 uint8_t i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800105
106 bcn = wma->interfaces[vdev_id].beacon;
107 if (!bcn->buf) {
108 WMA_LOGE("%s: Invalid beacon buffer", __func__);
109 return;
110 }
111
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530112 qdf_spin_lock_bh(&bcn->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800113
Nirav Shahcbc6d722016-03-01 16:24:53 +0530114 bcn_payload = qdf_nbuf_data(bcn->buf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800115
116 tim_ie = (struct beacon_tim_ie *)(&bcn_payload[bcn->tim_ie_offset]);
117
118 if (tim_info->tim_changed) {
119 if (tim_info->tim_num_ps_pending)
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530120 qdf_mem_copy(&tim_ie->tim_bitmap, tim_info->tim_bitmap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800121 WMA_TIM_SUPPORTED_PVB_LENGTH);
122 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530123 qdf_mem_zero(&tim_ie->tim_bitmap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800124 WMA_TIM_SUPPORTED_PVB_LENGTH);
125 /*
126 * Currently we support fixed number of
127 * peers as limited by HAL_NUM_STA.
128 * tim offset is always 0
129 */
130 tim_ie->tim_bitctl = 0;
131 }
132
133 /* Update DTIM Count */
134 if (tim_ie->dtim_count == 0)
135 tim_ie->dtim_count = tim_ie->dtim_period - 1;
136 else
137 tim_ie->dtim_count--;
138
139 /*
140 * DTIM count needs to be backedup so that
141 * when umac updates the beacon template
142 * current dtim count can be updated properly
143 */
144 bcn->dtim_count = tim_ie->dtim_count;
145
146 /* update state for buffered multicast frames on DTIM */
147 if (tim_info->tim_mcast && (tim_ie->dtim_count == 0 ||
148 tim_ie->dtim_period == 1))
149 tim_ie->tim_bitctl |= 1;
150 else
151 tim_ie->tim_bitctl &= ~1;
152
153 /* To avoid sw generated frame sequence the same as H/W generated frame,
154 * the value lower than min_sw_seq is reserved for HW generated frame */
155 if ((bcn->seq_no & IEEE80211_SEQ_MASK) < MIN_SW_SEQ)
156 bcn->seq_no = MIN_SW_SEQ;
157
158 wh = (struct ieee80211_frame *)bcn_payload;
159 *(uint16_t *) &wh->i_seq[0] = htole16(bcn->seq_no
160 << IEEE80211_SEQ_SEQ_SHIFT);
161 bcn->seq_no++;
162
163 if (WMI_UNIFIED_NOA_ATTR_IS_MODIFIED(p2p_noa_info)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530164 qdf_mem_zero(&noa_ie, sizeof(noa_ie));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800165
166 noa_ie.index =
167 (uint8_t) WMI_UNIFIED_NOA_ATTR_INDEX_GET(p2p_noa_info);
168 noa_ie.oppPS =
169 (uint8_t) WMI_UNIFIED_NOA_ATTR_OPP_PS_GET(p2p_noa_info);
170 noa_ie.ctwindow =
171 (uint8_t) WMI_UNIFIED_NOA_ATTR_CTWIN_GET(p2p_noa_info);
172 noa_ie.num_descriptors =
173 (uint8_t) WMI_UNIFIED_NOA_ATTR_NUM_DESC_GET(p2p_noa_info);
174 WMA_LOGI("%s: index %u, oppPs %u, ctwindow %u, "
175 "num_descriptors = %u", __func__, noa_ie.index,
176 noa_ie.oppPS, noa_ie.ctwindow, noa_ie.num_descriptors);
177 for (i = 0; i < noa_ie.num_descriptors; i++) {
178 noa_ie.noa_descriptors[i].type_count =
179 (uint8_t) p2p_noa_info->noa_descriptors[i].
180 type_count;
181 noa_ie.noa_descriptors[i].duration =
182 p2p_noa_info->noa_descriptors[i].duration;
183 noa_ie.noa_descriptors[i].interval =
184 p2p_noa_info->noa_descriptors[i].interval;
185 noa_ie.noa_descriptors[i].start_time =
186 p2p_noa_info->noa_descriptors[i].start_time;
187 WMA_LOGI("%s: NoA descriptor[%d] type_count %u, "
188 "duration %u, interval %u, start_time = %u",
189 __func__, i,
190 noa_ie.noa_descriptors[i].type_count,
191 noa_ie.noa_descriptors[i].duration,
192 noa_ie.noa_descriptors[i].interval,
193 noa_ie.noa_descriptors[i].start_time);
194 }
195 wma_update_noa(bcn, &noa_ie);
196
197 /* Send a msg to LIM to update the NoA IE in probe response
198 * frames transmitted by the host */
199 wma_update_probe_resp_noa(wma, &noa_ie);
200 }
201
202 if (bcn->dma_mapped) {
Leo Chang96464902016-10-28 11:10:54 -0700203 qdf_nbuf_unmap_single(wma->qdf_dev, bcn->buf, QDF_DMA_TO_DEVICE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800204 bcn->dma_mapped = 0;
205 }
Leo Chang96464902016-10-28 11:10:54 -0700206 ret = qdf_nbuf_map_single(wma->qdf_dev, bcn->buf, QDF_DMA_TO_DEVICE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530207 if (ret != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800208 WMA_LOGE("%s: failed map beacon buf to DMA region", __func__);
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530209 qdf_spin_unlock_bh(&bcn->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800210 return;
211 }
212
213 bcn->dma_mapped = 1;
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530214 params.vdev_id = vdev_id;
215 params.data_len = bcn->len;
216 params.frame_ctrl = *((A_UINT16 *) wh->i_fc);
217 params.frag_ptr = qdf_nbuf_get_frag_paddr(bcn->buf, 0);
218 params.dtim_flag = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800219 /* notify Firmware of DTM and mcast/bcast traffic */
220 if (tim_ie->dtim_count == 0) {
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530221 params.dtim_flag |= WMI_BCN_SEND_DTIM_ZERO;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800222 /* deliver mcast/bcast traffic in next DTIM beacon */
223 if (tim_ie->tim_bitctl & 0x01)
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530224 params.dtim_flag |= WMI_BCN_SEND_DTIM_BITCTL_SET;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800225 }
226
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530227 wmi_unified_bcn_buf_ll_cmd(wma->wmi_handle,
228 &params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800229
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530230 qdf_spin_unlock_bh(&bcn->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800231}
232
233/**
234 * wma_beacon_swba_handler() - swba event handler
235 * @handle: wma handle
236 * @event: event data
237 * @len: data length
238 *
239 * SWBA event is alert event to Host requesting host to Queue a beacon
240 * for transmission use only in host beacon mode
241 *
242 * Return: 0 for success or error code
243 */
244int wma_beacon_swba_handler(void *handle, uint8_t *event, uint32_t len)
245{
246 tp_wma_handle wma = (tp_wma_handle) handle;
247 WMI_HOST_SWBA_EVENTID_param_tlvs *param_buf;
248 wmi_host_swba_event_fixed_param *swba_event;
249 uint32_t vdev_map;
Leo Chang96464902016-10-28 11:10:54 -0700250 void *pdev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800251 uint8_t vdev_id = 0;
Leo Chang96464902016-10-28 11:10:54 -0700252 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800253
254 param_buf = (WMI_HOST_SWBA_EVENTID_param_tlvs *) event;
255 if (!param_buf) {
256 WMA_LOGE("Invalid swba event buffer");
257 return -EINVAL;
258 }
259 swba_event = param_buf->fixed_param;
260 vdev_map = swba_event->vdev_map;
261
Anurag Chouhan6d760662016-02-20 16:05:43 +0530262 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800263 if (!pdev) {
264 WMA_LOGE("%s: pdev is NULL", __func__);
265 return -EINVAL;
266 }
267
268 for (; vdev_map; vdev_id++, vdev_map >>= 1) {
269 if (!(vdev_map & 0x1))
270 continue;
Leo Chang96464902016-10-28 11:10:54 -0700271 if (!cdp_cfg_is_high_latency(soc,
272 cds_get_context(QDF_MODULE_ID_CFG)))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800273 wma_send_bcn_buf_ll(wma, pdev, vdev_id, param_buf);
274 break;
275 }
276 return 0;
277}
278
279/**
280 * wma_peer_sta_kickout_event_handler() - kickout event handler
281 * @handle: wma handle
282 * @event: event data
283 * @len: data length
284 *
285 * Kickout event is received from firmware on observing beacon miss
286 * It handles kickout event for different modes and indicate to
287 * upper layers.
288 *
289 * Return: 0 for success or error code
290 */
291int wma_peer_sta_kickout_event_handler(void *handle, u8 *event, u32 len)
292{
293 tp_wma_handle wma = (tp_wma_handle) handle;
294 WMI_PEER_STA_KICKOUT_EVENTID_param_tlvs *param_buf = NULL;
295 wmi_peer_sta_kickout_event_fixed_param *kickout_event = NULL;
296 uint8_t vdev_id, peer_id, macaddr[IEEE80211_ADDR_LEN];
Leo Chang96464902016-10-28 11:10:54 -0700297 void *peer;
298 void *pdev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800299 tpDeleteStaContext del_sta_ctx;
300 tpSirIbssPeerInactivityInd p_inactivity;
Leo Chang96464902016-10-28 11:10:54 -0700301 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800302
303 WMA_LOGD("%s: Enter", __func__);
304 param_buf = (WMI_PEER_STA_KICKOUT_EVENTID_param_tlvs *) event;
305 kickout_event = param_buf->fixed_param;
Anurag Chouhan6d760662016-02-20 16:05:43 +0530306 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800307 if (!pdev) {
308 WMA_LOGE("%s: pdev is NULL", __func__);
309 return -EINVAL;
310 }
311 WMI_MAC_ADDR_TO_CHAR_ARRAY(&kickout_event->peer_macaddr, macaddr);
Leo Chang96464902016-10-28 11:10:54 -0700312 peer = cdp_peer_find_by_addr(soc, pdev, macaddr, &peer_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800313 if (!peer) {
314 WMA_LOGE("PEER [%pM] not found", macaddr);
315 return -EINVAL;
316 }
317
Leo Chang96464902016-10-28 11:10:54 -0700318 if (cdp_peer_get_vdevid(soc, peer, &vdev_id) != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800319 WMA_LOGE("Not able to find BSSID for peer [%pM]", macaddr);
320 return -EINVAL;
321 }
322
323 WMA_LOGA("%s: PEER:[%pM], ADDR:[%pN], INTERFACE:%d, peer_id:%d, reason:%d",
324 __func__, macaddr, wma->interfaces[vdev_id].addr, vdev_id,
325 peer_id, kickout_event->reason);
Varun Reddy Yeturu30bc42c2016-02-04 10:07:30 -0800326 if (wma->interfaces[vdev_id].roaming_in_progress) {
327 WMA_LOGE("Ignore STA kick out since roaming is in progress");
328 return -EINVAL;
329 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800330
331 switch (kickout_event->reason) {
332 case WMI_PEER_STA_KICKOUT_REASON_IBSS_DISCONNECT:
333 p_inactivity = (tpSirIbssPeerInactivityInd)
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530334 qdf_mem_malloc(sizeof(tSirIbssPeerInactivityInd));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800335 if (!p_inactivity) {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530336 WMA_LOGE("QDF MEM Alloc Failed for tSirIbssPeerInactivity");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800337 return -ENOMEM;
338 }
339
340 p_inactivity->staIdx = peer_id;
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530341 qdf_mem_copy(p_inactivity->peer_addr.bytes, macaddr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800342 IEEE80211_ADDR_LEN);
343 wma_send_msg(wma, WMA_IBSS_PEER_INACTIVITY_IND,
344 (void *)p_inactivity, 0);
345 goto exit_handler;
346 break;
347
348#ifdef FEATURE_WLAN_TDLS
349 case WMI_PEER_STA_KICKOUT_REASON_TDLS_DISCONNECT:
350 del_sta_ctx = (tpDeleteStaContext)
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530351 qdf_mem_malloc(sizeof(tDeleteStaContext));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800352 if (!del_sta_ctx) {
353 WMA_LOGE("%s: mem alloc failed for tDeleteStaContext for TDLS peer: %pM",
354 __func__, macaddr);
355 return -ENOMEM;
356 }
357
Naveen Rawat9801ac02016-06-22 11:02:50 -0700358 del_sta_ctx->is_tdls = true;
359 del_sta_ctx->vdev_id = vdev_id;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800360 del_sta_ctx->staId = peer_id;
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530361 qdf_mem_copy(del_sta_ctx->addr2, macaddr, IEEE80211_ADDR_LEN);
362 qdf_mem_copy(del_sta_ctx->bssId, wma->interfaces[vdev_id].bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800363 IEEE80211_ADDR_LEN);
364 del_sta_ctx->reasonCode = HAL_DEL_STA_REASON_CODE_KEEP_ALIVE;
365 wma_send_msg(wma, SIR_LIM_DELETE_STA_CONTEXT_IND,
366 (void *)del_sta_ctx, 0);
367 goto exit_handler;
368 break;
369#endif /* FEATURE_WLAN_TDLS */
370
371 case WMI_PEER_STA_KICKOUT_REASON_XRETRY:
372 if (wma->interfaces[vdev_id].type == WMI_VDEV_TYPE_STA &&
373 (wma->interfaces[vdev_id].sub_type == 0 ||
374 wma->interfaces[vdev_id].sub_type ==
375 WMI_UNIFIED_VDEV_SUBTYPE_P2P_CLIENT) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530376 !qdf_mem_cmp(wma->interfaces[vdev_id].bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800377 macaddr, IEEE80211_ADDR_LEN)) {
378 /*
379 * KICKOUT event is for current station-AP connection.
380 * Treat it like final beacon miss. Station may not have
381 * missed beacons but not able to transmit frames to AP
382 * for a long time. Must disconnect to get out of
383 * this sticky situation.
384 * In future implementation, roaming module will also
385 * handle this event and perform a scan.
386 */
387 WMA_LOGW("%s: WMI_PEER_STA_KICKOUT_REASON_XRETRY event for STA",
388 __func__);
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +0530389 wma_beacon_miss_handler(wma, vdev_id,
390 kickout_event->rssi);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800391 goto exit_handler;
392 }
393 break;
394
395 case WMI_PEER_STA_KICKOUT_REASON_UNSPECIFIED:
396 /*
397 * Default legacy value used by original firmware implementation.
398 */
399 if (wma->interfaces[vdev_id].type == WMI_VDEV_TYPE_STA &&
400 (wma->interfaces[vdev_id].sub_type == 0 ||
401 wma->interfaces[vdev_id].sub_type ==
402 WMI_UNIFIED_VDEV_SUBTYPE_P2P_CLIENT) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530403 !qdf_mem_cmp(wma->interfaces[vdev_id].bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800404 macaddr, IEEE80211_ADDR_LEN)) {
405 /*
406 * KICKOUT event is for current station-AP connection.
407 * Treat it like final beacon miss. Station may not have
408 * missed beacons but not able to transmit frames to AP
409 * for a long time. Must disconnect to get out of
410 * this sticky situation.
411 * In future implementation, roaming module will also
412 * handle this event and perform a scan.
413 */
414 WMA_LOGW("%s: WMI_PEER_STA_KICKOUT_REASON_UNSPECIFIED event for STA",
415 __func__);
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +0530416 wma_beacon_miss_handler(wma, vdev_id,
417 kickout_event->rssi);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800418 goto exit_handler;
419 }
420 break;
421
422 case WMI_PEER_STA_KICKOUT_REASON_INACTIVITY:
Naveen Rawat9801ac02016-06-22 11:02:50 -0700423 /*
424 * Handle SA query kickout is same as inactivity kickout.
425 * This could be for STA or SAP role
426 */
mukul sharma72c8b222015-09-04 17:02:01 +0530427 case WMI_PEER_STA_KICKOUT_REASON_SA_QUERY_TIMEOUT:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800428 default:
429 break;
430 }
431
432 /*
433 * default action is to send delete station context indication to LIM
434 */
435 del_sta_ctx =
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530436 (tpDeleteStaContext) qdf_mem_malloc(sizeof(tDeleteStaContext));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800437 if (!del_sta_ctx) {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530438 WMA_LOGE("QDF MEM Alloc Failed for tDeleteStaContext");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800439 return -ENOMEM;
440 }
441
Naveen Rawat9801ac02016-06-22 11:02:50 -0700442 del_sta_ctx->is_tdls = false;
443 del_sta_ctx->vdev_id = vdev_id;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800444 del_sta_ctx->staId = peer_id;
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530445 qdf_mem_copy(del_sta_ctx->addr2, macaddr, IEEE80211_ADDR_LEN);
446 qdf_mem_copy(del_sta_ctx->bssId, wma->interfaces[vdev_id].addr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800447 IEEE80211_ADDR_LEN);
448 del_sta_ctx->reasonCode = HAL_DEL_STA_REASON_CODE_KEEP_ALIVE;
Kiran Kumar Lokere37d3aa22015-11-03 14:58:26 -0800449 del_sta_ctx->rssi = kickout_event->rssi + WMA_TGT_NOISE_FLOOR_DBM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800450 wma_send_msg(wma, SIR_LIM_DELETE_STA_CONTEXT_IND, (void *)del_sta_ctx,
451 0);
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +0530452 wma_lost_link_info_handler(wma, vdev_id, kickout_event->rssi +
453 WMA_TGT_NOISE_FLOOR_DBM);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800454exit_handler:
455 WMA_LOGD("%s: Exit", __func__);
456 return 0;
457}
458
459/**
460 * wma_unified_bcntx_status_event_handler() - beacon tx status event handler
461 * @handle: wma handle
462 * @cmd_param_info: event data
463 * @len: data length
464 *
465 * WMI Handler for WMI_OFFLOAD_BCN_TX_STATUS_EVENTID event from firmware.
466 * This event is generated by FW when the beacon transmission is offloaded
467 * and the host performs beacon template modification using WMI_BCN_TMPL_CMDID
468 * The FW generates this event when the first successful beacon transmission
469 * after template update
470 *
471 * Return: 0 for success or error code
472 */
473int wma_unified_bcntx_status_event_handler(void *handle,
474 uint8_t *cmd_param_info,
475 uint32_t len)
476{
477 tp_wma_handle wma = (tp_wma_handle) handle;
478 WMI_OFFLOAD_BCN_TX_STATUS_EVENTID_param_tlvs *param_buf;
479 wmi_offload_bcn_tx_status_event_fixed_param *resp_event;
480 tSirFirstBeaconTxCompleteInd *beacon_tx_complete_ind;
481
482 param_buf =
483 (WMI_OFFLOAD_BCN_TX_STATUS_EVENTID_param_tlvs *) cmd_param_info;
484 if (!param_buf) {
485 WMA_LOGE("Invalid bcn tx response event buffer");
486 return -EINVAL;
487 }
488
489 resp_event = param_buf->fixed_param;
490
Chandrasekaran, Manishekarce2172e2016-02-18 16:12:43 +0530491 WMA_LOGD("%s", __func__);
492
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800493 /* Check for valid handle to ensure session is not
494 * deleted in any race
495 */
496 if (!wma->interfaces[resp_event->vdev_id].handle) {
497 WMA_LOGE("%s: The session does not exist", __func__);
498 return -EINVAL;
499 }
500
501 /* Beacon Tx Indication supports only AP mode. Ignore in other modes */
502 if (wma_is_vdev_in_ap_mode(wma, resp_event->vdev_id) == false) {
503 WMA_LOGI("%s: Beacon Tx Indication does not support type %d and sub_type %d",
504 __func__, wma->interfaces[resp_event->vdev_id].type,
505 wma->interfaces[resp_event->vdev_id].sub_type);
506 return 0;
507 }
508
509 beacon_tx_complete_ind = (tSirFirstBeaconTxCompleteInd *)
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530510 qdf_mem_malloc(sizeof(tSirFirstBeaconTxCompleteInd));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800511 if (!beacon_tx_complete_ind) {
512 WMA_LOGE("%s: Failed to alloc beacon_tx_complete_ind",
513 __func__);
514 return -ENOMEM;
515 }
516
517 beacon_tx_complete_ind->messageType = WMA_DFS_BEACON_TX_SUCCESS_IND;
518 beacon_tx_complete_ind->length = sizeof(tSirFirstBeaconTxCompleteInd);
519 beacon_tx_complete_ind->bssIdx = resp_event->vdev_id;
520
521 wma_send_msg(wma, WMA_DFS_BEACON_TX_SUCCESS_IND,
522 (void *)beacon_tx_complete_ind, 0);
523 return 0;
524}
525
526/**
527 * wma_get_link_probe_timeout() - get link timeout based on sub type
528 * @mac: UMAC handler
529 * @sub_type: vdev syb type
530 * @max_inactive_time: return max inactive time
531 * @max_unresponsive_time: return max unresponsive time
532 *
533 * Return: none
534 */
535static inline void wma_get_link_probe_timeout(struct sAniSirGlobal *mac,
536 uint32_t sub_type,
537 uint32_t *max_inactive_time,
538 uint32_t *max_unresponsive_time)
539{
540 uint32_t keep_alive;
541 uint16_t lm_id, ka_id;
542
543 switch (sub_type) {
544 case WMI_UNIFIED_VDEV_SUBTYPE_P2P_GO:
545 lm_id = WNI_CFG_GO_LINK_MONITOR_TIMEOUT;
546 ka_id = WNI_CFG_GO_KEEP_ALIVE_TIMEOUT;
547 break;
548 default:
549 /*For softAp the subtype value will be zero */
550 lm_id = WNI_CFG_AP_LINK_MONITOR_TIMEOUT;
551 ka_id = WNI_CFG_AP_KEEP_ALIVE_TIMEOUT;
552 }
553
554 if (wlan_cfg_get_int(mac, lm_id, max_inactive_time) != eSIR_SUCCESS) {
555 WMA_LOGE("Failed to read link monitor for subtype %d",
556 sub_type);
557 *max_inactive_time = WMA_LINK_MONITOR_DEFAULT_TIME_SECS;
558 }
559
560 if (wlan_cfg_get_int(mac, ka_id, &keep_alive) != eSIR_SUCCESS) {
561 WMA_LOGE("Failed to read keep alive for subtype %d", sub_type);
562 keep_alive = WMA_KEEP_ALIVE_DEFAULT_TIME_SECS;
563 }
564 *max_unresponsive_time = *max_inactive_time + keep_alive;
565}
566
567/**
568 * wma_set_sap_keepalive() - set SAP keep alive parameters to fw
569 * @wma: wma handle
570 * @vdev_id: vdev id
571 *
572 * Return: none
573 */
574void wma_set_sap_keepalive(tp_wma_handle wma, uint8_t vdev_id)
575{
576 uint32_t min_inactive_time, max_inactive_time, max_unresponsive_time;
Anurag Chouhan6d760662016-02-20 16:05:43 +0530577 struct sAniSirGlobal *mac = cds_get_context(QDF_MODULE_ID_PE);
Govind Singhd76a5b02016-03-08 15:12:14 +0530578 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800579
580 if (NULL == mac) {
581 WMA_LOGE("%s: Failed to get mac", __func__);
582 return;
583 }
584
585 wma_get_link_probe_timeout(mac, wma->interfaces[vdev_id].sub_type,
586 &max_inactive_time, &max_unresponsive_time);
587
588 min_inactive_time = max_inactive_time / 2;
589
Govind Singhd76a5b02016-03-08 15:12:14 +0530590 status = wma_vdev_set_param(wma->wmi_handle,
591 vdev_id,
592 WMI_VDEV_PARAM_AP_KEEPALIVE_MIN_IDLE_INACTIVE_TIME_SECS,
593 min_inactive_time);
594 if (QDF_IS_STATUS_ERROR(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800595 WMA_LOGE("Failed to Set AP MIN IDLE INACTIVE TIME");
596
Govind Singhd76a5b02016-03-08 15:12:14 +0530597 status = wma_vdev_set_param(wma->wmi_handle,
598 vdev_id,
599 WMI_VDEV_PARAM_AP_KEEPALIVE_MAX_IDLE_INACTIVE_TIME_SECS,
600 max_inactive_time);
601 if (QDF_IS_STATUS_ERROR(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800602 WMA_LOGE("Failed to Set AP MAX IDLE INACTIVE TIME");
603
Govind Singhd76a5b02016-03-08 15:12:14 +0530604 status = wma_vdev_set_param(wma->wmi_handle,
605 vdev_id,
606 WMI_VDEV_PARAM_AP_KEEPALIVE_MAX_UNRESPONSIVE_TIME_SECS,
607 max_unresponsive_time);
608 if (QDF_IS_STATUS_ERROR(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800609 WMA_LOGE("Failed to Set MAX UNRESPONSIVE TIME");
610
611 WMA_LOGD("%s:vdev_id:%d min_inactive_time: %u max_inactive_time: %u"
612 " max_unresponsive_time: %u", __func__, vdev_id,
613 min_inactive_time, max_inactive_time, max_unresponsive_time);
614}
615
616/**
mukul sharma72c8b222015-09-04 17:02:01 +0530617 * wma_set_sta_sa_query_param() - set sta sa query parameters
618 * @wma: wma handle
619 * @vdev_id: vdev id
620
621 * This function sets sta query related parameters in fw.
622 *
623 * Return: none
624 */
625
626void wma_set_sta_sa_query_param(tp_wma_handle wma,
627 uint8_t vdev_id)
628{
Anurag Chouhan6d760662016-02-20 16:05:43 +0530629 struct sAniSirGlobal *mac = cds_get_context(QDF_MODULE_ID_PE);
mukul sharma72c8b222015-09-04 17:02:01 +0530630 uint32_t max_retries, retry_interval;
mukul sharma72c8b222015-09-04 17:02:01 +0530631
632 WMA_LOGD(FL("Enter:"));
mukul sharma72c8b222015-09-04 17:02:01 +0530633
634 if (wlan_cfg_get_int
635 (mac, WNI_CFG_PMF_SA_QUERY_MAX_RETRIES,
636 &max_retries) != eSIR_SUCCESS) {
637 max_retries = DEFAULT_STA_SA_QUERY_MAX_RETRIES_COUNT;
638 WMA_LOGE(FL("Failed to get value for WNI_CFG_PMF_SA_QUERY_MAX_RETRIES"));
639 }
640 if (wlan_cfg_get_int
641 (mac, WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL,
642 &retry_interval) != eSIR_SUCCESS) {
643 retry_interval = DEFAULT_STA_SA_QUERY_RETRY_INTERVAL;
644 WMA_LOGE(FL("Failed to get value for WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL"));
645 }
646
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530647 wmi_unified_set_sta_sa_query_param_cmd(wma->wmi_handle,
648 vdev_id,
649 max_retries,
650 retry_interval);
mukul sharma72c8b222015-09-04 17:02:01 +0530651
652 WMA_LOGD(FL("Exit :"));
653 return;
654}
655
656/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800657 * wma_set_sta_keep_alive() - set sta keep alive parameters
658 * @wma: wma handle
659 * @vdev_id: vdev id
660 * @method: method for keep alive
661 * @timeperiod: time period
662 * @hostv4addr: host ipv4 address
663 * @destv4addr: dst ipv4 address
664 * @destmac: destination mac
665 *
666 * This function sets keep alive related parameters in fw.
667 *
668 * Return: none
669 */
670void wma_set_sta_keep_alive(tp_wma_handle wma, uint8_t vdev_id,
671 uint32_t method, uint32_t timeperiod,
672 uint8_t *hostv4addr, uint8_t *destv4addr,
673 uint8_t *destmac)
674{
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530675 struct sta_params params;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800676
677 WMA_LOGD("%s: Enter", __func__);
678
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530679 if (!wma) {
680 WMA_LOGE("%s: wma handle is NULL", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800681 return;
682 }
683
Govind Singhfe9ab252016-06-21 14:35:35 +0530684 if (timeperiod > WNI_CFG_INFRA_STA_KEEP_ALIVE_PERIOD_STAMAX) {
685 WMI_LOGE("Invalid period %d Max limit %d", timeperiod,
686 WNI_CFG_INFRA_STA_KEEP_ALIVE_PERIOD_STAMAX);
687 return;
688 }
689
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530690 params.vdev_id = vdev_id;
691 params.method = method;
692 params.timeperiod = timeperiod;
693 params.hostv4addr = hostv4addr;
694 params.destv4addr = destv4addr;
695 params.destmac = destmac;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800696
Himanshu Agarwal009f1572016-03-09 17:26:02 +0530697 wmi_unified_set_sta_keep_alive_cmd(wma->wmi_handle,
698 &params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800699
700 WMA_LOGD("%s: Exit", __func__);
701 return;
702}
703
704/**
705 * wma_vdev_install_key_complete_event_handler() - install key complete handler
706 * @handle: wma handle
707 * @event: event data
708 * @len: data length
709 *
710 * This event is sent by fw once WPA/WPA2 keys are installed in fw.
711 *
712 * Return: 0 for success or error code
713 */
714int wma_vdev_install_key_complete_event_handler(void *handle,
715 uint8_t *event,
716 uint32_t len)
717{
718 WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID_param_tlvs *param_buf = NULL;
719 wmi_vdev_install_key_complete_event_fixed_param *key_fp = NULL;
720
721 if (!event) {
722 WMA_LOGE("%s: event param null", __func__);
723 return -EINVAL;
724 }
725
726 param_buf = (WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID_param_tlvs *) event;
727 if (!param_buf) {
728 WMA_LOGE("%s: received null buf from target", __func__);
729 return -EINVAL;
730 }
731
732 key_fp = param_buf->fixed_param;
733 if (!key_fp) {
734 WMA_LOGE("%s: received null event data from target", __func__);
735 return -EINVAL;
736 }
737 /*
738 * Do nothing for now. Completion of set key is already indicated to lim
739 */
740 WMA_LOGI("%s: WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID", __func__);
741 return 0;
742}
743/*
744 * 802.11n D2.0 defined values for "Minimum MPDU Start Spacing":
745 * 0 for no restriction
746 * 1 for 1/4 us - Our lower layer calculations limit our precision to 1 msec
747 * 2 for 1/2 us - Our lower layer calculations limit our precision to 1 msec
748 * 3 for 1 us
749 * 4 for 2 us
750 * 5 for 4 us
751 * 6 for 8 us
752 * 7 for 16 us
753 */
754static const uint8_t wma_mpdu_spacing[] = { 0, 1, 1, 1, 2, 4, 8, 16 };
755
756/**
757 * wma_parse_mpdudensity() - give mpdu spacing from mpdu density
758 * @mpdudensity: mpdu density
759 *
760 * Return: mpdu spacing or 0 for error
761 */
762static inline uint8_t wma_parse_mpdudensity(uint8_t mpdudensity)
763{
764 if (mpdudensity < sizeof(wma_mpdu_spacing))
765 return wma_mpdu_spacing[mpdudensity];
766 else
767 return 0;
768}
769
Poddar, Siddarth5a91f5b2016-04-28 12:24:10 +0530770#if defined(CONFIG_HL_SUPPORT) && defined(FEATURE_WLAN_TDLS)
771
772/**
773 * wma_unified_peer_state_update() - update peer state
774 * @pdev: pdev handle
775 * @sta_mac: pointer to sta mac addr
776 * @bss_addr: bss address
777 * @sta_type: sta entry type
778 *
779 *
780 * Return: None
781 */
782static void
783wma_unified_peer_state_update(
Leo Chang96464902016-10-28 11:10:54 -0700784 void *pdev,
Poddar, Siddarth5a91f5b2016-04-28 12:24:10 +0530785 uint8_t *sta_mac,
786 uint8_t *bss_addr,
787 uint8_t sta_type)
788{
Leo Chang96464902016-10-28 11:10:54 -0700789 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
790
Poddar, Siddarth5a91f5b2016-04-28 12:24:10 +0530791 if (STA_ENTRY_TDLS_PEER == sta_type)
Leo Chang96464902016-10-28 11:10:54 -0700792 cdp_peer_state_update(soc, pdev, sta_mac,
Poddar, Siddarth5a91f5b2016-04-28 12:24:10 +0530793 OL_TXRX_PEER_STATE_AUTH);
794 else
Leo Chang96464902016-10-28 11:10:54 -0700795 cdp_peer_state_update(soc, pdev, bss_addr,
Poddar, Siddarth5a91f5b2016-04-28 12:24:10 +0530796 OL_TXRX_PEER_STATE_AUTH);
797}
798#else
799
800static inline void
801wma_unified_peer_state_update(
Leo Chang96464902016-10-28 11:10:54 -0700802 void *pdev,
Poddar, Siddarth5a91f5b2016-04-28 12:24:10 +0530803 uint8_t *sta_mac,
804 uint8_t *bss_addr,
805 uint8_t sta_type)
806{
Leo Chang96464902016-10-28 11:10:54 -0700807 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
808
809 cdp_peer_state_update(soc, pdev, bss_addr, OL_TXRX_PEER_STATE_AUTH);
Poddar, Siddarth5a91f5b2016-04-28 12:24:10 +0530810}
811#endif
812
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800813/**
814 * wmi_unified_send_peer_assoc() - send peer assoc command to fw
815 * @wma: wma handle
816 * @nw_type: nw type
817 * @params: add sta params
818 *
819 * This function send peer assoc command to firmware with
820 * different parameters.
821 *
Govind Singhb30d4c02016-03-24 11:01:23 +0530822 * Return: QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800823 */
Govind Singhb30d4c02016-03-24 11:01:23 +0530824QDF_STATUS wma_send_peer_assoc(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800825 tSirNwType nw_type,
826 tpAddStaParams params)
827{
Leo Chang96464902016-10-28 11:10:54 -0700828 void *pdev;
Govind Singhb30d4c02016-03-24 11:01:23 +0530829 struct peer_assoc_params *cmd;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800830 int32_t ret, max_rates, i;
831 uint8_t rx_stbc, tx_stbc;
Govind Singhb30d4c02016-03-24 11:01:23 +0530832 uint8_t *rate_pos;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800833 wmi_rate_set peer_legacy_rates, peer_ht_rates;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800834 uint32_t num_peer_11b_rates = 0;
835 uint32_t num_peer_11a_rates = 0;
836 uint32_t phymode;
837 uint32_t peer_nss = 1;
838 struct wma_txrx_node *intr = NULL;
Govind Singhb30d4c02016-03-24 11:01:23 +0530839 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800840
Govind Singhb30d4c02016-03-24 11:01:23 +0530841 cmd = qdf_mem_malloc(sizeof(struct peer_assoc_params));
842 if (!cmd) {
843 WMA_LOGE("Failed to allocate peer_assoc_params param");
844 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800845 }
Govind Singhb30d4c02016-03-24 11:01:23 +0530846
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800847 intr = &wma->interfaces[params->smesessionId];
848
Anurag Chouhan6d760662016-02-20 16:05:43 +0530849 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800850
851 if (NULL == pdev) {
852 WMA_LOGE("%s: Failed to get pdev", __func__);
Govind Singhb30d4c02016-03-24 11:01:23 +0530853 qdf_mem_free(cmd);
854 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800855 }
856
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530857 qdf_mem_zero(&peer_legacy_rates, sizeof(wmi_rate_set));
858 qdf_mem_zero(&peer_ht_rates, sizeof(wmi_rate_set));
Govind Singhb30d4c02016-03-24 11:01:23 +0530859 qdf_mem_zero(cmd, sizeof(struct peer_assoc_params));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800860
861 phymode = wma_peer_phymode(nw_type, params->staType,
862 params->htCapable,
863 params->ch_width,
864 params->vhtCapable);
865
866 /* Legacy Rateset */
867 rate_pos = (uint8_t *) peer_legacy_rates.rates;
868 for (i = 0; i < SIR_NUM_11B_RATES; i++) {
869 if (!params->supportedRates.llbRates[i])
870 continue;
871 rate_pos[peer_legacy_rates.num_rates++] =
872 params->supportedRates.llbRates[i];
873 num_peer_11b_rates++;
874 }
875 for (i = 0; i < SIR_NUM_11A_RATES; i++) {
876 if (!params->supportedRates.llaRates[i])
877 continue;
878 rate_pos[peer_legacy_rates.num_rates++] =
879 params->supportedRates.llaRates[i];
880 num_peer_11a_rates++;
881 }
882
883 if ((phymode == MODE_11A && num_peer_11a_rates == 0) ||
884 (phymode == MODE_11B && num_peer_11b_rates == 0)) {
885 WMA_LOGW("%s: Invalid phy rates. phymode 0x%x, 11b_rates %d, 11a_rates %d",
886 __func__, phymode, num_peer_11b_rates, num_peer_11a_rates);
Govind Singhb30d4c02016-03-24 11:01:23 +0530887 qdf_mem_free(cmd);
888 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800889 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800890
891 /* HT Rateset */
892 max_rates = sizeof(peer_ht_rates.rates) /
893 sizeof(peer_ht_rates.rates[0]);
894 rate_pos = (uint8_t *) peer_ht_rates.rates;
895 for (i = 0; i < MAX_SUPPORTED_RATES; i++) {
896 if (params->supportedRates.supportedMCSSet[i / 8] &
897 (1 << (i % 8))) {
898 rate_pos[peer_ht_rates.num_rates++] = i;
899 if (i >= 8) {
900 /* MCS8 or higher rate is present, must be 2x2 */
901 peer_nss = 2;
902 }
903 }
904 if (peer_ht_rates.num_rates == max_rates)
905 break;
906 }
907
908 if (params->htCapable && !peer_ht_rates.num_rates) {
909 uint8_t temp_ni_rates[8] = { 0x0, 0x1, 0x2, 0x3,
910 0x4, 0x5, 0x6, 0x7};
911 /*
912 * Workaround for EV 116382: The peer is marked HT but with
913 * supported rx mcs set is set to 0. 11n spec mandates MCS0-7
914 * for a HT STA. So forcing the supported rx mcs rate to
915 * MCS 0-7. This workaround will be removed once we get
916 * clarification from WFA regarding this STA behavior.
917 */
918
919 /* TODO: Do we really need this? */
920 WMA_LOGW("Peer is marked as HT capable but supported mcs rate is 0");
921 peer_ht_rates.num_rates = sizeof(temp_ni_rates);
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530922 qdf_mem_copy((uint8_t *) peer_ht_rates.rates, temp_ni_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800923 peer_ht_rates.num_rates);
924 }
925
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800926 /* in ap/ibss mode and for tdls peer, use mac address of the peer in
927 * the other end as the new peer address; in sta mode, use bss id to
928 * be the new peer address
929 */
930 if ((wma_is_vdev_in_ap_mode(wma, params->smesessionId))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800931 || (wma_is_vdev_in_ibss_mode(wma, params->smesessionId))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800932#ifdef FEATURE_WLAN_TDLS
933 || (STA_ENTRY_TDLS_PEER == params->staType)
934#endif /* FEATURE_WLAN_TDLS */
935 )
936 WMI_CHAR_ARRAY_TO_MAC_ADDR(params->staMac, &cmd->peer_macaddr);
937 else
938 WMI_CHAR_ARRAY_TO_MAC_ADDR(params->bssId, &cmd->peer_macaddr);
939 cmd->vdev_id = params->smesessionId;
940 cmd->peer_new_assoc = 1;
941 cmd->peer_associd = params->assocId;
942
943 /*
944 * The target only needs a subset of the flags maintained in the host.
945 * Just populate those flags and send it down
946 */
947 cmd->peer_flags = 0;
948
949 if (params->wmmEnabled)
950 cmd->peer_flags |= WMI_PEER_QOS;
951
952 if (params->uAPSD) {
953 cmd->peer_flags |= WMI_PEER_APSD;
954 WMA_LOGD("Set WMI_PEER_APSD: uapsd Mask %d", params->uAPSD);
955 }
956
957 if (params->htCapable) {
958 cmd->peer_flags |= (WMI_PEER_HT | WMI_PEER_QOS);
959 cmd->peer_rate_caps |= WMI_RC_HT_FLAG;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800960
Krishna Kumaar Natarajan59f546c2016-02-16 10:31:55 -0800961 if (params->ch_width) {
962 cmd->peer_flags |= WMI_PEER_40MHZ;
963 cmd->peer_rate_caps |= WMI_RC_CW40_FLAG;
964 if (params->fShortGI40Mhz)
965 cmd->peer_rate_caps |= WMI_RC_SGI_FLAG;
966 } else if (params->fShortGI20Mhz) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800967 cmd->peer_rate_caps |= WMI_RC_SGI_FLAG;
Krishna Kumaar Natarajan59f546c2016-02-16 10:31:55 -0800968 }
969 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800970
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800971 if (params->vhtCapable) {
972 cmd->peer_flags |= (WMI_PEER_HT | WMI_PEER_VHT | WMI_PEER_QOS);
973 cmd->peer_rate_caps |= WMI_RC_HT_FLAG;
974 }
975
976 if (params->ch_width == CH_WIDTH_80MHZ)
977 cmd->peer_flags |= WMI_PEER_80MHZ;
978 else if (params->ch_width == CH_WIDTH_160MHZ)
979 cmd->peer_flags |= WMI_PEER_160MHZ;
980 else if (params->ch_width == CH_WIDTH_80P80MHZ)
981 cmd->peer_flags |= WMI_PEER_160MHZ;
982
983 cmd->peer_vht_caps = params->vht_caps;
Agrawal Ashishb2d1a452016-05-05 12:23:58 +0530984 if (params->p2pCapableSta)
985 cmd->peer_flags |= WMI_PEER_IS_P2P_CAPABLE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800986
987 if (params->rmfEnabled)
988 cmd->peer_flags |= WMI_PEER_PMF;
989
990 rx_stbc = (params->ht_caps & IEEE80211_HTCAP_C_RXSTBC) >>
991 IEEE80211_HTCAP_C_RXSTBC_S;
992 if (rx_stbc) {
993 cmd->peer_flags |= WMI_PEER_STBC;
994 cmd->peer_rate_caps |= (rx_stbc << WMI_RC_RX_STBC_FLAG_S);
995 }
996
997 tx_stbc = (params->ht_caps & IEEE80211_HTCAP_C_TXSTBC) >>
998 IEEE80211_HTCAP_C_TXSTBC_S;
999 if (tx_stbc) {
1000 cmd->peer_flags |= WMI_PEER_STBC;
1001 cmd->peer_rate_caps |= (tx_stbc << WMI_RC_TX_STBC_FLAG_S);
1002 }
1003
1004 if (params->htLdpcCapable || params->vhtLdpcCapable)
1005 cmd->peer_flags |= WMI_PEER_LDPC;
1006
1007 switch (params->mimoPS) {
1008 case eSIR_HT_MIMO_PS_STATIC:
1009 cmd->peer_flags |= WMI_PEER_STATIC_MIMOPS;
1010 break;
1011 case eSIR_HT_MIMO_PS_DYNAMIC:
1012 cmd->peer_flags |= WMI_PEER_DYN_MIMOPS;
1013 break;
1014 case eSIR_HT_MIMO_PS_NO_LIMIT:
1015 cmd->peer_flags |= WMI_PEER_SPATIAL_MUX;
1016 break;
1017 default:
1018 break;
1019 }
1020
1021#ifdef FEATURE_WLAN_TDLS
1022 if (STA_ENTRY_TDLS_PEER == params->staType)
1023 cmd->peer_flags |= WMI_PEER_AUTH;
1024#endif /* FEATURE_WLAN_TDLS */
1025
1026 if (params->wpa_rsn
1027#ifdef FEATURE_WLAN_WAPI
1028 || params->encryptType == eSIR_ED_WPI
1029#endif /* FEATURE_WLAN_WAPI */
1030 )
1031 cmd->peer_flags |= WMI_PEER_NEED_PTK_4_WAY;
1032 if (params->wpa_rsn >> 1)
1033 cmd->peer_flags |= WMI_PEER_NEED_GTK_2_WAY;
1034
Poddar, Siddarth5a91f5b2016-04-28 12:24:10 +05301035 wma_unified_peer_state_update(pdev, params->staMac,
1036 params->bssId, params->staType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001037
1038#ifdef FEATURE_WLAN_WAPI
1039 if (params->encryptType == eSIR_ED_WPI) {
Govind Singhd76a5b02016-03-08 15:12:14 +05301040 ret = wma_vdev_set_param(wma->wmi_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001041 params->smesessionId,
1042 WMI_VDEV_PARAM_DROP_UNENCRY,
1043 false);
1044 if (ret) {
1045 WMA_LOGE
1046 ("Set WMI_VDEV_PARAM_DROP_UNENCRY Param status:%d\n",
1047 ret);
Govind Singhb30d4c02016-03-24 11:01:23 +05301048 qdf_mem_free(cmd);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001049 return ret;
1050 }
1051 }
1052#endif /* FEATURE_WLAN_WAPI */
1053
1054 cmd->peer_caps = params->capab_info;
1055 cmd->peer_listen_intval = params->listenInterval;
1056 cmd->peer_ht_caps = params->ht_caps;
1057 cmd->peer_max_mpdu = (1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR +
1058 params->maxAmpduSize)) - 1;
1059 cmd->peer_mpdu_density = wma_parse_mpdudensity(params->maxAmpduDensity);
1060
1061 if (params->supportedRates.supportedMCSSet[1] &&
1062 params->supportedRates.supportedMCSSet[2])
1063 cmd->peer_rate_caps |= WMI_RC_TS_FLAG;
1064 else if (params->supportedRates.supportedMCSSet[1])
1065 cmd->peer_rate_caps |= WMI_RC_DS_FLAG;
1066
1067 /* Update peer legacy rate information */
Govind Singhb30d4c02016-03-24 11:01:23 +05301068 cmd->peer_legacy_rates.num_rates = peer_legacy_rates.num_rates;
1069 qdf_mem_copy(cmd->peer_legacy_rates.rates, peer_legacy_rates.rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001070 peer_legacy_rates.num_rates);
1071
1072 /* Update peer HT rate information */
Govind Singhb30d4c02016-03-24 11:01:23 +05301073 cmd->peer_ht_rates.num_rates = peer_ht_rates.num_rates;
1074 qdf_mem_copy(cmd->peer_ht_rates.rates, peer_ht_rates.rates,
1075 peer_ht_rates.num_rates);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001076
1077 /* VHT Rates */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001078
1079 cmd->peer_nss = peer_nss;
Naveen Rawatb14cab32015-11-02 17:01:51 -08001080 /*
1081 * Because of DBS a vdev may come up in any of the two MACs with
1082 * different capabilities. STBC capab should be fetched for given
1083 * hard_mode->MAC_id combo. It is planned that firmware should provide
1084 * these dev capabilities. But for now number of tx streams can be used
1085 * to identify if Tx STBC needs to be disabled.
1086 */
1087 if (intr->tx_streams < 2) {
1088 cmd->peer_vht_caps &= ~(1 << SIR_MAC_VHT_CAP_TXSTBC);
1089 WMA_LOGD("Num tx_streams: %d, Disabled txSTBC",
1090 intr->tx_streams);
1091 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001092 WMA_LOGD("peer_nss %d peer_ht_rates.num_rates %d ", cmd->peer_nss,
1093 peer_ht_rates.num_rates);
1094
Govind Singhb30d4c02016-03-24 11:01:23 +05301095 cmd->vht_capable = params->vhtCapable;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001096 if (params->vhtCapable) {
1097#define VHT2x2MCSMASK 0xc
Govind Singhb30d4c02016-03-24 11:01:23 +05301098 cmd->rx_max_rate = params->supportedRates.vhtRxHighestDataRate;
1099 cmd->rx_mcs_set = params->supportedRates.vhtRxMCSMap;
1100 cmd->tx_max_rate = params->supportedRates.vhtTxHighestDataRate;
1101 cmd->tx_mcs_set = params->supportedRates.vhtTxMCSMap;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001102
1103 if (params->vhtSupportedRxNss) {
1104 cmd->peer_nss = params->vhtSupportedRxNss;
1105 } else {
Govind Singhb30d4c02016-03-24 11:01:23 +05301106 cmd->peer_nss = ((cmd->rx_mcs_set & VHT2x2MCSMASK)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001107 == VHT2x2MCSMASK) ? 1 : 2;
1108 }
1109 }
1110
1111 /*
1112 * Limit nss to max number of rf chain supported by target
1113 * Otherwise Fw will crash
1114 */
1115 wma_update_txrx_chainmask(wma->num_rf_chains, &cmd->peer_nss);
1116
1117 intr->nss = cmd->peer_nss;
1118 cmd->peer_phymode = phymode;
1119 WMA_LOGD("%s: vdev_id %d associd %d peer_flags %x rate_caps %x "
1120 "peer_caps %x listen_intval %d ht_caps %x max_mpdu %d "
1121 "nss %d phymode %d peer_mpdu_density %d encr_type %d "
1122 "cmd->peer_vht_caps %x", __func__,
1123 cmd->vdev_id, cmd->peer_associd, cmd->peer_flags,
1124 cmd->peer_rate_caps, cmd->peer_caps,
1125 cmd->peer_listen_intval, cmd->peer_ht_caps,
1126 cmd->peer_max_mpdu, cmd->peer_nss, cmd->peer_phymode,
1127 cmd->peer_mpdu_density, params->encryptType,
1128 cmd->peer_vht_caps);
1129
Govind Singhb30d4c02016-03-24 11:01:23 +05301130 status = wmi_unified_peer_assoc_send(wma->wmi_handle,
1131 cmd);
1132 if (QDF_IS_STATUS_ERROR(status))
Arif Hussain49a5ffc2016-07-19 10:11:58 -07001133 WMA_LOGP(FL("Failed to send peer assoc command status = %d"),
1134 status);
Govind Singhb30d4c02016-03-24 11:01:23 +05301135 qdf_mem_free(cmd);
1136
1137 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001138}
1139
1140/**
1141 * wmi_unified_vdev_set_gtx_cfg_send() - set GTX params
1142 * @wmi_handle: wmi handle
1143 * @if_id: vdev id
1144 * @gtx_info: GTX config params
1145 *
1146 * This function set GTX related params in firmware.
1147 *
1148 * Return: 0 for success or error code
1149 */
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301150QDF_STATUS wmi_unified_vdev_set_gtx_cfg_send(wmi_unified_t wmi_handle,
1151 uint32_t if_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001152 gtx_config_t *gtx_info)
1153{
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301154 struct wmi_gtx_config params;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001155
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301156 params.gtx_rt_mask[0] = gtx_info->gtxRTMask[0];
1157 params.gtx_rt_mask[1] = gtx_info->gtxRTMask[1];
1158 params.gtx_usrcfg = gtx_info->gtxUsrcfg;
1159 params.gtx_threshold = gtx_info->gtxPERThreshold;
1160 params.gtx_margin = gtx_info->gtxPERMargin;
1161 params.gtx_tpcstep = gtx_info->gtxTPCstep;
1162 params.gtx_tpcmin = gtx_info->gtxTPCMin;
1163 params.gtx_bwmask = gtx_info->gtxBWMask;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001164
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301165 return wmi_unified_vdev_set_gtx_cfg_cmd(wmi_handle,
1166 if_id, &params);
1167
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001168}
1169
1170/**
1171 * wma_update_protection_mode() - update protection mode
1172 * @wma: wma handle
1173 * @vdev_id: vdev id
1174 * @llbcoexist: protection mode info
1175 *
1176 * This function set protection mode(RTS/CTS) to fw for passed vdev id.
1177 *
1178 * Return: none
1179 */
1180void wma_update_protection_mode(tp_wma_handle wma, uint8_t vdev_id,
1181 uint8_t llbcoexist)
1182{
Govind Singhd76a5b02016-03-08 15:12:14 +05301183 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001184 enum ieee80211_protmode prot_mode;
1185
1186 prot_mode = llbcoexist ? IEEE80211_PROT_CTSONLY : IEEE80211_PROT_NONE;
1187
Govind Singhd76a5b02016-03-08 15:12:14 +05301188 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001189 WMI_VDEV_PARAM_PROTECTION_MODE,
1190 prot_mode);
1191
Govind Singhd76a5b02016-03-08 15:12:14 +05301192 if (QDF_IS_STATUS_ERROR(ret))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001193 WMA_LOGE("Failed to send wmi protection mode cmd");
1194 else
1195 WMA_LOGD("Updated protection mode %d to target", prot_mode);
1196}
1197
1198/**
1199 * wma_update_beacon_interval() - update beacon interval in fw
1200 * @wma: wma handle
1201 * @vdev_id: vdev id
1202 * @beaconInterval: becon interval
1203 *
1204 * Return: none
1205 */
1206static void
1207wma_update_beacon_interval(tp_wma_handle wma, uint8_t vdev_id,
1208 uint16_t beaconInterval)
1209{
Govind Singhd76a5b02016-03-08 15:12:14 +05301210 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001211
Govind Singhd76a5b02016-03-08 15:12:14 +05301212 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001213 WMI_VDEV_PARAM_BEACON_INTERVAL,
1214 beaconInterval);
1215
Govind Singhd76a5b02016-03-08 15:12:14 +05301216 if (QDF_IS_STATUS_ERROR(ret))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001217 WMA_LOGE("Failed to update beacon interval");
1218 else
1219 WMA_LOGI("Updated beacon interval %d for vdev %d",
1220 beaconInterval, vdev_id);
1221}
1222
1223/**
1224 * wma_process_update_beacon_params() - update beacon parameters to target
1225 * @wma: wma handle
1226 * @bcn_params: beacon parameters
1227 *
1228 * Return: none
1229 */
1230void
1231wma_process_update_beacon_params(tp_wma_handle wma,
1232 tUpdateBeaconParams *bcn_params)
1233{
1234 if (!bcn_params) {
1235 WMA_LOGE("bcn_params NULL");
1236 return;
1237 }
1238
1239 if (bcn_params->smeSessionId >= wma->max_bssid) {
1240 WMA_LOGE("Invalid vdev id %d", bcn_params->smeSessionId);
1241 return;
1242 }
1243
1244 if (bcn_params->paramChangeBitmap & PARAM_BCN_INTERVAL_CHANGED) {
1245 wma_update_beacon_interval(wma, bcn_params->smeSessionId,
1246 bcn_params->beaconInterval);
1247 }
1248
1249 if (bcn_params->paramChangeBitmap & PARAM_llBCOEXIST_CHANGED)
1250 wma_update_protection_mode(wma, bcn_params->smeSessionId,
1251 bcn_params->llbCoexist);
1252}
1253
1254/**
1255 * wma_update_cfg_params() - update cfg parameters to target
1256 * @wma: wma handle
1257 * @cfgParam: cfg parameter
1258 *
1259 * Return: none
1260 */
Rajeev Kumar416b73f2017-01-21 16:45:21 -08001261void wma_update_cfg_params(tp_wma_handle wma, struct scheduler_msg *cfgParam)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001262{
1263 uint8_t vdev_id;
1264 uint32_t param_id;
1265 uint32_t cfg_val;
Govind Singhd76a5b02016-03-08 15:12:14 +05301266 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001267 /* get mac to acess CFG data base */
1268 struct sAniSirGlobal *pmac;
1269
1270 switch (cfgParam->bodyval) {
1271 case WNI_CFG_RTS_THRESHOLD:
1272 param_id = WMI_VDEV_PARAM_RTS_THRESHOLD;
1273 break;
1274 case WNI_CFG_FRAGMENTATION_THRESHOLD:
1275 param_id = WMI_VDEV_PARAM_FRAGMENTATION_THRESHOLD;
1276 break;
1277 default:
1278 WMA_LOGD("Unhandled cfg parameter %d", cfgParam->bodyval);
1279 return;
1280 }
1281
Anurag Chouhan6d760662016-02-20 16:05:43 +05301282 pmac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001283
1284 if (NULL == pmac) {
1285 WMA_LOGE("%s: Failed to get pmac", __func__);
1286 return;
1287 }
1288
1289 if (wlan_cfg_get_int(pmac, (uint16_t) cfgParam->bodyval,
1290 &cfg_val) != eSIR_SUCCESS) {
1291 WMA_LOGE("Failed to get value for CFG PARAMS %d. returning without updating",
1292 cfgParam->bodyval);
1293 return;
1294 }
1295
1296 for (vdev_id = 0; vdev_id < wma->max_bssid; vdev_id++) {
1297 if (wma->interfaces[vdev_id].handle != 0) {
Govind Singhd76a5b02016-03-08 15:12:14 +05301298 ret = wma_vdev_set_param(wma->wmi_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001299 vdev_id, param_id,
1300 cfg_val);
Govind Singhd76a5b02016-03-08 15:12:14 +05301301 if (QDF_IS_STATUS_ERROR(ret))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001302 WMA_LOGE("Update cfg params failed for vdevId %d",
1303 vdev_id);
1304 }
1305 }
1306}
1307
1308/**
1309 * wma_read_cfg_wepkey() - fill key_info for WEP key
1310 * @wma_handle: wma handle
1311 * @key_info: key_info ptr
1312 * @def_key_idx: default key index
1313 * @num_keys: number of keys
1314 *
1315 * This function reads WEP keys from cfg and fills
1316 * up key_info.
1317 *
1318 * Return: none
1319 */
1320static void wma_read_cfg_wepkey(tp_wma_handle wma_handle,
1321 tSirKeys *key_info, uint32_t *def_key_idx,
1322 uint8_t *num_keys)
1323{
1324 tSirRetStatus status;
1325 uint32_t val = SIR_MAC_KEY_LENGTH;
1326 uint8_t i, j;
1327
1328 WMA_LOGD("Reading WEP keys from cfg");
1329 /* NOTE:def_key_idx is initialized to 0 by the caller */
1330 status = wlan_cfg_get_int(wma_handle->mac_context,
1331 WNI_CFG_WEP_DEFAULT_KEYID, def_key_idx);
1332 if (status != eSIR_SUCCESS)
1333 WMA_LOGE("Unable to read default id, defaulting to 0");
1334
1335 for (i = 0, j = 0; i < SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS; i++) {
1336 status = wlan_cfg_get_str(wma_handle->mac_context,
1337 (uint16_t) WNI_CFG_WEP_DEFAULT_KEY_1 +
1338 i, key_info[j].key, &val);
1339 if (status != eSIR_SUCCESS) {
1340 WMA_LOGE("WEP key is not configured at :%d", i);
1341 } else {
1342 key_info[j].keyId = i;
1343 key_info[j].keyLength = (uint16_t) val;
1344 j++;
1345 }
1346 }
1347 *num_keys = j;
1348}
1349
1350/**
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301351 * wma_setup_install_key_cmd() - set key parameters
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001352 * @wma_handle: wma handle
1353 * @key_params: key parameters
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001354 * @mode: op mode
1355 *
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301356 * This function fills structure from information
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001357 * passed in key_params.
1358 *
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301359 * Return: QDF_STATUS_SUCCESS - success
1360 QDF_STATUS_E_FAILURE - failure
1361 QDF_STATUS_E_NOMEM - invalid request
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001362 */
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301363static QDF_STATUS wma_setup_install_key_cmd(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001364 struct wma_set_key_params
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301365 *key_params, uint8_t mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001366{
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301367 struct set_key_params params;
1368 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001369#ifdef WLAN_FEATURE_11W
1370 struct wma_txrx_node *iface = NULL;
1371#endif /* WLAN_FEATURE_11W */
1372 if ((key_params->key_type == eSIR_ED_NONE &&
1373 key_params->key_len) || (key_params->key_type != eSIR_ED_NONE &&
1374 !key_params->key_len)) {
1375 WMA_LOGE("%s:Invalid set key request", __func__);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301376 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001377 }
1378
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301379 params.vdev_id = key_params->vdev_id;
1380 params.key_idx = key_params->key_idx;
1381 qdf_mem_copy(params.peer_mac, key_params->peer_mac, IEEE80211_ADDR_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001382
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301383#ifdef FEATURE_WLAN_WAPI
1384 qdf_mem_set(params.tx_iv, 16, 0);
1385 qdf_mem_set(params.rx_iv, 16, 0);
1386#endif
1387 params.key_txmic_len = 0;
1388 params.key_rxmic_len = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001389
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301390 params.key_flags = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001391 if (key_params->unicast)
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301392 params.key_flags |= PAIRWISE_USAGE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001393 else
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301394 params.key_flags |= GROUP_USAGE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001395
1396 switch (key_params->key_type) {
1397 case eSIR_ED_NONE:
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301398 params.key_cipher = WMI_CIPHER_NONE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001399 break;
1400 case eSIR_ED_WEP40:
1401 case eSIR_ED_WEP104:
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301402 params.key_cipher = WMI_CIPHER_WEP;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001403 if (key_params->unicast &&
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301404 params.key_idx == key_params->def_key_idx) {
Ganesh Kondabattini59a4a952015-11-30 11:55:40 +05301405 WMA_LOGD("STA Mode: cmd->key_flags |= TX_USAGE");
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301406 params.key_flags |= TX_USAGE;
Ganesh Kondabattini59a4a952015-11-30 11:55:40 +05301407 } else if ((mode == wlan_op_mode_ap) &&
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301408 (params.key_idx == key_params->def_key_idx)) {
Ganesh Kondabattini59a4a952015-11-30 11:55:40 +05301409 WMA_LOGD("AP Mode: cmd->key_flags |= TX_USAGE");
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301410 params.key_flags |= TX_USAGE;
Ganesh Kondabattini59a4a952015-11-30 11:55:40 +05301411 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001412 break;
1413 case eSIR_ED_TKIP:
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301414 params.key_txmic_len = WMA_TXMIC_LEN;
1415 params.key_rxmic_len = WMA_RXMIC_LEN;
1416 params.key_cipher = WMI_CIPHER_TKIP;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001417 break;
1418#ifdef FEATURE_WLAN_WAPI
1419#define WPI_IV_LEN 16
1420 case eSIR_ED_WPI:
1421 {
1422 /*initialize receive and transmit IV with default values */
1423 /* **Note: tx_iv must be sent in reverse** */
1424 unsigned char tx_iv[16] = { 0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c,
1425 0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c,
1426 0x36, 0x5c, 0x36, 0x5c};
1427 unsigned char rx_iv[16] = { 0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36,
1428 0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36,
1429 0x5c, 0x36, 0x5c, 0x37};
1430 if (mode == wlan_op_mode_ap) {
1431 /* Authenticator initializes the value of PN as
1432 * 0x5C365C365C365C365C365C365C365C36 for MCastkey Update
1433 */
1434 if (key_params->unicast)
1435 tx_iv[0] = 0x37;
1436
1437 rx_iv[WPI_IV_LEN - 1] = 0x36;
1438 } else {
1439 if (!key_params->unicast)
1440 rx_iv[WPI_IV_LEN - 1] = 0x36;
1441 }
1442
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301443 params.key_txmic_len = WMA_TXMIC_LEN;
1444 params.key_rxmic_len = WMA_RXMIC_LEN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001445
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301446 qdf_mem_copy(&params.rx_iv, &rx_iv,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001447 WPI_IV_LEN);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301448 qdf_mem_copy(&params.tx_iv, &tx_iv,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001449 WPI_IV_LEN);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301450 params.key_cipher = WMI_CIPHER_WAPI;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001451 break;
1452 }
1453#endif /* FEATURE_WLAN_WAPI */
1454 case eSIR_ED_CCMP:
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301455 params.key_cipher = WMI_CIPHER_AES_CCM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001456 break;
1457#ifdef WLAN_FEATURE_11W
1458 case eSIR_ED_AES_128_CMAC:
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301459 params.key_cipher = WMI_CIPHER_AES_CMAC;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001460 break;
1461#endif /* WLAN_FEATURE_11W */
1462 default:
1463 /* TODO: MFP ? */
1464 WMA_LOGE("%s:Invalid encryption type:%d", __func__,
1465 key_params->key_type);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301466 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001467 }
1468
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001469#ifdef BIG_ENDIAN_HOST
1470 {
1471 /* for big endian host, copy engine byte_swap is enabled
1472 * But the key data content is in network byte order
1473 * Need to byte swap the key data content - so when copy engine
1474 * does byte_swap - target gets key_data content in the correct
1475 * order.
1476 */
1477 int8_t i;
1478 uint32_t *destp, *srcp;
1479
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301480 destp = (uint32_t *) params.key_data;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001481 srcp = (uint32_t *) key_params->key_data;
1482 for (i = 0;
1483 i < roundup(key_params->key_len, sizeof(uint32_t)) / 4;
1484 i++) {
1485 *destp = le32_to_cpu(*srcp);
1486 destp++;
1487 srcp++;
1488 }
1489 }
1490#else
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301491 qdf_mem_copy((void *)params.key_data,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001492 (const void *)key_params->key_data, key_params->key_len);
1493#endif /* BIG_ENDIAN_HOST */
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301494 params.key_len = key_params->key_len;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001495
1496#ifdef WLAN_FEATURE_11W
1497 if (key_params->key_type == eSIR_ED_AES_128_CMAC) {
1498 iface = &wma_handle->interfaces[key_params->vdev_id];
1499 if (iface) {
1500 iface->key.key_length = key_params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301501 qdf_mem_copy(iface->key.key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001502 (const void *)key_params->key_data,
1503 iface->key.key_length);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301504 if ((params.key_idx == WMA_IGTK_KEY_INDEX_4) ||
1505 (params.key_idx == WMA_IGTK_KEY_INDEX_5))
1506 qdf_mem_zero(iface->key.key_id[params.key_idx -
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001507 WMA_IGTK_KEY_INDEX_4].ipn,
1508 CMAC_IPN_LEN);
1509 }
1510 }
1511#endif /* WLAN_FEATURE_11W */
1512
1513 WMA_LOGD("Key setup : vdev_id %d key_idx %d key_type %d key_len %d"
1514 " unicast %d peer_mac %pM def_key_idx %d", key_params->vdev_id,
1515 key_params->key_idx, key_params->key_type, key_params->key_len,
1516 key_params->unicast, key_params->peer_mac,
1517 key_params->def_key_idx);
1518
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301519 status = wmi_unified_setup_install_key_cmd(wma_handle->wmi_handle,
1520 &params);
1521
1522 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001523}
1524
1525/**
1526 * wma_set_bsskey() - set encryption key to fw.
1527 * @wma_handle: wma handle
1528 * @key_info: key info
1529 *
1530 * Return: none
1531 */
1532void wma_set_bsskey(tp_wma_handle wma_handle, tpSetBssKeyParams key_info)
1533{
1534 struct wma_set_key_params key_params;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301535 QDF_STATUS status = QDF_STATUS_SUCCESS;
1536 uint32_t i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001537 uint32_t def_key_idx = 0;
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001538 uint32_t wlan_opmode;
Leo Chang96464902016-10-28 11:10:54 -07001539 void *txrx_vdev;
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001540 uint8_t *mac_addr;
Leo Chang96464902016-10-28 11:10:54 -07001541 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001542
1543 WMA_LOGD("BSS key setup");
1544 txrx_vdev = wma_find_vdev_by_id(wma_handle, key_info->smesessionId);
1545 if (!txrx_vdev) {
1546 WMA_LOGE("%s:Invalid vdev handle", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301547 key_info->status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001548 goto out;
1549 }
Leo Chang96464902016-10-28 11:10:54 -07001550 wlan_opmode = cdp_get_opmode(soc, txrx_vdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001551
1552 /*
1553 * For IBSS, WMI expects the BSS key to be set per peer key
1554 * So cache the BSS key in the wma_handle and re-use it when the
1555 * STA key is been setup for a peer
1556 */
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001557 if (wlan_op_mode_ibss == wlan_opmode) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301558 key_info->status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001559 if (wma_handle->ibss_started > 0)
1560 goto out;
1561 WMA_LOGD("Caching IBSS Key");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301562 qdf_mem_copy(&wma_handle->ibsskey_info, key_info,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001563 sizeof(tSetBssKeyParams));
1564 }
1565
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301566 qdf_mem_set(&key_params, sizeof(key_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001567 key_params.vdev_id = key_info->smesessionId;
1568 key_params.key_type = key_info->encType;
1569 key_params.singl_tid_rc = key_info->singleTidRc;
1570 key_params.unicast = false;
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001571 if (wlan_opmode == wlan_op_mode_sta) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301572 qdf_mem_copy(key_params.peer_mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001573 wma_handle->interfaces[key_info->smesessionId].bssid,
1574 IEEE80211_ADDR_LEN);
1575 } else {
Leo Chang96464902016-10-28 11:10:54 -07001576 mac_addr = cdp_get_vdev_mac_addr(soc, txrx_vdev);
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001577 if (mac_addr == NULL) {
1578 WMA_LOGE("%s: mac_addr is NULL for vdev with id %d",
1579 __func__, key_info->smesessionId);
1580 goto out;
1581 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001582 /* vdev mac address will be passed for all other modes */
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001583 qdf_mem_copy(key_params.peer_mac, mac_addr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001584 IEEE80211_ADDR_LEN);
1585 WMA_LOGA("BSS Key setup with vdev_mac %pM\n",
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001586 mac_addr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001587 }
1588
1589 if (key_info->numKeys == 0 &&
1590 (key_info->encType == eSIR_ED_WEP40 ||
1591 key_info->encType == eSIR_ED_WEP104)) {
1592 wma_read_cfg_wepkey(wma_handle, key_info->key,
1593 &def_key_idx, &key_info->numKeys);
1594 }
1595
1596 for (i = 0; i < key_info->numKeys; i++) {
1597 if (key_params.key_type != eSIR_ED_NONE &&
1598 !key_info->key[i].keyLength)
1599 continue;
1600 if (key_info->encType == eSIR_ED_WPI) {
1601 key_params.key_idx = key_info->key[i].keyId;
1602 key_params.def_key_idx = key_info->key[i].keyId;
1603 } else
1604 key_params.key_idx = key_info->key[i].keyId;
1605
1606 key_params.key_len = key_info->key[i].keyLength;
1607 if (key_info->encType == eSIR_ED_TKIP) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301608 qdf_mem_copy(key_params.key_data,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001609 key_info->key[i].key, 16);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301610 qdf_mem_copy(&key_params.key_data[16],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001611 &key_info->key[i].key[24], 8);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301612 qdf_mem_copy(&key_params.key_data[24],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001613 &key_info->key[i].key[16], 8);
1614 } else
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301615 qdf_mem_copy((void *)key_params.key_data,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001616 (const void *)key_info->key[i].key,
1617 key_info->key[i].keyLength);
1618
1619 WMA_LOGD("%s: bss key[%d] length %d", __func__, i,
1620 key_info->key[i].keyLength);
1621
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301622 status = wma_setup_install_key_cmd(wma_handle, &key_params,
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001623 wlan_opmode);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301624 if (status == QDF_STATUS_E_NOMEM) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001625 WMA_LOGE("%s:Failed to setup install key buf",
1626 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301627 key_info->status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001628 goto out;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301629 } else if (status == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001630 WMA_LOGE("%s:Failed to send install key command",
1631 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301632 key_info->status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001633 goto out;
1634 }
1635 }
1636
1637 wma_handle->ibss_started++;
1638 /* TODO: Should we wait till we get HTT_T2H_MSG_TYPE_SEC_IND? */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301639 key_info->status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001640
1641out:
1642 wma_send_msg(wma_handle, WMA_SET_BSSKEY_RSP, (void *)key_info, 0);
1643}
1644
1645#ifdef QCA_IBSS_SUPPORT
1646/**
1647 * wma_calc_ibss_heart_beat_timer() - calculate IBSS heart beat timer
1648 * @peer_num: number of peers
1649 *
1650 * Return: heart beat timer value
1651 */
1652static uint16_t wma_calc_ibss_heart_beat_timer(int16_t peer_num)
1653{
1654 /* heart beat timer value look-up table */
1655 /* entry index : (the number of currently connected peers) - 1
1656 entry value : the heart time threshold value in seconds for
1657 detecting ibss peer departure */
Naveen Rawatc45d1622016-07-05 12:20:09 -07001658 static const uint16_t heart_beat_timer[MAX_PEERS] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001659 4, 4, 4, 4, 4, 4, 4, 4,
1660 8, 8, 8, 8, 8, 8, 8, 8,
1661 12, 12, 12, 12, 12, 12, 12, 12,
1662 16, 16, 16, 16, 16, 16, 16, 16
1663 };
1664
Naveen Rawatc45d1622016-07-05 12:20:09 -07001665 if (peer_num < 1 || peer_num > MAX_PEERS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001666 return 0;
1667
1668 return heart_beat_timer[peer_num - 1];
1669
1670}
1671
1672/**
1673 * wma_adjust_ibss_heart_beat_timer() - set ibss heart beat timer in fw.
1674 * @wma: wma handle
1675 * @vdev_id: vdev id
1676 * @peer_num_delta: peer number delta value
1677 *
1678 * Return: none
1679 */
1680void wma_adjust_ibss_heart_beat_timer(tp_wma_handle wma,
1681 uint8_t vdev_id,
1682 int8_t peer_num_delta)
1683{
Leo Chang96464902016-10-28 11:10:54 -07001684 void *vdev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001685 int16_t new_peer_num;
1686 uint16_t new_timer_value_sec;
1687 uint32_t new_timer_value_ms;
Govind Singhd76a5b02016-03-08 15:12:14 +05301688 QDF_STATUS status;
Leo Chang96464902016-10-28 11:10:54 -07001689 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001690
1691 if (peer_num_delta != 1 && peer_num_delta != -1) {
1692 WMA_LOGE("Invalid peer_num_delta value %d", peer_num_delta);
1693 return;
1694 }
1695
1696 vdev = wma_find_vdev_by_id(wma, vdev_id);
1697 if (!vdev) {
1698 WMA_LOGE("vdev not found : vdev_id %d", vdev_id);
1699 return;
1700 }
1701
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001702 /* adjust peer numbers */
Leo Chang96464902016-10-28 11:10:54 -07001703 new_peer_num = cdp_peer_update_ibss_add_peer_num_of_vdev(soc, vdev,
1704 peer_num_delta);
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001705 if (OL_TXRX_INVALID_NUM_PEERS == new_peer_num) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001706 WMA_LOGE("new peer num %d out of valid boundary", new_peer_num);
1707 return;
1708 }
1709
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001710 /* reset timer value if all peers departed */
1711 if (new_peer_num == 0) {
Leo Chang96464902016-10-28 11:10:54 -07001712 cdp_set_ibss_vdev_heart_beat_timer(soc, vdev, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001713 return;
1714 }
1715
1716 /* calculate new timer value */
1717 new_timer_value_sec = wma_calc_ibss_heart_beat_timer(new_peer_num);
1718 if (new_timer_value_sec == 0) {
1719 WMA_LOGE("timer value %d is invalid for peer number %d",
1720 new_timer_value_sec, new_peer_num);
1721 return;
1722 }
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001723 if (new_timer_value_sec ==
Leo Chang96464902016-10-28 11:10:54 -07001724 cdp_set_ibss_vdev_heart_beat_timer(soc, vdev, new_timer_value_sec)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001725 WMA_LOGD("timer value %d stays same, no need to notify target",
1726 new_timer_value_sec);
1727 return;
1728 }
1729
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001730 new_timer_value_ms = ((uint32_t) new_timer_value_sec) * 1000;
1731
Govind Singhd76a5b02016-03-08 15:12:14 +05301732 status = wma_vdev_set_param(wma->wmi_handle, vdev_id,
1733 WMI_VDEV_PARAM_IBSS_MAX_BCN_LOST_MS,
1734 new_timer_value_ms);
1735 if (QDF_IS_STATUS_ERROR(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001736 WMA_LOGE("Failed to set IBSS link monitoring timer value");
1737 return;
1738 }
1739
1740 WMA_LOGD("Set IBSS link monitor timer: peer_num = %d timer_value = %d",
1741 new_peer_num, new_timer_value_ms);
1742}
1743
1744#endif /* QCA_IBSS_SUPPORT */
1745/**
1746 * wma_set_ibsskey_helper() - cached IBSS key in wma handle
1747 * @wma_handle: wma handle
1748 * @key_info: set bss key info
1749 * @peerMacAddr: peer mac address
1750 *
1751 * Return: none
1752 */
1753static void wma_set_ibsskey_helper(tp_wma_handle wma_handle,
1754 tpSetBssKeyParams key_info,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301755 struct qdf_mac_addr peer_macaddr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001756{
1757 struct wma_set_key_params key_params;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301758 QDF_STATUS status = QDF_STATUS_SUCCESS;
1759 uint32_t i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001760 uint32_t def_key_idx = 0;
Leo Chang96464902016-10-28 11:10:54 -07001761 void *txrx_vdev;
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001762 int opmode;
Leo Chang96464902016-10-28 11:10:54 -07001763 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001764
1765 WMA_LOGD("BSS key setup for peer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001766 txrx_vdev = wma_find_vdev_by_id(wma_handle, key_info->smesessionId);
1767 if (!txrx_vdev) {
1768 WMA_LOGE("%s:Invalid vdev handle", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301769 key_info->status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001770 return;
1771 }
1772
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301773 qdf_mem_set(&key_params, sizeof(key_params), 0);
Leo Chang96464902016-10-28 11:10:54 -07001774 opmode = cdp_get_opmode(soc, txrx_vdev);
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001775 qdf_mem_set(&key_params, sizeof(key_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001776 key_params.vdev_id = key_info->smesessionId;
1777 key_params.key_type = key_info->encType;
1778 key_params.singl_tid_rc = key_info->singleTidRc;
1779 key_params.unicast = false;
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001780 ASSERT(wlan_op_mode_ibss == opmode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001781
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301782 qdf_mem_copy(key_params.peer_mac, peer_macaddr.bytes,
Srinivas Girigowdad5965c42015-12-04 13:43:16 -08001783 IEEE80211_ADDR_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001784
1785 if (key_info->numKeys == 0 &&
1786 (key_info->encType == eSIR_ED_WEP40 ||
1787 key_info->encType == eSIR_ED_WEP104)) {
1788 wma_read_cfg_wepkey(wma_handle, key_info->key,
1789 &def_key_idx, &key_info->numKeys);
Masti, Narayanraddiab712a72016-08-04 11:59:11 +05301790 } else if ((key_info->encType == eSIR_ED_WEP40) ||
1791 (key_info->encType == eSIR_ED_WEP104)) {
1792 struct wma_txrx_node *intf =
1793 &wma_handle->interfaces[key_info->smesessionId];
1794 key_params.def_key_idx = intf->wep_default_key_idx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001795 }
1796
1797 for (i = 0; i < key_info->numKeys; i++) {
1798 if (key_params.key_type != eSIR_ED_NONE &&
1799 !key_info->key[i].keyLength)
1800 continue;
1801 key_params.key_idx = key_info->key[i].keyId;
1802 key_params.key_len = key_info->key[i].keyLength;
1803 if (key_info->encType == eSIR_ED_TKIP) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301804 qdf_mem_copy(key_params.key_data,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001805 key_info->key[i].key, 16);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301806 qdf_mem_copy(&key_params.key_data[16],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001807 &key_info->key[i].key[24], 8);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301808 qdf_mem_copy(&key_params.key_data[24],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001809 &key_info->key[i].key[16], 8);
1810 } else
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301811 qdf_mem_copy((void *)key_params.key_data,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001812 (const void *)key_info->key[i].key,
1813 key_info->key[i].keyLength);
1814
1815 WMA_LOGD("%s: peer bcast key[%d] length %d", __func__, i,
1816 key_info->key[i].keyLength);
1817
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301818 status = wma_setup_install_key_cmd(wma_handle, &key_params,
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001819 opmode);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301820 if (status == QDF_STATUS_E_NOMEM) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001821 WMA_LOGE("%s:Failed to setup install key buf",
1822 __func__);
1823 return;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301824 } else if (status == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001825 WMA_LOGE("%s:Failed to send install key command",
1826 __func__);
1827 }
1828 }
1829}
1830
1831/**
1832 * wma_set_stakey() - set encryption key
1833 * @wma_handle: wma handle
1834 * @key_info: station key info
1835 *
1836 * This function sets encryption key for WEP/WPA/WPA2
1837 * encryption mode in firmware and send response to upper layer.
1838 *
1839 * Return: none
1840 */
1841void wma_set_stakey(tp_wma_handle wma_handle, tpSetStaKeyParams key_info)
1842{
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301843 int32_t i;
1844 QDF_STATUS status = QDF_STATUS_SUCCESS;
Leo Chang96464902016-10-28 11:10:54 -07001845 void *txrx_pdev;
1846 void *txrx_vdev;
1847 void *peer;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001848 uint8_t num_keys = 0, peer_id;
1849 struct wma_set_key_params key_params;
1850 uint32_t def_key_idx = 0;
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001851 int opmode;
Leo Chang96464902016-10-28 11:10:54 -07001852 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001853
1854 WMA_LOGD("STA key setup");
1855
1856 /* Get the txRx Pdev handle */
Anurag Chouhan6d760662016-02-20 16:05:43 +05301857 txrx_pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001858 if (!txrx_pdev) {
1859 WMA_LOGE("%s:Invalid txrx pdev handle", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301860 key_info->status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001861 goto out;
1862 }
1863
Leo Chang96464902016-10-28 11:10:54 -07001864 peer = cdp_peer_find_by_addr(soc, txrx_pdev,
Srinivas Girigowdad5965c42015-12-04 13:43:16 -08001865 key_info->peer_macaddr.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001866 &peer_id);
1867 if (!peer) {
1868 WMA_LOGE("%s:Invalid peer for key setting", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301869 key_info->status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001870 goto out;
1871 }
1872
1873 txrx_vdev = wma_find_vdev_by_id(wma_handle, key_info->smesessionId);
1874 if (!txrx_vdev) {
1875 WMA_LOGE("%s:TxRx Vdev Handle is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301876 key_info->status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001877 goto out;
1878 }
Leo Chang96464902016-10-28 11:10:54 -07001879 opmode = cdp_get_opmode(soc, txrx_vdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001880
1881 if (key_info->defWEPIdx == WMA_INVALID_KEY_IDX &&
1882 (key_info->encType == eSIR_ED_WEP40 ||
1883 key_info->encType == eSIR_ED_WEP104) &&
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001884 opmode != wlan_op_mode_ap) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001885 wma_read_cfg_wepkey(wma_handle, key_info->key,
1886 &def_key_idx, &num_keys);
1887 key_info->defWEPIdx = def_key_idx;
1888 } else {
1889 num_keys = SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS;
1890 if (key_info->encType != eSIR_ED_NONE) {
1891 for (i = 0; i < num_keys; i++) {
1892 if (key_info->key[i].keyDirection ==
1893 eSIR_TX_DEFAULT) {
1894 key_info->defWEPIdx = i;
1895 break;
1896 }
1897 }
1898 }
1899 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301900 qdf_mem_set(&key_params, sizeof(key_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001901 key_params.vdev_id = key_info->smesessionId;
1902 key_params.key_type = key_info->encType;
1903 key_params.singl_tid_rc = key_info->singleTidRc;
1904 key_params.unicast = true;
1905 key_params.def_key_idx = key_info->defWEPIdx;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301906 qdf_mem_copy((void *)key_params.peer_mac,
Srinivas Girigowdad5965c42015-12-04 13:43:16 -08001907 (const void *)key_info->peer_macaddr.bytes,
1908 IEEE80211_ADDR_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001909 for (i = 0; i < num_keys; i++) {
1910 if (key_params.key_type != eSIR_ED_NONE &&
1911 !key_info->key[i].keyLength)
1912 continue;
1913 if (key_info->encType == eSIR_ED_TKIP) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301914 qdf_mem_copy(key_params.key_data,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001915 key_info->key[i].key, 16);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301916 qdf_mem_copy(&key_params.key_data[16],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001917 &key_info->key[i].key[24], 8);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301918 qdf_mem_copy(&key_params.key_data[24],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001919 &key_info->key[i].key[16], 8);
1920 } else
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301921 qdf_mem_copy(key_params.key_data, key_info->key[i].key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001922 key_info->key[i].keyLength);
1923 if (key_info->encType == eSIR_ED_WPI) {
1924 key_params.key_idx = key_info->key[i].keyId;
1925 key_params.def_key_idx = key_info->key[i].keyId;
1926 } else
1927 key_params.key_idx = i;
1928
1929 key_params.key_len = key_info->key[i].keyLength;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301930 status = wma_setup_install_key_cmd(wma_handle, &key_params,
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001931 opmode);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301932 if (status == QDF_STATUS_E_NOMEM) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001933 WMA_LOGE("%s:Failed to setup install key buf",
1934 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301935 key_info->status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001936 goto out;
1937 }
1938
1939 WMA_LOGD("%s: peer unicast key[%d] %d ", __func__, i,
1940 key_info->key[i].keyLength);
1941
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301942 if (status == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001943 WMA_LOGE("%s:Failed to send install key command",
1944 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301945 key_info->status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001946 goto out;
1947 }
1948 }
1949
1950 /* In IBSS mode, set the BSS KEY for this peer
1951 * BSS key is supposed to be cache into wma_handle
1952 */
Manjunathappa Prakash10d357a2016-03-31 19:20:49 -07001953 if (wlan_op_mode_ibss == opmode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001954 wma_set_ibsskey_helper(wma_handle, &wma_handle->ibsskey_info,
Srinivas Girigowdad5965c42015-12-04 13:43:16 -08001955 key_info->peer_macaddr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001956 }
1957
1958 /* TODO: Should we wait till we get HTT_T2H_MSG_TYPE_SEC_IND? */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301959 key_info->status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001960out:
1961 if (key_info->sendRsp)
1962 wma_send_msg(wma_handle, WMA_SET_STAKEY_RSP, (void *)key_info,
1963 0);
1964}
1965
1966/**
1967 * wma_process_update_edca_param_req() - update EDCA params
1968 * @handle: wma handle
1969 * @edca_params: edca parameters
1970 *
1971 * This function updates EDCA parameters to the target
1972 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05301973 * Return: QDF Status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001974 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301975QDF_STATUS wma_process_update_edca_param_req(WMA_HANDLE handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001976 tEdcaParams *edca_params)
1977{
1978 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301979 wmi_wmm_vparams wmm_param[WME_NUM_AC];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001980 tSirMacEdcaParamRecord *edca_record;
1981 int ac;
Leo Chang96464902016-10-28 11:10:54 -07001982 void *pdev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001983 struct ol_tx_wmm_param_t ol_tx_wmm_param;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301984 uint8_t vdev_id;
1985 QDF_STATUS status;
Leo Chang96464902016-10-28 11:10:54 -07001986 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05301987 vdev_id = edca_params->bssIdx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001988
1989 for (ac = 0; ac < WME_NUM_AC; ac++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001990 switch (ac) {
1991 case WME_AC_BE:
1992 edca_record = &edca_params->acbe;
1993 break;
1994 case WME_AC_BK:
1995 edca_record = &edca_params->acbk;
1996 break;
1997 case WME_AC_VI:
1998 edca_record = &edca_params->acvi;
1999 break;
2000 case WME_AC_VO:
2001 edca_record = &edca_params->acvo;
2002 break;
2003 default:
2004 goto fail;
2005 }
2006
Himanshu Agarwal009f1572016-03-09 17:26:02 +05302007 wma_update_edca_params_for_ac(edca_record, &wmm_param[ac], ac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002008
Himanshu Agarwal009f1572016-03-09 17:26:02 +05302009 ol_tx_wmm_param.ac[ac].aifs = wmm_param[ac].aifs;
2010 ol_tx_wmm_param.ac[ac].cwmin = wmm_param[ac].cwmin;
2011 ol_tx_wmm_param.ac[ac].cwmax = wmm_param[ac].cwmax;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002012 }
2013
Himanshu Agarwal009f1572016-03-09 17:26:02 +05302014 status = wmi_unified_process_update_edca_param(wma_handle->wmi_handle,
2015 vdev_id, wmm_param);
2016 if (status == QDF_STATUS_E_NOMEM)
2017 return status;
2018 else if (status == QDF_STATUS_E_FAILURE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002019 goto fail;
2020
Anurag Chouhan6d760662016-02-20 16:05:43 +05302021 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Himanshu Agarwal94045e42015-10-19 19:16:19 +05302022 if (pdev)
Leo Chang96464902016-10-28 11:10:54 -07002023 cdp_set_wmm_param(soc, pdev, ol_tx_wmm_param);
Himanshu Agarwal94045e42015-10-19 19:16:19 +05302024 else
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302025 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002026
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302027 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002028
2029fail:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002030 WMA_LOGE("%s: Failed to set WMM Paremeters", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302031 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002032}
2033
2034/**
2035 * wmi_unified_probe_rsp_tmpl_send() - send probe response template to fw
2036 * @wma: wma handle
2037 * @vdev_id: vdev id
2038 * @probe_rsp_info: probe response info
2039 *
2040 * Return: 0 for success or error code
2041 */
2042static int wmi_unified_probe_rsp_tmpl_send(tp_wma_handle wma,
2043 uint8_t vdev_id,
2044 tpSendProbeRespParams probe_rsp_info)
2045{
Himanshu Agarwal009f1572016-03-09 17:26:02 +05302046 uint8_t *frm;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002047 uint64_t adjusted_tsf_le;
2048 struct ieee80211_frame *wh;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05302049 struct wmi_probe_resp_params params;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002050
2051 WMA_LOGD(FL("Send probe response template for vdev %d"), vdev_id);
2052
2053 frm = probe_rsp_info->pProbeRespTemplate;
Himanshu Agarwal009f1572016-03-09 17:26:02 +05302054
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002055 /*
2056 * Make the TSF offset negative so probe response in the same
2057 * staggered batch have the same TSF.
2058 */
2059 adjusted_tsf_le = cpu_to_le64(0ULL -
2060 wma->interfaces[vdev_id].tsfadjust);
2061 /* Update the timstamp in the probe response buffer with adjusted TSF */
2062 wh = (struct ieee80211_frame *)frm;
2063 A_MEMCPY(&wh[1], &adjusted_tsf_le, sizeof(adjusted_tsf_le));
2064
Himanshu Agarwal009f1572016-03-09 17:26:02 +05302065 params.pProbeRespTemplate = probe_rsp_info->pProbeRespTemplate;
2066 params.probeRespTemplateLen = probe_rsp_info->probeRespTemplateLen;
2067 qdf_mem_copy(params.bssId, probe_rsp_info->bssId,
Krunal Soniab793342016-04-22 18:43:20 -07002068 IEEE80211_ADDR_LEN);
Himanshu Agarwal009f1572016-03-09 17:26:02 +05302069 qdf_mem_copy(params.ucProxyProbeReqValidIEBmap,
2070 probe_rsp_info->ucProxyProbeReqValidIEBmap,
2071 8 * sizeof(uint32_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002072
Himanshu Agarwal009f1572016-03-09 17:26:02 +05302073 return wmi_unified_probe_rsp_tmpl_send_cmd(wma->wmi_handle, vdev_id,
2074 &params, frm);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002075}
2076
2077/**
Govind Singh61ad2622016-02-22 17:25:02 +05302078 * wma_unified_bcn_tmpl_send() - send beacon template to fw
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002079 * @wma:wma handle
2080 * @vdev_id: vdev id
2081 * @bcn_info: beacon info
2082 * @bytes_to_strip: bytes to strip
2083 *
Govind Singh61ad2622016-02-22 17:25:02 +05302084 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002085 */
Govind Singh61ad2622016-02-22 17:25:02 +05302086static QDF_STATUS wma_unified_bcn_tmpl_send(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002087 uint8_t vdev_id,
Govind Singh61ad2622016-02-22 17:25:02 +05302088 const tpSendbeaconParams bcn_info,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002089 uint8_t bytes_to_strip)
2090{
Govind Singh61ad2622016-02-22 17:25:02 +05302091 struct beacon_params params = {0};
2092 uint32_t tmpl_len, tmpl_len_aligned;
2093 uint8_t *frm;
2094 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002095 uint8_t *p2p_ie;
2096 uint16_t p2p_ie_len = 0;
2097 uint64_t adjusted_tsf_le;
2098 struct ieee80211_frame *wh;
2099
2100 WMA_LOGD("Send beacon template for vdev %d", vdev_id);
2101
2102 if (bcn_info->p2pIeOffset) {
2103 p2p_ie = bcn_info->beacon + bcn_info->p2pIeOffset;
2104 p2p_ie_len = (uint16_t) p2p_ie[1] + 2;
2105 }
2106
2107 /*
2108 * XXX: The first byte of beacon buffer contains beacon length
2109 * only when UMAC in sending the beacon template. In othercases
2110 * (ex: from tbtt update) beacon length is read from beacon
2111 * information.
2112 */
2113 if (bytes_to_strip)
2114 tmpl_len = *(uint32_t *) &bcn_info->beacon[0];
2115 else
2116 tmpl_len = bcn_info->beaconLength;
2117 if (p2p_ie_len) {
2118 tmpl_len -= (uint32_t) p2p_ie_len;
2119 }
2120
2121 frm = bcn_info->beacon + bytes_to_strip;
2122 tmpl_len_aligned = roundup(tmpl_len, sizeof(A_UINT32));
2123 /*
2124 * Make the TSF offset negative so beacons in the same
2125 * staggered batch have the same TSF.
2126 */
2127 adjusted_tsf_le = cpu_to_le64(0ULL -
2128 wma->interfaces[vdev_id].tsfadjust);
2129 /* Update the timstamp in the beacon buffer with adjusted TSF */
2130 wh = (struct ieee80211_frame *)frm;
2131 A_MEMCPY(&wh[1], &adjusted_tsf_le, sizeof(adjusted_tsf_le));
2132
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002133
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002134
Govind Singh61ad2622016-02-22 17:25:02 +05302135 params.vdev_id = vdev_id;
2136 params.tim_ie_offset = bcn_info->timIeOffset - bytes_to_strip;
2137 params.tmpl_len = tmpl_len;
2138 params.frm = frm;
2139 params.tmpl_len_aligned = tmpl_len_aligned;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002140
Govind Singh61ad2622016-02-22 17:25:02 +05302141 ret = wmi_unified_beacon_send_cmd(wma->wmi_handle,
2142 &params);
2143 if (QDF_IS_STATUS_ERROR(ret)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002144 WMA_LOGE("%s: Failed to send bcn tmpl: %d", __func__, ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002145 }
2146
2147 return ret;
2148}
2149
2150/**
2151 * wma_store_bcn_tmpl() - store beacon template
2152 * @wma: wma handle
2153 * @vdev_id: vdev id
2154 * @bcn_info: beacon params
2155 *
2156 * This function stores beacon template locally.
2157 * This will send to target on the reception of
2158 * SWBA event.
2159 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302160 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002161 */
Jeff Johnsonc4b47a92016-10-07 12:34:41 -07002162static QDF_STATUS wma_store_bcn_tmpl(tp_wma_handle wma, uint8_t vdev_id,
2163 tpSendbeaconParams bcn_info)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002164{
2165 struct beacon_info *bcn;
2166 uint32_t len;
2167 uint8_t *bcn_payload;
2168 struct beacon_tim_ie *tim_ie;
2169
2170 bcn = wma->interfaces[vdev_id].beacon;
2171 if (!bcn || !bcn->buf) {
2172 WMA_LOGE("%s: Memory is not allocated to hold bcn template",
2173 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302174 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002175 }
2176
2177 len = *(u32 *) &bcn_info->beacon[0];
2178 if (len > WMA_BCN_BUF_MAX_SIZE) {
2179 WMA_LOGE("%s: Received beacon len %d exceeding max limit %d",
2180 __func__, len, WMA_BCN_BUF_MAX_SIZE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302181 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002182 }
2183 WMA_LOGD("%s: Storing received beacon template buf to local buffer",
2184 __func__);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302185 qdf_spin_lock_bh(&bcn->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002186
2187 /*
2188 * Copy received beacon template content in local buffer.
2189 * this will be send to target on the reception of SWBA
2190 * event from target.
2191 */
Nirav Shahcbc6d722016-03-01 16:24:53 +05302192 qdf_nbuf_trim_tail(bcn->buf, qdf_nbuf_len(bcn->buf));
2193 memcpy(qdf_nbuf_data(bcn->buf),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002194 bcn_info->beacon + 4 /* Exclude beacon length field */,
2195 len);
2196 if (bcn_info->timIeOffset > 3) {
2197 bcn->tim_ie_offset = bcn_info->timIeOffset - 4;
2198 } else {
2199 bcn->tim_ie_offset = bcn_info->timIeOffset;
2200 }
2201
2202 if (bcn_info->p2pIeOffset > 3) {
2203 bcn->p2p_ie_offset = bcn_info->p2pIeOffset - 4;
2204 } else {
2205 bcn->p2p_ie_offset = bcn_info->p2pIeOffset;
2206 }
Nirav Shahcbc6d722016-03-01 16:24:53 +05302207 bcn_payload = qdf_nbuf_data(bcn->buf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002208 if (bcn->tim_ie_offset) {
2209 tim_ie =
2210 (struct beacon_tim_ie *)(&bcn_payload[bcn->tim_ie_offset]);
2211 /*
2212 * Intial Value of bcn->dtim_count will be 0.
2213 * But if the beacon gets updated then current dtim
2214 * count will be restored
2215 */
2216 tim_ie->dtim_count = bcn->dtim_count;
2217 tim_ie->tim_bitctl = 0;
2218 }
2219
Nirav Shahcbc6d722016-03-01 16:24:53 +05302220 qdf_nbuf_put_tail(bcn->buf, len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002221 bcn->len = len;
2222
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302223 qdf_spin_unlock_bh(&bcn->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002224
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302225 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002226}
2227
2228/**
2229 * wma_tbttoffset_update_event_handler() - tbtt offset update handler
2230 * @handle: wma handle
2231 * @event: event buffer
2232 * @len: data length
2233 *
2234 * Return: 0 for success or error code
2235 */
2236int wma_tbttoffset_update_event_handler(void *handle, uint8_t *event,
2237 uint32_t len)
2238{
2239 tp_wma_handle wma = (tp_wma_handle) handle;
2240 WMI_TBTTOFFSET_UPDATE_EVENTID_param_tlvs *param_buf;
2241 wmi_tbtt_offset_event_fixed_param *tbtt_offset_event;
2242 struct wma_txrx_node *intf;
2243 struct beacon_info *bcn;
2244 tSendbeaconParams bcn_info;
2245 uint32_t *adjusted_tsf = NULL;
2246 uint32_t if_id = 0, vdev_map;
2247
2248 if (!wma) {
2249 WMA_LOGE("Invalid wma handle");
2250 return -EINVAL;
2251 }
2252
2253 param_buf = (WMI_TBTTOFFSET_UPDATE_EVENTID_param_tlvs *) event;
2254 if (!param_buf) {
2255 WMA_LOGE("Invalid tbtt update event buffer");
2256 return -EINVAL;
2257 }
2258
2259 tbtt_offset_event = param_buf->fixed_param;
2260 intf = wma->interfaces;
2261 vdev_map = tbtt_offset_event->vdev_map;
2262 adjusted_tsf = param_buf->tbttoffset_list;
2263 if (!adjusted_tsf) {
2264 WMA_LOGE("%s: Invalid adjusted_tsf", __func__);
2265 return -EINVAL;
2266 }
2267
2268 for (; (vdev_map); vdev_map >>= 1, if_id++) {
2269 if (!(vdev_map & 0x1) || (!(intf[if_id].handle)))
2270 continue;
2271
2272 bcn = intf[if_id].beacon;
2273 if (!bcn) {
2274 WMA_LOGE("%s: Invalid beacon", __func__);
2275 return -EINVAL;
2276 }
2277 if (!bcn->buf) {
2278 WMA_LOGE("%s: Invalid beacon buffer", __func__);
2279 return -EINVAL;
2280 }
2281 /* Save the adjusted TSF */
2282 intf[if_id].tsfadjust = adjusted_tsf[if_id];
2283
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302284 qdf_spin_lock_bh(&bcn->lock);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302285 qdf_mem_zero(&bcn_info, sizeof(bcn_info));
Nirav Shahcbc6d722016-03-01 16:24:53 +05302286 bcn_info.beacon = qdf_nbuf_data(bcn->buf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002287 bcn_info.p2pIeOffset = bcn->p2p_ie_offset;
2288 bcn_info.beaconLength = bcn->len;
2289 bcn_info.timIeOffset = bcn->tim_ie_offset;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302290 qdf_spin_unlock_bh(&bcn->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002291
2292 /* Update beacon template in firmware */
Govind Singh61ad2622016-02-22 17:25:02 +05302293 wma_unified_bcn_tmpl_send(wma, if_id, &bcn_info, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002294 }
2295 return 0;
2296}
2297
2298/**
2299 * wma_p2p_go_set_beacon_ie() - set beacon IE for p2p go
2300 * @wma_handle: wma handle
2301 * @vdev_id: vdev id
2302 * @p2pIe: p2p IE
2303 *
2304 * Return: 0 for success or error code
2305 */
2306static int wma_p2p_go_set_beacon_ie(t_wma_handle *wma_handle,
2307 A_UINT32 vdev_id, uint8_t *p2pIe)
2308{
Himanshu Agarwal009f1572016-03-09 17:26:02 +05302309 if (!wma_handle) {
2310 WMA_LOGE("%s: wma handle is NULL", __func__);
2311 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002312 }
2313
Himanshu Agarwal009f1572016-03-09 17:26:02 +05302314 return wmi_unified_p2p_go_set_beacon_ie_cmd(wma_handle->wmi_handle,
2315 vdev_id, p2pIe);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002316}
2317
2318/**
2319 * wma_send_probe_rsp_tmpl() - send probe resp template
2320 * @wma: wma handle
2321 * @probe_rsp_info: probe response info
2322 *
2323 * This funciton sends probe response template to fw which
2324 * firmware will use in case of probe response offload.
2325 *
2326 * Return: none
2327 */
2328void wma_send_probe_rsp_tmpl(tp_wma_handle wma,
2329 tpSendProbeRespParams probe_rsp_info)
2330{
Leo Chang96464902016-10-28 11:10:54 -07002331 void *vdev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002332 uint8_t vdev_id;
2333 tpAniProbeRspStruct probe_rsp;
2334
2335 if (!probe_rsp_info) {
2336 WMA_LOGE(FL("probe_rsp_info is NULL"));
2337 return;
2338 }
2339
2340 probe_rsp = (tpAniProbeRspStruct) (probe_rsp_info->pProbeRespTemplate);
2341 if (!probe_rsp) {
2342 WMA_LOGE(FL("probe_rsp is NULL"));
2343 return;
2344 }
2345
2346 vdev = wma_find_vdev_by_addr(wma, probe_rsp->macHdr.sa, &vdev_id);
2347 if (!vdev) {
2348 WMA_LOGE(FL("failed to get vdev handle"));
2349 return;
2350 }
2351
2352 if (WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
2353 WMI_SERVICE_BEACON_OFFLOAD)) {
2354 WMA_LOGI("Beacon Offload Enabled Sending Unified command");
2355 if (wmi_unified_probe_rsp_tmpl_send(wma, vdev_id,
2356 probe_rsp_info) < 0) {
2357 WMA_LOGE(FL("wmi_unified_probe_rsp_tmpl_send Failed "));
2358 return;
2359 }
2360 }
2361}
2362
2363/**
2364 * wma_send_beacon() - send beacon template
2365 * @wma: wma handle
2366 * @bcn_info: beacon info
2367 *
2368 * This funciton store beacon template locally and
2369 * update keep alive parameters
2370 *
2371 * Return: none
2372 */
2373void wma_send_beacon(tp_wma_handle wma, tpSendbeaconParams bcn_info)
2374{
Leo Chang96464902016-10-28 11:10:54 -07002375 void *vdev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002376 uint8_t vdev_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302377 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002378 uint8_t *p2p_ie;
2379 tpAniBeaconStruct beacon;
Govind Singhd76a5b02016-03-08 15:12:14 +05302380 struct vdev_up_params param = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002381
2382 beacon = (tpAniBeaconStruct) (bcn_info->beacon);
2383 vdev = wma_find_vdev_by_addr(wma, beacon->macHdr.sa, &vdev_id);
2384 if (!vdev) {
2385 WMA_LOGE("%s : failed to get vdev handle", __func__);
2386 return;
2387 }
2388
2389 if (WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
2390 WMI_SERVICE_BEACON_OFFLOAD)) {
2391 WMA_LOGI("Beacon Offload Enabled Sending Unified command");
Govind Singh61ad2622016-02-22 17:25:02 +05302392 status = wma_unified_bcn_tmpl_send(wma, vdev_id, bcn_info, 4);
2393 if (QDF_IS_STATUS_ERROR(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002394 WMA_LOGE("%s : wmi_unified_bcn_tmpl_send Failed ",
2395 __func__);
2396 return;
2397 }
2398
2399 if (bcn_info->p2pIeOffset) {
2400 p2p_ie = bcn_info->beacon + bcn_info->p2pIeOffset;
2401 WMA_LOGI
2402 (" %s: p2pIe is present - vdev_id %hu, p2p_ie = %p, p2p ie len = %hu",
2403 __func__, vdev_id, p2p_ie, p2p_ie[1]);
2404 if (wma_p2p_go_set_beacon_ie(wma, vdev_id, p2p_ie) < 0) {
2405 WMA_LOGE
2406 ("%s : wmi_unified_bcn_tmpl_send Failed ",
2407 __func__);
2408 return;
2409 }
2410 }
2411 }
2412 status = wma_store_bcn_tmpl(wma, vdev_id, bcn_info);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302413 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002414 WMA_LOGE("%s : wma_store_bcn_tmpl Failed", __func__);
2415 return;
2416 }
Agrawal Ashish7dd7c592016-02-22 14:25:11 +05302417 if (!((qdf_atomic_read(
2418 &wma->interfaces[vdev_id].vdev_restart_params.
2419 hidden_ssid_restart_in_progress)) ||
2420 (wma->interfaces[vdev_id].is_channel_switch))) {
2421 if (!wma->interfaces[vdev_id].vdev_up) {
2422 param.vdev_id = vdev_id;
2423 param.assoc_id = 0;
2424 status = wmi_unified_vdev_up_send(wma->wmi_handle,
2425 bcn_info->bssId,
2426 &param);
2427 if (QDF_IS_STATUS_ERROR(status)) {
2428 WMA_LOGE(FL("failed to send vdev up"));
2429 cds_set_do_hw_mode_change_flag(false);
2430 return;
2431 }
2432 wma->interfaces[vdev_id].vdev_up = true;
2433 wma_set_sap_keepalive(wma, vdev_id);
2434
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002435 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002436 }
2437}
2438
2439/**
2440 * wma_set_keepalive_req() - send keep alive request to fw
2441 * @wma: wma handle
2442 * @keepalive: keep alive parameters
2443 *
2444 * Return: none
2445 */
2446void wma_set_keepalive_req(tp_wma_handle wma,
2447 tSirKeepAliveReq *keepalive)
2448{
2449 WMA_LOGD("KEEPALIVE:PacketType:%d", keepalive->packetType);
2450 wma_set_sta_keep_alive(wma, keepalive->sessionId,
2451 keepalive->packetType,
2452 keepalive->timePeriod,
2453 keepalive->hostIpv4Addr,
Srinivas Girigowda9c330a92015-11-24 12:28:25 -08002454 keepalive->destIpv4Addr,
2455 keepalive->dest_macaddr.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002456
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302457 qdf_mem_free(keepalive);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002458}
2459
2460/**
2461 * wma_beacon_miss_handler() - beacon miss event handler
2462 * @wma: wma handle
2463 * @vdev_id: vdev id
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05302464 * @riis: rssi value
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002465 *
2466 * This function send beacon miss indication to upper layers.
2467 *
2468 * Return: none
2469 */
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05302470void wma_beacon_miss_handler(tp_wma_handle wma, uint32_t vdev_id, int32_t rssi)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002471{
2472 tSirSmeMissedBeaconInd *beacon_miss_ind;
2473
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302474 beacon_miss_ind = (tSirSmeMissedBeaconInd *) qdf_mem_malloc
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002475 (sizeof(tSirSmeMissedBeaconInd));
2476
2477 if (NULL == beacon_miss_ind) {
2478 WMA_LOGE("%s: Memory allocation failure", __func__);
2479 return;
2480 }
2481 beacon_miss_ind->messageType = WMA_MISSED_BEACON_IND;
2482 beacon_miss_ind->length = sizeof(tSirSmeMissedBeaconInd);
2483 beacon_miss_ind->bssIdx = vdev_id;
2484
2485 wma_send_msg(wma, WMA_MISSED_BEACON_IND, (void *)beacon_miss_ind, 0);
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05302486 wma_lost_link_info_handler(wma, vdev_id, rssi +
2487 WMA_TGT_NOISE_FLOOR_DBM);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002488}
2489
2490/**
Nirav Shah20489972016-06-16 19:20:28 +05302491 * wma_process_mgmt_tx_completion() - process mgmt completion
2492 * @wma_handle: wma handle
2493 * @desc_id: descriptor id
2494 * @status: status
2495 *
2496 * Return: 0 for success or error code
2497 */
Jeff Johnsonc4b47a92016-10-07 12:34:41 -07002498static int wma_process_mgmt_tx_completion(tp_wma_handle wma_handle,
2499 uint32_t desc_id, uint32_t status)
Nirav Shah20489972016-06-16 19:20:28 +05302500{
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05302501 struct wlan_objmgr_psoc *psoc;
2502 qdf_nbuf_t buf = NULL;
2503 uint8_t vdev_id = 0;
2504 QDF_STATUS ret;
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 Agarwal795b7f72017-01-17 21:19:43 +05302521 buf = mgmt_txrx_get_nbuf(psoc, desc_id);
2522 vdev_id = mgmt_txrx_get_vdev_id(psoc, desc_id);
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05302523
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05302524 if (buf)
2525 qdf_nbuf_unmap_single(wma_handle->qdf_dev, buf,
Nirav Shah20489972016-06-16 19:20:28 +05302526 QDF_DMA_TO_DEVICE);
Himanshu Agarwalf65bd4c2016-12-05 17:21:12 +05302527
Himanshu Agarwalbb226bc2017-01-18 20:45:01 +05302528 packetdump_cb = wma_handle->wma_mgmt_tx_packetdump_cb;
2529 if (packetdump_cb)
2530 packetdump_cb(buf, QDF_STATUS_SUCCESS,
2531 vdev_id, TX_MGMT_PKT);
Himanshu Agarwalf65bd4c2016-12-05 17:21:12 +05302532
Himanshu Agarwal795b7f72017-01-17 21:19:43 +05302533 ret = mgmt_txrx_tx_completion_handler(psoc, desc_id, status, NULL);
Nirav Shah20489972016-06-16 19:20:28 +05302534
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05302535 if (ret != QDF_STATUS_SUCCESS) {
2536 WMA_LOGE("%s: Failed to process mgmt tx completion", __func__);
2537 return -EINVAL;
2538 }
Nirav Shah20489972016-06-16 19:20:28 +05302539
Nirav Shah20489972016-06-16 19:20:28 +05302540 return 0;
2541}
2542
2543/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002544 * wma_mgmt_tx_completion_handler() - wma mgmt Tx completion event handler
2545 * @handle: wma handle
2546 * @cmpl_event_params: completion event handler data
2547 * @len: length of @cmpl_event_params
2548 *
2549 * Return: 0 on success; error number otherwise
2550 */
2551
2552int wma_mgmt_tx_completion_handler(void *handle, uint8_t *cmpl_event_params,
2553 uint32_t len)
2554{
2555 tp_wma_handle wma_handle = (tp_wma_handle)handle;
2556 WMI_MGMT_TX_COMPLETION_EVENTID_param_tlvs *param_buf;
2557 wmi_mgmt_tx_compl_event_fixed_param *cmpl_params;
Naveen Rawat35804772016-06-27 15:40:28 -07002558
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002559 param_buf = (WMI_MGMT_TX_COMPLETION_EVENTID_param_tlvs *)
2560 cmpl_event_params;
Naveen Rawat35804772016-06-27 15:40:28 -07002561 if (!param_buf || !wma_handle) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002562 WMA_LOGE("%s: Invalid mgmt Tx completion event", __func__);
2563 return -EINVAL;
2564 }
2565 cmpl_params = param_buf->fixed_param;
2566
Nirav Shah20489972016-06-16 19:20:28 +05302567 wma_process_mgmt_tx_completion(wma_handle,
2568 cmpl_params->desc_id, cmpl_params->status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002569
Nirav Shah20489972016-06-16 19:20:28 +05302570 return 0;
2571}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002572
Nirav Shah20489972016-06-16 19:20:28 +05302573/**
2574 * wma_mgmt_tx_bundle_completion_handler() - mgmt bundle comp handler
2575 * @handle: wma handle
2576 * @buf: buffer
2577 * @len: length
2578 *
2579 * Return: 0 for success or error code
2580 */
2581int wma_mgmt_tx_bundle_completion_handler(void *handle, uint8_t *buf,
2582 uint32_t len)
2583{
2584 tp_wma_handle wma_handle = (tp_wma_handle)handle;
2585 WMI_MGMT_TX_BUNDLE_COMPLETION_EVENTID_param_tlvs *param_buf;
2586 wmi_mgmt_tx_compl_bundle_event_fixed_param *cmpl_params;
2587 uint32_t num_reports;
2588 uint32_t *desc_ids;
2589 uint32_t *status;
2590 int i;
2591
2592 param_buf = (WMI_MGMT_TX_BUNDLE_COMPLETION_EVENTID_param_tlvs *)buf;
Arif Hussain31576d92016-10-25 14:32:12 -07002593 if (!param_buf || !wma_handle) {
Nirav Shah20489972016-06-16 19:20:28 +05302594 WMA_LOGE("%s: Invalid mgmt Tx completion event", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002595 return -EINVAL;
2596 }
Nirav Shah20489972016-06-16 19:20:28 +05302597 cmpl_params = param_buf->fixed_param;
2598 num_reports = cmpl_params->num_reports;
2599 desc_ids = (uint32_t *)(param_buf->desc_ids);
2600 status = (uint32_t *)(param_buf->status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002601
Nirav Shah20489972016-06-16 19:20:28 +05302602 for (i = 0; i < num_reports; i++)
2603 wma_process_mgmt_tx_completion(wma_handle,
2604 desc_ids[i], status[i]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002605 return 0;
2606}
2607
2608/**
2609 * wma_process_update_opmode() - process update VHT opmode cmd from UMAC
2610 * @wma_handle: wma handle
2611 * @update_vht_opmode: vht opmode
2612 *
2613 * Return: none
2614 */
2615void wma_process_update_opmode(tp_wma_handle wma_handle,
2616 tUpdateVHTOpMode *update_vht_opmode)
2617{
2618 WMA_LOGD("%s: opMode = %d", __func__, update_vht_opmode->opMode);
2619
2620 wma_set_peer_param(wma_handle, update_vht_opmode->peer_mac,
2621 WMI_PEER_CHWIDTH, update_vht_opmode->opMode,
2622 update_vht_opmode->smesessionId);
2623}
2624
2625/**
2626 * wma_process_update_rx_nss() - process update RX NSS cmd from UMAC
2627 * @wma_handle: wma handle
2628 * @update_rx_nss: rx nss value
2629 *
2630 * Return: none
2631 */
2632void wma_process_update_rx_nss(tp_wma_handle wma_handle,
2633 tUpdateRxNss *update_rx_nss)
2634{
2635 struct wma_txrx_node *intr =
2636 &wma_handle->interfaces[update_rx_nss->smesessionId];
2637 int rx_nss = update_rx_nss->rxNss;
2638
2639 wma_update_txrx_chainmask(wma_handle->num_rf_chains, &rx_nss);
2640
2641 intr->nss = (uint8_t)rx_nss;
2642 update_rx_nss->rxNss = (uint32_t)rx_nss;
2643
2644 WMA_LOGD("%s: Rx Nss = %d", __func__, update_rx_nss->rxNss);
2645
2646 wma_set_peer_param(wma_handle, update_rx_nss->peer_mac,
2647 WMI_PEER_NSS, update_rx_nss->rxNss,
2648 update_rx_nss->smesessionId);
2649}
2650
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002651/**
2652 * wma_process_update_membership() - process update group membership cmd
2653 * @wma_handle: wma handle
2654 * @membership: group membership info
2655 *
2656 * Return: none
2657 */
2658void wma_process_update_membership(tp_wma_handle wma_handle,
2659 tUpdateMembership *membership)
2660{
2661 WMA_LOGD("%s: membership = %x ", __func__, membership->membership);
2662
2663 wma_set_peer_param(wma_handle, membership->peer_mac,
2664 WMI_PEER_MEMBERSHIP, membership->membership,
2665 membership->smesessionId);
2666}
2667
2668/**
2669 * wma_process_update_userpos() - process update user pos cmd from UMAC
2670 * @wma_handle: wma handle
2671 * @userpos: user pos value
2672 *
2673 * Return: none
2674 */
2675void wma_process_update_userpos(tp_wma_handle wma_handle,
2676 tUpdateUserPos *userpos)
2677{
2678 WMA_LOGD("%s: userPos = %x ", __func__, userpos->userPos);
2679
2680 wma_set_peer_param(wma_handle, userpos->peer_mac,
2681 WMI_PEER_USERPOS, userpos->userPos,
2682 userpos->smesessionId);
2683
2684 /* Now that membership/userpos is updated in fw,
2685 * enable GID PPS.
2686 */
2687 wma_set_ppsconfig(userpos->smesessionId, WMA_VHT_PPS_GID_MATCH, 1);
2688
2689}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002690
Agrawal Ashishb2d1a452016-05-05 12:23:58 +05302691QDF_STATUS wma_set_cts2self_for_p2p_go(void *wma_handle,
2692 uint32_t cts2self_for_p2p_go)
2693{
2694 int32_t ret;
2695 tp_wma_handle wma = (tp_wma_handle)wma_handle;
2696 struct pdev_params pdevparam;
2697
2698 pdevparam.param_id = WMI_PDEV_PARAM_CTS2SELF_FOR_P2P_GO_CONFIG;
2699 pdevparam.param_value = cts2self_for_p2p_go;
2700
2701 ret = wmi_unified_pdev_param_send(wma->wmi_handle,
2702 &pdevparam,
2703 WMA_WILDCARD_PDEV_ID);
2704 if (ret) {
2705 WMA_LOGE("Fail to Set CTS2SELF for p2p GO %d",
2706 cts2self_for_p2p_go);
2707 return QDF_STATUS_E_FAILURE;
2708 }
2709
2710 WMA_LOGD("Successfully Set CTS2SELF for p2p GO %d",
2711 cts2self_for_p2p_go);
2712
2713 return QDF_STATUS_SUCCESS;
2714}
2715
2716
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002717/**
2718 * wma_set_htconfig() - set ht config parameters to target
2719 * @vdev_id: vdev id
2720 * @ht_capab: ht capablity
2721 * @value: value of ht param
2722 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302723 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002724 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302725QDF_STATUS wma_set_htconfig(uint8_t vdev_id, uint16_t ht_capab, int value)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002726{
Anurag Chouhan6d760662016-02-20 16:05:43 +05302727 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
Govind Singhd76a5b02016-03-08 15:12:14 +05302728 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002729
2730 if (NULL == wma) {
2731 WMA_LOGE("%s: Failed to get wma", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302732 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002733 }
2734
2735 switch (ht_capab) {
2736 case WNI_CFG_HT_CAP_INFO_ADVANCE_CODING:
Govind Singhd76a5b02016-03-08 15:12:14 +05302737 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002738 WMI_VDEV_PARAM_LDPC,
2739 value);
2740 break;
2741 case WNI_CFG_HT_CAP_INFO_TX_STBC:
Govind Singhd76a5b02016-03-08 15:12:14 +05302742 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002743 WMI_VDEV_PARAM_TX_STBC,
2744 value);
2745 break;
2746 case WNI_CFG_HT_CAP_INFO_RX_STBC:
Govind Singhd76a5b02016-03-08 15:12:14 +05302747 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002748 WMI_VDEV_PARAM_RX_STBC,
2749 value);
2750 break;
2751 case WNI_CFG_HT_CAP_INFO_SHORT_GI_20MHZ:
2752 case WNI_CFG_HT_CAP_INFO_SHORT_GI_40MHZ:
2753 WMA_LOGE("%s: ht_capab = %d, value = %d", __func__, ht_capab,
2754 value);
Govind Singhd76a5b02016-03-08 15:12:14 +05302755 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002756 WMI_VDEV_PARAM_SGI, value);
Govind Singhd76a5b02016-03-08 15:12:14 +05302757 if (ret == QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002758 wma->interfaces[vdev_id].config.shortgi = value;
2759 break;
2760 default:
2761 WMA_LOGE("%s:INVALID HT CONFIG", __func__);
2762 }
2763
Govind Singhd76a5b02016-03-08 15:12:14 +05302764 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002765}
2766
2767/**
2768 * wma_hidden_ssid_vdev_restart() - vdev restart for hidden ssid
2769 * @wma_handle: wma handle
2770 * @pReq: hidden ssid vdev restart request
2771 *
2772 * Return: none
2773 */
2774void wma_hidden_ssid_vdev_restart(tp_wma_handle wma_handle,
2775 tHalHiddenSsidVdevRestart *pReq)
2776{
2777 struct wma_txrx_node *intr = wma_handle->interfaces;
Selvaraj, Sridhara0083c42016-06-22 22:15:43 +05302778 struct wma_target_req *msg;
Leo Chang96464902016-10-28 11:10:54 -07002779 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002780
2781 if ((pReq->sessionId !=
2782 intr[pReq->sessionId].vdev_restart_params.vdev_id)
2783 || !((intr[pReq->sessionId].type == WMI_VDEV_TYPE_AP)
2784 && (intr[pReq->sessionId].sub_type == 0))) {
2785 WMA_LOGE("%s : invalid session id", __func__);
2786 return;
2787 }
2788
2789 intr[pReq->sessionId].vdev_restart_params.ssidHidden = pReq->ssidHidden;
Anurag Chouhan8e0ccd32016-02-19 15:30:20 +05302790 qdf_atomic_set(&intr[pReq->sessionId].vdev_restart_params.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002791 hidden_ssid_restart_in_progress, 1);
2792
Selvaraj, Sridhara0083c42016-06-22 22:15:43 +05302793 msg = wma_fill_vdev_req(wma_handle, pReq->sessionId,
2794 WMA_HIDDEN_SSID_VDEV_RESTART,
2795 WMA_TARGET_REQ_TYPE_VDEV_STOP, pReq,
2796 WMA_VDEV_STOP_REQUEST_TIMEOUT);
2797 if (!msg) {
2798 WMA_LOGE("%s: Failed to fill vdev restart request for vdev_id %d",
2799 __func__, pReq->sessionId);
2800 return;
2801 }
2802
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002803 /* vdev stop -> vdev restart -> vdev up */
2804 WMA_LOGD("%s, vdev_id: %d, pausing tx_ll_queue for VDEV_STOP",
2805 __func__, pReq->sessionId);
Leo Chang96464902016-10-28 11:10:54 -07002806 cdp_fc_vdev_pause(soc, wma_handle->interfaces[pReq->sessionId].handle,
2807 OL_TXQ_PAUSE_REASON_VDEV_STOP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002808 wma_handle->interfaces[pReq->sessionId].pause_bitmap |=
2809 (1 << PAUSE_TYPE_HOST);
2810 if (wmi_unified_vdev_stop_send(wma_handle->wmi_handle, pReq->sessionId)) {
2811 WMA_LOGE("%s: %d Failed to send vdev stop", __func__, __LINE__);
Anurag Chouhan8e0ccd32016-02-19 15:30:20 +05302812 qdf_atomic_set(&intr[pReq->sessionId].vdev_restart_params.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002813 hidden_ssid_restart_in_progress, 0);
Selvaraj, Sridhara0083c42016-06-22 22:15:43 +05302814 wma_remove_vdev_req(wma_handle, pReq->sessionId,
2815 WMA_TARGET_REQ_TYPE_VDEV_STOP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002816 return;
2817 }
2818}
2819
2820
2821#ifdef WLAN_FEATURE_11W
2822
2823/**
2824 * wma_extract_ccmp_pn() - extract 6 byte PN from the CCMP header
2825 * @ccmp_ptr: CCMP header
2826 *
2827 * Return: PN extracted from header.
2828 */
2829static uint64_t wma_extract_ccmp_pn(uint8_t *ccmp_ptr)
2830{
2831 uint8_t rsvd, key, pn[6];
2832 uint64_t new_pn;
2833
2834 /*
2835 * +-----+-----+------+----------+-----+-----+-----+-----+
2836 * | PN0 | PN1 | rsvd | rsvd/key | PN2 | PN3 | PN4 | PN5 |
2837 * +-----+-----+------+----------+-----+-----+-----+-----+
2838 * CCMP Header Format
2839 */
2840
2841 /* Extract individual bytes */
2842 pn[0] = (uint8_t) *ccmp_ptr;
2843 pn[1] = (uint8_t) *(ccmp_ptr + 1);
2844 rsvd = (uint8_t) *(ccmp_ptr + 2);
2845 key = (uint8_t) *(ccmp_ptr + 3);
2846 pn[2] = (uint8_t) *(ccmp_ptr + 4);
2847 pn[3] = (uint8_t) *(ccmp_ptr + 5);
2848 pn[4] = (uint8_t) *(ccmp_ptr + 6);
2849 pn[5] = (uint8_t) *(ccmp_ptr + 7);
2850
2851 /* Form 6 byte PN with 6 individual bytes of PN */
2852 new_pn = ((uint64_t) pn[5] << 40) |
2853 ((uint64_t) pn[4] << 32) |
2854 ((uint64_t) pn[3] << 24) |
2855 ((uint64_t) pn[2] << 16) |
2856 ((uint64_t) pn[1] << 8) | ((uint64_t) pn[0] << 0);
2857
2858 WMA_LOGE("PN of received packet is %llu", new_pn);
2859 return new_pn;
2860}
2861
2862/**
2863 * wma_is_ccmp_pn_replay_attack() - detect replay attacking using PN in CCMP
2864 * @cds_ctx: cds context
2865 * @wh: 802.11 frame header
2866 * @ccmp_ptr: CCMP frame header
2867 *
2868 * Return: true/false
2869 */
2870static bool
2871wma_is_ccmp_pn_replay_attack(void *cds_ctx, struct ieee80211_frame *wh,
2872 uint8_t *ccmp_ptr)
2873{
Leo Chang96464902016-10-28 11:10:54 -07002874 void *pdev;
2875 void *vdev;
2876 void *peer;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002877 uint8_t vdev_id, peer_id;
2878 uint8_t *last_pn_valid;
2879 uint64_t *last_pn, new_pn;
2880 uint32_t *rmf_pn_replays;
Leo Chang96464902016-10-28 11:10:54 -07002881 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002882
Anurag Chouhan6d760662016-02-20 16:05:43 +05302883 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002884 if (!pdev) {
2885 WMA_LOGE("%s: Failed to find pdev", __func__);
2886 return true;
2887 }
2888
Mukul Sharmaa748fbb2015-12-01 19:51:36 +05302889 vdev = wma_find_vdev_by_bssid(cds_ctx, wh->i_addr3, &vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002890 if (!vdev) {
2891 WMA_LOGE("%s: Failed to find vdev", __func__);
2892 return true;
2893 }
2894
2895 /* Retrieve the peer based on vdev and addr */
Leo Chang96464902016-10-28 11:10:54 -07002896 peer = cdp_peer_find_by_addr_and_vdev(soc, pdev, vdev, wh->i_addr2,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002897 &peer_id);
2898
2899 if (NULL == peer) {
2900 WMA_LOGE("%s: Failed to find peer, Not able to validate PN",
2901 __func__);
2902 return true;
2903 }
2904
2905 new_pn = wma_extract_ccmp_pn(ccmp_ptr);
Leo Chang96464902016-10-28 11:10:54 -07002906 cdp_get_pn_info(soc, peer, &last_pn_valid, &last_pn, &rmf_pn_replays);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002907
2908 if (*last_pn_valid) {
2909 if (new_pn > *last_pn) {
2910 *last_pn = new_pn;
2911 WMA_LOGE("%s: PN validation successful", __func__);
2912 } else {
2913 WMA_LOGE("%s: PN Replay attack detected", __func__);
2914 /* per 11W amendment, keeping track of replay attacks */
2915 *rmf_pn_replays += 1;
2916 return true;
2917 }
2918 } else {
2919 *last_pn_valid = 1;
2920 *last_pn = new_pn;
2921 }
2922
2923 return false;
2924}
2925
2926/**
mukul sharma72c8b222015-09-04 17:02:01 +05302927 * wma_process_bip() - process mmie in rmf frame
2928 * @wma_handle: wma handle
2929 * @iface: txrx node
2930 * @wh: 80211 frame
2931 * @wbuf: Buffer
2932 *
2933 * Return: 0 for success or error code
2934 */
2935
2936static
2937int wma_process_bip(tp_wma_handle wma_handle,
2938 struct wma_txrx_node *iface,
2939 struct ieee80211_frame *wh,
Nirav Shahcbc6d722016-03-01 16:24:53 +05302940 qdf_nbuf_t wbuf
mukul sharma72c8b222015-09-04 17:02:01 +05302941)
2942{
2943 uint16_t key_id;
2944 uint8_t *efrm;
2945
Nirav Shahcbc6d722016-03-01 16:24:53 +05302946 efrm = qdf_nbuf_data(wbuf) + qdf_nbuf_len(wbuf);
mukul sharma72c8b222015-09-04 17:02:01 +05302947 key_id = (uint16_t)*(efrm - cds_get_mmie_size() + 2);
2948
2949 if (!((key_id == WMA_IGTK_KEY_INDEX_4)
2950 || (key_id == WMA_IGTK_KEY_INDEX_5))) {
2951 WMA_LOGE(FL("Invalid KeyID(%d) dropping the frame"), key_id);
2952 return -EINVAL;
2953 }
2954 if (WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap,
2955 WMI_SERVICE_STA_PMF_OFFLOAD)) {
2956 /*
2957 * if 11w offload is enabled then mmie validation is performed
2958 * in firmware, host just need to trim the mmie.
2959 */
Nirav Shahcbc6d722016-03-01 16:24:53 +05302960 qdf_nbuf_trim_tail(wbuf, cds_get_mmie_size());
mukul sharma72c8b222015-09-04 17:02:01 +05302961 } else {
2962 if (cds_is_mmie_valid(iface->key.key,
2963 iface->key.key_id[key_id - WMA_IGTK_KEY_INDEX_4].ipn,
2964 (uint8_t *) wh, efrm)) {
2965 WMA_LOGE(FL("Protected BC/MC frame MMIE validation successful"));
2966 /* Remove MMIE */
Nirav Shahcbc6d722016-03-01 16:24:53 +05302967 qdf_nbuf_trim_tail(wbuf, cds_get_mmie_size());
mukul sharma72c8b222015-09-04 17:02:01 +05302968 } else {
2969 WMA_LOGE(FL("BC/MC MIC error or MMIE not present, dropping the frame"));
2970 return -EINVAL;
2971 }
2972 }
2973 return 0;
2974}
2975
2976/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002977 * wma_process_rmf_frame() - process rmf frame
2978 * @wma_handle: wma handle
2979 * @iface: txrx node
2980 * @wh: 80211 frame
2981 * @rx_pkt: rx packet
2982 * @wbuf: Buffer
2983 *
2984 * Return: 0 for success or error code
2985 */
2986static
2987int wma_process_rmf_frame(tp_wma_handle wma_handle,
2988 struct wma_txrx_node *iface,
2989 struct ieee80211_frame *wh,
2990 cds_pkt_t *rx_pkt,
Nirav Shahcbc6d722016-03-01 16:24:53 +05302991 qdf_nbuf_t wbuf)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002992{
mukul sharma72c8b222015-09-04 17:02:01 +05302993 uint8_t *orig_hdr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002994 uint8_t *ccmp;
2995
2996 if ((wh)->i_fc[1] & IEEE80211_FC1_WEP) {
2997 if (IEEE80211_IS_BROADCAST(wh->i_addr1) ||
2998 IEEE80211_IS_MULTICAST(wh->i_addr1)) {
2999 WMA_LOGE("Encrypted BC/MC frame dropping the frame");
3000 cds_pkt_return_packet(rx_pkt);
3001 return -EINVAL;
3002 }
3003
Nirav Shahcbc6d722016-03-01 16:24:53 +05303004 orig_hdr = (uint8_t *) qdf_nbuf_data(wbuf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003005 /* Pointer to head of CCMP header */
3006 ccmp = orig_hdr + sizeof(*wh);
3007 if (wma_is_ccmp_pn_replay_attack(
3008 wma_handle, wh, ccmp)) {
3009 WMA_LOGE("Dropping the frame");
3010 cds_pkt_return_packet(rx_pkt);
3011 return -EINVAL;
3012 }
3013
3014 /* Strip privacy headers (and trailer)
3015 * for a received frame
3016 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303017 qdf_mem_move(orig_hdr +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003018 IEEE80211_CCMP_HEADERLEN, wh,
3019 sizeof(*wh));
Nirav Shahcbc6d722016-03-01 16:24:53 +05303020 qdf_nbuf_pull_head(wbuf,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003021 IEEE80211_CCMP_HEADERLEN);
Krunal Soni54da0c62016-08-01 17:04:25 -07003022 qdf_nbuf_trim_tail(wbuf, IEEE80211_CCMP_MICLEN);
3023 /*
3024 * CCMP header has been pulled off
3025 * reinitialize the start pointer of mac header
3026 * to avoid accessing incorrect address
3027 */
3028 wh = (struct ieee80211_frame *) qdf_nbuf_data(wbuf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003029 rx_pkt->pkt_meta.mpdu_hdr_ptr =
Nirav Shahcbc6d722016-03-01 16:24:53 +05303030 qdf_nbuf_data(wbuf);
3031 rx_pkt->pkt_meta.mpdu_len = qdf_nbuf_len(wbuf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003032 rx_pkt->pkt_meta.mpdu_data_len =
3033 rx_pkt->pkt_meta.mpdu_len -
3034 rx_pkt->pkt_meta.mpdu_hdr_len;
3035 rx_pkt->pkt_meta.mpdu_data_ptr =
3036 rx_pkt->pkt_meta.mpdu_hdr_ptr +
3037 rx_pkt->pkt_meta.mpdu_hdr_len;
3038 rx_pkt->pkt_meta.tsf_delta = rx_pkt->pkt_meta.tsf_delta;
3039 rx_pkt->pkt_buf = wbuf;
3040 WMA_LOGD(FL("BSSID: "MAC_ADDRESS_STR" tsf_delta: %u"),
3041 MAC_ADDR_ARRAY(wh->i_addr3), rx_pkt->pkt_meta.tsf_delta);
3042 } else {
3043 if (IEEE80211_IS_BROADCAST(wh->i_addr1) ||
3044 IEEE80211_IS_MULTICAST(wh->i_addr1)) {
mukul sharma72c8b222015-09-04 17:02:01 +05303045 if (0 != wma_process_bip(wma_handle, iface, wh, wbuf)) {
3046 cds_pkt_return_packet(rx_pkt);
3047 return -EINVAL;
Mukul Sharmaa748fbb2015-12-01 19:51:36 +05303048 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003049 } else {
3050 WMA_LOGE("Rx unprotected unicast mgmt frame");
3051 rx_pkt->pkt_meta.dpuFeedback =
3052 DPU_FEEDBACK_UNPROTECTED_ERROR;
3053 }
3054 }
3055 return 0;
3056}
3057#endif
3058
3059/**
Krishna Kumaar Natarajanb7f9a352016-03-18 11:40:07 -07003060 * wma_is_pkt_drop_candidate() - check if the mgmt frame should be droppped
3061 * @wma_handle: wma handle
3062 * @peer_addr: peer MAC address
3063 * @subtype: Management frame subtype
3064 *
3065 * This function is used to decide if a particular management frame should be
3066 * dropped to prevent DOS attack. Timestamp is used to decide the DOS attack.
3067 *
3068 * Return: true if the packet should be dropped and false oterwise
3069 */
3070static bool wma_is_pkt_drop_candidate(tp_wma_handle wma_handle,
3071 uint8_t *peer_addr, uint8_t subtype)
3072{
Leo Chang96464902016-10-28 11:10:54 -07003073 void *peer;
3074 void *pdev_ctx;
Krishna Kumaar Natarajanb7f9a352016-03-18 11:40:07 -07003075 uint8_t peer_id;
3076 bool should_drop = false;
Nishank Aggarwal21282ec2016-12-01 17:41:33 +05303077 qdf_time_t *ptr;
Leo Chang96464902016-10-28 11:10:54 -07003078 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Krishna Kumaar Natarajanb7f9a352016-03-18 11:40:07 -07003079
3080 /*
3081 * Currently this function handles only Disassoc,
3082 * Deauth and Assoc req frames. Return false for
3083 * all other frames.
3084 */
3085 if (subtype != IEEE80211_FC0_SUBTYPE_DISASSOC &&
3086 subtype != IEEE80211_FC0_SUBTYPE_DEAUTH &&
3087 subtype != IEEE80211_FC0_SUBTYPE_ASSOC_REQ) {
3088 should_drop = false;
3089 goto end;
3090 }
3091
3092 pdev_ctx = cds_get_context(QDF_MODULE_ID_TXRX);
3093 if (!pdev_ctx) {
3094 WMA_LOGE(FL("Failed to get the context"));
3095 should_drop = true;
3096 goto end;
3097 }
3098
Leo Chang96464902016-10-28 11:10:54 -07003099 peer = cdp_peer_find_by_addr(soc, pdev_ctx, peer_addr, &peer_id);
Krishna Kumaar Natarajanb7f9a352016-03-18 11:40:07 -07003100 if (!peer) {
3101 if (SIR_MAC_MGMT_ASSOC_REQ != subtype) {
3102 WMA_LOGI(
3103 FL("Received mgmt frame: %0x from unknow peer: %pM"),
3104 subtype, peer_addr);
3105 should_drop = true;
3106 }
3107 goto end;
3108 }
3109
3110 switch (subtype) {
3111 case SIR_MAC_MGMT_ASSOC_REQ:
Nishank Aggarwal21282ec2016-12-01 17:41:33 +05303112 ptr = cdp_peer_last_assoc_received(soc, peer);
3113 if (ptr == NULL) {
3114 WMA_LOGE(FL("cdp_peer_last_assoc_received Failed"));
3115 should_drop = true;
3116 goto end;
3117 } else {
Leo Chang96464902016-10-28 11:10:54 -07003118 if ((qdf_get_system_timestamp() -
3119 *cdp_peer_last_assoc_received(soc, peer)) <
Krishna Kumaar Natarajanb7f9a352016-03-18 11:40:07 -07003120 WMA_MGMT_FRAME_DETECT_DOS_TIMER) {
3121 WMA_LOGI(FL("Dropping Assoc Req received"));
3122 should_drop = true;
3123 }
3124 }
Leo Chang96464902016-10-28 11:10:54 -07003125 *cdp_peer_last_assoc_received(soc, peer) =
3126 qdf_get_system_timestamp();
Krishna Kumaar Natarajanb7f9a352016-03-18 11:40:07 -07003127 break;
3128 case SIR_MAC_MGMT_DISASSOC:
Leo Chang96464902016-10-28 11:10:54 -07003129 if (*cdp_peer_last_disassoc_received(soc, peer)) {
3130 if ((qdf_get_system_timestamp() -
3131 *cdp_peer_last_disassoc_received(soc, peer)) <
Krishna Kumaar Natarajanb7f9a352016-03-18 11:40:07 -07003132 WMA_MGMT_FRAME_DETECT_DOS_TIMER) {
3133 WMA_LOGI(FL("Dropping DisAssoc received"));
3134 should_drop = true;
3135 }
3136 }
Leo Chang96464902016-10-28 11:10:54 -07003137 *cdp_peer_last_disassoc_received(soc, peer) =
3138 qdf_get_system_timestamp();
Krishna Kumaar Natarajanb7f9a352016-03-18 11:40:07 -07003139 break;
3140 case SIR_MAC_MGMT_DEAUTH:
Leo Chang96464902016-10-28 11:10:54 -07003141 if (*cdp_peer_last_deauth_received(soc, peer)) {
3142 if ((qdf_get_system_timestamp() -
3143 *cdp_peer_last_deauth_received(soc, peer)) <
Krishna Kumaar Natarajanb7f9a352016-03-18 11:40:07 -07003144 WMA_MGMT_FRAME_DETECT_DOS_TIMER) {
3145 WMA_LOGI(FL("Dropping Deauth received"));
3146 should_drop = true;
3147 }
3148 }
Leo Chang96464902016-10-28 11:10:54 -07003149 *cdp_peer_last_deauth_received(soc, peer) =
3150 qdf_get_system_timestamp();
Krishna Kumaar Natarajanb7f9a352016-03-18 11:40:07 -07003151 break;
3152 default:
3153 break;
3154 }
3155
3156end:
3157 return should_drop;
3158}
3159
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303160int wma_form_rx_packet(qdf_nbuf_t buf,
3161 void *params,
3162 cds_pkt_t *rx_pkt)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003163{
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303164 wmi_host_mgmt_rx_hdr *mgmt_rx_params =
3165 (wmi_host_mgmt_rx_hdr *)params;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003166 struct wma_txrx_node *iface = NULL;
Mukul Sharmaa748fbb2015-12-01 19:51:36 +05303167 uint8_t vdev_id = WMA_INVALID_VDEV_ID;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003168 struct ieee80211_frame *wh;
3169 uint8_t mgt_type, mgt_subtype;
3170 int status;
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303171 tp_wma_handle wma_handle = (tp_wma_handle)
3172 cds_get_context(QDF_MODULE_ID_WMA);
Himanshu Agarwalbb226bc2017-01-18 20:45:01 +05303173 tp_wma_packetdump_cb packetdump_cb;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003174
3175 if (!wma_handle) {
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303176 WMA_LOGE(FL("wma handle is NULL"));
3177 qdf_nbuf_free(buf);
3178 qdf_mem_free(rx_pkt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003179 return -EINVAL;
3180 }
3181
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303182 if (!mgmt_rx_params) {
3183 WMA_LOGE(FL("mgmt rx params is NULL"));
3184 qdf_nbuf_free(buf);
3185 qdf_mem_free(rx_pkt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003186 return -EINVAL;
3187 }
3188
Rajeev Kumarfec3dbe2016-01-19 15:23:52 -08003189 if (cds_is_load_or_unload_in_progress()) {
Krishna Kumaar Natarajan93c9de12016-06-16 17:04:30 -07003190 WMA_LOGW(FL("Load/Unload in progress"));
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303191 qdf_nbuf_free(buf);
3192 qdf_mem_free(rx_pkt);
Naveen Rawat10ccf872015-11-03 14:15:55 -08003193 return -EINVAL;
3194 }
3195
Mukul Sharma80edc782016-09-12 15:59:24 +05303196 if (cds_is_driver_recovering()) {
3197 WMA_LOGW(FL("Recovery in progress"));
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303198 qdf_nbuf_free(buf);
3199 qdf_mem_free(rx_pkt);
Mukul Sharma80edc782016-09-12 15:59:24 +05303200 return -EINVAL;
3201 }
3202
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003203 /*
3204 * Fill in meta information needed by pe/lim
3205 * TODO: Try to maintain rx metainfo as part of skb->data.
3206 */
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303207 rx_pkt->pkt_meta.channel = mgmt_rx_params->channel;
3208 rx_pkt->pkt_meta.scan_src = mgmt_rx_params->flags;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -07003209
3210 /*
3211 * Get the rssi value from the current snr value
3212 * using standard noise floor of -96.
3213 */
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303214 rx_pkt->pkt_meta.rssi = mgmt_rx_params->snr +
3215 WMA_NOISE_FLOOR_DBM_DEFAULT;
3216 rx_pkt->pkt_meta.snr = mgmt_rx_params->snr;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -07003217
3218 /* If absolute rssi is available from firmware, use it */
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303219 if (mgmt_rx_params->rssi != 0)
3220 rx_pkt->pkt_meta.rssi_raw = mgmt_rx_params->rssi;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -07003221 else
3222 rx_pkt->pkt_meta.rssi_raw = rx_pkt->pkt_meta.rssi;
3223
3224
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003225 /*
3226 * FIXME: Assigning the local timestamp as hw timestamp is not
3227 * available. Need to see if pe/lim really uses this data.
3228 */
3229 rx_pkt->pkt_meta.timestamp = (uint32_t) jiffies;
3230 rx_pkt->pkt_meta.mpdu_hdr_len = sizeof(struct ieee80211_frame);
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303231 rx_pkt->pkt_meta.mpdu_len = mgmt_rx_params->buf_len;
3232 rx_pkt->pkt_meta.mpdu_data_len = mgmt_rx_params->buf_len -
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003233 rx_pkt->pkt_meta.mpdu_hdr_len;
3234
3235 rx_pkt->pkt_meta.roamCandidateInd = 0;
3236
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303237 wh = (struct ieee80211_frame *)qdf_nbuf_data(buf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003238
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303239 rx_pkt->pkt_meta.mpdu_hdr_ptr = qdf_nbuf_data(buf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003240 rx_pkt->pkt_meta.mpdu_data_ptr = rx_pkt->pkt_meta.mpdu_hdr_ptr +
3241 rx_pkt->pkt_meta.mpdu_hdr_len;
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303242 rx_pkt->pkt_meta.tsf_delta = mgmt_rx_params->tsf_delta;
3243 rx_pkt->pkt_buf = buf;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003244
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -07003245 WMA_LOGD(
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303246 FL("BSSID: "MAC_ADDRESS_STR" snr = %d, rssi = %d, rssi_raw = %d tsf_delta: %u"),
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -07003247 MAC_ADDR_ARRAY(wh->i_addr3),
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303248 mgmt_rx_params->snr, rx_pkt->pkt_meta.rssi,
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303249 rx_pkt->pkt_meta.rssi_raw,
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303250 mgmt_rx_params->tsf_delta);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003251
3252 /* If it is a beacon/probe response, save it for future use */
3253 mgt_type = (wh)->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
3254 mgt_subtype = (wh)->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
3255
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003256#ifdef WLAN_FEATURE_11W
3257 if (mgt_type == IEEE80211_FC0_TYPE_MGT &&
3258 (mgt_subtype == IEEE80211_FC0_SUBTYPE_DISASSOC ||
3259 mgt_subtype == IEEE80211_FC0_SUBTYPE_DEAUTH ||
3260 mgt_subtype == IEEE80211_FC0_SUBTYPE_ACTION)) {
Mukul Sharmaa748fbb2015-12-01 19:51:36 +05303261 if (wma_find_vdev_by_bssid(
3262 wma_handle, wh->i_addr3, &vdev_id)) {
3263 iface = &(wma_handle->interfaces[vdev_id]);
3264 if (iface->rmfEnabled) {
3265 status = wma_process_rmf_frame(wma_handle,
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303266 iface, wh, rx_pkt, buf);
3267 if (status != 0)
3268 return status;
Krunal Soni54da0c62016-08-01 17:04:25 -07003269 /*
3270 * CCMP header might have been pulled off
3271 * reinitialize the start pointer of mac header
3272 */
3273 wh = (struct ieee80211_frame *)
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303274 qdf_nbuf_data(buf);
Mukul Sharmaa748fbb2015-12-01 19:51:36 +05303275 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003276 }
3277 }
3278#endif /* WLAN_FEATURE_11W */
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303279
Mukul Sharmaa748fbb2015-12-01 19:51:36 +05303280 rx_pkt->pkt_meta.sessionId =
3281 (vdev_id == WMA_INVALID_VDEV_ID ? 0 : vdev_id);
Krishna Kumaar Natarajanb7f9a352016-03-18 11:40:07 -07003282
3283 if (wma_is_pkt_drop_candidate(wma_handle, wh->i_addr2, mgt_subtype)) {
3284 cds_pkt_return_packet(rx_pkt);
3285 return -EINVAL;
3286 }
3287
Himanshu Agarwalbb226bc2017-01-18 20:45:01 +05303288 packetdump_cb = wma_handle->wma_mgmt_rx_packetdump_cb;
Himanshu Agarwalf65bd4c2016-12-05 17:21:12 +05303289 if ((mgt_type == IEEE80211_FC0_TYPE_MGT &&
3290 mgt_subtype != IEEE80211_FC0_SUBTYPE_BEACON) &&
Himanshu Agarwalbb226bc2017-01-18 20:45:01 +05303291 packetdump_cb)
3292 packetdump_cb(rx_pkt->pkt_buf, QDF_STATUS_SUCCESS,
3293 rx_pkt->pkt_meta.sessionId, RX_MGMT_PKT);
Himanshu Agarwalf65bd4c2016-12-05 17:21:12 +05303294
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303295 return 0;
3296}
3297
3298/**
3299 * wma_mem_endianness_based_copy() - does memory copy from src to dst
3300 * @dst: destination address
3301 * @src: source address
3302 * @size: size to be copied
3303 *
3304 * This function copies the memory of size passed from source
3305 * address to destination address.
3306 *
3307 * Return: Nothing
3308 */
3309#ifdef BIG_ENDIAN_HOST
3310static void wma_mem_endianness_based_copy(
3311 uint8_t *dst, uint8_t *src, uint32_t size)
3312{
3313 /*
3314 * For big endian host, copy engine byte_swap is enabled
3315 * But the rx mgmt frame buffer content is in network byte order
3316 * Need to byte swap the mgmt frame buffer content - so when
3317 * copy engine does byte_swap - host gets buffer content in the
3318 * correct byte order.
3319 */
3320
3321 uint32_t i;
3322 uint32_t *destp, *srcp;
3323
3324 destp = (uint32_t *) dst;
3325 srcp = (uint32_t *) src;
3326 for (i = 0; i < (roundup(size, sizeof(uint32_t)) / 4); i++) {
3327 *destp = cpu_to_le32(*srcp);
3328 destp++;
3329 srcp++;
3330 }
3331}
3332#else
3333static void wma_mem_endianness_based_copy(
3334 uint8_t *dst, uint8_t *src, uint32_t size)
3335{
3336 qdf_mem_copy(dst, src, size);
3337}
3338#endif
3339
3340/**
3341 * wma_mgmt_rx_process() - process management rx frame.
3342 * @handle: wma handle
3343 * @data: rx data
3344 * @data_len: data length
3345 *
3346 * Return: 0 for success or error code
3347 */
3348static int wma_mgmt_rx_process(void *handle, uint8_t *data,
3349 uint32_t data_len)
3350{
3351 tp_wma_handle wma_handle = (tp_wma_handle) handle;
3352 wmi_host_mgmt_rx_hdr *mgmt_rx_params;
3353 struct wlan_objmgr_psoc *psoc;
3354 uint8_t *bufp;
3355 qdf_nbuf_t wbuf;
3356 QDF_STATUS status;
3357
3358 if (!wma_handle) {
3359 WMA_LOGE("%s: Failed to get WMA context", __func__);
3360 return -EINVAL;
3361 }
3362
3363 mgmt_rx_params = qdf_mem_malloc(sizeof(*mgmt_rx_params));
3364 if (!mgmt_rx_params) {
3365 WMA_LOGE("%s: memory allocation failed", __func__);
3366 return -ENOMEM;
3367 }
3368
3369 if (wmi_extract_mgmt_rx_params(wma_handle->wmi_handle,
3370 data, mgmt_rx_params, &bufp) != QDF_STATUS_SUCCESS) {
3371 WMA_LOGE("%s: Extraction of mgmt rx params failed", __func__);
3372 qdf_mem_free(mgmt_rx_params);
3373 return -EINVAL;
3374 }
3375
3376 wbuf = qdf_nbuf_alloc(NULL, roundup(mgmt_rx_params->buf_len, 4),
3377 0, 4, false);
3378 if (!wbuf) {
3379 WMA_LOGE("%s: Failed to allocate wbuf for mgmt rx len(%u)",
3380 __func__, mgmt_rx_params->buf_len);
3381 qdf_mem_free(mgmt_rx_params);
3382 return -ENOMEM;
3383 }
3384
3385 qdf_nbuf_put_tail(wbuf, mgmt_rx_params->buf_len);
3386 qdf_nbuf_set_protocol(wbuf, ETH_P_CONTROL);
3387
3388 wma_mem_endianness_based_copy(qdf_nbuf_data(wbuf),
3389 bufp, mgmt_rx_params->buf_len);
3390
3391 psoc = (struct wlan_objmgr_psoc *)
3392 wma_handle->psoc;
3393 if (!psoc) {
3394 WMA_LOGE("%s: psoc ctx is NULL", __func__);
3395 qdf_nbuf_free(wbuf);
3396 qdf_mem_free(mgmt_rx_params);
3397 return -EINVAL;
3398 }
3399
Himanshu Agarwal795b7f72017-01-17 21:19:43 +05303400 status = mgmt_txrx_rx_handler(psoc, wbuf, mgmt_rx_params);
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303401 if (status != QDF_STATUS_SUCCESS) {
3402 WMA_LOGE("%s: Failed to process mgmt rx frame", __func__);
3403 qdf_mem_free(mgmt_rx_params);
3404 return -EINVAL;
3405 }
3406
3407 qdf_mem_free(mgmt_rx_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003408 return 0;
3409}
3410
3411/**
3412 * wma_de_register_mgmt_frm_client() - deregister management frame
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303413 *
3414 * This function deregisters the event handler registered for
3415 * WMI_MGMT_RX_EVENTID.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003416 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303417 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003418 */
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303419QDF_STATUS wma_de_register_mgmt_frm_client(void)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003420{
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303421 tp_wma_handle wma_handle = (tp_wma_handle)
3422 cds_get_context(QDF_MODULE_ID_WMA);
3423
3424 if (!wma_handle) {
3425 WMA_LOGE("%s: Failed to get WMA context", __func__);
3426 return QDF_STATUS_E_NULL_VALUE;
3427 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003428
3429#ifdef QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +05303430 if (cds_get_conparam() == QDF_GLOBAL_FTM_MODE)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303431 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003432#endif
3433
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003434 if (wmi_unified_unregister_event_handler(wma_handle->wmi_handle,
3435 WMI_MGMT_RX_EVENTID) != 0) {
3436 WMA_LOGE("Failed to Unregister rx mgmt handler with wmi");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303437 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003438 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303439 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003440}
3441
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003442#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003443/**
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003444 * wma_register_roaming_callbacks() - Register roaming callbacks
3445 * @cds_ctx: CDS Context
3446 * @csr_roam_synch_cb: CSR roam synch callback routine pointer
3447 * @pe_roam_synch_cb: PE roam synch callback routine pointer
3448 *
3449 * Register the SME and PE callback routines with WMA for
3450 * handling roaming
3451 *
3452 * Return: Success or Failure Status
3453 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303454QDF_STATUS wma_register_roaming_callbacks(void *cds_ctx,
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003455 void (*csr_roam_synch_cb)(tpAniSirGlobal mac,
3456 roam_offload_synch_ind *roam_synch_data,
Varun Reddy Yeturuf907f912016-03-21 15:06:22 -07003457 tpSirBssDescription bss_desc_ptr,
3458 enum sir_roam_op_code reason),
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303459 QDF_STATUS (*pe_roam_synch_cb)(tpAniSirGlobal mac,
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003460 roam_offload_synch_ind *roam_synch_data,
3461 tpSirBssDescription bss_desc_ptr))
3462{
3463
Anurag Chouhan6d760662016-02-20 16:05:43 +05303464 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003465
3466 if (!wma) {
3467 WMA_LOGE("%s: Failed to get WMA context", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303468 return QDF_STATUS_E_FAILURE;
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003469 }
3470 wma->csr_roam_synch_cb = csr_roam_synch_cb;
3471 wma->pe_roam_synch_cb = pe_roam_synch_cb;
3472 WMA_LOGD("Registered roam synch callbacks with WMA successfully");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303473 return QDF_STATUS_SUCCESS;
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003474}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003475#endif
3476
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003477/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003478 * wma_register_mgmt_frm_client() - register management frame callback
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303479 *
3480 * This function registers event handler for WMI_MGMT_RX_EVENTID.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003481 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303482 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003483 */
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303484QDF_STATUS wma_register_mgmt_frm_client(void)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003485{
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303486 tp_wma_handle wma_handle = (tp_wma_handle)
3487 cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003488
3489 if (!wma_handle) {
3490 WMA_LOGE("%s: Failed to get WMA context", __func__);
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303491 return QDF_STATUS_E_NULL_VALUE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003492 }
3493
3494 if (wmi_unified_register_event_handler(wma_handle->wmi_handle,
3495 WMI_MGMT_RX_EVENTID,
Govind Singhd76a5b02016-03-08 15:12:14 +05303496 wma_mgmt_rx_process,
3497 WMA_RX_WORK_CTX) != 0) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003498 WMA_LOGE("Failed to register rx mgmt handler with wmi");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303499 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003500 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003501
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303502 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003503}
Himanshu Agarwalf65bd4c2016-12-05 17:21:12 +05303504
3505/**
3506 * wma_register_packetdump_callback() - stores tx and rx mgmt packet dump
3507 * callback handler
3508 * @wma_mgmt_tx_packetdump_cb: tx mgmt packetdump cb
3509 * @wma_mgmt_rx_packetdump_cb: rx mgmt packetdump cb
3510 *
3511 * This function is used to store tx and rx mgmt. packet dump callback
3512 *
3513 * Return: None
3514 *
3515 */
3516void wma_register_packetdump_callback(
3517 tp_wma_packetdump_cb wma_mgmt_tx_packetdump_cb,
3518 tp_wma_packetdump_cb wma_mgmt_rx_packetdump_cb)
3519{
3520 tp_wma_handle wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
3521
3522 if (!wma_handle) {
3523 WMA_LOGE("wma handle is NULL");
3524 return;
3525 }
3526
3527 wma_handle->wma_mgmt_tx_packetdump_cb = wma_mgmt_tx_packetdump_cb;
3528 wma_handle->wma_mgmt_rx_packetdump_cb = wma_mgmt_rx_packetdump_cb;
3529}
3530
3531/**
3532 * wma_deregister_packetdump_callback() - removes tx and rx mgmt packet dump
3533 * callback handler
3534 *
3535 * This function is used to remove tx and rx mgmt. packet dump callback
3536 *
3537 * Return: None
3538 *
3539 */
3540void wma_deregister_packetdump_callback(void)
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 = NULL;
3550 wma_handle->wma_mgmt_rx_packetdump_cb = NULL;
3551}
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +05303552
3553QDF_STATUS wma_mgmt_unified_cmd_send(struct wlan_objmgr_vdev *vdev,
3554 qdf_nbuf_t buf, uint32_t desc_id,
3555 void *mgmt_tx_params)
3556{
3557 tp_wma_handle wma_handle;
3558 QDF_STATUS status;
3559 struct wmi_mgmt_params *mgmt_params =
3560 (struct wmi_mgmt_params *)mgmt_tx_params;
3561
3562 if (!mgmt_params) {
3563 WMA_LOGE("%s: mgmt_params ptr passed is NULL", __func__);
3564 return QDF_STATUS_E_INVAL;
3565 }
3566 mgmt_params->desc_id = desc_id;
3567
3568 if (!vdev) {
3569 WMA_LOGE("%s: vdev ptr passed is NULL", __func__);
3570 return QDF_STATUS_E_INVAL;
3571 }
3572
3573 wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
3574 if (!wma_handle) {
3575 WMA_LOGE("%s: wma handle is NULL", __func__);
3576 return QDF_STATUS_E_INVAL;
3577 }
3578
3579 status = wmi_mgmt_unified_cmd_send(wma_handle->wmi_handle,
3580 mgmt_params);
3581 if (status != QDF_STATUS_SUCCESS) {
3582 WMA_LOGE("%s: mgmt tx failed", __func__);
3583 return status;
3584 }
3585
3586 return QDF_STATUS_SUCCESS;
3587}
3588