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