xref: /wlan-dirver/qcacld-3.0/core/mac/src/pe/lim/lim_assoc_utils.c (revision e22f9adc774eb030715d9a453ec9ea346916ed3b)
1 /*
2  * Copyright (c) 2011-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /*
21  * This file lim_assoc_utils.cc contains the utility functions
22  * LIM uses while processing (Re) Association messages.
23  * Author:        Chandra Modumudi
24  * Date:          02/13/02
25  * History:-
26  * Date           Modified by    Modification Information
27  * --------------------------------------------------------------------
28  * 05/26/10       js             WPA handling in (Re)Assoc frames
29  *
30  */
31 
32 #include "cds_api.h"
33 #include "ani_global.h"
34 #include "wni_api.h"
35 #include "sir_common.h"
36 
37 #include "wni_cfg.h"
38 #include "cfg_ucfg_api.h"
39 
40 #include "sch_api.h"
41 #include "utils_api.h"
42 #include "lim_utils.h"
43 #include "lim_assoc_utils.h"
44 #include "lim_security_utils.h"
45 #include "lim_ser_des_utils.h"
46 #include "lim_admit_control.h"
47 #include "lim_send_messages.h"
48 #include "lim_ft_defs.h"
49 #include "lim_session.h"
50 #include "lim_process_fils.h"
51 
52 #include "qdf_types.h"
53 #include "wma_types.h"
54 #include "lim_types.h"
55 #include "wlan_utility.h"
56 #include "wlan_mlme_api.h"
57 #include "wma.h"
58 #include "../../core/src/vdev_mgr_ops.h"
59 
60 #include <cdp_txrx_cfg.h>
61 #include <cdp_txrx_cmn.h>
62 #include <lim_mlo.h>
63 
64 /**
65  * lim_cmp_ssid() - utility function to compare SSIDs
66  * @rx_ssid: Received SSID
67  * @session_entry: Session entry
68  *
69  * This function is called in various places within LIM code
70  * to determine whether received SSID is same as SSID in use.
71  *
72  * Return: zero if SSID matched, non-zero otherwise.
73  */
74 uint32_t lim_cmp_ssid(tSirMacSSid *rx_ssid, struct pe_session *session_entry)
75 {
76 	if (session_entry->ssId.length != rx_ssid->length)
77 		return 1;
78 
79 	return qdf_mem_cmp(rx_ssid->ssId, &session_entry->ssId.ssId,
80 				session_entry->ssId.length);
81 }
82 
83 /**
84  * lim_compare_capabilities()
85  *
86  ***FUNCTION:
87  * This function is called during Association/Reassociation
88  * frame handling to determine whether received capabilities
89  * match with local capabilities or not.
90  *
91  ***LOGIC:
92  *
93  ***ASSUMPTIONS:
94  * NA
95  *
96  ***NOTE:
97  * NA
98  *
99  * @param  mac         - Pointer to Global MAC structure
100  * @param  pAssocReq    - Pointer to received Assoc Req frame
101  * @param  pLocalCapabs - Pointer to local capabilities
102  *
103  * @return status - true for Capabilitity match else false.
104  */
105 
106 uint8_t
107 lim_compare_capabilities(struct mac_context *mac,
108 			 tSirAssocReq *pAssocReq,
109 			 tSirMacCapabilityInfo *pLocalCapabs,
110 			 struct pe_session *pe_session)
111 {
112 	if (LIM_IS_AP_ROLE(pe_session) &&
113 	    (pAssocReq->capabilityInfo.ibss)) {
114 		/* Requesting STA asserting IBSS capability. */
115 		pe_debug("Requesting STA asserting IBSS capability");
116 		return false;
117 	}
118 	/* Compare CF capabilities */
119 	if (pAssocReq->capabilityInfo.cfPollable ||
120 	    pAssocReq->capabilityInfo.cfPollReq) {
121 		/* AP does not support PCF functionality */
122 		pe_debug(" AP does not support PCF functionality");
123 		return false;
124 	}
125 	/* Compare short preamble capability */
126 	if (pAssocReq->capabilityInfo.shortPreamble &&
127 	    (pAssocReq->capabilityInfo.shortPreamble !=
128 	     pLocalCapabs->shortPreamble)) {
129 		/* Allowing a STA requesting short preamble while */
130 		/* AP does not support it */
131 	}
132 
133 	pe_debug("QoS in AssocReq: %d, local capabs qos: %d",
134 		pAssocReq->capabilityInfo.qos, pLocalCapabs->qos);
135 
136 	/* Compare QoS capability */
137 	if (pAssocReq->capabilityInfo.qos &&
138 	    (pAssocReq->capabilityInfo.qos != pLocalCapabs->qos))
139 		pe_debug("Received unmatched QOS but cfg to suppress - continuing");
140 
141 	/*
142 	 * If AP supports shortSlot and if apple user has
143 	 * enforced association only from shortSlot station,
144 	 * then AP must reject any station that does not support
145 	 * shortSlot
146 	 */
147 	if (LIM_IS_AP_ROLE(pe_session) &&
148 	    (pLocalCapabs->shortSlotTime == 1)) {
149 		if (mac->mlme_cfg->feature_flags.accept_short_slot_assoc) {
150 			if (pAssocReq->capabilityInfo.shortSlotTime !=
151 			    pLocalCapabs->shortSlotTime) {
152 				pe_err("AP rejects association as station doesn't support shortslot time");
153 				return false;
154 			}
155 			return false;
156 		}
157 	}
158 
159 	return true;
160 } /****** end lim_compare_capabilities() ******/
161 
162 /**
163  * lim_check_rx_basic_rates()
164  *
165  ***FUNCTION:
166  * This function is called during Association/Reassociation
167  * frame handling to determine whether received rates in
168  * Assoc/Reassoc request frames include all BSS basic rates
169  * or not.
170  *
171  ***LOGIC:
172  *
173  ***ASSUMPTIONS:
174  * NA
175  *
176  ***NOTE:
177  * NA
178  *
179  * @param  rxRateSet - pointer to SSID structure
180  *
181  * @return status - true if ALL BSS basic rates are present in the
182  *                  received rateset else false.
183  */
184 
185 uint8_t
186 lim_check_rx_basic_rates(struct mac_context *mac, tSirMacRateSet rxRateSet,
187 			 struct pe_session *pe_session)
188 {
189 	tSirMacRateSet *pRateSet, basicRate;
190 	uint8_t i, j, k, match;
191 
192 	pRateSet = qdf_mem_malloc(sizeof(tSirMacRateSet));
193 	if (!pRateSet)
194 		return false;
195 
196 	/* Copy operational rate set from session Entry */
197 	qdf_mem_copy(pRateSet->rate, (pe_session->rateSet.rate),
198 		     pe_session->rateSet.numRates);
199 
200 	pRateSet->numRates = pe_session->rateSet.numRates;
201 
202 	/* Extract BSS basic rateset from operational rateset */
203 	for (i = 0, j = 0;
204 	     ((i < pRateSet->numRates) && (i < SIR_MAC_MAX_NUMBER_OF_RATES));
205 	     i++) {
206 		if ((pRateSet->rate[i] & 0x80) == 0x80) {
207 			/* msb is set, so this is a basic rate */
208 			basicRate.rate[j++] = pRateSet->rate[i];
209 		}
210 	}
211 
212 	/*
213 	 * For each BSS basic rate, find if it is present in the
214 	 * received rateset.
215 	 */
216 	for (k = 0; k < j; k++) {
217 		match = 0;
218 		for (i = 0;
219 		     ((i < rxRateSet.numRates) &&
220 		      (i < SIR_MAC_MAX_NUMBER_OF_RATES)); i++) {
221 			if ((rxRateSet.rate[i] | 0x80) == basicRate.rate[k])
222 				match = 1;
223 		}
224 
225 		if (!match) {
226 			/* Free up memory allocated for rateset */
227 			qdf_mem_free((uint8_t *) pRateSet);
228 
229 			return false;
230 		}
231 	}
232 
233 	/* Free up memory allocated for rateset */
234 	qdf_mem_free((uint8_t *) pRateSet);
235 
236 	return true;
237 } /****** end lim_check_rx_basic_rates() ******/
238 
239 /**
240  * lim_check_mcs_set()
241  *
242  ***FUNCTION:
243  * This function is called during Association/Reassociation
244  * frame handling to determine whether received MCS rates in
245  * Assoc/Reassoc request frames includes all Basic MCS Rate Set or not.
246  *
247  ***LOGIC:
248  *
249  ***ASSUMPTIONS:
250  * NA
251  *
252  ***NOTE:
253  * NA
254  *
255  * @param  supportedMCSSet - pointer to Supported MCS Rate Set
256  *
257  * @return status - true if ALL MCS Basic Rate Set rates are present in the
258  *                  received rateset else false.
259  */
260 
261 uint8_t lim_check_mcs_set(struct mac_context *mac, uint8_t *supportedMCSSet)
262 {
263 	uint8_t basicMCSSet[SIZE_OF_BASIC_MCS_SET] = { 0 };
264 	qdf_size_t cfg_len = 0;
265 	uint8_t i;
266 	uint8_t validBytes;
267 	uint8_t lastByteMCSMask = 0x1f;
268 
269 	cfg_len = mac->mlme_cfg->rates.basic_mcs_set.len;
270 	if (wlan_mlme_get_cfg_str((uint8_t *)basicMCSSet,
271 				  &mac->mlme_cfg->rates.basic_mcs_set,
272 				  &cfg_len) != QDF_STATUS_SUCCESS) {
273 		/* / Could not get Basic MCS rateset from CFG. Log error. */
274 		pe_err("could not retrieve Basic MCS rateset");
275 		return false;
276 	}
277 
278 	validBytes = VALID_MCS_SIZE / 8;
279 
280 	/* check if all the Basic MCS Bits are set in supported MCS bitmap */
281 	for (i = 0; i < validBytes; i++) {
282 		if ((basicMCSSet[i] & supportedMCSSet[i]) != basicMCSSet[i]) {
283 			pe_warn("One of Basic MCS Set Rates is not supported by the Station");
284 			return false;
285 		}
286 	}
287 
288 	/* check the last 5 bits of the valid MCS bitmap */
289 	if (((basicMCSSet[i] & lastByteMCSMask) &
290 	     (supportedMCSSet[i] & lastByteMCSMask)) !=
291 	    (basicMCSSet[i] & lastByteMCSMask)) {
292 		pe_warn("One of Basic MCS Set Rates is not supported by the Station");
293 		return false;
294 	}
295 
296 	return true;
297 }
298 
299 #define SECURITY_SUITE_TYPE_MASK 0xFF
300 #define SECURITY_SUITE_TYPE_WEP40 0x1
301 #define SECURITY_SUITE_TYPE_TKIP 0x2
302 #define SECURITY_SUITE_TYPE_CCMP 0x4
303 #define SECURITY_SUITE_TYPE_WEP104 0x4
304 #define SECURITY_SUITE_TYPE_GCMP 0x8
305 #define SECURITY_SUITE_TYPE_GCMP_256 0x9
306 
307 /**
308  *lim_del_peer_info() - remove all peer information from host driver and fw
309  * @mac:    Pointer to Global MAC structure
310  * @pe_session: Pointer to PE Session entry
311  *
312  * @Return: QDF_STATUS
313  */
314 
315 QDF_STATUS lim_del_peer_info(struct mac_context *mac,
316 			     struct pe_session *pe_session)
317 {
318 	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
319 	uint16_t i;
320 	uint32_t  bitmap = 1 << CDP_PEER_DELETE_NO_SPECIAL;
321 	bool peer_unmap_conf_support_enabled;
322 
323 	peer_unmap_conf_support_enabled =
324 				cdp_cfg_get_peer_unmap_conf_support(soc);
325 
326 	for (i = 0; i < pe_session->dph.dphHashTable.size; i++) {
327 		tpDphHashNode sta_ds;
328 
329 		sta_ds = dph_get_hash_entry(mac, i,
330 					    &pe_session->dph.dphHashTable);
331 		if (!sta_ds)
332 			continue;
333 
334 		cdp_peer_teardown(soc, pe_session->vdev_id, sta_ds->staAddr);
335 		if (peer_unmap_conf_support_enabled)
336 			cdp_peer_delete_sync(soc, pe_session->vdev_id,
337 					     sta_ds->staAddr,
338 					     wma_peer_unmap_conf_cb,
339 					     bitmap);
340 		else
341 			cdp_peer_delete(soc, pe_session->vdev_id,
342 					sta_ds->staAddr, bitmap);
343 	}
344 	return QDF_STATUS_SUCCESS;
345 }
346 
347 /**
348  * lim_del_sta_all(): Cleanup all peers associated with VDEV
349  * @mac:    Pointer to Global MAC structure
350  * @pe_session: Pointer to PE Session entry
351  *
352  * @Return: QDF Status of operation
353  */
354 
355 QDF_STATUS lim_del_sta_all(struct mac_context *mac,
356 			   struct pe_session *pe_session)
357 {
358 	QDF_STATUS status = QDF_STATUS_SUCCESS;
359 	struct vdev_mlme_obj *mlme_obj;
360 	uint32_t i;
361 	tpDphHashNode sta_ds;
362 
363 	if (!LIM_IS_AP_ROLE(pe_session))
364 		return QDF_STATUS_E_INVAL;
365 
366 	mlme_obj = wlan_vdev_mlme_get_cmpt_obj(pe_session->vdev);
367 	if (!mlme_obj) {
368 		pe_err("vdev component object is NULL");
369 		return QDF_STATUS_E_FAILURE;
370 	}
371 
372 	if (wlan_vdev_mlme_is_mlo_ap(pe_session->vdev)) {
373 		for (i = 1; i < pe_session->dph.dphHashTable.size; i++) {
374 			sta_ds = dph_get_hash_entry(
375 					mac, i,
376 					&pe_session->dph.dphHashTable);
377 			if (!sta_ds)
378 				continue;
379 			if (lim_is_mlo_conn(pe_session, sta_ds))
380 				lim_mlo_delete_link_peer(pe_session, sta_ds);
381 		}
382 	}
383 	status = vdev_mgr_peer_delete_all_send(mlme_obj);
384 	if (status != QDF_STATUS_SUCCESS) {
385 		pe_err("failed status = %d", status);
386 		return status;
387 	}
388 
389 	status = lim_del_peer_info(mac, pe_session);
390 
391 	return status;
392 }
393 
394 QDF_STATUS
395 lim_cleanup_rx_path(struct mac_context *mac, tpDphHashNode sta,
396 		    struct pe_session *pe_session, bool delete_peer)
397 {
398 	QDF_STATUS retCode = QDF_STATUS_SUCCESS;
399 
400 	pe_debug("Cleanup Rx Path for AID: %d limSmeState: %d, mlmState: %d, delete_peer %d",
401 		 sta->assocId, pe_session->limSmeState,
402 		 sta->mlmStaContext.mlmState, delete_peer);
403 
404 	pe_session->isCiscoVendorAP = false;
405 
406 	if (mac->lim.gLimAddtsSent) {
407 		MTRACE(mac_trace
408 			       (mac, TRACE_CODE_TIMER_DEACTIVATE,
409 			       pe_session->peSessionId, eLIM_ADDTS_RSP_TIMER));
410 		tx_timer_deactivate(&mac->lim.lim_timers.gLimAddtsRspTimer);
411 		pe_debug("Reset gLimAddtsSent flag and send addts timeout to SME");
412 		lim_process_sme_addts_rsp_timeout(mac,
413 					mac->lim.gLimAddtsRspTimerCount);
414 	}
415 
416 	if (sta->mlmStaContext.mlmState == eLIM_MLM_WT_ASSOC_CNF_STATE) {
417 		lim_deactivate_and_change_per_sta_id_timer(mac, eLIM_CNF_WAIT_TIMER,
418 							   sta->assocId);
419 
420 		if (!sta->mlmStaContext.updateContext) {
421 			/**
422 			 * There is no context at Polaris to delete.
423 			 * Release our assigned AID back to the free pool
424 			 */
425 			if (LIM_IS_AP_ROLE(pe_session)) {
426 				lim_del_sta(mac, sta, true, pe_session);
427 				return retCode;
428 			}
429 			lim_delete_dph_hash_entry(mac, sta->staAddr,
430 						  sta->assocId, pe_session);
431 
432 			return retCode;
433 		}
434 	}
435 	/* delete all tspecs associated with this sta. */
436 	lim_admit_control_delete_sta(mac, sta->assocId);
437 
438 	/**
439 	 * Make STA hash entry invalid at eCPU so that DPH
440 	 * does not process any more data packets and
441 	 * releases those BDs
442 	 */
443 	sta->valid = 0;
444 	lim_send_sme_tsm_ie_ind(mac, pe_session, 0, 0, 0);
445 	/* Any roaming related changes should be above this line */
446 	if (!delete_peer)
447 		return QDF_STATUS_SUCCESS;
448 
449 	sta->mlmStaContext.mlmState = eLIM_MLM_WT_DEL_STA_RSP_STATE;
450 
451 	if (LIM_IS_STA_ROLE(pe_session)) {
452 		MTRACE(mac_trace
453 		       (mac, TRACE_CODE_MLM_STATE, pe_session->peSessionId,
454 		       eLIM_MLM_WT_DEL_STA_RSP_STATE));
455 		pe_session->limMlmState = eLIM_MLM_WT_DEL_STA_RSP_STATE;
456 		/* Deactivating probe after heart beat timer */
457 		lim_deactivate_and_change_timer(mac, eLIM_JOIN_FAIL_TIMER);
458 	}
459 
460 	/* Do DEL BSS or DEL STA only if ADD BSS was success */
461 	if (!pe_session->add_bss_failed) {
462 		if (pe_session->limSmeState == eLIM_SME_JOIN_FAILURE_STATE) {
463 			retCode =
464 				lim_del_bss(mac, sta, pe_session->vdev_id,
465 					    pe_session);
466 		} else
467 			retCode = lim_del_sta(mac,
468 					 sta, true, pe_session);
469 	}
470 
471 	return retCode;
472 
473 } /*** end lim_cleanup_rx_path() ***/
474 
475 /**
476  * lim_send_del_sta_cnf() - Send Del sta confirmation
477  * @mac: Pointer to Global MAC structure
478  * @sta_dsaddr: sta ds address
479  * @staDsAssocId: sta ds association id
480  * @mlmStaContext: MLM station context
481  * @status_code: Status code
482  * @pe_session: Session entry
483  *
484  * This function is called to send appropriate CNF message to SME.
485  *
486  * Return: None
487  */
488 void
489 lim_send_del_sta_cnf(struct mac_context *mac, struct qdf_mac_addr sta_dsaddr,
490 		     uint16_t staDsAssocId,
491 		     struct lim_sta_context mlmStaContext,
492 		     tSirResultCodes status_code, struct pe_session *pe_session)
493 {
494 	tLimMlmDisassocCnf mlmDisassocCnf;
495 	tLimMlmDeauthCnf mlmDeauthCnf;
496 	tLimMlmPurgeStaInd mlmPurgeStaInd;
497 
498 	pe_debug("Sessionid: %d staDsAssocId: %d Trigger: %d status_code: %d sta_dsaddr: "QDF_MAC_ADDR_FMT,
499 		pe_session->peSessionId, staDsAssocId,
500 		mlmStaContext.cleanupTrigger, status_code,
501 		QDF_MAC_ADDR_REF(sta_dsaddr.bytes));
502 
503 	if (LIM_IS_STA_ROLE(pe_session)) {
504 		/* Set BSSID at CFG to null */
505 		tSirMacAddr nullAddr = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
506 
507 		sir_copy_mac_addr(nullAddr, pe_session->bssId);
508 
509 		/* Free up buffer allocated for JoinReq held by */
510 		/* MLM state machine */
511 		if (pe_session->pLimMlmJoinReq) {
512 			qdf_mem_free(pe_session->pLimMlmJoinReq);
513 			pe_session->pLimMlmJoinReq = NULL;
514 		}
515 
516 		pe_session->limAID = 0;
517 	}
518 
519 	if ((mlmStaContext.cleanupTrigger ==
520 					eLIM_HOST_DISASSOC) ||
521 		(mlmStaContext.cleanupTrigger ==
522 					eLIM_LINK_MONITORING_DISASSOC) ||
523 		(mlmStaContext.cleanupTrigger ==
524 					eLIM_PROMISCUOUS_MODE_DISASSOC)) {
525 		qdf_mem_copy((uint8_t *) &mlmDisassocCnf.peerMacAddr,
526 			     (uint8_t *) sta_dsaddr.bytes, QDF_MAC_ADDR_SIZE);
527 		mlmDisassocCnf.resultCode = status_code;
528 		mlmDisassocCnf.disassocTrigger = mlmStaContext.cleanupTrigger;
529 		/* Update PE session Id */
530 		mlmDisassocCnf.sessionId = pe_session->peSessionId;
531 
532 		lim_post_sme_message(mac,
533 				     LIM_MLM_DISASSOC_CNF,
534 				     (uint32_t *) &mlmDisassocCnf);
535 	} else if ((mlmStaContext.cleanupTrigger ==
536 					eLIM_HOST_DEAUTH) ||
537 			(mlmStaContext.cleanupTrigger ==
538 					eLIM_LINK_MONITORING_DEAUTH)) {
539 		qdf_copy_macaddr(&mlmDeauthCnf.peer_macaddr, &sta_dsaddr);
540 		mlmDeauthCnf.resultCode = status_code;
541 		mlmDeauthCnf.deauthTrigger = mlmStaContext.cleanupTrigger;
542 		/* PE session Id */
543 		mlmDeauthCnf.sessionId = pe_session->peSessionId;
544 
545 		lim_post_sme_message(mac,
546 				     LIM_MLM_DEAUTH_CNF,
547 				     (uint32_t *) &mlmDeauthCnf);
548 	} else if ((mlmStaContext.cleanupTrigger ==
549 		    eLIM_PEER_ENTITY_DISASSOC) ||
550 		   (mlmStaContext.cleanupTrigger == eLIM_PEER_ENTITY_DEAUTH)) {
551 		qdf_mem_copy((uint8_t *) &mlmPurgeStaInd.peerMacAddr,
552 			     (uint8_t *) sta_dsaddr.bytes, QDF_MAC_ADDR_SIZE);
553 		mlmPurgeStaInd.reasonCode =
554 			(uint8_t) mlmStaContext.disassocReason;
555 		mlmPurgeStaInd.aid = staDsAssocId;
556 		mlmPurgeStaInd.purgeTrigger = mlmStaContext.cleanupTrigger;
557 		mlmPurgeStaInd.sessionId = pe_session->peSessionId;
558 
559 		lim_post_sme_message(mac,
560 				     LIM_MLM_PURGE_STA_IND,
561 				     (uint32_t *) &mlmPurgeStaInd);
562 	} else if (mlmStaContext.cleanupTrigger == eLIM_JOIN_FAILURE) {
563 		/* PE setup the peer entry in HW upfront, right after join is completed. */
564 		/* If there is a failure during rest of the assoc sequence, this context needs to be cleaned up. */
565 		uint8_t smesessionId;
566 
567 		smesessionId = pe_session->smeSessionId;
568 		pe_session->limSmeState = eLIM_SME_JOIN_FAILURE_STATE;
569 		MTRACE(mac_trace
570 			       (mac, TRACE_CODE_SME_STATE, pe_session->peSessionId,
571 			       pe_session->limSmeState));
572 
573 		/* if it is a reassoc failure to join new AP */
574 		if ((mlmStaContext.resultCode ==
575 		     eSIR_SME_FT_REASSOC_TIMEOUT_FAILURE)
576 		    || (mlmStaContext.resultCode == eSIR_SME_FT_REASSOC_FAILURE)
577 		    || (mlmStaContext.resultCode ==
578 			eSIR_SME_REASSOC_TIMEOUT_RESULT_CODE)) {
579 			pe_debug("Lim Posting eWNI_SME_REASSOC_RSP to SME"
580 				"resultCode: %d, status_code: %d,"
581 				"sessionId: %d",
582 				mlmStaContext.resultCode,
583 				mlmStaContext.protStatusCode,
584 				pe_session->peSessionId);
585 
586 			lim_send_sme_join_reassoc_rsp(mac, eWNI_SME_REASSOC_RSP,
587 						      mlmStaContext.resultCode,
588 						      mlmStaContext.protStatusCode,
589 						      pe_session, smesessionId);
590 			if (mlmStaContext.resultCode != eSIR_SME_SUCCESS) {
591 				pe_delete_session(mac, pe_session);
592 				pe_session = NULL;
593 			}
594 		} else {
595 			qdf_mem_free(pe_session->lim_join_req);
596 			pe_session->lim_join_req = NULL;
597 
598 			pe_debug("Lim Posting eWNI_SME_JOIN_RSP to SME."
599 				"resultCode: %d,status_code: %d,"
600 				"sessionId: %d",
601 				mlmStaContext.resultCode,
602 				mlmStaContext.protStatusCode,
603 				pe_session->peSessionId);
604 
605 			lim_send_sme_join_reassoc_rsp(mac, eWNI_SME_JOIN_RSP,
606 						      mlmStaContext.resultCode,
607 						      mlmStaContext.protStatusCode,
608 						      pe_session, smesessionId);
609 
610 			if (mlmStaContext.resultCode != eSIR_SME_SUCCESS) {
611 				pe_delete_session(mac, pe_session);
612 				pe_session = NULL;
613 			}
614 		}
615 
616 	} else if (mlmStaContext.cleanupTrigger == eLIM_DUPLICATE_ENTRY) {
617 
618 		qdf_mem_copy((uint8_t *) &mlmDisassocCnf.peerMacAddr,
619 			     (uint8_t *) sta_dsaddr.bytes, QDF_MAC_ADDR_SIZE);
620 		mlmDisassocCnf.resultCode = status_code;
621 		mlmDisassocCnf.disassocTrigger = eLIM_DUPLICATE_ENTRY;
622 		/* Update PE session Id */
623 		mlmDisassocCnf.sessionId = pe_session->peSessionId;
624 
625 		lim_post_sme_message(mac,
626 				     LIM_MLM_DISASSOC_CNF,
627 				     (uint32_t *) &mlmDisassocCnf);
628 	}
629 
630 	if (pe_session && !LIM_IS_AP_ROLE(pe_session)) {
631 		pe_delete_session(mac, pe_session);
632 		pe_session = NULL;
633 	}
634 }
635 
636 /**
637  * lim_reject_association() - function to reject Re/Association Request
638  *
639  * @mac_ctx: pointer to global mac structure
640  * @peer_addr: mac address of the peer
641  * @sub_type: Indicates whether it is Association Request (=0) or
642  *            Reassociation Request (=1) frame
643  * @add_pre_auth_context:Indicates whether pre-auth context
644  *                     to be added for this STA
645  * @auth_type: Indicates auth type to be added
646  * @sta_id: Indicates staId of the STA being rejected
647  *          association
648  * @delete_sta: Indicates whether to delete STA context
649  *              at Polaris
650  * @result_code: Indicates what reasonCode to be sent in
651  *          Re/Assoc response to STA
652  * @session_entry: pointer to PE session
653  *
654  * This function is called whenever Re/Association Request need
655  * to be rejected due to failure in assigning an AID or failure
656  * in adding STA context at Polaris or reject by applications.
657  * Resources allocated if any are freedup and (Re) Association
658  * Response frame is sent to requesting STA. Pre-Auth context
659  * will be added for this STA if it does not exist already
660  *
661  * Return: none
662  */
663 
664 void
665 lim_reject_association(struct mac_context *mac_ctx, tSirMacAddr peer_addr,
666 			uint8_t sub_type, uint8_t add_pre_auth_context,
667 			tAniAuthType auth_type, uint16_t sta_id,
668 			uint8_t delete_sta, enum wlan_status_code result_code,
669 			struct pe_session *session_entry)
670 {
671 	tpDphHashNode sta_ds;
672 
673 	pe_debug("Sessionid: %d auth_type: %d sub_type: %d add_pre_auth_context: %d sta_id: %d delete_sta: %d result_code : %d peer_addr: " QDF_MAC_ADDR_FMT,
674 		session_entry->peSessionId, auth_type, sub_type,
675 		add_pre_auth_context, sta_id, delete_sta, result_code,
676 		QDF_MAC_ADDR_REF(peer_addr));
677 
678 	if (add_pre_auth_context) {
679 		/* Create entry for this STA in pre-auth list */
680 		struct tLimPreAuthNode *auth_node;
681 
682 		auth_node = lim_acquire_free_pre_auth_node(mac_ctx,
683 			       &mac_ctx->lim.gLimPreAuthTimerTable);
684 
685 		if (auth_node) {
686 			qdf_mem_copy((uint8_t *) auth_node->peerMacAddr,
687 				     peer_addr, sizeof(tSirMacAddr));
688 			auth_node->fTimerStarted = 0;
689 			auth_node->mlmState = eLIM_MLM_AUTHENTICATED_STATE;
690 			auth_node->authType = (tAniAuthType) auth_type;
691 			auth_node->timestamp = qdf_mc_timer_get_system_ticks();
692 			lim_add_pre_auth_node(mac_ctx, auth_node);
693 		}
694 	}
695 
696 	sta_ds = dph_get_hash_entry(mac_ctx, sta_id,
697 				    &session_entry->dph.dphHashTable);
698 
699 	if (delete_sta == false) {
700 		lim_send_assoc_rsp_mgmt_frame(
701 				mac_ctx,
702 				STATUS_AP_UNABLE_TO_HANDLE_NEW_STA,
703 				1, peer_addr, sub_type, sta_ds, session_entry,
704 				false);
705 		pe_debug("Received Re/Assoc req when max associated STAs reached from " QDF_MAC_ADDR_FMT,
706 			 QDF_MAC_ADDR_REF(peer_addr));
707 		lim_send_sme_max_assoc_exceeded_ntf(mac_ctx, peer_addr,
708 					session_entry->smeSessionId);
709 		return;
710 	}
711 
712 	if (!sta_ds) {
713 		pe_err("No STA context, yet rejecting Association");
714 		return;
715 	}
716 
717 	/*
718 	 * Polaris has state for this STA.
719 	 * Trigger cleanup.
720 	 */
721 	sta_ds->mlmStaContext.cleanupTrigger = eLIM_REASSOC_REJECT;
722 
723 	/* Receive path cleanup */
724 	lim_cleanup_rx_path(mac_ctx, sta_ds, session_entry, true);
725 
726 	/*
727 	 * Send Re/Association Response with
728 	 * status code to requesting STA.
729 	 */
730 	lim_send_assoc_rsp_mgmt_frame(mac_ctx, result_code, 0, peer_addr,
731 				      sub_type, sta_ds, session_entry, false);
732 
733 	if (session_entry->parsedAssocReq[sta_ds->assocId]) {
734 		lim_free_assoc_req_frm_buf(
735 			session_entry->parsedAssocReq[sta_ds->assocId]);
736 
737 		qdf_mem_free(session_entry->parsedAssocReq[sta_ds->assocId]);
738 		session_entry->parsedAssocReq[sta_ds->assocId] = NULL;
739 	}
740 }
741 
742 void lim_free_assoc_req_frm_buf(tpSirAssocReq assoc_req)
743 {
744 	if (!assoc_req)
745 		return;
746 	if (assoc_req->assoc_req_buf) {
747 		qdf_nbuf_free(assoc_req->assoc_req_buf);
748 		assoc_req->assoc_req_buf = NULL;
749 		assoc_req->assocReqFrame = NULL;
750 		assoc_req->assocReqFrameLength = 0;
751 	}
752 }
753 
754 bool lim_alloc_assoc_req_frm_buf(tpSirAssocReq assoc_req,
755 				 qdf_nbuf_t buf, uint32_t mac_header_len,
756 				 uint32_t frame_len)
757 {
758 	if (!assoc_req)
759 		return false;
760 	assoc_req->assoc_req_buf = qdf_nbuf_clone(buf);
761 	if (!assoc_req->assoc_req_buf)
762 		return false;
763 	assoc_req->assocReqFrame = qdf_nbuf_data(assoc_req->assoc_req_buf) +
764 				   mac_header_len;
765 	assoc_req->assocReqFrameLength = frame_len;
766 
767 	return true;
768 }
769 
770 /**
771  * lim_decide_ap_protection_on_ht20_delete() - function to update protection
772  *                                              parameters.
773  * @mac_ctx: pointer to global mac structure
774  * @sta_ds: station node
775  * @beacon_params: ap beacon parameters
776  * @session_entry: pe session entry
777  *
778  * protection related function while HT20 station is getting deleted.
779  *
780  * Return: none
781  */
782 static void
783 lim_decide_ap_protection_on_ht20_delete(struct mac_context *mac_ctx,
784 					tpDphHashNode sta_ds,
785 					tpUpdateBeaconParams beacon_params,
786 					struct pe_session *session_entry)
787 {
788 	uint32_t i = 0;
789 
790 	pe_debug("(%d) A HT 20 STA is disassociated. Addr is "QDF_MAC_ADDR_FMT,
791 		session_entry->gLimHt20Params.numSta,
792 		QDF_MAC_ADDR_REF(sta_ds->staAddr));
793 
794 	if (session_entry->gLimHt20Params.numSta > 0) {
795 		for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) {
796 			if (!session_entry->protStaCache[i].active)
797 				continue;
798 
799 			if (!qdf_mem_cmp(session_entry->protStaCache[i].addr,
800 				sta_ds->staAddr, sizeof(tSirMacAddr))) {
801 				session_entry->gLimHt20Params.numSta--;
802 				session_entry->protStaCache[i].active =
803 						false;
804 				break;
805 			}
806 		}
807 	}
808 
809 	if (session_entry->gLimHt20Params.numSta == 0) {
810 		/* disable protection */
811 		pe_debug("No 11B STA exists, PESessionID %d",
812 				session_entry->peSessionId);
813 		lim_enable_ht20_protection(mac_ctx, false, false, beacon_params,
814 					session_entry);
815 	}
816 }
817 
818 /**
819  * lim_decide_ap_protection_on_delete() - update SAP protection on station
820  *                                       deletion.
821  * @mac_ctx: pointer to global mac structure
822  * @sta_ds: station node
823  * @beacon_params: ap beacon parameters
824  * @session_entry: pe session entry
825  *
826  * Decides about protection related settings when a station is getting deleted.
827  *
828  * Return: none
829  */
830 void
831 lim_decide_ap_protection_on_delete(struct mac_context *mac_ctx,
832 				   tpDphHashNode sta_ds,
833 				   tpUpdateBeaconParams beacon_params,
834 				   struct pe_session *session_entry)
835 {
836 	uint32_t phy_mode;
837 	tHalBitVal erp_enabled = eHAL_CLEAR;
838 	enum reg_wifi_band rf_band = REG_BAND_UNKNOWN;
839 	uint32_t i;
840 
841 	if (!sta_ds)
842 		return;
843 
844 	lim_get_rf_band_new(mac_ctx, &rf_band, session_entry);
845 	lim_get_phy_mode(mac_ctx, &phy_mode, session_entry);
846 	erp_enabled = sta_ds->erpEnabled;
847 
848 	if ((REG_BAND_5G == rf_band) &&
849 		(true == session_entry->htCapability) &&
850 		(session_entry->beaconParams.llaCoexist) &&
851 		(false == sta_ds->mlmStaContext.htCapability)) {
852 		/*
853 		 * we are HT. if we are 11A, then protection is not required or
854 		 * we are HT and 11A station is leaving.
855 		 * protection consideration required.
856 		 * HT station leaving ==> this case is commonly handled
857 		 * between both the bands below.
858 		 */
859 		pe_debug("(%d) A 11A STA is disassociated. Addr is "QDF_MAC_ADDR_FMT,
860 			session_entry->gLim11aParams.numSta,
861 			QDF_MAC_ADDR_REF(sta_ds->staAddr));
862 		for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) {
863 			if (session_entry->protStaCache[i].active &&
864 				(!qdf_mem_cmp(
865 					session_entry->protStaCache[i].addr,
866 					 sta_ds->staAddr,
867 					sizeof(tSirMacAddr)))) {
868 				session_entry->protStaCache[i].active = false;
869 				break;
870 			}
871 		}
872 
873 		if (session_entry->gLim11aParams.numSta == 0) {
874 			/* disable protection */
875 			lim_update_11a_protection(mac_ctx, false, false,
876 				beacon_params, session_entry);
877 		}
878 	}
879 
880 	/* we are HT or 11G and 11B station is getting deleted */
881 	if ((REG_BAND_2G == rf_band) &&
882 		(phy_mode == WNI_CFG_PHY_MODE_11G ||
883 		session_entry->htCapability) &&
884 		(erp_enabled == eHAL_CLEAR)) {
885 		pe_debug("(%d) A legacy STA is disassociated. Addr is "QDF_MAC_ADDR_FMT,
886 			session_entry->gLim11bParams.numSta,
887 			QDF_MAC_ADDR_REF(sta_ds->staAddr));
888 		for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) {
889 			if (session_entry->protStaCache[i].active &&
890 				(!qdf_mem_cmp(
891 					session_entry->protStaCache[i].addr,
892 					sta_ds->staAddr,
893 					sizeof(tSirMacAddr)))) {
894 					session_entry->gLim11bParams.numSta--;
895 					session_entry->protStaCache[i].active =
896 						 false;
897 				break;
898 			}
899 		}
900 
901 		if (session_entry->gLim11bParams.numSta == 0) {
902 			/* disable protection */
903 			lim_enable11g_protection(mac_ctx, false, false,
904 						 beacon_params, session_entry);
905 		}
906 	}
907 
908 	/*
909 	 * we are HT AP and non-11B station is leaving.
910 	 * 11g station is leaving
911 	 */
912 	if ((REG_BAND_2G == rf_band) &&
913 		session_entry->htCapability &&
914 		!sta_ds->mlmStaContext.htCapability) {
915 		pe_debug("(%d) A 11g STA is disassociated. Addr is "QDF_MAC_ADDR_FMT,
916 			session_entry->gLim11bParams.numSta,
917 			QDF_MAC_ADDR_REF(sta_ds->staAddr));
918 		for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) {
919 			if (session_entry->protStaCache[i].active &&
920 				(!qdf_mem_cmp(
921 					session_entry->protStaCache[i].addr,
922 					sta_ds->staAddr,
923 					sizeof(tSirMacAddr)))) {
924 				session_entry->gLim11gParams.numSta--;
925 				session_entry->protStaCache[i].active = false;
926 				break;
927 			}
928 		}
929 
930 		if (session_entry->gLim11gParams.numSta == 0) {
931 		    /* disable protection */
932 		    lim_enable_ht_protection_from11g(mac_ctx, false, false,
933 							 beacon_params,
934 							 session_entry);
935 		}
936 	}
937 
938 	if (!((true == session_entry->htCapability) &&
939 		(true == sta_ds->mlmStaContext.htCapability)))
940 		return;
941 
942 	/*
943 	 * Applies to 2.4 as well as 5 GHZ.
944 	 * HT non-GF leaving
945 	 */
946 	if (!sta_ds->htGreenfield) {
947 		pe_debug("(%d) A non-GF STA is disassociated. Addr is "QDF_MAC_ADDR_FMT,
948 			session_entry->gLimNonGfParams.numSta,
949 			QDF_MAC_ADDR_REF(sta_ds->staAddr));
950 		for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) {
951 			if (session_entry->protStaCache[i].active &&
952 				(!qdf_mem_cmp(
953 					session_entry->protStaCache[i].addr,
954 					sta_ds->staAddr,
955 					sizeof(tSirMacAddr)))) {
956 				session_entry->protStaCache[i].active = false;
957 				break;
958 			}
959 		}
960 
961 		if (session_entry->gLimNonGfParams.numSta == 0) {
962 			/* disable protection */
963 			lim_enable_ht_non_gf_protection(mac_ctx, false, false,
964 					beacon_params, session_entry);
965 		}
966 	}
967 
968 	/*
969 	 * Applies to 2.4 as well as 5 GHZ.
970 	 * HT 20Mhz station leaving
971 	 */
972 	if (session_entry->beaconParams.ht20Coexist &&
973 		(eHT_CHANNEL_WIDTH_20MHZ ==
974 			 sta_ds->htSupportedChannelWidthSet)) {
975 		lim_decide_ap_protection_on_ht20_delete(mac_ctx, sta_ds,
976 					beacon_params, session_entry);
977 	}
978 
979 	/*
980 	 * Applies to 2.4 as well as 5 GHZ.
981 	 * LSIG TXOP not supporting staiton leaving
982 	 */
983 	if ((false == session_entry->beaconParams.
984 				fLsigTXOPProtectionFullSupport) &&
985 		(false == sta_ds->htLsigTXOPProtection)) {
986 		pe_debug("(%d) A HT LSIG not supporting STA is disassociated. Addr is "QDF_MAC_ADDR_FMT,
987 			session_entry->gLimLsigTxopParams.numSta,
988 			QDF_MAC_ADDR_REF(sta_ds->staAddr));
989 		for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) {
990 			if (session_entry->protStaCache[i].active &&
991 				(!qdf_mem_cmp(
992 					session_entry->protStaCache[i].addr,
993 					sta_ds->staAddr,
994 					sizeof(tSirMacAddr)))) {
995 				session_entry->protStaCache[i].active = false;
996 				break;
997 			}
998 		}
999 
1000 		if (session_entry->gLimLsigTxopParams.numSta == 0) {
1001 			/* disable protection */
1002 			lim_enable_ht_lsig_txop_protection(mac_ctx, true,
1003 				false, beacon_params, session_entry);
1004 		}
1005 	}
1006 }
1007 
1008 /**
1009  * lim_decide_short_preamble() - update short preamble parameters
1010  * @mac_ctx: pointer to global mac structure
1011  * @sta_ds: station node
1012  * @beacon_params: ap beacon parameters
1013  * @session_entry: pe session entry
1014  *
1015  * Decides about any short preamble related change because of new station
1016  * joining.
1017  *
1018  * Return: None
1019  */
1020 static void lim_decide_short_preamble(struct mac_context *mac_ctx,
1021 				      tpDphHashNode sta_ds,
1022 				      tpUpdateBeaconParams beacon_params,
1023 				      struct pe_session *session_entry)
1024 {
1025 	uint32_t i;
1026 
1027 	if (sta_ds->shortPreambleEnabled == eHAL_CLEAR) {
1028 		pe_debug("(%d) A non-short preamble STA is disassociated. Addr is "QDF_MAC_ADDR_FMT,
1029 			 session_entry->gLimNoShortParams.numNonShortPreambleSta,
1030 			 QDF_MAC_ADDR_REF(sta_ds->staAddr));
1031 		for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) {
1032 			if (session_entry->gLimNoShortParams.
1033 				staNoShortCache[i].active &&
1034 				(!qdf_mem_cmp(session_entry->
1035 					gLimNoShortParams.
1036 					staNoShortCache[i].addr,
1037 					sta_ds->staAddr,
1038 					sizeof(tSirMacAddr)))) {
1039 				session_entry->gLimNoShortParams.
1040 					numNonShortPreambleSta--;
1041 				session_entry->gLimNoShortParams.
1042 					staNoShortCache[i].active = false;
1043 				break;
1044 			}
1045 		}
1046 
1047 		if (session_entry->gLimNoShortParams.numNonShortPreambleSta)
1048 			return;
1049 
1050 		/*
1051 		 * enable short preamble
1052 		 * reset the cache
1053 		 */
1054 		qdf_mem_zero((uint8_t *) &session_entry->gLimNoShortParams,
1055 				sizeof(tLimNoShortParams));
1056 		if (lim_enable_short_preamble(mac_ctx, true,
1057 			beacon_params, session_entry) != QDF_STATUS_SUCCESS)
1058 			pe_err("Cannot enable short preamble");
1059 	}
1060 }
1061 
1062 /**
1063  * lim_decide_short_slot() - update short slot time related  parameters
1064  * @mac_ctx: pointer to global mac structure
1065  * @sta_ds: station node
1066  * @beacon_params: ap beacon parameters
1067  * @session_entry: pe session entry
1068  *
1069  * Decides about any short slot time related change because of station leaving
1070  *        the BSS.
1071  * Return: None
1072  */
1073 static void
1074 lim_decide_short_slot(struct mac_context *mac_ctx, tpDphHashNode sta_ds,
1075 		      tpUpdateBeaconParams beacon_params,
1076 		      struct pe_session *session_entry)
1077 {
1078 	uint32_t i, val, non_short_slot_sta_count;
1079 
1080 	if (sta_ds->shortSlotTimeEnabled != eHAL_CLEAR)
1081 		return;
1082 
1083 	pe_debug("(%d) A non-short slottime STA is disassociated. Addr is "QDF_MAC_ADDR_FMT,
1084 		mac_ctx->lim.gLimNoShortSlotParams.numNonShortSlotSta,
1085 		QDF_MAC_ADDR_REF(sta_ds->staAddr));
1086 
1087 	val = mac_ctx->mlme_cfg->feature_flags.enable_short_slot_time_11g;
1088 
1089 	if (LIM_IS_AP_ROLE(session_entry)) {
1090 		non_short_slot_sta_count =
1091 		      session_entry->gLimNoShortSlotParams.numNonShortSlotSta;
1092 		for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) {
1093 			if (session_entry->gLimNoShortSlotParams.
1094 				staNoShortSlotCache[i].active &&
1095 				(!qdf_mem_cmp(session_entry->
1096 					gLimNoShortSlotParams.
1097 						staNoShortSlotCache[i].addr,
1098 					sta_ds->staAddr,
1099 					sizeof(tSirMacAddr)))) {
1100 				non_short_slot_sta_count--;
1101 				session_entry->gLimNoShortSlotParams.
1102 					staNoShortSlotCache[i].active = false;
1103 				break;
1104 			}
1105 		}
1106 
1107 		if (non_short_slot_sta_count == 0 && val) {
1108 			/*
1109 			 * enable short slot time
1110 			 * reset the cache
1111 			 */
1112 			qdf_mem_zero((uint8_t *) &session_entry->
1113 				gLimNoShortSlotParams,
1114 				sizeof(tLimNoShortSlotParams));
1115 			beacon_params->fShortSlotTime = true;
1116 			beacon_params->paramChangeBitmap |=
1117 				PARAM_SHORT_SLOT_TIME_CHANGED;
1118 			session_entry->shortSlotTimeSupported = true;
1119 		}
1120 		session_entry->gLimNoShortSlotParams.numNonShortSlotSta =
1121 			non_short_slot_sta_count;
1122 	} else {
1123 		non_short_slot_sta_count =
1124 			mac_ctx->lim.gLimNoShortSlotParams.numNonShortSlotSta;
1125 		for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) {
1126 			if (mac_ctx->lim.gLimNoShortSlotParams.
1127 				staNoShortSlotCache[i].active &&
1128 				(!qdf_mem_cmp(
1129 					mac_ctx->lim.gLimNoShortSlotParams.
1130 						staNoShortSlotCache[i].addr,
1131 					sta_ds->staAddr,
1132 					sizeof(tSirMacAddr)))) {
1133 				non_short_slot_sta_count--;
1134 				mac_ctx->lim.gLimNoShortSlotParams.
1135 					staNoShortSlotCache[i].active = false;
1136 				break;
1137 			}
1138 		}
1139 
1140 		if (val && !non_short_slot_sta_count) {
1141 			/*
1142 			 * enable short slot time
1143 			 * reset the cache
1144 			 */
1145 			qdf_mem_zero(
1146 				(uint8_t *) &mac_ctx->lim.gLimNoShortSlotParams,
1147 				sizeof(tLimNoShortSlotParams));
1148 			/*in case of AP set SHORT_SLOT_TIME to enable*/
1149 			if (LIM_IS_AP_ROLE(session_entry)) {
1150 				beacon_params->fShortSlotTime = true;
1151 				beacon_params->paramChangeBitmap |=
1152 					PARAM_SHORT_SLOT_TIME_CHANGED;
1153 				session_entry->shortSlotTimeSupported = true;
1154 			}
1155 		}
1156 		mac_ctx->lim.gLimNoShortSlotParams.numNonShortSlotSta =
1157 			non_short_slot_sta_count;
1158 	}
1159 }
1160 
1161 static uint8_t lim_get_nss_from_vht_mcs_map(uint16_t mcs_map)
1162 {
1163 	uint8_t nss = 0;
1164 	uint16_t mcs_mask = 0x3;
1165 
1166 	for (nss = 0; nss < VHT_MAX_NSS; nss++) {
1167 		if ((mcs_map & mcs_mask) ==  mcs_mask)
1168 			return nss;
1169 
1170 		mcs_mask = (mcs_mask << 2);
1171 	}
1172 
1173 	return nss;
1174 }
1175 
1176 static void lim_get_vht_gt80_nss(struct mac_context *mac_ctx,
1177 				 struct sDphHashNode *sta_ds,
1178 				 tDot11fIEVHTCaps *vht_caps,
1179 				 struct pe_session *session)
1180 {
1181 	uint8_t nss;
1182 
1183 	if (!vht_caps->vht_extended_nss_bw_cap) {
1184 		sta_ds->vht_160mhz_nss = 0;
1185 		sta_ds->vht_80p80mhz_nss = 0;
1186 		pe_debug("peer does not support vht extnd nss bw");
1187 
1188 		return;
1189 	}
1190 
1191 	nss = lim_get_nss_from_vht_mcs_map(vht_caps->rxMCSMap);
1192 
1193 	if (!nss) {
1194 		pe_debug("Invalid peer VHT MCS map %0X", vht_caps->rxMCSMap);
1195 		nss = 1;
1196 	}
1197 
1198 	switch (vht_caps->supportedChannelWidthSet) {
1199 	case VHT_CAP_NO_160M_SUPP:
1200 		if (vht_caps->extended_nss_bw_supp ==
1201 		    VHT_EXTD_NSS_80_HALF_NSS_160) {
1202 			sta_ds->vht_160mhz_nss = nss / 2;
1203 			sta_ds->vht_80p80mhz_nss = 0;
1204 		} else if (vht_caps->extended_nss_bw_supp ==
1205 			   VHT_EXTD_NSS_80_HALF_NSS_80P80) {
1206 			sta_ds->vht_160mhz_nss = nss / 2;
1207 			sta_ds->vht_80p80mhz_nss = nss / 2;
1208 		} else if (vht_caps->extended_nss_bw_supp ==
1209 			   VHT_EXTD_NSS_80_3QUART_NSS_80P80) {
1210 			sta_ds->vht_160mhz_nss = (nss * 3) / 4;
1211 			sta_ds->vht_80p80mhz_nss = (nss * 3) / 4;
1212 		} else {
1213 			sta_ds->vht_160mhz_nss = 0;
1214 			sta_ds->vht_80p80mhz_nss = 0;
1215 		}
1216 		break;
1217 	case VHT_CAP_160_SUPP:
1218 		sta_ds->vht_160mhz_nss = nss;
1219 		if (vht_caps->extended_nss_bw_supp ==
1220 		    VHT_EXTD_NSS_160_HALF_NSS_80P80) {
1221 			sta_ds->vht_80p80mhz_nss = nss / 2;
1222 		} else if (vht_caps->extended_nss_bw_supp ==
1223 			   VHT_EXTD_NSS_160_3QUART_NSS_80P80) {
1224 			sta_ds->vht_80p80mhz_nss = (nss * 3) / 4;
1225 		} else if (vht_caps->extended_nss_bw_supp ==
1226 			   VHT_EXTD_NSS_2X_NSS_160_1X_NSS_80P80) {
1227 			if (nss > (VHT_MAX_NSS / 2)) {
1228 				pe_debug("Invalid extnd nss bw support val");
1229 				sta_ds->vht_80p80mhz_nss = nss / 2;
1230 				break;
1231 			}
1232 			sta_ds->vht_160mhz_nss = nss * 2;
1233 			if (session->nss == MAX_VDEV_NSS)
1234 				break;
1235 			if (!mac_ctx->mlme_cfg->vht_caps.vht_cap_info.enable2x2)
1236 				break;
1237 			session->nss *= 2;
1238 		} else {
1239 			sta_ds->vht_80p80mhz_nss = 0;
1240 		}
1241 		break;
1242 	case VHT_CAP_160_AND_80P80_SUPP:
1243 		if (vht_caps->extended_nss_bw_supp ==
1244 		    VHT_EXTD_NSS_2X_NSS_80_1X_NSS_80P80) {
1245 			if (nss > (VHT_MAX_NSS / 2)) {
1246 				pe_debug("Invalid extnd nss bw support val");
1247 				break;
1248 			}
1249 			if (session->nss == MAX_VDEV_NSS)
1250 				break;
1251 			if (!mac_ctx->mlme_cfg->vht_caps.vht_cap_info.enable2x2)
1252 				break;
1253 			session->nss *= 2;
1254 		} else {
1255 			sta_ds->vht_160mhz_nss = nss;
1256 			sta_ds->vht_80p80mhz_nss = nss;
1257 		}
1258 		break;
1259 	default:
1260 		sta_ds->vht_160mhz_nss = 0;
1261 		sta_ds->vht_80p80mhz_nss = 0;
1262 	}
1263 	pe_debug("AP Nss config: 160MHz: %d, 80P80MHz %d",
1264 		 sta_ds->vht_160mhz_nss, sta_ds->vht_80p80mhz_nss);
1265 	sta_ds->vht_160mhz_nss = QDF_MIN(sta_ds->vht_160mhz_nss, session->nss);
1266 	sta_ds->vht_80p80mhz_nss = QDF_MIN(sta_ds->vht_80p80mhz_nss,
1267 					   session->nss);
1268 	pe_debug("Session Nss config: 160MHz: %d, 80P80MHz %d, session Nss %d",
1269 		 sta_ds->vht_160mhz_nss, sta_ds->vht_80p80mhz_nss,
1270 		 session->nss);
1271 }
1272 
1273 QDF_STATUS lim_populate_vht_mcs_set(struct mac_context *mac_ctx,
1274 				    struct supported_rates *rates,
1275 				    tDot11fIEVHTCaps *peer_vht_caps,
1276 				    struct pe_session *session_entry,
1277 				    uint8_t nss,
1278 				    struct sDphHashNode *sta_ds)
1279 {
1280 	uint32_t self_sta_dot11mode = 0;
1281 	uint16_t mcs_map_mask = MCSMAPMASK1x1;
1282 	uint16_t mcs_map_mask2x2 = 0;
1283 	struct mlme_vht_capabilities_info *vht_cap_info;
1284 
1285 	self_sta_dot11mode = mac_ctx->mlme_cfg->dot11_mode.dot11_mode;
1286 
1287 	if (!IS_DOT11_MODE_VHT(self_sta_dot11mode))
1288 		return QDF_STATUS_SUCCESS;
1289 
1290 	if (!peer_vht_caps || !peer_vht_caps->present)
1291 		return QDF_STATUS_SUCCESS;
1292 
1293 	vht_cap_info = &mac_ctx->mlme_cfg->vht_caps.vht_cap_info;
1294 
1295 	rates->vhtRxMCSMap = (uint16_t)vht_cap_info->rx_mcs_map;
1296 	rates->vhtTxMCSMap = (uint16_t)vht_cap_info->tx_mcs_map;
1297 	rates->vhtRxHighestDataRate =
1298 			(uint16_t)vht_cap_info->rx_supp_data_rate;
1299 	rates->vhtTxHighestDataRate =
1300 			(uint16_t)vht_cap_info->tx_supp_data_rate;
1301 
1302 	if (NSS_1x1_MODE == nss) {
1303 		rates->vhtRxMCSMap |= VHT_MCS_1x1;
1304 		rates->vhtTxMCSMap |= VHT_MCS_1x1;
1305 		rates->vhtTxHighestDataRate =
1306 			VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1;
1307 		rates->vhtRxHighestDataRate =
1308 			VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1;
1309 		if (session_entry && !session_entry->ch_width &&
1310 		    !vht_cap_info->enable_vht20_mcs9 &&
1311 		    ((rates->vhtRxMCSMap & VHT_1x1_MCS_MASK) ==
1312 				 VHT_1x1_MCS9_MAP)) {
1313 			DISABLE_VHT_MCS_9(rates->vhtRxMCSMap,
1314 					NSS_1x1_MODE);
1315 			DISABLE_VHT_MCS_9(rates->vhtTxMCSMap,
1316 					NSS_1x1_MODE);
1317 		}
1318 	} else {
1319 		if (session_entry && !session_entry->ch_width &&
1320 			!vht_cap_info->enable_vht20_mcs9 &&
1321 			((rates->vhtRxMCSMap & VHT_2x2_MCS_MASK) ==
1322 			VHT_2x2_MCS9_MAP)) {
1323 			DISABLE_VHT_MCS_9(rates->vhtRxMCSMap,
1324 					NSS_2x2_MODE);
1325 			DISABLE_VHT_MCS_9(rates->vhtTxMCSMap,
1326 					NSS_2x2_MODE);
1327 		}
1328 	}
1329 
1330 	if (peer_vht_caps->txSupDataRate)
1331 		rates->vhtTxHighestDataRate =
1332 			QDF_MIN(rates->vhtTxHighestDataRate,
1333 				peer_vht_caps->txSupDataRate);
1334 	if (peer_vht_caps->rxHighSupDataRate)
1335 		rates->vhtRxHighestDataRate =
1336 			QDF_MIN(rates->vhtRxHighestDataRate,
1337 				peer_vht_caps->rxHighSupDataRate);
1338 
1339 	if (session_entry && session_entry->nss == NSS_2x2_MODE)
1340 		mcs_map_mask2x2 = MCSMAPMASK2x2;
1341 
1342 	if ((peer_vht_caps->txMCSMap & mcs_map_mask) <
1343 	    (rates->vhtRxMCSMap & mcs_map_mask)) {
1344 		rates->vhtRxMCSMap &= ~(mcs_map_mask);
1345 		rates->vhtRxMCSMap |= (peer_vht_caps->txMCSMap & mcs_map_mask);
1346 	}
1347 	if ((peer_vht_caps->rxMCSMap & mcs_map_mask) <
1348 	    (rates->vhtTxMCSMap & mcs_map_mask)) {
1349 		rates->vhtTxMCSMap &= ~(mcs_map_mask);
1350 		rates->vhtTxMCSMap |= (peer_vht_caps->rxMCSMap & mcs_map_mask);
1351 	}
1352 
1353 	if (mcs_map_mask2x2) {
1354 		uint16_t peer_mcs_map, self_mcs_map;
1355 
1356 		peer_mcs_map = peer_vht_caps->txMCSMap & mcs_map_mask2x2;
1357 		self_mcs_map = rates->vhtRxMCSMap & mcs_map_mask2x2;
1358 
1359 		if ((self_mcs_map != mcs_map_mask2x2) &&
1360 		    ((peer_mcs_map == mcs_map_mask2x2) ||
1361 		     (peer_mcs_map < self_mcs_map))) {
1362 			rates->vhtRxMCSMap &= ~mcs_map_mask2x2;
1363 			rates->vhtRxMCSMap |= peer_mcs_map;
1364 		}
1365 
1366 		peer_mcs_map = (peer_vht_caps->rxMCSMap & mcs_map_mask2x2);
1367 		self_mcs_map = (rates->vhtTxMCSMap & mcs_map_mask2x2);
1368 
1369 		if ((self_mcs_map != mcs_map_mask2x2) &&
1370 		    ((peer_mcs_map == mcs_map_mask2x2) ||
1371 		     (peer_mcs_map < self_mcs_map))) {
1372 			rates->vhtTxMCSMap &= ~mcs_map_mask2x2;
1373 			rates->vhtTxMCSMap |= peer_mcs_map;
1374 		}
1375 	}
1376 
1377 	pe_debug("RxMCSMap %x TxMCSMap %x", rates->vhtRxMCSMap,
1378 		 rates->vhtTxMCSMap);
1379 
1380 	if (!session_entry)
1381 		return QDF_STATUS_SUCCESS;
1382 
1383 	session_entry->supported_nss_1x1 =
1384 		((rates->vhtTxMCSMap & VHT_MCS_1x1) == VHT_MCS_1x1) ?
1385 		true : false;
1386 
1387 	if (!sta_ds || CH_WIDTH_80MHZ >= session_entry->ch_width)
1388 		return QDF_STATUS_SUCCESS;
1389 
1390 	sta_ds->vht_extended_nss_bw_cap =
1391 		peer_vht_caps->vht_extended_nss_bw_cap;
1392 	lim_get_vht_gt80_nss(mac_ctx, sta_ds, peer_vht_caps, session_entry);
1393 
1394 	return QDF_STATUS_SUCCESS;
1395 }
1396 
1397 static void lim_dump_ht_mcs_mask(uint8_t *self_mcs, uint8_t *peer_mcs)
1398 {
1399 	uint32_t len = 0;
1400 	uint8_t idx;
1401 	uint8_t *buff;
1402 	uint32_t buff_len;
1403 
1404 	/*
1405 	 * Buffer of (SIR_MAC_MAX_SUPPORTED_MCS_SET * 5) + 1  to consider the 4
1406 	 * char MCS eg 0xff and 1 space after it and 1 to end the string with
1407 	 * NULL.
1408 	 */
1409 	buff_len = (SIR_MAC_MAX_SUPPORTED_MCS_SET * 5) + 1;
1410 	buff = qdf_mem_malloc(buff_len);
1411 	if (!buff)
1412 		return;
1413 
1414 	if (self_mcs) {
1415 		for (idx = 0; idx < SIR_MAC_MAX_SUPPORTED_MCS_SET; idx++)
1416 			len += qdf_scnprintf(buff + len, buff_len - len,
1417 					     "0x%x ", self_mcs[idx]);
1418 
1419 		pe_nofl_debug("SELF HT MCS: %s", buff);
1420 	}
1421 
1422 	if (peer_mcs) {
1423 		len = 0;
1424 		for (idx = 0; idx < SIR_MAC_MAX_SUPPORTED_MCS_SET; idx++)
1425 			len += qdf_scnprintf(buff + len, buff_len - len,
1426 					     "0x%x ", peer_mcs[idx]);
1427 
1428 		pe_nofl_debug("PEER HT MCS: %s", buff);
1429 	}
1430 
1431 	qdf_mem_free(buff);
1432 }
1433 
1434 QDF_STATUS lim_populate_own_rate_set(struct mac_context *mac_ctx,
1435 				     struct supported_rates *rates,
1436 				     uint8_t *supported_mcs_set,
1437 				     uint8_t basic_only,
1438 				     struct pe_session *session_entry,
1439 				     struct sDot11fIEVHTCaps *vht_caps,
1440 				     struct sDot11fIEhe_cap *he_caps,
1441 				     struct sDot11fIEeht_cap *eht_caps)
1442 {
1443 	tSirMacRateSet temp_rate_set;
1444 	tSirMacRateSet temp_rate_set2;
1445 	uint32_t i, j, val, min, is_arate;
1446 	uint32_t phy_mode = 0;
1447 	uint32_t self_sta_dot11mode = 0;
1448 	uint8_t a_rate_index = 0;
1449 	uint8_t b_rate_index = 0;
1450 	qdf_size_t val_len;
1451 
1452 	is_arate = 0;
1453 
1454 	self_sta_dot11mode = mac_ctx->mlme_cfg->dot11_mode.dot11_mode;
1455 	lim_get_phy_mode(mac_ctx, &phy_mode, session_entry);
1456 
1457 	/*
1458 	 * Include 11b rates only when the device configured in
1459 	 *  auto, 11a/b/g or 11b_only
1460 	 */
1461 	if ((self_sta_dot11mode == MLME_DOT11_MODE_ALL) ||
1462 	    (self_sta_dot11mode == MLME_DOT11_MODE_11A) ||
1463 	    (self_sta_dot11mode == MLME_DOT11_MODE_11AC) ||
1464 	    (self_sta_dot11mode == MLME_DOT11_MODE_11N) ||
1465 	    (self_sta_dot11mode == MLME_DOT11_MODE_11G) ||
1466 	    (self_sta_dot11mode == MLME_DOT11_MODE_11B) ||
1467 	    (self_sta_dot11mode == MLME_DOT11_MODE_11AX)) {
1468 		val_len = mac_ctx->mlme_cfg->rates.supported_11b.len;
1469 		wlan_mlme_get_cfg_str((uint8_t *)&temp_rate_set.rate,
1470 				      &mac_ctx->mlme_cfg->rates.supported_11b,
1471 				      &val_len);
1472 		temp_rate_set.numRates = (uint8_t)val_len;
1473 	} else {
1474 		temp_rate_set.numRates = 0;
1475 	}
1476 
1477 	/* Include 11a rates when the device configured in non-11b mode */
1478 	if (!IS_DOT11_MODE_11B(self_sta_dot11mode)) {
1479 		val_len = mac_ctx->mlme_cfg->rates.supported_11a.len;
1480 		wlan_mlme_get_cfg_str((uint8_t *)&temp_rate_set2.rate,
1481 				      &mac_ctx->mlme_cfg->rates.supported_11a,
1482 				      &val_len);
1483 		temp_rate_set2.numRates = (uint8_t)val_len;
1484 	} else {
1485 		temp_rate_set2.numRates = 0;
1486 	}
1487 
1488 	if ((temp_rate_set.numRates + temp_rate_set2.numRates) > 12) {
1489 		pe_err("more than 12 rates in CFG");
1490 		return QDF_STATUS_E_FAILURE;
1491 	}
1492 	/* copy all rates in temp_rate_set, there are 12 rates max */
1493 	for (i = 0; i < temp_rate_set2.numRates; i++)
1494 		temp_rate_set.rate[i + temp_rate_set.numRates] =
1495 			temp_rate_set2.rate[i];
1496 
1497 	temp_rate_set.numRates += temp_rate_set2.numRates;
1498 
1499 	/**
1500 	 * Sort rates in temp_rate_set (they are likely to be already sorted)
1501 	 * put the result in pSupportedRates
1502 	 */
1503 
1504 	qdf_mem_zero(rates, sizeof(*rates));
1505 	for (i = 0; i < temp_rate_set.numRates; i++) {
1506 		min = 0;
1507 		val = 0xff;
1508 		is_arate = 0;
1509 
1510 		for (j = 0; (j < temp_rate_set.numRates) &&
1511 			 (j < SIR_MAC_MAX_NUMBER_OF_RATES); j++) {
1512 			if ((uint32_t) (temp_rate_set.rate[j] & 0x7f) <
1513 					val) {
1514 				val = temp_rate_set.rate[j] & 0x7f;
1515 				min = j;
1516 			}
1517 		}
1518 
1519 		if (sirIsArate(temp_rate_set.rate[min] & 0x7f))
1520 			is_arate = 1;
1521 
1522 		if (is_arate)
1523 			rates->llaRates[a_rate_index++] =
1524 						temp_rate_set.rate[min];
1525 		else
1526 			rates->llbRates[b_rate_index++] =
1527 						temp_rate_set.rate[min];
1528 		temp_rate_set.rate[min] = 0xff;
1529 	}
1530 
1531 	if (IS_DOT11_MODE_HT(self_sta_dot11mode)) {
1532 		val_len = SIZE_OF_SUPPORTED_MCS_SET;
1533 		if (wlan_mlme_get_cfg_str(
1534 			rates->supportedMCSSet,
1535 			&mac_ctx->mlme_cfg->rates.supported_mcs_set,
1536 			&val_len) != QDF_STATUS_SUCCESS) {
1537 			pe_err("could not retrieve supportedMCSSet");
1538 			return QDF_STATUS_E_FAILURE;
1539 		}
1540 
1541 		if (session_entry->nss == NSS_1x1_MODE)
1542 			rates->supportedMCSSet[1] = 0;
1543 		/*
1544 		 * if supported MCS Set of the peer is passed in,
1545 		 * then do the intersection
1546 		 * else use the MCS set from local CFG.
1547 		 */
1548 
1549 		if (supported_mcs_set) {
1550 			for (i = 0; i < SIR_MAC_MAX_SUPPORTED_MCS_SET; i++)
1551 				rates->supportedMCSSet[i] &=
1552 					 supported_mcs_set[i];
1553 		}
1554 
1555 		lim_dump_ht_mcs_mask(rates->supportedMCSSet, NULL);
1556 	}
1557 	lim_populate_vht_mcs_set(mac_ctx, rates, vht_caps, session_entry,
1558 				 session_entry->nss, NULL);
1559 	lim_populate_he_mcs_set(mac_ctx, rates, he_caps,
1560 			session_entry, session_entry->nss);
1561 	lim_populate_eht_mcs_set(mac_ctx, rates, eht_caps,
1562 				 session_entry, session_entry->nss);
1563 
1564 	return QDF_STATUS_SUCCESS;
1565 }
1566 
1567 #ifdef WLAN_FEATURE_11AX
1568 static bool lim_check_valid_mcs_for_nss(struct pe_session *session,
1569 					tDot11fIEhe_cap *he_caps)
1570 {
1571 	uint16_t mcs_map;
1572 	uint8_t mcs_count = 2, i;
1573 
1574 	if (!session->he_capable || !he_caps || !he_caps->present)
1575 		return true;
1576 
1577 	mcs_map = he_caps->rx_he_mcs_map_lt_80;
1578 
1579 	do {
1580 		for (i = 0; i < session->nss; i++) {
1581 			if (((mcs_map >> (i * 2)) & 0x3) == 0x3)
1582 				return false;
1583 		}
1584 
1585 		mcs_map = he_caps->tx_he_mcs_map_lt_80;
1586 		mcs_count--;
1587 	} while (mcs_count);
1588 
1589 	if ((session->ch_width == CH_WIDTH_160MHZ ||
1590 	     lim_is_session_chwidth_320mhz(session)) &&
1591 	     !he_caps->chan_width_2) {
1592 		pe_err("session BW 160/320 MHz but peer BW less than 160 MHz");
1593 		return false;
1594 	}
1595 
1596 	return true;
1597 
1598 }
1599 #else
1600 static bool lim_check_valid_mcs_for_nss(struct pe_session *session,
1601 					tDot11fIEhe_cap *he_caps)
1602 {
1603 	return true;
1604 }
1605 #endif
1606 
1607 /**
1608  * lim_remove_membership_selectors() - remove elements from rate set
1609  *
1610  * @rate_set: pointer to rate set
1611  *
1612  * Removes the BSS membership selector elements from the rate set, and keep
1613  * only the rates
1614  *
1615  * Return: none
1616  */
1617 static void lim_remove_membership_selectors(tSirMacRateSet *rate_set)
1618 {
1619 	int i, selector_count = 0;
1620 
1621 	for (i = 0; i < rate_set->numRates; i++) {
1622 		if ((rate_set->rate[i] == (WLAN_BASIC_RATE_MASK |
1623 				WLAN_BSS_MEMBERSHIP_SELECTOR_HT_PHY)) ||
1624 		    (rate_set->rate[i] == (WLAN_BASIC_RATE_MASK |
1625 				WLAN_BSS_MEMBERSHIP_SELECTOR_VHT_PHY)) ||
1626 		    (rate_set->rate[i] == (WLAN_BASIC_RATE_MASK |
1627 				WLAN_BSS_MEMBERSHIP_SELECTOR_GLK)) ||
1628 		    (rate_set->rate[i] == (WLAN_BASIC_RATE_MASK |
1629 				WLAN_BSS_MEMBERSHIP_SELECTOR_EPD)) ||
1630 		    (rate_set->rate[i] == (WLAN_BASIC_RATE_MASK |
1631 				WLAN_BSS_MEMBERSHIP_SELECTOR_SAE_H2E)) ||
1632 		    (rate_set->rate[i] == (WLAN_BASIC_RATE_MASK |
1633 				WLAN_BSS_MEMBERSHIP_SELECTOR_HE_PHY)))
1634 			selector_count++;
1635 
1636 		if (i + selector_count < rate_set->numRates)
1637 			rate_set->rate[i] = rate_set->rate[i + selector_count];
1638 	}
1639 	rate_set->numRates -= selector_count;
1640 }
1641 
1642 QDF_STATUS lim_populate_peer_rate_set(struct mac_context *mac,
1643 				      struct supported_rates *pRates,
1644 				      uint8_t *pSupportedMCSSet,
1645 				      uint8_t basicOnly,
1646 				      struct pe_session *pe_session,
1647 				      tDot11fIEVHTCaps *pVHTCaps,
1648 				      tDot11fIEhe_cap *he_caps,
1649 				      tDot11fIEeht_cap *eht_caps,
1650 				      struct sDphHashNode *sta_ds,
1651 				      struct bss_description *bss_desc)
1652 {
1653 	tSirMacRateSet tempRateSet;
1654 	tSirMacRateSet tempRateSet2;
1655 	uint32_t i, j, val, min;
1656 	qdf_size_t val_len;
1657 	uint8_t aRateIndex = 0;
1658 	uint8_t bRateIndex = 0;
1659 	tDot11fIEhe_cap *peer_he_caps;
1660 	tSchBeaconStruct *pBeaconStruct = NULL;
1661 
1662 	/* copy operational rate set from pe_session */
1663 	if (pe_session->rateSet.numRates <= SIR_MAC_MAX_NUMBER_OF_RATES) {
1664 		qdf_mem_copy((uint8_t *) tempRateSet.rate,
1665 			     (uint8_t *) (pe_session->rateSet.rate),
1666 			     pe_session->rateSet.numRates);
1667 		tempRateSet.numRates = pe_session->rateSet.numRates;
1668 	} else {
1669 		pe_err("more than SIR_MAC_MAX_NUMBER_OF_RATES rates");
1670 		return QDF_STATUS_E_FAILURE;
1671 	}
1672 	if ((pe_session->dot11mode == MLME_DOT11_MODE_11G) ||
1673 		(pe_session->dot11mode == MLME_DOT11_MODE_11A) ||
1674 		(pe_session->dot11mode == MLME_DOT11_MODE_11AC) ||
1675 		(pe_session->dot11mode == MLME_DOT11_MODE_11N) ||
1676 		(pe_session->dot11mode == MLME_DOT11_MODE_11AX)) {
1677 		if (pe_session->extRateSet.numRates <=
1678 		    SIR_MAC_MAX_NUMBER_OF_RATES) {
1679 			qdf_mem_copy((uint8_t *) tempRateSet2.rate,
1680 				     (uint8_t *) (pe_session->extRateSet.
1681 						  rate),
1682 				     pe_session->extRateSet.numRates);
1683 			tempRateSet2.numRates =
1684 				pe_session->extRateSet.numRates;
1685 		} else {
1686 			pe_err("numRates more than SIR_MAC_MAX_NUM_OF_RATES");
1687 			return QDF_STATUS_E_FAILURE;
1688 		}
1689 	} else
1690 		tempRateSet2.numRates = 0;
1691 
1692 	lim_remove_membership_selectors(&tempRateSet);
1693 	lim_remove_membership_selectors(&tempRateSet2);
1694 
1695 	if ((tempRateSet.numRates + tempRateSet2.numRates) >
1696 	    SIR_MAC_MAX_NUMBER_OF_RATES) {
1697 		pe_err("rates in CFG are more than SIR_MAC_MAX_NUM_OF_RATES");
1698 		return QDF_STATUS_E_FAILURE;
1699 	}
1700 
1701 	/* copy all rates in tempRateSet, there are 12 rates max */
1702 	for (i = 0; i < tempRateSet2.numRates; i++)
1703 		tempRateSet.rate[i + tempRateSet.numRates] =
1704 			tempRateSet2.rate[i];
1705 	tempRateSet.numRates += tempRateSet2.numRates;
1706 	/**
1707 	 * Sort rates in tempRateSet (they are likely to be already sorted)
1708 	 * put the result in pSupportedRates
1709 	 */
1710 
1711 	qdf_mem_zero(pRates, sizeof(*pRates));
1712 	for (i = 0; i < tempRateSet.numRates; i++) {
1713 		min = 0;
1714 		val = 0xff;
1715 		for (j = 0; (j < tempRateSet.numRates) &&
1716 		     (j < SIR_MAC_MAX_NUMBER_OF_RATES); j++) {
1717 			if ((uint32_t)(tempRateSet.rate[j] & 0x7f) <
1718 					val) {
1719 				val = tempRateSet.rate[j] & 0x7f;
1720 				min = j;
1721 			}
1722 		}
1723 		/*
1724 		 * HAL needs to know whether the rate is basic rate or not,
1725 		 * as it needs to update the response rate table accordingly.
1726 		 * e.g. if one of the 11a rates is basic rate, then that rate
1727 		 * can be used for sending control frames. HAL updates the
1728 		 * response rate table whenever basic rate set is changed.
1729 		 */
1730 		if (basicOnly && !(tempRateSet.rate[min] & 0x80)) {
1731 			pe_debug("Invalid basic rate");
1732 		} else if (sirIsArate(tempRateSet.rate[min] & 0x7f)) {
1733 			if (aRateIndex >= SIR_NUM_11A_RATES) {
1734 				pe_debug("OOB, aRateIndex: %d", aRateIndex);
1735 			} else if (aRateIndex >= 1 && (tempRateSet.rate[min] ==
1736 				   pRates->llaRates[aRateIndex - 1])) {
1737 				pe_debug("Duplicate 11a rate: %d",
1738 					 tempRateSet.rate[min]);
1739 			} else {
1740 				pRates->llaRates[aRateIndex++] =
1741 						tempRateSet.rate[min];
1742 			}
1743 		} else if (sirIsBrate(tempRateSet.rate[min] & 0x7f)) {
1744 			if (bRateIndex >= SIR_NUM_11B_RATES) {
1745 				pe_debug("OOB, bRateIndex: %d", bRateIndex);
1746 			} else if (bRateIndex >= 1 && (tempRateSet.rate[min] ==
1747 				   pRates->llbRates[bRateIndex - 1])) {
1748 				pe_debug("Duplicate 11b rate: %d",
1749 					 tempRateSet.rate[min]);
1750 			} else {
1751 				pRates->llbRates[bRateIndex++] =
1752 						tempRateSet.rate[min];
1753 			}
1754 		} else {
1755 			pe_debug("%d is neither 11a nor 11b rate",
1756 				 tempRateSet.rate[min]);
1757 		}
1758 		tempRateSet.rate[min] = 0xff;
1759 	}
1760 
1761 	if (IS_DOT11_MODE_HT(pe_session->dot11mode) &&
1762 	    !lim_is_he_6ghz_band(pe_session)) {
1763 		val_len = SIZE_OF_SUPPORTED_MCS_SET;
1764 		if (wlan_mlme_get_cfg_str(
1765 			pRates->supportedMCSSet,
1766 			&mac->mlme_cfg->rates.supported_mcs_set,
1767 			&val_len) != QDF_STATUS_SUCCESS) {
1768 			pe_err("could not retrieve supportedMCSSet");
1769 			return QDF_STATUS_E_FAILURE;
1770 		}
1771 		if (pe_session->nss == NSS_1x1_MODE)
1772 			pRates->supportedMCSSet[1] = 0;
1773 
1774 		/* if supported MCS Set of the peer is passed in, then do the
1775 		 * intersection, else use the MCS set from local CFG.
1776 		 */
1777 		if (pSupportedMCSSet) {
1778 			for (i = 0; i < SIR_MAC_MAX_SUPPORTED_MCS_SET; i++)
1779 				pRates->supportedMCSSet[i] &=
1780 					pSupportedMCSSet[i];
1781 		}
1782 
1783 		lim_dump_ht_mcs_mask(NULL, pRates->supportedMCSSet);
1784 
1785 		if (pRates->supportedMCSSet[0] == 0) {
1786 			pe_debug("Incorrect MCS 0 - 7. They must be supported");
1787 			pRates->supportedMCSSet[0] = 0xFF;
1788 		}
1789 
1790 		pe_session->supported_nss_1x1 =
1791 			((pRates->supportedMCSSet[1] != 0) ? false : true);
1792 	}
1793 	lim_populate_vht_mcs_set(mac, pRates, pVHTCaps, pe_session,
1794 				 pe_session->nss, sta_ds);
1795 
1796 	if (lim_check_valid_mcs_for_nss(pe_session, he_caps)) {
1797 		peer_he_caps = he_caps;
1798 	} else {
1799 		if (!bss_desc) {
1800 			pe_err("bssDescription is NULL");
1801 			return QDF_STATUS_E_INVAL;
1802 		}
1803 		pBeaconStruct = qdf_mem_malloc(sizeof(tSchBeaconStruct));
1804 		if (!pBeaconStruct)
1805 			return QDF_STATUS_E_NOMEM;
1806 
1807 		lim_extract_ap_capabilities(
1808 				mac, (uint8_t *)bss_desc->ieFields,
1809 				lim_get_ielen_from_bss_description(bss_desc),
1810 				pBeaconStruct);
1811 		peer_he_caps = &pBeaconStruct->he_cap;
1812 	}
1813 
1814 	lim_populate_he_mcs_set(mac, pRates, peer_he_caps,
1815 			pe_session, pe_session->nss);
1816 	lim_populate_eht_mcs_set(mac, pRates, eht_caps,
1817 				 pe_session, pe_session->nss);
1818 
1819 	pe_debug("nss 1x1 %d nss %d", pe_session->supported_nss_1x1,
1820 		 pe_session->nss);
1821 
1822 	if (pBeaconStruct)
1823 		qdf_mem_free(pBeaconStruct);
1824 
1825 	return QDF_STATUS_SUCCESS;
1826 } /*** lim_populate_peer_rate_set() ***/
1827 
1828 /**
1829  * lim_populate_matching_rate_set() -process the CFG rate sets and
1830  *          the rate sets received in the Assoc request on AP.
1831  * @mac_ctx: pointer to global mac structure
1832  * @sta_ds: station node
1833  * @oper_rate_set: pointer to operating rate set
1834  * @ext_rate_set: pointer to extended rate set
1835  * @supported_mcs_set: pointer to supported rate set
1836  * @session_entry: pointer to pe session entry
1837  * @vht_caps: pointer to vht capabilities
1838  * @he_caps: pointer to he capabilities
1839  * @eht_caps: pointer to eht capabilities
1840  *
1841  * This is called at the time of Association Request
1842  * processing on AP and while adding peer's context
1843  * in IBSS role to process the CFG rate sets and
1844  * the rate sets received in the Assoc request on AP
1845  *
1846  * 1. It makes the intersection between our own rate set
1847  *    and extended rate set and the ones received in the
1848  *    association request.
1849  * 2. It creates a combined rate set of 12 rates max which
1850  *    comprised the basic and extended rates
1851  * 3. It sorts the combined rate Set and copy it in the
1852  *    rate array of the pSTA descriptor
1853  *
1854  * The parser has already ensured unicity of the rates in the
1855  * association request structure
1856  *
1857  * Return: QDF_STATUS_SUCCESS on success else QDF_STATUS_E_FAILURE
1858  */
1859 QDF_STATUS lim_populate_matching_rate_set(struct mac_context *mac_ctx,
1860 					  tpDphHashNode sta_ds,
1861 					  tSirMacRateSet *oper_rate_set,
1862 					  tSirMacRateSet *ext_rate_set,
1863 					  uint8_t *supported_mcs_set,
1864 					  struct pe_session *session_entry,
1865 					  tDot11fIEVHTCaps *vht_caps,
1866 					  tDot11fIEhe_cap *he_caps,
1867 					  tDot11fIEeht_cap *eht_caps)
1868 {
1869 	tSirMacRateSet temp_rate_set;
1870 	tSirMacRateSet temp_rate_set2 = {0};
1871 	uint32_t i, j, val, min, is_arate;
1872 	uint32_t phy_mode;
1873 	uint8_t mcs_set[SIZE_OF_SUPPORTED_MCS_SET];
1874 	struct supported_rates *rates;
1875 	uint8_t a_rate_index = 0;
1876 	uint8_t b_rate_index = 0;
1877 	qdf_size_t val_len;
1878 
1879 	is_arate = 0;
1880 
1881 	lim_get_phy_mode(mac_ctx, &phy_mode, session_entry);
1882 
1883 	/* copy operational rate set from session_entry */
1884 	qdf_mem_copy((temp_rate_set.rate), (session_entry->rateSet.rate),
1885 		     session_entry->rateSet.numRates);
1886 	temp_rate_set.numRates = (uint8_t) session_entry->rateSet.numRates;
1887 
1888 	if (phy_mode == WNI_CFG_PHY_MODE_11G) {
1889 		qdf_mem_copy((temp_rate_set2.rate),
1890 			     (session_entry->extRateSet.rate),
1891 			     session_entry->extRateSet.numRates);
1892 		temp_rate_set2.numRates =
1893 			(uint8_t) session_entry->extRateSet.numRates;
1894 	}
1895 
1896 	lim_remove_membership_selectors(&temp_rate_set);
1897 	lim_remove_membership_selectors(&temp_rate_set2);
1898 
1899 	/*
1900 	 * absolute sum of both num_rates should be less than 12. following
1901 	 * 16-bit sum avoids false condition where 8-bit arithmetic overflow
1902 	 * might have caused total sum to be less than 12
1903 	 */
1904 	if (((uint16_t)temp_rate_set.numRates +
1905 	    (uint16_t)temp_rate_set2.numRates) > SIR_MAC_MAX_NUMBER_OF_RATES) {
1906 		pe_err("more than 12 rates in CFG");
1907 		return QDF_STATUS_E_FAILURE;
1908 	}
1909 
1910 	/*
1911 	 * Handling of the rate set IEs is the following:
1912 	 * - keep only rates that we support and that the station supports
1913 	 * - sort and the rates into the pSta->rate array
1914 	 */
1915 
1916 	/* Copy all rates in temp_rate_set, there are 12 rates max */
1917 	for (i = 0; i < temp_rate_set2.numRates; i++)
1918 		temp_rate_set.rate[i + temp_rate_set.numRates] =
1919 			temp_rate_set2.rate[i];
1920 
1921 	temp_rate_set.numRates += temp_rate_set2.numRates;
1922 
1923 	/*
1924 	 * Sort rates in temp_rate_set (they are likely to be already sorted)
1925 	 * put the result in temp_rate_set2
1926 	 */
1927 	temp_rate_set2.numRates = 0;
1928 
1929 	for (i = 0; i < temp_rate_set.numRates; i++) {
1930 		min = 0;
1931 		val = 0xff;
1932 
1933 		for (j = 0; j < temp_rate_set.numRates; j++)
1934 			if ((uint32_t) (temp_rate_set.rate[j] & 0x7f) < val) {
1935 				val = temp_rate_set.rate[j] & 0x7f;
1936 				min = j;
1937 			}
1938 
1939 		temp_rate_set2.rate[temp_rate_set2.numRates++] =
1940 			temp_rate_set.rate[min];
1941 		temp_rate_set.rate[min] = 0xff;
1942 	}
1943 
1944 	/*
1945 	 * Copy received rates in temp_rate_set, the parser has ensured
1946 	 * unicity of the rates so there cannot be more than 12
1947 	 */
1948 	for (i = 0; (i < oper_rate_set->numRates &&
1949 			 i < SIR_MAC_MAX_NUMBER_OF_RATES); i++)
1950 		temp_rate_set.rate[i] = oper_rate_set->rate[i];
1951 
1952 	temp_rate_set.numRates = oper_rate_set->numRates;
1953 
1954 	pe_debug("Sum of SUPPORTED and EXTENDED Rate Set (%1d)",
1955 		temp_rate_set.numRates + ext_rate_set->numRates);
1956 
1957 	if (ext_rate_set->numRates &&
1958 		((temp_rate_set.numRates + ext_rate_set->numRates) > 12) &&
1959 		temp_rate_set.numRates < 12) {
1960 		int found = 0;
1961 		int tail = temp_rate_set.numRates;
1962 
1963 		for (i = 0; (i < ext_rate_set->numRates &&
1964 				i < SIR_MAC_MAX_NUMBER_OF_RATES); i++) {
1965 			found = 0;
1966 			for (j = 0; j < (uint32_t) tail; j++) {
1967 				if ((temp_rate_set.rate[j] & 0x7F) ==
1968 					(ext_rate_set->rate[i] & 0x7F)) {
1969 					found = 1;
1970 					break;
1971 				}
1972 			}
1973 
1974 			if (!found) {
1975 				temp_rate_set.rate[temp_rate_set.numRates++] =
1976 						ext_rate_set->rate[i];
1977 				if (temp_rate_set.numRates >= 12)
1978 					break;
1979 			}
1980 		}
1981 	} else if (ext_rate_set->numRates &&
1982 		 ((temp_rate_set.numRates + ext_rate_set->numRates) <= 12)) {
1983 		for (j = 0; ((j < ext_rate_set->numRates) &&
1984 				 (j < SIR_MAC_MAX_NUMBER_OF_RATES) &&
1985 				 ((i + j) < SIR_MAC_MAX_NUMBER_OF_RATES)); j++)
1986 			temp_rate_set.rate[i + j] = ext_rate_set->rate[j];
1987 
1988 		temp_rate_set.numRates += ext_rate_set->numRates;
1989 	} else if (ext_rate_set->numRates) {
1990 		pe_debug("Relying only on the SUPPORTED Rate Set IE");
1991 	}
1992 
1993 	rates = &sta_ds->supportedRates;
1994 	qdf_mem_zero(rates, sizeof(*rates));
1995 	for (i = 0; (i < temp_rate_set2.numRates &&
1996 			 i < SIR_MAC_MAX_NUMBER_OF_RATES); i++) {
1997 		for (j = 0; (j < temp_rate_set.numRates &&
1998 				 j < SIR_MAC_MAX_NUMBER_OF_RATES); j++) {
1999 			if ((temp_rate_set2.rate[i] & 0x7F) !=
2000 				(temp_rate_set.rate[j] & 0x7F))
2001 				continue;
2002 
2003 			if (sirIsArate(temp_rate_set2.rate[i] & 0x7f) &&
2004 				a_rate_index < SIR_NUM_11A_RATES) {
2005 				is_arate = 1;
2006 				rates->llaRates[a_rate_index++] =
2007 							temp_rate_set2.rate[i];
2008 			} else if ((b_rate_index < SIR_NUM_11B_RATES) &&
2009 				!(sirIsArate(temp_rate_set2.rate[i] & 0x7f))) {
2010 				rates->llbRates[b_rate_index++] =
2011 					temp_rate_set2.rate[i];
2012 			}
2013 			break;
2014 		}
2015 	}
2016 
2017 	/*
2018 	 * Now add the Polaris rates only when Proprietary rates are enabled.
2019 	 * compute the matching MCS rate set, if peer is 11n capable and self
2020 	 * mode is 11n
2021 	 */
2022 #ifdef FEATURE_WLAN_TDLS
2023 	if (sta_ds->mlmStaContext.htCapability)
2024 #else
2025 	if (IS_DOT11_MODE_HT(session_entry->dot11mode) &&
2026 		(sta_ds->mlmStaContext.htCapability))
2027 #endif
2028 	{
2029 		val_len = SIZE_OF_SUPPORTED_MCS_SET;
2030 		if (wlan_mlme_get_cfg_str(
2031 			mcs_set,
2032 			&mac_ctx->mlme_cfg->rates.supported_mcs_set,
2033 			&val_len) != QDF_STATUS_SUCCESS) {
2034 			pe_err("could not retrieve supportedMCSet");
2035 			return QDF_STATUS_E_FAILURE;
2036 		}
2037 
2038 		if (session_entry->nss == NSS_1x1_MODE)
2039 			mcs_set[1] = 0;
2040 
2041 		for (i = 0; i < val_len; i++)
2042 			sta_ds->supportedRates.supportedMCSSet[i] =
2043 				mcs_set[i] & supported_mcs_set[i];
2044 
2045 		lim_dump_ht_mcs_mask(mcs_set,
2046 				     sta_ds->supportedRates.supportedMCSSet);
2047 	}
2048 	lim_populate_vht_mcs_set(mac_ctx, &sta_ds->supportedRates, vht_caps,
2049 				 session_entry, session_entry->nss, sta_ds);
2050 	lim_populate_he_mcs_set(mac_ctx, &sta_ds->supportedRates, he_caps,
2051 				session_entry, session_entry->nss);
2052 	lim_populate_eht_mcs_set(mac_ctx, &sta_ds->supportedRates, eht_caps,
2053 				 session_entry, session_entry->nss);
2054 	/*
2055 	 * Set the erpEnabled bit if the phy is in G mode and at least
2056 	 * one A rate is supported
2057 	 */
2058 	if ((phy_mode == WNI_CFG_PHY_MODE_11G) && is_arate)
2059 		sta_ds->erpEnabled = eHAL_SET;
2060 
2061 	return QDF_STATUS_SUCCESS;
2062 }
2063 
2064 /**
2065  * lim_populate_vht_caps() - populates vht capabilities based on input
2066  *        capabilities
2067  * @input_caps: input capabilities based on which we format the vht
2068  *      capabilities
2069  *
2070  * function to populate the supported vht capabilities.
2071  *
2072  * Return: vht capabilities derived based on input parameters.
2073  */
2074 static uint32_t lim_populate_vht_caps(tDot11fIEVHTCaps input_caps)
2075 {
2076 	uint32_t vht_caps;
2077 
2078 	vht_caps = ((input_caps.maxMPDULen << SIR_MAC_VHT_CAP_MAX_MPDU_LEN) |
2079 			(input_caps.supportedChannelWidthSet <<
2080 				 SIR_MAC_VHT_CAP_SUPP_CH_WIDTH_SET) |
2081 			(input_caps.ldpcCodingCap <<
2082 				SIR_MAC_VHT_CAP_LDPC_CODING_CAP) |
2083 			(input_caps.shortGI80MHz <<
2084 				 SIR_MAC_VHT_CAP_SHORTGI_80MHZ) |
2085 			(input_caps.shortGI160and80plus80MHz <<
2086 				SIR_MAC_VHT_CAP_SHORTGI_160_80_80MHZ) |
2087 			(input_caps.txSTBC << SIR_MAC_VHT_CAP_TXSTBC) |
2088 			(input_caps.rxSTBC << SIR_MAC_VHT_CAP_RXSTBC) |
2089 			(input_caps.suBeamFormerCap <<
2090 				SIR_MAC_VHT_CAP_SU_BEAMFORMER_CAP) |
2091 			(input_caps.suBeamformeeCap <<
2092 				SIR_MAC_VHT_CAP_SU_BEAMFORMEE_CAP) |
2093 			(input_caps.csnofBeamformerAntSup <<
2094 				SIR_MAC_VHT_CAP_CSN_BEAMORMER_ANT_SUP) |
2095 			(input_caps.numSoundingDim <<
2096 				SIR_MAC_VHT_CAP_NUM_SOUNDING_DIM) |
2097 			(input_caps.muBeamformerCap <<
2098 				SIR_MAC_VHT_CAP_NUM_BEAM_FORMER_CAP) |
2099 			(input_caps.muBeamformeeCap <<
2100 				SIR_MAC_VHT_CAP_NUM_BEAM_FORMEE_CAP) |
2101 			(input_caps.vhtTXOPPS <<
2102 				SIR_MAC_VHT_CAP_TXOPPS) |
2103 			(input_caps.htcVHTCap <<
2104 				 SIR_MAC_VHT_CAP_HTC_CAP) |
2105 			(input_caps.maxAMPDULenExp <<
2106 				SIR_MAC_VHT_CAP_MAX_AMDU_LEN_EXPO) |
2107 			(input_caps.vhtLinkAdaptCap <<
2108 				SIR_MAC_VHT_CAP_LINK_ADAPT_CAP) |
2109 			(input_caps.rxAntPattern <<
2110 				SIR_MAC_VHT_CAP_RX_ANTENNA_PATTERN) |
2111 			(input_caps.txAntPattern <<
2112 				SIR_MAC_VHT_CAP_TX_ANTENNA_PATTERN) |
2113 			(input_caps.extended_nss_bw_supp <<
2114 				SIR_MAC_VHT_CAP_EXTD_NSS_BW));
2115 
2116 	return vht_caps;
2117 }
2118 
2119 /**
2120  * lim_update_he_stbc_capable() - Update stbc capable flag based on
2121  * HE capability
2122  * @add_sta_params: add sta related parameters
2123  *
2124  * Update stbc cpable flag based on HE capability
2125  *
2126  * Return: None
2127  */
2128 #ifdef WLAN_FEATURE_11AX
2129 static void lim_update_he_stbc_capable(tpAddStaParams add_sta_params)
2130 {
2131 	if (add_sta_params &&
2132 	    add_sta_params->he_capable &&
2133 	    add_sta_params->stbc_capable)
2134 		add_sta_params->stbc_capable =
2135 			add_sta_params->he_config.rx_stbc_lt_80mhz;
2136 }
2137 
2138 static void lim_update_he_mcs_12_13(tpAddStaParams add_sta_params,
2139 				    tpDphHashNode sta_ds)
2140 {
2141 	pe_debug("he_mcs_12_13_map %0x", sta_ds->he_mcs_12_13_map);
2142 	if (sta_ds->he_mcs_12_13_map)
2143 		add_sta_params->he_mcs_12_13_map = sta_ds->he_mcs_12_13_map;
2144 }
2145 
2146 static bool lim_is_add_sta_params_he_capable(tpAddStaParams add_sta_params)
2147 {
2148 	return add_sta_params->he_capable;
2149 }
2150 #else
2151 static void lim_update_he_stbc_capable(tpAddStaParams add_sta_params)
2152 {}
2153 
2154 static void lim_update_he_mcs_12_13(tpAddStaParams add_sta_params,
2155 				    tpDphHashNode sta_ds)
2156 {}
2157 
2158 static bool lim_is_add_sta_params_he_capable(tpAddStaParams add_sta_params)
2159 {
2160 	return false;
2161 }
2162 #endif
2163 
2164 #ifdef FEATURE_WLAN_TDLS
2165 #ifdef WLAN_FEATURE_11BE
2166 static void lim_add_tdls_sta_eht_config(tpAddStaParams add_sta_params,
2167 					tpDphHashNode sta_ds)
2168 {
2169 	if (add_sta_params->eht_capable) {
2170 		pe_debug("Adding tdls eht capabilities");
2171 		qdf_mem_copy(&add_sta_params->eht_config, &sta_ds->eht_config,
2172 			     sizeof(add_sta_params->eht_config));
2173 		qdf_mem_copy(&add_sta_params->eht_op, &sta_ds->eht_op,
2174 			     sizeof(add_sta_params->eht_op));
2175 	}
2176 }
2177 #else
2178 static void lim_add_tdls_sta_eht_config(tpAddStaParams add_sta_params,
2179 					tpDphHashNode sta_ds)
2180 {
2181 }
2182 
2183 #endif
2184 #ifdef WLAN_FEATURE_11AX
2185 static void lim_add_tdls_sta_he_config(tpAddStaParams add_sta_params,
2186 				       tpDphHashNode sta_ds)
2187 {
2188 	pe_debug("Adding tdls he capabilities");
2189 	qdf_mem_copy(&add_sta_params->he_config, &sta_ds->he_config,
2190 		     sizeof(add_sta_params->he_config));
2191 }
2192 
2193 static void lim_add_tdls_sta_6ghz_he_cap(struct mac_context *mac_ctx,
2194 					 tpAddStaParams add_sta_params,
2195 					 tpDphHashNode sta_ds)
2196 {
2197 	lim_update_he_6ghz_band_caps(mac_ctx, &sta_ds->he_6g_band_cap,
2198 				     add_sta_params);
2199 }
2200 
2201 #else
2202 static void lim_add_tdls_sta_he_config(tpAddStaParams add_sta_params,
2203 				       tpDphHashNode sta_ds)
2204 {
2205 }
2206 
2207 static void lim_add_tdls_sta_6ghz_he_cap(struct mac_context *mac_ctx,
2208 					 tpAddStaParams add_sta_params,
2209 					 tpDphHashNode sta_ds)
2210 {
2211 }
2212 #endif /* WLAN_FEATURE_11AX */
2213 #endif /* FEATURE_WLAN_TDLS */
2214 
2215 #ifdef WLAN_FEATURE_11BE
2216 static bool lim_is_add_sta_params_eht_capable(tpAddStaParams add_sta_params)
2217 {
2218 	return add_sta_params->eht_capable;
2219 }
2220 
2221 static bool lim_is_eht_connection_op_info_present(struct pe_session *pe_session,
2222 						  tpSirAssocRsp assoc_rsp)
2223 {
2224 	if (IS_DOT11_MODE_EHT(pe_session->dot11mode) &&
2225 	    assoc_rsp->eht_op.present &&
2226 	    assoc_rsp->eht_op.eht_op_information_present)
2227 		return true;
2228 
2229 	return false;
2230 }
2231 #else
2232 static bool lim_is_add_sta_params_eht_capable(tpAddStaParams add_sta_params)
2233 {
2234 	return false;
2235 }
2236 
2237 static bool lim_is_eht_connection_op_info_present(struct pe_session *pe_session,
2238 						  tpSirAssocRsp assoc_rsp)
2239 {
2240 	return false;
2241 }
2242 #endif
2243 
2244 #ifdef WLAN_SUPPORT_TWT
2245 /**
2246  * lim_update_peer_twt_caps() - Update peer twt caps to add sta params
2247  * @add_sta_params: pointer to add sta params
2248  * @session_entry: pe session entry
2249  *
2250  * Return: None
2251  */
2252 static void lim_update_peer_twt_caps(tpAddStaParams add_sta_params,
2253 				    struct pe_session *session_entry)
2254 {
2255 	add_sta_params->twt_requestor = session_entry->peer_twt_requestor;
2256 	add_sta_params->twt_responder = session_entry->peer_twt_responder;
2257 }
2258 #else
2259 static inline void
2260 lim_update_peer_twt_caps(tpAddStaParams add_sta_params,
2261 			     struct pe_session *session_entry)
2262 {}
2263 #endif
2264 
2265 #ifdef WLAN_FEATURE_SR
2266 /**
2267  * lim_update_srp_ie() - Updates SRP IE to STA node
2268  * @bp_rsp: pointer to probe response / beacon frame
2269  * @sta_ds: STA Node
2270  *
2271  * Return: QDF_STATUS
2272  */
2273 static QDF_STATUS lim_update_srp_ie(tSirProbeRespBeacon *bp_rsp,
2274 				    tpDphHashNode sta_ds)
2275 {
2276 	QDF_STATUS status = QDF_STATUS_E_NOSUPPORT;
2277 
2278 	if (bp_rsp->srp_ie.present) {
2279 		sta_ds->parsed_ies.srp_ie = bp_rsp->srp_ie;
2280 		status = QDF_STATUS_SUCCESS;
2281 	}
2282 
2283 	return status;
2284 }
2285 #else
2286 static QDF_STATUS lim_update_srp_ie(tSirProbeRespBeacon *bp_rsp,
2287 				    tpDphHashNode sta_ds)
2288 {
2289 	return QDF_STATUS_SUCCESS;
2290 }
2291 #endif
2292 
2293 /**
2294  * lim_add_sta()- called to add an STA context at hardware
2295  * @mac_ctx: pointer to global mac structure
2296  * @sta_ds: station node
2297  * @update_entry: set to true for updating the entry
2298  * @session_entry: pe session entry
2299  *
2300  * This function is called to add an STA context at hardware
2301  * whenever a STA is (Re) Associated.
2302  *
2303  * Return: QDF_STATUS_SUCCESS on success else QDF_STATUS failure codes
2304  */
2305 
2306 QDF_STATUS
2307 lim_add_sta(struct mac_context *mac_ctx,
2308 	tpDphHashNode sta_ds, uint8_t update_entry, struct pe_session *session_entry)
2309 {
2310 	tpAddStaParams add_sta_params = NULL;
2311 	struct scheduler_msg msg_q = {0};
2312 	QDF_STATUS ret_code = QDF_STATUS_SUCCESS;
2313 	tSirMacAddr sta_mac, *sta_Addr;
2314 	tpSirAssocReq assoc_req;
2315 	uint8_t i, nw_type_11b = 0;
2316 	const uint8_t *p2p_ie = NULL;
2317 	tDot11fIEVHTCaps vht_caps;
2318 	struct mlme_vht_capabilities_info *vht_cap_info;
2319 
2320 	vht_cap_info = &mac_ctx->mlme_cfg->vht_caps.vht_cap_info;
2321 
2322 	sir_copy_mac_addr(sta_mac, session_entry->self_mac_addr);
2323 
2324 	add_sta_params = qdf_mem_malloc(sizeof(tAddStaParams));
2325 	if (!add_sta_params)
2326 		return QDF_STATUS_E_NOMEM;
2327 
2328 	if (LIM_IS_AP_ROLE(session_entry) || LIM_IS_NDI_ROLE(session_entry))
2329 		sta_Addr = &sta_ds->staAddr;
2330 #ifdef FEATURE_WLAN_TDLS
2331 	/* SystemRole shouldn't be matter if staType is TDLS peer */
2332 	else if (STA_ENTRY_TDLS_PEER == sta_ds->staType)
2333 		sta_Addr = &sta_ds->staAddr;
2334 #endif
2335 	else
2336 		sta_Addr = &sta_mac;
2337 
2338 	qdf_mem_copy((uint8_t *) add_sta_params->staMac,
2339 		     (uint8_t *) *sta_Addr, sizeof(tSirMacAddr));
2340 	qdf_mem_copy((uint8_t *) add_sta_params->bssId,
2341 		     session_entry->bssId, sizeof(tSirMacAddr));
2342 	qdf_mem_copy(&add_sta_params->capab_info,
2343 		     &sta_ds->mlmStaContext.capabilityInfo,
2344 		     sizeof(add_sta_params->capab_info));
2345 
2346 	/* Copy legacy rates */
2347 	qdf_mem_copy(&add_sta_params->supportedRates,
2348 		     &sta_ds->supportedRates,
2349 		     sizeof(sta_ds->supportedRates));
2350 
2351 	add_sta_params->assocId = sta_ds->assocId;
2352 
2353 	add_sta_params->wmmEnabled = sta_ds->qosMode;
2354 	add_sta_params->listenInterval = sta_ds->mlmStaContext.listenInterval;
2355 	if (LIM_IS_AP_ROLE(session_entry) &&
2356 	   (sta_ds->mlmStaContext.subType == LIM_REASSOC)) {
2357 		/*
2358 		 * TBD - need to remove this REASSOC check
2359 		 * after fixinf rmmod issue
2360 		 */
2361 		add_sta_params->updateSta = sta_ds->mlmStaContext.updateContext;
2362 	}
2363 	sta_ds->valid = 0;
2364 	sta_ds->mlmStaContext.mlmState = eLIM_MLM_WT_ADD_STA_RSP_STATE;
2365 	add_sta_params->staType = sta_ds->staType;
2366 
2367 	add_sta_params->updateSta = update_entry;
2368 
2369 	add_sta_params->status = QDF_STATUS_SUCCESS;
2370 
2371 	/* Update VHT/HT Capability */
2372 	if (LIM_IS_AP_ROLE(session_entry)) {
2373 		add_sta_params->htCapable =
2374 			sta_ds->mlmStaContext.htCapability &&
2375 			session_entry->htCapability;
2376 		add_sta_params->vhtCapable =
2377 			 sta_ds->mlmStaContext.vhtCapability &&
2378 			 session_entry->vhtCapability;
2379 	}
2380 #ifdef FEATURE_WLAN_TDLS
2381 	/* SystemRole shouldn't be matter if staType is TDLS peer */
2382 	else if (STA_ENTRY_TDLS_PEER == sta_ds->staType) {
2383 		add_sta_params->htCapable = sta_ds->mlmStaContext.htCapability;
2384 		add_sta_params->vhtCapable =
2385 			 sta_ds->mlmStaContext.vhtCapability;
2386 	}
2387 #endif
2388 	else {
2389 		add_sta_params->htCapable = session_entry->htCapability;
2390 		add_sta_params->vhtCapable = session_entry->vhtCapability;
2391 	}
2392 
2393 	/*
2394 	 * If HT client is connected to SAP DUT and self cap is NSS = 2 then
2395 	 * disable ASYNC DBS scan by sending wmi_vdev_param_smps_intolerant
2396 	 * to FW, because HT client's can't drop down chain using SMPS frames.
2397 	 */
2398 	if (!policy_mgr_is_hw_dbs_2x2_capable(mac_ctx->psoc) &&
2399 		LIM_IS_AP_ROLE(session_entry) &&
2400 		(STA_ENTRY_PEER == sta_ds->staType) &&
2401 		!add_sta_params->vhtCapable &&
2402 		(session_entry->nss == 2)) {
2403 		session_entry->ht_client_cnt++;
2404 		if (session_entry->ht_client_cnt == 1) {
2405 			wma_cli_set_command(session_entry->smeSessionId,
2406 				(int)wmi_vdev_param_smps_intolerant,
2407 				1, VDEV_CMD);
2408 		}
2409 	}
2410 
2411 	lim_update_sta_he_capable(mac_ctx, add_sta_params, sta_ds,
2412 				  session_entry);
2413 
2414 	lim_update_sta_eht_capable(mac_ctx, add_sta_params, sta_ds,
2415 				   session_entry);
2416 
2417 	lim_update_tdls_sta_eht_capable(mac_ctx, add_sta_params, sta_ds,
2418 					session_entry);
2419 
2420 	lim_update_sta_mlo_info(session_entry, add_sta_params, sta_ds);
2421 
2422 	add_sta_params->maxAmpduDensity = sta_ds->htAMpduDensity;
2423 	add_sta_params->maxAmpduSize = sta_ds->htMaxRxAMpduFactor;
2424 	add_sta_params->fShortGI20Mhz = sta_ds->htShortGI20Mhz;
2425 	add_sta_params->fShortGI40Mhz = sta_ds->htShortGI40Mhz;
2426 	add_sta_params->ch_width = sta_ds->ch_width;
2427 	add_sta_params->mimoPS = sta_ds->htMIMOPSState;
2428 
2429 	if (add_sta_params->vhtCapable) {
2430 		if (sta_ds->vhtSupportedChannelWidthSet)
2431 			add_sta_params->ch_width =
2432 				sta_ds->vhtSupportedChannelWidthSet + 1;
2433 
2434 		add_sta_params->vhtSupportedRxNss = sta_ds->vhtSupportedRxNss;
2435 		if (LIM_IS_AP_ROLE(session_entry) ||
2436 				LIM_IS_P2P_DEVICE_GO(session_entry))
2437 			add_sta_params->vhtSupportedRxNss = QDF_MIN(
2438 					add_sta_params->vhtSupportedRxNss,
2439 					session_entry->nss);
2440 		add_sta_params->vhtTxBFCapable =
2441 #ifdef FEATURE_WLAN_TDLS
2442 			((STA_ENTRY_PEER == sta_ds->staType)
2443 			 || (STA_ENTRY_TDLS_PEER == sta_ds->staType)) ?
2444 				 sta_ds->vhtBeamFormerCapable :
2445 				 session_entry->vht_config.su_beam_formee;
2446 #else
2447 			(STA_ENTRY_PEER == sta_ds->staType) ?
2448 				 sta_ds->vhtBeamFormerCapable :
2449 				 session_entry->vht_config.su_beam_formee;
2450 #endif
2451 		add_sta_params->enable_su_tx_bformer =
2452 			sta_ds->vht_su_bfee_capable;
2453 		add_sta_params->vht_mcs_10_11_supp =
2454 			sta_ds->vht_mcs_10_11_supp;
2455 	}
2456 
2457 #ifdef FEATURE_WLAN_TDLS
2458 	if ((STA_ENTRY_PEER == sta_ds->staType) ||
2459 		(STA_ENTRY_TDLS_PEER == sta_ds->staType))
2460 #else
2461 	if (STA_ENTRY_PEER == sta_ds->staType)
2462 #endif
2463 	{
2464 		/*
2465 		 * peer STA get the LDPC capability from sta_ds,
2466 		 * which populated from
2467 		 * HT/VHT capability
2468 		 */
2469 		if (add_sta_params->vhtTxBFCapable
2470 		    && vht_cap_info->disable_ldpc_with_txbf_ap) {
2471 			add_sta_params->htLdpcCapable = 0;
2472 			add_sta_params->vhtLdpcCapable = 0;
2473 		} else {
2474 			if (session_entry->txLdpcIniFeatureEnabled & 0x1)
2475 				add_sta_params->htLdpcCapable =
2476 						sta_ds->htLdpcCapable;
2477 			else
2478 				add_sta_params->htLdpcCapable = 0;
2479 
2480 			if (session_entry->txLdpcIniFeatureEnabled & 0x2)
2481 				add_sta_params->vhtLdpcCapable =
2482 						sta_ds->vhtLdpcCapable;
2483 			else
2484 				add_sta_params->vhtLdpcCapable = 0;
2485 		}
2486 	} else if (STA_ENTRY_SELF == sta_ds->staType) {
2487 		/* For Self STA get the LDPC capability from config.ini */
2488 		add_sta_params->htLdpcCapable =
2489 			(session_entry->txLdpcIniFeatureEnabled & 0x01);
2490 		add_sta_params->vhtLdpcCapable =
2491 			((session_entry->txLdpcIniFeatureEnabled >> 1) & 0x01);
2492 	}
2493 
2494 	/* Update PE session ID */
2495 	add_sta_params->sessionId = session_entry->peSessionId;
2496 
2497 	/* Update SME session ID */
2498 	add_sta_params->smesessionId = session_entry->smeSessionId;
2499 
2500 	add_sta_params->maxTxPower = session_entry->maxTxPower;
2501 
2502 	if (session_entry->parsedAssocReq) {
2503 		uint16_t aid = sta_ds->assocId;
2504 		/* Get a copy of the already parsed Assoc Request */
2505 		assoc_req =
2506 			(tpSirAssocReq) session_entry->parsedAssocReq[aid];
2507 		if (assoc_req && assoc_req->addIEPresent
2508 		    && assoc_req->addIE.length) {
2509 			p2p_ie = limGetP2pIEPtr(mac_ctx,
2510 					assoc_req->addIE.addIEdata,
2511 					assoc_req->addIE.length);
2512 		}
2513 
2514 		add_sta_params->p2pCapableSta = (p2p_ie != NULL);
2515 		if (assoc_req && add_sta_params->htCapable) {
2516 			qdf_mem_copy(&add_sta_params->ht_caps,
2517 				     ((uint8_t *) &assoc_req->HTCaps) + 1,
2518 				     sizeof(add_sta_params->ht_caps));
2519 		}
2520 
2521 		if (assoc_req && add_sta_params->vhtCapable) {
2522 			if (assoc_req->vendor_vht_ie.VHTCaps.present)
2523 				vht_caps = assoc_req->vendor_vht_ie.VHTCaps;
2524 			else
2525 				vht_caps = assoc_req->VHTCaps;
2526 			add_sta_params->vht_caps =
2527 				lim_populate_vht_caps(vht_caps);
2528 		}
2529 
2530 		lim_add_he_cap(mac_ctx, session_entry,
2531 			       add_sta_params, assoc_req);
2532 
2533 		lim_add_eht_cap(mac_ctx, session_entry, add_sta_params,
2534 				assoc_req);
2535 
2536 	}
2537 
2538 #ifdef FEATURE_WLAN_TDLS
2539 	if (STA_ENTRY_TDLS_PEER == sta_ds->staType) {
2540 		add_sta_params->ht_caps = sta_ds->ht_caps;
2541 		add_sta_params->vht_caps = sta_ds->vht_caps;
2542 		if (add_sta_params->vhtCapable) {
2543 			add_sta_params->maxAmpduSize =
2544 				SIR_MAC_GET_VHT_MAX_AMPDU_EXPO(
2545 						sta_ds->vht_caps);
2546 		}
2547 		lim_add_tdls_sta_he_config(add_sta_params, sta_ds);
2548 
2549 		if (lim_is_he_6ghz_band(session_entry))
2550 			lim_add_tdls_sta_6ghz_he_cap(mac_ctx, add_sta_params,
2551 						     sta_ds);
2552 		lim_add_tdls_sta_eht_config(add_sta_params, sta_ds);
2553 	}
2554 #endif
2555 
2556 #ifdef FEATURE_WLAN_TDLS
2557 	if (sta_ds->wmeEnabled &&
2558 	   (LIM_IS_AP_ROLE(session_entry) ||
2559 	   (STA_ENTRY_TDLS_PEER == sta_ds->staType)))
2560 #else
2561 	if (sta_ds->wmeEnabled && LIM_IS_AP_ROLE(session_entry))
2562 #endif
2563 	{
2564 		add_sta_params->uAPSD = 0;
2565 		/*
2566 		 * update UAPSD and send it to LIM to add STA
2567 		 * bitmap MSB <- LSB MSB 4 bits are for
2568 		 * trigger enabled AC setting and LSB 4 bits
2569 		 * are for delivery enabled AC setting
2570 		 * 7   6    5    4    3    2    1    0
2571 		 * BE  BK   VI   VO   BE   BK   VI   VO
2572 		 */
2573 		add_sta_params->uAPSD |=
2574 			sta_ds->qos.capability.qosInfo.acvo_uapsd;
2575 		add_sta_params->uAPSD |=
2576 			(sta_ds->qos.capability.qosInfo.acvi_uapsd << 1);
2577 		add_sta_params->uAPSD |=
2578 			(sta_ds->qos.capability.qosInfo.acbk_uapsd << 2);
2579 		add_sta_params->uAPSD |=
2580 			(sta_ds->qos.capability.qosInfo.acbe_uapsd << 3);
2581 		/*
2582 		 * making delivery enabled and
2583 		 * trigger enabled setting the same.
2584 		 */
2585 		add_sta_params->uAPSD |= add_sta_params->uAPSD << 4;
2586 
2587 		add_sta_params->maxSPLen =
2588 			sta_ds->qos.capability.qosInfo.maxSpLen;
2589 	}
2590 	add_sta_params->rmfEnabled = sta_ds->rmfEnabled;
2591 
2592 	if (!add_sta_params->htLdpcCapable)
2593 		add_sta_params->ht_caps &= ~(1 << SIR_MAC_HT_CAP_ADVCODING_S);
2594 	if (!add_sta_params->vhtLdpcCapable)
2595 		add_sta_params->vht_caps &=
2596 			~(1 << SIR_MAC_VHT_CAP_LDPC_CODING_CAP);
2597 
2598 	/*
2599 	 * we need to defer the message until we get the
2600 	 * response back from HAL.
2601 	 */
2602 	SET_LIM_PROCESS_DEFD_MESGS(mac_ctx, false);
2603 
2604 	add_sta_params->nwType = session_entry->nwType;
2605 
2606 	if (!(add_sta_params->htCapable || add_sta_params->vhtCapable ||
2607 	    lim_is_add_sta_params_he_capable(add_sta_params) ||
2608 	    lim_is_add_sta_params_eht_capable(add_sta_params))) {
2609 		nw_type_11b = 1;
2610 		for (i = 0; i < SIR_NUM_11A_RATES; i++) {
2611 			if (sirIsArate(sta_ds->supportedRates.llaRates[i] &
2612 						0x7F)) {
2613 				nw_type_11b = 0;
2614 				break;
2615 			}
2616 		}
2617 		if (nw_type_11b)
2618 			add_sta_params->nwType = eSIR_11B_NW_TYPE;
2619 	}
2620 
2621 	if (add_sta_params->htCapable && session_entry->ht_config.tx_stbc) {
2622 		struct sDot11fIEHTCaps *ht_caps = (struct sDot11fIEHTCaps *)
2623 			&add_sta_params->ht_caps;
2624 		if (ht_caps->rxSTBC)
2625 			add_sta_params->stbc_capable = 1;
2626 		else
2627 			add_sta_params->stbc_capable = 0;
2628 	}
2629 
2630 	if (add_sta_params->vhtCapable && add_sta_params->stbc_capable) {
2631 		struct sDot11fIEVHTCaps *vht_caps = (struct sDot11fIEVHTCaps *)
2632 			&add_sta_params->vht_caps;
2633 		if (vht_caps->rxSTBC)
2634 			add_sta_params->stbc_capable = 1;
2635 		else
2636 			add_sta_params->stbc_capable = 0;
2637 	}
2638 
2639 	if (session_entry->opmode == QDF_SAP_MODE ||
2640 	    session_entry->opmode == QDF_P2P_GO_MODE) {
2641 		if (session_entry->parsedAssocReq) {
2642 			uint16_t aid = sta_ds->assocId;
2643 			/* Get a copy of the already parsed Assoc Request */
2644 			assoc_req =
2645 			(tpSirAssocReq) session_entry->parsedAssocReq[aid];
2646 
2647 			if (assoc_req) {
2648 				add_sta_params->wpa_rsn = assoc_req->rsnPresent;
2649 				add_sta_params->wpa_rsn |=
2650 					(assoc_req->wpaPresent << 1);
2651 			}
2652 		}
2653 	}
2654 
2655 	lim_update_he_stbc_capable(add_sta_params);
2656 	lim_update_he_mcs_12_13(add_sta_params, sta_ds);
2657 
2658 	/* Send peer twt req and res bit during peer assoc command */
2659 	lim_update_peer_twt_caps(add_sta_params, session_entry);
2660 
2661 	msg_q.type = WMA_ADD_STA_REQ;
2662 	msg_q.reserved = 0;
2663 	msg_q.bodyptr = add_sta_params;
2664 	msg_q.bodyval = 0;
2665 
2666 	pe_debug("vdev %d: " QDF_MAC_ADDR_FMT " opmode %d sta_type %d subtype %d: update %d aid %d wmm %d li %d ht %d vht %d ht client %d",
2667 		 session_entry->vdev_id,
2668 		 QDF_MAC_ADDR_REF(add_sta_params->staMac),
2669 		 session_entry->opmode, sta_ds->staType,
2670 		 sta_ds->mlmStaContext.subType, add_sta_params->updateSta,
2671 		 add_sta_params->assocId, add_sta_params->wmmEnabled,
2672 		 add_sta_params->listenInterval, add_sta_params->htCapable,
2673 		 add_sta_params->vhtCapable, session_entry->ht_client_cnt);
2674 	pe_nofl_debug("max_ampdu: density %d size %d, width %d sgi20 %d sgi40 %d mimops %d txbf %d subfer %d vht_mcs11 %d uapsd %d "
2675 		      "max splen %d pmf %d ht ldpc %d vht ldpc %d isp2p %d",
2676 		      add_sta_params->maxAmpduDensity,
2677 		      add_sta_params->maxAmpduSize, add_sta_params->ch_width,
2678 		      add_sta_params->fShortGI20Mhz,
2679 		      add_sta_params->fShortGI40Mhz,
2680 		      add_sta_params->mimoPS, add_sta_params->vhtTxBFCapable,
2681 		      add_sta_params->enable_su_tx_bformer,
2682 		      add_sta_params->vht_mcs_10_11_supp, add_sta_params->uAPSD,
2683 		      add_sta_params->maxSPLen, add_sta_params->rmfEnabled,
2684 		      add_sta_params->htLdpcCapable,
2685 		      add_sta_params->vhtLdpcCapable,
2686 		      add_sta_params->p2pCapableSta);
2687 
2688 	MTRACE(mac_trace_msg_tx(mac_ctx, session_entry->peSessionId,
2689 			 msg_q.type));
2690 
2691 	ret_code = wma_post_ctrl_msg(mac_ctx, &msg_q);
2692 	if (QDF_STATUS_SUCCESS != ret_code) {
2693 		SET_LIM_PROCESS_DEFD_MESGS(mac_ctx, true);
2694 		pe_err("ADD_STA_REQ for aId %d failed (reason %X)",
2695 			sta_ds->assocId, ret_code);
2696 		qdf_mem_free(add_sta_params);
2697 	}
2698 
2699 	return ret_code;
2700 }
2701 
2702 /**
2703  * lim_del_sta()
2704  *
2705  ***FUNCTION:
2706  * This function is called to delete an STA context at hardware
2707  * whenever a STA is disassociated
2708  *
2709  ***LOGIC:
2710  *
2711  ***ASSUMPTIONS:
2712  * NA
2713  *
2714  ***NOTE:
2715  * NA
2716  *
2717  * @param  mac    - Pointer to Global MAC structure
2718  * @param  sta  - Pointer to the STA datastructure created by
2719  *                   LIM and maintained by DPH
2720  * @param  fRespReqd - flag to indicate whether the delete is synchronous (true)
2721  *                   or not (false)
2722  * @return retCode - Indicates success or failure return code
2723  */
2724 
2725 QDF_STATUS
2726 lim_del_sta(struct mac_context *mac,
2727 	    tpDphHashNode sta, bool fRespReqd, struct pe_session *pe_session)
2728 {
2729 	tpDeleteStaParams pDelStaParams = NULL;
2730 	struct scheduler_msg msgQ = {0};
2731 	QDF_STATUS retCode = QDF_STATUS_SUCCESS;
2732 
2733 	pDelStaParams = qdf_mem_malloc(sizeof(tDeleteStaParams));
2734 	if (!pDelStaParams)
2735 		return QDF_STATUS_E_NOMEM;
2736 
2737 	/*
2738 	 * 2G-AS platform: SAP associates with HT (11n)clients as 2x1 in 2G and
2739 	 * 2X2 in 5G
2740 	 * Non-2G-AS platform: SAP associates with HT (11n) clients as 2X2 in 2G
2741 	 * and 5G; and enable async dbs scan when all HT clients are gone
2742 	 * 5G-AS: Don't care
2743 	 */
2744 	if (!policy_mgr_is_hw_dbs_2x2_capable(mac->psoc) &&
2745 		LIM_IS_AP_ROLE(pe_session) &&
2746 		(sta->staType == STA_ENTRY_PEER) &&
2747 		!sta->mlmStaContext.vhtCapability &&
2748 		(pe_session->nss == 2)) {
2749 		pe_session->ht_client_cnt--;
2750 		if (pe_session->ht_client_cnt == 0) {
2751 			pe_debug("clearing SMPS intolrent vdev_param");
2752 			wma_cli_set_command(pe_session->smeSessionId,
2753 				(int)wmi_vdev_param_smps_intolerant,
2754 				0, VDEV_CMD);
2755 		}
2756 	}
2757 
2758 	pDelStaParams->assocId = sta->assocId;
2759 	sta->valid = 0;
2760 
2761 	if (!fRespReqd)
2762 		pDelStaParams->respReqd = 0;
2763 	else {
2764 		if (!(IS_TDLS_PEER(sta->staType))) {
2765 			/* when lim_del_sta is called from processSmeAssocCnf
2766 			 * then mlmState is already set properly. */
2767 			if (eLIM_MLM_WT_ASSOC_DEL_STA_RSP_STATE !=
2768 				GET_LIM_STA_CONTEXT_MLM_STATE(sta)) {
2769 				MTRACE(mac_trace
2770 					(mac, TRACE_CODE_MLM_STATE,
2771 					 pe_session->peSessionId,
2772 					 eLIM_MLM_WT_DEL_STA_RSP_STATE));
2773 				SET_LIM_STA_CONTEXT_MLM_STATE(sta,
2774 					eLIM_MLM_WT_DEL_STA_RSP_STATE);
2775 			}
2776 			if (LIM_IS_STA_ROLE(pe_session)) {
2777 				MTRACE(mac_trace
2778 					(mac, TRACE_CODE_MLM_STATE,
2779 					 pe_session->peSessionId,
2780 					 eLIM_MLM_WT_DEL_STA_RSP_STATE));
2781 
2782 				pe_session->limMlmState =
2783 					eLIM_MLM_WT_DEL_STA_RSP_STATE;
2784 
2785 			}
2786 		}
2787 
2788 		/* we need to defer the message until we get the
2789 		 * response back from HAL. */
2790 		SET_LIM_PROCESS_DEFD_MESGS(mac, false);
2791 
2792 		pDelStaParams->respReqd = 1;
2793 	}
2794 
2795 	/* notify mlo peer to detach reference of the
2796 	 * link peer before post WMA_DELETE_STA_REQ, which will free
2797 	 * wlan_objmgr_peer of the link peer
2798 	 */
2799 	lim_mlo_notify_peer_disconn(pe_session, sta);
2800 	lim_mlo_delete_link_peer(pe_session, sta);
2801 	/* Update PE session ID */
2802 	pDelStaParams->sessionId = pe_session->peSessionId;
2803 	pDelStaParams->smesessionId = pe_session->smeSessionId;
2804 
2805 	pDelStaParams->staType = sta->staType;
2806 	qdf_mem_copy((uint8_t *) pDelStaParams->staMac,
2807 		     (uint8_t *) sta->staAddr, sizeof(tSirMacAddr));
2808 
2809 	pDelStaParams->status = QDF_STATUS_SUCCESS;
2810 	msgQ.type = WMA_DELETE_STA_REQ;
2811 	msgQ.reserved = 0;
2812 	msgQ.bodyptr = pDelStaParams;
2813 	msgQ.bodyval = 0;
2814 
2815 	pe_debug("Sessionid %d :Sending SIR_HAL_DELETE_STA_REQ "
2816 		 "for mac_addr "QDF_MAC_ADDR_FMT" and AssocID: %d MAC : "
2817 		 QDF_MAC_ADDR_FMT, pDelStaParams->sessionId,
2818 		 QDF_MAC_ADDR_REF(pDelStaParams->staMac),
2819 		 pDelStaParams->assocId,
2820 		 QDF_MAC_ADDR_REF(sta->staAddr));
2821 
2822 	MTRACE(mac_trace_msg_tx(mac, pe_session->peSessionId, msgQ.type));
2823 	retCode = wma_post_ctrl_msg(mac, &msgQ);
2824 	if (QDF_STATUS_SUCCESS != retCode) {
2825 		if (fRespReqd)
2826 			SET_LIM_PROCESS_DEFD_MESGS(mac, true);
2827 		pe_err("Posting DELETE_STA_REQ to HAL failed, reason=%X",
2828 			retCode);
2829 		qdf_mem_free(pDelStaParams);
2830 	}
2831 
2832 	return retCode;
2833 }
2834 
2835 /**
2836  * lim_set_mbssid_info() - Save mbssid info
2837  * @pe_session: pe session entry
2838  *
2839  * Return: None
2840  */
2841 static void lim_set_mbssid_info(struct pe_session *pe_session)
2842 {
2843 	struct scan_mbssid_info *mbssid_info;
2844 
2845 	if (!pe_session->lim_join_req && !pe_session->pLimReAssocReq)
2846 		return;
2847 
2848 	if (pe_session->lim_join_req)
2849 		mbssid_info =
2850 			&pe_session->lim_join_req->bssDescription.mbssid_info;
2851 	else
2852 		mbssid_info =
2853 			&pe_session->pLimReAssocReq->bssDescription.mbssid_info;
2854 
2855 	mlme_set_mbssid_info(pe_session->vdev, mbssid_info);
2856 }
2857 
2858 /**
2859  * lim_add_sta_self()
2860  *
2861  ***FUNCTION:
2862  * This function is called to add an STA context at hardware
2863  * whenever a STA is (Re) Associated.
2864  *
2865  ***LOGIC:
2866  *
2867  ***ASSUMPTIONS:
2868  * NA
2869  *
2870  ***NOTE:
2871  * NA
2872  *
2873  * @param  mac    - Pointer to Global MAC structure
2874  * @param  sta  - Pointer to the STA datastructure created by
2875  *                   LIM and maintained by DPH
2876  * @return retCode - Indicates success or failure return code
2877  */
2878 
2879 QDF_STATUS
2880 lim_add_sta_self(struct mac_context *mac, uint8_t updateSta,
2881 		 struct pe_session *pe_session)
2882 {
2883 	tpAddStaParams pAddStaParams = NULL;
2884 	struct scheduler_msg msgQ = {0};
2885 	QDF_STATUS retCode = QDF_STATUS_SUCCESS;
2886 	tSirMacAddr staMac;
2887 	uint32_t listenInterval = MLME_CFG_LISTEN_INTERVAL;
2888 	/*This self Sta dot 11 mode comes from the cfg and the expectation here is
2889 	 * that cfg carries the systemwide capability that device under
2890 	 * consideration can support. This capability gets plumbed into the cfg
2891 	 * cache at system initialization time via the .dat and .ini file override
2892 	 * mechanisms and will not change. If it does change, it is the
2893 	 * responsibility of SME to evict the selfSta and reissue a new AddStaSelf
2894 	 * command.*/
2895 	uint32_t selfStaDot11Mode = 0;
2896 
2897 	selfStaDot11Mode = mac->mlme_cfg->dot11_mode.dot11_mode;
2898 
2899 	sir_copy_mac_addr(staMac, pe_session->self_mac_addr);
2900 	pAddStaParams = qdf_mem_malloc(sizeof(tAddStaParams));
2901 	if (!pAddStaParams)
2902 		return QDF_STATUS_E_NOMEM;
2903 
2904 	/* / Add STA context at MAC HW (BMU, RHP & TFP) */
2905 	qdf_mem_copy((uint8_t *) pAddStaParams->staMac,
2906 		     (uint8_t *) staMac, sizeof(tSirMacAddr));
2907 
2908 	qdf_mem_copy((uint8_t *) pAddStaParams->bssId,
2909 		     pe_session->bssId, sizeof(tSirMacAddr));
2910 
2911 	pAddStaParams->assocId = pe_session->limAID;
2912 	pAddStaParams->staType = STA_ENTRY_SELF;
2913 	pAddStaParams->status = QDF_STATUS_SUCCESS;
2914 
2915 	/* Update  PE session ID */
2916 	pAddStaParams->sessionId = pe_session->peSessionId;
2917 
2918 	/* Update SME session ID */
2919 	pAddStaParams->smesessionId = pe_session->smeSessionId;
2920 
2921 	pAddStaParams->maxTxPower = pe_session->maxTxPower;
2922 
2923 	pAddStaParams->updateSta = updateSta;
2924 
2925 	lim_set_mbssid_info(pe_session);
2926 
2927 	lim_populate_own_rate_set(mac, &pAddStaParams->supportedRates,
2928 				  NULL, false,
2929 				  pe_session, NULL, NULL, NULL);
2930 	if (IS_DOT11_MODE_HT(selfStaDot11Mode)) {
2931 		pAddStaParams->htCapable = true;
2932 
2933 		pAddStaParams->ch_width =
2934 			mac->roam.configParam.channelBondingMode5GHz;
2935 		pAddStaParams->mimoPS =
2936 			lim_get_ht_capability(mac, eHT_MIMO_POWER_SAVE,
2937 					      pe_session);
2938 		pAddStaParams->maxAmpduDensity =
2939 			lim_get_ht_capability(mac, eHT_MPDU_DENSITY,
2940 					      pe_session);
2941 		pAddStaParams->maxAmpduSize =
2942 			lim_get_ht_capability(mac, eHT_MAX_RX_AMPDU_FACTOR,
2943 					      pe_session);
2944 		pAddStaParams->fShortGI20Mhz =
2945 			pe_session->ht_config.short_gi_20_mhz;
2946 		pAddStaParams->fShortGI40Mhz =
2947 			pe_session->ht_config.short_gi_40_mhz;
2948 	}
2949 	pAddStaParams->vhtCapable = pe_session->vhtCapability;
2950 	if (pAddStaParams->vhtCapable)
2951 		pAddStaParams->ch_width =
2952 			pe_session->ch_width;
2953 
2954 	pAddStaParams->vhtTxBFCapable =
2955 		pe_session->vht_config.su_beam_formee;
2956 	pAddStaParams->enable_su_tx_bformer =
2957 		pe_session->vht_config.su_beam_former;
2958 
2959 	/* In 11ac mode, the hardware is capable of supporting 128K AMPDU size */
2960 	if (pe_session->vhtCapability)
2961 		pAddStaParams->maxAmpduSize =
2962 		mac->mlme_cfg->vht_caps.vht_cap_info.ampdu_len_exponent;
2963 
2964 	pAddStaParams->vhtTxMUBformeeCapable =
2965 				pe_session->vht_config.mu_beam_formee;
2966 	pAddStaParams->enableVhtpAid = pe_session->enableVhtpAid;
2967 	pAddStaParams->enableAmpduPs = pe_session->enableAmpduPs;
2968 	pAddStaParams->enableHtSmps = (mac->mlme_cfg->ht_caps.enable_smps &&
2969 				(!pe_session->supported_nss_1x1));
2970 	pAddStaParams->htSmpsconfig = mac->mlme_cfg->ht_caps.smps;
2971 	pAddStaParams->send_smps_action =
2972 		pe_session->send_smps_action;
2973 
2974 	/* For Self STA get the LDPC capability from session i.e config.ini */
2975 	pAddStaParams->htLdpcCapable =
2976 		(pe_session->txLdpcIniFeatureEnabled & 0x01);
2977 	pAddStaParams->vhtLdpcCapable =
2978 		((pe_session->txLdpcIniFeatureEnabled >> 1) & 0x01);
2979 
2980 	listenInterval = mac->mlme_cfg->sap_cfg.listen_interval;
2981 	pAddStaParams->listenInterval = (uint16_t) listenInterval;
2982 
2983 	if (QDF_P2P_CLIENT_MODE == pe_session->opmode)
2984 		pAddStaParams->p2pCapableSta = 1;
2985 
2986 	if (pe_session->isNonRoamReassoc) {
2987 		pAddStaParams->nonRoamReassoc = 1;
2988 		pe_session->isNonRoamReassoc = 0;
2989 	}
2990 
2991 	if (IS_DOT11_MODE_HE(selfStaDot11Mode))
2992 		lim_add_self_he_cap(pAddStaParams, pe_session);
2993 
2994 	if (IS_DOT11_MODE_EHT(selfStaDot11Mode))
2995 		lim_add_self_eht_cap(pAddStaParams, pe_session);
2996 
2997 	if (lim_is_fils_connection(pe_session))
2998 		pAddStaParams->no_ptk_4_way = true;
2999 
3000 	msgQ.type = WMA_ADD_STA_REQ;
3001 	msgQ.reserved = 0;
3002 	msgQ.bodyptr = pAddStaParams;
3003 	msgQ.bodyval = 0;
3004 
3005 	pe_debug(QDF_MAC_ADDR_FMT ": vdev %d Sending WMA_ADD_STA_REQ.LI %d",
3006 		 QDF_MAC_ADDR_REF(pAddStaParams->staMac),
3007 		 pe_session->vdev_id, pAddStaParams->listenInterval);
3008 	MTRACE(mac_trace_msg_tx(mac, pe_session->peSessionId, msgQ.type));
3009 
3010 	retCode = wma_post_ctrl_msg(mac, &msgQ);
3011 	if (QDF_STATUS_SUCCESS != retCode) {
3012 		pe_err("Posting WMA_ADD_STA_REQ to HAL failed, reason=%X",
3013 			retCode);
3014 		qdf_mem_free(pAddStaParams);
3015 	}
3016 	return retCode;
3017 }
3018 
3019 /**
3020  * lim_handle_cnf_wait_timeout()
3021  *
3022  ***FUNCTION:
3023  * This function is called by limProcessMessageQueue to handle
3024  * various confirmation failure cases.
3025  *
3026  ***LOGIC:
3027  *
3028  ***ASSUMPTIONS:
3029  *
3030  ***NOTE:
3031  *
3032  * @param  mac - Pointer to Global MAC structure
3033  * @param  sta - Pointer to a sta descriptor
3034  * @return None
3035  */
3036 
3037 void lim_handle_cnf_wait_timeout(struct mac_context *mac, uint16_t staId)
3038 {
3039 	tpDphHashNode sta;
3040 	struct pe_session *pe_session = NULL;
3041 
3042 	pe_session = pe_find_session_by_session_id(mac,
3043 			mac->lim.lim_timers.gpLimCnfWaitTimer[staId].sessionId);
3044 	if (!pe_session) {
3045 		pe_err("Session Does not exist for given sessionID");
3046 		return;
3047 	}
3048 	sta = dph_get_hash_entry(mac, staId, &pe_session->dph.dphHashTable);
3049 
3050 	if (!sta) {
3051 		pe_err("No STA context in SIR_LIM_CNF_WAIT_TIMEOUT");
3052 		return;
3053 	}
3054 
3055 	switch (sta->mlmStaContext.mlmState) {
3056 	case eLIM_MLM_WT_ASSOC_CNF_STATE:
3057 		pe_debug("Did not receive Assoc Cnf in eLIM_MLM_WT_ASSOC_CNF_STATE sta Assoc id %d and STA: "QDF_MAC_ADDR_FMT,
3058 			 sta->assocId, QDF_MAC_ADDR_REF(sta->staAddr));
3059 
3060 		if (LIM_IS_AP_ROLE(pe_session)) {
3061 			lim_reject_association(mac, sta->staAddr,
3062 					       sta->mlmStaContext.subType,
3063 					       true,
3064 					       sta->mlmStaContext.authType,
3065 					       sta->assocId, true,
3066 					       STATUS_UNSPECIFIED_FAILURE,
3067 					       pe_session);
3068 		}
3069 		break;
3070 
3071 	default:
3072 		pe_warn("Received CNF_WAIT_TIMEOUT in state %d",
3073 			sta->mlmStaContext.mlmState);
3074 	}
3075 }
3076 
3077 /**
3078  * lim_delete_dph_hash_entry()- function to delete dph hash entry
3079  * @mac_ctx: pointer to global mac structure
3080  * @sta_addr: peer station address
3081  * @sta_id: id assigned to peer station
3082  * @session_entry: pe session entry
3083  *
3084  * This function is called whenever we need to delete
3085  * the dph hash entry
3086  *
3087  * Return: none
3088  */
3089 
3090 void
3091 lim_delete_dph_hash_entry(struct mac_context *mac_ctx, tSirMacAddr sta_addr,
3092 				 uint16_t sta_id, struct pe_session *session_entry)
3093 {
3094 	uint16_t aid;
3095 	tpDphHashNode sta_ds;
3096 	tUpdateBeaconParams beacon_params;
3097 
3098 	qdf_mem_zero(&beacon_params, sizeof(tUpdateBeaconParams));
3099 	beacon_params.paramChangeBitmap = 0;
3100 	lim_deactivate_and_change_per_sta_id_timer(mac_ctx, eLIM_CNF_WAIT_TIMER,
3101 		 sta_id);
3102 	if (!session_entry) {
3103 		pe_err("NULL session_entry");
3104 		return;
3105 	}
3106 
3107 	beacon_params.bss_idx = session_entry->vdev_id;
3108 	sta_ds = dph_lookup_hash_entry(mac_ctx, sta_addr, &aid,
3109 			 &session_entry->dph.dphHashTable);
3110 
3111 	if (!sta_ds) {
3112 		pe_err("sta_ds is NULL");
3113 		return;
3114 	}
3115 
3116 	pe_debug("Deleting DPH Hash entry sta mac " QDF_MAC_ADDR_FMT,
3117 		 QDF_MAC_ADDR_REF(sta_addr));
3118 	/*
3119 	 * update the station count and perform associated actions
3120 	 * do this before deleting the dph hash entry
3121 	 */
3122 	lim_util_count_sta_del(mac_ctx, sta_ds, session_entry);
3123 
3124 	if (LIM_IS_AP_ROLE(session_entry)) {
3125 		if (LIM_IS_AP_ROLE(session_entry)) {
3126 			if (session_entry->gLimProtectionControl !=
3127 				MLME_FORCE_POLICY_PROTECTION_DISABLE)
3128 				lim_decide_ap_protection_on_delete(mac_ctx,
3129 					sta_ds, &beacon_params, session_entry);
3130 		}
3131 
3132 		if (sta_ds->non_ecsa_capable) {
3133 			if (session_entry->lim_non_ecsa_cap_num == 0) {
3134 				pe_debug("NonECSA sta 0, id %d is ecsa",
3135 					 sta_id);
3136 			} else {
3137 				session_entry->lim_non_ecsa_cap_num--;
3138 				pe_debug("reducing the non ECSA num to %d",
3139 					 session_entry->lim_non_ecsa_cap_num);
3140 			}
3141 		}
3142 
3143 		lim_decide_short_preamble(mac_ctx, sta_ds, &beacon_params,
3144 					  session_entry);
3145 		lim_decide_short_slot(mac_ctx, sta_ds, &beacon_params,
3146 				      session_entry);
3147 
3148 		/* Send message to HAL about beacon parameter change. */
3149 		pe_debug("param bitmap: %d", beacon_params.paramChangeBitmap);
3150 		if (beacon_params.paramChangeBitmap &&
3151 			(false ==
3152 			 mac_ctx->sap.SapDfsInfo.is_dfs_cac_timer_running)) {
3153 			sch_set_fixed_beacon_fields(mac_ctx, session_entry);
3154 			lim_send_beacon_params(mac_ctx, &beacon_params,
3155 					       session_entry);
3156 		}
3157 
3158 		lim_obss_send_detection_cfg(mac_ctx, session_entry, false);
3159 
3160 		if (sta_ds->rmfEnabled) {
3161 			pe_debug("delete pmf timer assoc-id:%d sta mac "
3162 				 QDF_MAC_ADDR_FMT, sta_ds->assocId,
3163 				 QDF_MAC_ADDR_REF(sta_ds->staAddr));
3164 			tx_timer_delete(&sta_ds->pmfSaQueryTimer);
3165 		}
3166 	}
3167 
3168 	if (dph_delete_hash_entry(mac_ctx, sta_addr, sta_id,
3169 		 &session_entry->dph.dphHashTable) != QDF_STATUS_SUCCESS)
3170 		pe_err("error deleting hash entry");
3171 	lim_ap_check_6g_compatible_peer(mac_ctx, session_entry);
3172 }
3173 
3174 /**
3175  * lim_check_and_announce_join_success()- function to check if the received
3176  * Beacon/Probe Response is from the BSS that we're attempting to join.
3177  * @mac: pointer to global mac structure
3178  * @beacon_probe_rsp: pointer to reveived beacon/probe response frame
3179  * @header: pointer to received management frame header
3180  * @session_entry: pe session entry
3181  *
3182  * This function is called upon receiving Beacon/Probe Response
3183  * frame in WT_JOIN_BEACON_STATE to check if the received
3184  * Beacon/Probe Response is from the BSS that we're attempting
3185  * to join.
3186  * If the Beacon/Probe Response is indeed from the BSS we're
3187  * attempting to join, join success is sent to SME.
3188  *
3189  * Return: none
3190  */
3191 
3192 void
3193 lim_check_and_announce_join_success(struct mac_context *mac_ctx,
3194 		tSirProbeRespBeacon *beacon_probe_rsp, tpSirMacMgmtHdr header,
3195 		struct pe_session *session_entry)
3196 {
3197 	tSirMacSSid current_ssid;
3198 	tLimMlmJoinCnf mlm_join_cnf;
3199 	tpDphHashNode sta_ds = NULL;
3200 	uint32_t val;
3201 	uint32_t *noa_duration_from_beacon = NULL;
3202 	uint32_t *noa2_duration_from_beacon = NULL;
3203 	uint32_t noa;
3204 	uint32_t total_num_noa_desc = 0;
3205 	uint16_t aid;
3206 	bool check_assoc_disallowed;
3207 
3208 	qdf_mem_copy(current_ssid.ssId,
3209 		     session_entry->ssId.ssId, session_entry->ssId.length);
3210 
3211 	current_ssid.length = (uint8_t) session_entry->ssId.length;
3212 
3213 	/*
3214 	 * Check for SSID only in probe response. Beacons may not carry
3215 	 * SSID information in hidden SSID case
3216 	 */
3217 	if (((SIR_MAC_MGMT_FRAME == header->fc.type) &&
3218 		(SIR_MAC_MGMT_PROBE_RSP == header->fc.subType)) &&
3219 		current_ssid.length &&
3220 		(qdf_mem_cmp((uint8_t *) &beacon_probe_rsp->ssId,
3221 				  (uint8_t *) &current_ssid,
3222 				  (uint8_t) (1 + current_ssid.length)))) {
3223 		/*
3224 		 * Received SSID does not match with the one we've.
3225 		 * Ignore received Beacon frame
3226 		 */
3227 		pe_debug("SSID received in Beacon does not match");
3228 		return;
3229 	}
3230 
3231 	if (!LIM_IS_STA_ROLE(session_entry))
3232 		return;
3233 
3234 	if (SIR_MAC_MGMT_BEACON == header->fc.subType &&
3235 	    lim_is_null_ssid(&beacon_probe_rsp->ssId)) {
3236 		pe_debug("for hidden ap, waiting probersp to announce join success");
3237 		return;
3238 	}
3239 
3240 	pe_debug("Received Beacon/PR with BSSID:"QDF_MAC_ADDR_FMT" pe session %d vdev %d",
3241 		 QDF_MAC_ADDR_REF(session_entry->bssId),
3242 		 session_entry->peSessionId,
3243 		 session_entry->vdev_id);
3244 
3245 	/* Deactivate Join Failure timer */
3246 	lim_deactivate_and_change_timer(mac_ctx, eLIM_JOIN_FAIL_TIMER);
3247 	/* Deactivate Periodic Join timer */
3248 	lim_deactivate_and_change_timer(mac_ctx,
3249 		eLIM_PERIODIC_JOIN_PROBE_REQ_TIMER);
3250 
3251 	if (QDF_P2P_CLIENT_MODE == session_entry->opmode &&
3252 	    beacon_probe_rsp->P2PProbeRes.NoticeOfAbsence.present) {
3253 
3254 		noa_duration_from_beacon = (uint32_t *)
3255 		(beacon_probe_rsp->P2PProbeRes.NoticeOfAbsence.NoADesc + 1);
3256 
3257 		if (beacon_probe_rsp->P2PProbeRes.NoticeOfAbsence.num_NoADesc)
3258 			total_num_noa_desc =
3259 				beacon_probe_rsp->P2PProbeRes.NoticeOfAbsence.
3260 				num_NoADesc / SIZE_OF_NOA_DESCRIPTOR;
3261 
3262 		noa = *noa_duration_from_beacon;
3263 
3264 		if (total_num_noa_desc > 1) {
3265 			noa2_duration_from_beacon = (uint32_t *)
3266 			(beacon_probe_rsp->P2PProbeRes.NoticeOfAbsence.NoADesc +
3267 				SIZE_OF_NOA_DESCRIPTOR + 1);
3268 			noa += *noa2_duration_from_beacon;
3269 		}
3270 
3271 		/*
3272 		 * If MAX Noa exceeds 3 secs we will consider only 3 secs to
3273 		 * avoid arbitrary values in noa duration field
3274 		 */
3275 		noa = noa > MAX_NOA_PERIOD_IN_MICROSECS ?
3276 				MAX_NOA_PERIOD_IN_MICROSECS : noa;
3277 		noa = noa / 1000; /* Convert to ms */
3278 
3279 		session_entry->defaultAuthFailureTimeout =
3280 			mac_ctx->mlme_cfg->timeouts.auth_failure_timeout;
3281 		val = mac_ctx->mlme_cfg->timeouts.auth_failure_timeout + noa;
3282 		if (cfg_in_range(CFG_AUTH_FAILURE_TIMEOUT, val))
3283 			mac_ctx->mlme_cfg->timeouts.auth_failure_timeout = val;
3284 		else
3285 			mac_ctx->mlme_cfg->timeouts.auth_failure_timeout =
3286 				cfg_default(CFG_AUTH_FAILURE_TIMEOUT);
3287 	} else {
3288 		session_entry->defaultAuthFailureTimeout = 0;
3289 	}
3290 
3291 	wlan_cm_get_check_assoc_disallowed(mac_ctx->psoc,
3292 					   &check_assoc_disallowed);
3293 
3294 	/*
3295 	 * Check if MBO Association disallowed subattr is present and post
3296 	 * failure status to LIM if present
3297 	 */
3298 	if (check_assoc_disallowed && beacon_probe_rsp->assoc_disallowed) {
3299 		pe_err("Connection fails due to assoc disallowed reason(%d):"QDF_MAC_ADDR_FMT" PESessionID %d",
3300 				beacon_probe_rsp->assoc_disallowed_reason,
3301 				QDF_MAC_ADDR_REF(session_entry->bssId),
3302 				session_entry->peSessionId);
3303 		mlm_join_cnf.resultCode = eSIR_SME_ASSOC_REFUSED;
3304 		mlm_join_cnf.protStatusCode = STATUS_UNSPECIFIED_FAILURE;
3305 		session_entry->limMlmState = eLIM_MLM_IDLE_STATE;
3306 		mlm_join_cnf.sessionId = session_entry->peSessionId;
3307 		if (session_entry->pLimMlmJoinReq) {
3308 			qdf_mem_free(session_entry->pLimMlmJoinReq);
3309 			session_entry->pLimMlmJoinReq = NULL;
3310 		}
3311 		lim_post_sme_message(mac_ctx, LIM_MLM_JOIN_CNF,
3312 				(uint32_t *) &mlm_join_cnf);
3313 		return;
3314 	}
3315 
3316 	/* Update Beacon Interval at CFG database */
3317 
3318 	if (beacon_probe_rsp->HTCaps.present)
3319 		lim_update_sta_run_time_ht_capability(mac_ctx,
3320 			 &beacon_probe_rsp->HTCaps);
3321 	if (beacon_probe_rsp->HTInfo.present)
3322 		lim_update_sta_run_time_ht_info(mac_ctx,
3323 			 &beacon_probe_rsp->HTInfo, session_entry);
3324 	session_entry->limMlmState = eLIM_MLM_JOINED_STATE;
3325 	MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE,
3326 			 session_entry->peSessionId, eLIM_MLM_JOINED_STATE));
3327 
3328 	/*
3329 	 * update the capability info based on recently received beacon/probe
3330 	 * response frame
3331 	 */
3332 	session_entry->limCurrentBssCaps =
3333 		lim_get_u16((uint8_t *)&beacon_probe_rsp->capabilityInfo);
3334 
3335 	/*
3336 	 * Announce join success by sending
3337 	 * Join confirm to SME.
3338 	 */
3339 	mlm_join_cnf.resultCode = eSIR_SME_SUCCESS;
3340 	mlm_join_cnf.protStatusCode = STATUS_SUCCESS;
3341 	/* Update PE sessionId */
3342 	mlm_join_cnf.sessionId = session_entry->peSessionId;
3343 	lim_post_sme_message(mac_ctx, LIM_MLM_JOIN_CNF,
3344 			     (uint32_t *) &mlm_join_cnf);
3345 
3346 	if (session_entry->vhtCapability &&
3347 	    beacon_probe_rsp->vendor_vht_ie.VHTCaps.present) {
3348 		session_entry->is_vendor_specific_vhtcaps = true;
3349 		session_entry->vendor_specific_vht_ie_sub_type =
3350 			beacon_probe_rsp->vendor_vht_ie.sub_type;
3351 		pe_debug("VHT caps are present in vendor specific IE");
3352 	}
3353 
3354 	/* Update HS 2.0 Information Element */
3355 	if (beacon_probe_rsp->hs20vendor_ie.present) {
3356 		pe_debug("HS20 Indication Element Present, rel#:%u, id:%u",
3357 			beacon_probe_rsp->hs20vendor_ie.release_num,
3358 			beacon_probe_rsp->hs20vendor_ie.hs_id_present);
3359 		qdf_mem_copy(&session_entry->hs20vendor_ie,
3360 			&beacon_probe_rsp->hs20vendor_ie,
3361 			sizeof(tDot11fIEhs20vendor_ie) -
3362 			sizeof(beacon_probe_rsp->hs20vendor_ie.hs_id));
3363 		if (beacon_probe_rsp->hs20vendor_ie.hs_id_present)
3364 			qdf_mem_copy(&session_entry->hs20vendor_ie.hs_id,
3365 				&beacon_probe_rsp->hs20vendor_ie.hs_id,
3366 				sizeof(beacon_probe_rsp->hs20vendor_ie.hs_id));
3367 	}
3368 
3369 	sta_ds =  dph_lookup_hash_entry(mac_ctx, session_entry->self_mac_addr,
3370 					&aid,
3371 					&session_entry->dph.dphHashTable);
3372 
3373 	if (sta_ds && QDF_IS_STATUS_SUCCESS(lim_update_srp_ie(beacon_probe_rsp,
3374 							      sta_ds))) {
3375 		/* update the SR parameters */
3376 		lim_update_vdev_sr_elements(session_entry, sta_ds);
3377 		/* TODO: Need to send SRP IE update event to userspace */
3378 	}
3379 }
3380 
3381 /**
3382  * lim_extract_ap_capabilities()
3383  *
3384  ***FUNCTION:
3385  * This function is called to extract all of the AP's capabilities
3386  * from the IEs received from it in Beacon/Probe Response frames
3387  *
3388  ***LOGIC:
3389  * This routine mimics the lim_extract_ap_capability() API. The difference here
3390  * is that this API returns the entire tSirProbeRespBeacon info as is. It is
3391  * left to the caller of this API to use this info as required
3392  *
3393  ***ASSUMPTIONS:
3394  * NA
3395  *
3396  ***NOTE:
3397  *
3398  * @param   mac         Pointer to Global MAC structure
3399  * @param   pIE          Pointer to starting IE in Beacon/Probe Response
3400  * @param   ieLen        Length of all IEs combined
3401  * @param   beaconStruct A pointer to tSirProbeRespBeacon that needs to be
3402  *                       populated
3403  * @return  status       A status reporting QDF_STATUS_SUCCESS or QDF_STATUS_E_FAILURE
3404  */
3405 QDF_STATUS lim_extract_ap_capabilities(struct mac_context *mac,
3406 					  uint8_t *pIE,
3407 					  uint16_t ieLen,
3408 					  tpSirProbeRespBeacon beaconStruct)
3409 {
3410 	qdf_mem_zero((uint8_t *) beaconStruct, sizeof(tSirProbeRespBeacon));
3411 
3412 	/* Parse the Beacon IE's, Don't try to parse if we dont have anything in IE */
3413 	if (ieLen > 0) {
3414 		if (QDF_STATUS_SUCCESS !=
3415 		    sir_parse_beacon_ie(mac, beaconStruct, pIE,
3416 					(uint32_t) ieLen)) {
3417 			pe_err("APCapExtract: Beacon parsing error!");
3418 			return QDF_STATUS_E_FAILURE;
3419 		}
3420 	}
3421 
3422 	return QDF_STATUS_SUCCESS;
3423 }
3424 
3425 /**
3426  * lim_del_bss()
3427  *
3428  ***FUNCTION:
3429  * This function is called to delete BSS context at hardware
3430  * whenever a STA is disassociated
3431  *
3432  ***LOGIC:
3433  *
3434  ***ASSUMPTIONS:
3435  * NA
3436  *
3437  ***NOTE:
3438  * NA
3439  *
3440  * @param  mac    - Pointer to Global MAC structure
3441  * @param  sta  - Pointer to the STA datastructure created by
3442  *                   LIM and maintained by DPH
3443  * @return retCode - Indicates success or failure return code
3444  */
3445 
3446 QDF_STATUS
3447 lim_del_bss(struct mac_context *mac, tpDphHashNode sta, uint16_t bss_idx,
3448 	    struct pe_session *pe_session)
3449 {
3450 	struct scheduler_msg msgQ = {0};
3451 	QDF_STATUS retCode = QDF_STATUS_SUCCESS;
3452 
3453 	/* DPH was storing the AssocID in staID field, */
3454 	/* staID is actually assigned by HAL when AddSTA message is sent. */
3455 	if (sta) {
3456 		sta->valid = 0;
3457 		sta->mlmStaContext.mlmState = eLIM_MLM_WT_DEL_BSS_RSP_STATE;
3458 	}
3459 	pe_session->limMlmState = eLIM_MLM_WT_DEL_BSS_RSP_STATE;
3460 	MTRACE(mac_trace
3461 		       (mac, TRACE_CODE_MLM_STATE, pe_session->peSessionId,
3462 		       eLIM_MLM_WT_DEL_BSS_RSP_STATE));
3463 
3464 	if ((pe_session->peSessionId ==
3465 	     mac->lim.lim_timers.gLimJoinFailureTimer.sessionId)
3466 	    && (true ==
3467 		tx_timer_running(&mac->lim.lim_timers.gLimJoinFailureTimer))) {
3468 		lim_deactivate_and_change_timer(mac, eLIM_JOIN_FAIL_TIMER);
3469 	}
3470 
3471 	/* we need to defer the message until we get the response back from HAL. */
3472 	SET_LIM_PROCESS_DEFD_MESGS(mac, false);
3473 
3474 	if (pe_session->process_ho_fail)
3475 		msgQ.type = WMA_DELETE_BSS_HO_FAIL_REQ;
3476 	else
3477 		msgQ.type = WMA_DELETE_BSS_REQ;
3478 	msgQ.reserved = 0;
3479 	msgQ.bodyptr = NULL;
3480 	msgQ.bodyval = pe_session->smeSessionId;
3481 
3482 	pe_debug("Sessionid %d : Sending HAL_DELETE_BSS_REQ BSSID:" QDF_MAC_ADDR_FMT,
3483 		 pe_session->peSessionId,
3484 		 QDF_MAC_ADDR_REF(pe_session->bssId));
3485 	MTRACE(mac_trace_msg_tx(mac, pe_session->peSessionId, msgQ.type));
3486 
3487 	retCode = wma_post_ctrl_msg(mac, &msgQ);
3488 	if (QDF_STATUS_SUCCESS != retCode) {
3489 		SET_LIM_PROCESS_DEFD_MESGS(mac, true);
3490 		pe_err("Posting DELETE_BSS_REQ to HAL failed, reason=%X",
3491 			retCode);
3492 	}
3493 
3494 	return retCode;
3495 }
3496 
3497 /**
3498  * lim_update_vhtcaps_assoc_resp : Update VHT caps in assoc response.
3499  * @mac_ctx Pointer to Global MAC structure
3500  * @pAddBssParams: parameters required for add bss params.
3501  * @vht_caps: VHT capabilities.
3502  * @pe_session : session entry.
3503  *
3504  * Return : void
3505  */
3506 void lim_update_vhtcaps_assoc_resp(struct mac_context *mac_ctx,
3507 				   struct bss_params *pAddBssParams,
3508 				   tDot11fIEVHTCaps *vht_caps,
3509 				   struct pe_session *pe_session)
3510 {
3511 	pAddBssParams->staContext.vht_caps =
3512 		((vht_caps->maxMPDULen <<
3513 		  SIR_MAC_VHT_CAP_MAX_MPDU_LEN) |
3514 		 (vht_caps->supportedChannelWidthSet <<
3515 		  SIR_MAC_VHT_CAP_SUPP_CH_WIDTH_SET) |
3516 		 (vht_caps->ldpcCodingCap <<
3517 		  SIR_MAC_VHT_CAP_LDPC_CODING_CAP) |
3518 		 (vht_caps->shortGI80MHz <<
3519 		  SIR_MAC_VHT_CAP_SHORTGI_80MHZ) |
3520 		 (vht_caps->shortGI160and80plus80MHz <<
3521 		  SIR_MAC_VHT_CAP_SHORTGI_160_80_80MHZ) |
3522 		 (vht_caps->txSTBC <<
3523 		  SIR_MAC_VHT_CAP_TXSTBC) |
3524 		 (vht_caps->rxSTBC <<
3525 		  SIR_MAC_VHT_CAP_RXSTBC) |
3526 		 (vht_caps->suBeamFormerCap <<
3527 		  SIR_MAC_VHT_CAP_SU_BEAMFORMER_CAP) |
3528 		 (vht_caps->suBeamformeeCap <<
3529 		  SIR_MAC_VHT_CAP_SU_BEAMFORMEE_CAP) |
3530 		 (vht_caps->csnofBeamformerAntSup <<
3531 		  SIR_MAC_VHT_CAP_CSN_BEAMORMER_ANT_SUP) |
3532 		 (vht_caps->numSoundingDim <<
3533 		  SIR_MAC_VHT_CAP_NUM_SOUNDING_DIM) |
3534 		 (vht_caps->muBeamformerCap <<
3535 		  SIR_MAC_VHT_CAP_NUM_BEAM_FORMER_CAP) |
3536 		 (vht_caps->muBeamformeeCap <<
3537 		  SIR_MAC_VHT_CAP_NUM_BEAM_FORMEE_CAP) |
3538 		 (vht_caps->vhtTXOPPS <<
3539 		  SIR_MAC_VHT_CAP_TXOPPS) |
3540 		 (vht_caps->htcVHTCap <<
3541 		  SIR_MAC_VHT_CAP_HTC_CAP) |
3542 		 (vht_caps->maxAMPDULenExp <<
3543 		  SIR_MAC_VHT_CAP_MAX_AMDU_LEN_EXPO) |
3544 		 (vht_caps->vhtLinkAdaptCap <<
3545 		  SIR_MAC_VHT_CAP_LINK_ADAPT_CAP) |
3546 		 (vht_caps->rxAntPattern <<
3547 		  SIR_MAC_VHT_CAP_RX_ANTENNA_PATTERN) |
3548 		 (vht_caps->txAntPattern <<
3549 		  SIR_MAC_VHT_CAP_TX_ANTENNA_PATTERN) |
3550 		 (vht_caps->extended_nss_bw_supp <<
3551 		  SIR_MAC_VHT_CAP_EXTD_NSS_BW));
3552 
3553 	pAddBssParams->staContext.maxAmpduSize =
3554 		SIR_MAC_GET_VHT_MAX_AMPDU_EXPO(
3555 				pAddBssParams->staContext.vht_caps);
3556 }
3557 
3558 /**
3559  * lim_update_vht_oper_assoc_resp : Update VHT Operations in assoc response.
3560  * @mac_ctx Pointer to Global MAC structure
3561  * @pAddBssParams: parameters required for add bss params.
3562  * @vht_caps: VHT CAP IE to update.
3563  * @vht_oper: VHT Operations to update.
3564  * @ht_info: HT Info IE to update.
3565  * @pe_session : session entry.
3566  *
3567  * Return : void
3568  */
3569 static void lim_update_vht_oper_assoc_resp(struct mac_context *mac_ctx,
3570 		struct bss_params *pAddBssParams,
3571 		tDot11fIEVHTCaps *vht_caps, tDot11fIEVHTOperation *vht_oper,
3572 		tDot11fIEHTInfo *ht_info, struct pe_session *pe_session)
3573 {
3574 	uint8_t ch_width;
3575 
3576 	ch_width = pAddBssParams->ch_width;
3577 
3578 	if (vht_oper->chanWidth == WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ &&
3579 	    pe_session->ch_width)
3580 		ch_width =
3581 			lim_get_vht_ch_width(vht_caps, vht_oper, ht_info) + 1;
3582 
3583 	if (ch_width > pe_session->ch_width)
3584 		ch_width = pe_session->ch_width;
3585 
3586 	pAddBssParams->ch_width = ch_width;
3587 	pAddBssParams->staContext.ch_width = ch_width;
3588 }
3589 
3590 #ifdef WLAN_FEATURE_11BE
3591 /**
3592  * lim_update_eht_oper_assoc_resp : Update BW based on EHT operation IE.
3593  * @pe_session : session entry.
3594  * @pAddBssParams: parameters required for add bss params.
3595  * @eht_op: EHT Oper IE to update.
3596  *
3597  * Return : void
3598  */
3599 static void lim_update_eht_oper_assoc_resp(struct pe_session *pe_session,
3600 					   struct bss_params *pAddBssParams,
3601 					   tDot11fIEeht_op *eht_op)
3602 {
3603 	enum phy_ch_width ch_width;
3604 
3605 	ch_width = wlan_mlme_convert_eht_op_bw_to_phy_ch_width(
3606 						eht_op->channel_width);
3607 
3608 	/* Due to puncturing, EHT AP's send seg1 in VHT IE as zero which causes
3609 	 * downgrade to 80 MHz, check EHT IE and if EHT IE supports 160MHz
3610 	 * then stick to 160MHz only
3611 	 */
3612 
3613 	if (ch_width > pAddBssParams->ch_width &&
3614 	    ch_width >= pe_session->ch_width) {
3615 		pe_debug("eht ch_width %d and ch_width of add bss param %d",
3616 			 ch_width, pAddBssParams->ch_width);
3617 		ch_width = pe_session->ch_width;
3618 	}
3619 
3620 	pAddBssParams->ch_width = ch_width;
3621 	pAddBssParams->staContext.ch_width = ch_width;
3622 }
3623 #else
3624 static void lim_update_eht_oper_assoc_resp(struct pe_session *pe_session,
3625 					   struct bss_params *pAddBssParams,
3626 					   tDot11fIEeht_op *eht_op)
3627 {
3628 }
3629 #endif
3630 
3631 #ifdef WLAN_SUPPORT_TWT
3632 /**
3633  * lim_set_sta_ctx_twt() - Save the TWT settings in STA context
3634  * @sta_ctx: Pointer to Station Context
3635  * @session: Pointer to PE session
3636  *
3637  * Return: None
3638  */
3639 static void lim_set_sta_ctx_twt(tAddStaParams *sta_ctx, struct pe_session *session)
3640 {
3641 	sta_ctx->twt_requestor = session->peer_twt_requestor;
3642 	sta_ctx->twt_responder = session->peer_twt_responder;
3643 }
3644 #else
3645 static inline void lim_set_sta_ctx_twt(tAddStaParams *sta_ctx,
3646 				       struct pe_session *session)
3647 {
3648 }
3649 #endif
3650 
3651 void lim_sta_add_bss_update_ht_parameter(uint32_t bss_chan_freq,
3652 					 tDot11fIEHTCaps* ht_cap,
3653 					 tDot11fIEHTInfo* ht_inf,
3654 					 bool chan_width_support,
3655 					 struct bss_params *add_bss)
3656 {
3657 	if (!ht_cap->present)
3658 		return;
3659 
3660 	add_bss->htCapable = ht_cap->present;
3661 
3662 	if (!ht_inf->present)
3663 		return;
3664 
3665 	if (chan_width_support && ht_cap->supportedChannelWidthSet)
3666 		add_bss->ch_width = ht_inf->recommendedTxWidthSet;
3667 	else
3668 		add_bss->ch_width = CH_WIDTH_20MHZ;
3669 }
3670 
3671 QDF_STATUS lim_sta_send_add_bss(struct mac_context *mac, tpSirAssocRsp pAssocRsp,
3672 				   tpSchBeaconStruct pBeaconStruct,
3673 				   struct bss_description *bssDescription,
3674 				   uint8_t updateEntry, struct pe_session *pe_session)
3675 {
3676 	struct bss_params *pAddBssParams = NULL;
3677 	uint32_t retCode;
3678 	tpDphHashNode sta = NULL;
3679 	bool chan_width_support = false;
3680 	bool is_vht_cap_in_vendor_ie = false;
3681 	tDot11fIEVHTCaps *vht_caps = NULL;
3682 	tDot11fIEVHTOperation *vht_oper = NULL;
3683 	tAddStaParams *sta_context;
3684 	uint32_t listen_interval = MLME_CFG_LISTEN_INTERVAL;
3685 	struct mlme_vht_capabilities_info *vht_cap_info;
3686 
3687 	vht_cap_info = &mac->mlme_cfg->vht_caps.vht_cap_info;
3688 
3689 	/* Package SIR_HAL_ADD_BSS_REQ message parameters */
3690 	pAddBssParams = qdf_mem_malloc(sizeof(struct bss_params));
3691 	if (!pAddBssParams) {
3692 		retCode = QDF_STATUS_E_NOMEM;
3693 		goto returnFailure;
3694 	}
3695 
3696 	qdf_mem_copy(pAddBssParams->bssId, bssDescription->bssId,
3697 		     sizeof(tSirMacAddr));
3698 
3699 	pAddBssParams->beaconInterval = bssDescription->beaconInterval;
3700 
3701 	pAddBssParams->dtimPeriod = pBeaconStruct->tim.dtimPeriod;
3702 	pAddBssParams->updateBss = updateEntry;
3703 
3704 	if (IS_DOT11_MODE_11B(pe_session->dot11mode) &&
3705 	    bssDescription->nwType != eSIR_11B_NW_TYPE) {
3706 		pAddBssParams->nwType = eSIR_11B_NW_TYPE;
3707 	} else {
3708 		pAddBssParams->nwType = bssDescription->nwType;
3709 	}
3710 
3711 	pAddBssParams->shortSlotTimeSupported =
3712 		(uint8_t) pAssocRsp->capabilityInfo.shortSlotTime;
3713 	pAddBssParams->llbCoexist =
3714 		(uint8_t) pe_session->beaconParams.llbCoexist;
3715 
3716 	/* Use the advertised capabilities from the received beacon/PR */
3717 	if (IS_DOT11_MODE_HT(pe_session->dot11mode)) {
3718 		chan_width_support =
3719 			lim_get_ht_capability(mac,
3720 					      eHT_SUPPORTED_CHANNEL_WIDTH_SET,
3721 					      pe_session);
3722 
3723 		lim_sta_add_bss_update_ht_parameter(bssDescription->chan_freq,
3724 						    &pAssocRsp->HTCaps,
3725 						    &pAssocRsp->HTInfo,
3726 						    chan_width_support,
3727 						    pAddBssParams);
3728 		/**
3729 		 * in limExtractApCapability function intersection of FW
3730 		 * advertised channel width and AP advertised channel
3731 		 * width has been taken into account for calculating
3732 		 * pe_session->ch_width
3733 		 */
3734 		if ((chan_width_support &&
3735 		     ((pAssocRsp->HTCaps.present &&
3736 		       pAssocRsp->HTCaps.supportedChannelWidthSet) ||
3737 		      (pBeaconStruct->HTCaps.present &&
3738 		       pBeaconStruct->HTCaps.supportedChannelWidthSet))) ||
3739 		    lim_is_eht_connection_op_info_present(pe_session,
3740 							  pAssocRsp)) {
3741 			pAddBssParams->ch_width =
3742 					pe_session->ch_width;
3743 			pAddBssParams->staContext.ch_width =
3744 						pe_session->ch_width;
3745 		} else {
3746 			pAddBssParams->ch_width = CH_WIDTH_20MHZ;
3747 			pAddBssParams->staContext.ch_width = CH_WIDTH_20MHZ;
3748 			if (!vht_cap_info->enable_txbf_20mhz)
3749 				pAddBssParams->staContext.vhtTxBFCapable = 0;
3750 		}
3751 	}
3752 
3753 	if (pe_session->vhtCapability && (pAssocRsp->VHTCaps.present)) {
3754 		pAddBssParams->vhtCapable = pAssocRsp->VHTCaps.present;
3755 		vht_caps =  &pAssocRsp->VHTCaps;
3756 		vht_oper = &pAssocRsp->VHTOperation;
3757 	} else if (pe_session->vhtCapability &&
3758 			pAssocRsp->vendor_vht_ie.VHTCaps.present){
3759 		pAddBssParams->vhtCapable =
3760 			pAssocRsp->vendor_vht_ie.VHTCaps.present;
3761 		pe_debug("VHT Caps and Operation are present in vendor Specific IE");
3762 		vht_caps = &pAssocRsp->vendor_vht_ie.VHTCaps;
3763 		vht_oper = &pAssocRsp->vendor_vht_ie.VHTOperation;
3764 	} else {
3765 		pAddBssParams->vhtCapable = 0;
3766 	}
3767 	if (pAddBssParams->vhtCapable) {
3768 		if (vht_oper)
3769 			lim_update_vht_oper_assoc_resp(mac, pAddBssParams,
3770 						       vht_caps, vht_oper,
3771 						       &pAssocRsp->HTInfo,
3772 						       pe_session);
3773 		if (vht_caps)
3774 			lim_update_vhtcaps_assoc_resp(mac, pAddBssParams,
3775 					vht_caps, pe_session);
3776 	}
3777 
3778 	if (lim_is_session_he_capable(pe_session) &&
3779 			(pAssocRsp->he_cap.present)) {
3780 		lim_add_bss_he_cap(pAddBssParams, pAssocRsp);
3781 		lim_add_bss_he_cfg(pAddBssParams, pe_session);
3782 	}
3783 
3784 	if (lim_is_session_eht_capable(pe_session) &&
3785 	    (pAssocRsp->eht_cap.present)) {
3786 		lim_add_bss_eht_cap(pAddBssParams, pAssocRsp);
3787 		lim_add_bss_eht_cfg(pAddBssParams, pe_session);
3788 	}
3789 
3790 	if (lim_is_session_eht_capable(pe_session) &&
3791 	    pAssocRsp->eht_op.present &&
3792 	    pAssocRsp->eht_op.eht_op_information_present)
3793 		lim_update_eht_oper_assoc_resp(pe_session, pAddBssParams,
3794 					       &pAssocRsp->eht_op);
3795 
3796 	if (pAssocRsp->bss_max_idle_period.present) {
3797 		pAddBssParams->bss_max_idle_period =
3798 			pAssocRsp->bss_max_idle_period.max_idle_period;
3799 		pe_debug("bss_max_idle_period %d",
3800 			 pAddBssParams->bss_max_idle_period);
3801 	} else {
3802 		pAddBssParams->bss_max_idle_period = 0;
3803 	}
3804 
3805 	/*
3806 	 * Populate the STA-related parameters here
3807 	 * Note that the STA here refers to the AP
3808 	 * staType = PEER
3809 	 */
3810 	sta_context = &pAddBssParams->staContext;
3811 	/* Identifying AP as an STA */
3812 	pAddBssParams->staContext.staType = STA_ENTRY_OTHER;
3813 
3814 	qdf_mem_copy(pAddBssParams->staContext.bssId,
3815 			bssDescription->bssId, sizeof(tSirMacAddr));
3816 
3817 	listen_interval = mac->mlme_cfg->sap_cfg.listen_interval;
3818 	pAddBssParams->staContext.listenInterval = listen_interval;
3819 
3820 	/* Get STA hash entry from the dph table */
3821 	sta = dph_lookup_hash_entry(mac, pAddBssParams->staContext.bssId,
3822 				&pAddBssParams->staContext.assocId,
3823 				&pe_session->dph.dphHashTable);
3824 	if (!sta) {
3825 		pe_err("Couldn't get assoc id for " "MAC ADDR: "
3826 			QDF_MAC_ADDR_FMT,
3827 			QDF_MAC_ADDR_REF(
3828 				pAddBssParams->staContext.staMac));
3829 			qdf_mem_free(pAddBssParams);
3830 			return QDF_STATUS_E_FAILURE;
3831 	}
3832 
3833 	/* Update Assoc id from pe_session for STA */
3834 	pAddBssParams->staContext.assocId = pe_session->limAID;
3835 
3836 	pAddBssParams->staContext.uAPSD =
3837 		pe_session->gUapsdPerAcBitmask;
3838 
3839 	pAddBssParams->staContext.maxSPLen = 0;
3840 	pAddBssParams->staContext.updateSta = updateEntry;
3841 
3842 	if (IS_DOT11_MODE_HT(pe_session->dot11mode)
3843 			&& pBeaconStruct->HTCaps.present) {
3844 		pAddBssParams->staContext.htCapable = 1;
3845 		if (pe_session->ht_config.tx_stbc)
3846 			pAddBssParams->staContext.stbc_capable =
3847 				pAssocRsp->HTCaps.rxSTBC;
3848 
3849 		if (pe_session->vhtCapability &&
3850 				(IS_BSS_VHT_CAPABLE(pBeaconStruct->VHTCaps) ||
3851 				 IS_BSS_VHT_CAPABLE(pBeaconStruct->
3852 						    vendor_vht_ie.VHTCaps))) {
3853 			pAddBssParams->staContext.vhtCapable = 1;
3854 			pAddBssParams->staContext.vht_mcs_10_11_supp =
3855 				sta->vht_mcs_10_11_supp;
3856 
3857 			pAddBssParams->staContext.vhtSupportedRxNss =
3858 				sta->vhtSupportedRxNss;
3859 			if (pAssocRsp->VHTCaps.present)
3860 				vht_caps = &pAssocRsp->VHTCaps;
3861 			else if (pAssocRsp->vendor_vht_ie.VHTCaps.present) {
3862 				vht_caps = &pAssocRsp->vendor_vht_ie.VHTCaps;
3863 				pe_debug("VHT Caps are in vendor Specific IE");
3864 				is_vht_cap_in_vendor_ie = true;
3865 			}
3866 
3867 			if ((vht_caps) && (vht_caps->suBeamFormerCap ||
3868 				vht_caps->muBeamformerCap) &&
3869 				pe_session->vht_config.su_beam_formee)
3870 				sta_context->vhtTxBFCapable = 1;
3871 
3872 			if ((vht_caps) && vht_caps->muBeamformerCap &&
3873 				pe_session->vht_config.mu_beam_formee)
3874 				sta_context->vhtTxMUBformeeCapable = 1;
3875 
3876 			if ((vht_caps) && vht_caps->suBeamformeeCap &&
3877 				pe_session->vht_config.su_beam_former)
3878 				sta_context->enable_su_tx_bformer = 1;
3879 
3880 			if (vht_caps && pAddBssParams->staContext.stbc_capable)
3881 				pAddBssParams->staContext.stbc_capable =
3882 					vht_caps->rxSTBC;
3883 			if (pe_session->ch_width == CH_WIDTH_160MHZ ||
3884 			    pe_session->ch_width == CH_WIDTH_80P80MHZ) {
3885 				sta_context->vht_160mhz_nss =
3886 						sta->vht_160mhz_nss;
3887 				sta_context->vht_80p80mhz_nss =
3888 						sta->vht_80p80mhz_nss;
3889 				sta_context->vht_extended_nss_bw_cap =
3890 						sta->vht_extended_nss_bw_cap;
3891 			} else {
3892 				sta_context->vht_160mhz_nss = 0;
3893 				sta_context->vht_80p80mhz_nss = 0;
3894 				sta_context->vht_extended_nss_bw_cap = 0;
3895 			}
3896 		}
3897 		if (lim_is_session_he_capable(pe_session) &&
3898 		    (pAssocRsp->he_cap.present ||
3899 		     pBeaconStruct->he_cap.present)) {
3900 			lim_intersect_ap_he_caps(pe_session,
3901 						 pAddBssParams,
3902 						 pBeaconStruct,
3903 						 pAssocRsp, bssDescription);
3904 			lim_update_he_stbc_capable(&pAddBssParams->staContext);
3905 			lim_update_he_mcs_12_13(&pAddBssParams->staContext,
3906 						sta);
3907 		}
3908 
3909 		if (lim_is_session_eht_capable(pe_session) &&
3910 		    (pAssocRsp->eht_cap.present ||
3911 		     pBeaconStruct->eht_cap.present)) {
3912 			lim_intersect_ap_eht_caps(pe_session,
3913 						  pAddBssParams,
3914 						  pBeaconStruct,
3915 						  pAssocRsp);
3916 		}
3917 
3918 		pAddBssParams->staContext.mimoPS =
3919 			(tSirMacHTMIMOPowerSaveState)
3920 			pAssocRsp->HTCaps.mimoPowerSave;
3921 		pAddBssParams->staContext.maxAmpduDensity =
3922 			pAssocRsp->HTCaps.mpduDensity;
3923 		/*
3924 		 * We will check gShortGI20Mhz and gShortGI40Mhz from
3925 		 * session entry  if they are set then we will use what ever
3926 		 * Assoc response coming from AP supports. If these
3927 		 * values are set as 0 in session entry then we will
3928 		 * hardcode this values to 0.
3929 		 */
3930 		if (pe_session->ht_config.short_gi_20_mhz) {
3931 			pAddBssParams->staContext.fShortGI20Mhz =
3932 				(uint8_t)pAssocRsp->HTCaps.shortGI20MHz;
3933 		} else {
3934 			pAddBssParams->staContext.fShortGI20Mhz = false;
3935 		}
3936 
3937 		if (pe_session->ht_config.short_gi_40_mhz) {
3938 			pAddBssParams->staContext.fShortGI40Mhz =
3939 				(uint8_t) pAssocRsp->HTCaps.shortGI40MHz;
3940 		} else {
3941 			pAddBssParams->staContext.fShortGI40Mhz = false;
3942 		}
3943 
3944 		if (!pAddBssParams->staContext.vhtCapable)
3945 			/* Use max ampd factor advertised in
3946 			 * HTCAP for non-vht connection */
3947 		{
3948 			pAddBssParams->staContext.maxAmpduSize =
3949 				pAssocRsp->HTCaps.maxRxAMPDUFactor;
3950 		} else if (pAddBssParams->staContext.maxAmpduSize <
3951 				pAssocRsp->HTCaps.maxRxAMPDUFactor) {
3952 			pAddBssParams->staContext.maxAmpduSize =
3953 				pAssocRsp->HTCaps.maxRxAMPDUFactor;
3954 		}
3955 		if (pAddBssParams->staContext.vhtTxBFCapable
3956 		    && vht_cap_info->disable_ldpc_with_txbf_ap) {
3957 			pAddBssParams->staContext.htLdpcCapable = 0;
3958 			pAddBssParams->staContext.vhtLdpcCapable = 0;
3959 		} else {
3960 			if (pe_session->txLdpcIniFeatureEnabled & 0x1)
3961 				pAddBssParams->staContext.htLdpcCapable =
3962 				    (uint8_t) pAssocRsp->HTCaps.advCodingCap;
3963 			else
3964 				pAddBssParams->staContext.htLdpcCapable = 0;
3965 
3966 			if (pAssocRsp->VHTCaps.present)
3967 				vht_caps = &pAssocRsp->VHTCaps;
3968 			else if (pAssocRsp->vendor_vht_ie.VHTCaps.present) {
3969 				vht_caps = &pAssocRsp->vendor_vht_ie.VHTCaps;
3970 				pe_debug("VHT Caps is in vendor Specific IE");
3971 			}
3972 			if (vht_caps &&
3973 				(pe_session->txLdpcIniFeatureEnabled & 0x2)) {
3974 				if (!is_vht_cap_in_vendor_ie)
3975 					pAddBssParams->staContext.vhtLdpcCapable =
3976 					  (uint8_t) pAssocRsp->VHTCaps.ldpcCodingCap;
3977 				else
3978 					pAddBssParams->staContext.vhtLdpcCapable =
3979 					    (uint8_t) vht_caps->ldpcCodingCap;
3980 			} else {
3981 				pAddBssParams->staContext.vhtLdpcCapable = 0;
3982 			}
3983 		}
3984 
3985 	}
3986 	if (lim_is_he_6ghz_band(pe_session)) {
3987 		if (lim_is_session_he_capable(pe_session) &&
3988 		    (pAssocRsp->he_cap.present ||
3989 		     pBeaconStruct->he_cap.present)) {
3990 			lim_intersect_ap_he_caps(pe_session,
3991 						 pAddBssParams,
3992 						 pBeaconStruct,
3993 						 pAssocRsp, bssDescription);
3994 			lim_update_he_stbc_capable(&pAddBssParams->staContext);
3995 			lim_update_he_mcs_12_13(&pAddBssParams->staContext,
3996 						sta);
3997 			if (!lim_is_eht_connection_op_info_present(pe_session,
3998 								   pAssocRsp))
3999 				lim_update_he_6gop_assoc_resp(pAddBssParams,
4000 							      &pAssocRsp->he_op,
4001 							      pe_session);
4002 			lim_update_he_6ghz_band_caps(mac,
4003 						&pAssocRsp->he_6ghz_band_cap,
4004 						&pAddBssParams->staContext);
4005 		}
4006 		if (lim_is_session_eht_capable(pe_session) &&
4007 		    (pAssocRsp->eht_cap.present ||
4008 		     pBeaconStruct->eht_cap.present)) {
4009 			lim_intersect_ap_eht_caps(pe_session,
4010 						  pAddBssParams,
4011 						  pBeaconStruct,
4012 						  pAssocRsp);
4013 		}
4014 	}
4015 
4016 	lim_extract_per_link_id(pe_session, pAddBssParams, pAssocRsp);
4017 	lim_extract_ml_info(pe_session, pAddBssParams, pAssocRsp);
4018 	lim_intersect_ap_emlsr_caps(mac, pe_session, pAddBssParams, pAssocRsp);
4019 	lim_extract_msd_caps(mac, pe_session, pAddBssParams, pAssocRsp);
4020 
4021 	pAddBssParams->staContext.smesessionId =
4022 		pe_session->smeSessionId;
4023 	pAddBssParams->staContext.wpa_rsn = pBeaconStruct->rsnPresent;
4024 	pAddBssParams->staContext.wpa_rsn |=
4025 		(pBeaconStruct->wpaPresent << 1);
4026 	/* For OSEN Connection AP does not advertise RSN or WPA IE
4027 	 * so from the IEs we get from supplicant we get this info
4028 	 * so for FW to transmit EAPOL message 4 we shall set
4029 	 * wpa_rsn
4030 	 */
4031 	if ((!pAddBssParams->staContext.wpa_rsn)
4032 			&& (pe_session->isOSENConnection))
4033 		pAddBssParams->staContext.wpa_rsn = 1;
4034 	qdf_mem_copy(&pAddBssParams->staContext.capab_info,
4035 			&pAssocRsp->capabilityInfo,
4036 			sizeof(pAddBssParams->staContext.capab_info));
4037 	qdf_mem_copy(&pAddBssParams->staContext.ht_caps,
4038 			(uint8_t *) &pAssocRsp->HTCaps + sizeof(uint8_t),
4039 			sizeof(pAddBssParams->staContext.ht_caps));
4040 
4041 	/* If WMM IE or 802.11E IE is present then enable WMM */
4042 	if ((pe_session->limWmeEnabled && pAssocRsp->wmeEdcaPresent) ||
4043 		(pe_session->limQosEnabled && pAssocRsp->edcaPresent))
4044 		pAddBssParams->staContext.wmmEnabled = 1;
4045 	else
4046 		pAddBssParams->staContext.wmmEnabled = 0;
4047 
4048 	/* Update the rates */
4049 	sta = dph_get_hash_entry(mac, DPH_STA_HASH_INDEX_PEER,
4050 				&pe_session->dph.dphHashTable);
4051 	if (sta) {
4052 		qdf_mem_copy(&pAddBssParams->staContext.supportedRates,
4053 			     &sta->supportedRates,
4054 			     sizeof(sta->supportedRates));
4055 	} else
4056 		pe_err("could not Update the supported rates");
4057 	pAddBssParams->staContext.encryptType = pe_session->encryptType;
4058 
4059 	pAddBssParams->maxTxPower = pe_session->maxTxPower;
4060 
4061 	if (QDF_P2P_CLIENT_MODE == pe_session->opmode)
4062 		pAddBssParams->staContext.p2pCapableSta = 1;
4063 
4064 	if (pe_session->limRmfEnabled) {
4065 		pAddBssParams->rmfEnabled = 1;
4066 		pAddBssParams->staContext.rmfEnabled = 1;
4067 	}
4068 
4069 	/* Set a new state for MLME */
4070 	if (eLIM_MLM_WT_ASSOC_RSP_STATE == pe_session->limMlmState)
4071 		pe_session->limMlmState =
4072 			eLIM_MLM_WT_ADD_BSS_RSP_ASSOC_STATE;
4073 	else
4074 		pe_session->limMlmState =
4075 			eLIM_MLM_WT_ADD_BSS_RSP_REASSOC_STATE;
4076 	MTRACE(mac_trace
4077 		       (mac, TRACE_CODE_MLM_STATE, pe_session->peSessionId,
4078 		       pe_session->limMlmState));
4079 
4080 	if (!pAddBssParams->staContext.htLdpcCapable)
4081 		pAddBssParams->staContext.ht_caps &=
4082 			~(1 << SIR_MAC_HT_CAP_ADVCODING_S);
4083 	if (!pAddBssParams->staContext.vhtLdpcCapable)
4084 		pAddBssParams->staContext.vht_caps &=
4085 			~(1 << SIR_MAC_VHT_CAP_LDPC_CODING_CAP);
4086 
4087 	if (pe_session->isNonRoamReassoc)
4088 		pAddBssParams->nonRoamReassoc = 1;
4089 
4090 	pe_debug("update %d MxAmpduDen %d mimoPS %d vht_mcs11 %d shortSlot %d BI %d DTIM %d enc type %d p2p cab STA %d",
4091 		 updateEntry,
4092 		 pAddBssParams->staContext.maxAmpduDensity,
4093 		 pAddBssParams->staContext.mimoPS,
4094 		 pAddBssParams->staContext.vht_mcs_10_11_supp,
4095 		 pAddBssParams->shortSlotTimeSupported,
4096 		 pAddBssParams->beaconInterval, pAddBssParams->dtimPeriod,
4097 		 pAddBssParams->staContext.encryptType,
4098 		 pAddBssParams->staContext.p2pCapableSta);
4099 	if (cds_is_5_mhz_enabled()) {
4100 		pAddBssParams->ch_width = CH_WIDTH_5MHZ;
4101 		pAddBssParams->staContext.ch_width = CH_WIDTH_5MHZ;
4102 	} else if (cds_is_10_mhz_enabled()) {
4103 		pAddBssParams->ch_width = CH_WIDTH_10MHZ;
4104 		pAddBssParams->staContext.ch_width = CH_WIDTH_10MHZ;
4105 	}
4106 	lim_set_sta_ctx_twt(&pAddBssParams->staContext, pe_session);
4107 
4108 	if (lim_is_fils_connection(pe_session))
4109 		pAddBssParams->no_ptk_4_way = true;
4110 
4111 	/* we need to defer the message until we get the response back */
4112 	SET_LIM_PROCESS_DEFD_MESGS(mac, false);
4113 
4114 	retCode = wma_send_peer_assoc_req(pAddBssParams);
4115 	if (QDF_IS_STATUS_ERROR(retCode)) {
4116 		SET_LIM_PROCESS_DEFD_MESGS(mac, true);
4117 		pe_err("wma_send_peer_assoc_req failed=%X",
4118 		       retCode);
4119 	}
4120 	qdf_mem_free(pAddBssParams);
4121 
4122 returnFailure:
4123 	/* Clean-up will be done by the caller... */
4124 	return retCode;
4125 }
4126 
4127 QDF_STATUS lim_sta_send_add_bss_pre_assoc(struct mac_context *mac,
4128 					  struct pe_session *pe_session)
4129 {
4130 	struct bss_params *pAddBssParams = NULL;
4131 	uint32_t retCode;
4132 	tSchBeaconStruct *pBeaconStruct;
4133 	bool chan_width_support = false;
4134 	tDot11fIEVHTOperation *vht_oper = NULL;
4135 	tDot11fIEVHTCaps *vht_caps = NULL;
4136 	uint32_t listen_interval = MLME_CFG_LISTEN_INTERVAL;
4137 	struct bss_description *bssDescription = NULL;
4138 	struct mlme_vht_capabilities_info *vht_cap_info;
4139 
4140 	if (!pe_session->lim_join_req) {
4141 		pe_err("Lim Join request is NULL");
4142 		return QDF_STATUS_E_FAILURE;
4143 	}
4144 
4145 	bssDescription = &pe_session->lim_join_req->bssDescription;
4146 	vht_cap_info = &mac->mlme_cfg->vht_caps.vht_cap_info;
4147 
4148 	pBeaconStruct = qdf_mem_malloc(sizeof(tSchBeaconStruct));
4149 	if (!pBeaconStruct)
4150 		return QDF_STATUS_E_NOMEM;
4151 
4152 	/* Package SIR_HAL_ADD_BSS_REQ message parameters */
4153 	pAddBssParams = qdf_mem_malloc(sizeof(struct bss_params));
4154 	if (!pAddBssParams) {
4155 		retCode = QDF_STATUS_E_NOMEM;
4156 		goto returnFailure;
4157 	}
4158 
4159 	lim_extract_ap_capabilities(mac, (uint8_t *) bssDescription->ieFields,
4160 			lim_get_ielen_from_bss_description(bssDescription),
4161 			pBeaconStruct);
4162 
4163 	if (mac->lim.gLimProtectionControl !=
4164 	    MLME_FORCE_POLICY_PROTECTION_DISABLE)
4165 		lim_decide_sta_protection_on_assoc(mac, pBeaconStruct,
4166 						   pe_session);
4167 	qdf_mem_copy(pAddBssParams->bssId, bssDescription->bssId,
4168 		     sizeof(tSirMacAddr));
4169 
4170 	pAddBssParams->beaconInterval = bssDescription->beaconInterval;
4171 
4172 	pAddBssParams->dtimPeriod = pBeaconStruct->tim.dtimPeriod;
4173 	pAddBssParams->updateBss = false;
4174 
4175 	pAddBssParams->nwType = bssDescription->nwType;
4176 
4177 	pAddBssParams->shortSlotTimeSupported =
4178 		(uint8_t) pBeaconStruct->capabilityInfo.shortSlotTime;
4179 	pAddBssParams->llbCoexist =
4180 		(uint8_t) pe_session->beaconParams.llbCoexist;
4181 
4182 	/* Use the advertised capabilities from the received beacon/PR */
4183 	if (IS_DOT11_MODE_HT(pe_session->dot11mode)) {
4184 		chan_width_support =
4185 			lim_get_ht_capability(mac,
4186 					      eHT_SUPPORTED_CHANNEL_WIDTH_SET,
4187 					      pe_session);
4188 		lim_sta_add_bss_update_ht_parameter(bssDescription->chan_freq,
4189 						    &pBeaconStruct->HTCaps,
4190 						    &pBeaconStruct->HTInfo,
4191 						    chan_width_support,
4192 						    pAddBssParams);
4193 	}
4194 
4195 	if (pe_session->vhtCapability &&
4196 		(IS_BSS_VHT_CAPABLE(pBeaconStruct->VHTCaps) ||
4197 		 IS_BSS_VHT_CAPABLE(pBeaconStruct->vendor_vht_ie.VHTCaps))) {
4198 
4199 		pAddBssParams->vhtCapable = 1;
4200 		if (pBeaconStruct->VHTOperation.present)
4201 			vht_oper = &pBeaconStruct->VHTOperation;
4202 		else if (pBeaconStruct->vendor_vht_ie.VHTOperation.present) {
4203 			vht_oper = &pBeaconStruct->vendor_vht_ie.VHTOperation;
4204 			pe_debug("VHT Operation is present in vendor Specific IE");
4205 		}
4206 
4207 		/*
4208 		 * in limExtractApCapability function intersection of FW
4209 		 * advertised channel width and AP advertised channel width has
4210 		 * been taken into account for calculating
4211 		 * pe_session->ch_width
4212 		 */
4213 		pAddBssParams->ch_width =
4214 			pe_session->ch_width;
4215 		pAddBssParams->staContext.maxAmpduSize =
4216 			SIR_MAC_GET_VHT_MAX_AMPDU_EXPO(
4217 					pAddBssParams->staContext.vht_caps);
4218 	} else {
4219 		pAddBssParams->vhtCapable = 0;
4220 	}
4221 
4222 	if (lim_is_session_he_capable(pe_session) &&
4223 	    pBeaconStruct->he_cap.present) {
4224 		lim_update_bss_he_capable(mac, pAddBssParams);
4225 		lim_add_bss_he_cfg(pAddBssParams, pe_session);
4226 	}
4227 
4228 	if (lim_is_session_eht_capable(pe_session) &&
4229 	    pBeaconStruct->eht_cap.present) {
4230 		lim_update_bss_eht_capable(mac, pAddBssParams);
4231 		lim_add_bss_eht_cfg(pAddBssParams, pe_session);
4232 	}
4233 
4234 	/*
4235 	 * Populate the STA-related parameters here
4236 	 * Note that the STA here refers to the AP
4237 	 */
4238 	/* Identifying AP as an STA */
4239 	pAddBssParams->staContext.staType = STA_ENTRY_OTHER;
4240 
4241 	qdf_mem_copy(pAddBssParams->staContext.bssId,
4242 			bssDescription->bssId, sizeof(tSirMacAddr));
4243 
4244 	listen_interval = mac->mlme_cfg->sap_cfg.listen_interval;
4245 	pAddBssParams->staContext.listenInterval = listen_interval;
4246 	pAddBssParams->staContext.assocId = 0;
4247 	pAddBssParams->staContext.uAPSD = 0;
4248 	pAddBssParams->staContext.maxSPLen = 0;
4249 	pAddBssParams->staContext.updateSta = false;
4250 
4251 	if (IS_DOT11_MODE_HT(pe_session->dot11mode)
4252 			&& (pBeaconStruct->HTCaps.present)) {
4253 		pAddBssParams->staContext.htCapable = 1;
4254 		if (pe_session->vhtCapability &&
4255 			(IS_BSS_VHT_CAPABLE(pBeaconStruct->VHTCaps) ||
4256 			 IS_BSS_VHT_CAPABLE(
4257 				 pBeaconStruct->vendor_vht_ie.VHTCaps))) {
4258 			pAddBssParams->staContext.vhtCapable = 1;
4259 			if (pBeaconStruct->VHTCaps.present)
4260 				vht_caps = &pBeaconStruct->VHTCaps;
4261 			else if (pBeaconStruct->vendor_vht_ie.VHTCaps.present)
4262 				vht_caps = &pBeaconStruct->
4263 						vendor_vht_ie.VHTCaps;
4264 
4265 			if ((vht_caps) && (vht_caps->suBeamFormerCap ||
4266 				vht_caps->muBeamformerCap) &&
4267 				pe_session->vht_config.su_beam_formee)
4268 				pAddBssParams->staContext.vhtTxBFCapable = 1;
4269 
4270 			if ((vht_caps) && vht_caps->muBeamformerCap &&
4271 				pe_session->vht_config.mu_beam_formee)
4272 				pAddBssParams->staContext.vhtTxMUBformeeCapable
4273 						= 1;
4274 
4275 			if ((vht_caps) && vht_caps->suBeamformeeCap &&
4276 				pe_session->vht_config.su_beam_former)
4277 				pAddBssParams->staContext.enable_su_tx_bformer
4278 						= 1;
4279 		}
4280 		if (lim_is_session_he_capable(pe_session) &&
4281 			pBeaconStruct->he_cap.present)
4282 			lim_intersect_ap_he_caps(pe_session, pAddBssParams,
4283 						 pBeaconStruct, NULL,
4284 						 bssDescription);
4285 
4286 		if (lim_is_session_eht_capable(pe_session) &&
4287 		    pBeaconStruct->eht_cap.present)
4288 			lim_intersect_ap_eht_caps(pe_session, pAddBssParams,
4289 						  pBeaconStruct, NULL);
4290 
4291 		if (pBeaconStruct->HTCaps.supportedChannelWidthSet &&
4292 		    chan_width_support) {
4293 			pAddBssParams->staContext.ch_width =
4294 				(uint8_t) pBeaconStruct->HTInfo.
4295 				recommendedTxWidthSet;
4296 			if ((vht_oper) &&
4297 					pAddBssParams->staContext.vhtCapable &&
4298 					vht_oper->chanWidth)
4299 				pAddBssParams->staContext.ch_width =
4300 					vht_oper->chanWidth + 1;
4301 		} else {
4302 			pAddBssParams->staContext.ch_width =
4303 				CH_WIDTH_20MHZ;
4304 		}
4305 		pAddBssParams->staContext.mimoPS =
4306 			(tSirMacHTMIMOPowerSaveState) pBeaconStruct->HTCaps.
4307 			mimoPowerSave;
4308 		pAddBssParams->staContext.maxAmpduDensity =
4309 			pBeaconStruct->HTCaps.mpduDensity;
4310 		/*
4311 		 * We will check gShortGI20Mhz and gShortGI40Mhz from ini file.
4312 		 * if they are set then we will use what ever Beacon coming
4313 		 * from AP supports. If these values are set as 0 in ini file
4314 		 * then we will hardcode this values to 0.
4315 		 */
4316 		if (pe_session->ht_config.short_gi_20_mhz)
4317 			pAddBssParams->staContext.fShortGI20Mhz =
4318 				(uint8_t)pBeaconStruct->HTCaps.shortGI20MHz;
4319 		else
4320 			pAddBssParams->staContext.fShortGI20Mhz = false;
4321 
4322 		if (pe_session->ht_config.short_gi_40_mhz)
4323 			pAddBssParams->staContext.fShortGI40Mhz =
4324 				(uint8_t) pBeaconStruct->HTCaps.shortGI40MHz;
4325 		else
4326 			pAddBssParams->staContext.fShortGI40Mhz = false;
4327 
4328 		pAddBssParams->staContext.maxAmpduSize =
4329 			pBeaconStruct->HTCaps.maxRxAMPDUFactor;
4330 		if (pAddBssParams->staContext.vhtTxBFCapable
4331 		    && vht_cap_info->disable_ldpc_with_txbf_ap) {
4332 			pAddBssParams->staContext.htLdpcCapable = 0;
4333 			pAddBssParams->staContext.vhtLdpcCapable = 0;
4334 		} else {
4335 			if (pe_session->txLdpcIniFeatureEnabled & 0x1)
4336 				pAddBssParams->staContext.htLdpcCapable =
4337 					(uint8_t) pBeaconStruct->HTCaps.
4338 						advCodingCap;
4339 			else
4340 				pAddBssParams->staContext.htLdpcCapable = 0;
4341 
4342 			if (pBeaconStruct->VHTCaps.present)
4343 				vht_caps = &pBeaconStruct->VHTCaps;
4344 			else if (pBeaconStruct->vendor_vht_ie.VHTCaps.present) {
4345 				vht_caps =
4346 					&pBeaconStruct->vendor_vht_ie.VHTCaps;
4347 			}
4348 			if (vht_caps &&
4349 				(pe_session->txLdpcIniFeatureEnabled & 0x2))
4350 				pAddBssParams->staContext.vhtLdpcCapable =
4351 					(uint8_t) vht_caps->ldpcCodingCap;
4352 			else
4353 				pAddBssParams->staContext.vhtLdpcCapable = 0;
4354 		}
4355 	}
4356 	/*
4357 	 * If WMM IE or 802.11E IE is not present
4358 	 * and AP is HT AP then enable WMM
4359 	 */
4360 	if ((pe_session->limWmeEnabled && (pBeaconStruct->wmeEdcaPresent ||
4361 			pAddBssParams->staContext.htCapable)) ||
4362 			(pe_session->limQosEnabled &&
4363 			 (pBeaconStruct->edcaPresent ||
4364 			  pAddBssParams->staContext.htCapable)))
4365 		pAddBssParams->staContext.wmmEnabled = 1;
4366 	else
4367 		pAddBssParams->staContext.wmmEnabled = 0;
4368 
4369 	/* Update the rates */
4370 	lim_populate_peer_rate_set(mac,
4371 			&pAddBssParams->staContext.
4372 			supportedRates,
4373 			pBeaconStruct->HTCaps.supportedMCSSet,
4374 			false, pe_session,
4375 			&pBeaconStruct->VHTCaps,
4376 			&pBeaconStruct->he_cap,
4377 			&pBeaconStruct->eht_cap, NULL,
4378 			bssDescription);
4379 
4380 	pAddBssParams->staContext.encryptType = pe_session->encryptType;
4381 
4382 	pAddBssParams->maxTxPower = pe_session->maxTxPower;
4383 
4384 	pAddBssParams->staContext.smesessionId = pe_session->smeSessionId;
4385 	pAddBssParams->staContext.sessionId = pe_session->peSessionId;
4386 
4387 	if (pe_session->limRmfEnabled) {
4388 		pAddBssParams->rmfEnabled = 1;
4389 		pAddBssParams->staContext.rmfEnabled = 1;
4390 	}
4391 	/* Set a new state for MLME */
4392 	pe_session->limMlmState = eLIM_MLM_WT_ADD_BSS_RSP_PREASSOC_STATE;
4393 
4394 	MTRACE(mac_trace
4395 		       (mac, TRACE_CODE_MLM_STATE, pe_session->peSessionId,
4396 		       pe_session->limMlmState));
4397 	if (cds_is_5_mhz_enabled()) {
4398 		pAddBssParams->ch_width = CH_WIDTH_5MHZ;
4399 		pAddBssParams->staContext.ch_width = CH_WIDTH_5MHZ;
4400 	} else if (cds_is_10_mhz_enabled()) {
4401 		pAddBssParams->ch_width = CH_WIDTH_10MHZ;
4402 		pAddBssParams->staContext.ch_width = CH_WIDTH_10MHZ;
4403 	}
4404 
4405 	if (lim_is_fils_connection(pe_session))
4406 		pAddBssParams->no_ptk_4_way = true;
4407 
4408 	retCode = wma_pre_assoc_req(pAddBssParams);
4409 	lim_process_sta_add_bss_rsp_pre_assoc(mac, pAddBssParams,
4410 					      pe_session, retCode);
4411 	qdf_mem_free(pAddBssParams);
4412 	/*
4413 	 * Set retCode success as lim_process_sta_add_bss_rsp_pre_assoc take
4414 	 * care of failure
4415 	 */
4416 	retCode = QDF_STATUS_SUCCESS;
4417 
4418 returnFailure:
4419 	/* Clean-up will be done by the caller... */
4420 	qdf_mem_free(pBeaconStruct);
4421 	return retCode;
4422 }
4423 
4424 /**
4425  * lim_prepare_and_send_del_all_sta_cnf() - prepares and send del all sta cnf
4426  * @mac:          mac global context
4427  * @status_code:    status code
4428  * @pe_session: session context
4429  *
4430  * deletes DPH entry, changes the MLM mode for station, calls
4431  * lim_send_del_sta_cnf
4432  *
4433  * Return: void
4434  */
4435 void lim_prepare_and_send_del_all_sta_cnf(struct mac_context *mac,
4436 					  tSirResultCodes status_code,
4437 					  struct pe_session *pe_session)
4438 {
4439 	tLimMlmDeauthCnf mlm_deauth;
4440 	tpDphHashNode sta_ds = NULL;
4441 	uint32_t i;
4442 
4443 	if (!LIM_IS_AP_ROLE(pe_session))
4444 		return;
4445 
4446 	for (i = 1; i < pe_session->dph.dphHashTable.size; i++) {
4447 		sta_ds = dph_get_hash_entry(mac, i,
4448 					    &pe_session->dph.dphHashTable);
4449 		if (!sta_ds)
4450 			continue;
4451 
4452 		lim_delete_dph_hash_entry(mac, sta_ds->staAddr,
4453 					  sta_ds->assocId, pe_session);
4454 		if (lim_is_mlo_conn(pe_session, sta_ds))
4455 			lim_release_mlo_conn_idx(mac, sta_ds->assocId,
4456 						 pe_session, false);
4457 		else
4458 			lim_release_peer_idx(mac, sta_ds->assocId, pe_session);
4459 	}
4460 
4461 	qdf_set_macaddr_broadcast(&mlm_deauth.peer_macaddr);
4462 	mlm_deauth.resultCode = status_code;
4463 	mlm_deauth.deauthTrigger = eLIM_HOST_DEAUTH;
4464 	mlm_deauth.sessionId = pe_session->peSessionId;
4465 
4466 	lim_post_sme_message(mac, LIM_MLM_DEAUTH_CNF,
4467 			    (uint32_t *)&mlm_deauth);
4468 }
4469 
4470 /**
4471  * lim_prepare_and_send_del_sta_cnf() - prepares and send del sta cnf
4472  *
4473  * @mac:          mac global context
4474  * @sta:        sta dph node
4475  * @status_code:    status code
4476  * @pe_session: session context
4477  *
4478  * deletes DPH entry, changes the MLM mode for station, calls
4479  * lim_send_del_sta_cnf
4480  *
4481  * Return: void
4482  */
4483 void
4484 lim_prepare_and_send_del_sta_cnf(struct mac_context *mac, tpDphHashNode sta,
4485 				 tSirResultCodes status_code,
4486 				 struct pe_session *pe_session)
4487 {
4488 	uint16_t staDsAssocId = 0;
4489 	struct qdf_mac_addr sta_dsaddr;
4490 	struct lim_sta_context mlmStaContext;
4491 	bool mlo_conn = false;
4492 
4493 	if (!sta) {
4494 		pe_err("sta is NULL");
4495 		return;
4496 	}
4497 
4498 	staDsAssocId = sta->assocId;
4499 	qdf_mem_copy((uint8_t *) sta_dsaddr.bytes,
4500 		     sta->staAddr, QDF_MAC_ADDR_SIZE);
4501 
4502 	mlmStaContext = sta->mlmStaContext;
4503 
4504 	if (LIM_IS_AP_ROLE(pe_session)) {
4505 		mlo_conn = lim_is_mlo_conn(pe_session, sta);
4506 		if (mlo_conn)
4507 			lim_release_mlo_conn_idx(mac, sta->assocId,
4508 						 pe_session, false);
4509 		else
4510 			lim_release_peer_idx(mac, sta->assocId, pe_session);
4511 	}
4512 
4513 	lim_delete_dph_hash_entry(mac, sta->staAddr, sta->assocId,
4514 				  pe_session);
4515 
4516 	if (LIM_IS_STA_ROLE(pe_session)) {
4517 		pe_session->limMlmState = eLIM_MLM_IDLE_STATE;
4518 		MTRACE(mac_trace(mac, TRACE_CODE_MLM_STATE,
4519 				 pe_session->peSessionId,
4520 				 pe_session->limMlmState));
4521 	}
4522 
4523 	lim_send_del_sta_cnf(mac, sta_dsaddr, staDsAssocId, mlmStaContext,
4524 			     status_code, pe_session);
4525 }
4526 
4527 /** -------------------------------------------------------------
4528    \fn lim_init_pre_auth_timer_table
4529    \brief Initialize the Pre Auth Tanle and creates the timer for
4530        each node for the timeout value got from cfg.
4531    \param     struct mac_context *   mac
4532    \param     tpLimPreAuthTable pPreAuthTimerTable
4533    \return none
4534    -------------------------------------------------------------*/
4535 void lim_init_pre_auth_timer_table(struct mac_context *mac,
4536 				   tpLimPreAuthTable pPreAuthTimerTable)
4537 {
4538 	uint32_t cfgValue;
4539 	uint32_t authNodeIdx;
4540 
4541 	tLimPreAuthNode **pAuthNode = pPreAuthTimerTable->pTable;
4542 
4543 	/* Get AUTH_RSP Timers value */
4544 	cfgValue = SYS_MS_TO_TICKS(mac->mlme_cfg->timeouts.auth_rsp_timeout);
4545 	for (authNodeIdx = 0; authNodeIdx < pPreAuthTimerTable->numEntry;
4546 	     authNodeIdx++) {
4547 		if (tx_timer_create(mac, &(pAuthNode[authNodeIdx]->timer),
4548 			"AUTH RESPONSE TIMEOUT",
4549 			lim_auth_response_timer_handler, authNodeIdx,
4550 			cfgValue, 0, TX_NO_ACTIVATE) != TX_SUCCESS) {
4551 			pe_err("Cannot create Auth Rsp timer of Index: %d",
4552 				authNodeIdx);
4553 			return;
4554 		}
4555 		pAuthNode[authNodeIdx]->authNodeIdx = (uint8_t) authNodeIdx;
4556 		pAuthNode[authNodeIdx]->fFree = 1;
4557 	}
4558 }
4559 
4560 /** -------------------------------------------------------------
4561    \fn lim_acquire_free_pre_auth_node
4562    \brief Retrieves a free Pre Auth node from Pre Auth Table.
4563    \param     struct mac_context *   mac
4564    \param     tpLimPreAuthTable pPreAuthTimerTable
4565    \return none
4566    -------------------------------------------------------------*/
4567 tLimPreAuthNode *lim_acquire_free_pre_auth_node(struct mac_context *mac,
4568 						tpLimPreAuthTable pPreAuthTimerTable)
4569 {
4570 	uint32_t i;
4571 	tLimPreAuthNode **pTempNode = pPreAuthTimerTable->pTable;
4572 
4573 	for (i = 0; i < pPreAuthTimerTable->numEntry; i++) {
4574 		if (pTempNode[i]->fFree == 1) {
4575 			pTempNode[i]->fFree = 0;
4576 			return pTempNode[i];
4577 		}
4578 	}
4579 
4580 	return NULL;
4581 }
4582 
4583 /** -------------------------------------------------------------
4584    \fn lim_get_pre_auth_node_from_index
4585    \brief Depending on the Index this retrieves the pre auth node.
4586    \param     struct mac_context *   mac
4587    \param     tpLimPreAuthTable pAuthTable
4588    \param     uint32_t authNodeIdx
4589    \return none
4590    -------------------------------------------------------------*/
4591 tLimPreAuthNode *lim_get_pre_auth_node_from_index(struct mac_context *mac,
4592 						  tpLimPreAuthTable pAuthTable,
4593 						  uint32_t authNodeIdx)
4594 {
4595 	if ((authNodeIdx >= pAuthTable->numEntry)
4596 	    || (!pAuthTable->pTable)) {
4597 		pe_err("Invalid Auth Timer Index: %d NumEntry: %d",
4598 			authNodeIdx, pAuthTable->numEntry);
4599 		return NULL;
4600 	}
4601 
4602 	return pAuthTable->pTable[authNodeIdx];
4603 }
4604 
4605 /* Util API to check if the channels supported by STA is within range */
4606 QDF_STATUS lim_is_dot11h_supported_channels_valid(struct mac_context *mac,
4607 						     tSirAssocReq *assoc)
4608 {
4609 	/*
4610 	 * Allow all the stations to join with us.
4611 	 * 802.11h-2003 11.6.1 => An AP may use the supported channels list for associated STAs
4612 	 * as an input into an algorithm used to select a new channel for the BSS.
4613 	 * The specification of the algorithm is beyond the scope of this amendment.
4614 	 */
4615 
4616 	return QDF_STATUS_SUCCESS;
4617 }
4618 
4619 /* Util API to check if the txpower supported by STA is within range */
4620 QDF_STATUS lim_is_dot11h_power_capabilities_in_range(struct mac_context *mac,
4621 							tSirAssocReq *assoc,
4622 							struct pe_session *pe_session)
4623 {
4624 	int8_t localMaxTxPower;
4625 	uint8_t local_pwr_constraint;
4626 
4627 	localMaxTxPower = wlan_reg_get_channel_reg_power_for_freq(
4628 					mac->pdev, pe_session->curr_op_freq);
4629 
4630 	local_pwr_constraint = mac->mlme_cfg->power.local_power_constraint;
4631 	localMaxTxPower -= (int8_t)local_pwr_constraint;
4632 
4633 	/**
4634 	 *  The min Tx Power of the associating station should not be greater than (regulatory
4635 	 *  max tx power - local power constraint configured on AP).
4636 	 */
4637 	if (assoc->powerCapability.minTxPower > localMaxTxPower) {
4638 		pe_warn("minTxPower (STA): %d, localMaxTxPower (AP): %d",
4639 			assoc->powerCapability.minTxPower, localMaxTxPower);
4640 		return QDF_STATUS_E_FAILURE;
4641 	}
4642 
4643 	return QDF_STATUS_SUCCESS;
4644 }
4645 
4646 void lim_fill_rx_highest_supported_rate(struct mac_context *mac,
4647 					uint16_t *rxHighestRate,
4648 					uint8_t *pSupportedMCSSet)
4649 {
4650 	tSirMacRxHighestSupportRate *pRxHighestRate;
4651 	uint8_t *pBuf;
4652 	uint16_t rate = 0;
4653 
4654 	pBuf = pSupportedMCSSet + MCS_RX_HIGHEST_SUPPORTED_RATE_BYTE_OFFSET;
4655 	rate = lim_get_u16(pBuf);
4656 
4657 	pRxHighestRate = (tSirMacRxHighestSupportRate *) &rate;
4658 	*rxHighestRate = pRxHighestRate->rate;
4659 
4660 	return;
4661 }
4662 
4663 /** -------------------------------------------------------------
4664    \fn     lim_send_sme_unprotected_mgmt_frame_ind
4665    \brief  Forwards the unprotected management frame to SME.
4666    \param  struct mac_context *   mac
4667    \param  frameType - 802.11 frame type
4668    \param  frame - frame buffer
4669    \param  sessionId - id for the current session
4670    \param  pe_session - PE session context
4671    \return none
4672    -------------------------------------------------------------*/
4673 void lim_send_sme_unprotected_mgmt_frame_ind(struct mac_context *mac, uint8_t frameType,
4674 					     uint8_t *frame, uint32_t frameLen,
4675 					     uint16_t sessionId,
4676 					     struct pe_session *pe_session)
4677 {
4678 	struct scheduler_msg mmhMsg = {0};
4679 	tSirSmeUnprotMgmtFrameInd *pSirSmeMgmtFrame = NULL;
4680 	uint16_t length;
4681 
4682 	length = sizeof(tSirSmeUnprotMgmtFrameInd) + frameLen;
4683 
4684 	pSirSmeMgmtFrame = qdf_mem_malloc(length);
4685 	if (!pSirSmeMgmtFrame)
4686 		return;
4687 
4688 	pSirSmeMgmtFrame->sessionId = sessionId;
4689 	pSirSmeMgmtFrame->frameType = frameType;
4690 
4691 	qdf_mem_copy(pSirSmeMgmtFrame->frameBuf, frame, frameLen);
4692 	pSirSmeMgmtFrame->frameLen = frameLen;
4693 
4694 	mmhMsg.type = eWNI_SME_UNPROT_MGMT_FRM_IND;
4695 	mmhMsg.bodyptr = pSirSmeMgmtFrame;
4696 	mmhMsg.bodyval = 0;
4697 
4698 	lim_sys_process_mmh_msg_api(mac, &mmhMsg);
4699 	return;
4700 }
4701 
4702 #ifdef FEATURE_WLAN_ESE
4703 void lim_send_sme_tsm_ie_ind(struct mac_context *mac,
4704 			     struct pe_session *pe_session,
4705 			     uint8_t tid, uint8_t state,
4706 			     uint16_t measurement_interval)
4707 {
4708 	struct scheduler_msg msg = {0};
4709 	struct tsm_ie_ind *tsm_ie_ind;
4710 
4711 	if (!mac || !pe_session)
4712 		return;
4713 
4714 	tsm_ie_ind = qdf_mem_malloc(sizeof(*tsm_ie_ind));
4715 	if (!tsm_ie_ind)
4716 		return;
4717 
4718 	tsm_ie_ind->sessionId = pe_session->smeSessionId;
4719 	tsm_ie_ind->tsm_ie.tsid = tid;
4720 	tsm_ie_ind->tsm_ie.state = state;
4721 	tsm_ie_ind->tsm_ie.msmt_interval = measurement_interval;
4722 
4723 	msg.type = eWNI_SME_TSM_IE_IND;
4724 	msg.bodyptr = tsm_ie_ind;
4725 	msg.bodyval = 0;
4726 
4727 	lim_sys_process_mmh_msg_api(mac, &msg);
4728 }
4729 #endif /* FEATURE_WLAN_ESE */
4730 
4731 void lim_extract_ies_from_deauth_disassoc(struct pe_session *session,
4732 					  uint8_t *deauth_disassoc_frame,
4733 					  uint16_t deauth_disassoc_frame_len)
4734 {
4735 	uint16_t reason_code, ie_offset;
4736 	struct element_info ie;
4737 
4738 	if (!session) {
4739 		pe_err("NULL session");
4740 		return;
4741 	}
4742 
4743 	/* Get the offset of IEs */
4744 	ie_offset = sizeof(struct wlan_frame_hdr) + sizeof(reason_code);
4745 
4746 	if (!deauth_disassoc_frame || deauth_disassoc_frame_len <= ie_offset)
4747 		return;
4748 
4749 	ie.ptr = deauth_disassoc_frame + ie_offset;
4750 	ie.len = deauth_disassoc_frame_len - ie_offset;
4751 
4752 	mlme_set_peer_disconnect_ies(session->vdev, &ie);
4753 }
4754