xref: /wlan-dirver/qcacld-3.0/core/wma/src/wma_mgmt.c (revision 63d7e2a202b3cd37d6c1c20a39582b297a267b6b)
1 /*
2  * Copyright (c) 2013-2021 The Linux Foundation. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for
5  * any purpose with or without fee is hereby granted, provided that the
6  * above copyright notice and this permission notice appear in all
7  * copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16  * PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 /**
20  *  DOC:  wma_mgmt.c
21  *
22  *  This file contains STA/SAP and protocol related functions.
23  */
24 
25 /* Header files */
26 
27 #include "wma.h"
28 #include "wma_api.h"
29 #include "cds_api.h"
30 #include "wmi_unified_api.h"
31 #include "wlan_qct_sys.h"
32 #include "wni_api.h"
33 #include "ani_global.h"
34 #include "wmi_unified.h"
35 #include "wni_cfg.h"
36 
37 #include "qdf_nbuf.h"
38 #include "qdf_types.h"
39 #include "qdf_mem.h"
40 
41 #include "wma_types.h"
42 #include "lim_api.h"
43 #include "lim_session_utils.h"
44 
45 #include "cds_utils.h"
46 #include "wlan_blm_api.h"
47 #if !defined(REMOVE_PKT_LOG)
48 #include "pktlog_ac.h"
49 #else
50 #include "pktlog_ac_fmt.h"
51 #endif /* REMOVE_PKT_LOG */
52 
53 #include "dbglog_host.h"
54 #include "csr_api.h"
55 #include "ol_fw.h"
56 #include "wma_internal.h"
57 #include "wlan_policy_mgr_api.h"
58 #include "cdp_txrx_flow_ctrl_legacy.h"
59 #include <cdp_txrx_peer_ops.h>
60 #include <cdp_txrx_pmf.h>
61 #include <cdp_txrx_cfg.h>
62 #include <cdp_txrx_cmn.h>
63 #include <cdp_txrx_misc.h>
64 #include <cdp_txrx_misc.h>
65 #include "wlan_mgmt_txrx_tgt_api.h"
66 #include "wlan_objmgr_psoc_obj.h"
67 #include "wlan_objmgr_pdev_obj.h"
68 #include "wlan_objmgr_vdev_obj.h"
69 #include "wlan_lmac_if_api.h"
70 #include <cdp_txrx_handle.h>
71 #include "wma_he.h"
72 #include "wma_eht.h"
73 #include <qdf_crypto.h>
74 #include "wma_twt.h"
75 #include "wlan_p2p_cfg_api.h"
76 #include "cfg_ucfg_api.h"
77 #include "cfg_mlme_sta.h"
78 #include "wlan_mlme_api.h"
79 #include "wmi_unified_bcn_api.h"
80 #include <wlan_crypto_global_api.h>
81 #include <wlan_mlme_main.h>
82 #include <../../core/src/vdev_mgr_ops.h>
83 #include "wlan_pkt_capture_ucfg_api.h"
84 
85 #if !defined(REMOVE_PKT_LOG)
86 #include <wlan_logging_sock_svc.h>
87 #endif
88 #include "wlan_cm_roam_api.h"
89 
90 /**
91  * wma_send_bcn_buf_ll() - prepare and send beacon buffer to fw for LL
92  * @wma: wma handle
93  * @vdev_id: vdev id
94  * @param_buf: SWBA parameters
95  *
96  * Return: none
97  */
98 #ifdef WLAN_WMI_BCN
99 static void wma_send_bcn_buf_ll(tp_wma_handle wma,
100 				uint8_t vdev_id,
101 				WMI_HOST_SWBA_EVENTID_param_tlvs *param_buf)
102 {
103 	struct ieee80211_frame *wh;
104 	struct beacon_info *bcn;
105 	wmi_tim_info *tim_info = param_buf->tim_info;
106 	uint8_t *bcn_payload;
107 	QDF_STATUS ret;
108 	struct beacon_tim_ie *tim_ie;
109 	wmi_p2p_noa_info *p2p_noa_info = param_buf->p2p_noa_info;
110 	struct p2p_sub_element_noa noa_ie;
111 	struct wmi_bcn_send_from_host params;
112 	uint8_t i;
113 
114 	bcn = wma->interfaces[vdev_id].beacon;
115 	if (!bcn || !bcn->buf) {
116 		wma_err("Invalid beacon buffer");
117 		return;
118 	}
119 
120 	if (!param_buf->tim_info || !param_buf->p2p_noa_info) {
121 		wma_err("Invalid tim info or p2p noa info");
122 		return;
123 	}
124 
125 	if (WMI_UNIFIED_NOA_ATTR_NUM_DESC_GET(p2p_noa_info) >
126 			WMI_P2P_MAX_NOA_DESCRIPTORS) {
127 		wma_err("Too many descriptors %d",
128 			WMI_UNIFIED_NOA_ATTR_NUM_DESC_GET(p2p_noa_info));
129 		return;
130 	}
131 
132 	qdf_spin_lock_bh(&bcn->lock);
133 
134 	bcn_payload = qdf_nbuf_data(bcn->buf);
135 
136 	tim_ie = (struct beacon_tim_ie *)(&bcn_payload[bcn->tim_ie_offset]);
137 
138 	if (tim_info->tim_changed) {
139 		if (tim_info->tim_num_ps_pending)
140 			qdf_mem_copy(&tim_ie->tim_bitmap, tim_info->tim_bitmap,
141 				     WMA_TIM_SUPPORTED_PVB_LENGTH);
142 		else
143 			qdf_mem_zero(&tim_ie->tim_bitmap,
144 				     WMA_TIM_SUPPORTED_PVB_LENGTH);
145 		/*
146 		 * Currently we support fixed number of
147 		 * peers as limited by HAL_NUM_STA.
148 		 * tim offset is always 0
149 		 */
150 		tim_ie->tim_bitctl = 0;
151 	}
152 
153 	/* Update DTIM Count */
154 	if (tim_ie->dtim_count == 0)
155 		tim_ie->dtim_count = tim_ie->dtim_period - 1;
156 	else
157 		tim_ie->dtim_count--;
158 
159 	/*
160 	 * DTIM count needs to be backedup so that
161 	 * when umac updates the beacon template
162 	 * current dtim count can be updated properly
163 	 */
164 	bcn->dtim_count = tim_ie->dtim_count;
165 
166 	/* update state for buffered multicast frames on DTIM */
167 	if (tim_info->tim_mcast && (tim_ie->dtim_count == 0 ||
168 				    tim_ie->dtim_period == 1))
169 		tim_ie->tim_bitctl |= 1;
170 	else
171 		tim_ie->tim_bitctl &= ~1;
172 
173 	/* To avoid sw generated frame sequence the same as H/W generated frame,
174 	 * the value lower than min_sw_seq is reserved for HW generated frame
175 	 */
176 	if ((bcn->seq_no & IEEE80211_SEQ_MASK) < MIN_SW_SEQ)
177 		bcn->seq_no = MIN_SW_SEQ;
178 
179 	wh = (struct ieee80211_frame *)bcn_payload;
180 	*(uint16_t *) &wh->i_seq[0] = htole16(bcn->seq_no
181 					      << IEEE80211_SEQ_SEQ_SHIFT);
182 	bcn->seq_no++;
183 
184 	if (WMI_UNIFIED_NOA_ATTR_IS_MODIFIED(p2p_noa_info)) {
185 		qdf_mem_zero(&noa_ie, sizeof(noa_ie));
186 
187 		noa_ie.index =
188 			(uint8_t) WMI_UNIFIED_NOA_ATTR_INDEX_GET(p2p_noa_info);
189 		noa_ie.oppPS =
190 			(uint8_t) WMI_UNIFIED_NOA_ATTR_OPP_PS_GET(p2p_noa_info);
191 		noa_ie.ctwindow =
192 			(uint8_t) WMI_UNIFIED_NOA_ATTR_CTWIN_GET(p2p_noa_info);
193 		noa_ie.num_descriptors = (uint8_t)
194 				WMI_UNIFIED_NOA_ATTR_NUM_DESC_GET(p2p_noa_info);
195 		wma_debug("index %u, oppPs %u, ctwindow %u, num_descriptors = %u",
196 			 noa_ie.index,
197 			 noa_ie.oppPS, noa_ie.ctwindow, noa_ie.num_descriptors);
198 		for (i = 0; i < noa_ie.num_descriptors; i++) {
199 			noa_ie.noa_descriptors[i].type_count =
200 				(uint8_t) p2p_noa_info->noa_descriptors[i].
201 				type_count;
202 			noa_ie.noa_descriptors[i].duration =
203 				p2p_noa_info->noa_descriptors[i].duration;
204 			noa_ie.noa_descriptors[i].interval =
205 				p2p_noa_info->noa_descriptors[i].interval;
206 			noa_ie.noa_descriptors[i].start_time =
207 				p2p_noa_info->noa_descriptors[i].start_time;
208 			wma_debug("NoA descriptor[%d] type_count %u, duration %u, interval %u, start_time = %u",
209 				 i,
210 				 noa_ie.noa_descriptors[i].type_count,
211 				 noa_ie.noa_descriptors[i].duration,
212 				 noa_ie.noa_descriptors[i].interval,
213 				 noa_ie.noa_descriptors[i].start_time);
214 		}
215 		wma_update_noa(bcn, &noa_ie);
216 
217 		/* Send a msg to LIM to update the NoA IE in probe response
218 		 * frames transmitted by the host
219 		 */
220 		wma_update_probe_resp_noa(wma, &noa_ie);
221 	}
222 
223 	if (bcn->dma_mapped) {
224 		qdf_nbuf_unmap_single(wma->qdf_dev, bcn->buf, QDF_DMA_TO_DEVICE);
225 		bcn->dma_mapped = 0;
226 	}
227 	ret = qdf_nbuf_map_single(wma->qdf_dev, bcn->buf, QDF_DMA_TO_DEVICE);
228 	if (ret != QDF_STATUS_SUCCESS) {
229 		wma_err("failed map beacon buf to DMA region");
230 		qdf_spin_unlock_bh(&bcn->lock);
231 		return;
232 	}
233 
234 	bcn->dma_mapped = 1;
235 	params.vdev_id = vdev_id;
236 	params.data_len = bcn->len;
237 	params.frame_ctrl = *((A_UINT16 *) wh->i_fc);
238 	params.frag_ptr = qdf_nbuf_get_frag_paddr(bcn->buf, 0);
239 	params.dtim_flag = 0;
240 	/* notify Firmware of DTM and mcast/bcast traffic */
241 	if (tim_ie->dtim_count == 0) {
242 		params.dtim_flag |= WMI_BCN_SEND_DTIM_ZERO;
243 		/* deliver mcast/bcast traffic in next DTIM beacon */
244 		if (tim_ie->tim_bitctl & 0x01)
245 			params.dtim_flag |= WMI_BCN_SEND_DTIM_BITCTL_SET;
246 	}
247 
248 	wmi_unified_bcn_buf_ll_cmd(wma->wmi_handle,
249 					&params);
250 
251 	qdf_spin_unlock_bh(&bcn->lock);
252 }
253 #else
254 static inline void
255 wma_send_bcn_buf_ll(tp_wma_handle wma,
256 		    uint8_t vdev_id,
257 		    WMI_HOST_SWBA_EVENTID_param_tlvs *param_buf)
258 {
259 }
260 #endif
261 /**
262  * wma_beacon_swba_handler() - swba event handler
263  * @handle: wma handle
264  * @event: event data
265  * @len: data length
266  *
267  * SWBA event is alert event to Host requesting host to Queue a beacon
268  * for transmission use only in host beacon mode
269  *
270  * Return: 0 for success or error code
271  */
272 #ifdef WLAN_WMI_BCN
273 int wma_beacon_swba_handler(void *handle, uint8_t *event, uint32_t len)
274 {
275 	tp_wma_handle wma = (tp_wma_handle) handle;
276 	WMI_HOST_SWBA_EVENTID_param_tlvs *param_buf;
277 	wmi_host_swba_event_fixed_param *swba_event;
278 	uint32_t vdev_map;
279 	uint8_t vdev_id = 0;
280 	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
281 
282 	param_buf = (WMI_HOST_SWBA_EVENTID_param_tlvs *) event;
283 	if (!param_buf) {
284 		wma_err("Invalid swba event buffer");
285 		return -EINVAL;
286 	}
287 	swba_event = param_buf->fixed_param;
288 	vdev_map = swba_event->vdev_map;
289 
290 	wma_debug("vdev_map = %d", vdev_map);
291 	for (; vdev_map && vdev_id < wma->max_bssid;
292 			vdev_id++, vdev_map >>= 1) {
293 		if (!(vdev_map & 0x1))
294 			continue;
295 		if (!cdp_cfg_is_high_latency(soc,
296 			(struct cdp_cfg *)cds_get_context(QDF_MODULE_ID_CFG)))
297 			wma_send_bcn_buf_ll(wma, vdev_id, param_buf);
298 		break;
299 	}
300 	return 0;
301 }
302 #else
303 static inline int
304 wma_beacon_swba_handler(void *handle, uint8_t *event, uint32_t len)
305 {
306 	return 0;
307 }
308 #endif
309 
310 #ifdef FEATURE_WLAN_DIAG_SUPPORT
311 void wma_sta_kickout_event(uint32_t kickout_reason, uint8_t vdev_id,
312 			   uint8_t *macaddr)
313 {
314 	WLAN_HOST_DIAG_EVENT_DEF(sta_kickout, struct host_event_wlan_kickout);
315 	qdf_mem_zero(&sta_kickout, sizeof(sta_kickout));
316 	sta_kickout.reasoncode = kickout_reason;
317 	sta_kickout.vdev_id = vdev_id;
318 	if (macaddr)
319 		qdf_mem_copy(sta_kickout.peer_mac, macaddr,
320 			     QDF_MAC_ADDR_SIZE);
321 	WLAN_HOST_DIAG_EVENT_REPORT(&sta_kickout, EVENT_WLAN_STA_KICKOUT);
322 }
323 #endif
324 
325 int wma_peer_sta_kickout_event_handler(void *handle, uint8_t *event,
326 				       uint32_t len)
327 {
328 	tp_wma_handle wma = (tp_wma_handle) handle;
329 	WMI_PEER_STA_KICKOUT_EVENTID_param_tlvs *param_buf = NULL;
330 	wmi_peer_sta_kickout_event_fixed_param *kickout_event = NULL;
331 	uint8_t vdev_id, macaddr[QDF_MAC_ADDR_SIZE];
332 	tpDeleteStaContext del_sta_ctx;
333 	uint8_t *addr, *bssid;
334 	struct wlan_objmgr_vdev *vdev;
335 	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
336 
337 	param_buf = (WMI_PEER_STA_KICKOUT_EVENTID_param_tlvs *) event;
338 	kickout_event = param_buf->fixed_param;
339 	WMI_MAC_ADDR_TO_CHAR_ARRAY(&kickout_event->peer_macaddr, macaddr);
340 	if (cdp_peer_get_vdevid(soc, macaddr, &vdev_id) !=
341 			QDF_STATUS_SUCCESS) {
342 		wma_err("Not able to find BSSID for peer ["QDF_MAC_ADDR_FMT"]",
343 			 QDF_MAC_ADDR_REF(macaddr));
344 		return -EINVAL;
345 	}
346 	vdev = wma->interfaces[vdev_id].vdev;
347 	if (!vdev) {
348 		wma_err("Not able to find vdev for VDEV_%d", vdev_id);
349 		return -EINVAL;
350 	}
351 	addr = wlan_vdev_mlme_get_macaddr(vdev);
352 
353 	wma_nofl_info("STA kickout for "QDF_MAC_ADDR_FMT", on mac "QDF_MAC_ADDR_FMT", vdev %d, reason:%d",
354 		      QDF_MAC_ADDR_REF(macaddr), QDF_MAC_ADDR_REF(addr),
355 		      vdev_id, kickout_event->reason);
356 
357 	if (wma->interfaces[vdev_id].roaming_in_progress) {
358 		wma_err("Ignore STA kick out since roaming is in progress");
359 		return -EINVAL;
360 	}
361 	bssid = wma_get_vdev_bssid(wma->interfaces[vdev_id].vdev);
362 	if (!bssid) {
363 		wma_err("Failed to get bssid for vdev_%d", vdev_id);
364 		return -ENOMEM;
365 	}
366 
367 	switch (kickout_event->reason) {
368 	case WMI_PEER_STA_KICKOUT_REASON_IBSS_DISCONNECT:
369 		goto exit_handler;
370 #ifdef FEATURE_WLAN_TDLS
371 	case WMI_PEER_STA_KICKOUT_REASON_TDLS_DISCONNECT:
372 		del_sta_ctx = (tpDeleteStaContext)
373 			qdf_mem_malloc(sizeof(tDeleteStaContext));
374 		if (!del_sta_ctx) {
375 			wma_err("mem alloc failed for struct del_sta_context for TDLS peer: "QDF_MAC_ADDR_FMT,
376 				QDF_MAC_ADDR_REF(macaddr));
377 			return -ENOMEM;
378 		}
379 
380 		del_sta_ctx->is_tdls = true;
381 		del_sta_ctx->vdev_id = vdev_id;
382 		qdf_mem_copy(del_sta_ctx->addr2, macaddr, QDF_MAC_ADDR_SIZE);
383 		qdf_mem_copy(del_sta_ctx->bssId, bssid,
384 			     QDF_MAC_ADDR_SIZE);
385 		del_sta_ctx->reasonCode = HAL_DEL_STA_REASON_CODE_KEEP_ALIVE;
386 		wma_send_msg(wma, SIR_LIM_DELETE_STA_CONTEXT_IND,
387 			     (void *)del_sta_ctx, 0);
388 		goto exit_handler;
389 #endif /* FEATURE_WLAN_TDLS */
390 
391 	case WMI_PEER_STA_KICKOUT_REASON_UNSPECIFIED:
392 		/*
393 		 * Default legacy value used by original firmware implementation
394 		 */
395 		if (wma->interfaces[vdev_id].type == WMI_VDEV_TYPE_STA &&
396 		    (wma->interfaces[vdev_id].sub_type == 0 ||
397 		     wma->interfaces[vdev_id].sub_type ==
398 		     WMI_UNIFIED_VDEV_SUBTYPE_P2P_CLIENT) &&
399 		    !qdf_mem_cmp(bssid,
400 				    macaddr, QDF_MAC_ADDR_SIZE)) {
401 			wma_sta_kickout_event(
402 			HOST_STA_KICKOUT_REASON_UNSPECIFIED, vdev_id, macaddr);
403 			/*
404 			 * KICKOUT event is for current station-AP connection.
405 			 * Treat it like final beacon miss. Station may not have
406 			 * missed beacons but not able to transmit frames to AP
407 			 * for a long time. Must disconnect to get out of
408 			 * this sticky situation.
409 			 * In future implementation, roaming module will also
410 			 * handle this event and perform a scan.
411 			 */
412 			wma_warn("WMI_PEER_STA_KICKOUT_REASON_UNSPECIFIED event for STA");
413 			wma_beacon_miss_handler(wma, vdev_id,
414 						kickout_event->rssi);
415 			goto exit_handler;
416 		}
417 		break;
418 
419 	case WMI_PEER_STA_KICKOUT_REASON_XRETRY:
420 	case WMI_PEER_STA_KICKOUT_REASON_INACTIVITY:
421 	/*
422 	 * Handle SA query kickout is same as inactivity kickout.
423 	 * This could be for STA or SAP role
424 	 */
425 	case WMI_PEER_STA_KICKOUT_REASON_SA_QUERY_TIMEOUT:
426 	default:
427 		break;
428 	}
429 
430 	/*
431 	 * default action is to send delete station context indication to LIM
432 	 */
433 	del_sta_ctx =
434 		(tDeleteStaContext *) qdf_mem_malloc(sizeof(tDeleteStaContext));
435 	if (!del_sta_ctx) {
436 		wma_err("QDF MEM Alloc Failed for struct del_sta_context");
437 		return -ENOMEM;
438 	}
439 
440 	del_sta_ctx->is_tdls = false;
441 	del_sta_ctx->vdev_id = vdev_id;
442 	qdf_mem_copy(del_sta_ctx->addr2, macaddr, QDF_MAC_ADDR_SIZE);
443 	qdf_mem_copy(del_sta_ctx->bssId, addr, QDF_MAC_ADDR_SIZE);
444 	if (kickout_event->reason ==
445 		WMI_PEER_STA_KICKOUT_REASON_SA_QUERY_TIMEOUT)
446 		del_sta_ctx->reasonCode =
447 			HAL_DEL_STA_REASON_CODE_SA_QUERY_TIMEOUT;
448 	else if (kickout_event->reason == WMI_PEER_STA_KICKOUT_REASON_XRETRY)
449 		del_sta_ctx->reasonCode = HAL_DEL_STA_REASON_CODE_XRETRY;
450 	else
451 		del_sta_ctx->reasonCode = HAL_DEL_STA_REASON_CODE_KEEP_ALIVE;
452 
453 	if (wmi_service_enabled(wma->wmi_handle,
454 				wmi_service_hw_db2dbm_support))
455 		del_sta_ctx->rssi = kickout_event->rssi;
456 	else
457 		del_sta_ctx->rssi = kickout_event->rssi +
458 					WMA_TGT_NOISE_FLOOR_DBM;
459 	wma_sta_kickout_event(del_sta_ctx->reasonCode, vdev_id, macaddr);
460 	wma_send_msg(wma, SIR_LIM_DELETE_STA_CONTEXT_IND, (void *)del_sta_ctx,
461 		     0);
462 	wma_lost_link_info_handler(wma, vdev_id, del_sta_ctx->rssi);
463 
464 exit_handler:
465 	return 0;
466 }
467 
468 int wma_unified_bcntx_status_event_handler(void *handle,
469 					   uint8_t *cmd_param_info,
470 					   uint32_t len)
471 {
472 	tp_wma_handle wma = (tp_wma_handle) handle;
473 	WMI_OFFLOAD_BCN_TX_STATUS_EVENTID_param_tlvs *param_buf;
474 	wmi_offload_bcn_tx_status_event_fixed_param *resp_event;
475 	tSirFirstBeaconTxCompleteInd *beacon_tx_complete_ind;
476 
477 	param_buf =
478 		(WMI_OFFLOAD_BCN_TX_STATUS_EVENTID_param_tlvs *) cmd_param_info;
479 	if (!param_buf) {
480 		wma_err("Invalid bcn tx response event buffer");
481 		return -EINVAL;
482 	}
483 
484 	resp_event = param_buf->fixed_param;
485 
486 	if (resp_event->vdev_id >= wma->max_bssid) {
487 		wma_err("received invalid vdev_id %d", resp_event->vdev_id);
488 		return -EINVAL;
489 	}
490 
491 	/* Check for valid handle to ensure session is not
492 	 * deleted in any race
493 	 */
494 	if (!wma->interfaces[resp_event->vdev_id].vdev) {
495 		wma_err("vdev is NULL for vdev_%d", resp_event->vdev_id);
496 		return -EINVAL;
497 	}
498 
499 	/* Beacon Tx Indication supports only AP mode. Ignore in other modes */
500 	if (wma_is_vdev_in_ap_mode(wma, resp_event->vdev_id) == false) {
501 		wma_debug("Beacon Tx Indication does not support type %d and sub_type %d",
502 			 wma->interfaces[resp_event->vdev_id].type,
503 			 wma->interfaces[resp_event->vdev_id].sub_type);
504 		return 0;
505 	}
506 
507 	beacon_tx_complete_ind = (tSirFirstBeaconTxCompleteInd *)
508 			qdf_mem_malloc(sizeof(tSirFirstBeaconTxCompleteInd));
509 	if (!beacon_tx_complete_ind) {
510 		wma_err("Failed to alloc beacon_tx_complete_ind");
511 		return -ENOMEM;
512 	}
513 
514 	beacon_tx_complete_ind->messageType = WMA_DFS_BEACON_TX_SUCCESS_IND;
515 	beacon_tx_complete_ind->length = sizeof(tSirFirstBeaconTxCompleteInd);
516 	beacon_tx_complete_ind->bss_idx = resp_event->vdev_id;
517 
518 	wma_send_msg(wma, WMA_DFS_BEACON_TX_SUCCESS_IND,
519 		     (void *)beacon_tx_complete_ind, 0);
520 	return 0;
521 }
522 
523 /**
524  * wma_get_go_probe_timeout() - get P2P GO probe timeout
525  * @mac: UMAC handler
526  * @max_inactive_time: return max inactive time
527  * @max_unresponsive_time: return max unresponsive time
528  *
529  * Return: none
530  */
531 #ifdef CONVERGED_P2P_ENABLE
532 static inline void
533 wma_get_go_probe_timeout(struct mac_context *mac,
534 			 uint32_t *max_inactive_time,
535 			 uint32_t *max_unresponsive_time)
536 {
537 	uint32_t keep_alive;
538 	QDF_STATUS status;
539 
540 	status = cfg_p2p_get_go_link_monitor_period(mac->psoc,
541 						    max_inactive_time);
542 	if (QDF_IS_STATUS_ERROR(status)) {
543 		wma_err("Failed to go monitor period");
544 		*max_inactive_time = WMA_LINK_MONITOR_DEFAULT_TIME_SECS;
545 	}
546 	status = cfg_p2p_get_go_keepalive_period(mac->psoc,
547 						 &keep_alive);
548 	if (QDF_IS_STATUS_ERROR(status)) {
549 		wma_err("Failed to read go keep alive");
550 		keep_alive = WMA_KEEP_ALIVE_DEFAULT_TIME_SECS;
551 	}
552 
553 	*max_unresponsive_time = *max_inactive_time + keep_alive;
554 }
555 #else
556 static inline void
557 wma_get_go_probe_timeout(struct mac_context *mac,
558 			 uint32_t *max_inactive_time,
559 			 uint32_t *max_unresponsive_time)
560 {
561 }
562 #endif
563 
564 /**
565  * wma_get_link_probe_timeout() - get link timeout based on sub type
566  * @mac: UMAC handler
567  * @sub_type: vdev syb type
568  * @max_inactive_time: return max inactive time
569  * @max_unresponsive_time: return max unresponsive time
570  *
571  * Return: none
572  */
573 static inline void
574 wma_get_link_probe_timeout(struct mac_context *mac,
575 			   uint32_t sub_type,
576 			   uint32_t *max_inactive_time,
577 			   uint32_t *max_unresponsive_time)
578 {
579 	if (sub_type == WMI_UNIFIED_VDEV_SUBTYPE_P2P_GO) {
580 		wma_get_go_probe_timeout(mac, max_inactive_time,
581 					 max_unresponsive_time);
582 	} else {
583 		*max_inactive_time =
584 			mac->mlme_cfg->timeouts.ap_link_monitor_timeout;
585 		*max_unresponsive_time = *max_inactive_time +
586 			mac->mlme_cfg->timeouts.ap_keep_alive_timeout;
587 	}
588 }
589 
590 /**
591  * wma_verify_rate_code() - verify if rate code is valid.
592  * @rate_code:     rate code
593  * @band:     band information
594  *
595  * Return: verify result
596  */
597 static bool wma_verify_rate_code(u_int32_t rate_code, enum cds_band_type band)
598 {
599 	uint8_t preamble, nss, rate;
600 	bool valid = true;
601 
602 	preamble = (rate_code & 0xc0) >> 6;
603 	nss = (rate_code & 0x30) >> 4;
604 	rate = rate_code & 0xf;
605 
606 	switch (preamble) {
607 	case WMI_RATE_PREAMBLE_CCK:
608 		if (nss != 0 || rate > 3 || band == CDS_BAND_5GHZ)
609 			valid = false;
610 		break;
611 	case WMI_RATE_PREAMBLE_OFDM:
612 		if (nss != 0 || rate > 7)
613 			valid = false;
614 		break;
615 	case WMI_RATE_PREAMBLE_HT:
616 		if (nss != 0 || rate > 7)
617 			valid = false;
618 		break;
619 	case WMI_RATE_PREAMBLE_VHT:
620 		if (nss != 0 || rate > 9)
621 			valid = false;
622 		break;
623 	default:
624 		break;
625 	}
626 	return valid;
627 }
628 
629 #define TX_MGMT_RATE_2G_ENABLE_OFFSET 30
630 #define TX_MGMT_RATE_5G_ENABLE_OFFSET 31
631 #define TX_MGMT_RATE_2G_OFFSET 0
632 #define TX_MGMT_RATE_5G_OFFSET 12
633 
634 /**
635  * wma_set_mgmt_rate() - set vdev mgmt rate.
636  * @wma:     wma handle
637  * @vdev_id: vdev id
638  *
639  * Return: None
640  */
641 void wma_set_vdev_mgmt_rate(tp_wma_handle wma, uint8_t vdev_id)
642 {
643 	uint32_t cfg_val;
644 	int ret;
645 	uint32_t per_band_mgmt_tx_rate = 0;
646 	enum cds_band_type band = 0;
647 	struct mac_context *mac = cds_get_context(QDF_MODULE_ID_PE);
648 
649 	if (!mac) {
650 		wma_err("Failed to get mac");
651 		return;
652 	}
653 
654 	cfg_val = mac->mlme_cfg->sap_cfg.rate_tx_mgmt;
655 	band = CDS_BAND_ALL;
656 	if ((cfg_val == MLME_CFG_TX_MGMT_RATE_DEF) ||
657 	    !wma_verify_rate_code(cfg_val, band)) {
658 		wma_nofl_debug("default WNI_CFG_RATE_FOR_TX_MGMT, ignore");
659 	} else {
660 		ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
661 					 WMI_VDEV_PARAM_MGMT_TX_RATE,
662 					 cfg_val);
663 		if (ret)
664 			wma_err("Failed to set WMI_VDEV_PARAM_MGMT_TX_RATE");
665 	}
666 
667 	cfg_val = mac->mlme_cfg->sap_cfg.rate_tx_mgmt_2g;
668 	band = CDS_BAND_2GHZ;
669 	if ((cfg_val == MLME_CFG_TX_MGMT_2G_RATE_DEF) ||
670 	    !wma_verify_rate_code(cfg_val, band)) {
671 		wma_nofl_debug("use default 2G MGMT rate.");
672 		per_band_mgmt_tx_rate &=
673 		    ~(1 << TX_MGMT_RATE_2G_ENABLE_OFFSET);
674 	} else {
675 		per_band_mgmt_tx_rate |=
676 		    (1 << TX_MGMT_RATE_2G_ENABLE_OFFSET);
677 		per_band_mgmt_tx_rate |=
678 		    ((cfg_val & 0x7FF) << TX_MGMT_RATE_2G_OFFSET);
679 	}
680 
681 	cfg_val = mac->mlme_cfg->sap_cfg.rate_tx_mgmt;
682 	band = CDS_BAND_5GHZ;
683 	if ((cfg_val == MLME_CFG_TX_MGMT_5G_RATE_DEF) ||
684 	    !wma_verify_rate_code(cfg_val, band)) {
685 		wma_nofl_debug("use default 5G MGMT rate.");
686 		per_band_mgmt_tx_rate &=
687 		    ~(1 << TX_MGMT_RATE_5G_ENABLE_OFFSET);
688 	} else {
689 		per_band_mgmt_tx_rate |=
690 		    (1 << TX_MGMT_RATE_5G_ENABLE_OFFSET);
691 		per_band_mgmt_tx_rate |=
692 		    ((cfg_val & 0x7FF) << TX_MGMT_RATE_5G_OFFSET);
693 	}
694 
695 	ret = wma_vdev_set_param(
696 		wma->wmi_handle,
697 		vdev_id,
698 		WMI_VDEV_PARAM_PER_BAND_MGMT_TX_RATE,
699 		per_band_mgmt_tx_rate);
700 	if (ret)
701 		wma_err("Failed to set WMI_VDEV_PARAM_PER_BAND_MGMT_TX_RATE");
702 
703 }
704 
705 /**
706  * wma_set_sap_keepalive() - set SAP keep alive parameters to fw
707  * @wma: wma handle
708  * @vdev_id: vdev id
709  *
710  * Return: none
711  */
712 void wma_set_sap_keepalive(tp_wma_handle wma, uint8_t vdev_id)
713 {
714 	uint32_t min_inactive_time, max_inactive_time, max_unresponsive_time;
715 	struct mac_context *mac = cds_get_context(QDF_MODULE_ID_PE);
716 	QDF_STATUS status;
717 
718 	if (!mac) {
719 		wma_err("Failed to get mac");
720 		return;
721 	}
722 
723 	wma_get_link_probe_timeout(mac, wma->interfaces[vdev_id].sub_type,
724 				   &max_inactive_time, &max_unresponsive_time);
725 
726 	min_inactive_time = max_inactive_time / 2;
727 
728 	status = wma_vdev_set_param(wma->wmi_handle, vdev_id,
729 			WMI_VDEV_PARAM_AP_KEEPALIVE_MIN_IDLE_INACTIVE_TIME_SECS,
730 			min_inactive_time);
731 	if (QDF_IS_STATUS_ERROR(status))
732 		wma_err("Failed to Set AP MIN IDLE INACTIVE TIME");
733 
734 	status = wma_vdev_set_param(wma->wmi_handle, vdev_id,
735 			WMI_VDEV_PARAM_AP_KEEPALIVE_MAX_IDLE_INACTIVE_TIME_SECS,
736 			max_inactive_time);
737 	if (QDF_IS_STATUS_ERROR(status))
738 		wma_err("Failed to Set AP MAX IDLE INACTIVE TIME");
739 
740 	status = wma_vdev_set_param(wma->wmi_handle, vdev_id,
741 			WMI_VDEV_PARAM_AP_KEEPALIVE_MAX_UNRESPONSIVE_TIME_SECS,
742 			max_unresponsive_time);
743 	if (QDF_IS_STATUS_ERROR(status))
744 		wma_err("Failed to Set MAX UNRESPONSIVE TIME");
745 
746 	wma_debug("vdev_id:%d min_inactive_time: %u max_inactive_time: %u max_unresponsive_time: %u",
747 		  vdev_id, min_inactive_time, max_inactive_time,
748 		  max_unresponsive_time);
749 }
750 
751 /**
752  * wma_set_sta_sa_query_param() - set sta sa query parameters
753  * @wma: wma handle
754  * @vdev_id: vdev id
755 
756  * This function sets sta query related parameters in fw.
757  *
758  * Return: none
759  */
760 
761 void wma_set_sta_sa_query_param(tp_wma_handle wma,
762 				  uint8_t vdev_id)
763 {
764 	struct mac_context *mac = cds_get_context(QDF_MODULE_ID_PE);
765 	uint8_t max_retries;
766 	uint16_t retry_interval;
767 
768 	if (!mac) {
769 		wma_err("mac context is NULL");
770 		return;
771 	}
772 
773 	max_retries = mac->mlme_cfg->gen.pmf_sa_query_max_retries;
774 	retry_interval = mac->mlme_cfg->gen.pmf_sa_query_retry_interval;
775 
776 	wmi_unified_set_sta_sa_query_param_cmd(wma->wmi_handle,
777 						vdev_id,
778 						max_retries,
779 						retry_interval);
780 }
781 
782 /**
783  * wma_set_sta_keep_alive() - set sta keep alive parameters
784  * @wma: wma handle
785  * @vdev_id: vdev id
786  * @method: method for keep alive
787  * @timeperiod: time period
788  * @hostv4addr: host ipv4 address
789  * @destv4addr: dst ipv4 address
790  * @destmac: destination mac
791  *
792  * This function sets keep alive related parameters in fw.
793  *
794  * Return: none
795  */
796 void wma_set_sta_keep_alive(tp_wma_handle wma, uint8_t vdev_id,
797 			    uint32_t method, uint32_t timeperiod,
798 			    uint8_t *hostv4addr, uint8_t *destv4addr,
799 			    uint8_t *destmac)
800 {
801 	struct sta_keep_alive_params params = { 0 };
802 	struct wma_txrx_node *intr;
803 
804 	if (wma_validate_handle(wma))
805 		return;
806 
807 	intr = &wma->interfaces[vdev_id];
808 	if (timeperiod > cfg_max(CFG_INFRA_STA_KEEP_ALIVE_PERIOD)) {
809 		wmi_err("Invalid period %d Max limit %d", timeperiod,
810 			 cfg_max(CFG_INFRA_STA_KEEP_ALIVE_PERIOD));
811 		return;
812 	}
813 
814 	params.vdev_id = vdev_id;
815 	params.method = method;
816 	params.timeperiod = timeperiod;
817 	if (intr) {
818 		if (intr->bss_max_idle_period)
819 			params.timeperiod = intr->bss_max_idle_period;
820 	}
821 
822 	if (hostv4addr)
823 		qdf_mem_copy(params.hostv4addr, hostv4addr, QDF_IPV4_ADDR_SIZE);
824 	if (destv4addr)
825 		qdf_mem_copy(params.destv4addr, destv4addr, QDF_IPV4_ADDR_SIZE);
826 	if (destmac)
827 		qdf_mem_copy(params.destmac, destmac, QDF_MAC_ADDR_SIZE);
828 
829 	wmi_unified_set_sta_keep_alive_cmd(wma->wmi_handle, &params);
830 }
831 
832 /**
833  * wma_vdev_install_key_complete_event_handler() - install key complete handler
834  * @handle: wma handle
835  * @event: event data
836  * @len: data length
837  *
838  * This event is sent by fw once WPA/WPA2 keys are installed in fw.
839  *
840  * Return: 0 for success or error code
841  */
842 int wma_vdev_install_key_complete_event_handler(void *handle,
843 						uint8_t *event,
844 						uint32_t len)
845 {
846 	WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID_param_tlvs *param_buf = NULL;
847 	wmi_vdev_install_key_complete_event_fixed_param *key_fp = NULL;
848 
849 	if (!event) {
850 		wma_err("event param null");
851 		return -EINVAL;
852 	}
853 
854 	param_buf = (WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID_param_tlvs *) event;
855 	if (!param_buf) {
856 		wma_err("received null buf from target");
857 		return -EINVAL;
858 	}
859 
860 	key_fp = param_buf->fixed_param;
861 	if (!key_fp) {
862 		wma_err("received null event data from target");
863 		return -EINVAL;
864 	}
865 	/*
866 	 * Do nothing for now. Completion of set key is already indicated to lim
867 	 */
868 	wma_debug("WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID");
869 	return 0;
870 }
871 /*
872  * 802.11n D2.0 defined values for "Minimum MPDU Start Spacing":
873  *   0 for no restriction
874  *   1 for 1/4 us - Our lower layer calculations limit our precision to 1 msec
875  *   2 for 1/2 us - Our lower layer calculations limit our precision to 1 msec
876  *   3 for 1 us
877  *   4 for 2 us
878  *   5 for 4 us
879  *   6 for 8 us
880  *   7 for 16 us
881  */
882 static const uint8_t wma_mpdu_spacing[] = { 0, 1, 1, 1, 2, 4, 8, 16 };
883 
884 /**
885  * wma_parse_mpdudensity() - give mpdu spacing from mpdu density
886  * @mpdudensity: mpdu density
887  *
888  * Return: mpdu spacing or 0 for error
889  */
890 static inline uint8_t wma_parse_mpdudensity(uint8_t mpdudensity)
891 {
892 	if (mpdudensity < sizeof(wma_mpdu_spacing))
893 		return wma_mpdu_spacing[mpdudensity];
894 	else
895 		return 0;
896 }
897 
898 #define CFG_CTRL_MASK              0xFF00
899 #define CFG_DATA_MASK              0x00FF
900 
901 /**
902  * wma_mask_tx_ht_rate() - mask tx ht rate based on config
903  * @wma:     wma handle
904  * @mcs_set  mcs set buffer
905  *
906  * Return: None
907  */
908 static void wma_mask_tx_ht_rate(tp_wma_handle wma, uint8_t *mcs_set)
909 {
910 	uint32_t i, j;
911 	uint16_t mcs_limit;
912 	uint8_t *rate_pos = mcs_set;
913 	struct mac_context *mac = wma->mac_context;
914 
915 	/*
916 	 * Get MCS limit from ini configure, and map it to rate parameters
917 	 * This will limit HT rate upper bound. CFG_CTRL_MASK is used to
918 	 * check whether ini config is enabled and CFG_DATA_MASK to get the
919 	 * MCS value.
920 	 */
921 	mcs_limit = mac->mlme_cfg->rates.max_htmcs_txdata;
922 
923 	if (mcs_limit & CFG_CTRL_MASK) {
924 		wma_debug("set mcs_limit %x", mcs_limit);
925 
926 		mcs_limit &= CFG_DATA_MASK;
927 		for (i = 0, j = 0; i < MAX_SUPPORTED_RATES;) {
928 			if (j < mcs_limit / 8) {
929 				rate_pos[j] = 0xff;
930 				j++;
931 				i += 8;
932 			} else if (j < mcs_limit / 8 + 1) {
933 				if (i <= mcs_limit)
934 					rate_pos[i / 8] |= 1 << (i % 8);
935 				else
936 					rate_pos[i / 8] &= ~(1 << (i % 8));
937 				i++;
938 
939 				if (i >= (j + 1) * 8)
940 					j++;
941 			} else {
942 				rate_pos[j++] = 0;
943 				i += 8;
944 			}
945 		}
946 	}
947 }
948 
949 #if SUPPORT_11AX
950 /**
951  * wma_fw_to_host_phymode_11ax() - convert fw to host phymode for 11ax phymodes
952  * @phymode: phymode to convert
953  *
954  * Return: one of the 11ax values defined in enum wlan_phymode;
955  *         or WLAN_PHYMODE_AUTO if the input is not an 11ax phymode
956  */
957 static enum wlan_phymode
958 wma_fw_to_host_phymode_11ax(WMI_HOST_WLAN_PHY_MODE phymode)
959 {
960 	switch (phymode) {
961 	default:
962 		return WLAN_PHYMODE_AUTO;
963 	case WMI_HOST_MODE_11AX_HE20:
964 		return WLAN_PHYMODE_11AXA_HE20;
965 	case WMI_HOST_MODE_11AX_HE40:
966 		return WLAN_PHYMODE_11AXA_HE40;
967 	case WMI_HOST_MODE_11AX_HE80:
968 		return WLAN_PHYMODE_11AXA_HE80;
969 	case WMI_HOST_MODE_11AX_HE80_80:
970 		return WLAN_PHYMODE_11AXA_HE80_80;
971 	case WMI_HOST_MODE_11AX_HE160:
972 		return WLAN_PHYMODE_11AXA_HE160;
973 	case WMI_HOST_MODE_11AX_HE20_2G:
974 		return WLAN_PHYMODE_11AXG_HE20;
975 	case WMI_HOST_MODE_11AX_HE40_2G:
976 		return WLAN_PHYMODE_11AXG_HE40;
977 	case WMI_HOST_MODE_11AX_HE80_2G:
978 		return WLAN_PHYMODE_11AXG_HE80;
979 	}
980 	return WLAN_PHYMODE_AUTO;
981 }
982 #else
983 static enum wlan_phymode
984 wma_fw_to_host_phymode_11ax(WMI_HOST_WLAN_PHY_MODE phymode)
985 {
986 	return WLAN_PHYMODE_AUTO;
987 }
988 #endif
989 
990 #ifdef WLAN_FEATURE_11BE
991 /**
992  * wma_fw_to_host_phymode_11be() - convert fw to host phymode for 11be phymodes
993  * @phymode: phymode to convert
994  *
995  * Return: one of the 11be values defined in enum wlan_phymode;
996  *         or WLAN_PHYMODE_AUTO if the input is not an 11be phymode
997  */
998 static enum wlan_phymode
999 wma_fw_to_host_phymode_11be(WMI_HOST_WLAN_PHY_MODE phymode)
1000 {
1001 	switch (phymode) {
1002 	default:
1003 		return WLAN_PHYMODE_AUTO;
1004 	case WMI_HOST_MODE_11BE_EHT20:
1005 		return WLAN_PHYMODE_11BEA_EHT20;
1006 	case WMI_HOST_MODE_11BE_EHT40:
1007 		return WLAN_PHYMODE_11BEA_EHT40;
1008 	case WMI_HOST_MODE_11BE_EHT80:
1009 		return WLAN_PHYMODE_11BEA_EHT80;
1010 	case WMI_HOST_MODE_11BE_EHT160:
1011 		return WLAN_PHYMODE_11BEA_EHT160;
1012 	case WMI_HOST_MODE_11BE_EHT320:
1013 		return WLAN_PHYMODE_11BEA_EHT320;
1014 	case WMI_HOST_MODE_11BE_EHT20_2G:
1015 		return WLAN_PHYMODE_11BEG_EHT20;
1016 	case WMI_HOST_MODE_11BE_EHT40_2G:
1017 		return WLAN_PHYMODE_11BEG_EHT40;
1018 	}
1019 	return WLAN_PHYMODE_AUTO;
1020 }
1021 #else
1022 static enum wlan_phymode
1023 wma_fw_to_host_phymode_11be(WMI_HOST_WLAN_PHY_MODE phymode)
1024 {
1025 	return WLAN_PHYMODE_AUTO;
1026 }
1027 #endif
1028 
1029 #ifdef CONFIG_160MHZ_SUPPORT
1030 /**
1031  * wma_fw_to_host_phymode_160() - convert fw to host phymode for 160 mhz
1032  * phymodes
1033  * @phymode: phymode to convert
1034  *
1035  * Return: one of the 160 mhz values defined in enum wlan_phymode;
1036  *         or WLAN_PHYMODE_AUTO if the input is not a 160 mhz phymode
1037  */
1038 static enum wlan_phymode
1039 wma_fw_to_host_phymode_160(WMI_HOST_WLAN_PHY_MODE phymode)
1040 {
1041 	switch (phymode) {
1042 	default:
1043 		return WLAN_PHYMODE_AUTO;
1044 	case WMI_HOST_MODE_11AC_VHT80_80:
1045 		return WLAN_PHYMODE_11AC_VHT80_80;
1046 	case WMI_HOST_MODE_11AC_VHT160:
1047 		return WLAN_PHYMODE_11AC_VHT160;
1048 	}
1049 }
1050 #else
1051 static enum wlan_phymode
1052 wma_fw_to_host_phymode_160(WMI_HOST_WLAN_PHY_MODE phymode)
1053 {
1054 	return WLAN_PHYMODE_AUTO;
1055 }
1056 #endif
1057 
1058 enum wlan_phymode wma_fw_to_host_phymode(WMI_HOST_WLAN_PHY_MODE phymode)
1059 {
1060 	enum wlan_phymode host_phymode;
1061 	switch (phymode) {
1062 	default:
1063 		host_phymode = wma_fw_to_host_phymode_160(phymode);
1064 		if (host_phymode != WLAN_PHYMODE_AUTO)
1065 			return host_phymode;
1066 		host_phymode = wma_fw_to_host_phymode_11ax(phymode);
1067 		if (host_phymode != WLAN_PHYMODE_AUTO)
1068 			return host_phymode;
1069 		return wma_fw_to_host_phymode_11be(phymode);
1070 	case WMI_HOST_MODE_11A:
1071 		return WLAN_PHYMODE_11A;
1072 	case WMI_HOST_MODE_11G:
1073 		return WLAN_PHYMODE_11G;
1074 	case WMI_HOST_MODE_11B:
1075 		return WLAN_PHYMODE_11B;
1076 	case WMI_HOST_MODE_11GONLY:
1077 		return WLAN_PHYMODE_11G_ONLY;
1078 	case WMI_HOST_MODE_11NA_HT20:
1079 		return WLAN_PHYMODE_11NA_HT20;
1080 	case WMI_HOST_MODE_11NG_HT20:
1081 		return WLAN_PHYMODE_11NG_HT20;
1082 	case WMI_HOST_MODE_11NA_HT40:
1083 		return WLAN_PHYMODE_11NA_HT40;
1084 	case WMI_HOST_MODE_11NG_HT40:
1085 		return WLAN_PHYMODE_11NG_HT40;
1086 	case WMI_HOST_MODE_11AC_VHT20:
1087 		return WLAN_PHYMODE_11AC_VHT20;
1088 	case WMI_HOST_MODE_11AC_VHT40:
1089 		return WLAN_PHYMODE_11AC_VHT40;
1090 	case WMI_HOST_MODE_11AC_VHT80:
1091 		return WLAN_PHYMODE_11AC_VHT80;
1092 	case WMI_HOST_MODE_11AC_VHT20_2G:
1093 		return WLAN_PHYMODE_11AC_VHT20_2G;
1094 	case WMI_HOST_MODE_11AC_VHT40_2G:
1095 		return WLAN_PHYMODE_11AC_VHT40_2G;
1096 	case WMI_HOST_MODE_11AC_VHT80_2G:
1097 		return WLAN_PHYMODE_11AC_VHT80_2G;
1098 	}
1099 }
1100 
1101 #ifdef CONFIG_160MHZ_SUPPORT
1102 /**
1103  * wma_host_to_fw_phymode_160() - convert host to fw phymode for 160 mhz
1104  * @host_phymode: phymode to convert
1105  *
1106  * Return: one of the 160 mhz values defined in enum WMI_HOST_WLAN_PHY_MODE;
1107  *         or WMI_HOST_MODE_UNKNOWN if the input is not a 160 mhz phymode
1108  */
1109 static WMI_HOST_WLAN_PHY_MODE
1110 wma_host_to_fw_phymode_160(enum wlan_phymode host_phymode)
1111 {
1112 	switch (host_phymode) {
1113 	case WLAN_PHYMODE_11AC_VHT80_80:
1114 		return WMI_HOST_MODE_11AC_VHT80_80;
1115 	case WLAN_PHYMODE_11AC_VHT160:
1116 		return WMI_HOST_MODE_11AC_VHT160;
1117 	default:
1118 		return WMI_HOST_MODE_UNKNOWN;
1119 	}
1120 }
1121 #else
1122 static WMI_HOST_WLAN_PHY_MODE
1123 wma_host_to_fw_phymode_160(enum wlan_phymode host_phymode)
1124 {
1125 	return WMI_HOST_MODE_UNKNOWN;
1126 }
1127 #endif
1128 
1129 #if SUPPORT_11AX
1130 /**
1131  * wma_host_to_fw_phymode_11ax() - convert host to fw phymode for 11ax phymode
1132  * @host_phymode: phymode to convert
1133  *
1134  * Return: one of the 11ax values defined in enum WMI_HOST_WLAN_PHY_MODE;
1135  *         or WMI_HOST_MODE_UNKNOWN if the input is not an 11ax phymode
1136  */
1137 static WMI_HOST_WLAN_PHY_MODE
1138 wma_host_to_fw_phymode_11ax(enum wlan_phymode host_phymode)
1139 {
1140 	switch (host_phymode) {
1141 	case WLAN_PHYMODE_11AXA_HE20:
1142 		return WMI_HOST_MODE_11AX_HE20;
1143 	case WLAN_PHYMODE_11AXA_HE40:
1144 		return WMI_HOST_MODE_11AX_HE40;
1145 	case WLAN_PHYMODE_11AXA_HE80:
1146 		return WMI_HOST_MODE_11AX_HE80;
1147 	case WLAN_PHYMODE_11AXA_HE80_80:
1148 		return WMI_HOST_MODE_11AX_HE80_80;
1149 	case WLAN_PHYMODE_11AXA_HE160:
1150 		return WMI_HOST_MODE_11AX_HE160;
1151 	case WLAN_PHYMODE_11AXG_HE20:
1152 		return WMI_HOST_MODE_11AX_HE20_2G;
1153 	case WLAN_PHYMODE_11AXG_HE40:
1154 	case WLAN_PHYMODE_11AXG_HE40PLUS:
1155 	case WLAN_PHYMODE_11AXG_HE40MINUS:
1156 		return WMI_HOST_MODE_11AX_HE40_2G;
1157 	case WLAN_PHYMODE_11AXG_HE80:
1158 		return WMI_HOST_MODE_11AX_HE80_2G;
1159 	default:
1160 		return WMI_HOST_MODE_UNKNOWN;
1161 	}
1162 }
1163 #else
1164 static WMI_HOST_WLAN_PHY_MODE
1165 wma_host_to_fw_phymode_11ax(enum wlan_phymode host_phymode)
1166 {
1167 	return WMI_HOST_MODE_UNKNOWN;
1168 }
1169 #endif
1170 
1171 #ifdef WLAN_FEATURE_11BE
1172 /**
1173  * wma_host_to_fw_phymode_11be() - convert host to fw phymode for 11be phymode
1174  * @host_phymode: phymode to convert
1175  *
1176  * Return: one of the 11be values defined in enum WMI_HOST_WLAN_PHY_MODE;
1177  *         or WMI_HOST_MODE_UNKNOWN if the input is not an 11be phymode
1178  */
1179 static WMI_HOST_WLAN_PHY_MODE
1180 wma_host_to_fw_phymode_11be(enum wlan_phymode host_phymode)
1181 {
1182 	switch (host_phymode) {
1183 	case WLAN_PHYMODE_11BEA_EHT20:
1184 		return WMI_HOST_MODE_11BE_EHT20;
1185 	case WLAN_PHYMODE_11BEA_EHT40:
1186 		return WMI_HOST_MODE_11BE_EHT40;
1187 	case WLAN_PHYMODE_11BEA_EHT80:
1188 		return WMI_HOST_MODE_11BE_EHT80;
1189 	case WLAN_PHYMODE_11BEA_EHT160:
1190 		return WMI_HOST_MODE_11BE_EHT160;
1191 	case WLAN_PHYMODE_11BEA_EHT320:
1192 		return WMI_HOST_MODE_11BE_EHT320;
1193 	case WLAN_PHYMODE_11BEG_EHT20:
1194 		return WMI_HOST_MODE_11BE_EHT20_2G;
1195 	case WLAN_PHYMODE_11BEG_EHT40:
1196 	case WLAN_PHYMODE_11BEG_EHT40PLUS:
1197 	case WLAN_PHYMODE_11BEG_EHT40MINUS:
1198 		return WMI_HOST_MODE_11BE_EHT40_2G;
1199 	default:
1200 		return WMI_HOST_MODE_UNKNOWN;
1201 	}
1202 }
1203 #else
1204 static WMI_HOST_WLAN_PHY_MODE
1205 wma_host_to_fw_phymode_11be(enum wlan_phymode host_phymode)
1206 {
1207 	return WMI_HOST_MODE_UNKNOWN;
1208 }
1209 #endif
1210 
1211 WMI_HOST_WLAN_PHY_MODE wma_host_to_fw_phymode(enum wlan_phymode host_phymode)
1212 {
1213 	WMI_HOST_WLAN_PHY_MODE fw_phymode;
1214 
1215 	switch (host_phymode) {
1216 	case WLAN_PHYMODE_11A:
1217 		return WMI_HOST_MODE_11A;
1218 	case WLAN_PHYMODE_11G:
1219 		return WMI_HOST_MODE_11G;
1220 	case WLAN_PHYMODE_11B:
1221 		return WMI_HOST_MODE_11B;
1222 	case WLAN_PHYMODE_11G_ONLY:
1223 		return WMI_HOST_MODE_11GONLY;
1224 	case WLAN_PHYMODE_11NA_HT20:
1225 		return WMI_HOST_MODE_11NA_HT20;
1226 	case WLAN_PHYMODE_11NG_HT20:
1227 		return WMI_HOST_MODE_11NG_HT20;
1228 	case WLAN_PHYMODE_11NA_HT40:
1229 		return WMI_HOST_MODE_11NA_HT40;
1230 	case WLAN_PHYMODE_11NG_HT40:
1231 	case WLAN_PHYMODE_11NG_HT40PLUS:
1232 	case WLAN_PHYMODE_11NG_HT40MINUS:
1233 		return WMI_HOST_MODE_11NG_HT40;
1234 	case WLAN_PHYMODE_11AC_VHT20:
1235 		return WMI_HOST_MODE_11AC_VHT20;
1236 	case WLAN_PHYMODE_11AC_VHT40:
1237 		return WMI_HOST_MODE_11AC_VHT40;
1238 	case WLAN_PHYMODE_11AC_VHT80:
1239 		return WMI_HOST_MODE_11AC_VHT80;
1240 	case WLAN_PHYMODE_11AC_VHT20_2G:
1241 		return WMI_HOST_MODE_11AC_VHT20_2G;
1242 	case WLAN_PHYMODE_11AC_VHT40PLUS_2G:
1243 	case WLAN_PHYMODE_11AC_VHT40MINUS_2G:
1244 	case WLAN_PHYMODE_11AC_VHT40_2G:
1245 		return WMI_HOST_MODE_11AC_VHT40_2G;
1246 	case WLAN_PHYMODE_11AC_VHT80_2G:
1247 		return WMI_HOST_MODE_11AC_VHT80_2G;
1248 	default:
1249 		fw_phymode = wma_host_to_fw_phymode_160(host_phymode);
1250 		if (fw_phymode != WMI_HOST_MODE_UNKNOWN)
1251 			return fw_phymode;
1252 		fw_phymode = wma_host_to_fw_phymode_11ax(host_phymode);
1253 		if (fw_phymode != WMI_HOST_MODE_UNKNOWN)
1254 			return fw_phymode;
1255 		return wma_host_to_fw_phymode_11be(host_phymode);
1256 	}
1257 }
1258 
1259 void wma_objmgr_set_peer_mlme_phymode(tp_wma_handle wma, uint8_t *mac_addr,
1260 				      enum wlan_phymode phymode)
1261 {
1262 	uint8_t pdev_id;
1263 	struct wlan_objmgr_peer *peer;
1264 	struct wlan_objmgr_psoc *psoc = wma->psoc;
1265 
1266 	pdev_id = wlan_objmgr_pdev_get_pdev_id(wma->pdev);
1267 	peer = wlan_objmgr_get_peer(psoc, pdev_id, mac_addr,
1268 				    WLAN_LEGACY_WMA_ID);
1269 	if (!peer)
1270 		return;
1271 
1272 	wlan_peer_obj_lock(peer);
1273 	wlan_peer_set_phymode(peer, phymode);
1274 	wlan_peer_obj_unlock(peer);
1275 	wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_WMA_ID);
1276 }
1277 
1278 /**
1279  * wma_objmgr_set_peer_mlme_type() - set peer type to peer object
1280  * @wma:      wma handle
1281  * @mac_addr: mac addr of peer
1282  * @peer_type:  peer type value to set
1283  *
1284  * Return: None
1285  */
1286 static void wma_objmgr_set_peer_mlme_type(tp_wma_handle wma,
1287 					  uint8_t *mac_addr,
1288 					  enum wlan_peer_type peer_type)
1289 {
1290 	uint8_t pdev_id;
1291 	struct wlan_objmgr_peer *peer;
1292 	struct wlan_objmgr_psoc *psoc = wma->psoc;
1293 
1294 	pdev_id = wlan_objmgr_pdev_get_pdev_id(wma->pdev);
1295 	peer = wlan_objmgr_get_peer(psoc, pdev_id, mac_addr,
1296 				    WLAN_LEGACY_WMA_ID);
1297 	if (!peer)
1298 		return;
1299 
1300 	wlan_peer_obj_lock(peer);
1301 	wlan_peer_set_peer_type(peer, peer_type);
1302 	wlan_peer_obj_unlock(peer);
1303 	wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_WMA_ID);
1304 }
1305 
1306 /**
1307  * wmi_unified_send_peer_assoc() - send peer assoc command to fw
1308  * @wma: wma handle
1309  * @nw_type: nw type
1310  * @params: add sta params
1311  *
1312  * This function send peer assoc command to firmware with
1313  * different parameters.
1314  *
1315  * Return: QDF_STATUS
1316  */
1317 QDF_STATUS wma_send_peer_assoc(tp_wma_handle wma,
1318 				    tSirNwType nw_type,
1319 				    tpAddStaParams params)
1320 {
1321 	struct peer_assoc_params *cmd;
1322 	int32_t ret, max_rates, i;
1323 	uint8_t *rate_pos;
1324 	wmi_rate_set peer_legacy_rates, peer_ht_rates;
1325 	uint32_t num_peer_11b_rates = 0;
1326 	uint32_t num_peer_11a_rates = 0;
1327 	enum wlan_phymode phymode, vdev_phymode;
1328 	uint32_t peer_nss = 1;
1329 	struct wma_txrx_node *intr = NULL;
1330 	bool is_he;
1331 	bool is_eht;
1332 	QDF_STATUS status;
1333 	struct mac_context *mac = wma->mac_context;
1334 	struct wlan_channel *des_chan;
1335 	int32_t keymgmt, uccipher, authmode;
1336 
1337 	cmd = qdf_mem_malloc(sizeof(struct peer_assoc_params));
1338 	if (!cmd) {
1339 		wma_err("Failed to allocate peer_assoc_params param");
1340 		return QDF_STATUS_E_NOMEM;
1341 	}
1342 
1343 	intr = &wma->interfaces[params->smesessionId];
1344 
1345 	wma_mask_tx_ht_rate(wma, params->supportedRates.supportedMCSSet);
1346 
1347 	qdf_mem_zero(&peer_legacy_rates, sizeof(wmi_rate_set));
1348 	qdf_mem_zero(&peer_ht_rates, sizeof(wmi_rate_set));
1349 	qdf_mem_zero(cmd, sizeof(struct peer_assoc_params));
1350 
1351 	is_he = wma_is_peer_he_capable(params);
1352 	is_eht = wma_is_peer_eht_capable(params);
1353 	if ((params->ch_width > CH_WIDTH_40MHZ) &&
1354 	    ((nw_type == eSIR_11G_NW_TYPE) ||
1355 	     (nw_type == eSIR_11B_NW_TYPE))) {
1356 		wma_err("ch_width %d sent in 11G, configure to 40MHz",
1357 			params->ch_width);
1358 		params->ch_width = CH_WIDTH_40MHZ;
1359 	}
1360 	phymode = wma_peer_phymode(nw_type, params->staType,
1361 				   params->htCapable, params->ch_width,
1362 				   params->vhtCapable, is_he, is_eht);
1363 
1364 	des_chan = wlan_vdev_mlme_get_des_chan(intr->vdev);
1365 	vdev_phymode = des_chan->ch_phymode;
1366 	if ((intr->type == WMI_VDEV_TYPE_AP) && (phymode > vdev_phymode)) {
1367 		wma_nofl_debug("Peer phymode %d is not allowed. Set it equal to sap/go phymode %d",
1368 			       phymode, vdev_phymode);
1369 		phymode = vdev_phymode;
1370 	}
1371 
1372 	if (!mac->mlme_cfg->rates.disable_abg_rate_txdata) {
1373 		/* Legacy Rateset */
1374 		rate_pos = (uint8_t *) peer_legacy_rates.rates;
1375 		for (i = 0; i < SIR_NUM_11B_RATES; i++) {
1376 			if (!params->supportedRates.llbRates[i])
1377 				continue;
1378 			rate_pos[peer_legacy_rates.num_rates++] =
1379 				params->supportedRates.llbRates[i];
1380 			num_peer_11b_rates++;
1381 		}
1382 		for (i = 0; i < SIR_NUM_11A_RATES; i++) {
1383 			if (!params->supportedRates.llaRates[i])
1384 				continue;
1385 			rate_pos[peer_legacy_rates.num_rates++] =
1386 				params->supportedRates.llaRates[i];
1387 			num_peer_11a_rates++;
1388 		}
1389 	}
1390 
1391 	if ((phymode == WLAN_PHYMODE_11A && num_peer_11a_rates == 0) ||
1392 	    (phymode == WLAN_PHYMODE_11B && num_peer_11b_rates == 0)) {
1393 		wma_warn("Invalid phy rates. phymode 0x%x, 11b_rates %d, 11a_rates %d",
1394 			phymode, num_peer_11b_rates,
1395 			num_peer_11a_rates);
1396 		qdf_mem_free(cmd);
1397 		return QDF_STATUS_E_INVAL;
1398 	}
1399 
1400 	/* HT Rateset */
1401 	max_rates = sizeof(peer_ht_rates.rates) /
1402 		    sizeof(peer_ht_rates.rates[0]);
1403 	rate_pos = (uint8_t *) peer_ht_rates.rates;
1404 	for (i = 0; i < MAX_SUPPORTED_RATES; i++) {
1405 		if (params->supportedRates.supportedMCSSet[i / 8] &
1406 		    (1 << (i % 8))) {
1407 			rate_pos[peer_ht_rates.num_rates++] = i;
1408 			if (i >= 8) {
1409 				/* MCS8 or higher rate is present, must be 2x2 */
1410 				peer_nss = 2;
1411 			}
1412 		}
1413 		if (peer_ht_rates.num_rates == max_rates)
1414 			break;
1415 	}
1416 
1417 	if (params->htCapable && !peer_ht_rates.num_rates) {
1418 		uint8_t temp_ni_rates[8] = { 0x0, 0x1, 0x2, 0x3,
1419 					     0x4, 0x5, 0x6, 0x7};
1420 		/*
1421 		 * Workaround for EV 116382: The peer is marked HT but with
1422 		 * supported rx mcs set is set to 0. 11n spec mandates MCS0-7
1423 		 * for a HT STA. So forcing the supported rx mcs rate to
1424 		 * MCS 0-7. This workaround will be removed once we get
1425 		 * clarification from WFA regarding this STA behavior.
1426 		 */
1427 
1428 		/* TODO: Do we really need this? */
1429 		wma_warn("Peer is marked as HT capable but supported mcs rate is 0");
1430 		peer_ht_rates.num_rates = sizeof(temp_ni_rates);
1431 		qdf_mem_copy((uint8_t *) peer_ht_rates.rates, temp_ni_rates,
1432 			     peer_ht_rates.num_rates);
1433 	}
1434 
1435 	/* in ap mode and for tdls peer, use mac address of the peer in
1436 	 * the other end as the new peer address; in sta mode, use bss id to
1437 	 * be the new peer address
1438 	 */
1439 	if ((wma_is_vdev_in_ap_mode(wma, params->smesessionId))
1440 #ifdef FEATURE_WLAN_TDLS
1441 	    || (STA_ENTRY_TDLS_PEER == params->staType)
1442 #endif /* FEATURE_WLAN_TDLS */
1443 	    ) {
1444 		qdf_mem_copy(cmd->peer_mac, params->staMac,
1445 						sizeof(cmd->peer_mac));
1446 	} else {
1447 		qdf_mem_copy(cmd->peer_mac, params->bssId,
1448 						sizeof(cmd->peer_mac));
1449 	}
1450 	wma_objmgr_set_peer_mlme_phymode(wma, cmd->peer_mac, phymode);
1451 
1452 	cmd->vdev_id = params->smesessionId;
1453 	cmd->peer_new_assoc = 1;
1454 	cmd->peer_associd = params->assocId;
1455 
1456 	cmd->is_wme_set = 1;
1457 
1458 	if (params->wmmEnabled)
1459 		cmd->qos_flag = 1;
1460 
1461 	if (params->uAPSD) {
1462 		cmd->apsd_flag = 1;
1463 		wma_nofl_debug("Set WMI_PEER_APSD: uapsd Mask %d",
1464 			       params->uAPSD);
1465 	}
1466 
1467 	if (params->htCapable) {
1468 		cmd->ht_flag = 1;
1469 		cmd->qos_flag = 1;
1470 		cmd->peer_rate_caps |= WMI_RC_HT_FLAG;
1471 	}
1472 
1473 	if (params->vhtCapable) {
1474 		cmd->ht_flag = 1;
1475 		cmd->qos_flag = 1;
1476 		cmd->vht_flag = 1;
1477 		cmd->peer_rate_caps |= WMI_RC_HT_FLAG;
1478 	}
1479 
1480 	if (params->ch_width) {
1481 		cmd->bw_40 = 1;
1482 		cmd->peer_rate_caps |= WMI_RC_CW40_FLAG;
1483 		if (params->fShortGI40Mhz)
1484 			cmd->peer_rate_caps |= WMI_RC_SGI_FLAG;
1485 	} else if (params->fShortGI20Mhz) {
1486 		cmd->peer_rate_caps |= WMI_RC_SGI_FLAG;
1487 	}
1488 
1489 	if (params->ch_width == CH_WIDTH_80MHZ)
1490 		cmd->bw_80 = 1;
1491 	else if (params->ch_width == CH_WIDTH_160MHZ)
1492 		cmd->bw_160 = 1;
1493 	else if (params->ch_width == CH_WIDTH_80P80MHZ)
1494 		cmd->bw_160 = 1;
1495 
1496 	wma_set_peer_assoc_params_bw_320(cmd, params->ch_width);
1497 
1498 	cmd->peer_vht_caps = params->vht_caps;
1499 	if (params->p2pCapableSta) {
1500 		cmd->p2p_capable_sta = 1;
1501 		wma_objmgr_set_peer_mlme_type(wma, params->staMac,
1502 					      WLAN_PEER_P2P_CLI);
1503 	}
1504 
1505 	if (params->rmfEnabled)
1506 		cmd->is_pmf_enabled = 1;
1507 
1508 	if (params->stbc_capable)
1509 		cmd->stbc_flag = 1;
1510 
1511 	if (params->htLdpcCapable || params->vhtLdpcCapable)
1512 		cmd->ldpc_flag = 1;
1513 
1514 	switch (params->mimoPS) {
1515 	case eSIR_HT_MIMO_PS_STATIC:
1516 		cmd->static_mimops_flag = 1;
1517 		break;
1518 	case eSIR_HT_MIMO_PS_DYNAMIC:
1519 		cmd->dynamic_mimops_flag = 1;
1520 		break;
1521 	case eSIR_HT_MIMO_PS_NO_LIMIT:
1522 		cmd->spatial_mux_flag = 1;
1523 		break;
1524 	default:
1525 		break;
1526 	}
1527 
1528 	wma_set_twt_peer_caps(params, cmd);
1529 #ifdef FEATURE_WLAN_TDLS
1530 	if (STA_ENTRY_TDLS_PEER == params->staType)
1531 		cmd->auth_flag = 1;
1532 #endif /* FEATURE_WLAN_TDLS */
1533 
1534 	if (params->wpa_rsn
1535 #ifdef FEATURE_WLAN_WAPI
1536 	    || params->encryptType == eSIR_ED_WPI
1537 #endif /* FEATURE_WLAN_WAPI */
1538 	    ) {
1539 		if (!params->no_ptk_4_way)
1540 			cmd->need_ptk_4_way = 1;
1541 		wma_nofl_debug("Acquire set key wake lock for %d ms",
1542 			       WMA_VDEV_SET_KEY_WAKELOCK_TIMEOUT);
1543 		wma_acquire_wakelock(&intr->vdev_set_key_wakelock,
1544 			WMA_VDEV_SET_KEY_WAKELOCK_TIMEOUT);
1545 		qdf_runtime_pm_prevent_suspend(
1546 			&intr->vdev_set_key_runtime_wakelock);
1547 	}
1548 	if (params->wpa_rsn >> 1)
1549 		cmd->need_gtk_2_way = 1;
1550 
1551 #ifdef FEATURE_WLAN_WAPI
1552 	if (params->encryptType == eSIR_ED_WPI) {
1553 		ret = wma_vdev_set_param(wma->wmi_handle, params->smesessionId,
1554 				      WMI_VDEV_PARAM_DROP_UNENCRY, false);
1555 		if (ret) {
1556 			wma_err("Set WMI_VDEV_PARAM_DROP_UNENCRY Param status:%d",
1557 				ret);
1558 			qdf_mem_free(cmd);
1559 			return ret;
1560 		}
1561 	}
1562 #endif /* FEATURE_WLAN_WAPI */
1563 
1564 	cmd->peer_caps = params->capab_info;
1565 	cmd->peer_listen_intval = params->listenInterval;
1566 	cmd->peer_ht_caps = params->ht_caps;
1567 	cmd->peer_max_mpdu = (1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR +
1568 				    params->maxAmpduSize)) - 1;
1569 	cmd->peer_mpdu_density = wma_parse_mpdudensity(params->maxAmpduDensity);
1570 
1571 	if (params->supportedRates.supportedMCSSet[1] &&
1572 	    params->supportedRates.supportedMCSSet[2])
1573 		cmd->peer_rate_caps |= WMI_RC_TS_FLAG;
1574 	else if (params->supportedRates.supportedMCSSet[1])
1575 		cmd->peer_rate_caps |= WMI_RC_DS_FLAG;
1576 
1577 	/* Update peer legacy rate information */
1578 	cmd->peer_legacy_rates.num_rates = peer_legacy_rates.num_rates;
1579 	qdf_mem_copy(cmd->peer_legacy_rates.rates, peer_legacy_rates.rates,
1580 		     peer_legacy_rates.num_rates);
1581 
1582 	/* Update peer HT rate information */
1583 	cmd->peer_ht_rates.num_rates = peer_ht_rates.num_rates;
1584 	qdf_mem_copy(cmd->peer_ht_rates.rates, peer_ht_rates.rates,
1585 				 peer_ht_rates.num_rates);
1586 
1587 	/* VHT Rates */
1588 
1589 	cmd->peer_nss = peer_nss;
1590 	/*
1591 	 * Because of DBS a vdev may come up in any of the two MACs with
1592 	 * different capabilities. STBC capab should be fetched for given
1593 	 * hard_mode->MAC_id combo. It is planned that firmware should provide
1594 	 * these dev capabilities. But for now number of tx streams can be used
1595 	 * to identify if Tx STBC needs to be disabled.
1596 	 */
1597 	if (intr->tx_streams < 2) {
1598 		cmd->peer_vht_caps &= ~(1 << SIR_MAC_VHT_CAP_TXSTBC);
1599 		wma_nofl_debug("Num tx_streams: %d, Disabled txSTBC",
1600 			       intr->tx_streams);
1601 	}
1602 
1603 	cmd->vht_capable = params->vhtCapable;
1604 	if (params->vhtCapable) {
1605 #define VHT2x2MCSMASK 0xc
1606 		cmd->rx_max_rate = params->supportedRates.vhtRxHighestDataRate;
1607 		cmd->rx_mcs_set = params->supportedRates.vhtRxMCSMap;
1608 		cmd->tx_max_rate = params->supportedRates.vhtTxHighestDataRate;
1609 		cmd->tx_mcs_set = params->supportedRates.vhtTxMCSMap;
1610 		/*
1611 		 *  tx_mcs_set is intersection of self tx NSS and peer rx mcs map
1612 		 */
1613 		if (params->vhtSupportedRxNss)
1614 			cmd->peer_nss = params->vhtSupportedRxNss;
1615 		else
1616 			cmd->peer_nss = ((cmd->tx_mcs_set & VHT2x2MCSMASK)
1617 					== VHT2x2MCSMASK) ? 1 : 2;
1618 
1619 		if (params->vht_mcs_10_11_supp) {
1620 			WMI_SET_BITS(cmd->tx_mcs_set, 16, cmd->peer_nss,
1621 				     ((1 << cmd->peer_nss) - 1));
1622 			WMI_VHT_MCS_NOTIFY_EXT_SS_SET(cmd->tx_mcs_set, 1);
1623 		}
1624 		if (params->vht_extended_nss_bw_cap &&
1625 		    (params->vht_160mhz_nss || params->vht_80p80mhz_nss)) {
1626 			/*
1627 			 * bit[2:0] : Represents value of Rx NSS for 160 MHz
1628 			 * bit[5:3] : Represents value of Rx NSS for 80_80 MHz
1629 			 *             Extended NSS support
1630 			 * bit[30:6]: Reserved
1631 			 * bit[31]  : MSB(0/1): 1 in case of valid data
1632 			 */
1633 			cmd->peer_bw_rxnss_override |= (1 << 31);
1634 			if (params->vht_160mhz_nss)
1635 				cmd->peer_bw_rxnss_override |=
1636 					(params->vht_160mhz_nss - 1);
1637 			if (params->vht_80p80mhz_nss)
1638 				cmd->peer_bw_rxnss_override |=
1639 					((params->vht_80p80mhz_nss - 1) << 3);
1640 			wma_debug("peer_bw_rxnss_override %0X",
1641 				  cmd->peer_bw_rxnss_override);
1642 		}
1643 	}
1644 
1645 	wma_debug("rx_max_rate %d, rx_mcs %x, tx_max_rate %d, tx_mcs: %x num rates %d need 4 way %d",
1646 		  cmd->rx_max_rate, cmd->rx_mcs_set, cmd->tx_max_rate,
1647 		  cmd->tx_mcs_set, peer_ht_rates.num_rates,
1648 		  cmd->need_ptk_4_way);
1649 
1650 	/*
1651 	 * Limit nss to max number of rf chain supported by target
1652 	 * Otherwise Fw will crash
1653 	 */
1654 	if (cmd->peer_nss > WMA_MAX_NSS) {
1655 		wma_err("peer Nss %d is more than supported", cmd->peer_nss);
1656 		cmd->peer_nss = WMA_MAX_NSS;
1657 	}
1658 
1659 	wma_populate_peer_he_cap(cmd, params);
1660 	wma_populate_peer_eht_cap(cmd, params);
1661 	if (!wma_is_vdev_in_ap_mode(wma, params->smesessionId))
1662 		intr->nss = cmd->peer_nss;
1663 
1664 	/* Till conversion is not done in WMI we need to fill fw phy mode */
1665 	cmd->peer_phymode = wma_host_to_fw_phymode(phymode);
1666 
1667 	keymgmt = wlan_crypto_get_param(intr->vdev, WLAN_CRYPTO_PARAM_KEY_MGMT);
1668 	authmode = wlan_crypto_get_param(intr->vdev,
1669 					 WLAN_CRYPTO_PARAM_AUTH_MODE);
1670 	uccipher = wlan_crypto_get_param(intr->vdev,
1671 					 WLAN_CRYPTO_PARAM_UCAST_CIPHER);
1672 
1673 	cmd->akm = cm_crypto_authmode_to_wmi_authmode(authmode,
1674 						      keymgmt,
1675 						      uccipher);
1676 
1677 	status = wmi_unified_peer_assoc_send(wma->wmi_handle,
1678 					 cmd);
1679 	if (QDF_IS_STATUS_ERROR(status))
1680 		wma_alert("Failed to send peer assoc command status = %d",
1681 			 status);
1682 	qdf_mem_free(cmd);
1683 
1684 	return status;
1685 }
1686 
1687 /**
1688  * wmi_unified_vdev_set_gtx_cfg_send() - set GTX params
1689  * @wmi_handle: wmi handle
1690  * @if_id: vdev id
1691  * @gtx_info: GTX config params
1692  *
1693  * This function set GTX related params in firmware.
1694  *
1695  * Return: 0 for success or error code
1696  */
1697 QDF_STATUS wmi_unified_vdev_set_gtx_cfg_send(wmi_unified_t wmi_handle,
1698 				  uint32_t if_id,
1699 				  gtx_config_t *gtx_info)
1700 {
1701 	struct wmi_gtx_config params;
1702 
1703 	params.gtx_rt_mask[0] = gtx_info->gtxRTMask[0];
1704 	params.gtx_rt_mask[1] = gtx_info->gtxRTMask[1];
1705 	params.gtx_usrcfg = gtx_info->gtxUsrcfg;
1706 	params.gtx_threshold = gtx_info->gtxPERThreshold;
1707 	params.gtx_margin = gtx_info->gtxPERMargin;
1708 	params.gtx_tpcstep = gtx_info->gtxTPCstep;
1709 	params.gtx_tpcmin = gtx_info->gtxTPCMin;
1710 	params.gtx_bwmask = gtx_info->gtxBWMask;
1711 
1712 	return wmi_unified_vdev_set_gtx_cfg_cmd(wmi_handle,
1713 						if_id, &params);
1714 
1715 }
1716 
1717 /**
1718  * wma_update_protection_mode() - update protection mode
1719  * @wma: wma handle
1720  * @vdev_id: vdev id
1721  * @llbcoexist: protection mode info
1722  *
1723  * This function set protection mode(RTS/CTS) to fw for passed vdev id.
1724  *
1725  * Return: none
1726  */
1727 void wma_update_protection_mode(tp_wma_handle wma, uint8_t vdev_id,
1728 			   uint8_t llbcoexist)
1729 {
1730 	QDF_STATUS ret;
1731 	enum ieee80211_protmode prot_mode;
1732 
1733 	prot_mode = llbcoexist ? IEEE80211_PROT_CTSONLY : IEEE80211_PROT_NONE;
1734 
1735 	ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
1736 					      WMI_VDEV_PARAM_PROTECTION_MODE,
1737 					      prot_mode);
1738 
1739 	if (QDF_IS_STATUS_ERROR(ret))
1740 		wma_err("Failed to send wmi protection mode cmd");
1741 	else
1742 		wma_nofl_debug("Updated protection mode %d to target",
1743 			       prot_mode);
1744 }
1745 
1746 void
1747 wma_update_beacon_interval(tp_wma_handle wma, uint8_t vdev_id,
1748 			   uint16_t beaconInterval)
1749 {
1750 	QDF_STATUS ret;
1751 
1752 	ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
1753 					      WMI_VDEV_PARAM_BEACON_INTERVAL,
1754 					      beaconInterval);
1755 
1756 	if (QDF_IS_STATUS_ERROR(ret))
1757 		wma_err("Failed to update beacon interval");
1758 	else
1759 		wma_info("Updated beacon interval %d for vdev %d",
1760 			 beaconInterval, vdev_id);
1761 }
1762 
1763 #ifdef WLAN_FEATURE_11AX_BSS_COLOR
1764 /**
1765  * wma_update_bss_color() - update beacon bss color in fw
1766  * @wma: wma handle
1767  * @vdev_id: vdev id
1768  * @he_ops: HE operation, only the bss_color and bss_color_disabled fields
1769  * are updated.
1770  *
1771  * Return: none
1772  */
1773 static void
1774 wma_update_bss_color(tp_wma_handle wma, uint8_t vdev_id,
1775 		     tUpdateBeaconParams *bcn_params)
1776 {
1777 	QDF_STATUS ret;
1778 	uint32_t dword_he_ops = 0;
1779 
1780 	WMI_HEOPS_COLOR_SET(dword_he_ops, bcn_params->bss_color);
1781 	WMI_HEOPS_BSSCOLORDISABLE_SET(dword_he_ops,
1782 				bcn_params->bss_color_disabled);
1783 	wma_nofl_debug("vdev: %d, update bss color, HE_OPS: 0x%x",
1784 		       vdev_id, dword_he_ops);
1785 	ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
1786 			      WMI_VDEV_PARAM_BSS_COLOR, dword_he_ops);
1787 	if (QDF_IS_STATUS_ERROR(ret))
1788 		wma_err("Failed to update HE operations");
1789 }
1790 #else
1791 static void wma_update_bss_color(tp_wma_handle wma, uint8_t vdev_id,
1792 			   tUpdateBeaconParams *bcn_params)
1793 {
1794 }
1795 #endif
1796 
1797 /**
1798  * wma_process_update_beacon_params() - update beacon parameters to target
1799  * @wma: wma handle
1800  * @bcn_params: beacon parameters
1801  *
1802  * Return: none
1803  */
1804 void
1805 wma_process_update_beacon_params(tp_wma_handle wma,
1806 				 tUpdateBeaconParams *bcn_params)
1807 {
1808 	if (!bcn_params) {
1809 		wma_err("bcn_params NULL");
1810 		return;
1811 	}
1812 
1813 	if (bcn_params->vdev_id >= wma->max_bssid) {
1814 		wma_err("Invalid vdev id %d", bcn_params->vdev_id);
1815 		return;
1816 	}
1817 
1818 	if (bcn_params->paramChangeBitmap & PARAM_BCN_INTERVAL_CHANGED) {
1819 		wma_update_beacon_interval(wma, bcn_params->vdev_id,
1820 					   bcn_params->beaconInterval);
1821 	}
1822 
1823 	if (bcn_params->paramChangeBitmap & PARAM_llBCOEXIST_CHANGED)
1824 		wma_update_protection_mode(wma, bcn_params->vdev_id,
1825 					   bcn_params->llbCoexist);
1826 
1827 	if (bcn_params->paramChangeBitmap & PARAM_BSS_COLOR_CHANGED)
1828 		wma_update_bss_color(wma, bcn_params->vdev_id,
1829 				     bcn_params);
1830 }
1831 
1832 void wma_update_rts_params(tp_wma_handle wma, uint32_t value)
1833 {
1834 	uint8_t vdev_id;
1835 	QDF_STATUS ret;
1836 	struct wlan_objmgr_vdev *vdev;
1837 
1838 	for (vdev_id = 0; vdev_id < wma->max_bssid; vdev_id++) {
1839 		vdev = wma->interfaces[vdev_id].vdev;
1840 		if (!vdev)
1841 			continue;
1842 		ret = wma_vdev_set_param(wma->wmi_handle,
1843 					 vdev_id,
1844 					 WMI_VDEV_PARAM_RTS_THRESHOLD,
1845 					 value);
1846 		if (QDF_IS_STATUS_ERROR(ret))
1847 			wma_err("Update cfg param fail for vdevId %d", vdev_id);
1848 	}
1849 }
1850 
1851 void wma_update_frag_params(tp_wma_handle wma, uint32_t value)
1852 {
1853 	uint8_t vdev_id;
1854 	QDF_STATUS ret;
1855 	struct wlan_objmgr_vdev *vdev;
1856 
1857 	for (vdev_id = 0; vdev_id < wma->max_bssid; vdev_id++) {
1858 		vdev = wma->interfaces[vdev_id].vdev;
1859 		if (!vdev)
1860 			continue;
1861 		ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
1862 					 WMI_VDEV_PARAM_FRAGMENTATION_THRESHOLD,
1863 					 value);
1864 		if (QDF_IS_STATUS_ERROR(ret))
1865 			wma_err("Update cfg params failed for vdevId %d",
1866 				 vdev_id);
1867 	}
1868 }
1869 
1870 #ifdef FEATURE_WLAN_WAPI
1871 #define WPI_IV_LEN 16
1872 #if defined(CONFIG_LITHIUM) || defined(CONFIG_BERYLLIUM)
1873 /**
1874  * wma_fill_in_wapi_key_params() - update key parameters about wapi
1875  * @key_params: wma key parameters
1876  * @params: parameters pointer to be set
1877  * @mode: operation mode
1878  *
1879  * Return: None
1880  */
1881 static inline void wma_fill_in_wapi_key_params(
1882 		struct wma_set_key_params *key_params,
1883 		struct set_key_params *params, uint8_t mode)
1884 {
1885 	/*
1886 	 * Since MCL shares same FW with WIN for Napier/Hasting, FW WAPI logic
1887 	 * is fit for WIN, change it to align with WIN.
1888 	 */
1889 	unsigned char iv_init_ap[16] = { 0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36,
1890 					 0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36,
1891 					 0x5c, 0x36, 0x5c, 0x37};
1892 	unsigned char iv_init_sta[16] = { 0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36,
1893 					  0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36,
1894 					  0x5c, 0x36, 0x5c, 0x36};
1895 
1896 	if (mode == wlan_op_mode_ap) {
1897 		qdf_mem_copy(params->rx_iv, iv_init_sta,
1898 			     WPI_IV_LEN);
1899 		qdf_mem_copy(params->tx_iv, iv_init_ap,
1900 			     WPI_IV_LEN);
1901 	} else {
1902 		qdf_mem_copy(params->rx_iv, iv_init_ap,
1903 			     WPI_IV_LEN);
1904 		qdf_mem_copy(params->tx_iv, iv_init_sta,
1905 			     WPI_IV_LEN);
1906 	}
1907 
1908 	params->key_txmic_len = WMA_TXMIC_LEN;
1909 	params->key_rxmic_len = WMA_RXMIC_LEN;
1910 
1911 	params->key_cipher = WMI_CIPHER_WAPI;
1912 }
1913 #else
1914 static inline void wma_fill_in_wapi_key_params(
1915 		struct wma_set_key_params *key_params,
1916 		struct set_key_params *params, uint8_t mode)
1917 {
1918 	/*initialize receive and transmit IV with default values */
1919 	/* **Note: tx_iv must be sent in reverse** */
1920 	unsigned char tx_iv[16] = { 0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c,
1921 				    0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c,
1922 				    0x36, 0x5c, 0x36, 0x5c};
1923 	unsigned char rx_iv[16] = { 0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36,
1924 				    0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36,
1925 				    0x5c, 0x36, 0x5c, 0x37};
1926 	if (mode == wlan_op_mode_ap) {
1927 		/* Authenticator initializes the value of PN as
1928 		 * 0x5C365C365C365C365C365C365C365C36 for MCastkeyUpdate
1929 		 */
1930 		if (key_params->unicast)
1931 			tx_iv[0] = 0x37;
1932 
1933 		rx_iv[WPI_IV_LEN - 1] = 0x36;
1934 	} else {
1935 		if (!key_params->unicast)
1936 			rx_iv[WPI_IV_LEN - 1] = 0x36;
1937 	}
1938 
1939 	params->key_txmic_len = WMA_TXMIC_LEN;
1940 	params->key_rxmic_len = WMA_RXMIC_LEN;
1941 
1942 	qdf_mem_copy(params->rx_iv, &rx_iv,
1943 		     WPI_IV_LEN);
1944 	qdf_mem_copy(params->tx_iv, &tx_iv,
1945 		     WPI_IV_LEN);
1946 	params->key_cipher = WMI_CIPHER_WAPI;
1947 }
1948 #endif
1949 #endif
1950 
1951 /**
1952  * wma_process_update_edca_param_req() - update EDCA params
1953  * @handle: wma handle
1954  * @edca_params: edca parameters
1955  *
1956  * This function updates EDCA parameters to the target
1957  *
1958  * Return: QDF Status
1959  */
1960 QDF_STATUS wma_process_update_edca_param_req(WMA_HANDLE handle,
1961 					     tEdcaParams *edca_params)
1962 {
1963 	tp_wma_handle wma_handle = (tp_wma_handle) handle;
1964 	struct wmi_host_wme_vparams wmm_param[QCA_WLAN_AC_ALL];
1965 	tSirMacEdcaParamRecord *edca_record;
1966 	int ac;
1967 	struct ol_tx_wmm_param_t ol_tx_wmm_param;
1968 	uint8_t vdev_id;
1969 	QDF_STATUS status;
1970 	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
1971 
1972 	vdev_id = edca_params->vdev_id;
1973 	if (!wma_is_vdev_valid(vdev_id)) {
1974 		wma_err("vdev id:%d is not active ", vdev_id);
1975 		goto fail;
1976 	}
1977 
1978 	for (ac = 0; ac < QCA_WLAN_AC_ALL; ac++) {
1979 		switch (ac) {
1980 		case QCA_WLAN_AC_BE:
1981 			edca_record = &edca_params->acbe;
1982 			break;
1983 		case QCA_WLAN_AC_BK:
1984 			edca_record = &edca_params->acbk;
1985 			break;
1986 		case QCA_WLAN_AC_VI:
1987 			edca_record = &edca_params->acvi;
1988 			break;
1989 		case QCA_WLAN_AC_VO:
1990 			edca_record = &edca_params->acvo;
1991 			break;
1992 		default:
1993 			goto fail;
1994 		}
1995 
1996 		wma_update_edca_params_for_ac(edca_record, &wmm_param[ac], ac,
1997 				edca_params->mu_edca_params);
1998 
1999 		ol_tx_wmm_param.ac[ac].aifs = wmm_param[ac].aifs;
2000 		ol_tx_wmm_param.ac[ac].cwmin = wmm_param[ac].cwmin;
2001 		ol_tx_wmm_param.ac[ac].cwmax = wmm_param[ac].cwmax;
2002 	}
2003 
2004 	status = wmi_unified_process_update_edca_param(wma_handle->wmi_handle,
2005 						vdev_id,
2006 						edca_params->mu_edca_params,
2007 						wmm_param);
2008 	if (status == QDF_STATUS_E_NOMEM)
2009 		return status;
2010 	else if (status == QDF_STATUS_E_FAILURE)
2011 		goto fail;
2012 
2013 	cdp_set_wmm_param(soc, WMI_PDEV_ID_SOC, ol_tx_wmm_param);
2014 
2015 	return QDF_STATUS_SUCCESS;
2016 
2017 fail:
2018 	wma_err("Failed to set WMM Paremeters");
2019 	return QDF_STATUS_E_FAILURE;
2020 }
2021 
2022 /**
2023  * wmi_unified_probe_rsp_tmpl_send() - send probe response template to fw
2024  * @wma: wma handle
2025  * @vdev_id: vdev id
2026  * @probe_rsp_info: probe response info
2027  *
2028  * Return: 0 for success or error code
2029  */
2030 static int wmi_unified_probe_rsp_tmpl_send(tp_wma_handle wma,
2031 				   uint8_t vdev_id,
2032 				   tpSendProbeRespParams probe_rsp_info)
2033 {
2034 	uint64_t adjusted_tsf_le;
2035 	struct ieee80211_frame *wh;
2036 	struct wmi_probe_resp_params params;
2037 
2038 	wma_debug("Send probe response template for vdev %d", vdev_id);
2039 
2040 	/*
2041 	 * Make the TSF offset negative so probe response in the same
2042 	 * staggered batch have the same TSF.
2043 	 */
2044 	adjusted_tsf_le = cpu_to_le64(0ULL -
2045 				      wma->interfaces[vdev_id].tsfadjust);
2046 	/* Update the timstamp in the probe response buffer with adjusted TSF */
2047 	wh = (struct ieee80211_frame *)probe_rsp_info->probeRespTemplate;
2048 	A_MEMCPY(&wh[1], &adjusted_tsf_le, sizeof(adjusted_tsf_le));
2049 
2050 	params.prb_rsp_template_len = probe_rsp_info->probeRespTemplateLen;
2051 	params.prb_rsp_template_frm = probe_rsp_info->probeRespTemplate;
2052 
2053 	return wmi_unified_probe_rsp_tmpl_send_cmd(wma->wmi_handle, vdev_id,
2054 						   &params);
2055 }
2056 
2057 /**
2058  * wma_unified_bcn_tmpl_send() - send beacon template to fw
2059  * @wma:wma handle
2060  * @vdev_id: vdev id
2061  * @bcn_info: beacon info
2062  * @bytes_to_strip: bytes to strip
2063  *
2064  * Return: QDF_STATUS_SUCCESS for success or error code
2065  */
2066 static QDF_STATUS wma_unified_bcn_tmpl_send(tp_wma_handle wma,
2067 				     uint8_t vdev_id,
2068 				     const tpSendbeaconParams bcn_info,
2069 				     uint8_t bytes_to_strip)
2070 {
2071 	struct beacon_tmpl_params params = {0};
2072 	uint32_t tmpl_len, tmpl_len_aligned;
2073 	uint8_t *frm;
2074 	QDF_STATUS ret;
2075 	uint8_t *p2p_ie;
2076 	uint16_t p2p_ie_len = 0;
2077 	uint64_t adjusted_tsf_le;
2078 	struct ieee80211_frame *wh;
2079 
2080 	if (!wma_is_vdev_valid(vdev_id)) {
2081 		wma_err("vdev id:%d is not active ", vdev_id);
2082 		return QDF_STATUS_E_INVAL;
2083 	}
2084 
2085 	wma_nofl_debug("Send beacon template for vdev %d", vdev_id);
2086 
2087 	if (bcn_info->p2pIeOffset) {
2088 		p2p_ie = bcn_info->beacon + bcn_info->p2pIeOffset;
2089 		p2p_ie_len = (uint16_t) p2p_ie[1] + 2;
2090 	}
2091 
2092 	/*
2093 	 * XXX: The first byte of beacon buffer contains beacon length
2094 	 * only when UMAC in sending the beacon template. In othercases
2095 	 * (ex: from tbtt update) beacon length is read from beacon
2096 	 * information.
2097 	 */
2098 	if (bytes_to_strip)
2099 		tmpl_len = *(uint32_t *) &bcn_info->beacon[0];
2100 	else
2101 		tmpl_len = bcn_info->beaconLength;
2102 
2103 	if (tmpl_len > WMI_BEACON_TX_BUFFER_SIZE) {
2104 		wma_err("tmpl_len: %d > %d. Invalid tmpl len", tmpl_len,
2105 			WMI_BEACON_TX_BUFFER_SIZE);
2106 		return -EINVAL;
2107 	}
2108 
2109 	if (p2p_ie_len) {
2110 		if (tmpl_len <= p2p_ie_len) {
2111 			wma_err("tmpl_len %d <= p2p_ie_len %d, Invalid",
2112 				tmpl_len, p2p_ie_len);
2113 			return -EINVAL;
2114 		}
2115 		tmpl_len -= (uint32_t) p2p_ie_len;
2116 	}
2117 
2118 	frm = bcn_info->beacon + bytes_to_strip;
2119 	tmpl_len_aligned = roundup(tmpl_len, sizeof(A_UINT32));
2120 	/*
2121 	 * Make the TSF offset negative so beacons in the same
2122 	 * staggered batch have the same TSF.
2123 	 */
2124 	adjusted_tsf_le = cpu_to_le64(0ULL -
2125 				      wma->interfaces[vdev_id].tsfadjust);
2126 	/* Update the timstamp in the beacon buffer with adjusted TSF */
2127 	wh = (struct ieee80211_frame *)frm;
2128 	A_MEMCPY(&wh[1], &adjusted_tsf_le, sizeof(adjusted_tsf_le));
2129 
2130 
2131 
2132 	params.vdev_id = vdev_id;
2133 	params.tim_ie_offset = bcn_info->timIeOffset - bytes_to_strip;
2134 	params.tmpl_len = tmpl_len;
2135 	params.frm = frm;
2136 	params.tmpl_len_aligned = tmpl_len_aligned;
2137 	params.enable_bigtk =
2138 		mlme_get_bigtk_support(wma->interfaces[vdev_id].vdev);
2139 	if (bcn_info->csa_count_offset &&
2140 	    (bcn_info->csa_count_offset > bytes_to_strip))
2141 		params.csa_switch_count_offset =
2142 			bcn_info->csa_count_offset - bytes_to_strip;
2143 	if (bcn_info->ecsa_count_offset &&
2144 	    (bcn_info->ecsa_count_offset > bytes_to_strip))
2145 		params.ext_csa_switch_count_offset =
2146 			bcn_info->ecsa_count_offset - bytes_to_strip;
2147 
2148 	ret = wmi_unified_beacon_tmpl_send_cmd(wma->wmi_handle,
2149 				 &params);
2150 	if (QDF_IS_STATUS_ERROR(ret))
2151 		wma_err("Failed to send bcn tmpl: %d", ret);
2152 
2153 	return ret;
2154 }
2155 
2156 /**
2157  * wma_store_bcn_tmpl() - store beacon template
2158  * @wma: wma handle
2159  * @vdev_id: vdev id
2160  * @bcn_info: beacon params
2161  *
2162  * This function stores beacon template locally.
2163  * This will send to target on the reception of
2164  * SWBA event.
2165  *
2166  * Return: QDF status
2167  */
2168 static QDF_STATUS wma_store_bcn_tmpl(tp_wma_handle wma, uint8_t vdev_id,
2169 				     tpSendbeaconParams bcn_info)
2170 {
2171 	struct beacon_info *bcn;
2172 	uint32_t len;
2173 	uint8_t *bcn_payload;
2174 	struct beacon_tim_ie *tim_ie;
2175 
2176 	bcn = wma->interfaces[vdev_id].beacon;
2177 	if (!bcn || !bcn->buf) {
2178 		wma_err("Memory is not allocated to hold bcn template");
2179 		return QDF_STATUS_E_INVAL;
2180 	}
2181 
2182 	len = *(uint32_t *) &bcn_info->beacon[0];
2183 	if (len > SIR_MAX_BEACON_SIZE - sizeof(uint32_t)) {
2184 		wma_err("Received beacon len %u exceeding max limit %lu",
2185 			len, (unsigned long)(
2186 			 SIR_MAX_BEACON_SIZE - sizeof(uint32_t)));
2187 		return QDF_STATUS_E_INVAL;
2188 	}
2189 	qdf_spin_lock_bh(&bcn->lock);
2190 
2191 	/*
2192 	 * Copy received beacon template content in local buffer.
2193 	 * this will be send to target on the reception of SWBA
2194 	 * event from target.
2195 	 */
2196 	qdf_nbuf_trim_tail(bcn->buf, qdf_nbuf_len(bcn->buf));
2197 	memcpy(qdf_nbuf_data(bcn->buf),
2198 	       bcn_info->beacon + 4 /* Exclude beacon length field */,
2199 	       len);
2200 	if (bcn_info->timIeOffset > 3)
2201 		bcn->tim_ie_offset = bcn_info->timIeOffset - 4;
2202 	else
2203 		bcn->tim_ie_offset = bcn_info->timIeOffset;
2204 
2205 	if (bcn_info->p2pIeOffset > 3)
2206 		bcn->p2p_ie_offset = bcn_info->p2pIeOffset - 4;
2207 	else
2208 		bcn->p2p_ie_offset = bcn_info->p2pIeOffset;
2209 
2210 	bcn_payload = qdf_nbuf_data(bcn->buf);
2211 	if (bcn->tim_ie_offset) {
2212 		tim_ie = (struct beacon_tim_ie *)
2213 				(&bcn_payload[bcn->tim_ie_offset]);
2214 		/*
2215 		 * Initial Value of bcn->dtim_count will be 0.
2216 		 * But if the beacon gets updated then current dtim
2217 		 * count will be restored
2218 		 */
2219 		tim_ie->dtim_count = bcn->dtim_count;
2220 		tim_ie->tim_bitctl = 0;
2221 	}
2222 
2223 	qdf_nbuf_put_tail(bcn->buf, len);
2224 	bcn->len = len;
2225 
2226 	qdf_spin_unlock_bh(&bcn->lock);
2227 
2228 	return QDF_STATUS_SUCCESS;
2229 }
2230 
2231 int wma_tbttoffset_update_event_handler(void *handle, uint8_t *event,
2232 					       uint32_t len)
2233 {
2234 	tp_wma_handle wma = (tp_wma_handle) handle;
2235 	WMI_TBTTOFFSET_UPDATE_EVENTID_param_tlvs *param_buf;
2236 	wmi_tbtt_offset_event_fixed_param *tbtt_offset_event;
2237 	struct wma_txrx_node *intf;
2238 	struct beacon_info *bcn;
2239 	tSendbeaconParams bcn_info;
2240 	uint32_t *adjusted_tsf = NULL;
2241 	uint32_t if_id = 0, vdev_map;
2242 
2243 	if (wma_validate_handle(wma))
2244 		return -EINVAL;
2245 
2246 	param_buf = (WMI_TBTTOFFSET_UPDATE_EVENTID_param_tlvs *) event;
2247 	if (!param_buf) {
2248 		wma_err("Invalid tbtt update event buffer");
2249 		return -EINVAL;
2250 	}
2251 
2252 	tbtt_offset_event = param_buf->fixed_param;
2253 	intf = wma->interfaces;
2254 	vdev_map = tbtt_offset_event->vdev_map;
2255 	adjusted_tsf = param_buf->tbttoffset_list;
2256 	if (!adjusted_tsf) {
2257 		wma_err("Invalid adjusted_tsf");
2258 		return -EINVAL;
2259 	}
2260 
2261 	for (; (if_id < wma->max_bssid && vdev_map); vdev_map >>= 1, if_id++) {
2262 		if (!intf[if_id].vdev)
2263 			continue;
2264 
2265 		if (!(vdev_map & 0x1))
2266 			continue;
2267 
2268 		bcn = intf[if_id].beacon;
2269 		if (!bcn) {
2270 			wma_err("Invalid beacon");
2271 			return -EINVAL;
2272 		}
2273 		if (!bcn->buf) {
2274 			wma_err("Invalid beacon buffer");
2275 			return -EINVAL;
2276 		}
2277 		/* Save the adjusted TSF */
2278 		intf[if_id].tsfadjust = adjusted_tsf[if_id];
2279 
2280 		qdf_spin_lock_bh(&bcn->lock);
2281 		qdf_mem_zero(&bcn_info, sizeof(bcn_info));
2282 		qdf_mem_copy(bcn_info.beacon,
2283 			     qdf_nbuf_data(bcn->buf), bcn->len);
2284 		bcn_info.p2pIeOffset = bcn->p2p_ie_offset;
2285 		bcn_info.beaconLength = bcn->len;
2286 		bcn_info.timIeOffset = bcn->tim_ie_offset;
2287 		qdf_spin_unlock_bh(&bcn->lock);
2288 
2289 		/* Update beacon template in firmware */
2290 		wma_unified_bcn_tmpl_send(wma, if_id, &bcn_info, 0);
2291 	}
2292 	return 0;
2293 }
2294 
2295 /**
2296  * wma_p2p_go_set_beacon_ie() - set beacon IE for p2p go
2297  * @wma_handle: wma handle
2298  * @vdev_id: vdev id
2299  * @p2pIe: p2p IE
2300  *
2301  * Return: 0 for success or error code
2302  */
2303 static int wma_p2p_go_set_beacon_ie(t_wma_handle *wma_handle,
2304 				    A_UINT32 vdev_id, uint8_t *p2pIe)
2305 {
2306 	if (wma_validate_handle(wma_handle))
2307 		return QDF_STATUS_E_FAILURE;
2308 
2309 	return wmi_unified_p2p_go_set_beacon_ie_cmd(wma_handle->wmi_handle,
2310 							vdev_id, p2pIe);
2311 }
2312 
2313 /**
2314  * wma_send_probe_rsp_tmpl() - send probe resp template
2315  * @wma: wma handle
2316  * @probe_rsp_info: probe response info
2317  *
2318  * This funciton sends probe response template to fw which
2319  * firmware will use in case of probe response offload.
2320  *
2321  * Return: none
2322  */
2323 void wma_send_probe_rsp_tmpl(tp_wma_handle wma,
2324 				    tpSendProbeRespParams probe_rsp_info)
2325 {
2326 	uint8_t vdev_id;
2327 	struct sAniProbeRspStruct *probe_rsp;
2328 
2329 	if (!probe_rsp_info) {
2330 		wma_err("probe_rsp_info is NULL");
2331 		return;
2332 	}
2333 
2334 	probe_rsp = (struct sAniProbeRspStruct *)
2335 			(probe_rsp_info->probeRespTemplate);
2336 	if (!probe_rsp) {
2337 		wma_err("probe_rsp is NULL");
2338 		return;
2339 	}
2340 
2341 	if (wma_find_vdev_id_by_addr(wma, probe_rsp->macHdr.sa, &vdev_id)) {
2342 		wma_err("failed to get vdev id");
2343 		return;
2344 	}
2345 
2346 	if (wmi_service_enabled(wma->wmi_handle,
2347 				   wmi_service_beacon_offload)) {
2348 		wma_nofl_debug("Beacon Offload Enabled Sending Unified command");
2349 		if (wmi_unified_probe_rsp_tmpl_send(wma, vdev_id,
2350 						    probe_rsp_info) < 0) {
2351 			wma_err("wmi_unified_probe_rsp_tmpl_send Failed");
2352 			return;
2353 		}
2354 	}
2355 }
2356 
2357 QDF_STATUS wma_set_ap_vdev_up(tp_wma_handle wma, uint8_t vdev_id)
2358 {
2359 	QDF_STATUS status = QDF_STATUS_SUCCESS;
2360 	struct vdev_mlme_obj *mlme_obj;
2361 	struct wlan_objmgr_vdev *vdev;
2362 	struct wma_txrx_node *iface;
2363 
2364 	iface = &wma->interfaces[vdev_id];
2365 	vdev = iface->vdev;
2366 	mlme_obj = wlan_vdev_mlme_get_cmpt_obj(vdev);
2367 	if (!mlme_obj) {
2368 		wma_err("failed to get mlme_obj");
2369 		return QDF_STATUS_E_INVAL;
2370 	}
2371 	mlme_obj->proto.sta.assoc_id = 0;
2372 
2373 	status = vdev_mgr_up_send(mlme_obj);
2374 	if (QDF_IS_STATUS_ERROR(status)) {
2375 		wma_err("failed to send vdev up");
2376 		return status;
2377 	}
2378 	wma_set_sap_keepalive(wma, vdev_id);
2379 	wma_set_vdev_mgmt_rate(wma, vdev_id);
2380 
2381 	return status;
2382 }
2383 
2384 /**
2385  * wma_send_beacon() - send beacon template
2386  * @wma: wma handle
2387  * @bcn_info: beacon info
2388  *
2389  * This funciton store beacon template locally and
2390  * update keep alive parameters
2391  *
2392  * Return: none
2393  */
2394 void wma_send_beacon(tp_wma_handle wma, tpSendbeaconParams bcn_info)
2395 {
2396 	uint8_t vdev_id;
2397 	QDF_STATUS status;
2398 	uint8_t *p2p_ie;
2399 	struct sAniBeaconStruct *beacon;
2400 
2401 	wma_nofl_debug("Beacon update reason %d", bcn_info->reason);
2402 	beacon = (struct sAniBeaconStruct *) (bcn_info->beacon);
2403 	if (wma_find_vdev_id_by_addr(wma, beacon->macHdr.sa, &vdev_id)) {
2404 		wma_err("failed to get vdev id");
2405 		status = QDF_STATUS_E_INVAL;
2406 		goto send_rsp;
2407 	}
2408 
2409 	if (wmi_service_enabled(wma->wmi_handle,
2410 				   wmi_service_beacon_offload)) {
2411 		status = wma_unified_bcn_tmpl_send(wma, vdev_id, bcn_info, 4);
2412 		if (QDF_IS_STATUS_ERROR(status)) {
2413 			wma_err("wmi_unified_bcn_tmpl_send Failed");
2414 			goto send_rsp;
2415 		}
2416 
2417 		if (bcn_info->p2pIeOffset) {
2418 			p2p_ie = bcn_info->beacon + bcn_info->p2pIeOffset;
2419 			wma_debug("p2pIe is present - vdev_id %hu, p2p_ie = %pK, p2p ie len = %hu",
2420 				  vdev_id, p2p_ie, p2p_ie[1]);
2421 			if (wma_p2p_go_set_beacon_ie(wma, vdev_id,
2422 							 p2p_ie) < 0) {
2423 				wma_err("wmi_unified_bcn_tmpl_send Failed");
2424 				status = QDF_STATUS_E_INVAL;
2425 				goto send_rsp;
2426 			}
2427 		}
2428 	}
2429 	status = wma_store_bcn_tmpl(wma, vdev_id, bcn_info);
2430 	if (status != QDF_STATUS_SUCCESS) {
2431 		wma_err("wma_store_bcn_tmpl Failed");
2432 		goto send_rsp;
2433 	}
2434 
2435 send_rsp:
2436 	bcn_info->status = status;
2437 	wma_send_msg(wma, WMA_SEND_BCN_RSP, (void *)bcn_info, 0);
2438 }
2439 
2440 /**
2441  * wma_set_keepalive_req() - send keep alive request to fw
2442  * @wma: wma handle
2443  * @keepalive: keep alive parameters
2444  *
2445  * Return: none
2446  */
2447 void wma_set_keepalive_req(tp_wma_handle wma,
2448 			   struct keep_alive_req *keepalive)
2449 {
2450 	wma_nofl_debug("KEEPALIVE:PacketType:%d", keepalive->packetType);
2451 	wma_set_sta_keep_alive(wma, keepalive->sessionId,
2452 			       keepalive->packetType,
2453 			       keepalive->timePeriod,
2454 			       keepalive->hostIpv4Addr,
2455 			       keepalive->destIpv4Addr,
2456 			       keepalive->dest_macaddr.bytes);
2457 
2458 	qdf_mem_free(keepalive);
2459 }
2460 
2461 /**
2462  * wma_beacon_miss_handler() - beacon miss event handler
2463  * @wma: wma handle
2464  * @vdev_id: vdev id
2465  * @riis: rssi value
2466  *
2467  * This function send beacon miss indication to upper layers.
2468  *
2469  * Return: none
2470  */
2471 void wma_beacon_miss_handler(tp_wma_handle wma, uint32_t vdev_id, int32_t rssi)
2472 {
2473 	struct missed_beacon_ind *beacon_miss_ind;
2474 	struct mac_context *mac = cds_get_context(QDF_MODULE_ID_PE);
2475 
2476 	beacon_miss_ind = qdf_mem_malloc(sizeof(*beacon_miss_ind));
2477 	if (!beacon_miss_ind)
2478 		return;
2479 
2480 	if (mac && mac->sme.tx_queue_cb)
2481 		mac->sme.tx_queue_cb(mac->hdd_handle, vdev_id,
2482 				     WLAN_STOP_ALL_NETIF_QUEUE,
2483 				     WLAN_CONTROL_PATH);
2484 	beacon_miss_ind->messageType = WMA_MISSED_BEACON_IND;
2485 	beacon_miss_ind->length = sizeof(*beacon_miss_ind);
2486 	beacon_miss_ind->bss_idx = vdev_id;
2487 
2488 	wma_send_msg(wma, WMA_MISSED_BEACON_IND, beacon_miss_ind, 0);
2489 	if (!wmi_service_enabled(wma->wmi_handle,
2490 				 wmi_service_hw_db2dbm_support))
2491 		rssi += WMA_TGT_NOISE_FLOOR_DBM;
2492 	wma_lost_link_info_handler(wma, vdev_id, rssi);
2493 }
2494 
2495 void wlan_cm_send_beacon_miss(uint8_t vdev_id, int32_t rssi)
2496 {
2497 	tp_wma_handle wma;
2498 
2499 	wma = cds_get_context(QDF_MODULE_ID_WMA);
2500 	if (!wma)
2501 		return;
2502 
2503 	wma_beacon_miss_handler(wma, vdev_id, rssi);
2504 }
2505 
2506 /**
2507  * wma_get_status_str() - get string of tx status from firmware
2508  * @status: tx status
2509  *
2510  * Return: converted string of tx status
2511  */
2512 static const char *wma_get_status_str(uint32_t status)
2513 {
2514 	switch (status) {
2515 	default:
2516 		return "unknown";
2517 	CASE_RETURN_STRING(WMI_MGMT_TX_COMP_TYPE_COMPLETE_OK);
2518 	CASE_RETURN_STRING(WMI_MGMT_TX_COMP_TYPE_DISCARD);
2519 	CASE_RETURN_STRING(WMI_MGMT_TX_COMP_TYPE_INSPECT);
2520 	CASE_RETURN_STRING(WMI_MGMT_TX_COMP_TYPE_COMPLETE_NO_ACK);
2521 	CASE_RETURN_STRING(WMI_MGMT_TX_COMP_TYPE_MAX);
2522 	}
2523 }
2524 
2525 #ifdef CONFIG_HL_SUPPORT
2526 static inline void wma_mgmt_unmap_buf(tp_wma_handle wma_handle, qdf_nbuf_t buf)
2527 {
2528 }
2529 #else
2530 static inline void wma_mgmt_unmap_buf(tp_wma_handle wma_handle, qdf_nbuf_t buf)
2531 {
2532 	qdf_nbuf_unmap_single(wma_handle->qdf_dev, buf, QDF_DMA_TO_DEVICE);
2533 }
2534 #endif
2535 
2536 #if !defined(REMOVE_PKT_LOG)
2537 /**
2538  * wma_mgmt_pktdump_status_map() - map MGMT Tx completion status with
2539  * packet dump Tx status
2540  * @status: MGMT Tx completion status
2541  *
2542  * Return: packet dump tx_status enum
2543  */
2544 static inline enum tx_status
2545 wma_mgmt_pktdump_status_map(WMI_MGMT_TX_COMP_STATUS_TYPE status)
2546 {
2547 	enum tx_status pktdump_status;
2548 
2549 	switch (status) {
2550 	case WMI_MGMT_TX_COMP_TYPE_COMPLETE_OK:
2551 		pktdump_status = tx_status_ok;
2552 		break;
2553 	case WMI_MGMT_TX_COMP_TYPE_DISCARD:
2554 		pktdump_status = tx_status_discard;
2555 		break;
2556 	case WMI_MGMT_TX_COMP_TYPE_COMPLETE_NO_ACK:
2557 		pktdump_status = tx_status_no_ack;
2558 		break;
2559 	default:
2560 		pktdump_status = tx_status_discard;
2561 		break;
2562 	}
2563 	return pktdump_status;
2564 }
2565 #endif
2566 
2567 /**
2568  * wma_process_mgmt_tx_completion() - process mgmt completion
2569  * @wma_handle: wma handle
2570  * @desc_id: descriptor id
2571  * @status: status
2572  *
2573  * Return: 0 for success or error code
2574  */
2575 static int wma_process_mgmt_tx_completion(tp_wma_handle wma_handle,
2576 					  uint32_t desc_id, uint32_t status)
2577 {
2578 	struct wlan_objmgr_pdev *pdev;
2579 	qdf_nbuf_t buf = NULL;
2580 	QDF_STATUS ret;
2581 #if !defined(REMOVE_PKT_LOG)
2582 	uint8_t vdev_id = 0;
2583 	ol_txrx_pktdump_cb packetdump_cb;
2584 	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
2585 	enum tx_status pktdump_status;
2586 #endif
2587 	struct wmi_mgmt_params mgmt_params = {};
2588 
2589 	if (wma_validate_handle(wma_handle))
2590 		return -EINVAL;
2591 
2592 	wma_debug("status: %s wmi_desc_id: %d",
2593 		  wma_get_status_str(status), desc_id);
2594 
2595 	pdev = wma_handle->pdev;
2596 	if (!pdev) {
2597 		wma_err("psoc ptr is NULL");
2598 		return -EINVAL;
2599 	}
2600 
2601 	buf = mgmt_txrx_get_nbuf(pdev, desc_id);
2602 
2603 
2604 	if (buf)
2605 		wma_mgmt_unmap_buf(wma_handle, buf);
2606 
2607 #if !defined(REMOVE_PKT_LOG)
2608 	vdev_id = mgmt_txrx_get_vdev_id(pdev, desc_id);
2609 	mgmt_params.vdev_id = vdev_id;
2610 	packetdump_cb = wma_handle->wma_mgmt_tx_packetdump_cb;
2611 	pktdump_status = wma_mgmt_pktdump_status_map(status);
2612 	if (packetdump_cb)
2613 		packetdump_cb(soc, WMI_PDEV_ID_SOC, vdev_id,
2614 			      buf, pktdump_status, TX_MGMT_PKT);
2615 #endif
2616 
2617 	ret = mgmt_txrx_tx_completion_handler(pdev, desc_id, status,
2618 					      &mgmt_params);
2619 
2620 	if (ret != QDF_STATUS_SUCCESS) {
2621 		wma_err("Failed to process mgmt tx completion");
2622 		return -EINVAL;
2623 	}
2624 
2625 	return 0;
2626 }
2627 
2628 /**
2629  * wma_extract_mgmt_offload_event_params() - Extract mgmt event params
2630  * @params: Management offload event params
2631  * @hdr: Management header to extract
2632  *
2633  * Return: None
2634  */
2635 static void wma_extract_mgmt_offload_event_params(
2636 				struct mgmt_offload_event_params *params,
2637 				wmi_mgmt_hdr *hdr)
2638 {
2639 	params->tsf_l32 = hdr->tsf_l32;
2640 	params->chan_freq = hdr->chan_freq;
2641 	params->rate_kbps = hdr->rate_kbps;
2642 	params->rssi = hdr->rssi;
2643 	params->buf_len = hdr->buf_len;
2644 	params->tx_status = hdr->tx_status;
2645 	params->tx_retry_cnt = hdr->tx_retry_cnt;
2646 }
2647 
2648 /**
2649  * wma_mgmt_tx_completion_handler() - wma mgmt Tx completion event handler
2650  * @handle: wma handle
2651  * @cmpl_event_params: completion event handler data
2652  * @len: length of @cmpl_event_params
2653  *
2654  * Return: 0 on success; error number otherwise
2655  */
2656 
2657 int wma_mgmt_tx_completion_handler(void *handle, uint8_t *cmpl_event_params,
2658 				   uint32_t len)
2659 {
2660 	tp_wma_handle wma_handle = (tp_wma_handle)handle;
2661 	WMI_MGMT_TX_COMPLETION_EVENTID_param_tlvs *param_buf;
2662 	wmi_mgmt_tx_compl_event_fixed_param *cmpl_params;
2663 
2664 	param_buf = (WMI_MGMT_TX_COMPLETION_EVENTID_param_tlvs *)
2665 		cmpl_event_params;
2666 	if (!param_buf || !wma_handle) {
2667 		wma_err("Invalid mgmt Tx completion event");
2668 		return -EINVAL;
2669 	}
2670 	cmpl_params = param_buf->fixed_param;
2671 
2672 	if ((ucfg_pkt_capture_get_pktcap_mode(wma_handle->psoc) &
2673 	    PKT_CAPTURE_MODE_MGMT_ONLY) && param_buf->mgmt_hdr) {
2674 		struct mgmt_offload_event_params params = {0};
2675 
2676 		wma_extract_mgmt_offload_event_params(
2677 					&params,
2678 					(wmi_mgmt_hdr *)param_buf->mgmt_hdr);
2679 		ucfg_pkt_capture_mgmt_tx_completion(wma_handle->pdev,
2680 						    cmpl_params->desc_id,
2681 						    cmpl_params->status,
2682 						    &params);
2683 	}
2684 
2685 	wma_process_mgmt_tx_completion(wma_handle, cmpl_params->desc_id,
2686 				       cmpl_params->status);
2687 
2688 	return 0;
2689 }
2690 
2691 /**
2692  * wma_mgmt_tx_bundle_completion_handler() - mgmt bundle comp handler
2693  * @handle: wma handle
2694  * @buf: buffer
2695  * @len: length
2696  *
2697  * Return: 0 for success or error code
2698  */
2699 int wma_mgmt_tx_bundle_completion_handler(void *handle, uint8_t *buf,
2700 				   uint32_t len)
2701 {
2702 	tp_wma_handle wma_handle = (tp_wma_handle)handle;
2703 	WMI_MGMT_TX_BUNDLE_COMPLETION_EVENTID_param_tlvs *param_buf;
2704 	wmi_mgmt_tx_compl_bundle_event_fixed_param	*cmpl_params;
2705 	uint32_t num_reports;
2706 	uint32_t *desc_ids;
2707 	uint32_t *status;
2708 	uint32_t i, buf_len;
2709 	bool excess_data = false;
2710 
2711 	param_buf = (WMI_MGMT_TX_BUNDLE_COMPLETION_EVENTID_param_tlvs *)buf;
2712 	if (!param_buf || !wma_handle) {
2713 		wma_err("Invalid mgmt Tx completion event");
2714 		return -EINVAL;
2715 	}
2716 	cmpl_params = param_buf->fixed_param;
2717 	num_reports = cmpl_params->num_reports;
2718 	desc_ids = (uint32_t *)(param_buf->desc_ids);
2719 	status = (uint32_t *)(param_buf->status);
2720 
2721 	/* buf contains num_reports * sizeof(uint32) len of desc_ids and
2722 	 * num_reports * sizeof(uint32) status,
2723 	 * so (2 x (num_reports * sizeof(uint32)) should not exceed MAX
2724 	 */
2725 	if (cmpl_params->num_reports > (WMI_SVC_MSG_MAX_SIZE /
2726 	    (2 * sizeof(uint32_t))))
2727 		excess_data = true;
2728 	else
2729 		buf_len = cmpl_params->num_reports * (2 * sizeof(uint32_t));
2730 
2731 	if (excess_data || (sizeof(*cmpl_params) > (WMI_SVC_MSG_MAX_SIZE -
2732 	    buf_len))) {
2733 		wma_err("excess wmi buffer: num_reports %d",
2734 			cmpl_params->num_reports);
2735 		return -EINVAL;
2736 	}
2737 
2738 	if ((cmpl_params->num_reports > param_buf->num_desc_ids) ||
2739 	    (cmpl_params->num_reports > param_buf->num_status)) {
2740 		wma_err("Invalid num_reports %d, num_desc_ids %d, num_status %d",
2741 			 cmpl_params->num_reports, param_buf->num_desc_ids,
2742 			 param_buf->num_status);
2743 		return -EINVAL;
2744 	}
2745 
2746 	for (i = 0; i < num_reports; i++) {
2747 		if ((ucfg_pkt_capture_get_pktcap_mode(wma_handle->psoc) &
2748 		    PKT_CAPTURE_MODE_MGMT_ONLY) && param_buf->mgmt_hdr) {
2749 			struct mgmt_offload_event_params params = {0};
2750 
2751 			wma_extract_mgmt_offload_event_params(
2752 				&params,
2753 				&((wmi_mgmt_hdr *)param_buf->mgmt_hdr)[i]);
2754 			ucfg_pkt_capture_mgmt_tx_completion(
2755 				wma_handle->pdev, desc_ids[i],
2756 				status[i], &params);
2757 		}
2758 
2759 		wma_process_mgmt_tx_completion(wma_handle,
2760 					       desc_ids[i], status[i]);
2761 	}
2762 	return 0;
2763 }
2764 
2765 /**
2766  * wma_process_update_opmode() - process update VHT opmode cmd from UMAC
2767  * @wma_handle: wma handle
2768  * @update_vht_opmode: vht opmode
2769  *
2770  * Return: none
2771  */
2772 void wma_process_update_opmode(tp_wma_handle wma_handle,
2773 			       tUpdateVHTOpMode *update_vht_opmode)
2774 {
2775 	wmi_host_channel_width ch_width;
2776 	uint8_t pdev_id;
2777 	struct wlan_objmgr_peer *peer;
2778 	struct wlan_objmgr_psoc *psoc = wma_handle->psoc;
2779 	enum wlan_phymode peer_phymode;
2780 	uint32_t fw_phymode;
2781 	enum wlan_peer_type peer_type;
2782 
2783 	pdev_id = wlan_objmgr_pdev_get_pdev_id(wma_handle->pdev);
2784 	peer = wlan_objmgr_get_peer(psoc, pdev_id,
2785 				    update_vht_opmode->peer_mac,
2786 				    WLAN_LEGACY_WMA_ID);
2787 	if (!peer) {
2788 		wma_err("peer object invalid");
2789 		return;
2790 	}
2791 
2792 	peer_type = wlan_peer_get_peer_type(peer);
2793 	if (peer_type == WLAN_PEER_SELF) {
2794 		wma_err("self peer wrongly used");
2795 		wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_WMA_ID);
2796 		return;
2797 	}
2798 
2799 	wlan_peer_obj_lock(peer);
2800 	peer_phymode = wlan_peer_get_phymode(peer);
2801 	wlan_peer_obj_unlock(peer);
2802 	wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_WMA_ID);
2803 
2804 	fw_phymode = wma_host_to_fw_phymode(peer_phymode);
2805 
2806 	ch_width = wmi_get_ch_width_from_phy_mode(wma_handle->wmi_handle,
2807 						  fw_phymode);
2808 	wma_debug("ch_width: %d, fw phymode: %d peer_phymode %d",
2809 		  ch_width, fw_phymode, peer_phymode);
2810 	if (ch_width < update_vht_opmode->opMode) {
2811 		wma_err("Invalid peer bw update %d, self bw %d",
2812 			update_vht_opmode->opMode, ch_width);
2813 		return;
2814 	}
2815 
2816 	wma_debug("opMode = %d", update_vht_opmode->opMode);
2817 	wma_set_peer_param(wma_handle, update_vht_opmode->peer_mac,
2818 			   WMI_PEER_CHWIDTH, update_vht_opmode->opMode,
2819 			   update_vht_opmode->smesessionId);
2820 }
2821 
2822 /**
2823  * wma_process_update_rx_nss() - process update RX NSS cmd from UMAC
2824  * @wma_handle: wma handle
2825  * @update_rx_nss: rx nss value
2826  *
2827  * Return: none
2828  */
2829 void wma_process_update_rx_nss(tp_wma_handle wma_handle,
2830 			       tUpdateRxNss *update_rx_nss)
2831 {
2832 	struct target_psoc_info *tgt_hdl;
2833 	struct wma_txrx_node *intr =
2834 		&wma_handle->interfaces[update_rx_nss->smesessionId];
2835 	int rx_nss = update_rx_nss->rxNss;
2836 	int num_rf_chains;
2837 
2838 	tgt_hdl = wlan_psoc_get_tgt_if_handle(wma_handle->psoc);
2839 	if (!tgt_hdl) {
2840 		wma_err("target psoc info is NULL");
2841 		return;
2842 	}
2843 
2844 	num_rf_chains = target_if_get_num_rf_chains(tgt_hdl);
2845 	if (rx_nss > num_rf_chains || rx_nss > WMA_MAX_NSS)
2846 		rx_nss = QDF_MIN(num_rf_chains, WMA_MAX_NSS);
2847 
2848 	intr->nss = (uint8_t)rx_nss;
2849 	update_rx_nss->rxNss = (uint32_t)rx_nss;
2850 
2851 	wma_debug("Rx Nss = %d", update_rx_nss->rxNss);
2852 
2853 	wma_set_peer_param(wma_handle, update_rx_nss->peer_mac,
2854 			   WMI_PEER_NSS, update_rx_nss->rxNss,
2855 			   update_rx_nss->smesessionId);
2856 }
2857 
2858 /**
2859  * wma_process_update_membership() - process update group membership cmd
2860  * @wma_handle: wma handle
2861  * @membership: group membership info
2862  *
2863  * Return: none
2864  */
2865 void wma_process_update_membership(tp_wma_handle wma_handle,
2866 				   tUpdateMembership *membership)
2867 {
2868 	wma_debug("membership = %x ", membership->membership);
2869 
2870 	wma_set_peer_param(wma_handle, membership->peer_mac,
2871 			   WMI_PEER_MEMBERSHIP, membership->membership,
2872 			   membership->smesessionId);
2873 }
2874 
2875 /**
2876  * wma_process_update_userpos() - process update user pos cmd from UMAC
2877  * @wma_handle: wma handle
2878  * @userpos: user pos value
2879  *
2880  * Return: none
2881  */
2882 void wma_process_update_userpos(tp_wma_handle wma_handle,
2883 				tUpdateUserPos *userpos)
2884 {
2885 	wma_debug("userPos = %x ", userpos->userPos);
2886 
2887 	wma_set_peer_param(wma_handle, userpos->peer_mac,
2888 			   WMI_PEER_USERPOS, userpos->userPos,
2889 			   userpos->smesessionId);
2890 
2891 	/* Now that membership/userpos is updated in fw,
2892 	 * enable GID PPS.
2893 	 */
2894 	wma_set_ppsconfig(userpos->smesessionId, WMA_VHT_PPS_GID_MATCH, 1);
2895 
2896 }
2897 
2898 QDF_STATUS wma_set_cts2self_for_p2p_go(void *wma_handle,
2899 				    uint32_t cts2self_for_p2p_go)
2900 {
2901 	int32_t ret;
2902 	tp_wma_handle wma = (tp_wma_handle)wma_handle;
2903 	struct pdev_params pdevparam;
2904 
2905 	pdevparam.param_id = WMI_PDEV_PARAM_CTS2SELF_FOR_P2P_GO_CONFIG;
2906 	pdevparam.param_value = cts2self_for_p2p_go;
2907 
2908 	ret = wmi_unified_pdev_param_send(wma->wmi_handle,
2909 			&pdevparam,
2910 			WMA_WILDCARD_PDEV_ID);
2911 	if (ret) {
2912 		wma_err("Fail to Set CTS2SELF for p2p GO %d",
2913 			cts2self_for_p2p_go);
2914 		return QDF_STATUS_E_FAILURE;
2915 	}
2916 
2917 	wma_nofl_debug("Successfully Set CTS2SELF for p2p GO %d",
2918 		       cts2self_for_p2p_go);
2919 
2920 	return QDF_STATUS_SUCCESS;
2921 }
2922 
2923 
2924 /**
2925  * wma_set_htconfig() - set ht config parameters to target
2926  * @vdev_id: vdev id
2927  * @ht_capab: ht capablity
2928  * @value: value of ht param
2929  *
2930  * Return: QDF status
2931  */
2932 QDF_STATUS wma_set_htconfig(uint8_t vdev_id, uint16_t ht_capab, int value)
2933 {
2934 	tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
2935 	QDF_STATUS ret = QDF_STATUS_E_FAILURE;
2936 
2937 	if (!wma)
2938 		return QDF_STATUS_E_INVAL;
2939 
2940 	switch (ht_capab) {
2941 	case WNI_CFG_HT_CAP_INFO_ADVANCE_CODING:
2942 		ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
2943 						      WMI_VDEV_PARAM_LDPC,
2944 						      value);
2945 		break;
2946 	case WNI_CFG_HT_CAP_INFO_TX_STBC:
2947 		ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
2948 						      WMI_VDEV_PARAM_TX_STBC,
2949 						      value);
2950 		break;
2951 	case WNI_CFG_HT_CAP_INFO_RX_STBC:
2952 		ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
2953 						      WMI_VDEV_PARAM_RX_STBC,
2954 						      value);
2955 		break;
2956 	case WNI_CFG_HT_CAP_INFO_SHORT_GI_20MHZ:
2957 	case WNI_CFG_HT_CAP_INFO_SHORT_GI_40MHZ:
2958 		wma_err("ht_capab = %d, value = %d", ht_capab,
2959 			 value);
2960 		ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
2961 						WMI_VDEV_PARAM_SGI, value);
2962 		if (ret == QDF_STATUS_SUCCESS)
2963 			wma->interfaces[vdev_id].config.shortgi = value;
2964 		break;
2965 	default:
2966 		wma_err("INVALID HT CONFIG");
2967 	}
2968 
2969 	return ret;
2970 }
2971 
2972 /**
2973  * wma_extract_ccmp_pn() - extract 6 byte PN from the CCMP header
2974  * @ccmp_ptr: CCMP header
2975  *
2976  * Return: PN extracted from header.
2977  */
2978 static uint64_t wma_extract_ccmp_pn(uint8_t *ccmp_ptr)
2979 {
2980 	uint8_t rsvd, key, pn[6];
2981 	uint64_t new_pn;
2982 
2983 	/*
2984 	 *   +-----+-----+------+----------+-----+-----+-----+-----+
2985 	 *   | PN0 | PN1 | rsvd | rsvd/key | PN2 | PN3 | PN4 | PN5 |
2986 	 *   +-----+-----+------+----------+-----+-----+-----+-----+
2987 	 *                   CCMP Header Format
2988 	 */
2989 
2990 	/* Extract individual bytes */
2991 	pn[0] = (uint8_t) *ccmp_ptr;
2992 	pn[1] = (uint8_t) *(ccmp_ptr + 1);
2993 	rsvd = (uint8_t) *(ccmp_ptr + 2);
2994 	key = (uint8_t) *(ccmp_ptr + 3);
2995 	pn[2] = (uint8_t) *(ccmp_ptr + 4);
2996 	pn[3] = (uint8_t) *(ccmp_ptr + 5);
2997 	pn[4] = (uint8_t) *(ccmp_ptr + 6);
2998 	pn[5] = (uint8_t) *(ccmp_ptr + 7);
2999 
3000 	/* Form 6 byte PN with 6 individual bytes of PN */
3001 	new_pn = ((uint64_t) pn[5] << 40) |
3002 		 ((uint64_t) pn[4] << 32) |
3003 		 ((uint64_t) pn[3] << 24) |
3004 		 ((uint64_t) pn[2] << 16) |
3005 		 ((uint64_t) pn[1] << 8) | ((uint64_t) pn[0] << 0);
3006 
3007 	return new_pn;
3008 }
3009 
3010 /**
3011  * wma_is_ccmp_pn_replay_attack() - detect replay attacking using PN in CCMP
3012  * @wma: wma context
3013  * @wh: 802.11 frame header
3014  * @ccmp_ptr: CCMP frame header
3015  *
3016  * Return: true/false
3017  */
3018 static bool
3019 wma_is_ccmp_pn_replay_attack(tp_wma_handle wma, struct ieee80211_frame *wh,
3020 			     uint8_t *ccmp_ptr)
3021 {
3022 	uint64_t new_pn;
3023 	bool ret = false;
3024 	struct peer_mlme_priv_obj *peer_priv;
3025 	struct wlan_objmgr_peer *peer;
3026 
3027 	new_pn = wma_extract_ccmp_pn(ccmp_ptr);
3028 
3029 	peer = wlan_objmgr_get_peer_by_mac(wma->psoc, wh->i_addr2,
3030 					   WLAN_LEGACY_WMA_ID);
3031 	if (!peer)
3032 		return ret;
3033 
3034 	peer_priv = wlan_objmgr_peer_get_comp_private_obj(peer,
3035 							  WLAN_UMAC_COMP_MLME);
3036 	if (!peer_priv) {
3037 		wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_WMA_ID);
3038 		return ret;
3039 	}
3040 
3041 	if (peer_priv->last_pn_valid) {
3042 		if (new_pn > peer_priv->last_pn) {
3043 			peer_priv->last_pn = new_pn;
3044 		} else {
3045 			wma_err_rl("PN Replay attack detected");
3046 			/* per 11W amendment, keeping track of replay attacks */
3047 			peer_priv->rmf_pn_replays += 1;
3048 			ret = true;
3049 		}
3050 	} else {
3051 		peer_priv->last_pn_valid = 1;
3052 		peer_priv->last_pn = new_pn;
3053 	}
3054 
3055 	wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_WMA_ID);
3056 
3057 	return ret;
3058 }
3059 
3060 /**
3061  * wma_process_bip() - process mmie in rmf frame
3062  * @wma_handle: wma handle
3063  * @iface: txrx node
3064  * @wh: 80211 frame
3065  * @wbuf: Buffer
3066  *
3067  * Return: 0 for success or error code
3068  */
3069 static
3070 int wma_process_bip(tp_wma_handle wma_handle, struct wma_txrx_node *iface,
3071 		    struct ieee80211_frame *wh, qdf_nbuf_t wbuf)
3072 {
3073 	uint16_t mmie_size;
3074 	uint8_t *efrm;
3075 	int32_t mgmtcipherset;
3076 	enum wlan_crypto_cipher_type key_cipher;
3077 
3078 	efrm = qdf_nbuf_data(wbuf) + qdf_nbuf_len(wbuf);
3079 
3080 	mgmtcipherset = wlan_crypto_get_param(iface->vdev,
3081 					      WLAN_CRYPTO_PARAM_MGMT_CIPHER);
3082 	if (mgmtcipherset <= 0) {
3083 		wma_err("Invalid key cipher %d", mgmtcipherset);
3084 		return -EINVAL;
3085 	}
3086 
3087 	if (mgmtcipherset & (1 << WLAN_CRYPTO_CIPHER_AES_CMAC)) {
3088 		key_cipher = WLAN_CRYPTO_CIPHER_AES_CMAC;
3089 		mmie_size = cds_get_mmie_size();
3090 	} else if (mgmtcipherset & (1 << WLAN_CRYPTO_CIPHER_AES_GMAC)) {
3091 		key_cipher = WLAN_CRYPTO_CIPHER_AES_GMAC;
3092 		mmie_size = cds_get_gmac_mmie_size();
3093 	} else if (mgmtcipherset & (1 << WLAN_CRYPTO_CIPHER_AES_GMAC_256)) {
3094 		key_cipher = WLAN_CRYPTO_CIPHER_AES_GMAC_256;
3095 		mmie_size = cds_get_gmac_mmie_size();
3096 	} else {
3097 		wma_err("Invalid key cipher %d", mgmtcipherset);
3098 		return -EINVAL;
3099 	}
3100 
3101 	/* Check if frame is invalid length */
3102 	if (efrm - (uint8_t *)wh < sizeof(*wh) + mmie_size) {
3103 		wma_err("Invalid frame length");
3104 		return -EINVAL;
3105 	}
3106 
3107 	switch (key_cipher) {
3108 	case WLAN_CRYPTO_CIPHER_AES_CMAC:
3109 		if (!wmi_service_enabled(wma_handle->wmi_handle,
3110 					 wmi_service_sta_pmf_offload)) {
3111 			if (!wlan_crypto_is_mmie_valid(iface->vdev,
3112 						       (uint8_t *)wh, efrm)) {
3113 				wma_debug("BC/MC MIC error or MMIE not present, dropping the frame");
3114 				return -EINVAL;
3115 			}
3116 		}
3117 		break;
3118 	case WLAN_CRYPTO_CIPHER_AES_GMAC:
3119 	case WLAN_CRYPTO_CIPHER_AES_GMAC_256:
3120 		if (!wmi_service_enabled(wma_handle->wmi_handle,
3121 					 wmi_service_gmac_offload_support)) {
3122 			if (!wlan_crypto_is_mmie_valid(iface->vdev,
3123 						       (uint8_t *)wh, efrm)) {
3124 				wma_debug("BC/MC GMAC MIC error or MMIE not present, dropping the frame");
3125 				return -EINVAL;
3126 			}
3127 		}
3128 		break;
3129 	default:
3130 		wma_err("Invalid key_type %d", key_cipher);
3131 		return -EINVAL;
3132 	}
3133 
3134 	qdf_nbuf_trim_tail(wbuf, mmie_size);
3135 
3136 	return 0;
3137 }
3138 
3139 /**
3140  * wma_process_rmf_frame() - process rmf frame
3141  * @wma_handle: wma handle
3142  * @iface: txrx node
3143  * @wh: 80211 frame
3144  * @rx_pkt: rx packet
3145  * @wbuf: Buffer
3146  *
3147  * Return: 0 for success or error code
3148  */
3149 static
3150 int wma_process_rmf_frame(tp_wma_handle wma_handle,
3151 	struct wma_txrx_node *iface,
3152 	struct ieee80211_frame *wh,
3153 	cds_pkt_t *rx_pkt,
3154 	qdf_nbuf_t wbuf)
3155 {
3156 	uint8_t *orig_hdr;
3157 	uint8_t *ccmp;
3158 	uint8_t mic_len, hdr_len, pdev_id;
3159 	QDF_STATUS status;
3160 
3161 	if ((wh)->i_fc[1] & IEEE80211_FC1_WEP) {
3162 		if (QDF_IS_ADDR_BROADCAST(wh->i_addr1) ||
3163 		    IEEE80211_IS_MULTICAST(wh->i_addr1)) {
3164 			wma_err("Encrypted BC/MC frame dropping the frame");
3165 			cds_pkt_return_packet(rx_pkt);
3166 			return -EINVAL;
3167 		}
3168 
3169 		if (iface->type == WMI_VDEV_TYPE_NDI) {
3170 			hdr_len = IEEE80211_CCMP_HEADERLEN;
3171 			mic_len = IEEE80211_CCMP_MICLEN;
3172 		} else {
3173 			pdev_id =
3174 				wlan_objmgr_pdev_get_pdev_id(wma_handle->pdev);
3175 			status = mlme_get_peer_mic_len(wma_handle->psoc,
3176 						       pdev_id, wh->i_addr2,
3177 						       &mic_len, &hdr_len);
3178 			if (QDF_IS_STATUS_ERROR(status)) {
3179 				wma_err("Failed to get mic hdr and length");
3180 				cds_pkt_return_packet(rx_pkt);
3181 				return -EINVAL;
3182 			}
3183 		}
3184 
3185 		if (qdf_nbuf_len(wbuf) < (sizeof(*wh) + hdr_len + mic_len)) {
3186 			wma_err("Buffer length less than expected %d",
3187 				 (int)qdf_nbuf_len(wbuf));
3188 			cds_pkt_return_packet(rx_pkt);
3189 			return -EINVAL;
3190 		}
3191 
3192 		orig_hdr = (uint8_t *) qdf_nbuf_data(wbuf);
3193 		/* Pointer to head of CCMP header */
3194 		ccmp = orig_hdr + sizeof(*wh);
3195 		if (wma_is_ccmp_pn_replay_attack(wma_handle, wh, ccmp)) {
3196 			wma_err_rl("Dropping the frame");
3197 			cds_pkt_return_packet(rx_pkt);
3198 			return -EINVAL;
3199 		}
3200 
3201 		/* Strip privacy headers (and trailer)
3202 		 * for a received frame
3203 		 */
3204 		qdf_mem_move(orig_hdr +
3205 			hdr_len, wh,
3206 			sizeof(*wh));
3207 		qdf_nbuf_pull_head(wbuf,
3208 			hdr_len);
3209 		qdf_nbuf_trim_tail(wbuf, mic_len);
3210 		/*
3211 		 * CCMP header has been pulled off
3212 		 * reinitialize the start pointer of mac header
3213 		 * to avoid accessing incorrect address
3214 		 */
3215 		wh = (struct ieee80211_frame *) qdf_nbuf_data(wbuf);
3216 		rx_pkt->pkt_meta.mpdu_hdr_ptr =
3217 				qdf_nbuf_data(wbuf);
3218 		rx_pkt->pkt_meta.mpdu_len = qdf_nbuf_len(wbuf);
3219 		rx_pkt->pkt_buf = wbuf;
3220 		if (rx_pkt->pkt_meta.mpdu_len >=
3221 			rx_pkt->pkt_meta.mpdu_hdr_len) {
3222 			rx_pkt->pkt_meta.mpdu_data_len =
3223 				rx_pkt->pkt_meta.mpdu_len -
3224 				rx_pkt->pkt_meta.mpdu_hdr_len;
3225 		} else {
3226 			wma_err("mpdu len %d less than hdr %d, dropping frame",
3227 				rx_pkt->pkt_meta.mpdu_len,
3228 				rx_pkt->pkt_meta.mpdu_hdr_len);
3229 			cds_pkt_return_packet(rx_pkt);
3230 			return -EINVAL;
3231 		}
3232 
3233 		if (rx_pkt->pkt_meta.mpdu_data_len > MAX_MGMT_MPDU_LEN) {
3234 			wma_err("Data Len %d greater than max, dropping frame",
3235 				rx_pkt->pkt_meta.mpdu_data_len);
3236 			cds_pkt_return_packet(rx_pkt);
3237 			return -EINVAL;
3238 		}
3239 		rx_pkt->pkt_meta.mpdu_data_ptr =
3240 		rx_pkt->pkt_meta.mpdu_hdr_ptr +
3241 		rx_pkt->pkt_meta.mpdu_hdr_len;
3242 		wma_debug("BSSID: "QDF_MAC_ADDR_FMT" tsf_delta: %u",
3243 			  QDF_MAC_ADDR_REF(wh->i_addr3),
3244 			  rx_pkt->pkt_meta.tsf_delta);
3245 	} else {
3246 		if (QDF_IS_ADDR_BROADCAST(wh->i_addr1) ||
3247 		    IEEE80211_IS_MULTICAST(wh->i_addr1)) {
3248 			if (0 != wma_process_bip(wma_handle, iface, wh, wbuf)) {
3249 				cds_pkt_return_packet(rx_pkt);
3250 				return -EINVAL;
3251 			}
3252 		} else {
3253 			wma_err("Rx unprotected unicast mgmt frame");
3254 			rx_pkt->pkt_meta.dpuFeedback =
3255 				DPU_FEEDBACK_UNPROTECTED_ERROR;
3256 		}
3257 	}
3258 	return 0;
3259 }
3260 
3261 /**
3262  * wma_get_peer_pmf_status() - Get the PMF capability of peer
3263  * @wma: wma handle
3264  * @peer_mac: peer mac addr
3265  *
3266  * Return: True if PMF is enabled, false otherwise.
3267  */
3268 static bool
3269 wma_get_peer_pmf_status(tp_wma_handle wma, uint8_t *peer_mac)
3270 {
3271 	struct wlan_objmgr_peer *peer;
3272 	bool is_pmf_enabled;
3273 
3274 	if (!peer_mac) {
3275 		wma_err("peer_mac is NULL");
3276 		return false;
3277 	}
3278 
3279 	peer = wlan_objmgr_get_peer(wma->psoc,
3280 				    wlan_objmgr_pdev_get_pdev_id(wma->pdev),
3281 				    peer_mac, WLAN_LEGACY_WMA_ID);
3282 	if (!peer) {
3283 		wma_err("Peer of peer_mac "QDF_MAC_ADDR_FMT" not found",
3284 			 QDF_MAC_ADDR_REF(peer_mac));
3285 		return false;
3286 	}
3287 	is_pmf_enabled = mlme_get_peer_pmf_status(peer);
3288 	wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_WMA_ID);
3289 	wma_nofl_debug("get is_pmf_enabled %d for "QDF_MAC_ADDR_FMT,
3290 		       is_pmf_enabled, QDF_MAC_ADDR_REF(peer_mac));
3291 
3292 	return is_pmf_enabled;
3293 }
3294 
3295 /**
3296  * wma_check_and_process_rmf_frame() - Process the frame if it is of rmf type
3297  * @wma_handle: wma handle
3298  * @vdev_id: vdev id
3299  * @wh: double pointer to 802.11 frame header which will be updated if the
3300  *	frame is of rmf type.
3301  * @rx_pkt: rx packet
3302  * @buf: Buffer
3303  *
3304  * Process the frame as rmf frame only if both DUT and peer are of PMF capable
3305  *
3306  * Return: 0 for success or error code
3307  */
3308 static int
3309 wma_check_and_process_rmf_frame(tp_wma_handle wma_handle,
3310 				uint8_t vdev_id,
3311 				struct ieee80211_frame **wh,
3312 				cds_pkt_t *rx_pkt,
3313 				qdf_nbuf_t buf)
3314 {
3315 	int status;
3316 	struct wma_txrx_node *iface;
3317 	struct ieee80211_frame *hdr = *wh;
3318 
3319 	iface = &(wma_handle->interfaces[vdev_id]);
3320 	if (iface->type != WMI_VDEV_TYPE_NDI && !iface->rmfEnabled)
3321 		return 0;
3322 
3323 	if (qdf_is_macaddr_group((struct qdf_mac_addr *)(hdr->i_addr1)) ||
3324 	    qdf_is_macaddr_broadcast((struct qdf_mac_addr *)(hdr->i_addr1)) ||
3325 	    wma_get_peer_pmf_status(wma_handle, hdr->i_addr2) ||
3326 	    (iface->type == WMI_VDEV_TYPE_NDI &&
3327 	    (hdr->i_fc[1] & IEEE80211_FC1_WEP))) {
3328 		status = wma_process_rmf_frame(wma_handle, iface, hdr,
3329 					       rx_pkt, buf);
3330 		if (status)
3331 			return status;
3332 		/*
3333 		 * CCMP header might have been pulled off reinitialize the
3334 		 * start pointer of mac header
3335 		 */
3336 		*wh = (struct ieee80211_frame *)qdf_nbuf_data(buf);
3337 	}
3338 
3339 	return 0;
3340 }
3341 
3342 /**
3343  * wma_is_pkt_drop_candidate() - check if the mgmt frame should be droppped
3344  * @wma_handle: wma handle
3345  * @peer_addr: peer MAC address
3346  * @bssid: BSSID Address
3347  * @subtype: Management frame subtype
3348  *
3349  * This function is used to decide if a particular management frame should be
3350  * dropped to prevent DOS attack. Timestamp is used to decide the DOS attack.
3351  *
3352  * Return: true if the packet should be dropped and false oterwise
3353  */
3354 static bool wma_is_pkt_drop_candidate(tp_wma_handle wma_handle,
3355 				      uint8_t *peer_addr, uint8_t *bssid,
3356 				      uint8_t subtype)
3357 {
3358 	bool should_drop = false;
3359 	uint8_t nan_addr[] = {0x50, 0x6F, 0x9A, 0x01, 0x00, 0x00};
3360 
3361 	/* Drop the beacons from NAN device */
3362 	if ((subtype == MGMT_SUBTYPE_BEACON) &&
3363 		(!qdf_mem_cmp(nan_addr, bssid, NAN_CLUSTER_ID_BYTES))) {
3364 			should_drop = true;
3365 			goto end;
3366 	}
3367 end:
3368 	return should_drop;
3369 }
3370 
3371 #define RATE_LIMIT 16
3372 
3373 int wma_form_rx_packet(qdf_nbuf_t buf,
3374 			struct mgmt_rx_event_params *mgmt_rx_params,
3375 			cds_pkt_t *rx_pkt)
3376 {
3377 	uint8_t vdev_id = WMA_INVALID_VDEV_ID;
3378 	struct ieee80211_frame *wh;
3379 	uint8_t mgt_type, mgt_subtype;
3380 	int status;
3381 	tp_wma_handle wma_handle = (tp_wma_handle)
3382 				cds_get_context(QDF_MODULE_ID_WMA);
3383 #if !defined(REMOVE_PKT_LOG)
3384 	ol_txrx_pktdump_cb packetdump_cb;
3385 	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
3386 #endif
3387 	static uint8_t limit_prints_invalid_len = RATE_LIMIT - 1;
3388 	static uint8_t limit_prints_load_unload = RATE_LIMIT - 1;
3389 	static uint8_t limit_prints_recovery = RATE_LIMIT - 1;
3390 
3391 	if (!wma_handle) {
3392 		qdf_nbuf_free(buf);
3393 		qdf_mem_free(rx_pkt);
3394 		return -EINVAL;
3395 	}
3396 
3397 	if (!mgmt_rx_params) {
3398 		limit_prints_invalid_len++;
3399 		if (limit_prints_invalid_len == RATE_LIMIT) {
3400 			wma_debug("mgmt rx params is NULL");
3401 			limit_prints_invalid_len = 0;
3402 		}
3403 		qdf_nbuf_free(buf);
3404 		qdf_mem_free(rx_pkt);
3405 		return -EINVAL;
3406 	}
3407 
3408 	if (cds_is_load_or_unload_in_progress()) {
3409 		limit_prints_load_unload++;
3410 		if (limit_prints_load_unload == RATE_LIMIT) {
3411 			wma_debug("Load/Unload in progress");
3412 			limit_prints_load_unload = 0;
3413 		}
3414 		qdf_nbuf_free(buf);
3415 		qdf_mem_free(rx_pkt);
3416 		return -EINVAL;
3417 	}
3418 
3419 	if (cds_is_driver_recovering()) {
3420 		limit_prints_recovery++;
3421 		if (limit_prints_recovery == RATE_LIMIT) {
3422 			wma_debug("Recovery in progress");
3423 			limit_prints_recovery = 0;
3424 		}
3425 		qdf_nbuf_free(buf);
3426 		qdf_mem_free(rx_pkt);
3427 		return -EINVAL;
3428 	}
3429 
3430 	if (cds_is_driver_in_bad_state()) {
3431 		limit_prints_recovery++;
3432 		if (limit_prints_recovery == RATE_LIMIT) {
3433 			wma_debug("Driver in bad state");
3434 			limit_prints_recovery = 0;
3435 		}
3436 		qdf_nbuf_free(buf);
3437 		qdf_mem_free(rx_pkt);
3438 		return -EINVAL;
3439 	}
3440 
3441 	/*
3442 	 * Fill in meta information needed by pe/lim
3443 	 * TODO: Try to maintain rx metainfo as part of skb->data.
3444 	 */
3445 	rx_pkt->pkt_meta.frequency = mgmt_rx_params->chan_freq;
3446 	rx_pkt->pkt_meta.scan_src = mgmt_rx_params->flags;
3447 
3448 	/*
3449 	 * Get the rssi value from the current snr value
3450 	 * using standard noise floor of -96.
3451 	 */
3452 	rx_pkt->pkt_meta.rssi = mgmt_rx_params->snr +
3453 				WMA_NOISE_FLOOR_DBM_DEFAULT;
3454 	rx_pkt->pkt_meta.snr = mgmt_rx_params->snr;
3455 
3456 	/* If absolute rssi is available from firmware, use it */
3457 	if (mgmt_rx_params->rssi != 0)
3458 		rx_pkt->pkt_meta.rssi_raw = mgmt_rx_params->rssi;
3459 	else
3460 		rx_pkt->pkt_meta.rssi_raw = rx_pkt->pkt_meta.rssi;
3461 
3462 
3463 	/*
3464 	 * FIXME: Assigning the local timestamp as hw timestamp is not
3465 	 * available. Need to see if pe/lim really uses this data.
3466 	 */
3467 	rx_pkt->pkt_meta.timestamp = (uint32_t) jiffies;
3468 	rx_pkt->pkt_meta.mpdu_hdr_len = sizeof(struct ieee80211_frame);
3469 	rx_pkt->pkt_meta.mpdu_len = mgmt_rx_params->buf_len;
3470 
3471 	/*
3472 	 * The buf_len should be at least 802.11 header len
3473 	 */
3474 	if (mgmt_rx_params->buf_len < rx_pkt->pkt_meta.mpdu_hdr_len) {
3475 		wma_err("MPDU Len %d lesser than header len %d",
3476 			 mgmt_rx_params->buf_len,
3477 			 rx_pkt->pkt_meta.mpdu_hdr_len);
3478 		qdf_nbuf_free(buf);
3479 		qdf_mem_free(rx_pkt);
3480 		return -EINVAL;
3481 	}
3482 
3483 	rx_pkt->pkt_meta.mpdu_data_len = mgmt_rx_params->buf_len -
3484 					 rx_pkt->pkt_meta.mpdu_hdr_len;
3485 
3486 	rx_pkt->pkt_meta.roamCandidateInd = 0;
3487 
3488 	wh = (struct ieee80211_frame *)qdf_nbuf_data(buf);
3489 
3490 	/*
3491 	 * If the mpdu_data_len is greater than Max (2k), drop the frame
3492 	 */
3493 	if (rx_pkt->pkt_meta.mpdu_data_len > MAX_MGMT_MPDU_LEN) {
3494 		wma_err("Data Len %d greater than max, dropping frame from "QDF_MAC_ADDR_FMT,
3495 			 rx_pkt->pkt_meta.mpdu_data_len,
3496 			 QDF_MAC_ADDR_REF(wh->i_addr3));
3497 		qdf_nbuf_free(buf);
3498 		qdf_mem_free(rx_pkt);
3499 		return -EINVAL;
3500 	}
3501 
3502 	rx_pkt->pkt_meta.mpdu_hdr_ptr = qdf_nbuf_data(buf);
3503 	rx_pkt->pkt_meta.mpdu_data_ptr = rx_pkt->pkt_meta.mpdu_hdr_ptr +
3504 					 rx_pkt->pkt_meta.mpdu_hdr_len;
3505 	rx_pkt->pkt_meta.tsf_delta = mgmt_rx_params->tsf_delta;
3506 	rx_pkt->pkt_buf = buf;
3507 
3508 	/* If it is a beacon/probe response, save it for future use */
3509 	mgt_type = (wh)->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
3510 	mgt_subtype = (wh)->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
3511 
3512 	if (mgt_type == IEEE80211_FC0_TYPE_MGT &&
3513 	    (mgt_subtype == MGMT_SUBTYPE_DISASSOC ||
3514 	     mgt_subtype == MGMT_SUBTYPE_DEAUTH ||
3515 	     mgt_subtype == MGMT_SUBTYPE_ACTION)) {
3516 		if (wma_find_vdev_id_by_bssid(wma_handle, wh->i_addr3,
3517 					      &vdev_id) == QDF_STATUS_SUCCESS) {
3518 			status = wma_check_and_process_rmf_frame(wma_handle,
3519 								 vdev_id,
3520 								 &wh,
3521 								 rx_pkt,
3522 								 buf);
3523 			if (status)
3524 				return status;
3525 		} else if (wma_find_vdev_id_by_addr(wma_handle, wh->i_addr1,
3526 					      &vdev_id) == QDF_STATUS_SUCCESS) {
3527 			status = wma_check_and_process_rmf_frame(wma_handle,
3528 								 vdev_id,
3529 								 &wh,
3530 								 rx_pkt,
3531 								 buf);
3532 			if (status)
3533 				return status;
3534 		}
3535 	}
3536 
3537 	rx_pkt->pkt_meta.session_id =
3538 		(vdev_id == WMA_INVALID_VDEV_ID ? 0 : vdev_id);
3539 
3540 	if (mgt_type == IEEE80211_FC0_TYPE_MGT &&
3541 	    (mgt_subtype == MGMT_SUBTYPE_BEACON ||
3542 	     mgt_subtype == MGMT_SUBTYPE_PROBE_RESP)) {
3543 		if (mgmt_rx_params->buf_len <=
3544 			(sizeof(struct ieee80211_frame) +
3545 			offsetof(struct wlan_bcn_frame, ie))) {
3546 			wma_debug("Dropping frame from "QDF_MAC_ADDR_FMT,
3547 				 QDF_MAC_ADDR_REF(wh->i_addr3));
3548 			cds_pkt_return_packet(rx_pkt);
3549 			return -EINVAL;
3550 		}
3551 	}
3552 
3553 	if (wma_is_pkt_drop_candidate(wma_handle, wh->i_addr2, wh->i_addr3,
3554 					mgt_subtype)) {
3555 		cds_pkt_return_packet(rx_pkt);
3556 		return -EINVAL;
3557 	}
3558 
3559 #if !defined(REMOVE_PKT_LOG)
3560 	packetdump_cb = wma_handle->wma_mgmt_rx_packetdump_cb;
3561 	if ((mgt_type == IEEE80211_FC0_TYPE_MGT &&
3562 		mgt_subtype != MGMT_SUBTYPE_BEACON) &&
3563 		packetdump_cb)
3564 		packetdump_cb(soc, mgmt_rx_params->pdev_id,
3565 			      rx_pkt->pkt_meta.session_id, rx_pkt->pkt_buf,
3566 			      QDF_STATUS_SUCCESS, RX_MGMT_PKT);
3567 #endif
3568 	return 0;
3569 }
3570 
3571 /**
3572  * wma_mem_endianness_based_copy() - does memory copy from src to dst
3573  * @dst: destination address
3574  * @src: source address
3575  * @size: size to be copied
3576  *
3577  * This function copies the memory of size passed from source
3578  * address to destination address.
3579  *
3580  * Return: Nothing
3581  */
3582 #ifdef BIG_ENDIAN_HOST
3583 static void wma_mem_endianness_based_copy(
3584 			uint8_t *dst, uint8_t *src, uint32_t size)
3585 {
3586 	/*
3587 	 * For big endian host, copy engine byte_swap is enabled
3588 	 * But the rx mgmt frame buffer content is in network byte order
3589 	 * Need to byte swap the mgmt frame buffer content - so when
3590 	 * copy engine does byte_swap - host gets buffer content in the
3591 	 * correct byte order.
3592 	 */
3593 
3594 	uint32_t i;
3595 	uint32_t *destp, *srcp;
3596 
3597 	destp = (uint32_t *) dst;
3598 	srcp = (uint32_t *) src;
3599 	for (i = 0; i < (roundup(size, sizeof(uint32_t)) / 4); i++) {
3600 		*destp = cpu_to_le32(*srcp);
3601 		destp++;
3602 		srcp++;
3603 	}
3604 }
3605 #else
3606 static void wma_mem_endianness_based_copy(
3607 			uint8_t *dst, uint8_t *src, uint32_t size)
3608 {
3609 	qdf_mem_copy(dst, src, size);
3610 }
3611 #endif
3612 
3613 #define RESERVE_BYTES                   100
3614 /**
3615  * wma_mgmt_rx_process() - process management rx frame.
3616  * @handle: wma handle
3617  * @data: rx data
3618  * @data_len: data length
3619  *
3620  * Return: 0 for success or error code
3621  */
3622 static int wma_mgmt_rx_process(void *handle, uint8_t *data,
3623 				  uint32_t data_len)
3624 {
3625 	tp_wma_handle wma_handle = (tp_wma_handle) handle;
3626 	struct mgmt_rx_event_params *mgmt_rx_params;
3627 	struct wlan_objmgr_psoc *psoc;
3628 	uint8_t *bufp;
3629 	qdf_nbuf_t wbuf;
3630 	QDF_STATUS status;
3631 
3632 	if (wma_validate_handle(wma_handle))
3633 		return -EINVAL;
3634 
3635 	mgmt_rx_params = qdf_mem_malloc(sizeof(*mgmt_rx_params));
3636 	if (!mgmt_rx_params) {
3637 		wma_err("memory allocation failed");
3638 		return -ENOMEM;
3639 	}
3640 
3641 	if (wmi_extract_mgmt_rx_params(wma_handle->wmi_handle,
3642 			data, mgmt_rx_params, &bufp) != QDF_STATUS_SUCCESS) {
3643 		wma_err("Extraction of mgmt rx params failed");
3644 		qdf_mem_free(mgmt_rx_params);
3645 		return -EINVAL;
3646 	}
3647 
3648 	if (mgmt_rx_params->buf_len > data_len ||
3649 	    !mgmt_rx_params->buf_len ||
3650 	    !bufp) {
3651 		wma_err("Invalid data_len %u, buf_len %u bufp %pK",
3652 			data_len, mgmt_rx_params->buf_len, bufp);
3653 		qdf_mem_free(mgmt_rx_params);
3654 		return -EINVAL;
3655 	}
3656 
3657 	if (!mgmt_rx_params->chan_freq) {
3658 		/*
3659 		 * It indicates that FW is legacy and is operating on
3660 		 * channel numbers and it also indicates that BAND_6G support
3661 		 * is not there as BAND_6G works only on frequencies and channel
3662 		 * numbers can be treated as unique.
3663 		 */
3664 		mgmt_rx_params->chan_freq = wlan_reg_legacy_chan_to_freq(
3665 					    wma_handle->pdev,
3666 					    mgmt_rx_params->channel);
3667 	}
3668 
3669 	mgmt_rx_params->pdev_id = 0;
3670 	mgmt_rx_params->rx_params = NULL;
3671 
3672 	/*
3673 	 * Allocate the memory for this rx packet, add extra 100 bytes for:-
3674 	 *
3675 	 * 1.  Filling the missing RSN capabilites by some APs, which fill the
3676 	 *     RSN IE length as extra 2 bytes but dont fill the IE data with
3677 	 *     capabilities, resulting in failure in unpack core due to length
3678 	 *     mismatch. Check sir_validate_and_rectify_ies for more info.
3679 	 *
3680 	 * 2.  In the API wma_process_rmf_frame(), the driver trims the CCMP
3681 	 *     header by overwriting the IEEE header to memory occupied by CCMP
3682 	 *     header, but an overflow is possible if the memory allocated to
3683 	 *     frame is less than the sizeof(struct ieee80211_frame) +CCMP
3684 	 *     HEADER len, so allocating 100 bytes would solve this issue too.
3685 	 *
3686 	 * 3.  CCMP header is pointing to orig_hdr +
3687 	 *     sizeof(struct ieee80211_frame) which could also result in OOB
3688 	 *     access, if the data len is less than
3689 	 *     sizeof(struct ieee80211_frame), allocating extra bytes would
3690 	 *     result in solving this issue too.
3691 	 */
3692 	wbuf = qdf_nbuf_alloc(NULL, roundup(mgmt_rx_params->buf_len +
3693 							RESERVE_BYTES,
3694 							4), 0, 4, false);
3695 	if (!wbuf) {
3696 		qdf_mem_free(mgmt_rx_params);
3697 		return -ENOMEM;
3698 	}
3699 
3700 	qdf_nbuf_put_tail(wbuf, mgmt_rx_params->buf_len);
3701 	qdf_nbuf_set_protocol(wbuf, ETH_P_CONTROL);
3702 
3703 	qdf_mem_zero(((uint8_t *)qdf_nbuf_data(wbuf) + mgmt_rx_params->buf_len),
3704 		     (roundup(mgmt_rx_params->buf_len + RESERVE_BYTES, 4) -
3705 		     mgmt_rx_params->buf_len));
3706 
3707 	wma_mem_endianness_based_copy(qdf_nbuf_data(wbuf),
3708 			bufp, mgmt_rx_params->buf_len);
3709 
3710 	psoc = (struct wlan_objmgr_psoc *)
3711 				wma_handle->psoc;
3712 	if (!psoc) {
3713 		wma_err("psoc ctx is NULL");
3714 		qdf_nbuf_free(wbuf);
3715 		qdf_mem_free(mgmt_rx_params);
3716 		return -EINVAL;
3717 	}
3718 
3719 	status = mgmt_txrx_rx_handler(psoc, wbuf, mgmt_rx_params);
3720 	if (status != QDF_STATUS_SUCCESS) {
3721 		qdf_mem_free(mgmt_rx_params);
3722 		return -EINVAL;
3723 	}
3724 
3725 	qdf_mem_free(mgmt_rx_params);
3726 	return 0;
3727 }
3728 
3729 /**
3730  * wma_de_register_mgmt_frm_client() - deregister management frame
3731  *
3732  * This function deregisters the event handler registered for
3733  * WMI_MGMT_RX_EVENTID.
3734  *
3735  * Return: QDF status
3736  */
3737 QDF_STATUS wma_de_register_mgmt_frm_client(void)
3738 {
3739 	tp_wma_handle wma_handle = (tp_wma_handle)
3740 				cds_get_context(QDF_MODULE_ID_WMA);
3741 
3742 	if (!wma_handle)
3743 		return QDF_STATUS_E_NULL_VALUE;
3744 
3745 #ifdef QCA_WIFI_FTM
3746 	if (cds_get_conparam() == QDF_GLOBAL_FTM_MODE)
3747 		return QDF_STATUS_SUCCESS;
3748 #endif
3749 
3750 	if (wmi_unified_unregister_event_handler(wma_handle->wmi_handle,
3751 						 wmi_mgmt_rx_event_id) != 0) {
3752 		wma_err("Failed to Unregister rx mgmt handler with wmi");
3753 		return QDF_STATUS_E_FAILURE;
3754 	}
3755 	return QDF_STATUS_SUCCESS;
3756 }
3757 
3758 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
3759 /**
3760  * wma_register_roaming_callbacks() - Register roaming callbacks
3761  * @csr_roam_synch_cb: CSR roam synch callback routine pointer
3762  * @csr_roam_auth_event_handle_cb: CSR callback routine pointer
3763  * @pe_roam_synch_cb: PE roam synch callback routine pointer
3764  *
3765  * Register the SME and PE callback routines with WMA for
3766  * handling roaming
3767  *
3768  * Return: Success or Failure Status
3769  */
3770 QDF_STATUS wma_register_roaming_callbacks(
3771 #ifndef FEATURE_CM_ENABLE
3772 	csr_roam_synch_fn_t csr_roam_synch_cb,
3773 #endif
3774 	QDF_STATUS (*csr_roam_auth_event_handle_cb)(struct mac_context *mac,
3775 						    uint8_t vdev_id,
3776 						    struct qdf_mac_addr bssid),
3777 	pe_roam_synch_fn_t pe_roam_synch_cb,
3778 	QDF_STATUS (*pe_disconnect_cb) (struct mac_context *mac,
3779 					uint8_t vdev_id,
3780 					uint8_t *deauth_disassoc_frame,
3781 					uint16_t deauth_disassoc_frame_len,
3782 					uint16_t reason_code))
3783 {
3784 
3785 	tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
3786 
3787 	if (!wma)
3788 		return QDF_STATUS_E_FAILURE;
3789 
3790 #ifndef FEATURE_CM_ENABLE
3791 	wma->csr_roam_synch_cb = csr_roam_synch_cb;
3792 #endif
3793 	wma->csr_roam_auth_event_handle_cb = csr_roam_auth_event_handle_cb;
3794 	wma->pe_roam_synch_cb = pe_roam_synch_cb;
3795 	wma->pe_disconnect_cb = pe_disconnect_cb;
3796 	wma_debug("Registered roam synch callbacks with WMA successfully");
3797 
3798 	return QDF_STATUS_SUCCESS;
3799 }
3800 #endif
3801 
3802 /**
3803  * wma_register_mgmt_frm_client() - register management frame callback
3804  *
3805  * This function registers event handler for WMI_MGMT_RX_EVENTID.
3806  *
3807  * Return: QDF status
3808  */
3809 QDF_STATUS wma_register_mgmt_frm_client(void)
3810 {
3811 	tp_wma_handle wma_handle = (tp_wma_handle)
3812 				cds_get_context(QDF_MODULE_ID_WMA);
3813 
3814 	if (!wma_handle)
3815 		return QDF_STATUS_E_NULL_VALUE;
3816 
3817 	if (wmi_unified_register_event_handler(wma_handle->wmi_handle,
3818 					       wmi_mgmt_rx_event_id,
3819 					       wma_mgmt_rx_process,
3820 					       WMA_RX_WORK_CTX) != 0) {
3821 		wma_err("Failed to register rx mgmt handler with wmi");
3822 		return QDF_STATUS_E_FAILURE;
3823 	}
3824 
3825 	return QDF_STATUS_SUCCESS;
3826 }
3827 
3828 /**
3829  * wma_register_packetdump_callback() - stores tx and rx mgmt packet dump
3830  *   callback handler
3831  * @tx_cb: tx mgmt packetdump cb
3832  * @rx_cb: rx mgmt packetdump cb
3833  *
3834  * This function is used to store tx and rx mgmt. packet dump callback
3835  *
3836  * Return: None
3837  *
3838  */
3839 void wma_register_packetdump_callback(
3840 	ol_txrx_pktdump_cb tx_cb,
3841 	ol_txrx_pktdump_cb rx_cb)
3842 {
3843 	tp_wma_handle wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
3844 
3845 	if (!wma_handle)
3846 		return;
3847 
3848 	wma_handle->wma_mgmt_tx_packetdump_cb = tx_cb;
3849 	wma_handle->wma_mgmt_rx_packetdump_cb = rx_cb;
3850 }
3851 
3852 /**
3853  * wma_deregister_packetdump_callback() - removes tx and rx mgmt packet dump
3854  *   callback handler
3855  *
3856  * This function is used to remove tx and rx mgmt. packet dump callback
3857  *
3858  * Return: None
3859  *
3860  */
3861 void wma_deregister_packetdump_callback(void)
3862 {
3863 	tp_wma_handle wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
3864 
3865 	if (!wma_handle)
3866 		return;
3867 
3868 	wma_handle->wma_mgmt_tx_packetdump_cb = NULL;
3869 	wma_handle->wma_mgmt_rx_packetdump_cb = NULL;
3870 }
3871 
3872 QDF_STATUS wma_mgmt_unified_cmd_send(struct wlan_objmgr_vdev *vdev,
3873 				qdf_nbuf_t buf, uint32_t desc_id,
3874 				void *mgmt_tx_params)
3875 {
3876 	tp_wma_handle wma_handle;
3877 	int ret;
3878 	QDF_STATUS status = QDF_STATUS_E_INVAL;
3879 	struct wmi_mgmt_params *mgmt_params =
3880 			(struct wmi_mgmt_params *)mgmt_tx_params;
3881 	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
3882 
3883 	if (!mgmt_params) {
3884 		wma_err("mgmt_params ptr passed is NULL");
3885 		return QDF_STATUS_E_INVAL;
3886 	}
3887 	mgmt_params->desc_id = desc_id;
3888 
3889 	if (!vdev) {
3890 		wma_err("vdev ptr passed is NULL");
3891 		return QDF_STATUS_E_INVAL;
3892 	}
3893 
3894 	wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
3895 	if (!wma_handle)
3896 		return QDF_STATUS_E_INVAL;
3897 
3898 	if (wmi_service_enabled(wma_handle->wmi_handle,
3899 				   wmi_service_mgmt_tx_wmi)) {
3900 		status = wmi_mgmt_unified_cmd_send(wma_handle->wmi_handle,
3901 						   mgmt_params);
3902 	} else {
3903 		QDF_NBUF_CB_MGMT_TXRX_DESC_ID(buf)
3904 						= mgmt_params->desc_id;
3905 
3906 		ret = cdp_mgmt_send_ext(soc, mgmt_params->vdev_id, buf,
3907 					mgmt_params->tx_type,
3908 					mgmt_params->use_6mbps,
3909 					mgmt_params->chanfreq);
3910 		status = qdf_status_from_os_return(ret);
3911 	}
3912 
3913 	if (status != QDF_STATUS_SUCCESS) {
3914 		wma_err("mgmt tx failed");
3915 		return status;
3916 	}
3917 
3918 	return QDF_STATUS_SUCCESS;
3919 }
3920 
3921 #ifndef CONFIG_HL_SUPPORT
3922 void wma_mgmt_nbuf_unmap_cb(struct wlan_objmgr_pdev *pdev,
3923 			    qdf_nbuf_t buf)
3924 {
3925 	struct wlan_objmgr_psoc *psoc;
3926 	qdf_device_t dev;
3927 
3928 	if (!buf)
3929 		return;
3930 
3931 	psoc = wlan_pdev_get_psoc(pdev);
3932 	if (!psoc) {
3933 		wma_err("Psoc handle NULL");
3934 		return;
3935 	}
3936 
3937 	dev = wlan_psoc_get_qdf_dev(psoc);
3938 	qdf_nbuf_unmap_single(dev, buf, QDF_DMA_TO_DEVICE);
3939 }
3940 
3941 QDF_STATUS wma_mgmt_frame_fill_peer_cb(struct wlan_objmgr_peer *peer,
3942 				       qdf_nbuf_t buf)
3943 {
3944 	struct wlan_objmgr_psoc *psoc;
3945 	struct wlan_objmgr_pdev *pdev;
3946 
3947 	psoc = wlan_peer_get_psoc(peer);
3948 	if (!psoc) {
3949 		wma_err("Psoc handle NULL");
3950 		return QDF_STATUS_E_INVAL;
3951 	}
3952 
3953 	pdev = wlan_objmgr_get_pdev_by_id((struct wlan_objmgr_psoc *)psoc,
3954 					  wlan_peer_get_pdev_id(peer),
3955 					  WLAN_LEGACY_WMA_ID);
3956 	if (!pdev) {
3957 		wma_err("Pdev handle NULL");
3958 		return QDF_STATUS_E_INVAL;
3959 	}
3960 	wma_mgmt_nbuf_unmap_cb(pdev, buf);
3961 	wlan_objmgr_pdev_release_ref(pdev, WLAN_LEGACY_WMA_ID);
3962 
3963 	return QDF_STATUS_SUCCESS;
3964 }
3965 #endif
3966