1 /*
2 * Copyright (c) 2012-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 sch_beacon_process.cc contains beacon processing related
22 * functions
23 *
24 * Author: Sandesh Goel
25 * Date: 02/25/02
26 * History:-
27 * Date Modified by Modification Information
28 * --------------------------------------------------------------------
29 *
30 */
31
32 #include "cds_api.h"
33 #include "wni_cfg.h"
34
35 #include "cfg_ucfg_api.h"
36 #include "lim_api.h"
37 #include "utils_api.h"
38 #include "sch_api.h"
39
40 #include "lim_utils.h"
41 #include "lim_send_messages.h"
42 #include "rrm_api.h"
43 #include "lim_mlo.h"
44
45 #ifdef FEATURE_WLAN_DIAG_SUPPORT
46 #include "host_diag_core_log.h"
47 #endif /* FEATURE_WLAN_DIAG_SUPPORT */
48
49 #include "wma.h"
50
51 #include "wlan_lmac_if_def.h"
52 #include "wlan_reg_services_api.h"
53 #include "wlan_mlo_mgr_sta.h"
54 #include "wlan_mlme_main.h"
55 #include <wlan_mlo_mgr_link_switch.h>
56
57 static void
ap_beacon_process_5_ghz(struct mac_context * mac_ctx,uint8_t * rx_pkt_info,tpSchBeaconStruct bcn_struct,tpUpdateBeaconParams bcn_prm,struct pe_session * session,uint32_t phy_mode)58 ap_beacon_process_5_ghz(struct mac_context *mac_ctx, uint8_t *rx_pkt_info,
59 tpSchBeaconStruct bcn_struct,
60 tpUpdateBeaconParams bcn_prm, struct pe_session *session,
61 uint32_t phy_mode)
62 {
63 tpSirMacMgmtHdr mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
64
65 if (!session->htCapability)
66 return;
67
68 if (bcn_struct->chan_freq != session->curr_op_freq)
69 return;
70
71 /* 11a (non HT) AP overlaps or */
72 /* HT AP with HT op mode as mixed overlaps. */
73 /* HT AP with HT op mode as overlap legacy overlaps. */
74 if (!bcn_struct->HTInfo.present
75 || (eSIR_HT_OP_MODE_MIXED == bcn_struct->HTInfo.opMode)
76 || (eSIR_HT_OP_MODE_OVERLAP_LEGACY == bcn_struct->HTInfo.opMode)) {
77 lim_update_overlap_sta_param(mac_ctx, mac_hdr->bssId,
78 &(session->gLimOverlap11aParams));
79
80 if (session->gLimOverlap11aParams.numSta
81 && !session->gLimOverlap11aParams.protectionEnabled) {
82 lim_update_11a_protection(mac_ctx, true, true,
83 bcn_prm, session);
84 }
85 return;
86 }
87 /* HT AP with HT20 op mode overlaps. */
88 if (eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT != bcn_struct->HTInfo.opMode)
89 return;
90
91 lim_update_overlap_sta_param(mac_ctx, mac_hdr->bssId,
92 &(session->gLimOverlapHt20Params));
93
94 if (session->gLimOverlapHt20Params.numSta
95 && !session->gLimOverlapHt20Params.protectionEnabled)
96 lim_enable_ht20_protection(mac_ctx, true, true,
97 bcn_prm, session);
98 }
99
100 static void
ap_beacon_process_24_ghz(struct mac_context * mac_ctx,uint8_t * rx_pkt_info,tpSchBeaconStruct bcn_struct,tpUpdateBeaconParams bcn_prm,struct pe_session * session,uint32_t phy_mode)101 ap_beacon_process_24_ghz(struct mac_context *mac_ctx, uint8_t *rx_pkt_info,
102 tpSchBeaconStruct bcn_struct,
103 tpUpdateBeaconParams bcn_prm, struct pe_session *session,
104 uint32_t phy_mode)
105 {
106 tpSirMacMgmtHdr mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
107 bool tmp_exp = false;
108 /* We are 11G AP. */
109 if ((phy_mode == WNI_CFG_PHY_MODE_11G) &&
110 (false == session->htCapability)) {
111 if (bcn_struct->chan_freq != session->curr_op_freq)
112 return;
113
114 tmp_exp = (!bcn_struct->erpPresent &&
115 !bcn_struct->HTInfo.present) ||
116 /* if erp not present then 11B AP overlapping */
117 (!mac_ctx->mlme_cfg->sta.ignore_peer_erp_info &&
118 bcn_struct->erpPresent &&
119 (bcn_struct->erpIEInfo.useProtection ||
120 bcn_struct->erpIEInfo.nonErpPresent));
121 if (!tmp_exp)
122 return;
123 #ifdef FEATURE_WLAN_ESE
124 if (wlan_cm_get_ese_assoc(mac_ctx->pdev, session->vdev_id))
125 pe_info("[INFOLOG]ESE 11g erpPresent=%d useProtection=%d nonErpPresent=%d",
126 bcn_struct->erpPresent,
127 bcn_struct->erpIEInfo.useProtection,
128 bcn_struct->erpIEInfo.nonErpPresent);
129 #endif
130 lim_enable_overlap11g_protection(mac_ctx, bcn_prm,
131 mac_hdr, session);
132 return;
133 }
134 /* handling the case when HT AP has overlapping legacy BSS. */
135 if (!session->htCapability)
136 return;
137
138 if (bcn_struct->chan_freq != session->curr_op_freq)
139 return;
140
141 tmp_exp = (!bcn_struct->erpPresent && !bcn_struct->HTInfo.present) ||
142 /* if erp not present then 11B AP overlapping */
143 (!mac_ctx->mlme_cfg->sta.ignore_peer_erp_info &&
144 bcn_struct->erpPresent &&
145 (bcn_struct->erpIEInfo.useProtection ||
146 bcn_struct->erpIEInfo.nonErpPresent));
147 if (tmp_exp) {
148 #ifdef FEATURE_WLAN_ESE
149 if (wlan_cm_get_ese_assoc(mac_ctx->pdev, session->vdev_id)) {
150 pe_info("[INFOLOG]ESE 11g erpPresent=%d useProtection=%d nonErpPresent=%d",
151 bcn_struct->erpPresent,
152 bcn_struct->erpIEInfo.useProtection,
153 bcn_struct->erpIEInfo.nonErpPresent);
154 }
155 #endif
156 lim_enable_overlap11g_protection(mac_ctx, bcn_prm,
157 mac_hdr, session);
158 }
159 /* 11g device overlaps */
160 tmp_exp = bcn_struct->erpPresent
161 && !(bcn_struct->erpIEInfo.useProtection
162 || bcn_struct->erpIEInfo.nonErpPresent)
163 && !(bcn_struct->HTInfo.present);
164 if (tmp_exp) {
165 lim_update_overlap_sta_param(mac_ctx, mac_hdr->bssId,
166 &(session->gLimOverlap11gParams));
167
168 if (session->gLimOverlap11gParams.numSta
169 && !session->gLimOverlap11gParams.protectionEnabled)
170 lim_enable_ht_protection_from11g(mac_ctx, true, true,
171 bcn_prm, session);
172 }
173 /* ht device overlaps.
174 * here we will check for HT related devices only which might need
175 * protection. check for 11b and 11g is already done in the previous
176 * blocks. so we will not check for HT operating mode as MIXED.
177 */
178 if (!bcn_struct->HTInfo.present)
179 return;
180
181 /*
182 * if we are not already in mixed mode or legacy mode as HT operating
183 * mode and received beacon has HT operating mode as legacy then we need
184 * to enable protection from 11g station. we don't need protection from
185 * 11b because if that's needed then our operating mode would have
186 * already been set to legacy in the previous blocks.
187 */
188 if ((eSIR_HT_OP_MODE_OVERLAP_LEGACY == bcn_struct->HTInfo.opMode) &&
189 !mac_ctx->mlme_cfg->sap_protection_cfg.ignore_peer_ht_opmode) {
190 if (eSIR_HT_OP_MODE_OVERLAP_LEGACY == mac_ctx->lim.gHTOperMode
191 || eSIR_HT_OP_MODE_MIXED == mac_ctx->lim.gHTOperMode)
192 return;
193 lim_update_overlap_sta_param(mac_ctx, mac_hdr->bssId,
194 &(session->gLimOverlap11gParams));
195 if (session->gLimOverlap11gParams.numSta
196 && !session->gLimOverlap11gParams.protectionEnabled)
197 lim_enable_ht_protection_from11g(mac_ctx, true, true,
198 bcn_prm, session);
199 return;
200 }
201
202 if (eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT == bcn_struct->HTInfo.opMode) {
203 lim_update_overlap_sta_param(mac_ctx, mac_hdr->bssId,
204 &(session->gLimOverlapHt20Params));
205 if (session->gLimOverlapHt20Params.numSta
206 && !session->gLimOverlapHt20Params.protectionEnabled)
207 lim_enable_ht20_protection(mac_ctx, true, true,
208 bcn_prm, session);
209 }
210 }
211
212 /**
213 * ap_beacon_process() - processes incoming beacons
214 *
215 * @mac_ctx: mac global context
216 * @rx_pkt_info: incoming beacon packet
217 * @bcn_struct: beacon struct
218 * @bcn_prm: beacon params
219 * @session: pe session entry
220 *
221 * Return: void
222 */
223 static void
ap_beacon_process(struct mac_context * mac_ctx,uint8_t * rx_pkt_info,tpSchBeaconStruct bcn_struct,tpUpdateBeaconParams bcn_prm,struct pe_session * session)224 ap_beacon_process(struct mac_context *mac_ctx, uint8_t *rx_pkt_info,
225 tpSchBeaconStruct bcn_struct,
226 tpUpdateBeaconParams bcn_prm, struct pe_session *session)
227 {
228 uint32_t phy_mode;
229 enum reg_wifi_band rf_band = REG_BAND_UNKNOWN;
230 /* Get RF band from session */
231 rf_band = session->limRFBand;
232
233 lim_get_phy_mode(mac_ctx, &phy_mode, session);
234
235 if (REG_BAND_5G == rf_band)
236 ap_beacon_process_5_ghz(mac_ctx, rx_pkt_info, bcn_struct,
237 bcn_prm, session, phy_mode);
238 else if (REG_BAND_2G == rf_band)
239 ap_beacon_process_24_ghz(mac_ctx, rx_pkt_info, bcn_struct,
240 bcn_prm, session, phy_mode);
241 }
242
243 /* -------------------------------------------------------------------- */
244
245 /*
246 * sch_bcn_process_sta() - Process the received beacon frame for sta
247 * @mac_ctx: mac_ctx
248 * @bcn: beacon struct
249 * @rx_pkt_info: received packet info
250 * @session: pe session pointer
251 * @beaconParams: update beacon params
252 * @sendProbeReq: out flag to indicate if probe rsp is to be sent
253 * @pMh: mac header
254 *
255 * Process the received beacon frame for sta
256 *
257 * Return: success of failure of operation
258 */
259 static bool
sch_bcn_process_sta(struct mac_context * mac_ctx,tpSchBeaconStruct bcn,uint8_t * rx_pkt_info,struct pe_session * session,tUpdateBeaconParams * beaconParams,uint8_t * sendProbeReq,tpSirMacMgmtHdr pMh)260 sch_bcn_process_sta(struct mac_context *mac_ctx,
261 tpSchBeaconStruct bcn,
262 uint8_t *rx_pkt_info,
263 struct pe_session *session,
264 tUpdateBeaconParams *beaconParams,
265 uint8_t *sendProbeReq, tpSirMacMgmtHdr pMh)
266 {
267 uint32_t bi;
268 tpDphHashNode sta = NULL;
269 QDF_STATUS status;
270
271 /*
272 * This handles two cases:
273 * -- Infra STA receiving beacons from AP
274 */
275
276 /**
277 * This is the Beacon received from the AP we're currently associated
278 * with. Check if there are any changes in AP's capabilities
279 */
280 if (bcn->chan_freq != session->curr_op_freq) {
281 pe_err("Channel Change freq from %d --> %d - Ignoring beacon!",
282 session->curr_op_freq, bcn->chan_freq);
283 return false;
284 }
285
286 /*
287 * Ignore bcn as channel switch IE present and csa offload is enabled,
288 * as in CSA offload enabled case FW will send Event to switch channel
289 */
290 if (bcn->channelSwitchPresent && wma_is_csa_offload_enabled()) {
291 pe_err_rl("Ignore bcn as channel switch IE present and csa offload is enabled");
292 return false;
293 }
294
295 lim_detect_change_in_ap_capabilities(mac_ctx, bcn, session, true);
296 beaconParams->bss_idx = session->vdev_id;
297 qdf_mem_copy((uint8_t *) &session->lastBeaconTimeStamp,
298 (uint8_t *) bcn->timeStamp, sizeof(uint64_t));
299 session->currentBssBeaconCnt++;
300 if (session->bcon_dtim_period != bcn->tim.dtimPeriod) {
301 session->bcon_dtim_period = bcn->tim.dtimPeriod;
302 lim_send_set_dtim_period(mac_ctx, bcn->tim.dtimPeriod,
303 session);
304 }
305 MTRACE(mac_trace(mac_ctx, TRACE_CODE_RX_MGMT_TSF,
306 session->peSessionId, bcn->timeStamp[0]));
307 MTRACE(mac_trace(mac_ctx, TRACE_CODE_RX_MGMT_TSF,
308 session->peSessionId, bcn->timeStamp[1]));
309
310 /* Read beacon interval session Entry */
311 bi = session->beaconParams.beaconInterval;
312 if (bi != bcn->beaconInterval) {
313 pe_debug("Beacon interval changed from %d to %d",
314 bcn->beaconInterval, bi);
315
316 bi = bcn->beaconInterval;
317 session->beaconParams.beaconInterval = (uint16_t) bi;
318 beaconParams->paramChangeBitmap |= PARAM_BCN_INTERVAL_CHANGED;
319 beaconParams->beaconInterval = (uint16_t) bi;
320 }
321
322 if (bcn->cfPresent) {
323 if (!cfg_in_range(CFG_CFP_PERIOD, bcn->cfParamSet.cfpPeriod)) {
324 pe_err("Error in setting CFG item CFP Period");
325 return false;
326 }
327 mac_ctx->mlme_cfg->rates.cfp_period = bcn->cfParamSet.cfpPeriod;
328 }
329
330 /* No need to send DTIM Period and Count to HAL/SMAC */
331 /* SMAC already parses TIM bit. */
332 if (bcn->timPresent) {
333 if (cfg_in_range(CFG_DTIM_PERIOD, bcn->tim.dtimPeriod))
334 mac_ctx->mlme_cfg->sap_cfg.dtim_interval =
335 bcn->tim.dtimPeriod;
336 }
337
338 if (mac_ctx->lim.gLimProtectionControl !=
339 MLME_FORCE_POLICY_PROTECTION_DISABLE)
340 lim_decide_sta_protection(mac_ctx, bcn, beaconParams, session);
341
342 if (bcn->erpPresent) {
343 if (bcn->erpIEInfo.barkerPreambleMode)
344 lim_enable_short_preamble(mac_ctx, false,
345 beaconParams, session);
346 else
347 lim_enable_short_preamble(mac_ctx, true,
348 beaconParams, session);
349 }
350 lim_update_short_slot(mac_ctx, bcn, beaconParams, session);
351
352 sta = dph_get_hash_entry(mac_ctx, DPH_STA_HASH_INDEX_PEER,
353 &session->dph.dphHashTable);
354 if ((bcn->wmeEdcaPresent && session->limWmeEnabled) ||
355 (bcn->edcaPresent && session->limQosEnabled)) {
356 if (bcn->edcaParams.qosInfo.count !=
357 session->gLimEdcaParamSetCount) {
358 qdf_mem_copy(&sta->qos.peer_edca_params,
359 &bcn->edcaParams,
360 sizeof(bcn->edcaParams));
361 status = sch_beacon_edca_process(mac_ctx,
362 &bcn->edcaParams,
363 session);
364 if (QDF_IS_STATUS_ERROR(status)) {
365 pe_err("EDCA parameter processing error");
366 } else if (sta) {
367 /* If needed, downgrade the EDCA parameters */
368 lim_set_active_edca_params(mac_ctx,
369 session->gLimEdcaParams, session);
370 lim_send_edca_params(mac_ctx,
371 session->gLimEdcaParamsActive,
372 session->vdev_id, false);
373 sch_qos_concurrency_update();
374 } else {
375 pe_err("Self Entry missing in Hash Table");
376 }
377 }
378 return true;
379 }
380
381 if ((bcn->qosCapabilityPresent && session->limQosEnabled)
382 && (bcn->qosCapability.qosInfo.count !=
383 session->gLimEdcaParamSetCount))
384 *sendProbeReq = true;
385
386 return true;
387 }
388
389 #ifdef WLAN_FEATURE_11AX_BSS_COLOR
390 static void
sch_bcn_update_he_ies(struct mac_context * mac_ctx,tpDphHashNode sta_ds,struct pe_session * session,tpSchBeaconStruct bcn,tpSirMacMgmtHdr mac_hdr)391 sch_bcn_update_he_ies(struct mac_context *mac_ctx, tpDphHashNode sta_ds,
392 struct pe_session *session, tpSchBeaconStruct bcn,
393 tpSirMacMgmtHdr mac_hdr)
394 {
395 uint8_t session_bss_col_disabled_flag;
396 bool anything_changed = false;
397
398 if (session->is_session_obss_color_collision_det_enabled)
399 return;
400
401 if (session->he_op.present && bcn->he_op.present) {
402 if (bcn->vendor_he_bss_color_change.present &&
403 (session->he_op.bss_color !=
404 bcn->vendor_he_bss_color_change.new_color)) {
405 pe_debug("bss color changed from [%d] to [%d]",
406 session->he_op.bss_color,
407 bcn->vendor_he_bss_color_change.new_color);
408 session->he_op.bss_color =
409 bcn->vendor_he_bss_color_change.new_color;
410 anything_changed = true;
411 }
412 session_bss_col_disabled_flag = session->he_op.bss_col_disabled;
413 if (session_bss_col_disabled_flag !=
414 bcn->he_op.bss_col_disabled) {
415 pe_debug("color disable flag changed from [%d] to [%d]",
416 session->he_op.bss_col_disabled,
417 bcn->he_op.bss_col_disabled);
418 session->he_op.bss_col_disabled =
419 bcn->he_op.bss_col_disabled;
420 anything_changed = true;
421 }
422 }
423 if (anything_changed)
424 lim_send_he_ie_update(mac_ctx, session);
425 }
426 #else
427 static void
sch_bcn_update_he_ies(struct mac_context * mac_ctx,tpDphHashNode sta_ds,struct pe_session * session,tpSchBeaconStruct bcn,tpSirMacMgmtHdr mac_hdr)428 sch_bcn_update_he_ies(struct mac_context *mac_ctx, tpDphHashNode sta_ds,
429 struct pe_session *session, tpSchBeaconStruct bcn,
430 tpSirMacMgmtHdr mac_hdr)
431 {
432 return;
433 }
434 #endif
435
436 static void
sch_bcn_update_opmode_change(struct mac_context * mac_ctx,tpDphHashNode sta_ds,struct pe_session * session,tpSchBeaconStruct bcn,tpSirMacMgmtHdr mac_hdr)437 sch_bcn_update_opmode_change(struct mac_context *mac_ctx, tpDphHashNode sta_ds,
438 struct pe_session *session, tpSchBeaconStruct bcn,
439 tpSirMacMgmtHdr mac_hdr)
440 {
441 enum phy_ch_width ch_bw;
442 enum phy_ch_width ch_width = CH_WIDTH_20MHZ;
443 tDot11fIEVHTCaps *vht_caps = NULL;
444 tDot11fIEVHTOperation *vht_op = NULL;
445 uint8_t bcn_vht_chwidth = 0;
446 bool is_40 = false;
447
448 /*
449 * Ignore opmode change during channel change The opmode will be updated
450 * with the beacons on new channel once the AP move to new channel.
451 */
452 if (session->ch_switch_in_progress) {
453 pe_debug("Ignore opmode change as channel switch is in progress");
454 return;
455 }
456 if (bcn->eht_op.eht_op_information_present) {
457 pe_debug("Ignore opmode change as there is EHT operation information");
458 return;
459 }
460
461 if (bcn->VHTCaps.present) {
462 vht_caps = &bcn->VHTCaps;
463 vht_op = &bcn->VHTOperation;
464 } else if (bcn->vendor_vht_ie.VHTCaps.present) {
465 vht_caps = &bcn->vendor_vht_ie.VHTCaps;
466 vht_op = &bcn->vendor_vht_ie.VHTOperation;
467 }
468 if (!session->vhtCapability ||
469 !(bcn->OperatingMode.present ||
470 (vht_op && vht_op->present && vht_caps)))
471 return;
472
473 is_40 = bcn->HTInfo.present ?
474 bcn->HTInfo.recommendedTxWidthSet : false;
475
476 if (bcn->OperatingMode.present) {
477 lim_update_nss(mac_ctx, sta_ds, bcn->OperatingMode.rxNSS,
478 session);
479 ch_width = bcn->OperatingMode.chanWidth;
480 pe_debug("OMN IE present in bcn/probe rsp, omn_ie_ch_width: %d",
481 ch_width);
482 lim_update_omn_ie_ch_width(session->vdev, ch_width);
483
484 } else {
485 bcn_vht_chwidth = lim_get_vht_ch_width(vht_caps, vht_op,
486 &bcn->HTInfo);
487 ch_width =
488 lim_convert_vht_chwidth_to_phy_chwidth(bcn_vht_chwidth,
489 is_40);
490 }
491
492 lim_update_channel_width(mac_ctx, sta_ds, session, ch_width, &ch_bw);
493 }
494
495 #ifdef WLAN_FEATURE_SR
496 /**
497 * lim_detect_change_in_srp() - Detect change in SRP IE
498 * of the beacon
499 *
500 * @mac_ctx: global mac context
501 * @sta: pointer to sta node
502 * @session: pointer to LIM session
503 * @bcn: beacon from associated AP
504 *
505 * Detect change in SRP IE of the beacon and update the params
506 * accordingly.
507 *
508 * Return: None
509 */
lim_detect_change_in_srp(struct mac_context * mac_ctx,tpDphHashNode sta,struct pe_session * session,tpSchBeaconStruct bcn)510 static void lim_detect_change_in_srp(struct mac_context *mac_ctx,
511 tpDphHashNode sta,
512 struct pe_session *session,
513 tpSchBeaconStruct bcn)
514 {
515 tDot11fIEspatial_reuse sr_ie;
516 int32_t ret = 0;
517
518 sr_ie = sta->parsed_ies.srp_ie;
519 if (sr_ie.present || bcn->srp_ie.present) {
520 ret = qdf_mem_cmp(&sr_ie, &bcn->srp_ie,
521 sizeof(tDot11fIEspatial_reuse));
522
523 if (ret) {
524 /*
525 * If SRP IE has changes, update the new params.
526 */
527 sta->parsed_ies.srp_ie = bcn->srp_ie;
528 lim_update_vdev_sr_elements(session, sta);
529
530 lim_handle_sr_cap(session->vdev,
531 SR_REASON_CODE_BCN_IE_CHANGE);
532 }
533 }
534 }
535 #else
lim_detect_change_in_srp(struct mac_context * mac_ctx,tpDphHashNode sta,struct pe_session * session,tpSchBeaconStruct bcn)536 static void lim_detect_change_in_srp(struct mac_context *mac_ctx,
537 tpDphHashNode sta,
538 struct pe_session *session,
539 tpSchBeaconStruct bcn)
540 {
541 }
542 #endif
543
544 static void
sch_bcn_process_sta_opmode(struct mac_context * mac_ctx,tpSchBeaconStruct bcn,uint8_t * rx_pkt_info,struct pe_session * session,tUpdateBeaconParams * beaconParams,uint8_t * sendProbeReq,tpSirMacMgmtHdr pMh)545 sch_bcn_process_sta_opmode(struct mac_context *mac_ctx,
546 tpSchBeaconStruct bcn,
547 uint8_t *rx_pkt_info,
548 struct pe_session *session,
549 tUpdateBeaconParams *beaconParams,
550 uint8_t *sendProbeReq, tpSirMacMgmtHdr pMh)
551 {
552 tpDphHashNode sta = NULL;
553 uint16_t aid;
554
555 /* check for VHT capability */
556 sta = dph_lookup_hash_entry(mac_ctx, pMh->sa, &aid,
557 &session->dph.dphHashTable);
558 if (!sta)
559 return;
560 sch_bcn_update_opmode_change(mac_ctx, sta, session, bcn, pMh);
561 sch_bcn_update_he_ies(mac_ctx, sta, session, bcn, pMh);
562 lim_detect_change_in_srp(mac_ctx, sta, session, bcn);
563 return;
564 }
565
566 /**
567 * get_local_power_constraint_beacon() - extracts local constraint
568 * from beacon
569 * @bcn: beacon structure
570 * @local_constraint: local constraint pointer
571 * @is_power_constraint_abs: is power constraint absolute
572 *
573 * Return: None
574 */
575 #ifdef FEATURE_WLAN_ESE
get_local_power_constraint_beacon(tpSchBeaconStruct bcn,int8_t * local_constraint,bool * is_power_constraint_abs)576 static void get_local_power_constraint_beacon(
577 tpSchBeaconStruct bcn,
578 int8_t *local_constraint,
579 bool *is_power_constraint_abs)
580 {
581 if (bcn->eseTxPwr.present) {
582 *local_constraint = bcn->eseTxPwr.power_limit;
583 *is_power_constraint_abs = true;
584 }
585 }
586 #else
get_local_power_constraint_beacon(tpSchBeaconStruct bcn,int8_t * local_constraint,bool * is_power_constraint_abs)587 static void get_local_power_constraint_beacon(
588 tpSchBeaconStruct bcn,
589 int8_t *local_constraint,
590 bool *is_power_constraint_abs)
591 {
592
593 }
594 #endif
595
__sch_beacon_process_for_session(struct mac_context * mac_ctx,tpSchBeaconStruct bcn,uint8_t * rx_pkt_info,struct pe_session * session)596 static void __sch_beacon_process_for_session(struct mac_context *mac_ctx,
597 tpSchBeaconStruct bcn,
598 uint8_t *rx_pkt_info,
599 struct pe_session *session)
600 {
601 tUpdateBeaconParams beaconParams;
602 uint8_t sendProbeReq = false;
603 tpSirMacMgmtHdr pMh = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
604 int8_t local_constraint = 0;
605 uint32_t chan_freq = 0;
606 struct vdev_mlme_obj *mlme_obj;
607 struct wlan_lmac_if_reg_tx_ops *tx_ops;
608 bool ap_constraint_change = false, tpe_change = false;
609 bool allow_tpc = false;
610 int8_t regMax = 0, maxTxPower = 0;
611 QDF_STATUS status;
612 bool skip_tpe = false, is_sap_go_switched_ch;
613 enum reg_6g_ap_type pwr_type_6g;
614 uint8_t bpcc;
615 bool cu_flag = true;
616 bool is_power_constraint_abs = false;
617
618 if (mlo_is_mld_sta(session->vdev)) {
619 cu_flag = false;
620 status = lim_get_bpcc_from_mlo_ie(bcn, &bpcc);
621 if (QDF_IS_STATUS_SUCCESS(status))
622 cu_flag = lim_check_cu_happens(session->vdev, bpcc);
623 lim_process_ml_reconfig(mac_ctx, session, rx_pkt_info);
624 }
625
626 if (!cu_flag)
627 return;
628
629 qdf_mem_zero(&beaconParams, sizeof(tUpdateBeaconParams));
630 beaconParams.paramChangeBitmap = 0;
631
632 if (LIM_IS_STA_ROLE(session)) {
633 is_sap_go_switched_ch =
634 wlan_vdev_mlme_is_sap_go_move_before_sta(session->vdev);
635 if (is_sap_go_switched_ch)
636 policy_mgr_sta_sap_dfs_enforce_scc(mac_ctx->psoc,
637 session->vdev_id);
638 if (false == sch_bcn_process_sta(mac_ctx, bcn, rx_pkt_info,
639 session, &beaconParams,
640 &sendProbeReq, pMh))
641 return;
642 }
643
644 /*
645 * For vht session, if opermode ie or vht oper IE is present
646 * bandwidth change will be taken care using these vht IEs.
647 */
648 if (!(session->vhtCapability && (bcn->OperatingMode.present ||
649 bcn->VHTOperation.present)) && session->htCapability &&
650 bcn->HTInfo.present)
651 lim_update_sta_run_time_ht_switch_chnl_params(mac_ctx,
652 &bcn->HTInfo, session);
653
654 if (LIM_IS_STA_ROLE(session))
655 sch_bcn_process_sta_opmode(mac_ctx, bcn, rx_pkt_info, session,
656 &beaconParams, &sendProbeReq, pMh);
657
658 mlme_obj = wlan_vdev_mlme_get_cmpt_obj(session->vdev);
659 if (!mlme_obj) {
660 pe_err("vdev component object is NULL");
661 return;
662 }
663
664 if (!wlan_reg_is_6ghz_chan_freq(bcn->chan_freq)) {
665 skip_tpe = wlan_mlme_skip_tpe(mac_ctx->psoc);
666 } else {
667 if (!bcn->countryInfoParam.countryString[0]) {
668 pe_err("Channel is 6G but country IE not present");
669 return;
670 }
671 if (bcn->he_op.oper_info_6g_present) {
672 session->ap_defined_power_type_6g =
673 bcn->he_op.oper_info_6g.info.reg_info;
674 if (session->ap_defined_power_type_6g < REG_INDOOR_AP ||
675 session->ap_defined_power_type_6g >
676 REG_MAX_SUPP_AP_TYPE) {
677 session->ap_defined_power_type_6g =
678 REG_CURRENT_MAX_AP_TYPE;
679 pe_debug("AP power type is invalid, defaulting to MAX_AP_TYPE");
680 }
681 } else {
682 pe_debug("AP power type is null, defaulting to MAX_AP_TYPE");
683 session->ap_defined_power_type_6g =
684 REG_CURRENT_MAX_AP_TYPE;
685 }
686
687 status = wlan_reg_get_best_6g_power_type(
688 mac_ctx->psoc, mac_ctx->pdev, &pwr_type_6g,
689 session->ap_defined_power_type_6g,
690 bcn->chan_freq);
691 if (QDF_IS_STATUS_ERROR(status))
692 return;
693
694 session->best_6g_power_type = pwr_type_6g;
695 mlme_set_best_6g_power_type(session->vdev, pwr_type_6g);
696 }
697
698 /*
699 * STA LPI + SAP VLP is supported. For this STA should operate in VLP
700 * power level of the SAP.
701 * If STA is operating in VLP power of SAP, do not update STA power.
702 */
703 if (wlan_reg_is_ext_tpc_supported(mac_ctx->psoc) &&
704 !session->sta_follows_sap_power) {
705 tx_ops = wlan_reg_get_tx_ops(mac_ctx->psoc);
706
707 lim_parse_tpe_ie(mac_ctx, session, bcn->transmit_power_env,
708 bcn->num_transmit_power_env, &bcn->he_op,
709 &tpe_change);
710
711 if (mac_ctx->mlme_cfg->sta.allow_tpc_from_ap) {
712 get_local_power_constraint_beacon(
713 bcn, &local_constraint,
714 &is_power_constraint_abs);
715
716 if (mac_ctx->rrm.rrmPEContext.rrmEnable &&
717 bcn->powerConstraintPresent) {
718 local_constraint =
719 bcn->localPowerConstraint.localPowerConstraints;
720 is_power_constraint_abs = false;
721 }
722 allow_tpc = true;
723 }
724
725 if (allow_tpc && local_constraint !=
726 mlme_obj->reg_tpc_obj.ap_constraint_power) {
727 mlme_obj->reg_tpc_obj.ap_constraint_power =
728 local_constraint;
729 mlme_obj->reg_tpc_obj.is_power_constraint_abs =
730 is_power_constraint_abs;
731 ap_constraint_change = true;
732 }
733
734 if (ap_constraint_change || (tpe_change && !skip_tpe)) {
735 lim_calculate_tpc(mac_ctx, session);
736
737 if (tx_ops->set_tpc_power)
738 tx_ops->set_tpc_power(mac_ctx->psoc,
739 session->vdev_id,
740 &mlme_obj->reg_tpc_obj);
741 }
742 } else if (!session->sta_follows_sap_power) {
743 /* Obtain the Max Tx power for the current regulatory */
744 regMax = wlan_reg_get_channel_reg_power_for_freq(
745 mac_ctx->pdev, session->curr_op_freq);
746 local_constraint = regMax;
747
748 if (mac_ctx->mlme_cfg->sta.allow_tpc_from_ap) {
749 get_local_power_constraint_beacon(
750 bcn, &local_constraint,
751 &is_power_constraint_abs);
752
753 if (mac_ctx->rrm.rrmPEContext.rrmEnable &&
754 bcn->powerConstraintPresent) {
755 local_constraint = regMax;
756 local_constraint -=
757 bcn->localPowerConstraint.localPowerConstraints;
758 is_power_constraint_abs = false;
759
760 }
761 }
762 mlme_obj->reg_tpc_obj.is_power_constraint_abs =
763 is_power_constraint_abs;
764 mlme_obj->reg_tpc_obj.reg_max[0] = regMax;
765 mlme_obj->reg_tpc_obj.ap_constraint_power = local_constraint;
766 mlme_obj->reg_tpc_obj.frequency[0] = session->curr_op_freq;
767
768 maxTxPower = lim_get_max_tx_power(mac_ctx, mlme_obj);
769
770 /* If maxTxPower is increased or decreased */
771 if (maxTxPower != session->maxTxPower) {
772 pe_debug("New maxTx power %d, old pwr %d",
773 maxTxPower, session->maxTxPower);
774 pe_debug("regMax %d, local %d", regMax,
775 local_constraint);
776 status = lim_send_set_max_tx_power_req(mac_ctx,
777 maxTxPower,
778 session);
779 if (status == QDF_STATUS_SUCCESS)
780 session->maxTxPower = maxTxPower;
781 }
782 }
783 /* Indicate to LIM that Beacon is received */
784 if (bcn->HTInfo.present) {
785 chan_freq = wlan_reg_legacy_chan_to_freq(mac_ctx->pdev,
786 bcn->HTInfo.primaryChannel);
787 lim_received_hb_handler(mac_ctx, chan_freq, session);
788 } else
789 lim_received_hb_handler(mac_ctx, bcn->chan_freq, session);
790
791 /*
792 * I don't know if any additional IE is required here. Currently, not
793 * include addIE.
794 */
795 if (sendProbeReq)
796 lim_send_probe_req_mgmt_frame(mac_ctx, &session->ssId,
797 session->bssId, session->curr_op_freq,
798 session->self_mac_addr, session->dot11mode, NULL, NULL);
799
800 if ((false == mac_ctx->sap.SapDfsInfo.is_dfs_cac_timer_running)
801 && beaconParams.paramChangeBitmap) {
802 pe_debug("Beacon for session[%d] got changed param change bitmap: 0x%x",
803 session->peSessionId, beaconParams.paramChangeBitmap);
804 lim_send_beacon_params(mac_ctx, &beaconParams, session);
805 }
806
807 if ((session->opmode == QDF_P2P_CLIENT_MODE) &&
808 session->send_p2p_conf_frame) {
809 lim_p2p_oper_chan_change_confirm_action_frame(mac_ctx,
810 session->bssId,
811 session);
812 session->send_p2p_conf_frame = false;
813 }
814
815 lim_process_beacon_eht(mac_ctx, session, bcn);
816 lim_process_bcn_prb_rsp_t2lm(mac_ctx, session, bcn);
817 }
818
819 #ifdef WLAN_FEATURE_11AX_BSS_COLOR
ap_update_bss_color_info(struct mac_context * mac_ctx,struct pe_session * session,uint8_t bss_color)820 static void ap_update_bss_color_info(struct mac_context *mac_ctx,
821 struct pe_session *session,
822 uint8_t bss_color)
823 {
824 if (!session)
825 return;
826
827 if (bss_color < 1 || bss_color > 63) {
828 pe_warn("Invalid BSS color");
829 return;
830 }
831
832 session->bss_color_info[bss_color - 1].seen_count++;
833 session->bss_color_info[bss_color - 1].timestamp =
834 qdf_get_system_timestamp();
835 }
836
ap_get_new_bss_color(struct mac_context * mac_ctx,struct pe_session * session)837 static uint8_t ap_get_new_bss_color(struct mac_context *mac_ctx, struct pe_session *session)
838 {
839 int i;
840 uint8_t new_bss_color;
841 struct bss_color_info color_info;
842 qdf_time_t cur_timestamp;
843
844 if (!session)
845 return 0;
846
847 color_info = session->bss_color_info[0];
848 new_bss_color = 0;
849 cur_timestamp = qdf_get_system_timestamp();
850 for (i = 1; i < MAX_BSS_COLOR_VALUE; i++) {
851 if (session->bss_color_info[i].seen_count == 0) {
852 new_bss_color = i + 1;
853 return new_bss_color;
854 }
855
856 if (color_info.seen_count >
857 session->bss_color_info[i].seen_count &&
858 (cur_timestamp - session->bss_color_info[i].
859 timestamp) > TIME_BEACON_NOT_UPDATED) {
860 color_info = session->bss_color_info[i];
861 new_bss_color = i + 1;
862 }
863 }
864 pe_debug("new bss color: %d", new_bss_color);
865 return new_bss_color;
866 }
867
sch_check_bss_color_ie(struct mac_context * mac_ctx,struct pe_session * ap_session,tSchBeaconStruct * bcn,tUpdateBeaconParams * bcn_prm)868 static void sch_check_bss_color_ie(struct mac_context *mac_ctx,
869 struct pe_session *ap_session,
870 tSchBeaconStruct *bcn,
871 tUpdateBeaconParams *bcn_prm)
872 {
873 /* check bss color in the beacon */
874 if (ap_session->he_op.present && !ap_session->he_op.bss_color) {
875 if (bcn->he_op.present &&
876 (bcn->he_op.bss_color ==
877 ap_session->he_op.bss_color)) {
878 ap_session->he_op.bss_col_disabled = 1;
879 bcn_prm->paramChangeBitmap |=
880 PARAM_BSS_COLOR_CHANGED;
881 ap_session->he_bss_color_change.countdown =
882 BSS_COLOR_SWITCH_COUNTDOWN;
883 ap_session->he_bss_color_change.new_color =
884 ap_get_new_bss_color(mac_ctx,
885 ap_session);
886 ap_session->he_op.bss_color = ap_session->
887 he_bss_color_change.new_color;
888 bcn_prm->bss_color = ap_session->he_op.bss_color;
889 bcn_prm->bss_color_disabled =
890 ap_session->he_op.bss_col_disabled;
891 ap_session->bss_color_changing = 1;
892 } else {
893 /* update info for the bss color */
894 if (bcn->he_op.present)
895 ap_update_bss_color_info(mac_ctx,
896 ap_session,
897 bcn->he_op.bss_color);
898 }
899 }
900 }
901
902 #else
sch_check_bss_color_ie(struct mac_context * mac_ctx,struct pe_session * ap_session,tSchBeaconStruct * bcn,tUpdateBeaconParams * bcn_prm)903 static void sch_check_bss_color_ie(struct mac_context *mac_ctx,
904 struct pe_session *ap_session,
905 tSchBeaconStruct *bcn,
906 tUpdateBeaconParams *bcn_prm)
907 {
908 }
909 #endif
910
sch_beacon_process_for_ap(struct mac_context * mac_ctx,uint8_t session_id,uint8_t * rx_pkt_info,tSchBeaconStruct * bcn)911 void sch_beacon_process_for_ap(struct mac_context *mac_ctx,
912 uint8_t session_id,
913 uint8_t *rx_pkt_info,
914 tSchBeaconStruct *bcn)
915 {
916 struct pe_session *ap_session;
917 tUpdateBeaconParams bcn_prm;
918
919 if (!bcn || !rx_pkt_info) {
920 pe_debug("bcn %pK or rx_pkt_info %pKis NULL",
921 bcn, rx_pkt_info);
922 return;
923 }
924
925 ap_session = pe_find_session_by_session_id(mac_ctx, session_id);
926 if (!ap_session)
927 return;
928
929 if (!LIM_IS_AP_ROLE(ap_session))
930 return;
931
932 qdf_mem_zero(&bcn_prm, sizeof(tUpdateBeaconParams));
933 bcn_prm.paramChangeBitmap = 0;
934
935 bcn_prm.bss_idx = ap_session->vdev_id;
936
937 if (!ap_session->is_session_obss_color_collision_det_enabled)
938 sch_check_bss_color_ie(mac_ctx, ap_session,
939 bcn, &bcn_prm);
940
941 if ((ap_session->gLimProtectionControl !=
942 MLME_FORCE_POLICY_PROTECTION_DISABLE) &&
943 !ap_session->is_session_obss_offload_enabled)
944 ap_beacon_process(mac_ctx, rx_pkt_info,
945 bcn, &bcn_prm, ap_session);
946
947 if ((false == mac_ctx->sap.SapDfsInfo.is_dfs_cac_timer_running)
948 && bcn_prm.paramChangeBitmap) {
949 /* Update the bcn and apply the new settings to HAL */
950 sch_set_fixed_beacon_fields(mac_ctx, ap_session);
951 pe_debug("Beacon for PE session[%d] got changed",
952 ap_session->peSessionId);
953 pe_debug("sending beacon param change bitmap: 0x%x",
954 bcn_prm.paramChangeBitmap);
955 lim_send_beacon_params(mac_ctx, &bcn_prm, ap_session);
956 }
957 }
958
959 #ifdef WLAN_BCN_RECV_FEATURE
960 /*
961 * sch_send_beacon_report() - To Fill beacon report for
962 * each beacon coming from connected peer and sends it
963 * to upper layer
964 * @mac_ctx: Mac context
965 * @beacon_struct: Pointing to beacon structure
966 * @session: pointer to the PE session
967 *
968 * Return: None
969 */
970 static
sch_send_beacon_report(struct mac_context * mac_ctx,struct sSirProbeRespBeacon * beacon_struct,struct pe_session * session)971 void sch_send_beacon_report(struct mac_context *mac_ctx,
972 struct sSirProbeRespBeacon *beacon_struct,
973 struct pe_session *session)
974 {
975 struct wlan_beacon_report beacon_report;
976 beacon_report_cb sme_bcn_cb;
977
978 sme_bcn_cb = mac_ctx->lim.sme_bcn_rcv_callback;
979 if (!sme_bcn_cb)
980 return;
981
982 if (!LIM_IS_STA_ROLE(session))
983 return;
984
985 if (sir_compare_mac_addr(session->bssId, beacon_struct->bssid)) {
986 /* Prepare beacon report from incoming beacon */
987 qdf_mem_copy(beacon_report.bssid.bytes, beacon_struct->bssid,
988 sizeof(tSirMacAddr));
989
990 qdf_mem_copy(&beacon_report.time_stamp,
991 &beacon_struct->timeStamp, sizeof(qdf_time_t));
992 beacon_report.beacon_interval = beacon_struct->beaconInterval;
993 beacon_report.frequency = beacon_struct->chan_freq;
994
995 beacon_report.ssid.length = beacon_struct->ssId.length;
996 qdf_mem_copy(&beacon_report.ssid.ssid,
997 &beacon_struct->ssId.ssId,
998 beacon_report.ssid.length);
999
1000 beacon_report.boot_time =
1001 qdf_do_div(qdf_get_monotonic_boottime(),
1002 QDF_MC_TIMER_TO_MS_UNIT);
1003
1004 beacon_report.vdev_id = session->vdev_id;
1005
1006 /* Send report to upper layer */
1007 sme_bcn_cb(mac_ctx->hdd_handle, &beacon_report);
1008 }
1009 }
1010
1011 #else
1012 static inline
sch_send_beacon_report(struct mac_context * mac_ctx,struct sSirProbeRespBeacon * beacon_struct,struct pe_session * session)1013 void sch_send_beacon_report(struct mac_context *mac_ctx,
1014 struct sSirProbeRespBeacon *beacon_struct,
1015 struct pe_session *session)
1016 {
1017 }
1018 #endif
1019
1020 /**
1021 * sch_beacon_process() - process the beacon frame
1022 * @mac_ctx: mac global context
1023 * @rx_pkt_info: pointer to buffer descriptor
1024 * @session: pointer to the PE session
1025 *
1026 * Return: None
1027 */
1028 void
sch_beacon_process(struct mac_context * mac_ctx,uint8_t * rx_pkt_info,struct pe_session * session)1029 sch_beacon_process(struct mac_context *mac_ctx, uint8_t *rx_pkt_info,
1030 struct pe_session *session)
1031 {
1032 static tSchBeaconStruct bcn;
1033
1034 if (!session)
1035 return;
1036
1037 /*
1038 * Drop the beacon/probe response from current connected AP in
1039 * below cases to avoid responding to the changes in beacon(e.g. doing
1040 * VDEV_RESTART to update to the latest capabilities),
1041 * 1. vdev is not in connected state: vdev might be transitioning
1042 * 2. Link switch is in progress: Current link or one of the partner
1043 * links are getting replaced.
1044 *
1045 * New beacons/probe rsps can be considered once post these operations.
1046 */
1047 if (LIM_IS_STA_ROLE(session) &&
1048 (!wlan_cm_is_vdev_connected(session->vdev) ||
1049 mlo_mgr_is_link_switch_in_progress(session->vdev))) {
1050 pe_debug_rl("vdev %d, drop beacon", session->vdev_id);
1051 return;
1052 }
1053
1054 /* Convert the beacon frame into a structure */
1055 if (sir_convert_beacon_frame2_struct(mac_ctx, (uint8_t *) rx_pkt_info,
1056 &bcn) != QDF_STATUS_SUCCESS) {
1057 pe_err_rl("beacon parsing failed");
1058 return;
1059 }
1060
1061 session->dtimPeriod = bcn.tim.dtimPeriod;
1062
1063 sch_send_beacon_report(mac_ctx, &bcn, session);
1064 __sch_beacon_process_for_session(mac_ctx, &bcn, rx_pkt_info, session);
1065 }
1066
1067 /**
1068 * sch_beacon_edca_process(): Process the EDCA parameter set in the received
1069 * beacon frame
1070 *
1071 * @mac_ctx: mac global context
1072 * @edca: reference to edca parameters in beacon struct
1073 * @session : pesession entry
1074 *
1075 * @return status of operation
1076 */
1077 QDF_STATUS
sch_beacon_edca_process(struct mac_context * mac,tSirMacEdcaParamSetIE * edca,struct pe_session * session)1078 sch_beacon_edca_process(struct mac_context *mac, tSirMacEdcaParamSetIE *edca,
1079 struct pe_session *session)
1080 {
1081 bool follow_ap_edca;
1082 #ifdef FEATURE_WLAN_DIAG_SUPPORT
1083 host_log_qos_edca_pkt_type *log_ptr = NULL;
1084 #endif /* FEATURE_WLAN_DIAG_SUPPORT */
1085
1086 if (!(mac->mlme_cfg)) {
1087 pe_err("invalid mlme cfg");
1088 return QDF_STATUS_E_FAILURE;
1089 }
1090
1091 follow_ap_edca = mlme_get_follow_ap_edca_flag(session->vdev);
1092
1093 session->gLimEdcaParamSetCount = edca->qosInfo.count;
1094 session->gLimEdcaParams[QCA_WLAN_AC_BE] = edca->acbe;
1095 session->gLimEdcaParams[QCA_WLAN_AC_BK] = edca->acbk;
1096 session->gLimEdcaParams[QCA_WLAN_AC_VI] = edca->acvi;
1097 session->gLimEdcaParams[QCA_WLAN_AC_VO] = edca->acvo;
1098
1099 if (mac->mlme_cfg->edca_params.enable_edca_params && !follow_ap_edca) {
1100 session->gLimEdcaParams[QCA_WLAN_AC_VO].aci.aifsn =
1101 mac->mlme_cfg->edca_params.edca_ac_vo.vo_aifs;
1102 session->gLimEdcaParams[QCA_WLAN_AC_VI].aci.aifsn =
1103 mac->mlme_cfg->edca_params.edca_ac_vi.vi_aifs;
1104 session->gLimEdcaParams[QCA_WLAN_AC_BK].aci.aifsn =
1105 mac->mlme_cfg->edca_params.edca_ac_bk.bk_aifs;
1106 session->gLimEdcaParams[QCA_WLAN_AC_BE].aci.aifsn =
1107 mac->mlme_cfg->edca_params.edca_ac_be.be_aifs;
1108
1109 session->gLimEdcaParams[QCA_WLAN_AC_VO].cw.min =
1110 mac->mlme_cfg->edca_params.edca_ac_vo.vo_cwmin;
1111 session->gLimEdcaParams[QCA_WLAN_AC_VI].cw.min =
1112 mac->mlme_cfg->edca_params.edca_ac_vi.vi_cwmin;
1113 session->gLimEdcaParams[QCA_WLAN_AC_BK].cw.min =
1114 mac->mlme_cfg->edca_params.edca_ac_bk.bk_cwmin;
1115 session->gLimEdcaParams[QCA_WLAN_AC_BE].cw.min =
1116 mac->mlme_cfg->edca_params.edca_ac_be.be_cwmin;
1117
1118 session->gLimEdcaParams[QCA_WLAN_AC_VO].cw.max =
1119 mac->mlme_cfg->edca_params.edca_ac_vo.vo_cwmax;
1120 session->gLimEdcaParams[QCA_WLAN_AC_VI].cw.max =
1121 mac->mlme_cfg->edca_params.edca_ac_vi.vi_cwmax;
1122 session->gLimEdcaParams[QCA_WLAN_AC_BK].cw.max =
1123 mac->mlme_cfg->edca_params.edca_ac_bk.bk_cwmax;
1124 session->gLimEdcaParams[QCA_WLAN_AC_BE].cw.max =
1125 mac->mlme_cfg->edca_params.edca_ac_be.be_cwmax;
1126 }
1127 #ifdef FEATURE_WLAN_DIAG_SUPPORT
1128 WLAN_HOST_DIAG_LOG_ALLOC(log_ptr, host_log_qos_edca_pkt_type,
1129 LOG_WLAN_QOS_EDCA_C);
1130 if (log_ptr) {
1131 log_ptr->aci_be = session->gLimEdcaParams[QCA_WLAN_AC_BE].aci.aci;
1132 log_ptr->cw_be =
1133 session->gLimEdcaParams[QCA_WLAN_AC_BE].cw.max << 4
1134 | session->gLimEdcaParams[QCA_WLAN_AC_BE].cw.min;
1135 log_ptr->txoplimit_be =
1136 session->gLimEdcaParams[QCA_WLAN_AC_BE].txoplimit;
1137 log_ptr->aci_bk =
1138 session->gLimEdcaParams[QCA_WLAN_AC_BK].aci.aci;
1139 log_ptr->cw_bk =
1140 session->gLimEdcaParams[QCA_WLAN_AC_BK].cw.max << 4
1141 | session->gLimEdcaParams[QCA_WLAN_AC_BK].cw.min;
1142 log_ptr->txoplimit_bk =
1143 session->gLimEdcaParams[QCA_WLAN_AC_BK].txoplimit;
1144 log_ptr->aci_vi =
1145 session->gLimEdcaParams[QCA_WLAN_AC_VI].aci.aci;
1146 log_ptr->cw_vi =
1147 session->gLimEdcaParams[QCA_WLAN_AC_VI].cw.max << 4
1148 | session->gLimEdcaParams[QCA_WLAN_AC_VI].cw.min;
1149 log_ptr->txoplimit_vi =
1150 session->gLimEdcaParams[QCA_WLAN_AC_VI].txoplimit;
1151 log_ptr->aci_vo =
1152 session->gLimEdcaParams[QCA_WLAN_AC_VO].aci.aci;
1153 log_ptr->cw_vo =
1154 session->gLimEdcaParams[QCA_WLAN_AC_VO].cw.max << 4
1155 | session->gLimEdcaParams[QCA_WLAN_AC_VO].cw.min;
1156 log_ptr->txoplimit_vo =
1157 session->gLimEdcaParams[QCA_WLAN_AC_VO].txoplimit;
1158 }
1159 WLAN_HOST_DIAG_LOG_REPORT(log_ptr);
1160 #endif /* FEATURE_WLAN_DIAG_SUPPORT */
1161 pe_debug("Edca param enabled %d. Updating Local Params to: AC_BE: AIFSN: %d, ACM %d, CWmin %d, CWmax %d, TxOp %d AC_BK: AIFSN: %d, ACM %d, CWmin %d, CWmax %d, TxOp %d AC_VI: AIFSN: %d, ACM %d, CWmin %d, CWmax %d, TxOp %d AC_VO: AIFSN: %d, ACM %d, CWmin %d, CWmax %d, TxOp %d",
1162 mac->mlme_cfg->edca_params.enable_edca_params,
1163 session->gLimEdcaParams[0].aci.aifsn,
1164 session->gLimEdcaParams[0].aci.acm,
1165 session->gLimEdcaParams[0].cw.min,
1166 session->gLimEdcaParams[0].cw.max,
1167 session->gLimEdcaParams[0].txoplimit,
1168 session->gLimEdcaParams[1].aci.aifsn,
1169 session->gLimEdcaParams[1].aci.acm,
1170 session->gLimEdcaParams[1].cw.min,
1171 session->gLimEdcaParams[1].cw.max,
1172 session->gLimEdcaParams[1].txoplimit,
1173 session->gLimEdcaParams[2].aci.aifsn,
1174 session->gLimEdcaParams[2].aci.acm,
1175 session->gLimEdcaParams[2].cw.min,
1176 session->gLimEdcaParams[2].cw.max,
1177 session->gLimEdcaParams[2].txoplimit,
1178 session->gLimEdcaParams[3].aci.aifsn,
1179 session->gLimEdcaParams[3].aci.acm,
1180 session->gLimEdcaParams[3].cw.min,
1181 session->gLimEdcaParams[3].cw.max,
1182 session->gLimEdcaParams[3].txoplimit);
1183
1184 return QDF_STATUS_SUCCESS;
1185 }
1186
lim_enable_obss_detection_config(struct mac_context * mac_ctx,struct pe_session * session)1187 void lim_enable_obss_detection_config(struct mac_context *mac_ctx,
1188 struct pe_session *session)
1189 {
1190 QDF_STATUS status = QDF_STATUS_SUCCESS;
1191
1192 if (!session) {
1193 pe_err("Invalid session, protection not enabled");
1194 return;
1195 }
1196
1197 if (session->gLimProtectionControl ==
1198 MLME_FORCE_POLICY_PROTECTION_DISABLE) {
1199 pe_err("protectiond disabled, force policy, session %d",
1200 session->smeSessionId);
1201 return;
1202 }
1203
1204 if (mac_ctx->mlme_cfg->obss_ht40.obss_detection_offload_enabled) {
1205 status = lim_obss_send_detection_cfg(mac_ctx, session, true);
1206 if (QDF_IS_STATUS_ERROR(status)) {
1207 pe_err("vdev %d: offload enable failed, trying legacy",
1208 session->smeSessionId);
1209 session->is_session_obss_offload_enabled = false;
1210 } else {
1211 pe_debug("vdev %d: offload detection enabled",
1212 session->smeSessionId);
1213 session->is_session_obss_offload_enabled = true;
1214 lim_obss_send_detection_cfg(mac_ctx, session, true);
1215 }
1216 }
1217
1218 if (!mac_ctx->mlme_cfg->obss_ht40.obss_detection_offload_enabled ||
1219 QDF_IS_STATUS_ERROR(status)) {
1220 status = qdf_mc_timer_start(&session->
1221 protection_fields_reset_timer,
1222 SCH_PROTECTION_RESET_TIME);
1223 if (QDF_IS_STATUS_ERROR(status))
1224 pe_err("vdev %d: start timer failed",
1225 session->smeSessionId);
1226 else
1227 pe_debug("vdev %d: legacy detection enabled",
1228 session->smeSessionId);
1229 }
1230 }
1231
lim_obss_generate_detection_config(struct mac_context * mac_ctx,struct pe_session * session,struct obss_detection_cfg * cfg)1232 QDF_STATUS lim_obss_generate_detection_config(struct mac_context *mac_ctx,
1233 struct pe_session *session,
1234 struct obss_detection_cfg *cfg)
1235 {
1236 uint32_t phy_mode;
1237 enum reg_wifi_band rf_band = REG_BAND_UNKNOWN;
1238 struct obss_detection_cfg *cur_detect;
1239
1240 if (!mac_ctx || !session || !cfg) {
1241 pe_err("Invalid params mac_ctx %pK, session %pK, cfg %pK",
1242 mac_ctx, session, cfg);
1243 return QDF_STATUS_E_INVAL;
1244 }
1245
1246 lim_get_phy_mode(mac_ctx, &phy_mode, session);
1247 rf_band = session->limRFBand;
1248 qdf_mem_zero(cfg, sizeof(*cfg));
1249 cur_detect = &session->current_obss_detection;
1250
1251 pe_debug("band:%d, phy_mode:%d, ht_cap:%d, ht_oper_mode:%d",
1252 rf_band, phy_mode, session->htCapability,
1253 mac_ctx->lim.gHTOperMode);
1254 pe_debug("assoc_sta: 11b:%d, 11g:%d, 11a:%d, ht20:%d",
1255 session->gLim11bParams.protectionEnabled,
1256 session->gLim11gParams.protectionEnabled,
1257 session->gLim11aParams.protectionEnabled,
1258 session->gLimHt20Params.protectionEnabled);
1259 pe_debug("obss: 11b:%d, 11g:%d, 11a:%d, ht20:%d",
1260 session->gLimOlbcParams.protectionEnabled,
1261 session->gLimOverlap11gParams.protectionEnabled,
1262 session->gLimOverlap11aParams.protectionEnabled,
1263 session->gLimOverlapHt20Params.protectionEnabled);
1264 pe_debug("detect: b_ap:%d, b_s:%d, g:%d, a:%d, htl:%d, htm:%d, ht20:%d",
1265 cur_detect->obss_11b_ap_detect_mode,
1266 cur_detect->obss_11b_sta_detect_mode,
1267 cur_detect->obss_11g_ap_detect_mode,
1268 cur_detect->obss_11a_detect_mode,
1269 cur_detect->obss_ht_legacy_detect_mode,
1270 cur_detect->obss_ht_mixed_detect_mode,
1271 cur_detect->obss_ht_20mhz_detect_mode);
1272
1273 if (rf_band == REG_BAND_2G) {
1274 if ((phy_mode == WNI_CFG_PHY_MODE_11G ||
1275 session->htCapability) &&
1276 !session->gLim11bParams.protectionEnabled) {
1277 if (!session->gLimOlbcParams.protectionEnabled &&
1278 !session->gLimOverlap11gParams.protectionEnabled) {
1279 cfg->obss_11b_ap_detect_mode =
1280 OBSS_OFFLOAD_DETECTION_PRESENT;
1281 cfg->obss_11b_sta_detect_mode =
1282 OBSS_OFFLOAD_DETECTION_PRESENT;
1283 } else {
1284 if (cur_detect->obss_11b_ap_detect_mode ==
1285 OBSS_OFFLOAD_DETECTION_PRESENT)
1286 cfg->obss_11b_ap_detect_mode =
1287 OBSS_OFFLOAD_DETECTION_ABSENT;
1288 if (cur_detect->obss_11b_sta_detect_mode ==
1289 OBSS_OFFLOAD_DETECTION_PRESENT)
1290 cfg->obss_11b_sta_detect_mode =
1291 OBSS_OFFLOAD_DETECTION_ABSENT;
1292 }
1293 } else if (session->gLim11bParams.protectionEnabled) {
1294 session->gLimOlbcParams.protectionEnabled = false;
1295 }
1296
1297 if (session->htCapability &&
1298 session->cfgProtection.overlapFromllg &&
1299 !session->gLim11gParams.protectionEnabled) {
1300 if (!session->gLimOverlap11gParams.protectionEnabled) {
1301 cfg->obss_11g_ap_detect_mode =
1302 OBSS_OFFLOAD_DETECTION_PRESENT;
1303 cfg->obss_ht_legacy_detect_mode =
1304 OBSS_OFFLOAD_DETECTION_PRESENT;
1305 cfg->obss_ht_mixed_detect_mode =
1306 OBSS_OFFLOAD_DETECTION_PRESENT;
1307 } else {
1308 if (cur_detect->obss_11g_ap_detect_mode ==
1309 OBSS_OFFLOAD_DETECTION_PRESENT)
1310 cfg->obss_11g_ap_detect_mode =
1311 OBSS_OFFLOAD_DETECTION_ABSENT;
1312 if (cur_detect->obss_ht_legacy_detect_mode ==
1313 OBSS_OFFLOAD_DETECTION_PRESENT)
1314 cfg->obss_ht_legacy_detect_mode =
1315 OBSS_OFFLOAD_DETECTION_ABSENT;
1316 if (cur_detect->obss_ht_mixed_detect_mode ==
1317 OBSS_OFFLOAD_DETECTION_PRESENT)
1318 cfg->obss_ht_mixed_detect_mode =
1319 OBSS_OFFLOAD_DETECTION_ABSENT;
1320 }
1321 } else if (session->gLim11gParams.protectionEnabled) {
1322 session->gLimOverlap11gParams.protectionEnabled = false;
1323 }
1324
1325 /* INI related settings */
1326 if (mac_ctx->mlme_cfg->sta.ignore_peer_erp_info)
1327 cfg->obss_11b_sta_detect_mode =
1328 OBSS_OFFLOAD_DETECTION_DISABLED;
1329
1330 if (mac_ctx->mlme_cfg->sap_protection_cfg.ignore_peer_ht_opmode)
1331 cfg->obss_ht_legacy_detect_mode =
1332 OBSS_OFFLOAD_DETECTION_DISABLED;
1333 }
1334
1335 if ((rf_band == REG_BAND_5G) && session->htCapability) {
1336 if (!session->gLim11aParams.protectionEnabled) {
1337 if (!session->gLimOverlap11aParams.protectionEnabled)
1338 cfg->obss_11a_detect_mode =
1339 OBSS_OFFLOAD_DETECTION_PRESENT;
1340 else if (cur_detect->obss_11a_detect_mode ==
1341 OBSS_OFFLOAD_DETECTION_PRESENT)
1342 cfg->obss_11a_detect_mode =
1343 OBSS_OFFLOAD_DETECTION_ABSENT;
1344 } else {
1345 session->gLimOverlap11aParams.protectionEnabled = false;
1346 }
1347 }
1348
1349 if (((rf_band == REG_BAND_2G) || (rf_band == REG_BAND_5G)) &&
1350 session->htCapability) {
1351
1352 if (!session->gLimHt20Params.protectionEnabled) {
1353 if (!session->gLimOverlapHt20Params.protectionEnabled) {
1354 cfg->obss_ht_20mhz_detect_mode =
1355 OBSS_OFFLOAD_DETECTION_PRESENT;
1356 } else if (cur_detect->obss_ht_20mhz_detect_mode ==
1357 OBSS_OFFLOAD_DETECTION_PRESENT) {
1358 cfg->obss_ht_20mhz_detect_mode =
1359 OBSS_OFFLOAD_DETECTION_ABSENT;
1360 }
1361 } else {
1362 session->gLimOverlapHt20Params.protectionEnabled =
1363 false;
1364 }
1365 }
1366
1367 pe_debug("b_ap:%d, b_s:%d, g:%d, a:%d, ht_le:%d, ht_m:%d, ht_20:%d",
1368 cfg->obss_11b_ap_detect_mode,
1369 cfg->obss_11b_sta_detect_mode,
1370 cfg->obss_11g_ap_detect_mode,
1371 cfg->obss_11a_detect_mode,
1372 cfg->obss_ht_legacy_detect_mode,
1373 cfg->obss_ht_mixed_detect_mode,
1374 cfg->obss_ht_20mhz_detect_mode);
1375
1376 return QDF_STATUS_SUCCESS;
1377 }
1378
lim_obss_send_detection_cfg(struct mac_context * mac_ctx,struct pe_session * session,bool force)1379 QDF_STATUS lim_obss_send_detection_cfg(struct mac_context *mac_ctx,
1380 struct pe_session *session, bool force)
1381 {
1382 QDF_STATUS status;
1383 struct obss_detection_cfg obss_cfg;
1384 struct wmi_obss_detection_cfg_param *req_param;
1385
1386 if (!session) {
1387 pe_err("Invalid session");
1388 return QDF_STATUS_E_INVAL;
1389 }
1390
1391 if (!session->is_session_obss_offload_enabled) {
1392 pe_debug("obss offload protectiond disabled, session %d",
1393 session->smeSessionId);
1394 /* Send success */
1395 return QDF_STATUS_SUCCESS;
1396 }
1397
1398 if (session->gLimProtectionControl ==
1399 MLME_FORCE_POLICY_PROTECTION_DISABLE) {
1400 pe_debug("protectiond disabled, force from policy, session %d",
1401 session->smeSessionId);
1402 /* Send success */
1403 return QDF_STATUS_SUCCESS;
1404 }
1405
1406 status = lim_obss_generate_detection_config(mac_ctx,
1407 session,
1408 &obss_cfg);
1409 if (QDF_IS_STATUS_ERROR(status)) {
1410 pe_err("Failed to generate obss detection cfg, session %d",
1411 session->smeSessionId);
1412 return status;
1413 }
1414
1415 if (qdf_mem_cmp(&session->obss_offload_cfg, &obss_cfg, sizeof(obss_cfg))
1416 || force) {
1417 struct scheduler_msg msg = {0};
1418 req_param = qdf_mem_malloc(sizeof(*req_param));
1419 if (!req_param)
1420 return QDF_STATUS_E_NOMEM;
1421 qdf_mem_copy(&session->obss_offload_cfg, &obss_cfg,
1422 sizeof(obss_cfg));
1423 req_param->vdev_id = session->smeSessionId;
1424 req_param->obss_detect_period_ms = OBSS_DETECTION_PERIOD_MS;
1425 req_param->obss_11b_ap_detect_mode =
1426 obss_cfg.obss_11b_ap_detect_mode;
1427 req_param->obss_11b_sta_detect_mode =
1428 obss_cfg.obss_11b_sta_detect_mode;
1429 req_param->obss_11g_ap_detect_mode =
1430 obss_cfg.obss_11g_ap_detect_mode;
1431 req_param->obss_11a_detect_mode =
1432 obss_cfg.obss_11a_detect_mode;
1433 req_param->obss_ht_legacy_detect_mode =
1434 obss_cfg.obss_ht_legacy_detect_mode;
1435 req_param->obss_ht_20mhz_detect_mode =
1436 obss_cfg.obss_ht_20mhz_detect_mode;
1437 req_param->obss_ht_mixed_detect_mode =
1438 obss_cfg.obss_ht_mixed_detect_mode;
1439
1440 msg.type = WMA_OBSS_DETECTION_REQ;
1441 msg.bodyptr = req_param;
1442 msg.reserved = 0;
1443 status = scheduler_post_message(QDF_MODULE_ID_PE,
1444 QDF_MODULE_ID_WMA,
1445 QDF_MODULE_ID_WMA, &msg);
1446 if (QDF_IS_STATUS_ERROR(status)) {
1447 qdf_mem_free(req_param);
1448 return status;
1449 }
1450 } else {
1451 pe_debug("Skipping WMA_OBSS_DETECTION_REQ, force = %d", force);
1452 }
1453
1454 return status;
1455 }
1456
lim_process_obss_detection_ind(struct mac_context * mac_ctx,struct wmi_obss_detect_info * obss_detection)1457 QDF_STATUS lim_process_obss_detection_ind(struct mac_context *mac_ctx,
1458 struct wmi_obss_detect_info
1459 *obss_detection)
1460 {
1461 QDF_STATUS status;
1462 uint32_t detect_masks;
1463 uint32_t reason;
1464 struct obss_detection_cfg *obss_cfg;
1465 bool enable;
1466 struct pe_session *session;
1467 tUpdateBeaconParams bcn_prm;
1468 enum reg_wifi_band rf_band = REG_BAND_UNKNOWN;
1469 struct obss_detection_cfg *cur_detect;
1470
1471 pe_debug("obss detect ind id %d, reason %d, msk 0x%x, " QDF_MAC_ADDR_FMT,
1472 obss_detection->vdev_id, obss_detection->reason,
1473 obss_detection->matched_detection_masks,
1474 QDF_MAC_ADDR_REF(obss_detection->matched_bssid_addr));
1475
1476 session = pe_find_session_by_vdev_id(mac_ctx, obss_detection->vdev_id);
1477 if (!session) {
1478 pe_err("Failed to get session for id %d",
1479 obss_detection->vdev_id);
1480 return QDF_STATUS_E_INVAL;
1481 }
1482
1483 if (!LIM_IS_AP_ROLE(session)) {
1484 pe_err("session %d is not AP", obss_detection->vdev_id);
1485 return QDF_STATUS_E_INVAL;
1486 }
1487
1488 if (!session->is_session_obss_offload_enabled) {
1489 pe_err("Offload already disabled for session %d",
1490 obss_detection->vdev_id);
1491 return QDF_STATUS_SUCCESS;
1492 }
1493
1494 reason = obss_detection->reason;
1495 detect_masks = obss_detection->matched_detection_masks;
1496
1497 if (reason == OBSS_OFFLOAD_DETECTION_PRESENT) {
1498 enable = true;
1499 } else if (reason == OBSS_OFFLOAD_DETECTION_ABSENT) {
1500 enable = false;
1501 } else if (reason == OBSS_OFFLOAD_DETECTION_DISABLED) {
1502 /*
1503 * Most common reason for this event-type from firmware
1504 * is insufficient memory.
1505 * Disable offload OBSS detection and enable legacy-way
1506 * of detecting OBSS by parsing beacons.
1507 **/
1508 session->is_session_obss_offload_enabled = false;
1509 pe_err("FW indicated obss offload disabled");
1510 pe_err("Enabling host based detection, session %d",
1511 obss_detection->vdev_id);
1512
1513 status = qdf_mc_timer_start(&session->
1514 protection_fields_reset_timer,
1515 SCH_PROTECTION_RESET_TIME);
1516 if (QDF_IS_STATUS_ERROR(status))
1517 pe_err("cannot start protection reset timer");
1518
1519 return QDF_STATUS_SUCCESS;
1520 } else {
1521 pe_err("Invalid reason %d, session %d",
1522 obss_detection->reason,
1523 obss_detection->vdev_id);
1524 return QDF_STATUS_E_INVAL;
1525 }
1526
1527 rf_band = session->limRFBand;
1528 qdf_mem_zero(&bcn_prm, sizeof(bcn_prm));
1529 obss_cfg = &session->obss_offload_cfg;
1530 cur_detect = &session->current_obss_detection;
1531
1532 if (OBSS_DETECTION_IS_11B_AP(detect_masks)) {
1533 if (reason != obss_cfg->obss_11b_ap_detect_mode ||
1534 rf_band != REG_BAND_2G)
1535 goto wrong_detection;
1536
1537 lim_enable11g_protection(mac_ctx, enable, true,
1538 &bcn_prm, session);
1539 cur_detect->obss_11b_ap_detect_mode = reason;
1540 }
1541 if (OBSS_DETECTION_IS_11B_STA(detect_masks)) {
1542 if (reason != obss_cfg->obss_11b_sta_detect_mode ||
1543 rf_band != REG_BAND_2G)
1544 goto wrong_detection;
1545
1546 lim_enable11g_protection(mac_ctx, enable, true,
1547 &bcn_prm, session);
1548 cur_detect->obss_11b_sta_detect_mode = reason;
1549 }
1550 if (OBSS_DETECTION_IS_11G_AP(detect_masks)) {
1551 if (reason != obss_cfg->obss_11g_ap_detect_mode ||
1552 rf_band != REG_BAND_2G)
1553 goto wrong_detection;
1554
1555 lim_enable_ht_protection_from11g(mac_ctx, enable, true,
1556 &bcn_prm, session);
1557 cur_detect->obss_11g_ap_detect_mode = reason;
1558 }
1559 if (OBSS_DETECTION_IS_11A(detect_masks)) {
1560 if (reason != obss_cfg->obss_11a_detect_mode ||
1561 rf_band != REG_BAND_5G)
1562 goto wrong_detection;
1563
1564 lim_update_11a_protection(mac_ctx, enable, true,
1565 &bcn_prm, session);
1566 cur_detect->obss_11a_detect_mode = reason;
1567 }
1568 if (OBSS_DETECTION_IS_HT_LEGACY(detect_masks)) {
1569 /* for 5GHz, we have only 11a detection, which covers legacy */
1570 if (reason != obss_cfg->obss_ht_legacy_detect_mode ||
1571 rf_band != REG_BAND_2G)
1572 goto wrong_detection;
1573
1574 lim_enable_ht_protection_from11g(mac_ctx, enable, true,
1575 &bcn_prm, session);
1576 cur_detect->obss_ht_legacy_detect_mode = reason;
1577 }
1578 if (OBSS_DETECTION_IS_HT_MIXED(detect_masks)) {
1579 /* for 5GHz, we have only 11a detection, which covers ht mix */
1580 if (reason != obss_cfg->obss_ht_mixed_detect_mode ||
1581 rf_band != REG_BAND_2G)
1582 goto wrong_detection;
1583
1584 lim_enable_ht_protection_from11g(mac_ctx, enable, true,
1585 &bcn_prm, session);
1586 cur_detect->obss_ht_mixed_detect_mode = reason;
1587 }
1588 if (OBSS_DETECTION_IS_HT_20MHZ(detect_masks)) {
1589 if (reason != obss_cfg->obss_ht_20mhz_detect_mode)
1590 goto wrong_detection;
1591
1592 lim_enable_ht20_protection(mac_ctx, enable, true,
1593 &bcn_prm, session);
1594 cur_detect->obss_ht_20mhz_detect_mode = reason;
1595 }
1596
1597 if ((false == mac_ctx->sap.SapDfsInfo.is_dfs_cac_timer_running) &&
1598 bcn_prm.paramChangeBitmap) {
1599 /* Update the bcn and apply the new settings to HAL */
1600 sch_set_fixed_beacon_fields(mac_ctx, session);
1601 pe_debug("Beacon for PE session: %d got changed: 0x%x",
1602 session->smeSessionId, bcn_prm.paramChangeBitmap);
1603 if (!QDF_IS_STATUS_SUCCESS(lim_send_beacon_params(
1604 mac_ctx, &bcn_prm, session))) {
1605 pe_err("Failed to send beacon param, session %d",
1606 obss_detection->vdev_id);
1607 return QDF_STATUS_E_FAULT;
1608 }
1609 }
1610
1611 status = lim_obss_send_detection_cfg(mac_ctx, session, true);
1612 if (QDF_IS_STATUS_ERROR(status)) {
1613 pe_err("Failed to send obss detection cfg, session %d",
1614 obss_detection->vdev_id);
1615 return status;
1616 }
1617
1618 return QDF_STATUS_SUCCESS;
1619
1620 wrong_detection:
1621 /*
1622 * We may get this wrong detection before FW can update latest cfg,
1623 * So keeping log level debug
1624 **/
1625 pe_debug("Wrong detection, session %d", obss_detection->vdev_id);
1626
1627 return QDF_STATUS_E_INVAL;
1628 }
1629