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 *) ¤t_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