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 *
22 * This file lim_process_assoc_rsp_frame.cc contains the code
23 * for processing Re/Association Response Frame.
24 * Author: Chandra Modumudi
25 * Date: 03/18/02
26 * History:-
27 * Date Modified by Modification Information
28 * --------------------------------------------------------------------
29 *
30 */
31
32 #include "wni_api.h"
33 #include "wni_cfg.h"
34 #include "ani_global.h"
35 #include "sch_api.h"
36
37 #include "utils_api.h"
38 #include "lim_types.h"
39 #include "lim_utils.h"
40 #include "lim_assoc_utils.h"
41 #include "lim_security_utils.h"
42 #include "lim_ser_des_utils.h"
43 #include "lim_send_messages.h"
44 #include "lim_process_fils.h"
45 #include "wlan_dlm_api.h"
46 #include "wlan_mlme_twt_api.h"
47 #include "wlan_mlme_ucfg_api.h"
48 #include "wlan_connectivity_logging.h"
49 #include <lim_mlo.h>
50 #include "parser_api.h"
51 #include "wlan_twt_cfg_ext_api.h"
52 #include "wlan_mlo_mgr_roam.h"
53
54 /**
55 * lim_update_stads_htcap() - Updates station Descriptor HT capability
56 * @mac_ctx: Pointer to Global MAC structure
57 * @sta_ds: Station Descriptor in DPH
58 * @assoc_rsp: Pointer to Association Response Structure
59 * @session_entry : PE session Entry
60 *
61 * This function is called to Update the HT capabilities in
62 * Station Descriptor (dph) Details from
63 * Association / ReAssociation Response Frame
64 *
65 * Return: None
66 */
lim_update_stads_htcap(struct mac_context * mac_ctx,tpDphHashNode sta_ds,tpSirAssocRsp assoc_rsp,struct pe_session * session_entry)67 static void lim_update_stads_htcap(struct mac_context *mac_ctx,
68 tpDphHashNode sta_ds, tpSirAssocRsp assoc_rsp,
69 struct pe_session *session_entry)
70 {
71 uint16_t highest_rxrate = 0;
72 tDot11fIEHTCaps *ht_caps;
73
74 ht_caps = &assoc_rsp->HTCaps;
75 sta_ds->mlmStaContext.htCapability = assoc_rsp->HTCaps.present;
76 if (assoc_rsp->HTCaps.present) {
77 sta_ds->htGreenfield =
78 (uint8_t) ht_caps->greenField;
79 if (session_entry->htSupportedChannelWidthSet) {
80 sta_ds->htSupportedChannelWidthSet =
81 (uint8_t) (ht_caps->supportedChannelWidthSet ?
82 assoc_rsp->HTInfo.recommendedTxWidthSet :
83 ht_caps->supportedChannelWidthSet);
84 } else
85 sta_ds->htSupportedChannelWidthSet =
86 eHT_CHANNEL_WIDTH_20MHZ;
87 sta_ds->htLsigTXOPProtection =
88 (uint8_t) ht_caps->lsigTXOPProtection;
89 sta_ds->htMIMOPSState =
90 (tSirMacHTMIMOPowerSaveState)ht_caps->mimoPowerSave;
91 sta_ds->htMaxAmsduLength =
92 (uint8_t) ht_caps->maximalAMSDUsize;
93 sta_ds->htAMpduDensity = ht_caps->mpduDensity;
94 sta_ds->htDsssCckRate40MHzSupport =
95 (uint8_t) ht_caps->dsssCckMode40MHz;
96 sta_ds->htMaxRxAMpduFactor =
97 ht_caps->maxRxAMPDUFactor;
98 lim_fill_rx_highest_supported_rate(mac_ctx, &highest_rxrate,
99 ht_caps->supportedMCSSet);
100 sta_ds->supportedRates.rxHighestDataRate =
101 highest_rxrate;
102 /*
103 * This is for AP as peer STA and we are INFRA STA
104 *.We will put APs offset in dph node which is peer STA
105 */
106 sta_ds->htSecondaryChannelOffset =
107 (uint8_t) assoc_rsp->HTInfo.secondaryChannelOffset;
108
109 /* Check if we have support for gShortGI20Mhz and
110 * gShortGI40Mhz from ini file
111 */
112 if (session_entry->ht_config.short_gi_20_mhz)
113 sta_ds->htShortGI20Mhz =
114 (uint8_t)assoc_rsp->HTCaps.shortGI20MHz;
115 else
116 sta_ds->htShortGI20Mhz = false;
117
118 if (session_entry->ht_config.short_gi_40_mhz)
119 sta_ds->htShortGI40Mhz =
120 (uint8_t)assoc_rsp->HTCaps.shortGI40MHz;
121 else
122 sta_ds->htShortGI40Mhz = false;
123 }
124 }
125
126 /**
127 * lim_update_assoc_sta_datas() - Updates station Descriptor
128 * mac_ctx: Pointer to Global MAC structure
129 * sta_ds: Station Descriptor in DPH
130 * assoc_rsp: Pointer to Association Response Structure
131 * session_entry : PE session Entry
132 *
133 * This function is called to Update the Station Descriptor (dph) Details from
134 * Association / ReAssociation Response Frame
135 *
136 * Return: None
137 */
lim_update_assoc_sta_datas(struct mac_context * mac_ctx,tpDphHashNode sta_ds,tpSirAssocRsp assoc_rsp,struct pe_session * session_entry,tSchBeaconStruct * beacon)138 void lim_update_assoc_sta_datas(struct mac_context *mac_ctx,
139 tpDphHashNode sta_ds, tpSirAssocRsp assoc_rsp,
140 struct pe_session *session_entry, tSchBeaconStruct *beacon)
141 {
142 uint32_t phy_mode;
143 bool qos_mode;
144 tDot11fIEVHTCaps *vht_caps = NULL;
145 tDot11fIEhe_cap *he_cap = NULL;
146 tDot11fIEeht_cap *eht_cap = NULL;
147 struct bss_description *bss_desc = NULL;
148 tDot11fIEVHTOperation *vht_oper = NULL;
149 enum phy_ch_width omn_ie_ch_width;
150
151 lim_get_phy_mode(mac_ctx, &phy_mode, session_entry);
152 sta_ds->staType = STA_ENTRY_SELF;
153 limGetQosMode(session_entry, &qos_mode);
154 sta_ds->mlmStaContext.authType = session_entry->limCurrentAuthType;
155
156 /* Add capabilities information, rates and AID */
157 sta_ds->mlmStaContext.capabilityInfo = assoc_rsp->capabilityInfo;
158 sta_ds->shortPreambleEnabled =
159 (uint8_t) assoc_rsp->capabilityInfo.shortPreamble;
160
161 /* Update HT Capabilities only when the self mode supports HT */
162 if (IS_DOT11_MODE_HT(session_entry->dot11mode))
163 lim_update_stads_htcap(mac_ctx, sta_ds, assoc_rsp,
164 session_entry);
165
166 if (assoc_rsp->VHTCaps.present) {
167 vht_caps = &assoc_rsp->VHTCaps;
168 vht_oper = &assoc_rsp->VHTOperation;
169 } else if (assoc_rsp->vendor_vht_ie.VHTCaps.present) {
170 vht_caps = &assoc_rsp->vendor_vht_ie.VHTCaps;
171 vht_oper = &assoc_rsp->vendor_vht_ie.VHTOperation;
172 }
173
174 if (session_entry->vhtCapability && (vht_caps && vht_caps->present)) {
175 sta_ds->mlmStaContext.vhtCapability =
176 vht_caps->present;
177
178 /*
179 * If 11ac is supported and if the peer is
180 * sending VHT capabilities,
181 * then htMaxRxAMpduFactor should be
182 * overloaded with VHT maxAMPDULenExp
183 */
184 sta_ds->htMaxRxAMpduFactor = vht_caps->maxAMPDULenExp;
185 if (session_entry->htSupportedChannelWidthSet) {
186 if (vht_oper && vht_oper->present)
187 sta_ds->vhtSupportedChannelWidthSet =
188 lim_get_vht_ch_width(vht_caps,
189 vht_oper,
190 &assoc_rsp->HTInfo);
191 else
192 sta_ds->vhtSupportedChannelWidthSet =
193 WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ;
194 }
195 sta_ds->vht_mcs_10_11_supp = 0;
196 if (mac_ctx->mlme_cfg->vht_caps.vht_cap_info.
197 vht_mcs_10_11_supp &&
198 assoc_rsp->qcn_ie.present &&
199 assoc_rsp->qcn_ie.vht_mcs11_attr.present)
200 sta_ds->vht_mcs_10_11_supp =
201 assoc_rsp->qcn_ie.vht_mcs11_attr.
202 vht_mcs_10_11_supp;
203 }
204
205 lim_update_stads_he_caps(mac_ctx, sta_ds, assoc_rsp,
206 session_entry, beacon);
207
208 lim_update_stads_eht_caps(mac_ctx, sta_ds, assoc_rsp,
209 session_entry, beacon);
210
211 if (lim_is_sta_he_capable(sta_ds))
212 he_cap = &assoc_rsp->he_cap;
213
214 if (lim_is_sta_eht_capable(sta_ds))
215 eht_cap = &assoc_rsp->eht_cap;
216
217 if (session_entry->lim_join_req)
218 bss_desc = &session_entry->lim_join_req->bssDescription;
219
220 if (lim_populate_peer_rate_set(mac_ctx, &sta_ds->supportedRates,
221 assoc_rsp->HTCaps.supportedMCSSet,
222 false, session_entry,
223 vht_caps, he_cap, eht_cap,
224 sta_ds, bss_desc) !=
225 QDF_STATUS_SUCCESS) {
226 pe_err("could not get rateset and extended rate set");
227 return;
228 }
229 sta_ds->vhtSupportedRxNss =
230 ((sta_ds->supportedRates.vhtTxMCSMap & MCSMAPMASK2x2)
231 == MCSMAPMASK2x2) ? 1 : 2;
232
233 /* If one of the rates is 11g rates, set the ERP mode. */
234 if ((phy_mode == WNI_CFG_PHY_MODE_11G) &&
235 sirIsArate(sta_ds->supportedRates.llaRates[0] & 0x7f))
236 sta_ds->erpEnabled = eHAL_SET;
237
238 /* Could not get prop rateset from CFG. Log error. */
239 sta_ds->qosMode = 0;
240 sta_ds->lleEnabled = 0;
241
242 /* update TSID to UP mapping */
243 if (qos_mode) {
244 if (assoc_rsp->edcaPresent) {
245 QDF_STATUS status;
246
247 qdf_mem_copy(&sta_ds->qos.peer_edca_params,
248 &assoc_rsp->edca,
249 sizeof(assoc_rsp->edca));
250
251 status =
252 sch_beacon_edca_process(mac_ctx,
253 &assoc_rsp->edca, session_entry);
254 pe_debug("Edca set update based on AssocRsp: status %d",
255 status);
256 if (status != QDF_STATUS_SUCCESS) {
257 pe_err("Edca error in AssocResp");
258 } else {
259 /* update default tidmap based on ACM */
260 sta_ds->qosMode = 1;
261 sta_ds->lleEnabled = 1;
262 }
263 }
264 }
265
266 sta_ds->wmeEnabled = 0;
267 sta_ds->wsmEnabled = 0;
268 if (session_entry->limWmeEnabled && assoc_rsp->wmeEdcaPresent) {
269 QDF_STATUS status;
270
271 qdf_mem_copy(&sta_ds->qos.peer_edca_params,
272 &assoc_rsp->edca,
273 sizeof(assoc_rsp->edca));
274
275 status = sch_beacon_edca_process(mac_ctx, &assoc_rsp->edca,
276 session_entry);
277 pe_debug("WME Edca set update based on AssocRsp: status %d",
278 status);
279
280 if (status != QDF_STATUS_SUCCESS)
281 pe_err("WME Edca error in AssocResp - ignoring");
282
283 else {
284 /* update default tidmap based on HashACM */
285 sta_ds->qosMode = 1;
286 sta_ds->wmeEnabled = 1;
287 }
288 } else {
289 /*
290 * We received assoc rsp from a legacy AP.
291 * So fill in the default local EDCA params.
292 * This is needed (refer to bug #14989) as we'll
293 * be passing the gLimEdcaParams to HAL in
294 * lim_process_sta_mlm_add_bss_rsp().
295 */
296 sch_set_default_edca_params(mac_ctx, session_entry);
297 }
298
299 if (qos_mode && (!sta_ds->qosMode) &&
300 sta_ds->mlmStaContext.htCapability) {
301 /*
302 * Enable QOS for all HT AP's even though WMM
303 * or 802.11E IE is not present
304 */
305 sta_ds->qosMode = 1;
306 sta_ds->wmeEnabled = 1;
307 }
308 if (session_entry->limRmfEnabled)
309 sta_ds->rmfEnabled = 1;
310
311 if (session_entry->vhtCapability && assoc_rsp->oper_mode_ntf.present) {
312 /**
313 * OMN IE is present in the Assoc response, but the channel
314 * width/Rx NSS update will happen through the peer_assoc cmd.
315 */
316 omn_ie_ch_width = assoc_rsp->oper_mode_ntf.chanWidth;
317 pe_debug("OMN IE present in re/assoc rsp, omn_ie_ch_width: %d",
318 omn_ie_ch_width);
319 lim_update_omn_ie_ch_width(session_entry->vdev,
320 omn_ie_ch_width);
321 }
322
323 if (lim_process_srp_ie(assoc_rsp, sta_ds) == QDF_STATUS_SUCCESS)
324 lim_update_vdev_sr_elements(session_entry, sta_ds);
325 }
326
327 /**
328 * lim_update_ric_data() - update session with ric data
329 * @mac_ctx: Pointer to Global MAC structure
330 * @session_entry: PE session handle
331 * @assoc_rsp: pointer to assoc response
332 *
333 * This function is called by lim_process_assoc_rsp_frame() to
334 * update PE session context with RIC data.
335 *
336 * Return: None
337 */
lim_update_ric_data(struct mac_context * mac_ctx,struct pe_session * session_entry,tpSirAssocRsp assoc_rsp)338 static void lim_update_ric_data(struct mac_context *mac_ctx,
339 struct pe_session *session_entry, tpSirAssocRsp assoc_rsp)
340 {
341 if (session_entry->ricData) {
342 qdf_mem_free(session_entry->ricData);
343 session_entry->ricData = NULL;
344 session_entry->RICDataLen = 0;
345 }
346 if (assoc_rsp->ricPresent) {
347 session_entry->RICDataLen =
348 assoc_rsp->num_RICData * sizeof(tDot11fIERICDataDesc);
349 if (session_entry->RICDataLen) {
350 session_entry->ricData =
351 qdf_mem_malloc(session_entry->RICDataLen);
352 if (!session_entry->ricData)
353 session_entry->RICDataLen = 0;
354 else
355 qdf_mem_copy(session_entry->ricData,
356 &assoc_rsp->RICData[0],
357 session_entry->RICDataLen);
358 } else {
359 pe_err("RIC data not present");
360 }
361 } else {
362 session_entry->RICDataLen = 0;
363 session_entry->ricData = NULL;
364 }
365 return;
366 }
367
368 #ifdef FEATURE_WLAN_ESE
369 /**
370 * lim_update_ese_tspec() - update session with Tspec info.
371 * @mac_ctx: Pointer to Global MAC structure
372 * @session_entry: PE session handle
373 * @assoc_rsp: pointer to assoc response
374 *
375 * This function is called by lim_process_assoc_rsp_frame() to
376 * update PE session context with Tspec data.
377 *
378 * Return: None
379 */
lim_update_ese_tspec(struct mac_context * mac_ctx,struct pe_session * session_entry,tpSirAssocRsp assoc_rsp)380 static void lim_update_ese_tspec(struct mac_context *mac_ctx,
381 struct pe_session *session_entry, tpSirAssocRsp assoc_rsp)
382 {
383 if (session_entry->tspecIes) {
384 qdf_mem_free(session_entry->tspecIes);
385 session_entry->tspecIes = NULL;
386 session_entry->tspecLen = 0;
387 }
388 if (assoc_rsp->tspecPresent) {
389 pe_debug("Tspec EID present in assoc rsp");
390 session_entry->tspecLen =
391 assoc_rsp->num_tspecs * sizeof(tDot11fIEWMMTSPEC);
392 if (session_entry->tspecLen) {
393 session_entry->tspecIes =
394 qdf_mem_malloc(session_entry->tspecLen);
395 if (!session_entry->tspecIes)
396 session_entry->tspecLen = 0;
397 else
398 qdf_mem_copy(session_entry->tspecIes,
399 &assoc_rsp->TSPECInfo[0],
400 session_entry->tspecLen);
401 } else {
402 pe_err("TSPEC has Zero length");
403 }
404 } else {
405 session_entry->tspecLen = 0;
406 session_entry->tspecIes = NULL;
407 }
408 return;
409 }
410
411 /**
412 * lim_update_ese_tsm() - update session with TSM info.
413 * @mac_ctx: Pointer to Global MAC structure
414 * @session_entry: PE session handle
415 * @assoc_rsp: pointer to assoc response
416 *
417 * This function is called by lim_process_assoc_rsp_frame() to
418 * update PE session context with TSM IE data and send
419 * eWNI_TSM_IE_IND to SME.
420 *
421 * Return: None
422 */
lim_update_ese_tsm(struct mac_context * mac_ctx,struct pe_session * session_entry,tpSirAssocRsp assoc_rsp)423 static void lim_update_ese_tsm(struct mac_context *mac_ctx,
424 struct pe_session *session_entry, tpSirAssocRsp assoc_rsp)
425 {
426 uint8_t cnt = 0;
427 tpEseTSMContext tsm_ctx;
428
429 pe_debug("TSM IE Present in Reassoc Rsp");
430 /*
431 * Start the TSM timer only if the TSPEC
432 * Ie is present in the reassoc rsp
433 */
434 if (!assoc_rsp->tspecPresent) {
435 pe_debug("TSM present but TSPEC IE not present");
436 return;
437 }
438 tsm_ctx = &session_entry->eseContext.tsm;
439 /* Find the TSPEC IE with VO user priority */
440 for (cnt = 0; cnt < assoc_rsp->num_tspecs; cnt++) {
441 if (upToAc(assoc_rsp->TSPECInfo[cnt].user_priority) ==
442 QCA_WLAN_AC_VO) {
443 tsm_ctx->tid =
444 assoc_rsp->TSPECInfo[cnt].user_priority;
445 qdf_mem_copy(&tsm_ctx->tsmInfo,
446 &assoc_rsp->tsmIE, sizeof(struct ese_tsm_ie));
447 lim_send_sme_tsm_ie_ind(mac_ctx,
448 session_entry, assoc_rsp->tsmIE.tsid,
449 assoc_rsp->tsmIE.state,
450 assoc_rsp->tsmIE.msmt_interval);
451 if (tsm_ctx->tsmInfo.state)
452 tsm_ctx->tsmMetrics.RoamingCount++;
453 break;
454 }
455 }
456 }
457 #endif
458
459 /**
460 * lim_update_stads_ext_cap() - update sta ds with ext cap
461 * @mac_ctx: Pointer to Global MAC structure
462 * @session_entry: PE session handle
463 * @assoc_rsp: pointer to assoc response
464 *
465 * This function is called by lim_process_assoc_rsp_frame() to
466 * update STA DS with ext capabilities.
467 *
468 * Return: None
469 */
lim_update_stads_ext_cap(struct mac_context * mac_ctx,struct pe_session * session_entry,tpSirAssocRsp assoc_rsp,tpDphHashNode sta_ds)470 static void lim_update_stads_ext_cap(struct mac_context *mac_ctx,
471 struct pe_session *session_entry, tpSirAssocRsp assoc_rsp,
472 tpDphHashNode sta_ds)
473 {
474 struct s_ext_cap *ext_cap;
475 struct wlan_objmgr_vdev *vdev;
476 struct vdev_mlme_obj *mlme_obj;
477
478 if (!assoc_rsp->ExtCap.present) {
479 sta_ds->timingMeasCap = 0;
480 #ifdef FEATURE_WLAN_TDLS
481 mlme_set_tdls_prohibited(session_entry->vdev, false);
482 mlme_set_tdls_chan_switch_prohibited(session_entry->vdev,
483 false);
484 #endif
485 pe_debug("ExtCap not present");
486 return;
487 }
488
489 ext_cap = (struct s_ext_cap *)assoc_rsp->ExtCap.bytes;
490 lim_set_stads_rtt_cap(sta_ds, ext_cap, mac_ctx);
491
492 vdev = session_entry->vdev;
493 if (vdev) {
494 mlme_obj = wlan_vdev_mlme_get_cmpt_obj(vdev);
495 if (!mlme_obj)
496 pe_err("vdev component object is NULL");
497 else
498 mlme_obj->ext_vdev_ptr->connect_info.timing_meas_cap =
499 sta_ds->timingMeasCap;
500 }
501
502 #ifdef FEATURE_WLAN_TDLS
503 mlme_set_tdls_prohibited(session_entry->vdev, ext_cap->tdls_prohibited);
504 mlme_set_tdls_chan_switch_prohibited(session_entry->vdev,
505 ext_cap->tdls_chan_swit_prohibited);
506 ;
507 pe_debug("ExtCap: tdls_prohibited: %d tdls_chan_swit_prohibited: %d",
508 ext_cap->tdls_prohibited,
509 ext_cap->tdls_chan_swit_prohibited);
510 #endif
511 lim_set_peer_twt_cap(session_entry, ext_cap);
512 }
513
514 /**
515 * lim_stop_reassoc_retry_timer() - Cleanup after reassoc response is received
516 * @mac_ctx: Global MAC context
517 *
518 * Stop the reassoc retry timer and release the stored reassoc request.
519 *
520 * Return: None
521 */
lim_stop_reassoc_retry_timer(struct mac_context * mac_ctx)522 static void lim_stop_reassoc_retry_timer(struct mac_context *mac_ctx)
523 {
524 mac_ctx->lim.reAssocRetryAttempt = 0;
525 if ((mac_ctx->lim.pe_session)
526 && (NULL !=
527 mac_ctx->lim.pe_session->pLimMlmReassocRetryReq)) {
528 qdf_mem_free(
529 mac_ctx->lim.pe_session->pLimMlmReassocRetryReq);
530 mac_ctx->lim.pe_session->pLimMlmReassocRetryReq = NULL;
531 }
532 lim_deactivate_and_change_timer(mac_ctx, eLIM_REASSOC_FAIL_TIMER);
533 }
534
lim_get_nss_supported_by_ap(tDot11fIEVHTCaps * vht_caps,tDot11fIEHTCaps * ht_caps,tDot11fIEhe_cap * he_caps)535 uint8_t lim_get_nss_supported_by_ap(tDot11fIEVHTCaps *vht_caps,
536 tDot11fIEHTCaps *ht_caps,
537 tDot11fIEhe_cap *he_caps)
538 {
539 if (he_caps->present) {
540 if ((he_caps->rx_he_mcs_map_lt_80 & 0xC0) != 0xC0)
541 return NSS_4x4_MODE;
542
543 if ((he_caps->rx_he_mcs_map_lt_80 & 0x30) != 0x30)
544 return NSS_3x3_MODE;
545
546 if ((he_caps->rx_he_mcs_map_lt_80 & 0x0C) != 0x0C)
547 return NSS_2x2_MODE;
548 } else if (vht_caps->present) {
549 if ((vht_caps->rxMCSMap & 0xC0) != 0xC0)
550 return NSS_4x4_MODE;
551
552 if ((vht_caps->rxMCSMap & 0x30) != 0x30)
553 return NSS_3x3_MODE;
554
555 if ((vht_caps->rxMCSMap & 0x0C) != 0x0C)
556 return NSS_2x2_MODE;
557 } else if (ht_caps->present) {
558 if (ht_caps->supportedMCSSet[3])
559 return NSS_4x4_MODE;
560
561 if (ht_caps->supportedMCSSet[2])
562 return NSS_3x3_MODE;
563
564 if (ht_caps->supportedMCSSet[1])
565 return NSS_2x2_MODE;
566 }
567
568 return NSS_1x1_MODE;
569 }
570
571 #ifdef WLAN_FEATURE_11AX
lim_process_he_info(tpSirProbeRespBeacon beacon,tpDphHashNode sta_ds)572 static void lim_process_he_info(tpSirProbeRespBeacon beacon,
573 tpDphHashNode sta_ds)
574 {
575 if (beacon->he_op.present)
576 sta_ds->parsed_ies.he_operation = beacon->he_op;
577 }
578 #else
lim_process_he_info(tpSirProbeRespBeacon beacon,tpDphHashNode sta_ds)579 static inline void lim_process_he_info(tpSirProbeRespBeacon beacon,
580 tpDphHashNode sta_ds)
581 {
582 }
583 #endif
584
585 #ifdef WLAN_FEATURE_SR
lim_process_srp_ie(tpSirAssocRsp ar,tpDphHashNode sta_ds)586 QDF_STATUS lim_process_srp_ie(tpSirAssocRsp ar, tpDphHashNode sta_ds)
587 {
588 QDF_STATUS status = QDF_STATUS_E_NOSUPPORT;
589
590 if (ar->srp_ie.present) {
591 sta_ds->parsed_ies.srp_ie = ar->srp_ie;
592 status = QDF_STATUS_SUCCESS;
593 }
594
595 return status;
596 }
597 #endif
598
599 #ifdef WLAN_FEATURE_11BE
lim_process_eht_info(tpSirProbeRespBeacon beacon,tpDphHashNode sta_ds)600 static void lim_process_eht_info(tpSirProbeRespBeacon beacon,
601 tpDphHashNode sta_ds)
602 {
603 if (beacon->eht_op.present)
604 sta_ds->parsed_ies.eht_operation = beacon->eht_op;
605 }
606 #else
lim_process_eht_info(tpSirProbeRespBeacon beacon,tpDphHashNode sta_ds)607 static inline void lim_process_eht_info(tpSirProbeRespBeacon beacon,
608 tpDphHashNode sta_ds)
609 {
610 }
611 #endif
612
613 #define MAX_RETRY_TIMER 1500
614 static QDF_STATUS
lim_handle_pmfcomeback_timer(struct pe_session * session_entry,tpSirAssocRsp assoc_rsp)615 lim_handle_pmfcomeback_timer(struct pe_session *session_entry,
616 tpSirAssocRsp assoc_rsp)
617 {
618 uint16_t timeout_value;
619
620 if (session_entry->opmode != QDF_STA_MODE)
621 return QDF_STATUS_E_FAILURE;
622
623 if (session_entry->limRmfEnabled &&
624 session_entry->pmf_retry_timer_info.retried &&
625 assoc_rsp->status_code == STATUS_ASSOC_REJECTED_TEMPORARILY) {
626 pe_debug("Already retry in progress");
627 return QDF_STATUS_SUCCESS;
628 }
629
630 /*
631 * Handle association Response for sta mode with RMF enabled and TRY
632 * again later with timeout interval and Assoc comeback type
633 */
634 if (!session_entry->limRmfEnabled || assoc_rsp->status_code !=
635 STATUS_ASSOC_REJECTED_TEMPORARILY ||
636 !assoc_rsp->TimeoutInterval.present ||
637 assoc_rsp->TimeoutInterval.timeoutType !=
638 SIR_MAC_TI_TYPE_ASSOC_COMEBACK ||
639 session_entry->pmf_retry_timer_info.retried)
640 return QDF_STATUS_E_FAILURE;
641
642 timeout_value = assoc_rsp->TimeoutInterval.timeoutValue;
643 if (timeout_value < 10) {
644 /*
645 * if this value is less than 10 then our timer
646 * will fail to start and due to this we will
647 * never re-attempt. Better modify the timer
648 * value here.
649 */
650 timeout_value = 10;
651 }
652 timeout_value = QDF_MIN(MAX_RETRY_TIMER, timeout_value);
653 pe_debug("ASSOC res with eSIR_MAC_TRY_AGAIN_LATER recvd.Starting timer to wait timeout: %d",
654 timeout_value);
655 if (QDF_STATUS_SUCCESS !=
656 qdf_mc_timer_start(&session_entry->pmf_retry_timer,
657 timeout_value)) {
658 pe_err("Failed to start comeback timer");
659 return QDF_STATUS_E_FAILURE;
660 }
661 session_entry->pmf_retry_timer_info.retried = true;
662
663 return QDF_STATUS_SUCCESS;
664 }
665
clean_up_ft_sha384(tpSirAssocRsp assoc_rsp,bool sha384_akm)666 static void clean_up_ft_sha384(tpSirAssocRsp assoc_rsp, bool sha384_akm)
667 {
668 if (sha384_akm) {
669 qdf_mem_free(assoc_rsp->sha384_ft_subelem.gtk);
670 qdf_mem_free(assoc_rsp->sha384_ft_subelem.igtk);
671 }
672 }
673
674 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
lim_set_r0kh(tpSirAssocRsp assoc_rsp,struct pe_session * session)675 static void lim_set_r0kh(tpSirAssocRsp assoc_rsp, struct pe_session *session)
676 {
677 struct mlme_legacy_priv *mlme_priv;
678
679 mlme_priv = wlan_vdev_mlme_get_ext_hdl(session->vdev);
680 if (!mlme_priv)
681 return;
682 if (assoc_rsp->sha384_ft_subelem.r0kh_id.present) {
683 mlme_priv->connect_info.ft_info.r0kh_id_len =
684 assoc_rsp->sha384_ft_subelem.r0kh_id.num_PMK_R0_ID;
685 qdf_mem_copy(mlme_priv->connect_info.ft_info.r0kh_id,
686 assoc_rsp->sha384_ft_subelem.r0kh_id.PMK_R0_ID,
687 mlme_priv->connect_info.ft_info.r0kh_id_len);
688 } else if (assoc_rsp->FTInfo.R0KH_ID.present) {
689 mlme_priv->connect_info.ft_info.r0kh_id_len =
690 assoc_rsp->FTInfo.R0KH_ID.num_PMK_R0_ID;
691 qdf_mem_copy(mlme_priv->connect_info.ft_info.r0kh_id,
692 assoc_rsp->FTInfo.R0KH_ID.PMK_R0_ID,
693 mlme_priv->connect_info.ft_info.r0kh_id_len);
694 } else {
695 mlme_priv->connect_info.ft_info.r0kh_id_len = 0;
696 qdf_mem_zero(mlme_priv->connect_info.ft_info.r0kh_id,
697 ROAM_R0KH_ID_MAX_LEN);
698 }
699 }
700 #else
701 static inline
lim_set_r0kh(tpSirAssocRsp assoc_rsp,struct pe_session * session)702 void lim_set_r0kh(tpSirAssocRsp assoc_rsp, struct pe_session *session) {}
703 #endif
704
705 /**
706 * lim_get_iot_aggr_sz() - check and get IOT aggr size for configured OUI
707 *
708 * @mac_ctx: Pointer to Global MAC structure
709 * @ie_ptr: Pointer to starting IE in Beacon/Probe Response
710 * @ie_len: Length of all IEs combined
711 * @amsdu_sz: pointer to buffer to store AMSDU size
712 * @ampdu_sz: pointer to buffer to store AMPDU size
713 *
714 * This function is called to find configured vendor specific OUIs
715 * from the IEs in Beacon/Probe Response frames, if one of the OUI is
716 * present, get the configured aggr size for the OUI.
717 *
718 * Return: true if found, false otherwise.
719 */
720 static bool
lim_get_iot_aggr_sz(struct mac_context * mac,uint8_t * ie_ptr,uint32_t ie_len,uint32_t * amsdu_sz,uint32_t * ampdu_sz)721 lim_get_iot_aggr_sz(struct mac_context *mac, uint8_t *ie_ptr, uint32_t ie_len,
722 uint32_t *amsdu_sz, uint32_t *ampdu_sz)
723 {
724 const uint8_t *oui, *vendor_ie;
725 struct wlan_mlme_iot *iot;
726 uint32_t oui_len, aggr_num;
727 int i;
728
729 iot = &mac->mlme_cfg->iot;
730 aggr_num = iot->aggr_num;
731 if (!aggr_num)
732 return false;
733
734 for (i = 0; i < aggr_num; i++) {
735 oui = iot->aggr[i].oui;
736 oui_len = iot->aggr[i].oui_len;
737 vendor_ie = wlan_get_vendor_ie_ptr_from_oui(oui, oui_len,
738 ie_ptr, ie_len);
739 if (!vendor_ie)
740 continue;
741
742 *amsdu_sz = iot->aggr[i].amsdu_sz;
743 *ampdu_sz = iot->aggr[i].ampdu_sz;
744 return true;
745 }
746
747 return false;
748 }
749
750 /**
751 * lim_update_iot_aggr_sz() - check and update IOT aggr size
752 *
753 * @mac_ctx: Pointer to Global MAC structure
754 * @ie_ptr: Pointer to starting IE in Beacon/Probe Response
755 * @ie_len: Length of all IEs combined
756 * @session_entry: A pointer to session entry
757 *
758 * This function is called to find configured vendor specific OUIs
759 * from the IEs in Beacon/Probe Response frames, and set the aggr
760 * size accordingly.
761 *
762 * Return: None
763 */
764 static void
lim_update_iot_aggr_sz(struct mac_context * mac_ctx,uint8_t * ie_ptr,uint32_t ie_len,struct pe_session * session_entry)765 lim_update_iot_aggr_sz(struct mac_context *mac_ctx, uint8_t *ie_ptr,
766 uint32_t ie_len, struct pe_session *session_entry)
767 {
768 int ret;
769 uint32_t amsdu_sz, ampdu_sz;
770 bool iot_hit;
771
772 if (!ie_ptr || !ie_len)
773 return;
774
775 iot_hit = lim_get_iot_aggr_sz(mac_ctx, ie_ptr, ie_len,
776 &amsdu_sz, &du_sz);
777 if (!iot_hit)
778 return;
779
780 pe_debug("Try to set iot amsdu size: %u", amsdu_sz);
781 ret = wma_cli_set_command(session_entry->smeSessionId,
782 GEN_VDEV_PARAM_AMSDU, amsdu_sz, GEN_CMD);
783 if (ret)
784 pe_err("Failed to set iot amsdu size: %d", ret);
785 }
786
787 /**
788 * hdd_cm_update_mcs_rate_set() - Update MCS rate set from HT capability
789 * @vdev: Pointer to vdev object
790 * @ht_cap: pointer to parsed HT capability
791 *
792 * Return: None.
793 */
794 static inline void
lim_update_mcs_rate_set(struct wlan_objmgr_vdev * vdev,tDot11fIEHTCaps * ht_cap)795 lim_update_mcs_rate_set(struct wlan_objmgr_vdev *vdev, tDot11fIEHTCaps *ht_cap)
796 {
797 qdf_size_t len = 0;
798 int i;
799 uint32_t *mcs_set;
800 uint8_t dst_rate[VALID_MAX_MCS_INDEX] = {0};
801
802 mcs_set = (uint32_t *)ht_cap->supportedMCSSet;
803 for (i = 0; i < VALID_MAX_MCS_INDEX; i++) {
804 if (!QDF_GET_BITS(*mcs_set, i, 1))
805 continue;
806
807 dst_rate[len++] = i;
808 }
809
810 mlme_set_mcs_rate(vdev, dst_rate, len);
811 }
812
813 #ifdef WLAN_FEATURE_11BE
814 /**
815 * lim_update_sta_vdev_punc() - Update puncture set according to assoc resp
816 * @psoc: Pointer to psoc object
817 * @vdev_id: vdev id
818 * @assoc_resp: pointer to parsed associate response
819 *
820 * Return: None.
821 */
822 static QDF_STATUS
lim_update_sta_vdev_punc(struct wlan_objmgr_psoc * psoc,uint8_t vdev_id,tpSirAssocRsp assoc_resp)823 lim_update_sta_vdev_punc(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id,
824 tpSirAssocRsp assoc_resp)
825 {
826 struct wlan_objmgr_vdev *vdev;
827 struct wlan_channel *des_chan;
828 enum phy_ch_width ori_bw;
829 uint16_t ori_puncture_bitmap;
830 uint16_t primary_puncture_bitmap = 0;
831 qdf_freq_t center_freq_320;
832 uint8_t band_mask;
833
834 if (!assoc_resp->eht_op.disabled_sub_chan_bitmap_present)
835 return QDF_STATUS_SUCCESS;
836 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
837 WLAN_LEGACY_MAC_ID);
838 if (!vdev) {
839 pe_err("vdev not found for id: %d", vdev_id);
840 return QDF_STATUS_E_FAILURE;
841 }
842
843 des_chan = wlan_vdev_mlme_get_des_chan(vdev);
844 ori_puncture_bitmap =
845 *(uint16_t *)assoc_resp->eht_op.disabled_sub_chan_bitmap;
846
847 ori_bw = wlan_mlme_convert_eht_op_bw_to_phy_ch_width(
848 assoc_resp->eht_op.channel_width);
849
850 if (ori_bw == CH_WIDTH_320MHZ) {
851 if (WLAN_REG_IS_24GHZ_CH_FREQ(des_chan->ch_freq))
852 band_mask = BIT(REG_BAND_2G);
853 else if (WLAN_REG_IS_6GHZ_CHAN_FREQ(des_chan->ch_freq))
854 band_mask = BIT(REG_BAND_6G);
855 else
856 band_mask = BIT(REG_BAND_5G);
857 center_freq_320 = wlan_reg_chan_band_to_freq(
858 wlan_vdev_get_pdev(vdev),
859 assoc_resp->eht_op.ccfs1,
860 band_mask);
861 } else {
862 center_freq_320 = 0;
863 }
864 wlan_reg_extract_puncture_by_bw(ori_bw, ori_puncture_bitmap,
865 des_chan->ch_freq,
866 center_freq_320,
867 CH_WIDTH_20MHZ,
868 &primary_puncture_bitmap);
869 if (primary_puncture_bitmap) {
870 pe_err("sta vdev %d freq %d assoc rsp bw %d puncture 0x%x primary chan is punctured",
871 vdev_id, des_chan->ch_freq, ori_bw, ori_puncture_bitmap);
872 wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID);
873 return QDF_STATUS_E_FAILURE;
874 }
875 if (des_chan->ch_width == ori_bw)
876 des_chan->puncture_bitmap = ori_puncture_bitmap;
877 else
878 wlan_reg_extract_puncture_by_bw(ori_bw, ori_puncture_bitmap,
879 des_chan->ch_freq,
880 center_freq_320,
881 des_chan->ch_width,
882 &des_chan->puncture_bitmap);
883 pe_debug("sta vdev %d freq %d assoc rsp bw %d puncture 0x%x 320M center frequency %d intersect bw %d puncture 0x%x",
884 vdev_id, des_chan->ch_freq, ori_bw, ori_puncture_bitmap,
885 center_freq_320, des_chan->ch_width,
886 des_chan->puncture_bitmap);
887 wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID);
888
889 return QDF_STATUS_SUCCESS;
890 }
891 #else
892 static QDF_STATUS
lim_update_sta_vdev_punc(struct wlan_objmgr_psoc * psoc,uint8_t vdev_id,tpSirAssocRsp assoc_resp)893 lim_update_sta_vdev_punc(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id,
894 tpSirAssocRsp assoc_resp)
895 {
896 return QDF_STATUS_SUCCESS;
897 }
898 #endif
899
900 /**
901 * hdd_cm_update_rate_set() - Update rate set according to assoc resp
902 * @psoc: Pointer to psoc object
903 * @vdev_id: vdev id
904 * @assoc_resp: pointer to parsed associate response
905 *
906 * Return: None.
907 */
908 static void
lim_update_vdev_rate_set(struct wlan_objmgr_psoc * psoc,uint8_t vdev_id,tpSirAssocRsp assoc_resp)909 lim_update_vdev_rate_set(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id,
910 tpSirAssocRsp assoc_resp)
911 {
912 struct wlan_objmgr_vdev *vdev;
913
914 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
915 WLAN_LEGACY_MAC_ID);
916 if (!vdev) {
917 pe_err("vdev not found for id: %d", vdev_id);
918 return;
919 }
920
921 if (assoc_resp->suppRatesPresent && assoc_resp->supportedRates.numRates)
922 mlme_set_opr_rate(vdev, assoc_resp->supportedRates.rate,
923 assoc_resp->supportedRates.numRates);
924
925 if (assoc_resp->extendedRatesPresent &&
926 assoc_resp->extendedRates.numRates)
927 mlme_set_ext_opr_rate(vdev,
928 assoc_resp->extendedRates.rate,
929 assoc_resp->extendedRates.numRates);
930 else
931 mlme_clear_ext_opr_rate(vdev);
932
933 if (assoc_resp->HTCaps.present)
934 lim_update_mcs_rate_set(vdev, &assoc_resp->HTCaps);
935 else
936 mlme_clear_mcs_rate(vdev);
937
938 wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID);
939 }
940
941 #ifdef WLAN_FEATURE_11BE_MLO
942 static void
lim_process_assoc_rsp_t2lm(struct pe_session * session,tpSirAssocRsp assoc_rsp)943 lim_process_assoc_rsp_t2lm(struct pe_session *session,
944 tpSirAssocRsp assoc_rsp)
945 {
946 struct wlan_objmgr_vdev *vdev;
947 struct wlan_t2lm_context *t2lm_ctx;
948 struct wlan_mlo_dev_context *mlo_dev_ctx;
949 struct wlan_objmgr_psoc *psoc;
950
951 if (!session || !assoc_rsp) {
952 pe_err("invalid input parameters");
953 return;
954 }
955
956 vdev = session->vdev;
957 if (!vdev || !wlan_vdev_mlme_is_mlo_vdev(vdev))
958 return;
959
960 psoc = wlan_vdev_get_psoc(vdev);
961 if (!psoc)
962 return;
963
964 if (!wlan_mlme_get_t2lm_negotiation_supported(psoc)) {
965 pe_err_rl("T2LM negotiation not supported");
966 return;
967 }
968
969 mlo_dev_ctx = wlan_vdev_get_mlo_dev_ctx(vdev);
970 if (!mlo_dev_ctx) {
971 pe_err("ml dev ctx is null");
972 return;
973 }
974
975 if (wlan_vdev_mlme_is_mlo_link_vdev(vdev))
976 return;
977
978 if (assoc_rsp->t2lm_ctx.upcoming_t2lm.t2lm.direction ==
979 WLAN_T2LM_INVALID_DIRECTION &&
980 assoc_rsp->t2lm_ctx.established_t2lm.t2lm.direction ==
981 WLAN_T2LM_INVALID_DIRECTION) {
982 pe_debug("No t2lm IE");
983 return;
984 }
985
986 t2lm_ctx = &mlo_dev_ctx->sta_ctx->copied_t2lm_ie_assoc_rsp;
987
988 if (assoc_rsp->t2lm_ctx.established_t2lm.t2lm.expected_duration_present &&
989 !assoc_rsp->t2lm_ctx.established_t2lm.t2lm.mapping_switch_time_present &&
990 assoc_rsp->t2lm_ctx.established_t2lm.t2lm.direction !=
991 WLAN_T2LM_INVALID_DIRECTION) {
992 qdf_mem_copy(&t2lm_ctx->established_t2lm.t2lm,
993 &assoc_rsp->t2lm_ctx.established_t2lm.t2lm,
994 sizeof(struct wlan_t2lm_info));
995 }
996
997 if (assoc_rsp->t2lm_ctx.upcoming_t2lm.t2lm.mapping_switch_time_present &&
998 assoc_rsp->t2lm_ctx.established_t2lm.t2lm.direction !=
999 WLAN_T2LM_INVALID_DIRECTION) {
1000 qdf_mem_copy(&t2lm_ctx->upcoming_t2lm.t2lm,
1001 &assoc_rsp->t2lm_ctx.upcoming_t2lm.t2lm,
1002 sizeof(struct wlan_t2lm_info));
1003 }
1004 }
1005 #else
1006 static inline void
lim_process_assoc_rsp_t2lm(struct pe_session * session,tpSirAssocRsp assoc_rsp)1007 lim_process_assoc_rsp_t2lm(struct pe_session *session,
1008 tpSirAssocRsp assoc_rsp)
1009 {
1010 }
1011 #endif
1012
1013 #ifdef WLAN_FEATURE_11BE_MLO
1014 /**
1015 * lim_cache_emlsr_params() - cache the EMLSR parameters in ML STA context
1016 * @session_entry: session entry
1017 * @assoc_rsp: pointer to parsed associate response
1018 *
1019 * Return: None
1020 */
lim_cache_emlsr_params(struct pe_session * session_entry,tpSirAssocRsp assoc_rsp)1021 static void lim_cache_emlsr_params(struct pe_session *session_entry,
1022 tpSirAssocRsp assoc_rsp)
1023 {
1024 struct wlan_mlo_sta *sta_ctx;
1025 struct wlan_objmgr_vdev *vdev = session_entry->vdev;
1026 struct emlsr_capability *ml_emlcap;
1027
1028 wlan_objmgr_vdev_get_ref(vdev, WLAN_MLME_SB_ID);
1029 if (!vdev) {
1030 pe_err("vdev is null");
1031 return;
1032 }
1033
1034 if (!vdev->mlo_dev_ctx) {
1035 pe_err("mlo dev ctx is null");
1036 goto end;
1037 }
1038
1039 sta_ctx = vdev->mlo_dev_ctx->sta_ctx;
1040 if (!sta_ctx) {
1041 pe_err("sta ctx is null");
1042 goto end;
1043 }
1044
1045 ml_emlcap = &sta_ctx->emlsr_cap;
1046
1047 if (wlan_vdev_mlme_cap_get(vdev,
1048 WLAN_VDEV_C_EMLSR_CAP)) {
1049 ml_emlcap->emlsr_supp = true;
1050 ml_emlcap->trans_timeout =
1051 assoc_rsp->mlo_ie.mlo_ie.eml_capabilities_info.transition_timeout;
1052 } else {
1053 ml_emlcap->emlsr_supp = false;
1054 ml_emlcap->trans_timeout = 0;
1055 }
1056
1057 pe_debug("EML caps support%d timeout%d", ml_emlcap->emlsr_supp,
1058 ml_emlcap->trans_timeout);
1059 end:
1060 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_SB_ID);
1061 }
1062 #else
lim_cache_emlsr_params(struct pe_session * session_entry,tpSirAssocRsp assoc_rsp)1063 static inline void lim_cache_emlsr_params(struct pe_session *session_entry,
1064 tpSirAssocRsp assoc_rsp)
1065 {
1066 }
1067 #endif
1068
1069 /**
1070 * lim_send_join_fail_on_vdev() - Send join failure for link vdev
1071 * @mac_ctx: Pointer to Global MAC structure
1072 * @session_entry: Session entry
1073 * @result_code: result code to send in join result
1074 *
1075 * This function sends join failure when bssid of assoc/reassoc
1076 * resp doesn't match with current bssid
1077 */
1078 static
lim_send_join_fail_on_vdev(struct mac_context * mac_ctx,struct pe_session * session_entry,enum eSirResultCodes result_code)1079 void lim_send_join_fail_on_vdev(struct mac_context *mac_ctx,
1080 struct pe_session *session_entry,
1081 enum eSirResultCodes result_code)
1082 {
1083 if (!wlan_vdev_mlme_is_mlo_link_vdev(session_entry->vdev))
1084 return;
1085
1086 session_entry->limSmeState = eLIM_SME_JOIN_FAILURE_STATE;
1087 MTRACE(mac_trace(mac_ctx, TRACE_CODE_SME_STATE,
1088 session_entry->peSessionId,
1089 session_entry->limSmeState));
1090
1091 /* Send Join response to Host */
1092 lim_handle_sme_join_result(
1093 mac_ctx, result_code, STATUS_UNSPECIFIED_FAILURE,
1094 session_entry);
1095 }
1096
1097 /**
1098 * lim_process_assoc_rsp_frame() - Processes assoc response
1099 * @mac_ctx: Pointer to Global MAC structure
1100 * @rx_packet_info - A pointer to Rx packet info structure
1101 * @frame_body_length - frame body length of reassoc/assoc response frame
1102 * @sub_type - Indicates whether it is Association Response (=0) or
1103 * Reassociation Response (=1) frame
1104 * @session_entry: Session entry
1105 *
1106 * This function is called by limProcessMessageQueue() upon
1107 * Re/Association Response frame reception.
1108 *
1109 * Return: None
1110 */
1111 void
lim_process_assoc_rsp_frame(struct mac_context * mac_ctx,uint8_t * rx_pkt_info,uint32_t frame_body_len,uint8_t subtype,struct pe_session * session_entry)1112 lim_process_assoc_rsp_frame(struct mac_context *mac_ctx, uint8_t *rx_pkt_info,
1113 uint32_t frame_body_len,
1114 uint8_t subtype, struct pe_session *session_entry)
1115 {
1116 uint8_t *body, *ie;
1117 uint16_t caps, ie_len;
1118 tSirMacAddr current_bssid;
1119 tpSirMacMgmtHdr hdr = NULL;
1120 tSirMacCapabilityInfo mac_capab;
1121 tpDphHashNode sta_ds;
1122 tpSirAssocRsp assoc_rsp;
1123 tLimMlmAssocCnf assoc_cnf;
1124 tSchBeaconStruct *beacon;
1125 uint8_t ap_nss;
1126 uint16_t aid;
1127 int8_t rssi;
1128 QDF_STATUS status;
1129 enum ani_akm_type auth_type;
1130 bool sha384_akm, twt_support_in_11n = false;
1131 struct s_ext_cap *ext_cap;
1132
1133 assoc_cnf.resultCode = eSIR_SME_SUCCESS;
1134 /* Update PE session Id */
1135 assoc_cnf.sessionId = session_entry->peSessionId;
1136
1137 if (LIM_IS_AP_ROLE(session_entry)) {
1138 /*
1139 * Should not have received Re/Association
1140 * Response frame on AP. Log error
1141 */
1142 pe_err("Should not received Re/Assoc Response in role: %d",
1143 GET_LIM_SYSTEM_ROLE(session_entry));
1144 return;
1145 }
1146
1147 if (lim_is_roam_synch_in_progress(mac_ctx->psoc, session_entry) ||
1148 wlan_vdev_mlme_is_mlo_link_vdev(session_entry->vdev)) {
1149 hdr = (tpSirMacMgmtHdr)rx_pkt_info;
1150 rssi = 0;
1151 } else {
1152 hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
1153 rssi = WMA_GET_RX_RSSI_NORMALIZED(rx_pkt_info);
1154 }
1155
1156 if (!hdr) {
1157 pe_err("LFR3: Reassoc response packet header is NULL");
1158 return;
1159 }
1160
1161 pe_nofl_rl_info("Assoc rsp RX: subtype %d vdev %d sys role %d lim state %d rssi %d from " QDF_MAC_ADDR_FMT,
1162 subtype, session_entry->vdev_id,
1163 GET_LIM_SYSTEM_ROLE(session_entry),
1164 session_entry->limMlmState, rssi,
1165 QDF_MAC_ADDR_REF(hdr->sa));
1166
1167 beacon = qdf_mem_malloc(sizeof(tSchBeaconStruct));
1168 if (!beacon)
1169 return;
1170
1171 if (((subtype == LIM_ASSOC) &&
1172 (session_entry->limMlmState != eLIM_MLM_WT_ASSOC_RSP_STATE)) ||
1173 ((subtype == LIM_REASSOC) &&
1174 !lim_is_roam_synch_in_progress(mac_ctx->psoc, session_entry) &&
1175 !MLME_IS_MLO_ROAM_SYNCH_IN_PROGRESS(mac_ctx->psoc,
1176 session_entry->vdev_id) &&
1177 ((session_entry->limMlmState != eLIM_MLM_WT_REASSOC_RSP_STATE)
1178 && (session_entry->limMlmState !=
1179 eLIM_MLM_WT_FT_REASSOC_RSP_STATE)
1180 ))) {
1181 /* Received unexpected Re/Association Response frame */
1182 pe_debug("Received Re/Assoc rsp in unexpected state: %d on session: %d",
1183 session_entry->limMlmState, session_entry->peSessionId);
1184 if (!hdr->fc.retry) {
1185 if (!(mac_ctx->lim.retry_packet_cnt & 0xf)) {
1186 pe_err("recvd Re/Assoc rsp:not a retry frame");
1187 lim_print_mlm_state(mac_ctx, LOGE,
1188 session_entry->limMlmState);
1189 } else {
1190 mac_ctx->lim.retry_packet_cnt++;
1191 }
1192 }
1193 qdf_mem_free(beacon);
1194 return;
1195 }
1196 sir_copy_mac_addr(current_bssid, session_entry->bssId);
1197 if (subtype == LIM_ASSOC) {
1198 if (qdf_mem_cmp
1199 (hdr->sa, current_bssid, sizeof(tSirMacAddr))) {
1200 /*
1201 * Received Association Response frame from an entity
1202 * other than one to which request was initiated.
1203 * Ignore this and wait until Assoc Failure Timeout
1204 */
1205 pe_warn("received AssocRsp from unexpected peer "QDF_MAC_ADDR_FMT,
1206 QDF_MAC_ADDR_REF(hdr->sa));
1207
1208 if (lim_is_roam_synch_in_progress(mac_ctx->psoc, session_entry)) {
1209 session_entry->is_unexpected_peer_error = true;
1210 qdf_mem_free(beacon);
1211 return;
1212 }
1213 /*
1214 * Send Assoc failure to avoid connection in
1215 * progress state for link vdev.
1216 */
1217 lim_send_join_fail_on_vdev(mac_ctx, session_entry,
1218 eSIR_SME_ASSOC_REFUSED);
1219 qdf_mem_free(beacon);
1220 return;
1221 }
1222 } else {
1223 if (qdf_mem_cmp
1224 (hdr->sa, session_entry->limReAssocbssId,
1225 sizeof(tSirMacAddr))) {
1226 /*
1227 * Received Reassociation Response frame from an entity
1228 * other than one to which request was initiated.
1229 * Ignore this and wait until Reassoc Failure Timeout.
1230 */
1231 pe_warn("received ReassocRsp from unexpected peer "QDF_MAC_ADDR_FMT,
1232 QDF_MAC_ADDR_REF(hdr->sa));
1233
1234 if (lim_is_roam_synch_in_progress(mac_ctx->psoc, session_entry)) {
1235 session_entry->is_unexpected_peer_error = true;
1236 qdf_mem_free(beacon);
1237 return;
1238 }
1239
1240 /*
1241 * Send Reassoc failure to avoid connection in
1242 * progress state for link vdev.
1243 */
1244 lim_send_join_fail_on_vdev(mac_ctx, session_entry,
1245 eSIR_SME_REASSOC_REFUSED);
1246 qdf_mem_free(beacon);
1247 return;
1248 }
1249 }
1250
1251 assoc_rsp = qdf_mem_malloc(sizeof(*assoc_rsp));
1252 if (!assoc_rsp) {
1253 qdf_mem_free(beacon);
1254 return;
1255 }
1256 /* Get pointer to Re/Association Response frame body */
1257 if (lim_is_roam_synch_in_progress(mac_ctx->psoc, session_entry) ||
1258 wlan_vdev_mlme_is_mlo_link_vdev(session_entry->vdev))
1259 body = rx_pkt_info + SIR_MAC_HDR_LEN_3A;
1260 else
1261 body = WMA_GET_RX_MPDU_DATA(rx_pkt_info);
1262 /* parse Re/Association Response frame. */
1263 if (sir_convert_assoc_resp_frame2_struct(mac_ctx, session_entry, body,
1264 frame_body_len, assoc_rsp) == QDF_STATUS_E_FAILURE) {
1265 qdf_mem_free(assoc_rsp);
1266 pe_err("Parse error Assoc resp subtype: %d" "length: %d",
1267 frame_body_len, subtype);
1268 qdf_mem_free(beacon);
1269 return;
1270 }
1271
1272 if (subtype == LIM_REASSOC) {
1273 lim_cp_stats_cstats_log_assoc_resp_evt
1274 (session_entry, CSTATS_DIR_RX, assoc_rsp->status_code,
1275 assoc_rsp->aid, hdr->bssId, hdr->da,
1276 assoc_rsp->HTCaps.present,
1277 assoc_rsp->VHTCaps.present, assoc_rsp->he_cap.present,
1278 assoc_rsp->eht_op.present, true);
1279 } else if (subtype == LIM_ASSOC) {
1280 lim_cp_stats_cstats_log_assoc_resp_evt
1281 (session_entry, CSTATS_DIR_RX, assoc_rsp->status_code,
1282 assoc_rsp->aid, hdr->bssId, hdr->da,
1283 assoc_rsp->HTCaps.present,
1284 assoc_rsp->VHTCaps.present, assoc_rsp->he_cap.present,
1285 assoc_rsp->eht_op.present, false);
1286 }
1287
1288 if (subtype != LIM_REASSOC) {
1289 aid = assoc_rsp->aid & 0x3FFF;
1290 wlan_connectivity_mgmt_event(mac_ctx->psoc,
1291 (struct wlan_frame_hdr *)hdr,
1292 session_entry->vdev_id,
1293 assoc_rsp->status_code, 0, rssi,
1294 0, 0, 0, aid,
1295 WLAN_ASSOC_RSP);
1296 }
1297
1298 if (lim_is_session_eht_capable(session_entry)) {
1299 uint8_t ies_offset;
1300
1301 if (subtype == LIM_ASSOC)
1302 ies_offset = WLAN_ASSOC_RSP_IES_OFFSET;
1303 else
1304 ies_offset = WLAN_REASSOC_REQ_IES_OFFSET;
1305
1306 if (frame_body_len < ies_offset) {
1307 pe_err("frame body length is < ies_offset");
1308 return;
1309 }
1310
1311 status = lim_strip_and_decode_eht_op(
1312 body + ies_offset,
1313 frame_body_len - ies_offset,
1314 &assoc_rsp->eht_op,
1315 assoc_rsp->VHTOperation,
1316 assoc_rsp->he_op,
1317 assoc_rsp->HTInfo);
1318
1319 if (status != QDF_STATUS_SUCCESS) {
1320 pe_err("Failed to extract eht op");
1321 return;
1322 }
1323
1324 status = lim_strip_and_decode_eht_cap(
1325 body + ies_offset,
1326 frame_body_len - ies_offset,
1327 &assoc_rsp->eht_cap,
1328 assoc_rsp->he_cap,
1329 session_entry->curr_op_freq);
1330 if (status != QDF_STATUS_SUCCESS) {
1331 pe_err("Failed to extract eht cap");
1332 return;
1333 }
1334 }
1335
1336 if (!assoc_rsp->suppRatesPresent) {
1337 pe_debug("assoc response does not have supported rate set");
1338 qdf_mem_copy(&assoc_rsp->supportedRates,
1339 &session_entry->rateSet,
1340 sizeof(tSirMacRateSet));
1341 }
1342
1343 assoc_cnf.protStatusCode = assoc_rsp->status_code;
1344 if (session_entry->assocRsp) {
1345 pe_warn("session_entry->assocRsp is not NULL freeing it and setting NULL");
1346 qdf_mem_free(session_entry->assocRsp);
1347 session_entry->assocRsp = NULL;
1348 session_entry->assocRspLen = 0;
1349 }
1350
1351 if (frame_body_len) {
1352 session_entry->assocRsp = qdf_mem_malloc(frame_body_len);
1353 if (session_entry->assocRsp) {
1354 /*
1355 * Store the Assoc response. This is sent
1356 * to csr/hdd in join cnf response.
1357 */
1358 qdf_mem_copy(session_entry->assocRsp, body, frame_body_len);
1359 session_entry->assocRspLen = frame_body_len;
1360 }
1361 }
1362
1363 lim_update_ric_data(mac_ctx, session_entry, assoc_rsp);
1364
1365 lim_set_r0kh(assoc_rsp, session_entry);
1366
1367 #ifdef FEATURE_WLAN_ESE
1368 lim_update_ese_tspec(mac_ctx, session_entry, assoc_rsp);
1369 #endif
1370
1371 auth_type = session_entry->connected_akm;
1372 sha384_akm = lim_is_sha384_akm(auth_type);
1373
1374 if (lim_get_capability_info(mac_ctx, &caps, session_entry)
1375 != QDF_STATUS_SUCCESS) {
1376 clean_up_ft_sha384(assoc_rsp, sha384_akm);
1377 qdf_mem_free(assoc_rsp);
1378 qdf_mem_free(beacon);
1379 pe_err("could not retrieve Capabilities");
1380 return;
1381 }
1382 lim_copy_u16((uint8_t *) &mac_capab, caps);
1383
1384 if (assoc_rsp->status_code == STATUS_DENIED_POOR_CHANNEL_CONDITIONS &&
1385 assoc_rsp->rssi_assoc_rej.present) {
1386 struct sir_rssi_disallow_lst ap_info = {{0}};
1387
1388 if (!assoc_rsp->rssi_assoc_rej.retry_delay)
1389 ap_info.expected_rssi = assoc_rsp->rssi_assoc_rej.delta_rssi +
1390 WMA_GET_RX_RSSI_NORMALIZED(rx_pkt_info) +
1391 wlan_dlm_get_rssi_denylist_threshold(mac_ctx->pdev);
1392 else
1393 ap_info.expected_rssi = assoc_rsp->rssi_assoc_rej.delta_rssi +
1394 WMA_GET_RX_RSSI_NORMALIZED(rx_pkt_info);
1395
1396 ap_info.retry_delay = assoc_rsp->rssi_assoc_rej.retry_delay *
1397 QDF_MC_TIMER_TO_MS_UNIT;
1398 qdf_mem_copy(ap_info.bssid.bytes, hdr->sa, QDF_MAC_ADDR_SIZE);
1399 ap_info.reject_reason = REASON_ASSOC_REJECT_OCE;
1400 ap_info.source = ADDED_BY_DRIVER;
1401 ap_info.original_timeout = ap_info.retry_delay;
1402 ap_info.received_time = qdf_mc_timer_get_system_time();
1403 lim_add_bssid_to_reject_list(mac_ctx->pdev, &ap_info);
1404 }
1405
1406 status = lim_handle_pmfcomeback_timer(session_entry, assoc_rsp);
1407 /* return if retry again timer is started and ignore this assoc resp */
1408 if (QDF_IS_STATUS_SUCCESS(status)) {
1409 qdf_mem_free(beacon);
1410 clean_up_ft_sha384(assoc_rsp, sha384_akm);
1411 qdf_mem_free(assoc_rsp);
1412 return;
1413 }
1414
1415 /* Stop Association failure timer */
1416 if (subtype == LIM_ASSOC)
1417 lim_deactivate_and_change_timer(mac_ctx, eLIM_ASSOC_FAIL_TIMER);
1418 else
1419 lim_stop_reassoc_retry_timer(mac_ctx);
1420
1421 if (assoc_rsp->status_code != STATUS_SUCCESS) {
1422 /*
1423 *Re/Association response was received
1424 * either with failure code.
1425 */
1426 pe_err("received Re/AssocRsp frame failure code: %d",
1427 assoc_rsp->status_code);
1428 /*
1429 * Need to update 'association failure' error counter
1430 * along with STATUS CODE
1431 * Return Assoc confirm to SME with received failure code
1432 */
1433 assoc_cnf.resultCode = eSIR_SME_ASSOC_REFUSED;
1434 /* Delete Pre-auth context for the associated BSS */
1435 if (lim_search_pre_auth_list(mac_ctx, hdr->sa))
1436 lim_delete_pre_auth_node(mac_ctx, hdr->sa);
1437 goto assocReject;
1438 } else if ((assoc_rsp->aid & 0x3FFF) > 2007) {
1439 /*
1440 * Re/Association response was received
1441 * with invalid AID value
1442 */
1443 pe_err("received Re/AssocRsp frame with invalid aid: %X",
1444 assoc_rsp->aid);
1445 assoc_cnf.resultCode = eSIR_SME_INVALID_ASSOC_RSP_RXED;
1446 assoc_cnf.protStatusCode = STATUS_UNSPECIFIED_FAILURE;
1447 /* Send advisory Disassociation frame to AP */
1448 lim_send_disassoc_mgmt_frame(mac_ctx,
1449 REASON_UNSPEC_FAILURE,
1450 hdr->sa, session_entry, false);
1451 goto assocReject;
1452 }
1453
1454 /*
1455 * If it is FILS connection, check is FILS params are matching
1456 * with Authentication stage.
1457 */
1458 if (!lim_verify_fils_params_assoc_rsp(mac_ctx, session_entry,
1459 assoc_rsp, &assoc_cnf)) {
1460 pe_err("FILS params does not match");
1461 assoc_cnf.resultCode = eSIR_SME_INVALID_ASSOC_RSP_RXED;
1462 assoc_cnf.protStatusCode = STATUS_UNSPECIFIED_FAILURE;
1463 /* Send advisory Disassociation frame to AP */
1464 lim_send_disassoc_mgmt_frame(mac_ctx,
1465 REASON_UNSPEC_FAILURE,
1466 hdr->sa, session_entry, false);
1467 goto assocReject;
1468 }
1469
1470 if (assoc_rsp->QosMapSet.present)
1471 qdf_mem_copy(&session_entry->QosMapSet,
1472 &assoc_rsp->QosMapSet,
1473 sizeof(struct qos_map_set));
1474 else
1475 qdf_mem_zero(&session_entry->QosMapSet,
1476 sizeof(struct qos_map_set));
1477
1478 if (assoc_rsp->obss_scanparams.present)
1479 lim_update_obss_scanparams(session_entry,
1480 &assoc_rsp->obss_scanparams);
1481
1482 if (lim_is_session_he_capable(session_entry)) {
1483 if (!wlan_cm_is_vdev_roaming(session_entry->vdev))
1484 lim_set_twt_peer_capabilities(
1485 mac_ctx,
1486 (struct qdf_mac_addr *)current_bssid,
1487 &assoc_rsp->he_cap,
1488 &assoc_rsp->he_op);
1489
1490 } else {
1491 wlan_twt_cfg_get_support_in_11n(mac_ctx->psoc,
1492 &twt_support_in_11n);
1493 if (twt_support_in_11n && session_entry->htCapability &&
1494 assoc_rsp->HTCaps.present && assoc_rsp->ExtCap.present) {
1495 ext_cap = (struct s_ext_cap *)assoc_rsp->ExtCap.bytes;
1496 lim_set_twt_ext_capabilities(
1497 mac_ctx,
1498 (struct qdf_mac_addr *)current_bssid,
1499 ext_cap);
1500 }
1501 }
1502
1503 lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_ROAM_ASSOC_COMP_EVENT,
1504 session_entry,
1505 (assoc_rsp->status_code ? QDF_STATUS_E_FAILURE :
1506 QDF_STATUS_SUCCESS), assoc_rsp->status_code);
1507
1508 ap_nss = lim_get_nss_supported_by_ap(&assoc_rsp->VHTCaps,
1509 &assoc_rsp->HTCaps,
1510 &assoc_rsp->he_cap);
1511
1512 if (subtype == LIM_REASSOC) {
1513 pe_debug("Successfully Reassociated with BSS");
1514 #ifdef FEATURE_WLAN_ESE
1515 if (assoc_rsp->tsmPresent)
1516 lim_update_ese_tsm(mac_ctx, session_entry, assoc_rsp);
1517 #endif
1518 if (session_entry->pLimMlmJoinReq) {
1519 qdf_mem_free(session_entry->pLimMlmJoinReq);
1520 session_entry->pLimMlmJoinReq = NULL;
1521 }
1522
1523 if (session_entry->limAssocResponseData) {
1524 tpSirAssocRsp pre_assoc_rsp;
1525
1526 pre_assoc_rsp = (tpSirAssocRsp)
1527 session_entry->limAssocResponseData;
1528 qdf_mem_free(pre_assoc_rsp->sha384_ft_subelem.gtk);
1529 qdf_mem_free(pre_assoc_rsp->sha384_ft_subelem.igtk);
1530 qdf_mem_free(session_entry->limAssocResponseData);
1531 }
1532 session_entry->limAssocResponseData = (void *)assoc_rsp;
1533 /*
1534 * Store the ReAssocRsp Frame in DphTable
1535 * to be used during processing DelSta and
1536 * DelBss to send AddBss again
1537 */
1538 sta_ds =
1539 dph_get_hash_entry(mac_ctx, DPH_STA_HASH_INDEX_PEER,
1540 &session_entry->dph.dphHashTable);
1541
1542 if (!sta_ds) {
1543 pe_err("could not get hash entry at DPH for SA: "QDF_MAC_ADDR_FMT,
1544 QDF_MAC_ADDR_REF(hdr->sa));
1545 assoc_cnf.resultCode =
1546 eSIR_SME_INVALID_ASSOC_RSP_RXED;
1547 assoc_cnf.protStatusCode =
1548 STATUS_UNSPECIFIED_FAILURE;
1549
1550 /* Send advisory Disassociation frame to AP */
1551 lim_send_disassoc_mgmt_frame(mac_ctx,
1552 REASON_UNSPEC_FAILURE, hdr->sa,
1553 session_entry, false);
1554 goto assocReject;
1555 }
1556
1557 if (ap_nss < session_entry->nss)
1558 session_entry->nss = ap_nss;
1559
1560 lim_objmgr_update_vdev_nss(mac_ctx->psoc,
1561 session_entry->smeSessionId,
1562 session_entry->nss);
1563 lim_update_vdev_rate_set(mac_ctx->psoc,
1564 session_entry->smeSessionId,
1565 assoc_rsp);
1566
1567 if ((session_entry->limMlmState ==
1568 eLIM_MLM_WT_FT_REASSOC_RSP_STATE) ||
1569 lim_is_roam_synch_in_progress(mac_ctx->psoc,
1570 session_entry)) {
1571 pe_debug("Sending self sta");
1572 lim_update_assoc_sta_datas(mac_ctx, sta_ds, assoc_rsp,
1573 session_entry, NULL);
1574 lim_update_stads_ext_cap(mac_ctx, session_entry,
1575 assoc_rsp, sta_ds);
1576 /* Store assigned AID for TIM processing */
1577 session_entry->limAID = assoc_rsp->aid & 0x3FFF;
1578 /* Downgrade the EDCA parameters if needed */
1579 lim_set_active_edca_params(mac_ctx,
1580 session_entry->gLimEdcaParams,
1581 session_entry);
1582 /* Send the active EDCA parameters to HAL */
1583 if (!lim_is_roam_synch_in_progress(mac_ctx->psoc,
1584 session_entry)) {
1585 lim_send_edca_params(mac_ctx,
1586 session_entry->gLimEdcaParamsActive,
1587 session_entry->vdev_id, false);
1588 lim_add_ft_sta_self(mac_ctx,
1589 (assoc_rsp->aid & 0x3FFF),
1590 session_entry);
1591 } else {
1592 lim_set_emlsr_caps(mac_ctx, session_entry);
1593 lim_objmgr_update_emlsr_caps(mac_ctx->psoc,
1594 session_entry->vdev_id,
1595 assoc_rsp);
1596 lim_cache_emlsr_params(session_entry,
1597 assoc_rsp);
1598 }
1599 qdf_mem_free(beacon);
1600 return;
1601 }
1602
1603 /*
1604 * If we're re-associating to the same BSS,
1605 * we don't want to invoke delete STA, delete
1606 * BSS, as that would remove the already
1607 * established TSPEC. Just go ahead and re-add
1608 * the BSS, STA with new capability information.
1609 * However, if we're re-associating to a different
1610 * BSS, then follow thru with del STA, del BSS,
1611 * add BSS, add STA.
1612 */
1613 if (sir_compare_mac_addr(session_entry->bssId,
1614 session_entry->limReAssocbssId))
1615 lim_handle_add_bss_in_re_assoc_context(mac_ctx, sta_ds,
1616 session_entry);
1617 else {
1618 /*
1619 * reset the uapsd mask settings since
1620 * we're re-associating to new AP
1621 */
1622 session_entry->gUapsdPerAcDeliveryEnableMask = 0;
1623 session_entry->gUapsdPerAcTriggerEnableMask = 0;
1624
1625 lim_mlo_notify_peer_disconn(session_entry, sta_ds);
1626 if (lim_cleanup_rx_path(mac_ctx, sta_ds, session_entry,
1627 true) != QDF_STATUS_SUCCESS) {
1628 pe_err("Could not cleanup the rx path");
1629 goto assocReject;
1630 }
1631 }
1632 if (!mlo_roam_is_auth_status_connected(mac_ctx->psoc,
1633 wlan_vdev_get_id(session_entry->vdev))) {
1634 qdf_mem_free(beacon);
1635 return;
1636 }
1637 }
1638 pe_debug("Successfully Associated with BSS " QDF_MAC_ADDR_FMT,
1639 QDF_MAC_ADDR_REF(hdr->sa));
1640
1641 #ifdef FEATURE_WLAN_ESE
1642 if (session_entry->eseContext.tsm.tsmInfo.state)
1643 session_entry->eseContext.tsm.tsmMetrics.RoamingCount = 0;
1644 #endif
1645 /* Store assigned AID for TIM processing */
1646 session_entry->limAID = assoc_rsp->aid & 0x3FFF;
1647
1648 /* STA entry was created during pre-assoc state. */
1649 sta_ds = dph_get_hash_entry(mac_ctx, DPH_STA_HASH_INDEX_PEER,
1650 &session_entry->dph.dphHashTable);
1651 if (!sta_ds) {
1652 /* Could not add hash table entry */
1653 pe_err("could not get hash entry at DPH SA: "QDF_MAC_ADDR_FMT,
1654 QDF_MAC_ADDR_REF(hdr->sa));
1655 assoc_cnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE;
1656 assoc_cnf.protStatusCode = eSIR_SME_SUCCESS;
1657 lim_post_sme_message(mac_ctx, LIM_MLM_ASSOC_CNF,
1658 (uint32_t *) &assoc_cnf);
1659 clean_up_ft_sha384(assoc_rsp, sha384_akm);
1660 /*
1661 * Don't free the assoc rsp if it's cached in pe_session.
1662 * It would be reused in link connect in cases like OWE
1663 * roaming
1664 */
1665 if (session_entry->limAssocResponseData != assoc_rsp)
1666 qdf_mem_free(assoc_rsp);
1667 qdf_mem_free(beacon);
1668 return;
1669 }
1670 /* Delete Pre-auth context for the associated BSS */
1671 if (lim_search_pre_auth_list(mac_ctx, hdr->sa))
1672 lim_delete_pre_auth_node(mac_ctx, hdr->sa);
1673
1674 if (ap_nss < session_entry->nss)
1675 session_entry->nss = ap_nss;
1676
1677 lim_objmgr_update_vdev_nss(mac_ctx->psoc,
1678 session_entry->smeSessionId,
1679 session_entry->nss);
1680 lim_update_vdev_rate_set(mac_ctx->psoc, session_entry->smeSessionId,
1681 assoc_rsp);
1682 if (QDF_IS_STATUS_ERROR(lim_update_sta_vdev_punc(
1683 mac_ctx->psoc,
1684 session_entry->smeSessionId,
1685 assoc_rsp))) {
1686 assoc_cnf.resultCode = eSIR_SME_INVALID_ASSOC_RSP_RXED;
1687 assoc_cnf.protStatusCode = STATUS_UNSPECIFIED_FAILURE;
1688 /* Send advisory Disassociation frame to AP */
1689 lim_send_disassoc_mgmt_frame(mac_ctx,
1690 REASON_UNSPEC_FAILURE,
1691 hdr->sa, session_entry, false);
1692 goto assocReject;
1693 }
1694
1695 lim_objmgr_update_emlsr_caps(mac_ctx->psoc, session_entry->smeSessionId,
1696 assoc_rsp);
1697
1698 lim_process_assoc_rsp_t2lm(session_entry, assoc_rsp);
1699 /*
1700 * Extract the AP capabilities from the beacon that
1701 * was received earlier
1702 */
1703 ie_len = lim_get_ielen_from_bss_description(
1704 &session_entry->lim_join_req->bssDescription);
1705 ie = (uint8_t *)session_entry->lim_join_req->bssDescription.ieFields;
1706 lim_update_iot_aggr_sz(mac_ctx, ie, ie_len, session_entry);
1707
1708 lim_extract_ap_capabilities(mac_ctx, ie, ie_len, beacon);
1709
1710 if (session_entry->opmode == QDF_STA_MODE) {
1711 lim_enable_cts_to_self_for_exempted_iot_ap(
1712 mac_ctx, session_entry,
1713 ie, ie_len);
1714 }
1715
1716 lim_update_assoc_sta_datas(mac_ctx, sta_ds, assoc_rsp,
1717 session_entry, beacon);
1718
1719 if (lim_is_session_he_capable(session_entry)) {
1720 session_entry->mu_edca_present = assoc_rsp->mu_edca_present;
1721 if (session_entry->mu_edca_present) {
1722 pe_debug("Save MU EDCA params to session");
1723 session_entry->ap_mu_edca_params[QCA_WLAN_AC_BE] =
1724 assoc_rsp->mu_edca.acbe;
1725 session_entry->ap_mu_edca_params[QCA_WLAN_AC_BK] =
1726 assoc_rsp->mu_edca.acbk;
1727 session_entry->ap_mu_edca_params[QCA_WLAN_AC_VI] =
1728 assoc_rsp->mu_edca.acvi;
1729 session_entry->ap_mu_edca_params[QCA_WLAN_AC_VO] =
1730 assoc_rsp->mu_edca.acvo;
1731 }
1732 }
1733
1734 if (beacon->VHTCaps.present)
1735 sta_ds->parsed_ies.vht_caps = beacon->VHTCaps;
1736 if (beacon->HTCaps.present)
1737 sta_ds->parsed_ies.ht_caps = beacon->HTCaps;
1738 if (beacon->hs20vendor_ie.present)
1739 sta_ds->parsed_ies.hs20vendor_ie = beacon->hs20vendor_ie;
1740 if (beacon->HTInfo.present)
1741 sta_ds->parsed_ies.ht_operation = beacon->HTInfo;
1742 if (beacon->VHTOperation.present)
1743 sta_ds->parsed_ies.vht_operation = beacon->VHTOperation;
1744
1745 lim_process_he_info(beacon, sta_ds);
1746 if (lim_process_srp_ie(assoc_rsp, sta_ds) == QDF_STATUS_SUCCESS)
1747 lim_update_vdev_sr_elements(session_entry, sta_ds);
1748
1749 if (lim_is_session_eht_capable(session_entry))
1750 lim_process_eht_info(beacon, sta_ds);
1751
1752 if (mac_ctx->lim.gLimProtectionControl !=
1753 MLME_FORCE_POLICY_PROTECTION_DISABLE)
1754 lim_decide_sta_protection_on_assoc(mac_ctx, beacon,
1755 session_entry);
1756
1757 if (beacon->erpPresent) {
1758 if (beacon->erpIEInfo.barkerPreambleMode)
1759 session_entry->beaconParams.fShortPreamble = false;
1760 else
1761 session_entry->beaconParams.fShortPreamble = true;
1762 }
1763
1764 #ifdef FEATURE_WLAN_DIAG_SUPPORT
1765 lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_CONNECTED, session_entry,
1766 QDF_STATUS_SUCCESS, QDF_STATUS_SUCCESS);
1767 #endif
1768 lim_update_stads_ext_cap(mac_ctx, session_entry, assoc_rsp, sta_ds);
1769
1770 /* Update the BSS Entry, this entry was added during preassoc. */
1771 if (QDF_STATUS_SUCCESS ==
1772 lim_sta_send_add_bss(mac_ctx, assoc_rsp, beacon,
1773 &session_entry->lim_join_req->bssDescription,
1774 true, session_entry)) {
1775 clean_up_ft_sha384(assoc_rsp, sha384_akm);
1776 if (session_entry->limAssocResponseData != assoc_rsp)
1777 qdf_mem_free(assoc_rsp);
1778
1779 qdf_mem_free(beacon);
1780
1781 return;
1782 }
1783
1784 pe_err("vdev:%d could not update the bss entry",
1785 session_entry->vdev_id);
1786 assoc_cnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE;
1787 assoc_cnf.protStatusCode = STATUS_UNSPECIFIED_FAILURE;
1788
1789 assocReject:
1790 if (subtype == LIM_ASSOC ||
1791 (subtype == LIM_REASSOC &&
1792 session_entry->limMlmState == eLIM_MLM_WT_FT_REASSOC_RSP_STATE)) {
1793 pe_err("Assoc Rejected by the peer mlmestate: %d sessionid: %d Reason: %d MACADDR:"
1794 QDF_MAC_ADDR_FMT, session_entry->limMlmState,
1795 session_entry->peSessionId, assoc_cnf.resultCode,
1796 QDF_MAC_ADDR_REF(hdr->sa));
1797
1798 session_entry->limMlmState = eLIM_MLM_IDLE_STATE;
1799 MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE,
1800 session_entry->peSessionId,
1801 session_entry->limMlmState));
1802 if (session_entry->pLimMlmJoinReq) {
1803 qdf_mem_free(session_entry->pLimMlmJoinReq);
1804 session_entry->pLimMlmJoinReq = NULL;
1805 }
1806
1807 if (subtype == LIM_ASSOC) {
1808 lim_post_sme_message(mac_ctx, LIM_MLM_ASSOC_CNF,
1809 (uint32_t *) &assoc_cnf);
1810 } else {
1811 assoc_cnf.resultCode = eSIR_SME_FT_REASSOC_FAILURE;
1812 lim_post_sme_message(mac_ctx, LIM_MLM_REASSOC_CNF,
1813 (uint32_t *)&assoc_cnf);
1814 }
1815 } else {
1816 lim_restore_pre_reassoc_state(mac_ctx,
1817 eSIR_SME_REASSOC_REFUSED,
1818 assoc_cnf.protStatusCode,
1819 session_entry);
1820 }
1821
1822 qdf_mem_free(beacon);
1823 qdf_mem_free(assoc_rsp->sha384_ft_subelem.gtk);
1824 qdf_mem_free(assoc_rsp->sha384_ft_subelem.igtk);
1825 qdf_mem_free(assoc_rsp);
1826
1827 return;
1828 }
1829