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