1 /* 2 * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2021-2023 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 * DOC: Defines scan utility functions 22 */ 23 24 #include <wlan_cmn.h> 25 #include <wlan_scan_ucfg_api.h> 26 #include <wlan_scan_utils_api.h> 27 #include <../../core/src/wlan_scan_cache_db.h> 28 #include <../../core/src/wlan_scan_main.h> 29 #include <wlan_reg_services_api.h> 30 #if defined(WLAN_SAE_SINGLE_PMK) && defined(WLAN_FEATURE_ROAM_OFFLOAD) 31 #include <wlan_mlme_api.h> 32 #endif 33 #ifdef WLAN_FEATURE_11BE_MLO 34 #include <wlan_utility.h> 35 #include "wlan_mlo_mgr_public_structs.h" 36 #include <utils_mlo.h> 37 #endif 38 #include "wlan_psoc_mlme_api.h" 39 #include "reg_services_public_struct.h" 40 41 #define MAX_IE_LEN 1024 42 #define SHORT_SSID_LEN 4 43 #define NEIGHBOR_AP_LEN 1 44 #define BSS_PARAMS_LEN 1 45 46 const char* 47 util_scan_get_ev_type_name(enum scan_event_type type) 48 { 49 static const char * const event_name[] = { 50 [SCAN_EVENT_TYPE_STARTED] = "STARTED", 51 [SCAN_EVENT_TYPE_COMPLETED] = "COMPLETED", 52 [SCAN_EVENT_TYPE_BSS_CHANNEL] = "HOME_CHANNEL", 53 [SCAN_EVENT_TYPE_FOREIGN_CHANNEL] = "FOREIGN_CHANNEL", 54 [SCAN_EVENT_TYPE_DEQUEUED] = "DEQUEUED", 55 [SCAN_EVENT_TYPE_PREEMPTED] = "PREEMPTED", 56 [SCAN_EVENT_TYPE_START_FAILED] = "START_FAILED", 57 [SCAN_EVENT_TYPE_RESTARTED] = "RESTARTED", 58 [SCAN_EVENT_TYPE_FOREIGN_CHANNEL_EXIT] = "FOREIGN_CHANNEL_EXIT", 59 [SCAN_EVENT_TYPE_SUSPENDED] = "SUSPENDED", 60 [SCAN_EVENT_TYPE_RESUMED] = "RESUMED", 61 [SCAN_EVENT_TYPE_NLO_COMPLETE] = "NLO_COMPLETE", 62 [SCAN_EVENT_TYPE_NLO_MATCH] = "NLO_MATCH", 63 [SCAN_EVENT_TYPE_INVALID] = "INVALID", 64 [SCAN_EVENT_TYPE_GPIO_TIMEOUT] = "GPIO_TIMEOUT", 65 [SCAN_EVENT_TYPE_RADIO_MEASUREMENT_START] = 66 "RADIO_MEASUREMENT_START", 67 [SCAN_EVENT_TYPE_RADIO_MEASUREMENT_END] = 68 "RADIO_MEASUREMENT_END", 69 [SCAN_EVENT_TYPE_BSSID_MATCH] = "BSSID_MATCH", 70 [SCAN_EVENT_TYPE_FOREIGN_CHANNEL_GET_NF] = 71 "FOREIGN_CHANNEL_GET_NF", 72 }; 73 74 if (type >= SCAN_EVENT_TYPE_MAX) 75 return "UNKNOWN"; 76 77 return event_name[type]; 78 } 79 80 81 const char* 82 util_scan_get_ev_reason_name(enum scan_completion_reason reason) 83 { 84 static const char * const reason_name[] = { 85 [SCAN_REASON_NONE] = "NONE", 86 [SCAN_REASON_COMPLETED] = "COMPLETED", 87 [SCAN_REASON_CANCELLED] = "CANCELLED", 88 [SCAN_REASON_PREEMPTED] = "PREEMPTED", 89 [SCAN_REASON_TIMEDOUT] = "TIMEDOUT", 90 [SCAN_REASON_INTERNAL_FAILURE] = "INTERNAL_FAILURE", 91 [SCAN_REASON_SUSPENDED] = "SUSPENDED", 92 [SCAN_REASON_RUN_FAILED] = "RUN_FAILED", 93 [SCAN_REASON_TERMINATION_FUNCTION] = "TERMINATION_FUNCTION", 94 [SCAN_REASON_MAX_OFFCHAN_RETRIES] = "MAX_OFFCHAN_RETRIES", 95 [SCAN_REASON_DFS_VIOLATION] = "DFS_NOL_VIOLATION", 96 }; 97 98 if (reason >= SCAN_REASON_MAX) 99 return "UNKNOWN"; 100 101 return reason_name[reason]; 102 } 103 104 qdf_time_t 105 util_get_last_scan_time(struct wlan_objmgr_vdev *vdev) 106 { 107 uint8_t pdev_id; 108 struct wlan_scan_obj *scan_obj; 109 110 if (!vdev) { 111 scm_warn("null vdev"); 112 QDF_ASSERT(0); 113 return 0; 114 } 115 pdev_id = wlan_scan_vdev_get_pdev_id(vdev); 116 scan_obj = wlan_vdev_get_scan_obj(vdev); 117 118 if (scan_obj) 119 return scan_obj->pdev_info[pdev_id].last_scan_time; 120 else 121 return 0; 122 } 123 124 enum wlan_band util_scan_scm_freq_to_band(uint16_t freq) 125 { 126 if (WLAN_REG_IS_24GHZ_CH_FREQ(freq)) 127 return WLAN_BAND_2_4_GHZ; 128 129 return WLAN_BAND_5_GHZ; 130 } 131 132 bool util_is_scan_entry_match( 133 struct scan_cache_entry *entry1, 134 struct scan_cache_entry *entry2) 135 { 136 137 if (entry1->cap_info.wlan_caps.ess != 138 entry2->cap_info.wlan_caps.ess) 139 return false; 140 141 if (entry1->cap_info.wlan_caps.ess && 142 !qdf_mem_cmp(entry1->bssid.bytes, 143 entry2->bssid.bytes, QDF_MAC_ADDR_SIZE)) { 144 /* Check for BSS */ 145 if (util_is_ssid_match(&entry1->ssid, &entry2->ssid) || 146 util_scan_is_null_ssid(&entry1->ssid) || 147 util_scan_is_null_ssid(&entry2->ssid)) 148 return true; 149 } else if (entry1->cap_info.wlan_caps.ibss && 150 (entry1->channel.chan_freq == 151 entry2->channel.chan_freq)) { 152 /* 153 * Same channel cannot have same SSID for 154 * different IBSS, so no need to check BSSID 155 */ 156 if (util_is_ssid_match( 157 &entry1->ssid, &entry2->ssid)) 158 return true; 159 } else if (!entry1->cap_info.wlan_caps.ibss && 160 !entry1->cap_info.wlan_caps.ess && 161 !qdf_mem_cmp(entry1->bssid.bytes, 162 entry2->bssid.bytes, QDF_MAC_ADDR_SIZE)) { 163 /* In case of P2P devices, ess and ibss will be set to zero */ 164 return true; 165 } 166 167 return false; 168 } 169 170 static bool util_is_pureg_rate(uint8_t *rates, uint8_t nrates) 171 { 172 static const uint8_t g_rates[] = {12, 18, 24, 36, 48, 72, 96, 108}; 173 bool pureg = false; 174 uint8_t i, j; 175 176 for (i = 0; i < nrates; i++) { 177 for (j = 0; j < QDF_ARRAY_SIZE(g_rates); j++) { 178 if (WLAN_RV(rates[i]) == g_rates[j]) { 179 pureg = true; 180 break; 181 } 182 } 183 if (pureg) 184 break; 185 } 186 187 return pureg; 188 } 189 190 #ifdef WLAN_FEATURE_11BE 191 static enum wlan_phymode 192 util_scan_get_phymode_11be(struct wlan_objmgr_pdev *pdev, 193 struct scan_cache_entry *scan_params, 194 enum wlan_phymode phymode, 195 uint8_t band_mask) 196 { 197 struct wlan_ie_ehtops *eht_ops; 198 uint8_t width; 199 200 eht_ops = (struct wlan_ie_ehtops *)util_scan_entry_ehtop(scan_params); 201 if (!util_scan_entry_ehtcap(scan_params) || !eht_ops) 202 return phymode; 203 204 if (QDF_GET_BITS(eht_ops->ehtop_param, 205 EHTOP_INFO_PRESENT_IDX, EHTOP_INFO_PRESENT_BITS)) { 206 width = QDF_GET_BITS(eht_ops->control, 207 EHTOP_INFO_CHAN_WIDTH_IDX, 208 EHTOP_INFO_CHAN_WIDTH_BITS); 209 switch (width) { 210 case WLAN_EHT_CHWIDTH_20: 211 phymode = WLAN_PHYMODE_11BEA_EHT20; 212 break; 213 case WLAN_EHT_CHWIDTH_40: 214 phymode = WLAN_PHYMODE_11BEA_EHT40; 215 break; 216 case WLAN_EHT_CHWIDTH_80: 217 phymode = WLAN_PHYMODE_11BEA_EHT80; 218 break; 219 case WLAN_EHT_CHWIDTH_160: 220 phymode = WLAN_PHYMODE_11BEA_EHT160; 221 break; 222 case WLAN_EHT_CHWIDTH_320: 223 phymode = WLAN_PHYMODE_11BEA_EHT320; 224 break; 225 default: 226 scm_debug("Invalid eht_ops width: %d", width); 227 phymode = WLAN_PHYMODE_11BEA_EHT20; 228 break; 229 } 230 } else { 231 switch (phymode) { 232 case WLAN_PHYMODE_11AXA_HE20: 233 phymode = WLAN_PHYMODE_11BEA_EHT20; 234 break; 235 case WLAN_PHYMODE_11AXG_HE20: 236 phymode = WLAN_PHYMODE_11BEG_EHT20; 237 break; 238 case WLAN_PHYMODE_11AXA_HE40: 239 phymode = WLAN_PHYMODE_11BEA_EHT40; 240 break; 241 case WLAN_PHYMODE_11AXG_HE40: 242 phymode = WLAN_PHYMODE_11BEG_EHT40; 243 break; 244 case WLAN_PHYMODE_11AXA_HE80: 245 phymode = WLAN_PHYMODE_11BEA_EHT80; 246 break; 247 case WLAN_PHYMODE_11AXA_HE160: 248 phymode = WLAN_PHYMODE_11BEA_EHT160; 249 break; 250 default: 251 break; 252 } 253 } 254 255 if (QDF_GET_BITS(eht_ops->ehtop_param, 256 EHTOP_INFO_PRESENT_IDX, EHTOP_INFO_PRESENT_BITS)) { 257 scan_params->channel.cfreq0 = 258 wlan_reg_chan_band_to_freq(pdev, 259 eht_ops->ccfs0, 260 band_mask); 261 scan_params->channel.cfreq1 = 262 wlan_reg_chan_band_to_freq(pdev, 263 eht_ops->ccfs1, 264 band_mask); 265 } 266 267 if (QDF_GET_BITS(eht_ops->ehtop_param, 268 EHTOP_PARAM_DISABLED_SC_BITMAP_PRESENT_IDX, 269 EHTOP_PARAM_DISABLED_SC_BITMAP_PRESENT_BITS)) { 270 scan_params->channel.puncture_bitmap = 271 QDF_GET_BITS(eht_ops->disabled_sub_chan_bitmap[0], 272 0, 8); 273 scan_params->channel.puncture_bitmap |= 274 QDF_GET_BITS(eht_ops->disabled_sub_chan_bitmap[1], 275 0, 8) << 8; 276 } else { 277 scan_params->channel.puncture_bitmap = 0; 278 } 279 280 return phymode; 281 } 282 #else 283 static enum wlan_phymode 284 util_scan_get_phymode_11be(struct wlan_objmgr_pdev *pdev, 285 struct scan_cache_entry *scan_params, 286 enum wlan_phymode phymode, 287 uint8_t band_mask) 288 { 289 return phymode; 290 } 291 #endif 292 293 #ifdef CONFIG_BAND_6GHZ 294 static struct he_oper_6g_param *util_scan_get_he_6g_params(uint8_t *he_ops) 295 { 296 uint8_t len; 297 uint32_t he_oper_params; 298 299 if (!he_ops) 300 return NULL; 301 302 len = he_ops[1]; 303 he_ops += sizeof(struct ie_header); 304 305 if (len < WLAN_HEOP_FIXED_PARAM_LENGTH) 306 return NULL; 307 308 /* element id extension */ 309 he_ops++; 310 len--; 311 312 he_oper_params = LE_READ_4(he_ops); 313 if (!(he_oper_params & WLAN_HEOP_6GHZ_INFO_PRESENT_MASK)) 314 return NULL; 315 316 /* fixed params - element id extension */ 317 he_ops += WLAN_HEOP_FIXED_PARAM_LENGTH - 1; 318 len -= WLAN_HEOP_FIXED_PARAM_LENGTH - 1; 319 320 if (!len) 321 return NULL; 322 323 /* vht oper params */ 324 if (he_oper_params & WLAN_HEOP_VHTOP_PRESENT_MASK) { 325 if (len < WLAN_HEOP_VHTOP_LENGTH) 326 return NULL; 327 he_ops += WLAN_HEOP_VHTOP_LENGTH; 328 len -= WLAN_HEOP_VHTOP_LENGTH; 329 } 330 331 if (!len) 332 return NULL; 333 334 if (he_oper_params & WLAN_HEOP_CO_LOCATED_BSS_MASK) { 335 he_ops += WLAN_HEOP_CO_LOCATED_BSS_LENGTH; 336 len -= WLAN_HEOP_CO_LOCATED_BSS_LENGTH; 337 } 338 339 if (len < sizeof(struct he_oper_6g_param)) 340 return NULL; 341 342 return (struct he_oper_6g_param *)he_ops; 343 } 344 345 #ifdef WLAN_FEATURE_11BE 346 /* 347 * util_scan_is_out_of_band_leak_eht() - Check if eht beacon out of BSS BW 348 * @pdev: pointer to pdev. 349 * @scan_params: scan entry generated by beacon/probe rsp 350 * @band_mask: band mask of frequency beacon/probe rsp received 351 * @current_freq: frequency beacon/probe rsp received 352 * 353 * 1. If BSS BW <= 80MHz 354 * If Absolute value of (Current Channel Channel Center Frequency Segment 0) <= 355 * BSS BW/2 then eht beacon in BSS operating BW 356 * else eht beacon out of BSS operating BW 357 * 358 * 2. If BSS BW > 80MHz 359 * If Absolute value of (Current Channel Channel Center Frequency Segment 1) <= 360 * BSS BW/2 then eht beacon in BSS operating BW 361 * else eht beacon out of BSS operating BW 362 * 363 * Return: bool, whether eht beacon out of BSS operating BW 364 */ 365 static bool 366 util_scan_is_out_of_band_leak_eht(struct wlan_objmgr_pdev *pdev, 367 struct scan_cache_entry *scan_params, 368 uint8_t band_mask, 369 qdf_freq_t current_freq) 370 { 371 struct wlan_ie_ehtops *eht_ops; 372 uint8_t ch_width; 373 uint32_t bw; 374 uint32_t freq_diff; 375 qdf_freq_t freq_seg0; 376 qdf_freq_t freq_seg1; 377 378 eht_ops = (struct wlan_ie_ehtops *)util_scan_entry_ehtop(scan_params); 379 if (!util_scan_entry_ehtcap(scan_params) || !eht_ops) 380 return false; 381 382 if (!QDF_GET_BITS(eht_ops->ehtop_param, 383 EHTOP_INFO_PRESENT_IDX, EHTOP_INFO_PRESENT_BITS)) 384 return false; 385 386 ch_width = QDF_GET_BITS(eht_ops->control, 387 EHTOP_INFO_CHAN_WIDTH_IDX, 388 EHTOP_INFO_CHAN_WIDTH_BITS); 389 freq_seg0 = wlan_reg_chan_band_to_freq(pdev, eht_ops->ccfs0, 390 band_mask); 391 freq_seg1 = wlan_reg_chan_band_to_freq(pdev, eht_ops->ccfs1, 392 band_mask); 393 if (ch_width == WLAN_EHT_CHWIDTH_320) 394 bw = BW_320_MHZ; 395 else if (ch_width == WLAN_EHT_CHWIDTH_160) 396 bw = BW_160_MHZ; 397 else if (ch_width == WLAN_EHT_CHWIDTH_80) 398 bw = BW_80_MHZ; 399 else if (ch_width == WLAN_EHT_CHWIDTH_40) 400 bw = BW_40_MHZ; 401 else if (ch_width == WLAN_EHT_CHWIDTH_20) 402 bw = BW_20_MHZ; 403 else 404 bw = BW_20_MHZ; 405 406 if (bw <= BW_80_MHZ) 407 freq_diff = abs(freq_seg0 - current_freq); 408 else 409 freq_diff = abs(freq_seg1 - current_freq); 410 if (freq_diff <= bw / 2) 411 return false; 412 413 scm_debug("Leaked freq:%u ch width:%u freq0:%u freq1:%u", 414 current_freq, bw, freq_seg0, freq_seg1); 415 return true; 416 } 417 #else 418 static bool 419 util_scan_is_out_of_band_leak_eht(struct wlan_objmgr_pdev *pdev, 420 struct scan_cache_entry *scan_params, 421 uint8_t band_mask, 422 qdf_freq_t current_freq) 423 { 424 return false; 425 } 426 #endif 427 428 /* 429 * util_scan_is_out_of_band_leak_he() - Check if HE beacon out of BSS BW 430 * @pdev: pointer to pdev. 431 * @he_6g_params: HE 6 GHz params 432 * @band_mask: band mask of frequency beacon/probe rsp received 433 * @current_freq: frequency beacon/probe rsp received 434 * 435 * 1. If BSS BW <= 80MHz 436 * If Absolute value of (Current Channel Channel Center Frequency Segment 0) <= 437 * BSS BW/2 then HE beacon in BSS operating BW 438 * 439 * 2. If BSS BW is 160MHz 440 * If Absolute value of (Current Channel Channel Center Frequency Segment 1) <= 441 * BSS BW/2 then HE beacon in BSS operating BW 442 * 443 * 3. If BSS BW is 80+80MHz 444 * If absolute value of (Current Channel - Channel Center Frequency Segment 0) 445 * <= 40 or absolute value of (Current Channel - Channel Center Frequency 446 * Segment 1) <= 40, then HE beacon in BSS operating BW 447 * 448 * Return: bool, whether HE beacon out of BSS operating BW 449 */ 450 static bool 451 util_scan_is_out_of_band_leak_he(struct wlan_objmgr_pdev *pdev, 452 struct he_oper_6g_param *he_6g_params, 453 uint8_t band_mask, 454 qdf_freq_t current_freq) 455 { 456 uint8_t ch_width; 457 uint32_t bw; 458 uint32_t freq_diff; 459 qdf_freq_t freq_seg0; 460 qdf_freq_t freq_seg1; 461 462 ch_width = he_6g_params->width; 463 freq_seg0 = wlan_reg_chan_band_to_freq(pdev, 464 he_6g_params->chan_freq_seg0, 465 band_mask); 466 freq_seg1 = wlan_reg_chan_band_to_freq(pdev, 467 he_6g_params->chan_freq_seg1, 468 band_mask); 469 if (ch_width == WLAN_HE_6GHZ_CHWIDTH_160_80_80) 470 bw = BW_160_MHZ; 471 else if (ch_width == WLAN_HE_6GHZ_CHWIDTH_80) 472 bw = BW_80_MHZ; 473 else if (ch_width == WLAN_HE_6GHZ_CHWIDTH_40) 474 bw = BW_40_MHZ; 475 else if (ch_width == WLAN_HE_6GHZ_CHWIDTH_20) 476 bw = BW_20_MHZ; 477 else 478 bw = BW_20_MHZ; 479 480 if (bw <= BW_80_MHZ) { 481 freq_diff = abs(freq_seg0 - current_freq); 482 if (freq_diff <= bw / 2) 483 return false; 484 } else if (WLAN_IS_HE160(he_6g_params)) { 485 freq_diff = abs(freq_seg1 - current_freq); 486 if (freq_diff <= bw / 2) 487 return false; 488 } else if (WLAN_IS_HE80_80(he_6g_params)) { 489 freq_diff = abs(freq_seg0 - current_freq); 490 if (freq_diff <= BW_40_MHZ) 491 return false; 492 freq_diff = abs(freq_seg1 - current_freq); 493 if (freq_diff <= BW_40_MHZ) 494 return false; 495 } 496 497 scm_debug("Leaked freq:%u ch width:%u freq0:%u freq1:%u", 498 current_freq, bw, freq_seg0, freq_seg1); 499 500 return true; 501 } 502 503 /* 504 * util_scan_get_chan_from_he_6g_params() - Get chan info from 6 GHz param 505 * @pdev: pointer to pdev. 506 * @scan_params: scan entry generated by beacon/probe rsp 507 * @chan_freq: output parameter, primary freq from 6 GHz he params 508 * @is_6g_dup_bcon: output parameter, bool, if false, invalid 6g duplicated 509 beacon out of BSS operating BW or not duplicated beacon, can drop if 510 channel mismatch 511 * @band_mask: band mask of frequency beacon/probe rsp received 512 * @current_freq: frequency beacon/probe rsp received 513 * 514 * Return: QDF_STATUS 515 */ 516 static QDF_STATUS 517 util_scan_get_chan_from_he_6g_params(struct wlan_objmgr_pdev *pdev, 518 struct scan_cache_entry *scan_params, 519 qdf_freq_t *chan_freq, 520 bool *is_6g_dup_bcon, uint8_t band_mask, 521 qdf_freq_t current_freq) 522 { 523 struct he_oper_6g_param *he_6g_params; 524 uint8_t *he_ops; 525 struct wlan_scan_obj *scan_obj; 526 struct wlan_objmgr_psoc *psoc; 527 bool is_out_of_band_leak = true; 528 529 psoc = wlan_pdev_get_psoc(pdev); 530 if (!psoc) { 531 scm_err("psoc is NULL"); 532 return QDF_STATUS_E_INVAL; 533 } 534 535 scan_obj = wlan_psoc_get_scan_obj(psoc); 536 if (!scan_obj) { 537 scm_err("scan_obj is NULL"); 538 return QDF_STATUS_E_INVAL; 539 } 540 541 *is_6g_dup_bcon = false; 542 543 he_ops = util_scan_entry_heop(scan_params); 544 if (!util_scan_entry_hecap(scan_params) || !he_ops) 545 return QDF_STATUS_SUCCESS; 546 547 he_6g_params = util_scan_get_he_6g_params(he_ops); 548 if (!he_6g_params) 549 return QDF_STATUS_SUCCESS; 550 551 *chan_freq = wlan_reg_chan_band_to_freq(pdev, 552 he_6g_params->primary_channel, 553 band_mask); 554 if (scan_obj->drop_bcn_on_invalid_freq && 555 !wlan_reg_is_freq_enabled(pdev, *chan_freq, REG_BEST_PWR_MODE)) { 556 scm_debug_rl(QDF_MAC_ADDR_FMT": Drop as invalid channel %d freq %d in HE 6Ghz params", 557 QDF_MAC_ADDR_REF(scan_params->bssid.bytes), 558 he_6g_params->primary_channel, *chan_freq); 559 return QDF_STATUS_E_INVAL; 560 } 561 562 if (!he_6g_params->duplicate_beacon) { 563 *is_6g_dup_bcon = false; 564 return QDF_STATUS_SUCCESS; 565 } 566 is_out_of_band_leak = 567 util_scan_is_out_of_band_leak_eht(pdev, scan_params, band_mask, 568 current_freq); 569 if (is_out_of_band_leak) { 570 *is_6g_dup_bcon = false; 571 return QDF_STATUS_SUCCESS; 572 } 573 is_out_of_band_leak = 574 util_scan_is_out_of_band_leak_he(pdev, he_6g_params, band_mask, 575 current_freq); 576 if (is_out_of_band_leak) { 577 *is_6g_dup_bcon = false; 578 return QDF_STATUS_SUCCESS; 579 } 580 581 *is_6g_dup_bcon = true; 582 583 return QDF_STATUS_SUCCESS; 584 } 585 586 static enum wlan_phymode 587 util_scan_get_phymode_6g(struct wlan_objmgr_pdev *pdev, 588 struct scan_cache_entry *scan_params) 589 { 590 struct he_oper_6g_param *he_6g_params; 591 enum wlan_phymode phymode = WLAN_PHYMODE_11AXA_HE20; 592 uint8_t *he_ops; 593 uint8_t band_mask = BIT(REG_BAND_6G); 594 595 he_ops = util_scan_entry_heop(scan_params); 596 if (!util_scan_entry_hecap(scan_params) || !he_ops) 597 return phymode; 598 599 he_6g_params = util_scan_get_he_6g_params(he_ops); 600 if (!he_6g_params) 601 return phymode; 602 603 switch (he_6g_params->width) { 604 case WLAN_HE_6GHZ_CHWIDTH_20: 605 phymode = WLAN_PHYMODE_11AXA_HE20; 606 break; 607 case WLAN_HE_6GHZ_CHWIDTH_40: 608 phymode = WLAN_PHYMODE_11AXA_HE40; 609 break; 610 case WLAN_HE_6GHZ_CHWIDTH_80: 611 phymode = WLAN_PHYMODE_11AXA_HE80; 612 break; 613 case WLAN_HE_6GHZ_CHWIDTH_160_80_80: 614 if (WLAN_IS_HE80_80(he_6g_params)) 615 phymode = WLAN_PHYMODE_11AXA_HE80_80; 616 else if (WLAN_IS_HE160(he_6g_params)) 617 phymode = WLAN_PHYMODE_11AXA_HE160; 618 else 619 phymode = WLAN_PHYMODE_11AXA_HE80; 620 break; 621 default: 622 scm_err("Invalid he_6g_params width: %d", he_6g_params->width); 623 phymode = WLAN_PHYMODE_11AXA_HE20; 624 break; 625 } 626 627 if (he_6g_params->chan_freq_seg0) 628 scan_params->channel.cfreq0 = 629 wlan_reg_chan_band_to_freq(pdev, 630 he_6g_params->chan_freq_seg0, 631 band_mask); 632 if (he_6g_params->chan_freq_seg1) 633 scan_params->channel.cfreq1 = 634 wlan_reg_chan_band_to_freq(pdev, 635 he_6g_params->chan_freq_seg1, 636 band_mask); 637 638 phymode = util_scan_get_phymode_11be(pdev, scan_params, 639 phymode, band_mask); 640 641 return phymode; 642 } 643 644 uint8_t 645 util_scan_get_6g_oper_channel(uint8_t *he_op_ie) 646 { 647 struct he_oper_6g_param *he_6g_params; 648 649 he_6g_params = util_scan_get_he_6g_params(he_op_ie); 650 if (!he_6g_params) 651 return 0; 652 653 return he_6g_params->primary_channel; 654 } 655 656 #else 657 static QDF_STATUS 658 util_scan_get_chan_from_he_6g_params(struct wlan_objmgr_pdev *pdev, 659 struct scan_cache_entry *scan_params, 660 qdf_freq_t *chan_freq, 661 bool *is_6g_dup_bcon, 662 uint8_t band_mask, 663 qdf_freq_t current_freq) 664 { 665 return QDF_STATUS_SUCCESS; 666 } 667 static inline enum wlan_phymode 668 util_scan_get_phymode_6g(struct wlan_objmgr_pdev *pdev, 669 struct scan_cache_entry *scan_params) 670 { 671 return WLAN_PHYMODE_AUTO; 672 } 673 #endif 674 675 static inline 676 uint32_t util_scan_sec_chan_freq_from_htinfo(struct wlan_ie_htinfo_cmn *htinfo, 677 uint32_t primary_chan_freq) 678 { 679 if (htinfo->hi_extchoff == WLAN_HTINFO_EXTOFFSET_ABOVE) 680 return primary_chan_freq + WLAN_CHAN_SPACING_20MHZ; 681 else if (htinfo->hi_extchoff == WLAN_HTINFO_EXTOFFSET_BELOW) 682 return primary_chan_freq - WLAN_CHAN_SPACING_20MHZ; 683 684 return 0; 685 } 686 687 static enum wlan_phymode 688 util_scan_get_phymode_5g(struct wlan_objmgr_pdev *pdev, 689 struct scan_cache_entry *scan_params) 690 { 691 enum wlan_phymode phymode = WLAN_PHYMODE_AUTO; 692 uint16_t ht_cap = 0; 693 struct htcap_cmn_ie *htcap; 694 struct wlan_ie_htinfo_cmn *htinfo; 695 struct wlan_ie_vhtop *vhtop; 696 uint8_t band_mask = BIT(REG_BAND_5G); 697 698 htcap = (struct htcap_cmn_ie *) 699 util_scan_entry_htcap(scan_params); 700 htinfo = (struct wlan_ie_htinfo_cmn *) 701 util_scan_entry_htinfo(scan_params); 702 vhtop = (struct wlan_ie_vhtop *) 703 util_scan_entry_vhtop(scan_params); 704 705 if (!(htcap && htinfo)) 706 return WLAN_PHYMODE_11A; 707 708 if (htcap) 709 ht_cap = le16toh(htcap->hc_cap); 710 711 if ((ht_cap & WLAN_HTCAP_C_CHWIDTH40) && 712 (htinfo->hi_extchoff == WLAN_HTINFO_EXTOFFSET_ABOVE || 713 htinfo->hi_extchoff == WLAN_HTINFO_EXTOFFSET_BELOW)) 714 phymode = WLAN_PHYMODE_11NA_HT40; 715 else 716 phymode = WLAN_PHYMODE_11NA_HT20; 717 718 scan_params->channel.cfreq0 = 719 util_scan_sec_chan_freq_from_htinfo(htinfo, 720 scan_params->channel.chan_freq); 721 722 if (util_scan_entry_vhtcap(scan_params) && vhtop) { 723 switch (vhtop->vht_op_chwidth) { 724 case WLAN_VHTOP_CHWIDTH_2040: 725 if (phymode == WLAN_PHYMODE_11NA_HT40) 726 phymode = WLAN_PHYMODE_11AC_VHT40; 727 else 728 phymode = WLAN_PHYMODE_11AC_VHT20; 729 break; 730 case WLAN_VHTOP_CHWIDTH_80: 731 if (WLAN_IS_REVSIG_VHT80_80(vhtop)) 732 phymode = WLAN_PHYMODE_11AC_VHT80_80; 733 else if (WLAN_IS_REVSIG_VHT160(vhtop)) 734 phymode = WLAN_PHYMODE_11AC_VHT160; 735 else 736 phymode = WLAN_PHYMODE_11AC_VHT80; 737 break; 738 case WLAN_VHTOP_CHWIDTH_160: 739 phymode = WLAN_PHYMODE_11AC_VHT160; 740 break; 741 case WLAN_VHTOP_CHWIDTH_80_80: 742 phymode = WLAN_PHYMODE_11AC_VHT80_80; 743 break; 744 default: 745 scm_debug("bad channel: %d", 746 vhtop->vht_op_chwidth); 747 phymode = WLAN_PHYMODE_11AC_VHT20; 748 break; 749 } 750 if (vhtop->vht_op_ch_freq_seg1) 751 scan_params->channel.cfreq0 = 752 wlan_reg_chan_band_to_freq(pdev, 753 vhtop->vht_op_ch_freq_seg1, 754 band_mask); 755 if (vhtop->vht_op_ch_freq_seg2) 756 scan_params->channel.cfreq1 = 757 wlan_reg_chan_band_to_freq(pdev, 758 vhtop->vht_op_ch_freq_seg2, 759 band_mask); 760 } 761 762 if (!util_scan_entry_hecap(scan_params)) 763 return phymode; 764 765 /* for 5Ghz Check for HE, only if VHT cap and HE cap are present */ 766 if (!IS_WLAN_PHYMODE_VHT(phymode)) 767 return phymode; 768 769 switch (phymode) { 770 case WLAN_PHYMODE_11AC_VHT20: 771 phymode = WLAN_PHYMODE_11AXA_HE20; 772 break; 773 case WLAN_PHYMODE_11AC_VHT40: 774 phymode = WLAN_PHYMODE_11AXA_HE40; 775 break; 776 case WLAN_PHYMODE_11AC_VHT80: 777 phymode = WLAN_PHYMODE_11AXA_HE80; 778 break; 779 case WLAN_PHYMODE_11AC_VHT160: 780 phymode = WLAN_PHYMODE_11AXA_HE160; 781 break; 782 case WLAN_PHYMODE_11AC_VHT80_80: 783 phymode = WLAN_PHYMODE_11AXA_HE80_80; 784 break; 785 default: 786 phymode = WLAN_PHYMODE_11AXA_HE20; 787 break; 788 } 789 790 phymode = util_scan_get_phymode_11be(pdev, scan_params, 791 phymode, band_mask); 792 793 return phymode; 794 } 795 796 #ifdef WLAN_FEATURE_11BE 797 static enum wlan_phymode 798 util_scan_get_phymode_2g_11be(struct scan_cache_entry *scan_params, 799 enum wlan_phymode phymode) 800 { 801 if (!util_scan_entry_ehtcap(scan_params)) 802 return phymode; 803 804 if (phymode == WLAN_PHYMODE_11AXG_HE40PLUS) 805 phymode = WLAN_PHYMODE_11BEG_EHT40PLUS; 806 else if (phymode == WLAN_PHYMODE_11AXG_HE40MINUS) 807 phymode = WLAN_PHYMODE_11BEG_EHT40MINUS; 808 else 809 phymode = WLAN_PHYMODE_11BEG_EHT20; 810 811 return phymode; 812 } 813 #else 814 static enum wlan_phymode 815 util_scan_get_phymode_2g_11be(struct scan_cache_entry *scan_params, 816 enum wlan_phymode phymode) 817 { 818 return phymode; 819 } 820 #endif 821 822 static enum wlan_phymode 823 util_scan_get_phymode_2g(struct scan_cache_entry *scan_params) 824 { 825 enum wlan_phymode phymode = WLAN_PHYMODE_AUTO; 826 uint16_t ht_cap = 0; 827 struct htcap_cmn_ie *htcap; 828 struct wlan_ie_htinfo_cmn *htinfo; 829 struct wlan_ie_vhtop *vhtop; 830 831 htcap = (struct htcap_cmn_ie *) 832 util_scan_entry_htcap(scan_params); 833 htinfo = (struct wlan_ie_htinfo_cmn *) 834 util_scan_entry_htinfo(scan_params); 835 vhtop = (struct wlan_ie_vhtop *) 836 util_scan_entry_vhtop(scan_params); 837 838 if (htcap) 839 ht_cap = le16toh(htcap->hc_cap); 840 841 if (htcap && htinfo) { 842 if ((ht_cap & WLAN_HTCAP_C_CHWIDTH40) && 843 (htinfo->hi_extchoff == WLAN_HTINFO_EXTOFFSET_ABOVE)) 844 phymode = WLAN_PHYMODE_11NG_HT40PLUS; 845 else if ((ht_cap & WLAN_HTCAP_C_CHWIDTH40) && 846 (htinfo->hi_extchoff == WLAN_HTINFO_EXTOFFSET_BELOW)) 847 phymode = WLAN_PHYMODE_11NG_HT40MINUS; 848 else 849 phymode = WLAN_PHYMODE_11NG_HT20; 850 } else if (util_scan_entry_xrates(scan_params)) { 851 /* only 11G stations will have more than 8 rates */ 852 phymode = WLAN_PHYMODE_11G; 853 } else { 854 /* Some mischievous g-only APs do not set extended rates */ 855 if (util_scan_entry_rates(scan_params)) { 856 if (util_is_pureg_rate(&scan_params->ie_list.rates[2], 857 scan_params->ie_list.rates[1])) 858 phymode = WLAN_PHYMODE_11G; 859 else 860 phymode = WLAN_PHYMODE_11B; 861 } else { 862 phymode = WLAN_PHYMODE_11B; 863 } 864 } 865 866 /* Check for VHT only if HT cap is present */ 867 if (!IS_WLAN_PHYMODE_HT(phymode)) 868 return phymode; 869 870 scan_params->channel.cfreq0 = 871 util_scan_sec_chan_freq_from_htinfo(htinfo, 872 scan_params->channel.chan_freq); 873 874 if (util_scan_entry_vhtcap(scan_params) && vhtop) { 875 switch (vhtop->vht_op_chwidth) { 876 case WLAN_VHTOP_CHWIDTH_2040: 877 if (phymode == WLAN_PHYMODE_11NG_HT40PLUS) 878 phymode = WLAN_PHYMODE_11AC_VHT40PLUS_2G; 879 else if (phymode == WLAN_PHYMODE_11NG_HT40MINUS) 880 phymode = WLAN_PHYMODE_11AC_VHT40MINUS_2G; 881 else 882 phymode = WLAN_PHYMODE_11AC_VHT20_2G; 883 884 break; 885 default: 886 scm_info("bad vht_op_chwidth: %d", 887 vhtop->vht_op_chwidth); 888 phymode = WLAN_PHYMODE_11AC_VHT20_2G; 889 break; 890 } 891 } 892 893 if (!util_scan_entry_hecap(scan_params)) 894 return phymode; 895 896 if (phymode == WLAN_PHYMODE_11AC_VHT40PLUS_2G || 897 phymode == WLAN_PHYMODE_11NG_HT40PLUS) 898 phymode = WLAN_PHYMODE_11AXG_HE40PLUS; 899 else if (phymode == WLAN_PHYMODE_11AC_VHT40MINUS_2G || 900 phymode == WLAN_PHYMODE_11NG_HT40MINUS) 901 phymode = WLAN_PHYMODE_11AXG_HE40MINUS; 902 else 903 phymode = WLAN_PHYMODE_11AXG_HE20; 904 905 phymode = util_scan_get_phymode_2g_11be(scan_params, phymode); 906 907 return phymode; 908 } 909 910 static enum wlan_phymode 911 util_scan_get_phymode(struct wlan_objmgr_pdev *pdev, 912 struct scan_cache_entry *scan_params) 913 { 914 if (WLAN_REG_IS_24GHZ_CH_FREQ(scan_params->channel.chan_freq)) 915 return util_scan_get_phymode_2g(scan_params); 916 else if (WLAN_REG_IS_6GHZ_CHAN_FREQ(scan_params->channel.chan_freq)) 917 return util_scan_get_phymode_6g(pdev, scan_params); 918 else 919 return util_scan_get_phymode_5g(pdev, scan_params); 920 } 921 922 static QDF_STATUS 923 util_scan_parse_chan_switch_wrapper_ie(struct scan_cache_entry *scan_params, 924 struct ie_header *sub_ie, qdf_size_t sub_ie_len) 925 { 926 /* Walk through to check nothing is malformed */ 927 while (sub_ie_len >= sizeof(struct ie_header)) { 928 /* At least one more header is present */ 929 sub_ie_len -= sizeof(struct ie_header); 930 931 if (sub_ie->ie_len == 0) { 932 sub_ie += 1; 933 continue; 934 } 935 if (sub_ie_len < sub_ie->ie_len) { 936 scm_debug_rl(QDF_MAC_ADDR_FMT": Incomplete corrupted IE:%x", 937 QDF_MAC_ADDR_REF(scan_params->bssid.bytes), 938 WLAN_ELEMID_CHAN_SWITCH_WRAP); 939 return QDF_STATUS_E_INVAL; 940 } 941 switch (sub_ie->ie_id) { 942 case WLAN_ELEMID_COUNTRY: 943 if (sub_ie->ie_len < WLAN_COUNTRY_IE_MIN_LEN) 944 return QDF_STATUS_E_INVAL; 945 scan_params->ie_list.country = (uint8_t *)sub_ie; 946 break; 947 case WLAN_ELEMID_WIDE_BAND_CHAN_SWITCH: 948 if (sub_ie->ie_len < WLAN_WIDE_BW_CHAN_SWITCH_IE_LEN) 949 return QDF_STATUS_E_INVAL; 950 scan_params->ie_list.widebw = (uint8_t *)sub_ie; 951 break; 952 case WLAN_ELEMID_VHT_TX_PWR_ENVLP: 953 if (sub_ie->ie_len > WLAN_TPE_IE_MAX_LEN) 954 return QDF_STATUS_E_INVAL; 955 scan_params->ie_list.txpwrenvlp = (uint8_t *)sub_ie; 956 break; 957 #ifdef WLAN_FEATURE_11BE 958 case WLAN_EXTN_ELEMID_BW_IND: 959 if (sub_ie->ie_len > WLAN_BW_IND_IE_MAX_LEN) 960 return QDF_STATUS_E_INVAL; 961 scan_params->ie_list.bw_ind = (uint8_t *)sub_ie; 962 break; 963 #endif 964 } 965 /* Consume sub info element */ 966 sub_ie_len -= sub_ie->ie_len; 967 /* go to next Sub IE */ 968 sub_ie = (struct ie_header *) 969 (((uint8_t *) sub_ie) + 970 sizeof(struct ie_header) + sub_ie->ie_len); 971 } 972 973 return QDF_STATUS_SUCCESS; 974 } 975 976 bool 977 util_scan_is_hidden_ssid(struct ie_ssid *ssid) 978 { 979 uint8_t i; 980 981 /* 982 * We flag this as Hidden SSID if the Length is 0 983 * of the SSID only contains 0's 984 */ 985 if (!ssid || !ssid->ssid_len) 986 return true; 987 988 for (i = 0; i < ssid->ssid_len; i++) 989 if (ssid->ssid[i] != 0) 990 return false; 991 992 /* All 0's */ 993 return true; 994 } 995 996 #ifdef WLAN_FEATURE_11BE_MLO 997 static void 998 util_scan_update_rnr_mld(struct rnr_bss_info *rnr, 999 struct neighbor_ap_info_field *ap_info, uint8_t *data) 1000 { 1001 bool mld_info_present = false; 1002 1003 switch (ap_info->tbtt_header.tbtt_info_length) { 1004 case TBTT_NEIGHBOR_AP_BSSID_S_SSID_BSS_PARAM_20MHZ_PSD_MLD_PARAM: 1005 qdf_mem_copy(&rnr->mld_info, &data[13], 1006 sizeof(struct rnr_mld_info)); 1007 mld_info_present = true; 1008 break; 1009 }; 1010 1011 rnr->mld_info_valid = mld_info_present; 1012 } 1013 #else 1014 static void 1015 util_scan_update_rnr_mld(struct rnr_bss_info *rnr, 1016 struct neighbor_ap_info_field *ap_info, uint8_t *data) 1017 { 1018 } 1019 #endif 1020 1021 static QDF_STATUS 1022 util_scan_update_rnr(struct rnr_bss_info *rnr, 1023 struct neighbor_ap_info_field *ap_info, 1024 uint8_t *data) 1025 { 1026 uint8_t tbtt_info_length; 1027 1028 tbtt_info_length = ap_info->tbtt_header.tbtt_info_length; 1029 1030 switch (tbtt_info_length) { 1031 case TBTT_NEIGHBOR_AP_OFFSET_ONLY: 1032 /* Dont store it skip*/ 1033 break; 1034 1035 case TBTT_NEIGHBOR_AP_BSS_PARAM: 1036 /* Dont store it skip*/ 1037 break; 1038 1039 case TBTT_NEIGHBOR_AP_S_SSID_BSS_PARAM: 1040 rnr->bss_params = data[5]; 1041 fallthrough; 1042 case TBTT_NEIGHBOR_AP_SHORTSSID: 1043 rnr->channel_number = ap_info->channel_number; 1044 rnr->operating_class = ap_info->operting_class; 1045 qdf_mem_copy(&rnr->short_ssid, &data[1], SHORT_SSID_LEN); 1046 break; 1047 1048 case TBTT_NEIGHBOR_AP_BSSID_BSS_PARAM_20MHZ_PSD: 1049 rnr->psd_20mhz = data[8]; 1050 fallthrough; 1051 case TBTT_NEIGHBOR_AP_BSSID_BSS_PARAM: 1052 rnr->bss_params = data[7]; 1053 fallthrough; 1054 case TBTT_NEIGHBOR_AP_BSSID: 1055 rnr->channel_number = ap_info->channel_number; 1056 rnr->operating_class = ap_info->operting_class; 1057 qdf_mem_copy(&rnr->bssid, &data[1], QDF_MAC_ADDR_SIZE); 1058 break; 1059 1060 case TBTT_NEIGHBOR_AP_BSSID_S_SSID_BSS_PARAM_20MHZ_PSD_MLD_PARAM: 1061 util_scan_update_rnr_mld(rnr, ap_info, data); 1062 fallthrough; 1063 case TBTT_NEIGHBOR_AP_BSSID_S_SSID_BSS_PARAM_20MHZ_PSD: 1064 rnr->psd_20mhz = data[12]; 1065 fallthrough; 1066 case TBTT_NEIGHBOR_AP_BSSID_S_SSID_BSS_PARAM: 1067 rnr->bss_params = data[11]; 1068 fallthrough; 1069 case TBTT_NEIGHBOR_AP_BSSSID_S_SSID: 1070 rnr->channel_number = ap_info->channel_number; 1071 rnr->operating_class = ap_info->operting_class; 1072 qdf_mem_copy(&rnr->bssid, &data[1], QDF_MAC_ADDR_SIZE); 1073 qdf_mem_copy(&rnr->short_ssid, &data[7], SHORT_SSID_LEN); 1074 break; 1075 1076 default: 1077 scm_debug("Wrong fieldtype"); 1078 } 1079 1080 return QDF_STATUS_SUCCESS; 1081 } 1082 1083 static QDF_STATUS 1084 util_scan_parse_rnr_ie(struct scan_cache_entry *scan_entry, 1085 struct ie_header *ie) 1086 { 1087 uint32_t rnr_ie_len; 1088 uint16_t tbtt_count, tbtt_length, i, fieldtype, idx; 1089 uint8_t *data; 1090 struct neighbor_ap_info_field *neighbor_ap_info; 1091 1092 rnr_ie_len = ie->ie_len; 1093 data = (uint8_t *)ie + sizeof(struct ie_header); 1094 idx = scan_entry->rnr.count; 1095 1096 while (data < ((uint8_t *)ie + rnr_ie_len + 2)) { 1097 neighbor_ap_info = (struct neighbor_ap_info_field *)data; 1098 tbtt_count = neighbor_ap_info->tbtt_header.tbtt_info_count; 1099 tbtt_length = neighbor_ap_info->tbtt_header.tbtt_info_length; 1100 fieldtype = neighbor_ap_info->tbtt_header.tbbt_info_fieldtype; 1101 scm_debug("chan %d, opclass %d tbtt_cnt %d, tbtt_len %d, fieldtype %d", 1102 neighbor_ap_info->channel_number, 1103 neighbor_ap_info->operting_class, 1104 tbtt_count, tbtt_length, fieldtype); 1105 data += sizeof(struct neighbor_ap_info_field); 1106 1107 if (tbtt_count > TBTT_INFO_COUNT) 1108 break; 1109 1110 for (i = 0; i < (tbtt_count + 1) && 1111 data < ((uint8_t *)ie + rnr_ie_len + 2); i++) { 1112 if ((i < MAX_RNR_BSS) && (idx < MAX_RNR_BSS)) 1113 util_scan_update_rnr( 1114 &scan_entry->rnr.bss_info[idx++], 1115 neighbor_ap_info, 1116 data); 1117 data += tbtt_length; 1118 } 1119 } 1120 1121 scan_entry->rnr.count = idx; 1122 1123 return QDF_STATUS_SUCCESS; 1124 } 1125 1126 #ifdef WLAN_FEATURE_11BE_MLO 1127 static void 1128 util_scan_parse_t2lm_ie(struct scan_cache_entry *scan_params, 1129 struct extn_ie_header *extn_ie) 1130 { 1131 uint8_t t2lm_idx = 0; 1132 1133 if (extn_ie->ie_extn_id == WLAN_EXTN_ELEMID_T2LM) 1134 for (t2lm_idx = 0; t2lm_idx < WLAN_MAX_T2LM_IE; t2lm_idx++) { 1135 if (!scan_params->ie_list.t2lm[t2lm_idx]) { 1136 scan_params->ie_list.t2lm[t2lm_idx] = 1137 (uint8_t *)extn_ie; 1138 return; 1139 } 1140 } 1141 } 1142 #endif 1143 1144 #ifdef WLAN_FEATURE_11BE 1145 #ifdef WLAN_FEATURE_11BE_MLO 1146 static void util_scan_parse_ml_ie(struct scan_cache_entry *scan_params, 1147 struct extn_ie_header *extn_ie) 1148 { 1149 uint8_t *ml_ie; 1150 uint32_t ml_ie_len; 1151 enum wlan_ml_variant ml_variant; 1152 QDF_STATUS ret; 1153 1154 if (extn_ie->ie_extn_id != WLAN_EXTN_ELEMID_MULTI_LINK) 1155 return; 1156 1157 ml_ie = (uint8_t *)extn_ie; 1158 ml_ie_len = ml_ie[TAG_LEN_POS]; 1159 1160 /* Adding the size of IE header to ML IE length */ 1161 ml_ie_len += sizeof(struct ie_header); 1162 ret = util_get_mlie_variant(ml_ie, ml_ie_len, (int *)&ml_variant); 1163 if (ret) { 1164 scm_err("Unable to get ml variant"); 1165 return; 1166 } 1167 1168 switch (ml_variant) { 1169 case WLAN_ML_VARIANT_BASIC: 1170 scan_params->ie_list.multi_link_bv = (uint8_t *)extn_ie; 1171 break; 1172 case WLAN_ML_VARIANT_RECONFIG: 1173 scan_params->ie_list.multi_link_rv = (uint8_t *)extn_ie; 1174 break; 1175 default: 1176 break; 1177 } 1178 } 1179 #else 1180 static void util_scan_parse_ml_ie(struct scan_cache_entry *scan_params, 1181 struct extn_ie_header *extn_ie) 1182 { 1183 } 1184 #endif 1185 static void util_scan_parse_eht_ie(struct scan_cache_entry *scan_params, 1186 struct extn_ie_header *extn_ie) 1187 { 1188 switch (extn_ie->ie_extn_id) { 1189 case WLAN_EXTN_ELEMID_EHTCAP: 1190 scan_params->ie_list.ehtcap = (uint8_t *)extn_ie; 1191 break; 1192 case WLAN_EXTN_ELEMID_EHTOP: 1193 scan_params->ie_list.ehtop = (uint8_t *)extn_ie; 1194 break; 1195 default: 1196 break; 1197 } 1198 1199 util_scan_parse_ml_ie(scan_params, extn_ie); 1200 util_scan_parse_t2lm_ie(scan_params, extn_ie); 1201 } 1202 #else 1203 static void util_scan_parse_eht_ie(struct scan_cache_entry *scan_params, 1204 struct extn_ie_header *extn_ie) 1205 { 1206 } 1207 #endif 1208 1209 static QDF_STATUS 1210 util_scan_parse_extn_ie(struct scan_cache_entry *scan_params, 1211 struct ie_header *ie) 1212 { 1213 struct extn_ie_header *extn_ie = (struct extn_ie_header *) ie; 1214 1215 switch (extn_ie->ie_extn_id) { 1216 case WLAN_EXTN_ELEMID_MAX_CHAN_SWITCH_TIME: 1217 if (extn_ie->ie_len != WLAN_MAX_CHAN_SWITCH_TIME_IE_LEN) 1218 return QDF_STATUS_E_INVAL; 1219 scan_params->ie_list.mcst = (uint8_t *)ie; 1220 break; 1221 case WLAN_EXTN_ELEMID_SRP: 1222 if (extn_ie->ie_len > WLAN_MAX_SRP_IE_LEN) 1223 return QDF_STATUS_E_INVAL; 1224 scan_params->ie_list.srp = (uint8_t *)ie; 1225 break; 1226 case WLAN_EXTN_ELEMID_HECAP: 1227 if ((extn_ie->ie_len < WLAN_MIN_HECAP_IE_LEN) || 1228 (extn_ie->ie_len > WLAN_MAX_HECAP_IE_LEN)) 1229 return QDF_STATUS_E_INVAL; 1230 scan_params->ie_list.hecap = (uint8_t *)ie; 1231 break; 1232 case WLAN_EXTN_ELEMID_HEOP: 1233 if (extn_ie->ie_len > WLAN_MAX_HEOP_IE_LEN) 1234 return QDF_STATUS_E_INVAL; 1235 scan_params->ie_list.heop = (uint8_t *)ie; 1236 break; 1237 case WLAN_EXTN_ELEMID_ESP: 1238 scan_params->ie_list.esp = (uint8_t *)ie; 1239 break; 1240 case WLAN_EXTN_ELEMID_MUEDCA: 1241 if (extn_ie->ie_len > WLAN_MAX_MUEDCA_IE_LEN) 1242 return QDF_STATUS_E_INVAL; 1243 scan_params->ie_list.muedca = (uint8_t *)ie; 1244 break; 1245 case WLAN_EXTN_ELEMID_HE_6G_CAP: 1246 if (extn_ie->ie_len > WLAN_MAX_HE_6G_CAP_IE_LEN) 1247 return QDF_STATUS_E_INVAL; 1248 scan_params->ie_list.hecap_6g = (uint8_t *)ie; 1249 break; 1250 default: 1251 break; 1252 } 1253 util_scan_parse_eht_ie(scan_params, extn_ie); 1254 1255 return QDF_STATUS_SUCCESS; 1256 } 1257 1258 static QDF_STATUS 1259 util_scan_parse_vendor_ie(struct scan_cache_entry *scan_params, 1260 struct ie_header *ie) 1261 { 1262 if (!scan_params->ie_list.vendor) 1263 scan_params->ie_list.vendor = (uint8_t *)ie; 1264 1265 if (is_wpa_oui((uint8_t *)ie)) { 1266 scan_params->ie_list.wpa = (uint8_t *)ie; 1267 } else if (is_wps_oui((uint8_t *)ie)) { 1268 scan_params->ie_list.wps = (uint8_t *)ie; 1269 /* WCN IE should be a subset of WPS IE */ 1270 if (is_wcn_oui((uint8_t *)ie)) 1271 scan_params->ie_list.wcn = (uint8_t *)ie; 1272 } else if (is_wme_param((uint8_t *)ie)) { 1273 if (ie->ie_len > WLAN_VENDOR_WME_IE_LEN) 1274 return QDF_STATUS_E_INVAL; 1275 1276 scan_params->ie_list.wmeparam = (uint8_t *)ie; 1277 } else if (is_wme_info((uint8_t *)ie)) { 1278 scan_params->ie_list.wmeinfo = (uint8_t *)ie; 1279 } else if (is_atheros_oui((uint8_t *)ie)) { 1280 if (ie->ie_len > WLAN_VENDOR_ATHCAPS_IE_LEN) 1281 return QDF_STATUS_E_INVAL; 1282 1283 scan_params->ie_list.athcaps = (uint8_t *)ie; 1284 } else if (is_atheros_extcap_oui((uint8_t *)ie)) { 1285 if (ie->ie_len > WLAN_VENDOR_ATH_EXTCAP_IE_LEN) 1286 return QDF_STATUS_E_INVAL; 1287 1288 scan_params->ie_list.athextcaps = (uint8_t *)ie; 1289 } else if (is_sfa_oui((uint8_t *)ie)) { 1290 if (ie->ie_len > WLAN_VENDOR_SFA_IE_LEN) 1291 return QDF_STATUS_E_INVAL; 1292 1293 scan_params->ie_list.sfa = (uint8_t *)ie; 1294 } else if (is_p2p_oui((uint8_t *)ie)) { 1295 scan_params->ie_list.p2p = (uint8_t *)ie; 1296 } else if (is_qca_son_oui((uint8_t *)ie, 1297 QCA_OUI_WHC_AP_INFO_SUBTYPE)) { 1298 1299 scan_params->ie_list.sonadv = (uint8_t *)ie; 1300 } else if (is_ht_cap((uint8_t *)ie)) { 1301 /* we only care if there isn't already an HT IE (ANA) */ 1302 if (!scan_params->ie_list.htcap) { 1303 if (ie->ie_len != (WLAN_VENDOR_HT_IE_OFFSET_LEN + 1304 sizeof(struct htcap_cmn_ie))) 1305 return QDF_STATUS_E_INVAL; 1306 scan_params->ie_list.htcap = 1307 (uint8_t *)&(((struct wlan_vendor_ie_htcap *)ie)->ie); 1308 } 1309 } else if (is_ht_info((uint8_t *)ie)) { 1310 /* we only care if there isn't already an HT IE (ANA) */ 1311 if (!scan_params->ie_list.htinfo) { 1312 if (ie->ie_len != WLAN_VENDOR_HT_IE_OFFSET_LEN + 1313 sizeof(struct wlan_ie_htinfo_cmn)) 1314 return QDF_STATUS_E_INVAL; 1315 scan_params->ie_list.htinfo = 1316 (uint8_t *)&(((struct wlan_vendor_ie_htinfo *) 1317 ie)->hi_ie); 1318 } 1319 } else if (is_interop_vht((uint8_t *)ie) && 1320 !(scan_params->ie_list.vhtcap)) { 1321 uint8_t *vendor_ie = (uint8_t *)(ie); 1322 1323 if (ie->ie_len < ((WLAN_VENDOR_VHTCAP_IE_OFFSET + 1324 sizeof(struct wlan_ie_vhtcaps)) - 1325 sizeof(struct ie_header))) 1326 return QDF_STATUS_E_INVAL; 1327 vendor_ie = ((uint8_t *)(ie)) + WLAN_VENDOR_VHTCAP_IE_OFFSET; 1328 if (vendor_ie[1] != (sizeof(struct wlan_ie_vhtcaps)) - 1329 sizeof(struct ie_header)) 1330 return QDF_STATUS_E_INVAL; 1331 /* location where Interop Vht Cap IE and VHT OP IE Present */ 1332 scan_params->ie_list.vhtcap = (((uint8_t *)(ie)) + 1333 WLAN_VENDOR_VHTCAP_IE_OFFSET); 1334 if (ie->ie_len > ((WLAN_VENDOR_VHTCAP_IE_OFFSET + 1335 sizeof(struct wlan_ie_vhtcaps)) - 1336 sizeof(struct ie_header))) { 1337 if (ie->ie_len < ((WLAN_VENDOR_VHTOP_IE_OFFSET + 1338 sizeof(struct wlan_ie_vhtop)) - 1339 sizeof(struct ie_header))) 1340 return QDF_STATUS_E_INVAL; 1341 vendor_ie = ((uint8_t *)(ie)) + 1342 WLAN_VENDOR_VHTOP_IE_OFFSET; 1343 if (vendor_ie[1] != (sizeof(struct wlan_ie_vhtop) - 1344 sizeof(struct ie_header))) 1345 return QDF_STATUS_E_INVAL; 1346 scan_params->ie_list.vhtop = (((uint8_t *)(ie)) + 1347 WLAN_VENDOR_VHTOP_IE_OFFSET); 1348 } 1349 } else if (is_bwnss_oui((uint8_t *)ie)) { 1350 /* 1351 * Bandwidth-NSS map has sub-type & version. 1352 * hence copy data just after version byte 1353 */ 1354 if (ie->ie_len > WLAN_BWNSS_MAP_OFFSET) 1355 scan_params->ie_list.bwnss_map = (((uint8_t *)ie) + 8); 1356 } else if (is_mbo_oce_oui((uint8_t *)ie)) { 1357 scan_params->ie_list.mbo_oce = (uint8_t *)ie; 1358 } else if (is_extender_oui((uint8_t *)ie)) { 1359 scan_params->ie_list.extender = (uint8_t *)ie; 1360 } else if (is_adaptive_11r_oui((uint8_t *)ie)) { 1361 if ((ie->ie_len < OUI_LENGTH) || 1362 (ie->ie_len > MAX_ADAPTIVE_11R_IE_LEN)) 1363 return QDF_STATUS_E_INVAL; 1364 1365 scan_params->ie_list.adaptive_11r = (uint8_t *)ie + 1366 sizeof(struct ie_header); 1367 } else if (is_sae_single_pmk_oui((uint8_t *)ie)) { 1368 if ((ie->ie_len < OUI_LENGTH) || 1369 (ie->ie_len > MAX_SAE_SINGLE_PMK_IE_LEN)) { 1370 scm_debug("Invalid sae single pmk OUI"); 1371 return QDF_STATUS_E_INVAL; 1372 } 1373 scan_params->ie_list.single_pmk = (uint8_t *)ie + 1374 sizeof(struct ie_header); 1375 } else if (is_qcn_oui((uint8_t *)ie)) { 1376 scan_params->ie_list.qcn = (uint8_t *)ie; 1377 } 1378 1379 return QDF_STATUS_SUCCESS; 1380 } 1381 1382 static QDF_STATUS 1383 util_scan_populate_bcn_ie_list(struct wlan_objmgr_pdev *pdev, 1384 struct scan_cache_entry *scan_params, 1385 qdf_freq_t *chan_freq, uint8_t band_mask) 1386 { 1387 struct ie_header *ie, *sub_ie; 1388 uint32_t ie_len, sub_ie_len; 1389 QDF_STATUS status; 1390 uint8_t chan_idx; 1391 struct wlan_scan_obj *scan_obj; 1392 struct wlan_objmgr_psoc *psoc; 1393 uint8_t tpe_idx = 0; 1394 1395 psoc = wlan_pdev_get_psoc(pdev); 1396 if (!psoc) { 1397 scm_err("psoc is NULL"); 1398 return QDF_STATUS_E_INVAL; 1399 } 1400 1401 scan_obj = wlan_psoc_get_scan_obj(psoc); 1402 if (!scan_obj) { 1403 scm_err("scan_obj is NULL"); 1404 return QDF_STATUS_E_INVAL; 1405 } 1406 1407 ie_len = util_scan_entry_ie_len(scan_params); 1408 ie = (struct ie_header *) 1409 util_scan_entry_ie_data(scan_params); 1410 1411 while (ie_len >= sizeof(struct ie_header)) { 1412 ie_len -= sizeof(struct ie_header); 1413 1414 if (!ie->ie_len) { 1415 ie += 1; 1416 continue; 1417 } 1418 1419 if (ie_len < ie->ie_len) { 1420 if (scan_obj->allow_bss_with_incomplete_ie) { 1421 scm_debug(QDF_MAC_ADDR_FMT": Scan allowed with incomplete corrupted IE:%x, ie_len: %d, ie->ie_len: %d, stop processing further", 1422 QDF_MAC_ADDR_REF(scan_params->bssid.bytes), 1423 ie->ie_id, ie_len, ie->ie_len); 1424 break; 1425 } 1426 scm_debug(QDF_MAC_ADDR_FMT": Scan not allowed with incomplete corrupted IE:%x, ie_len: %d, ie->ie_len: %d, stop processing further", 1427 QDF_MAC_ADDR_REF(scan_params->bssid.bytes), 1428 ie->ie_id, ie_len, ie->ie_len); 1429 return QDF_STATUS_E_INVAL; 1430 } 1431 1432 switch (ie->ie_id) { 1433 case WLAN_ELEMID_SSID: 1434 if (ie->ie_len > (sizeof(struct ie_ssid) - 1435 sizeof(struct ie_header))) 1436 goto err; 1437 scan_params->ie_list.ssid = (uint8_t *)ie; 1438 break; 1439 case WLAN_ELEMID_RATES: 1440 if (ie->ie_len > WLAN_SUPPORTED_RATES_IE_MAX_LEN) 1441 goto err; 1442 scan_params->ie_list.rates = (uint8_t *)ie; 1443 break; 1444 case WLAN_ELEMID_DSPARMS: 1445 if (ie->ie_len != WLAN_DS_PARAM_IE_MAX_LEN) 1446 return QDF_STATUS_E_INVAL; 1447 scan_params->ie_list.ds_param = (uint8_t *)ie; 1448 chan_idx = ((struct ds_ie *)ie)->cur_chan; 1449 *chan_freq = wlan_reg_chan_band_to_freq(pdev, chan_idx, 1450 band_mask); 1451 /* Drop if invalid freq */ 1452 if (scan_obj->drop_bcn_on_invalid_freq && 1453 !wlan_reg_is_freq_enabled(pdev, 1454 *chan_freq, 1455 REG_CURRENT_PWR_MODE)) { 1456 scm_debug(QDF_MAC_ADDR_FMT": Drop as invalid chan %d in DS IE, freq %d, band_mask %d", 1457 QDF_MAC_ADDR_REF( 1458 scan_params->bssid.bytes), 1459 chan_idx, *chan_freq, band_mask); 1460 return QDF_STATUS_E_INVAL; 1461 } 1462 break; 1463 case WLAN_ELEMID_TIM: 1464 if (ie->ie_len < WLAN_TIM_IE_MIN_LENGTH) 1465 goto err; 1466 scan_params->ie_list.tim = (uint8_t *)ie; 1467 scan_params->dtim_period = 1468 ((struct wlan_tim_ie *)ie)->tim_period; 1469 break; 1470 case WLAN_ELEMID_COUNTRY: 1471 if (ie->ie_len < WLAN_COUNTRY_IE_MIN_LEN) 1472 goto err; 1473 scan_params->ie_list.country = (uint8_t *)ie; 1474 break; 1475 case WLAN_ELEMID_QBSS_LOAD: 1476 if (ie->ie_len != sizeof(struct qbss_load_ie) - 1477 sizeof(struct ie_header)) { 1478 /* 1479 * Expected QBSS IE length is 5Bytes; For some 1480 * old cisco AP, QBSS IE length is 4Bytes, which 1481 * doesn't match with latest spec, So ignore 1482 * QBSS IE in such case. 1483 */ 1484 break; 1485 } 1486 scan_params->ie_list.qbssload = (uint8_t *)ie; 1487 break; 1488 case WLAN_ELEMID_CHANSWITCHANN: 1489 if (ie->ie_len != WLAN_CSA_IE_MAX_LEN) 1490 goto err; 1491 scan_params->ie_list.csa = (uint8_t *)ie; 1492 break; 1493 case WLAN_ELEMID_IBSSDFS: 1494 if (ie->ie_len < WLAN_IBSSDFS_IE_MIN_LEN) 1495 goto err; 1496 scan_params->ie_list.ibssdfs = (uint8_t *)ie; 1497 break; 1498 case WLAN_ELEMID_QUIET: 1499 if (ie->ie_len != WLAN_QUIET_IE_MAX_LEN) 1500 goto err; 1501 scan_params->ie_list.quiet = (uint8_t *)ie; 1502 break; 1503 case WLAN_ELEMID_ERP: 1504 if (ie->ie_len != (sizeof(struct erp_ie) - 1505 sizeof(struct ie_header))) 1506 goto err; 1507 scan_params->erp = ((struct erp_ie *)ie)->value; 1508 break; 1509 case WLAN_ELEMID_HTCAP_ANA: 1510 if (ie->ie_len == sizeof(struct htcap_cmn_ie)) { 1511 scan_params->ie_list.htcap = 1512 (uint8_t *)&(((struct htcap_ie *)ie)->ie); 1513 } 1514 break; 1515 case WLAN_ELEMID_RSN: 1516 /* 1517 * For security cert TC, RSNIE length can be 1 but if 1518 * beacon is dropped, old entry will remain in scan 1519 * cache and cause cert TC failure as connection with 1520 * old entry with valid RSN IE will pass. 1521 * So instead of dropping the frame, do not store the 1522 * RSN pointer so that old entry is overwritten. 1523 */ 1524 if (ie->ie_len >= WLAN_RSN_IE_MIN_LEN) 1525 scan_params->ie_list.rsn = (uint8_t *)ie; 1526 break; 1527 case WLAN_ELEMID_XRATES: 1528 if (ie->ie_len > WLAN_EXT_SUPPORTED_RATES_IE_MAX_LEN) 1529 goto err; 1530 scan_params->ie_list.xrates = (uint8_t *)ie; 1531 break; 1532 case WLAN_ELEMID_EXTCHANSWITCHANN: 1533 if (ie->ie_len != WLAN_XCSA_IE_MAX_LEN) 1534 goto err; 1535 scan_params->ie_list.xcsa = (uint8_t *)ie; 1536 break; 1537 case WLAN_ELEMID_SECCHANOFFSET: 1538 if (ie->ie_len != WLAN_SECCHANOFF_IE_MAX_LEN) 1539 goto err; 1540 scan_params->ie_list.secchanoff = (uint8_t *)ie; 1541 break; 1542 case WLAN_ELEMID_HTINFO_ANA: 1543 if (ie->ie_len != sizeof(struct wlan_ie_htinfo_cmn)) 1544 goto err; 1545 scan_params->ie_list.htinfo = 1546 (uint8_t *)&(((struct wlan_ie_htinfo *) ie)->hi_ie); 1547 chan_idx = ((struct wlan_ie_htinfo_cmn *) 1548 (scan_params->ie_list.htinfo))->hi_ctrlchannel; 1549 *chan_freq = wlan_reg_chan_band_to_freq(pdev, chan_idx, 1550 band_mask); 1551 /* Drop if invalid freq */ 1552 if (scan_obj->drop_bcn_on_invalid_freq && 1553 !wlan_reg_is_freq_enabled(pdev, 1554 *chan_freq, 1555 REG_CURRENT_PWR_MODE)) { 1556 scm_debug_rl(QDF_MAC_ADDR_FMT": Drop as invalid channel %d freq %d in HT_INFO IE", 1557 QDF_MAC_ADDR_REF(scan_params->bssid.bytes), 1558 chan_idx, *chan_freq); 1559 return QDF_STATUS_E_INVAL; 1560 } 1561 break; 1562 case WLAN_ELEMID_WAPI: 1563 if (ie->ie_len < WLAN_WAPI_IE_MIN_LEN) 1564 goto err; 1565 scan_params->ie_list.wapi = (uint8_t *)ie; 1566 break; 1567 case WLAN_ELEMID_XCAPS: 1568 if (ie->ie_len > WLAN_EXTCAP_IE_MAX_LEN) 1569 goto err; 1570 scan_params->ie_list.extcaps = (uint8_t *)ie; 1571 break; 1572 case WLAN_ELEMID_VHTCAP: 1573 if (ie->ie_len != (sizeof(struct wlan_ie_vhtcaps) - 1574 sizeof(struct ie_header))) 1575 goto err; 1576 scan_params->ie_list.vhtcap = (uint8_t *)ie; 1577 break; 1578 case WLAN_ELEMID_VHTOP: 1579 if (ie->ie_len != (sizeof(struct wlan_ie_vhtop) - 1580 sizeof(struct ie_header))) 1581 goto err; 1582 scan_params->ie_list.vhtop = (uint8_t *)ie; 1583 break; 1584 case WLAN_ELEMID_OP_MODE_NOTIFY: 1585 if (ie->ie_len != WLAN_OPMODE_IE_MAX_LEN) 1586 goto err; 1587 scan_params->ie_list.opmode = (uint8_t *)ie; 1588 break; 1589 case WLAN_ELEMID_MOBILITY_DOMAIN: 1590 if (ie->ie_len != WLAN_MOBILITY_DOMAIN_IE_MAX_LEN) 1591 goto err; 1592 scan_params->ie_list.mdie = (uint8_t *)ie; 1593 break; 1594 case WLAN_ELEMID_VENDOR: 1595 status = util_scan_parse_vendor_ie(scan_params, 1596 ie); 1597 if (QDF_IS_STATUS_ERROR(status)) 1598 goto err_status; 1599 break; 1600 case WLAN_ELEMID_VHT_TX_PWR_ENVLP: 1601 if (ie->ie_len < WLAN_TPE_IE_MIN_LEN) 1602 goto err; 1603 if (tpe_idx >= WLAN_MAX_NUM_TPE_IE) 1604 goto err; 1605 scan_params->ie_list.tpe[tpe_idx++] = (uint8_t *)ie; 1606 break; 1607 case WLAN_ELEMID_CHAN_SWITCH_WRAP: 1608 scan_params->ie_list.cswrp = (uint8_t *)ie; 1609 /* Go to next sub IE */ 1610 sub_ie = (struct ie_header *) 1611 (((uint8_t *)ie) + sizeof(struct ie_header)); 1612 sub_ie_len = ie->ie_len; 1613 status = 1614 util_scan_parse_chan_switch_wrapper_ie( 1615 scan_params, sub_ie, sub_ie_len); 1616 if (QDF_IS_STATUS_ERROR(status)) { 1617 goto err_status; 1618 } 1619 break; 1620 case WLAN_ELEMID_FILS_INDICATION: 1621 if (ie->ie_len < WLAN_FILS_INDICATION_IE_MIN_LEN) 1622 goto err; 1623 scan_params->ie_list.fils_indication = (uint8_t *)ie; 1624 break; 1625 case WLAN_ELEMID_RSNXE: 1626 if (!ie->ie_len) 1627 goto err; 1628 scan_params->ie_list.rsnxe = (uint8_t *)ie; 1629 break; 1630 case WLAN_ELEMID_EXTN_ELEM: 1631 status = util_scan_parse_extn_ie(scan_params, ie); 1632 if (QDF_IS_STATUS_ERROR(status)) 1633 goto err_status; 1634 break; 1635 case WLAN_ELEMID_REDUCED_NEIGHBOR_REPORT: 1636 if (ie->ie_len < WLAN_RNR_IE_MIN_LEN) 1637 goto err; 1638 scan_params->ie_list.rnrie = (uint8_t *)ie; 1639 status = util_scan_parse_rnr_ie(scan_params, ie); 1640 if (QDF_IS_STATUS_ERROR(status)) 1641 goto err_status; 1642 break; 1643 default: 1644 break; 1645 } 1646 1647 /* Consume info element */ 1648 ie_len -= ie->ie_len; 1649 /* Go to next IE */ 1650 ie = (struct ie_header *) 1651 (((uint8_t *) ie) + 1652 sizeof(struct ie_header) + 1653 ie->ie_len); 1654 } 1655 1656 return QDF_STATUS_SUCCESS; 1657 1658 err: 1659 status = QDF_STATUS_E_INVAL; 1660 err_status: 1661 scm_debug(QDF_MAC_ADDR_FMT ": failed to parse IE - id: %d, len: %d", 1662 QDF_MAC_ADDR_REF(scan_params->bssid.bytes), 1663 ie->ie_id, ie->ie_len); 1664 1665 return status; 1666 } 1667 1668 /** 1669 * util_scan_update_esp_data: update ESP params from beacon/probe response 1670 * @esp_information: pointer to wlan_esp_information 1671 * @scan_entry: new received entry 1672 * 1673 * The Estimated Service Parameters element is 1674 * used by a AP to provide information to another STA which 1675 * can then use the information as input to an algorithm to 1676 * generate an estimate of throughput between the two STAs. 1677 * The ESP Information List field contains from 1 to 4 ESP 1678 * Information fields(each field 24 bits), each corresponding 1679 * to an access category for which estimated service parameters 1680 * information is provided. 1681 * 1682 * Return: None 1683 */ 1684 static void util_scan_update_esp_data(struct wlan_esp_ie *esp_information, 1685 struct scan_cache_entry *scan_entry) 1686 { 1687 1688 uint8_t *data; 1689 int i = 0; 1690 uint64_t total_elements; 1691 struct wlan_esp_info *esp_info; 1692 struct wlan_esp_ie *esp_ie; 1693 1694 esp_ie = (struct wlan_esp_ie *) 1695 util_scan_entry_esp_info(scan_entry); 1696 1697 total_elements = esp_ie->esp_len; 1698 data = (uint8_t *)esp_ie + 3; 1699 do_div(total_elements, ESP_INFORMATION_LIST_LENGTH); 1700 1701 if (total_elements > MAX_ESP_INFORMATION_FIELD) { 1702 scm_err("No of Air time fractions are greater than supported"); 1703 return; 1704 } 1705 1706 for (i = 0; i < total_elements && 1707 data < ((uint8_t *)esp_ie + esp_ie->esp_len + 3); i++) { 1708 esp_info = (struct wlan_esp_info *)data; 1709 if (esp_info->access_category == ESP_AC_BK) { 1710 qdf_mem_copy(&esp_information->esp_info_AC_BK, 1711 data, 3); 1712 data = data + ESP_INFORMATION_LIST_LENGTH; 1713 continue; 1714 } 1715 if (esp_info->access_category == ESP_AC_BE) { 1716 qdf_mem_copy(&esp_information->esp_info_AC_BE, 1717 data, 3); 1718 data = data + ESP_INFORMATION_LIST_LENGTH; 1719 continue; 1720 } 1721 if (esp_info->access_category == ESP_AC_VI) { 1722 qdf_mem_copy(&esp_information->esp_info_AC_VI, 1723 data, 3); 1724 data = data + ESP_INFORMATION_LIST_LENGTH; 1725 continue; 1726 } 1727 if (esp_info->access_category == ESP_AC_VO) { 1728 qdf_mem_copy(&esp_information->esp_info_AC_VO, 1729 data, 3); 1730 data = data + ESP_INFORMATION_LIST_LENGTH; 1731 break; 1732 } 1733 } 1734 } 1735 1736 /** 1737 * util_scan_scm_update_bss_with_esp_data: calculate estimated air time 1738 * fraction 1739 * @scan_entry: new received entry 1740 * 1741 * This function process all Access category ESP params and provide 1742 * best effort air time fraction. 1743 * If best effort is not available, it will choose VI, VO and BK in sequence 1744 * 1745 */ 1746 static void util_scan_scm_update_bss_with_esp_data( 1747 struct scan_cache_entry *scan_entry) 1748 { 1749 uint8_t air_time_fraction = 0; 1750 struct wlan_esp_ie esp_information; 1751 1752 if (!scan_entry->ie_list.esp) 1753 return; 1754 1755 util_scan_update_esp_data(&esp_information, scan_entry); 1756 1757 /* 1758 * If the ESP metric is transmitting multiple airtime fractions, then 1759 * follow the sequence AC_BE, AC_VI, AC_VO, AC_BK and pick whichever is 1760 * the first one available 1761 */ 1762 if (esp_information.esp_info_AC_BE.access_category 1763 == ESP_AC_BE) 1764 air_time_fraction = 1765 esp_information.esp_info_AC_BE. 1766 estimated_air_fraction; 1767 else if (esp_information.esp_info_AC_VI.access_category 1768 == ESP_AC_VI) 1769 air_time_fraction = 1770 esp_information.esp_info_AC_VI. 1771 estimated_air_fraction; 1772 else if (esp_information.esp_info_AC_VO.access_category 1773 == ESP_AC_VO) 1774 air_time_fraction = 1775 esp_information.esp_info_AC_VO. 1776 estimated_air_fraction; 1777 else if (esp_information.esp_info_AC_BK.access_category 1778 == ESP_AC_BK) 1779 air_time_fraction = 1780 esp_information.esp_info_AC_BK. 1781 estimated_air_fraction; 1782 scan_entry->air_time_fraction = air_time_fraction; 1783 } 1784 1785 /** 1786 * util_scan_scm_calc_nss_supported_by_ap() - finds out nss from AP 1787 * @scan_params: new received entry 1788 * 1789 * Return: number of nss advertised by AP 1790 */ 1791 static int util_scan_scm_calc_nss_supported_by_ap( 1792 struct scan_cache_entry *scan_params) 1793 { 1794 struct htcap_cmn_ie *htcap; 1795 struct wlan_ie_vhtcaps *vhtcaps; 1796 uint8_t *he_cap; 1797 uint8_t *end_ptr = NULL; 1798 uint16_t rx_mcs_map = 0; 1799 uint8_t *mcs_map_offset; 1800 1801 htcap = (struct htcap_cmn_ie *) 1802 util_scan_entry_htcap(scan_params); 1803 vhtcaps = (struct wlan_ie_vhtcaps *) 1804 util_scan_entry_vhtcap(scan_params); 1805 he_cap = util_scan_entry_hecap(scan_params); 1806 1807 if (he_cap) { 1808 /* Using rx mcs map related to 80MHz or lower as in some 1809 * cases higher mcs may support lesser NSS than that 1810 * of lowe mcs. Thus giving max NSS capability. 1811 */ 1812 end_ptr = he_cap + he_cap[1] + sizeof(struct ie_header); 1813 mcs_map_offset = (he_cap + sizeof(struct extn_ie_header) + 1814 WLAN_HE_MACCAP_LEN + WLAN_HE_PHYCAP_LEN); 1815 if ((mcs_map_offset + WLAN_HE_MCS_MAP_LEN) <= end_ptr) { 1816 rx_mcs_map = *(uint16_t *)mcs_map_offset; 1817 } else { 1818 rx_mcs_map = WLAN_INVALID_RX_MCS_MAP; 1819 scm_debug("mcs_map_offset exceeds he cap len"); 1820 } 1821 } else if (vhtcaps) { 1822 rx_mcs_map = vhtcaps->rx_mcs_map; 1823 } 1824 1825 if (he_cap || vhtcaps) { 1826 if ((rx_mcs_map & 0xC000) != 0xC000) 1827 return 8; 1828 1829 if ((rx_mcs_map & 0x3000) != 0x3000) 1830 return 7; 1831 1832 if ((rx_mcs_map & 0x0C00) != 0x0C00) 1833 return 6; 1834 1835 if ((rx_mcs_map & 0x0300) != 0x0300) 1836 return 5; 1837 1838 if ((rx_mcs_map & 0x00C0) != 0x00C0) 1839 return 4; 1840 1841 if ((rx_mcs_map & 0x0030) != 0x0030) 1842 return 3; 1843 1844 if ((rx_mcs_map & 0x000C) != 0x000C) 1845 return 2; 1846 } else if (htcap) { 1847 if (htcap->mcsset[3]) 1848 return 4; 1849 1850 if (htcap->mcsset[2]) 1851 return 3; 1852 1853 if (htcap->mcsset[1]) 1854 return 2; 1855 1856 } 1857 return 1; 1858 } 1859 1860 #ifdef WLAN_DFS_CHAN_HIDDEN_SSID 1861 QDF_STATUS 1862 util_scan_add_hidden_ssid(struct wlan_objmgr_pdev *pdev, qdf_nbuf_t bcnbuf) 1863 { 1864 struct wlan_frame_hdr *hdr; 1865 struct wlan_bcn_frame *bcn; 1866 struct wlan_scan_obj *scan_obj; 1867 struct wlan_ssid *conf_ssid; 1868 struct ie_header *ie; 1869 uint32_t frame_len = qdf_nbuf_len(bcnbuf); 1870 uint16_t bcn_ie_offset, ssid_ie_start_offset, ssid_ie_end_offset; 1871 uint16_t tmplen, ie_length; 1872 uint8_t *pbeacon, *tmp; 1873 bool set_ssid_flag = false; 1874 struct ie_ssid ssid = {0}; 1875 uint8_t pdev_id; 1876 1877 if (!pdev) { 1878 scm_warn("pdev: 0x%pK is NULL", pdev); 1879 return QDF_STATUS_E_NULL_VALUE; 1880 } 1881 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); 1882 scan_obj = wlan_pdev_get_scan_obj(pdev); 1883 if (!scan_obj) { 1884 scm_warn("null scan_obj"); 1885 return QDF_STATUS_E_NULL_VALUE; 1886 } 1887 1888 conf_ssid = &scan_obj->pdev_info[pdev_id].conf_ssid; 1889 1890 hdr = (struct wlan_frame_hdr *)qdf_nbuf_data(bcnbuf); 1891 1892 /* received bssid does not match configured bssid */ 1893 if (qdf_mem_cmp(hdr->i_addr3, scan_obj->pdev_info[pdev_id].conf_bssid, 1894 QDF_MAC_ADDR_SIZE) || 1895 conf_ssid->length == 0) { 1896 return QDF_STATUS_SUCCESS; 1897 } 1898 1899 bcn = (struct wlan_bcn_frame *)(qdf_nbuf_data(bcnbuf) + sizeof(*hdr)); 1900 pbeacon = (uint8_t *)bcn; 1901 1902 ie = (struct ie_header *)(pbeacon + 1903 offsetof(struct wlan_bcn_frame, ie)); 1904 1905 bcn_ie_offset = offsetof(struct wlan_bcn_frame, ie); 1906 ie_length = (uint16_t)(frame_len - sizeof(*hdr) - 1907 bcn_ie_offset); 1908 1909 while (ie_length >= sizeof(struct ie_header)) { 1910 ie_length -= sizeof(struct ie_header); 1911 1912 bcn_ie_offset += sizeof(struct ie_header); 1913 1914 if (ie_length < ie->ie_len) { 1915 scm_debug("Incomplete corrupted IE:%x", ie->ie_id); 1916 return QDF_STATUS_E_INVAL; 1917 } 1918 if (ie->ie_id == WLAN_ELEMID_SSID) { 1919 if (ie->ie_len > (sizeof(struct ie_ssid) - 1920 sizeof(struct ie_header))) { 1921 return QDF_STATUS_E_INVAL; 1922 } 1923 ssid.ssid_id = ie->ie_id; 1924 ssid.ssid_len = ie->ie_len; 1925 1926 if (ssid.ssid_len) 1927 qdf_mem_copy(ssid.ssid, 1928 ie + sizeof(struct ie_header), 1929 ssid.ssid_len); 1930 1931 if (util_scan_is_hidden_ssid(&ssid)) { 1932 set_ssid_flag = true; 1933 ssid_ie_start_offset = bcn_ie_offset - 1934 sizeof(struct ie_header); 1935 ssid_ie_end_offset = bcn_ie_offset + 1936 ie->ie_len; 1937 } 1938 } 1939 if (ie->ie_len == 0) { 1940 ie += 1; /* next IE */ 1941 continue; 1942 } 1943 if (ie->ie_id == WLAN_ELEMID_VENDOR && 1944 is_wps_oui((uint8_t *)ie)) { 1945 set_ssid_flag = false; 1946 break; 1947 } 1948 /* Consume info element */ 1949 ie_length -= ie->ie_len; 1950 /* Go to next IE */ 1951 ie = (struct ie_header *)(((uint8_t *)ie) + 1952 sizeof(struct ie_header) + 1953 ie->ie_len); 1954 } 1955 1956 if (set_ssid_flag) { 1957 /* Hidden SSID if the Length is 0 */ 1958 if (!ssid.ssid_len) { 1959 /* increase the taillength by length of ssid */ 1960 if (qdf_nbuf_put_tail(bcnbuf, 1961 conf_ssid->length) == NULL) { 1962 scm_debug("No enough tailroom"); 1963 return QDF_STATUS_E_NOMEM; 1964 } 1965 /* 1966 * "qdf_nbuf_put_tail" might change the data pointer of 1967 * the skb. Therefore use the new data area. 1968 */ 1969 pbeacon = (qdf_nbuf_data(bcnbuf) + sizeof(*hdr)); 1970 /* length of the buffer to be copied */ 1971 tmplen = frame_len - 1972 sizeof(*hdr) - ssid_ie_end_offset; 1973 /* 1974 * tmp memory to copy the beacon info 1975 * after ssid ie. 1976 */ 1977 tmp = qdf_mem_malloc(tmplen * sizeof(u_int8_t)); 1978 if (!tmp) 1979 return QDF_STATUS_E_NOMEM; 1980 1981 /* Copy beacon data after ssid ie to tmp */ 1982 qdf_nbuf_copy_bits(bcnbuf, (sizeof(*hdr) + 1983 ssid_ie_end_offset), tmplen, tmp); 1984 /* Add ssid length */ 1985 *(pbeacon + (ssid_ie_start_offset + 1)) 1986 = conf_ssid->length; 1987 /* Insert the SSID string */ 1988 qdf_mem_copy((pbeacon + ssid_ie_end_offset), 1989 conf_ssid->ssid, conf_ssid->length); 1990 /* Copy rest of the beacon data */ 1991 qdf_mem_copy((pbeacon + ssid_ie_end_offset + 1992 conf_ssid->length), tmp, tmplen); 1993 qdf_mem_free(tmp); 1994 1995 /* Hidden ssid with all 0's */ 1996 } else if (ssid.ssid_len == conf_ssid->length) { 1997 /* Insert the SSID string */ 1998 qdf_mem_copy((pbeacon + ssid_ie_start_offset + 1999 sizeof(struct ie_header)), 2000 conf_ssid->ssid, conf_ssid->length); 2001 } else { 2002 scm_debug("mismatch in hidden ssid length"); 2003 return QDF_STATUS_E_INVAL; 2004 } 2005 } 2006 return QDF_STATUS_SUCCESS; 2007 } 2008 #endif /* WLAN_DFS_CHAN_HIDDEN_SSID */ 2009 2010 #ifdef WLAN_ADAPTIVE_11R 2011 /** 2012 * scm_fill_adaptive_11r_cap() - Check if the AP supports adaptive 11r 2013 * @scan_entry: Pointer to the scan entry 2014 * 2015 * Return: true if adaptive 11r is advertised else false 2016 */ 2017 static void scm_fill_adaptive_11r_cap(struct scan_cache_entry *scan_entry) 2018 { 2019 uint8_t *ie; 2020 uint8_t data; 2021 bool adaptive_11r; 2022 2023 ie = util_scan_entry_adaptive_11r(scan_entry); 2024 if (!ie) 2025 return; 2026 2027 data = *(ie + OUI_LENGTH); 2028 adaptive_11r = (data & 0x1) ? true : false; 2029 2030 scan_entry->adaptive_11r_ap = adaptive_11r; 2031 } 2032 #else 2033 static void scm_fill_adaptive_11r_cap(struct scan_cache_entry *scan_entry) 2034 { 2035 scan_entry->adaptive_11r_ap = false; 2036 } 2037 #endif 2038 2039 static void util_scan_set_security(struct scan_cache_entry *scan_params) 2040 { 2041 if (util_scan_entry_wpa(scan_params)) 2042 scan_params->security_type |= SCAN_SECURITY_TYPE_WPA; 2043 2044 if (util_scan_entry_rsn(scan_params)) 2045 scan_params->security_type |= SCAN_SECURITY_TYPE_RSN; 2046 if (util_scan_entry_wapi(scan_params)) 2047 scan_params->security_type |= SCAN_SECURITY_TYPE_WAPI; 2048 2049 if (!scan_params->security_type && 2050 scan_params->cap_info.wlan_caps.privacy) 2051 scan_params->security_type |= SCAN_SECURITY_TYPE_WEP; 2052 } 2053 2054 #ifdef WLAN_FEATURE_11BE_MLO 2055 /* 2056 * Multi link IE field offsets 2057 * ------------------------------------------------------------------------ 2058 * | EID(1) | Len (1) | EID_EXT (1) | ML_CONTROL (2) | CMN_INFO (var) | ... | 2059 * ------------------------------------------------------------------------ 2060 */ 2061 #define ML_CONTROL_OFFSET 3 2062 #define ML_CMN_INFO_OFFSET ML_CONTROL_OFFSET + 2 2063 2064 #define CMN_INFO_LINK_ID_PRESENT_BIT BIT(4) 2065 #define LINK_INFO_MAC_ADDR_PRESENT_BIT BIT(5) 2066 2067 /* This function is implemented as per IEEE802.11be D1.0, there is no difference 2068 * in presence bitmap for beacon, probe response and probe request frames. 2069 * This code is to be revisited for future drafts if the presence bitmap values 2070 * changes for the beacon, probe response and probe request frames. 2071 */ 2072 static uint8_t util_get_link_info_offset(uint8_t *ml_ie, bool *is_ml_ie_valid) 2073 { 2074 qdf_size_t ml_ie_len = 0; 2075 qdf_size_t parsed_ie_len = 0; 2076 struct wlan_ie_multilink *mlie_fixed; 2077 uint16_t mlcontrol; 2078 uint16_t presencebm; 2079 qdf_size_t actual_len; 2080 2081 if (!ml_ie) { 2082 scm_err("ml_ie is null"); 2083 return 0; 2084 } 2085 2086 if (!is_ml_ie_valid) { 2087 scm_err_rl("is_ml_ie_valid is null"); 2088 return 0; 2089 } 2090 2091 ml_ie_len = ml_ie[TAG_LEN_POS]; 2092 if (!ml_ie_len) { 2093 scm_err("ml_ie_len is zero"); 2094 return 0; 2095 } 2096 2097 if (ml_ie_len < sizeof(struct wlan_ie_multilink)) { 2098 scm_err_rl("Length %zu octets is smaller than required for the fixed portion of Multi-Link element (%zu octets)", 2099 ml_ie_len, sizeof(struct wlan_ie_multilink)); 2100 return 0; 2101 } 2102 2103 mlie_fixed = (struct wlan_ie_multilink *)ml_ie; 2104 mlcontrol = le16toh(mlie_fixed->mlcontrol); 2105 presencebm = QDF_GET_BITS(mlcontrol, WLAN_ML_CTRL_PBM_IDX, 2106 WLAN_ML_CTRL_PBM_BITS); 2107 2108 parsed_ie_len += sizeof(*mlie_fixed); 2109 2110 parsed_ie_len += WLAN_ML_BV_CINFO_LENGTH_SIZE; 2111 parsed_ie_len += QDF_MAC_ADDR_SIZE; 2112 2113 /* Check if Link ID info is present */ 2114 if (presencebm & WLAN_ML_BV_CTRL_PBM_LINKIDINFO_P) 2115 parsed_ie_len += WLAN_ML_BV_CINFO_LINKIDINFO_SIZE; 2116 2117 /* Check if BSS parameter change count is present */ 2118 if (presencebm & WLAN_ML_BV_CTRL_PBM_BSSPARAMCHANGECNT_P) 2119 parsed_ie_len += WLAN_ML_BSSPARAMCHNGCNT_SIZE; 2120 2121 /* Check if Medium Sync Delay Info is present */ 2122 if (presencebm & WLAN_ML_BV_CTRL_PBM_MEDIUMSYNCDELAYINFO_P) 2123 parsed_ie_len += WLAN_ML_BV_CINFO_MEDMSYNCDELAYINFO_SIZE; 2124 2125 /* Check if EML cap is present */ 2126 if (presencebm & WLAN_ML_BV_CTRL_PBM_EMLCAP_P) 2127 parsed_ie_len += WLAN_ML_BV_CINFO_EMLCAP_SIZE; 2128 2129 /* Check if MLD cap and op is present */ 2130 if (presencebm & WLAN_ML_BV_CTRL_PBM_MLDCAPANDOP_P) 2131 parsed_ie_len += WLAN_ML_BV_CINFO_MLDCAPANDOP_SIZE; 2132 2133 /* Check if MLD ID is present */ 2134 if (presencebm & WLAN_ML_BV_CTRL_PBM_MLDID_P) 2135 parsed_ie_len += WLAN_ML_BV_CINFO_MLDID_SIZE; 2136 2137 /* Check if Extended MLD Cap and Op is present */ 2138 if (presencebm & WLAN_ML_BV_CTRL_PBM_EXT_MLDCAPANDOP_P) 2139 parsed_ie_len += WLAN_ML_BV_CINFO_EXT_MLDCAPANDOP_SIZE; 2140 2141 /* Offset calculation starts from the beginning of the ML IE (including 2142 * EID) hence, adding the size of IE header to ML IE length. 2143 */ 2144 actual_len = ml_ie_len + sizeof(struct ie_header); 2145 if (parsed_ie_len <= actual_len) { 2146 *is_ml_ie_valid = true; 2147 } else { 2148 *is_ml_ie_valid = false; 2149 scm_err("Invalid ML IE, expect min len: %zu, actual len: %zu", 2150 parsed_ie_len, actual_len); 2151 } 2152 if (parsed_ie_len < actual_len) 2153 return parsed_ie_len; 2154 2155 return 0; 2156 } 2157 2158 static void 2159 util_get_ml_bv_partner_link_info(struct wlan_objmgr_pdev *pdev, 2160 struct scan_cache_entry *scan_entry) 2161 { 2162 uint8_t *ml_ie = scan_entry->ie_list.multi_link_bv; 2163 uint8_t *end_ptr = NULL; 2164 bool is_ml_ie_valid; 2165 uint8_t offset = util_get_link_info_offset(ml_ie, &is_ml_ie_valid); 2166 uint16_t sta_ctrl; 2167 uint8_t *stactrl_offset = NULL, *ielist_offset; 2168 uint8_t perstaprof_len = 0, perstaprof_stainfo_len = 0, ielist_len = 0; 2169 struct partner_link_info *link_info = NULL; 2170 uint8_t eid = 0; 2171 uint8_t link_idx = 0; 2172 uint8_t rnr_idx = 0; 2173 struct rnr_bss_info *rnr = NULL; 2174 qdf_size_t ml_ie_len = ml_ie[TAG_LEN_POS] + sizeof(struct ie_header); 2175 uint16_t freq; 2176 struct scan_cache_entry *tmp_entry; 2177 struct qdf_mac_addr bcast_addr = QDF_MAC_ADDR_BCAST_INIT; 2178 struct scan_mbssid_info *mbssid; 2179 2180 /* Update partner info from RNR IE */ 2181 while ((rnr_idx < MAX_RNR_BSS) && (rnr_idx < scan_entry->rnr.count)) { 2182 if (link_idx >= (MLD_MAX_LINKS - 1)) 2183 break; 2184 rnr = &scan_entry->rnr.bss_info[rnr_idx]; 2185 if (rnr->mld_info_valid && !rnr->mld_info.mld_id) { 2186 mbssid = &scan_entry->mbssid_info; 2187 freq = 2188 wlan_reg_chan_opclass_to_freq(rnr->channel_number, 2189 rnr->operating_class, 2190 true); 2191 2192 if ((!scan_entry->mbssid_info.profile_count) && 2193 !(rnr->bss_params & TBTT_BSS_PARAM_TRANS_BSSID_BIT)) { 2194 tmp_entry = 2195 scm_scan_get_scan_entry_by_mac_freq(pdev, 2196 &rnr->bssid, freq); 2197 if (tmp_entry) { 2198 qdf_mem_copy(mbssid, 2199 &tmp_entry->mbssid_info, 2200 sizeof(*mbssid)); 2201 util_scan_free_cache_entry(tmp_entry); 2202 } else { 2203 qdf_mem_copy(mbssid->non_trans_bssid, 2204 rnr->bssid.bytes, 2205 QDF_MAC_ADDR_SIZE); 2206 qdf_mem_copy(mbssid->trans_bssid, 2207 bcast_addr.bytes, 2208 QDF_MAC_ADDR_SIZE); 2209 } 2210 } 2211 2212 link_info = &scan_entry->ml_info.link_info[link_idx]; 2213 qdf_mem_copy(&link_info->link_addr, 2214 &rnr->bssid, QDF_MAC_ADDR_SIZE); 2215 2216 link_info->link_id = rnr->mld_info.link_id; 2217 link_info->freq = freq; 2218 2219 if (!link_info->freq) 2220 scm_debug("freq 0 rnr channel %u op_class %u", 2221 rnr->channel_number, 2222 rnr->operating_class); 2223 link_info->op_class = rnr->operating_class; 2224 link_idx++; 2225 } 2226 rnr_idx++; 2227 } 2228 2229 scan_entry->ml_info.num_links = link_idx; 2230 if (!offset) 2231 return; 2232 2233 /* TODO: loop through all the STA info fields */ 2234 2235 /* 2236 * Per-STA Profile subelement format of the Basic Multi-Link element 2237 * 2238 * |---------------|--------|-------------|----------|-------------| 2239 * | Subelement ID | Length | STA control | STA info | STA profile | 2240 * |---------------|--------|-------------|----------|-------------| 2241 * Octets: 1 1 2 variable variable 2242 */ 2243 2244 /* Sub element ID 0 represents Per-STA Profile */ 2245 if (ml_ie[offset] == 0) { 2246 perstaprof_len = ml_ie[offset + 1]; 2247 stactrl_offset = &ml_ie[offset + 2]; 2248 end_ptr = &ml_ie[offset] + perstaprof_len + 2; 2249 2250 if (!(end_ptr <= (ml_ie + ml_ie_len))) { 2251 if (ml_ie[TAG_LEN_POS] >= 255) 2252 scm_debug("Possible fragmentation in ml_ie. Ignore the processing"); 2253 else 2254 scm_debug("perstaprof exceeds ML IE boundary. Ignore the processing"); 2255 return; 2256 } 2257 2258 /* Skip sub element ID and length fields */ 2259 offset += 2; 2260 2261 sta_ctrl = *(uint16_t *)(ml_ie + offset); 2262 2263 /* Skip STA control field */ 2264 offset += 2; 2265 2266 /* 2267 * offset points to the beginning of the STA Info field which 2268 * indicates the number of octets in the STA Info field, 2269 * including one octet for the STA Info Length subfield. 2270 */ 2271 perstaprof_stainfo_len = ml_ie[offset]; 2272 2273 /* Skip STA Info Length field */ 2274 offset += perstaprof_stainfo_len; 2275 2276 /* 2277 * To point to the ie_list offset move past the STA Info 2278 * field. 2279 */ 2280 ielist_offset = &ml_ie[offset]; 2281 2282 /* 2283 * Ensure that the STA Control Field + STA Info Field 2284 * is smaller than the per-STA profile when incrementing 2285 * the pointer to avoid underflow during subtraction. 2286 */ 2287 if ((perstaprof_stainfo_len + 2288 WLAN_ML_BV_LINFO_PERSTAPROF_STACTRL_SIZE) < 2289 perstaprof_len) { 2290 if (!(ielist_offset <= end_ptr)) 2291 ielist_len = 0; 2292 else 2293 ielist_len = perstaprof_len - 2294 (WLAN_ML_BV_LINFO_PERSTAPROF_STACTRL_SIZE + 2295 perstaprof_stainfo_len); 2296 } else { 2297 scm_debug("No STA profile IE list found"); 2298 ielist_len = 0; 2299 } 2300 2301 link_info = NULL; 2302 for (link_idx = 0; link_idx < scan_entry->ml_info.num_links; 2303 link_idx++) { 2304 if (scan_entry->ml_info.link_info[link_idx].link_id == 2305 (sta_ctrl & 0xF)) { 2306 link_info = &scan_entry->ml_info.link_info[link_idx]; 2307 } 2308 } 2309 2310 /* Get the pointers to CSA, ECSA, Max Channel Switch Time IE. */ 2311 if (link_info) { 2312 link_info->csa_ie = wlan_get_ie_ptr_from_eid 2313 (WLAN_ELEMID_CHANSWITCHANN, ielist_offset, 2314 ielist_len); 2315 2316 link_info->ecsa_ie = wlan_get_ie_ptr_from_eid 2317 (WLAN_ELEMID_EXTCHANSWITCHANN, ielist_offset, 2318 ielist_len); 2319 2320 eid = WLAN_EXTN_ELEMID_MAX_CHAN_SWITCH_TIME; 2321 link_info->max_cst_ie = wlan_get_ext_ie_ptr_from_ext_id 2322 (&eid, 1, ielist_offset, ielist_len); 2323 } 2324 } 2325 } 2326 2327 static void util_scan_update_ml_info(struct wlan_objmgr_pdev *pdev, 2328 struct scan_cache_entry *scan_entry) 2329 { 2330 uint8_t *ml_ie = scan_entry->ie_list.multi_link_bv; 2331 uint16_t multi_link_ctrl; 2332 uint8_t offset; 2333 uint8_t mlie_min_len; 2334 bool is_ml_ie_valid = true; 2335 uint8_t *end_ptr = NULL; 2336 2337 if (!scan_entry->ie_list.ehtcap && scan_entry->ie_list.multi_link_bv) { 2338 scan_entry->ie_list.multi_link_bv = NULL; 2339 return; 2340 } 2341 if (!scan_entry->ie_list.multi_link_bv) 2342 return; 2343 2344 mlie_min_len = util_get_link_info_offset(ml_ie, &is_ml_ie_valid); 2345 if (!is_ml_ie_valid) { 2346 scan_entry->ie_list.multi_link_bv = NULL; 2347 return; 2348 } 2349 2350 end_ptr = ml_ie + ml_ie[TAG_LEN_POS] + sizeof(struct ie_header); 2351 2352 multi_link_ctrl = *(uint16_t *)(ml_ie + ML_CONTROL_OFFSET); 2353 2354 /* TODO: update ml_info based on ML IE */ 2355 2356 offset = ML_CMN_INFO_OFFSET; 2357 2358 /* Increment the offset to account for the Common Info Length */ 2359 offset += WLAN_ML_BV_CINFO_LENGTH_SIZE; 2360 2361 if ((ml_ie + offset + QDF_MAC_ADDR_SIZE) <= end_ptr) { 2362 qdf_mem_copy(&scan_entry->ml_info.mld_mac_addr, 2363 ml_ie + offset, QDF_MAC_ADDR_SIZE); 2364 offset += QDF_MAC_ADDR_SIZE; 2365 } 2366 2367 /* TODO: Decode it from ML IE */ 2368 scan_entry->ml_info.num_links = 0; 2369 2370 /** 2371 * Copy Link ID & MAC address of the scan cache entry as first entry 2372 * in the partner info list 2373 */ 2374 if (multi_link_ctrl & CMN_INFO_LINK_ID_PRESENT_BIT) { 2375 if (&ml_ie[offset] < end_ptr) 2376 scan_entry->ml_info.self_link_id = ml_ie[offset] & 0x0F; 2377 } 2378 2379 util_get_ml_bv_partner_link_info(pdev, scan_entry); 2380 } 2381 #else 2382 static void util_scan_update_ml_info(struct wlan_objmgr_pdev *pdev, 2383 struct scan_cache_entry *scan_entry) 2384 { 2385 } 2386 #endif 2387 2388 static QDF_STATUS 2389 util_scan_gen_scan_entry(struct wlan_objmgr_pdev *pdev, 2390 uint8_t *frame, qdf_size_t frame_len, 2391 uint32_t frm_subtype, 2392 struct mgmt_rx_event_params *rx_param, 2393 struct scan_mbssid_info *mbssid_info, 2394 qdf_list_t *scan_list) 2395 { 2396 struct wlan_frame_hdr *hdr; 2397 struct wlan_bcn_frame *bcn; 2398 QDF_STATUS status = QDF_STATUS_SUCCESS; 2399 struct ie_ssid *ssid; 2400 struct scan_cache_entry *scan_entry; 2401 struct qbss_load_ie *qbss_load; 2402 struct scan_cache_node *scan_node; 2403 uint8_t i; 2404 qdf_freq_t chan_freq = 0; 2405 bool is_6g_dup_bcon = false; 2406 uint8_t band_mask; 2407 qdf_freq_t recv_freq = 0; 2408 2409 scan_entry = qdf_mem_malloc_atomic(sizeof(*scan_entry)); 2410 if (!scan_entry) { 2411 scm_err("failed to allocate memory for scan_entry"); 2412 return QDF_STATUS_E_NOMEM; 2413 } 2414 2415 scan_entry->raw_frame.ptr = 2416 qdf_mem_malloc_atomic(frame_len); 2417 if (!scan_entry->raw_frame.ptr) { 2418 scm_err("failed to allocate memory for frame"); 2419 qdf_mem_free(scan_entry); 2420 return QDF_STATUS_E_NOMEM; 2421 } 2422 2423 bcn = (struct wlan_bcn_frame *) 2424 (frame + sizeof(*hdr)); 2425 hdr = (struct wlan_frame_hdr *)frame; 2426 2427 /* update timestamp in nanoseconds needed by kernel layers */ 2428 scan_entry->boottime_ns = qdf_get_bootbased_boottime_ns(); 2429 2430 scan_entry->frm_subtype = frm_subtype; 2431 qdf_mem_copy(scan_entry->bssid.bytes, 2432 hdr->i_addr3, QDF_MAC_ADDR_SIZE); 2433 /* Scr addr */ 2434 qdf_mem_copy(scan_entry->mac_addr.bytes, 2435 hdr->i_addr2, QDF_MAC_ADDR_SIZE); 2436 scan_entry->seq_num = 2437 (le16toh(*(uint16_t *)hdr->i_seq) >> WLAN_SEQ_SEQ_SHIFT); 2438 2439 scan_entry->snr = rx_param->snr; 2440 scan_entry->avg_snr = WLAN_SNR_IN(scan_entry->snr); 2441 scan_entry->rssi_raw = rx_param->rssi; 2442 scan_entry->avg_rssi = WLAN_RSSI_IN(scan_entry->rssi_raw); 2443 scan_entry->tsf_delta = rx_param->tsf_delta; 2444 scan_entry->pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); 2445 2446 recv_freq = rx_param->chan_freq; 2447 /* Copy per chain rssi to scan entry */ 2448 qdf_mem_copy(scan_entry->per_chain_rssi, rx_param->rssi_ctl, 2449 WLAN_MGMT_TXRX_HOST_MAX_ANTENNA); 2450 band_mask = BIT(wlan_reg_freq_to_band(recv_freq)); 2451 2452 if (!wlan_psoc_nif_fw_ext_cap_get(wlan_pdev_get_psoc(pdev), 2453 WLAN_SOC_CEXT_HW_DB2DBM)) { 2454 for (i = 0; i < WLAN_MGMT_TXRX_HOST_MAX_ANTENNA; i++) { 2455 if (scan_entry->per_chain_rssi[i] != 2456 WLAN_INVALID_PER_CHAIN_SNR) 2457 scan_entry->per_chain_rssi[i] += 2458 WLAN_NOISE_FLOOR_DBM_DEFAULT; 2459 else 2460 scan_entry->per_chain_rssi[i] = 2461 WLAN_INVALID_PER_CHAIN_RSSI; 2462 } 2463 } 2464 2465 /* store jiffies */ 2466 scan_entry->rrm_parent_tsf = (uint32_t)qdf_system_ticks(); 2467 2468 scan_entry->bcn_int = le16toh(bcn->beacon_interval); 2469 2470 /* 2471 * In case if the beacon doesn't have 2472 * valid beacon interval falback to def 2473 */ 2474 if (!scan_entry->bcn_int) 2475 scan_entry->bcn_int = 100; 2476 scan_entry->cap_info.value = le16toh(bcn->capability.value); 2477 qdf_mem_copy(scan_entry->tsf_info.data, 2478 bcn->timestamp, 8); 2479 scan_entry->erp = ERP_NON_ERP_PRESENT; 2480 2481 scan_entry->scan_entry_time = 2482 qdf_mc_timer_get_system_time(); 2483 2484 scan_entry->raw_frame.len = frame_len; 2485 qdf_mem_copy(scan_entry->raw_frame.ptr, 2486 frame, frame_len); 2487 status = util_scan_populate_bcn_ie_list(pdev, scan_entry, &chan_freq, 2488 band_mask); 2489 if (QDF_IS_STATUS_ERROR(status)) { 2490 qdf_mem_free(scan_entry->raw_frame.ptr); 2491 qdf_mem_free(scan_entry); 2492 return QDF_STATUS_E_FAILURE; 2493 } 2494 2495 ssid = (struct ie_ssid *) 2496 scan_entry->ie_list.ssid; 2497 2498 if (ssid && (ssid->ssid_len > WLAN_SSID_MAX_LEN)) { 2499 qdf_mem_free(scan_entry->raw_frame.ptr); 2500 qdf_mem_free(scan_entry); 2501 return QDF_STATUS_E_FAILURE; 2502 } 2503 2504 if (scan_entry->ie_list.p2p) 2505 scan_entry->is_p2p = true; 2506 2507 if (!chan_freq && util_scan_entry_hecap(scan_entry)) { 2508 status = util_scan_get_chan_from_he_6g_params(pdev, scan_entry, 2509 &chan_freq, 2510 &is_6g_dup_bcon, 2511 band_mask, 2512 recv_freq); 2513 if (QDF_IS_STATUS_ERROR(status)) { 2514 qdf_mem_free(scan_entry->raw_frame.ptr); 2515 qdf_mem_free(scan_entry); 2516 return QDF_STATUS_E_FAILURE; 2517 } 2518 } 2519 2520 if (chan_freq) 2521 scan_entry->channel.chan_freq = chan_freq; 2522 2523 /* If no channel info is present in beacon use meta channel */ 2524 if (!scan_entry->channel.chan_freq) { 2525 scan_entry->channel.chan_freq = recv_freq; 2526 } else if (recv_freq != 2527 scan_entry->channel.chan_freq) { 2528 if (!wlan_reg_is_49ghz_freq(scan_entry->channel.chan_freq) && 2529 !is_6g_dup_bcon) 2530 scan_entry->channel_mismatch = true; 2531 } 2532 2533 if (util_scan_is_hidden_ssid(ssid)) { 2534 scan_entry->ie_list.ssid = NULL; 2535 scan_entry->is_hidden_ssid = true; 2536 } else { 2537 qdf_mem_copy(scan_entry->ssid.ssid, 2538 ssid->ssid, ssid->ssid_len); 2539 scan_entry->ssid.length = ssid->ssid_len; 2540 scan_entry->hidden_ssid_timestamp = 2541 scan_entry->scan_entry_time; 2542 } 2543 qdf_mem_copy(&scan_entry->mbssid_info, mbssid_info, 2544 sizeof(scan_entry->mbssid_info)); 2545 2546 scan_entry->phy_mode = util_scan_get_phymode(pdev, scan_entry); 2547 2548 scan_entry->nss = util_scan_scm_calc_nss_supported_by_ap(scan_entry); 2549 scm_fill_adaptive_11r_cap(scan_entry); 2550 util_scan_set_security(scan_entry); 2551 2552 util_scan_scm_update_bss_with_esp_data(scan_entry); 2553 qbss_load = (struct qbss_load_ie *) 2554 util_scan_entry_qbssload(scan_entry); 2555 if (qbss_load) 2556 scan_entry->qbss_chan_load = qbss_load->qbss_chan_load; 2557 2558 scan_node = qdf_mem_malloc_atomic(sizeof(*scan_node)); 2559 if (!scan_node) { 2560 qdf_mem_free(scan_entry->raw_frame.ptr); 2561 qdf_mem_free(scan_entry); 2562 scm_err("failed to allocate memory for scan_node"); 2563 return QDF_STATUS_E_FAILURE; 2564 } 2565 2566 util_scan_update_ml_info(pdev, scan_entry); 2567 2568 scan_node->entry = scan_entry; 2569 qdf_list_insert_front(scan_list, &scan_node->node); 2570 2571 return status; 2572 } 2573 2574 #ifdef WLAN_FEATURE_MBSSID 2575 /* 2576 * util_is_noninh_ie() - find the noninhertance information element 2577 * in the received frame's IE list, so that we can stop inheriting that IE 2578 * in the caller function. 2579 * 2580 * @elem_id: Element ID in the received frame's IE, which is being processed. 2581 * @non_inh_list: pointer to the non inherited list of element IDs or 2582 * list of extension element IDs. 2583 * @len: Length of non inheritance IE list 2584 * 2585 * Return: False if the element ID is not found or else return true 2586 */ 2587 static bool util_is_noninh_ie(uint8_t elem_id, 2588 uint8_t *non_inh_list, 2589 int8_t len) 2590 { 2591 int count; 2592 2593 for (count = 0; count < len; count++) { 2594 if (elem_id == non_inh_list[count]) 2595 return true; 2596 } 2597 2598 return false; 2599 } 2600 2601 /* 2602 * util_scan_find_noninheritance_ie() - find noninheritance information element 2603 * This block of code is to identify if there is any non-inheritance element 2604 * present as part of the nontransmitted BSSID profile. 2605 * @elem_id: element id 2606 * @ies: pointer consisting of IEs 2607 * @len: IE length 2608 * 2609 * Return: NULL if the element ID is not found or if IE pointer is NULL else 2610 * pointer to the first byte of the requested element 2611 */ 2612 static uint8_t 2613 *util_scan_find_noninheritance_ie(uint8_t elem_id, uint8_t *ies, 2614 int32_t len) 2615 { 2616 if (!ies) 2617 return NULL; 2618 2619 while (len >= MIN_IE_LEN && len >= ies[TAG_LEN_POS] + MIN_IE_LEN) { 2620 if ((ies[ID_POS] == elem_id) && 2621 (ies[ELEM_ID_EXTN_POS] == 2622 WLAN_EXTN_ELEMID_NONINHERITANCE)) { 2623 return ies; 2624 } 2625 len -= ies[TAG_LEN_POS] + MIN_IE_LEN; 2626 ies += ies[TAG_LEN_POS] + MIN_IE_LEN; 2627 } 2628 2629 return NULL; 2630 } 2631 #endif 2632 2633 /* 2634 * util_scan_find_ie() - find information element 2635 * @eid: element id 2636 * @ies: pointer consisting of IEs 2637 * @len: IE length 2638 * 2639 * Return: NULL if the element ID is not found or if IE pointer is NULL else 2640 * pointer to the first byte of the requested element 2641 */ 2642 static uint8_t *util_scan_find_ie(uint8_t eid, uint8_t *ies, 2643 int32_t len) 2644 { 2645 if (!ies) 2646 return NULL; 2647 2648 while (len >= 2 && len >= ies[1] + 2) { 2649 if (ies[0] == eid) 2650 return ies; 2651 len -= ies[1] + 2; 2652 ies += ies[1] + 2; 2653 } 2654 2655 return NULL; 2656 } 2657 2658 #ifdef WLAN_FEATURE_MBSSID 2659 static void util_gen_new_bssid(uint8_t *bssid, uint8_t max_bssid, 2660 uint8_t mbssid_index, 2661 uint8_t *new_bssid_addr) 2662 { 2663 uint8_t lsb_n; 2664 int i; 2665 2666 for (i = 0; i < QDF_MAC_ADDR_SIZE; i++) 2667 new_bssid_addr[i] = bssid[i]; 2668 2669 lsb_n = new_bssid_addr[5] & ((1 << max_bssid) - 1); 2670 2671 new_bssid_addr[5] &= ~((1 << max_bssid) - 1); 2672 new_bssid_addr[5] |= (lsb_n + mbssid_index) % (1 << max_bssid); 2673 } 2674 2675 /* 2676 * util_parse_noninheritance_list() - This block of code will be executed only 2677 * if there is a valid non inheritance IE present in the nontx profile. 2678 * Host need not inherit those list of element IDs and list of element ID 2679 * extensions from the transmitted BSSID profile. 2680 * Since non-inheritance element is an element ID extension, it should 2681 * be part of extension element. So first we need to find if there are 2682 * any extension element present in the nontransmitted BSSID profile. 2683 * @extn_elem: If valid, it points to the element ID field of 2684 * extension element tag in the nontransmitted BSSID profile. 2685 * It may or may not have non inheritance tag present. 2686 * _____________________________________________ 2687 * | | | |List of|List of | 2688 * | Element |Length |Element|Element|Element ID | 2689 * | ID | |ID extn| IDs |Extension | 2690 * |_________|_______|_______|_______|___________| 2691 * List of Element IDs: 2692 * __________________ 2693 * | | | 2694 * | Length |Element | 2695 * | |ID List | 2696 * |_________|________| 2697 * List of Element ID Extensions: 2698 * __________________________ 2699 * | | | 2700 * | Length |Element ID | 2701 * | |extension List | 2702 * |_________|________________| 2703 * @elem_list: Element ID list 2704 * @extn_elem_list: Element ID exiension list 2705 * @non_inheritance_ie: Non inheritance IE information 2706 */ 2707 2708 static void util_parse_noninheritance_list(uint8_t *extn_elem, 2709 uint8_t **elem_list, 2710 uint8_t **extn_elem_list, 2711 struct non_inheritance_ie *ninh) 2712 { 2713 int8_t extn_rem_len = 0; 2714 2715 if (extn_elem[ELEM_ID_LIST_LEN_POS] < extn_elem[TAG_LEN_POS]) { 2716 /* 2717 * extn_rem_len represents the number of bytes after 2718 * the length subfield of list of Element IDs. 2719 * So here, extn_rem_len should be equal to 2720 * Element ID list + Length subfield of Element ID 2721 * extension list + Element ID extension list. 2722 * 2723 * Here we have taken two pointers pointing to the 2724 * element ID list and element ID extension list 2725 * which we will use to detect the same elements 2726 * in the transmitted BSSID profile and choose not 2727 * to inherit those elements while constructing the 2728 * frame for nontransmitted BSSID profile. 2729 */ 2730 extn_rem_len = extn_elem[TAG_LEN_POS] - MIN_IE_LEN; 2731 ninh->non_inherit = true; 2732 2733 if (extn_rem_len && extn_elem[ELEM_ID_LIST_LEN_POS]) { 2734 if (extn_rem_len >= extn_elem[ELEM_ID_LIST_LEN_POS]) { 2735 ninh->list_len = 2736 extn_elem[ELEM_ID_LIST_LEN_POS]; 2737 *elem_list = extn_elem + ELEM_ID_LIST_POS; 2738 extn_rem_len -= ninh->list_len; 2739 } else { 2740 /* 2741 * Corrupt frame. length subfield of 2742 * element ID list is greater than 2743 * what it should be. Go ahead with 2744 * frame generation but do not honour 2745 * the non inheritance part. Also, mark 2746 * the element ID in subcopy as 0, so 2747 * that this element info will not 2748 * be copied. 2749 */ 2750 ninh->non_inherit = false; 2751 extn_elem[0] = 0; 2752 } 2753 } 2754 2755 extn_rem_len--; 2756 if (extn_rem_len > 0) { 2757 if (!ninh->list_len) { 2758 ninh->extn_len = 2759 extn_elem[ELEM_ID_LIST_LEN_POS + 1]; 2760 } else { 2761 ninh->extn_len = 2762 extn_elem[ELEM_ID_LIST_POS + 2763 ninh->list_len]; 2764 } 2765 2766 if (extn_rem_len != ninh->extn_len) { 2767 /* 2768 * Corrupt frame. length subfield of 2769 * element ID extn list is not 2770 * what it should be. Go ahead with 2771 * frame generation but do not honour 2772 * the non inheritance part. Also, mark 2773 * the element ID in subcopy as 0, so 2774 * that this element info will not 2775 * be copied. 2776 */ 2777 ninh->non_inherit = false; 2778 extn_elem[0] = 0; 2779 } 2780 2781 if (ninh->extn_len) { 2782 *extn_elem_list = 2783 (extn_elem + ninh->list_len + 2784 ELEM_ID_LIST_POS + 1); 2785 } 2786 } 2787 } 2788 } 2789 2790 #ifdef WLAN_FEATURE_11BE_MLO 2791 static bool util_is_ml_ie(uint8_t *pos) 2792 { 2793 if (pos[PAYLOAD_START_POS] == WLAN_EXTN_ELEMID_MULTI_LINK) 2794 return true; 2795 2796 return false; 2797 } 2798 2799 /** 2800 * util_handle_rnr_ie_for_mbssid() - parse and modify RNR IE for MBSSID feature 2801 * @rnr: The pointer to RNR IE 2802 * @bssid_index: BSSID index from MBSSID index IE 2803 * @pos: The buffer pointer to save the transformed RNR IE, caller is expected 2804 * to supply a buffer that is at least as big as @rnr 2805 * 2806 * Per the description about Neighbor AP Information field about MLD 2807 * parameters subfield in section 9.4.2.170.2 of Draft P802.11be_D1.4. 2808 * If the reported AP is affiliated with the same MLD of the reporting AP, 2809 * the TBTT information is skipped; If the reported AP is affiliated with 2810 * the same MLD of the nontransmitted BSSID, the TBTT information is 2811 * copied and the MLD ID is changed to 0. 2812 * 2813 * Return: Length of the element written to @pos 2814 */ 2815 static int util_handle_rnr_ie_for_mbssid(const uint8_t *rnr, 2816 uint8_t bssid_index, uint8_t *pos) 2817 { 2818 size_t rnr_len; 2819 const uint8_t *data, *rnr_end; 2820 uint8_t *rnr_new; 2821 struct neighbor_ap_info_field *neighbor_ap_info; 2822 struct rnr_mld_info *mld_param; 2823 uint8_t tbtt_type, tbtt_len, tbtt_count; 2824 uint8_t mld_pos, mld_id; 2825 int32_t i, copy_len; 2826 /* The count of TBTT info field whose MLD ID equals to 0 in a neighbor 2827 * AP information field. 2828 */ 2829 uint32_t tbtt_info_field_count; 2830 /* The total bytes of TBTT info fields whose MLD ID equals to 0 in 2831 * current RNR IE. 2832 */ 2833 uint32_t tbtt_info_field_len = 0; 2834 uint8_t nbr_ap_info_len = sizeof(struct neighbor_ap_info_field); 2835 2836 rnr_len = rnr[TAG_LEN_POS]; 2837 rnr_end = rnr + rnr_len + MIN_IE_LEN; 2838 rnr_new = pos; 2839 qdf_mem_copy(pos, rnr, MIN_IE_LEN); 2840 pos += MIN_IE_LEN; 2841 2842 data = rnr + PAYLOAD_START_POS; 2843 while (data < rnr_end) { 2844 neighbor_ap_info = (struct neighbor_ap_info_field *)data; 2845 tbtt_count = neighbor_ap_info->tbtt_header.tbtt_info_count; 2846 tbtt_len = neighbor_ap_info->tbtt_header.tbtt_info_length; 2847 tbtt_type = neighbor_ap_info->tbtt_header.tbbt_info_fieldtype; 2848 scm_debug("channel number %d, op class %d, bssid_index %d", 2849 neighbor_ap_info->channel_number, 2850 neighbor_ap_info->operting_class, bssid_index); 2851 scm_debug("tbtt_count %d, tbtt_length %d, tbtt_type %d", 2852 tbtt_count, tbtt_len, tbtt_type); 2853 2854 copy_len = tbtt_len * (tbtt_count + 1) + 2855 nbr_ap_info_len; 2856 if (data + copy_len > rnr_end) 2857 return 0; 2858 2859 if (tbtt_len >= 2860 TBTT_NEIGHBOR_AP_BSSID_S_SSID_BSS_PARAM_20MHZ_PSD_MLD_PARAM) 2861 mld_pos = 2862 TBTT_NEIGHBOR_AP_BSSID_S_SSID_BSS_PARAM_20MHZ_PSD; 2863 else 2864 mld_pos = 0; 2865 2866 /* If MLD params do not exist, copy this neighbor AP 2867 * information field. 2868 * Per Draft P802.11be_D1.4, tbtt_type value 1, 2 and 3 2869 * are reserved, 2870 */ 2871 if (mld_pos == 0 || tbtt_type != 0) { 2872 scm_debug("no MLD params, tbtt_type %d", tbtt_type); 2873 qdf_mem_copy(pos, data, copy_len); 2874 pos += copy_len; 2875 data += copy_len; 2876 continue; 2877 } 2878 2879 qdf_mem_copy(pos, data, nbr_ap_info_len); 2880 neighbor_ap_info = (struct neighbor_ap_info_field *)pos; 2881 pos += nbr_ap_info_len; 2882 data += nbr_ap_info_len; 2883 2884 tbtt_info_field_count = 0; 2885 for (i = 0; i < tbtt_count + 1; i++) { 2886 mld_param = (struct rnr_mld_info *)&data[mld_pos]; 2887 mld_id = mld_param->mld_id; 2888 2889 /* Refer to Draft P802.11be_D1.4 2890 * 9.4.2.170.2 Neighbor AP Information field about 2891 * MLD parameters subfield 2892 */ 2893 if (mld_id == 0) { 2894 /* Skip this TBTT information since this 2895 * reported AP is affiliated with the same MLD 2896 * of the reporting AP who sending the frame 2897 * carrying this element. 2898 */ 2899 tbtt_info_field_len += tbtt_len; 2900 data += tbtt_len; 2901 tbtt_info_field_count++; 2902 } else if (mld_id == bssid_index) { 2903 /* Copy this TBTT information and change MLD 2904 * to 0 as this reported AP is affiliated with 2905 * the same MLD of the nontransmitted BSSID. 2906 */ 2907 qdf_mem_copy(pos, data, tbtt_len); 2908 mld_param = 2909 (struct rnr_mld_info *)&pos[mld_pos]; 2910 scm_debug("change MLD ID from %d to 0", 2911 mld_param->mld_id); 2912 mld_param->mld_id = 0; 2913 data += tbtt_len; 2914 pos += tbtt_len; 2915 } else { 2916 qdf_mem_copy(pos, data, tbtt_len); 2917 data += tbtt_len; 2918 pos += tbtt_len; 2919 } 2920 } 2921 2922 scm_debug("skip %d neighbor info", tbtt_info_field_count); 2923 if (tbtt_info_field_count == (tbtt_count + 1)) { 2924 /* If all the TBTT information are skipped, then also 2925 * revert the neighbor AP info which has been copied. 2926 */ 2927 pos -= nbr_ap_info_len; 2928 tbtt_info_field_len += nbr_ap_info_len; 2929 } else { 2930 neighbor_ap_info->tbtt_header.tbtt_info_count -= 2931 tbtt_info_field_count; 2932 } 2933 } 2934 2935 rnr_new[TAG_LEN_POS] = rnr_len - tbtt_info_field_len; 2936 if (rnr_new[TAG_LEN_POS] > 0) 2937 rnr_len = rnr_new[TAG_LEN_POS] + MIN_IE_LEN; 2938 else 2939 rnr_len = 0; 2940 2941 return rnr_len; 2942 } 2943 #else 2944 static bool util_is_ml_ie(uint8_t *pos) 2945 { 2946 return false; 2947 } 2948 2949 static int util_handle_rnr_ie_for_mbssid(const uint8_t *rnr, 2950 uint8_t bssid_index, uint8_t *pos) 2951 { 2952 return 0; 2953 } 2954 #endif 2955 2956 static uint32_t util_gen_new_ie(uint8_t *ie, uint32_t ielen, 2957 uint8_t *subelement, 2958 size_t subie_len, uint8_t *new_ie, 2959 uint8_t bssid_index) 2960 { 2961 uint8_t *pos, *tmp; 2962 const uint8_t *tmp_old, *tmp_new; 2963 uint8_t *sub_copy, *extn_elem = NULL; 2964 struct non_inheritance_ie ninh = {0}; 2965 uint8_t *elem_list = NULL, *extn_elem_list = NULL; 2966 size_t tmp_rem_len; 2967 2968 /* copy subelement as we need to change its content to 2969 * mark an ie after it is processed. 2970 */ 2971 sub_copy = qdf_mem_malloc(subie_len); 2972 if (!sub_copy) 2973 return 0; 2974 qdf_mem_copy(sub_copy, subelement, subie_len); 2975 2976 pos = &new_ie[0]; 2977 2978 /* new ssid */ 2979 tmp_new = util_scan_find_ie(WLAN_ELEMID_SSID, sub_copy, subie_len); 2980 if (tmp_new) { 2981 scm_debug(" SSID " QDF_SSID_FMT, 2982 QDF_SSID_REF(tmp_new[1], 2983 &tmp_new[PAYLOAD_START_POS])); 2984 if ((pos + tmp_new[1] + MIN_IE_LEN) <= 2985 (new_ie + ielen)) { 2986 qdf_mem_copy(pos, tmp_new, 2987 (tmp_new[1] + MIN_IE_LEN)); 2988 pos += (tmp_new[1] + MIN_IE_LEN); 2989 } 2990 } 2991 2992 extn_elem = util_scan_find_noninheritance_ie(WLAN_ELEMID_EXTN_ELEM, 2993 sub_copy, subie_len); 2994 2995 if (extn_elem && extn_elem[TAG_LEN_POS]) { 2996 util_parse_noninheritance_list(extn_elem, &elem_list, 2997 &extn_elem_list, &ninh); 2998 } 2999 3000 /* go through IEs in ie (skip SSID) and subelement, 3001 * merge them into new_ie 3002 */ 3003 tmp_old = util_scan_find_ie(WLAN_ELEMID_SSID, ie, ielen); 3004 tmp_old = (tmp_old) ? tmp_old + tmp_old[1] + MIN_IE_LEN : ie; 3005 3006 while (((tmp_old + tmp_old[1] + MIN_IE_LEN) - ie) <= ielen) { 3007 ninh.non_inh_ie_found = 0; 3008 if (ninh.non_inherit) { 3009 if (ninh.list_len) { 3010 ninh.non_inh_ie_found = 3011 util_is_noninh_ie(tmp_old[0], 3012 elem_list, 3013 ninh.list_len); 3014 } 3015 3016 if (!ninh.non_inh_ie_found && 3017 ninh.extn_len && 3018 (tmp_old[0] == WLAN_ELEMID_EXTN_ELEM)) { 3019 ninh.non_inh_ie_found = 3020 util_is_noninh_ie(tmp_old[2], 3021 extn_elem_list, 3022 ninh.extn_len); 3023 } 3024 } 3025 3026 if (ninh.non_inh_ie_found || (tmp_old[0] == 0)) { 3027 tmp_old += tmp_old[1] + MIN_IE_LEN; 3028 continue; 3029 } 3030 3031 tmp = (uint8_t *)util_scan_find_ie(tmp_old[0], sub_copy, 3032 subie_len); 3033 if (!tmp) { 3034 /* ie in old ie but not in subelement */ 3035 if (tmp_old[0] == WLAN_ELEMID_REDUCED_NEIGHBOR_REPORT) { 3036 /* handle rnr ie for mbssid*/ 3037 pos += 3038 util_handle_rnr_ie_for_mbssid(tmp_old, 3039 bssid_index, 3040 pos); 3041 } else if (tmp_old[0] != WLAN_ELEMID_MULTIPLE_BSSID) { 3042 if ((pos + tmp_old[1] + MIN_IE_LEN) <= 3043 (new_ie + ielen)) { 3044 qdf_mem_copy(pos, tmp_old, 3045 (tmp_old[1] + 3046 MIN_IE_LEN)); 3047 pos += tmp_old[1] + MIN_IE_LEN; 3048 } 3049 } 3050 } else { 3051 /* ie in transmitting ie also in subelement, 3052 * copy from subelement and flag the ie in subelement 3053 * as copied (by setting eid field to 0xff). 3054 * To determine if the vendor ies are same: 3055 * 1. For Cisco OUI, compare only OUI + type 3056 * 2. For other OUI, compare OUI + type + subType 3057 */ 3058 tmp_rem_len = subie_len - (tmp - sub_copy); 3059 if (tmp_old[0] == WLAN_ELEMID_VENDOR && 3060 tmp_rem_len >= MIN_VENDOR_TAG_LEN) { 3061 /* If Vendor IE also presents in STA profile, 3062 * then ignore the Vendor IE which is for 3063 * reporting STA. It only needs to copy Vendor 3064 * IE from STA profile for reported BSSID. 3065 * The copy happens when going through the 3066 * remaining IEs. 3067 */ 3068 ; 3069 } else if (tmp_old[0] == WLAN_ELEMID_EXTN_ELEM) { 3070 if (tmp_old[PAYLOAD_START_POS] == 3071 tmp[PAYLOAD_START_POS] && 3072 !util_is_ml_ie(tmp)) { 3073 /* same ie, copy from subelement 3074 * but multi link IE is exception, 3075 * it needs to copy from main frame 3076 * for full info. 3077 */ 3078 if ((pos + tmp[1] + MIN_IE_LEN) <= 3079 (new_ie + ielen)) { 3080 qdf_mem_copy(pos, tmp, 3081 tmp[1] + 3082 MIN_IE_LEN); 3083 pos += tmp[1] + MIN_IE_LEN; 3084 tmp[0] = 0; 3085 } 3086 } else { 3087 if ((pos + tmp_old[1] + MIN_IE_LEN) <= 3088 (new_ie + ielen)) { 3089 qdf_mem_copy(pos, tmp_old, 3090 tmp_old[1] + 3091 MIN_IE_LEN); 3092 pos += tmp_old[1] + 3093 MIN_IE_LEN; 3094 } 3095 } 3096 3097 } else { 3098 /* copy ie from subelement into new ie */ 3099 if ((pos + tmp[1] + MIN_IE_LEN) <= 3100 (new_ie + ielen)) { 3101 qdf_mem_copy(pos, tmp, 3102 tmp[1] + MIN_IE_LEN); 3103 pos += tmp[1] + MIN_IE_LEN; 3104 tmp[0] = 0; 3105 } 3106 } 3107 } 3108 3109 if (((tmp_old + tmp_old[1] + MIN_IE_LEN) - ie) >= ielen) 3110 break; 3111 3112 tmp_old += tmp_old[1] + MIN_IE_LEN; 3113 } 3114 3115 /* go through subelement again to check if there is any ie not 3116 * copied to new ie, skip ssid, capability, bssid-index ie 3117 */ 3118 tmp_new = sub_copy; 3119 while ((subie_len > 0) && 3120 (((tmp_new + tmp_new[1] + MIN_IE_LEN) - sub_copy) <= 3121 subie_len)) { 3122 if (!(tmp_new[0] == WLAN_ELEMID_NONTX_BSSID_CAP || 3123 tmp_new[0] == WLAN_ELEMID_SSID || 3124 tmp_new[0] == WLAN_ELEMID_MULTI_BSSID_IDX || 3125 ((tmp_new[0] == WLAN_ELEMID_EXTN_ELEM) && 3126 (tmp_new[2] == WLAN_EXTN_ELEMID_NONINHERITANCE)))) { 3127 if ((pos + tmp_new[1] + MIN_IE_LEN) <= 3128 (new_ie + ielen)) { 3129 qdf_mem_copy(pos, tmp_new, 3130 tmp_new[1] + MIN_IE_LEN); 3131 pos += tmp_new[1] + MIN_IE_LEN; 3132 } 3133 } 3134 if (((tmp_new + tmp_new[1] + MIN_IE_LEN) - sub_copy) >= 3135 (subie_len - 1)) 3136 break; 3137 tmp_new += tmp_new[1] + MIN_IE_LEN; 3138 } 3139 3140 qdf_mem_free(sub_copy); 3141 3142 if (pos > new_ie) 3143 return pos - new_ie; 3144 else 3145 return 0; 3146 } 3147 3148 static enum nontx_profile_reasoncode 3149 util_handle_nontx_prof(uint8_t *mbssid_elem, uint8_t *subelement, 3150 uint8_t *next_subelement, 3151 struct scan_mbssid_info *mbssid_info, 3152 char *bssid, char *new_bssid) 3153 { 3154 uint8_t *mbssid_index_ie; 3155 uint32_t prof_len; 3156 3157 prof_len = subelement[TAG_LEN_POS]; 3158 /* 3159 * If we are executing the split portion of the nontx 3160 * profile present in the subsequent MBSSID, then there 3161 * is no need of any sanity check for valid BSS profile 3162 */ 3163 3164 if (mbssid_info->split_prof_continue) { 3165 if ((subelement[ID_POS] != 0) || 3166 (subelement[TAG_LEN_POS] < SPLIT_PROF_DATA_LEAST_LEN)) { 3167 return INVALID_SPLIT_PROF; 3168 } 3169 } else { 3170 if ((subelement[ID_POS] != 0) || 3171 (subelement[TAG_LEN_POS] < VALID_ELEM_LEAST_LEN)) { 3172 /* not a valid BSS profile */ 3173 return INVALID_NONTX_PROF; 3174 } 3175 } 3176 3177 if (mbssid_info->split_profile) { 3178 if (next_subelement[PAYLOAD_START_POS] != 3179 WLAN_ELEMID_NONTX_BSSID_CAP) { 3180 mbssid_info->prof_residue = true; 3181 } 3182 } 3183 3184 if (!mbssid_info->split_prof_continue && 3185 ((subelement[PAYLOAD_START_POS] != WLAN_ELEMID_NONTX_BSSID_CAP) || 3186 (subelement[NONTX_BSSID_CAP_TAG_LEN_POS] != CAP_INFO_LEN))) { 3187 /* The first element within the Nontransmitted 3188 * BSSID Profile is not the Nontransmitted 3189 * BSSID Capability element. 3190 */ 3191 return INVALID_NONTX_PROF; 3192 } 3193 3194 /* found a Nontransmitted BSSID Profile */ 3195 mbssid_index_ie = 3196 util_scan_find_ie(WLAN_ELEMID_MULTI_BSSID_IDX, 3197 (subelement + PAYLOAD_START_POS), prof_len); 3198 3199 if (!mbssid_index_ie) { 3200 if (!mbssid_info->prof_residue) 3201 return INVALID_NONTX_PROF; 3202 3203 mbssid_info->skip_bssid_copy = true; 3204 } else if ((mbssid_index_ie[TAG_LEN_POS] < 1) || 3205 (mbssid_index_ie[BSS_INDEX_POS] == 0)) { 3206 /* No valid Multiple BSSID-Index element */ 3207 return INVALID_NONTX_PROF; 3208 } 3209 3210 if (!mbssid_info->skip_bssid_copy) { 3211 qdf_mem_copy(mbssid_info->trans_bssid, 3212 bssid, QDF_MAC_ADDR_SIZE); 3213 mbssid_info->profile_num = 3214 mbssid_index_ie[BSS_INDEX_POS]; 3215 util_gen_new_bssid(bssid, 3216 mbssid_elem[MBSSID_INDICATOR_POS], 3217 mbssid_index_ie[BSS_INDEX_POS], 3218 new_bssid); 3219 qdf_mem_copy(mbssid_info->non_trans_bssid, new_bssid, 3220 QDF_MAC_ADDR_SIZE); 3221 } 3222 /* In single MBSS IE, there could be subelement holding 3223 * remaining vendor IEs of non tx profile from last MBSS IE 3224 * [split profile] and new non tx profile, hence reset 3225 * skip_bssid_copy flag after each subelement processing 3226 */ 3227 mbssid_info->skip_bssid_copy = false; 3228 return VALID_NONTX_PROF; 3229 } 3230 3231 /* 3232 * What's split profile: 3233 * If any nontransmitted BSSID profile is fragmented across 3234 * multiple MBSSID elements, then it is called split profile. 3235 * For a split profile to exist we need to have at least two 3236 * MBSSID elements as part of the RX beacon or probe response 3237 * Hence, first we need to identify the next MBSSID element 3238 * and check for the 5th bit from the starting of the next 3239 * MBSSID IE and if it does not have Nontransmitted BSSID 3240 * capability element, then it's a split profile case. 3241 */ 3242 static bool util_scan_is_split_prof_found(uint8_t *next_elem, 3243 uint8_t *ie, uint32_t ielen) 3244 { 3245 uint8_t *next_mbssid_elem; 3246 3247 if (next_elem[0] == WLAN_ELEMID_MULTIPLE_BSSID) { 3248 if ((next_elem[TAG_LEN_POS] >= VALID_ELEM_LEAST_LEN) && 3249 (next_elem[SUBELEM_DATA_POS_FROM_MBSSID] != 3250 WLAN_ELEMID_NONTX_BSSID_CAP)) { 3251 return true; 3252 } 3253 } else { 3254 next_mbssid_elem = 3255 util_scan_find_ie(WLAN_ELEMID_MULTIPLE_BSSID, 3256 next_elem, 3257 ielen - (next_elem - ie)); 3258 if (!next_mbssid_elem) 3259 return false; 3260 3261 if ((next_mbssid_elem[TAG_LEN_POS] >= VALID_ELEM_LEAST_LEN) && 3262 (next_mbssid_elem[SUBELEM_DATA_POS_FROM_MBSSID] != 3263 WLAN_ELEMID_NONTX_BSSID_CAP)) { 3264 return true; 3265 } 3266 } 3267 3268 return false; 3269 } 3270 3271 static QDF_STATUS util_scan_parse_mbssid(struct wlan_objmgr_pdev *pdev, 3272 uint8_t *frame, qdf_size_t frame_len, 3273 uint32_t frm_subtype, 3274 struct mgmt_rx_event_params *rx_param, 3275 qdf_list_t *scan_list) 3276 { 3277 struct wlan_scan_obj *scan_obj; 3278 struct wlan_bcn_frame *bcn; 3279 struct wlan_frame_hdr *hdr; 3280 struct scan_mbssid_info mbssid_info = {0}; 3281 QDF_STATUS status; 3282 uint8_t *pos, *subelement, *next_elem; 3283 uint8_t *mbssid_elem; 3284 uint32_t subie_len, new_ie_len, ielen; 3285 uint8_t *next_subelement = NULL; 3286 uint8_t new_bssid[QDF_MAC_ADDR_SIZE], bssid[QDF_MAC_ADDR_SIZE]; 3287 uint8_t *new_ie, *split_prof_start = NULL, *split_prof_end = NULL; 3288 uint8_t *ie, *new_frame = NULL; 3289 int new_frame_len = 0, split_prof_len = 0; 3290 enum nontx_profile_reasoncode retval; 3291 uint8_t *nontx_profile = NULL; 3292 3293 scan_obj = wlan_pdev_get_scan_obj(pdev); 3294 if (!scan_obj) 3295 return QDF_STATUS_E_INVAL; 3296 3297 hdr = (struct wlan_frame_hdr *)frame; 3298 bcn = (struct wlan_bcn_frame *)(frame + sizeof(struct wlan_frame_hdr)); 3299 ie = (uint8_t *)&bcn->ie; 3300 ielen = (uint16_t)(frame_len - 3301 sizeof(struct wlan_frame_hdr) - 3302 offsetof(struct wlan_bcn_frame, ie)); 3303 qdf_mem_copy(bssid, hdr->i_addr3, QDF_MAC_ADDR_SIZE); 3304 3305 if (!util_scan_find_ie(WLAN_ELEMID_MULTIPLE_BSSID, ie, ielen)) 3306 return QDF_STATUS_E_FAILURE; 3307 3308 pos = ie; 3309 3310 new_ie = qdf_mem_malloc(ielen); 3311 if (!new_ie) 3312 return QDF_STATUS_E_NOMEM; 3313 3314 while (pos < (ie + ielen + MIN_IE_LEN)) { 3315 mbssid_elem = 3316 util_scan_find_ie(WLAN_ELEMID_MULTIPLE_BSSID, pos, 3317 ielen - (pos - ie)); 3318 if (!mbssid_elem) 3319 break; 3320 3321 mbssid_info.profile_count = 3322 (1 << mbssid_elem[MBSSID_INDICATOR_POS]); 3323 3324 next_elem = 3325 mbssid_elem + mbssid_elem[TAG_LEN_POS] + MIN_IE_LEN; 3326 3327 /* Skip Element ID, Len, MaxBSSID Indicator */ 3328 if (!mbssid_info.split_profile && 3329 (mbssid_elem[TAG_LEN_POS] < VALID_ELEM_LEAST_LEN)) { 3330 break; 3331 } 3332 3333 /* 3334 * Find if the next IE is MBSSID, if not, then scan through 3335 * the IE list and find the next MBSSID tag, if present. 3336 * Once we find the MBSSID tag, check if this MBSSID tag has 3337 * the other fragmented part of the non Tx profile. 3338 */ 3339 3340 mbssid_info.split_profile = 3341 util_scan_is_split_prof_found(next_elem, ie, ielen); 3342 3343 for (subelement = mbssid_elem + SUBELEMENT_START_POS; 3344 subelement < (next_elem - 1); 3345 subelement += MIN_IE_LEN + subelement[TAG_LEN_POS]) { 3346 subie_len = subelement[TAG_LEN_POS]; 3347 3348 /* 3349 * if prof_residue is true, that means we are 3350 * in the continuation of the fragmented profile part, 3351 * present in the next MBSSD IE else this profile 3352 * is a non fragmented non tx BSSID profile. 3353 */ 3354 3355 if (mbssid_info.prof_residue) 3356 mbssid_info.split_prof_continue = true; 3357 else 3358 mbssid_info.split_prof_continue = false; 3359 3360 if (subie_len > MAX_SUBELEM_LEN) { 3361 scm_debug_rl("Corrupt frame with subie_len: %d " 3362 "split_prof_continue: %d,prof_residue: %d", 3363 subie_len, 3364 mbssid_info.split_prof_continue, 3365 mbssid_info.prof_residue); 3366 if (mbssid_info.split_prof_continue) { 3367 qdf_mem_free(split_prof_start); 3368 split_prof_start = NULL; 3369 } 3370 3371 qdf_mem_free(new_ie); 3372 return QDF_STATUS_E_INVAL; 3373 } 3374 3375 if ((next_elem - subelement) < 3376 (MIN_IE_LEN + subie_len)) 3377 break; 3378 3379 next_subelement = subelement + subie_len + MIN_IE_LEN; 3380 retval = util_handle_nontx_prof(mbssid_elem, subelement, 3381 next_subelement, 3382 &mbssid_info, 3383 bssid, new_bssid); 3384 3385 if (retval == INVALID_SPLIT_PROF) { 3386 scm_debug_rl("Corrupt frame with ID_POS: %d,TAG_LEN_POS: %d", 3387 subelement[ID_POS], 3388 subelement[TAG_LEN_POS]); 3389 qdf_mem_free(split_prof_start); 3390 split_prof_start = NULL; 3391 qdf_mem_free(new_ie); 3392 return QDF_STATUS_E_INVAL; 3393 } else if (retval == INVALID_NONTX_PROF) { 3394 continue; 3395 } 3396 3397 /* 3398 * Merging parts of nontx profile- 3399 * Just for understanding, let's make an assumption 3400 * that nontx profile is fragmented across MBSSIE1 3401 * and MBSSIE2. 3402 * mbssid_info.prof_residue being set indicates 3403 * that the ongoing nontx profile is part of split 3404 * profile, whose other fragmented part is present 3405 * in MBSSIE2. 3406 * So once prof_residue is set, we need to 3407 * identify whether we are accessing the split 3408 * profile in MBSSIE1 or MBSSIE2. 3409 * If we are in MBSSIE1, then copy the part of split 3410 * profile from MBSSIE1 into a new buffer and then 3411 * move to the next part of the split profile which 3412 * is present in MBSSIE2 and append that part into 3413 * the new buffer. 3414 * Once the full profile is accumulated, go ahead with 3415 * the ie generation and length calculation of the 3416 * new frame. 3417 */ 3418 3419 if (mbssid_info.prof_residue) { 3420 if (!mbssid_info.split_prof_continue) { 3421 split_prof_start = 3422 qdf_mem_malloc(ielen); 3423 if (!split_prof_start) { 3424 scm_err_rl("Malloc failed"); 3425 qdf_mem_free(new_ie); 3426 return QDF_STATUS_E_NOMEM; 3427 } 3428 3429 qdf_mem_copy(split_prof_start, 3430 subelement, 3431 (subie_len + 3432 MIN_IE_LEN)); 3433 split_prof_end = (split_prof_start + 3434 subie_len + 3435 MIN_IE_LEN); 3436 break; 3437 } 3438 3439 /* 3440 * Currently we are accessing other part of the 3441 * split profile present in the subsequent 3442 * MBSSIE. There is a possibility that one 3443 * non tx profile is spread across more than 3444 * two MBSSID tag as well. This code will 3445 * handle such scenario. 3446 */ 3447 3448 if (split_prof_end) { 3449 qdf_mem_copy(split_prof_end, 3450 (subelement + MIN_IE_LEN), 3451 subie_len); 3452 split_prof_end += subie_len; 3453 } 3454 3455 /* 3456 * When to stop the process of accumulating 3457 * parts of split profile, is decided by 3458 * mbssid_info.prof_residue. prof_residue 3459 * could be made false if there is not any 3460 * continuation of the split profile. 3461 * which could be identified by two factors 3462 * 1. By checking if the next MBSSIE's first 3463 * non tx profile is not a fragmented one or 3464 * 2. there is a probability that first 3465 * subelement of MBSSIE2 is end if split 3466 * profile and the next subelement of MBSSIE2 3467 * is a non split one. 3468 */ 3469 3470 if (!mbssid_info.split_profile || 3471 (next_subelement[PAYLOAD_START_POS] == 3472 WLAN_ELEMID_NONTX_BSSID_CAP)) { 3473 mbssid_info.prof_residue = false; 3474 } 3475 3476 /* 3477 * Until above mentioned conditions are met, 3478 * we need to iterate and keep accumulating 3479 * the split profile contents. 3480 */ 3481 3482 if (mbssid_info.prof_residue) 3483 break; 3484 3485 if (split_prof_end) { 3486 split_prof_len = 3487 (split_prof_end - 3488 split_prof_start - MIN_IE_LEN); 3489 } 3490 } 3491 3492 if (mbssid_info.split_prof_continue) { 3493 nontx_profile = split_prof_start; 3494 subie_len = split_prof_len; 3495 } else { 3496 nontx_profile = subelement; 3497 } 3498 3499 new_ie_len = 3500 util_gen_new_ie(ie, ielen, 3501 (nontx_profile + 3502 PAYLOAD_START_POS), 3503 subie_len, new_ie, 3504 mbssid_info.profile_num); 3505 3506 if (!new_ie_len) { 3507 if (mbssid_info.split_prof_continue) { 3508 qdf_mem_free(split_prof_start); 3509 split_prof_start = NULL; 3510 split_prof_end = NULL; 3511 } 3512 continue; 3513 } 3514 3515 new_frame_len = frame_len - ielen + new_ie_len; 3516 3517 if (new_frame_len < 0 || new_frame_len > frame_len) { 3518 if (mbssid_info.split_prof_continue) { 3519 qdf_mem_free(split_prof_start); 3520 split_prof_start = NULL; 3521 } 3522 qdf_mem_free(new_ie); 3523 scm_debug_rl("Invalid frame:Stop MBSSIE parsing, Frame_len: %zu " 3524 "ielen:%u,new_ie_len:%u", 3525 frame_len, ielen, new_ie_len); 3526 return QDF_STATUS_E_INVAL; 3527 } 3528 3529 new_frame = qdf_mem_malloc(new_frame_len); 3530 if (!new_frame) { 3531 if (mbssid_info.split_prof_continue) { 3532 qdf_mem_free(split_prof_start); 3533 split_prof_start = NULL; 3534 } 3535 qdf_mem_free(new_ie); 3536 scm_err_rl("Malloc for new_frame failed"); 3537 scm_err_rl("split_prof_continue: %d", 3538 mbssid_info.split_prof_continue); 3539 return QDF_STATUS_E_NOMEM; 3540 } 3541 3542 /* 3543 * Copy the header(24byte), timestamp(8 byte), 3544 * beaconinterval(2byte) and capability(2byte) 3545 */ 3546 qdf_mem_copy(new_frame, frame, FIXED_LENGTH); 3547 /* Copy the new ie generated from MBSSID profile*/ 3548 hdr = (struct wlan_frame_hdr *)new_frame; 3549 qdf_mem_copy(hdr->i_addr2, new_bssid, 3550 QDF_MAC_ADDR_SIZE); 3551 qdf_mem_copy(hdr->i_addr3, new_bssid, 3552 QDF_MAC_ADDR_SIZE); 3553 bcn = (struct wlan_bcn_frame *) 3554 (new_frame + sizeof(struct wlan_frame_hdr)); 3555 /* update the non-tx capability */ 3556 qdf_mem_copy(&bcn->capability, 3557 nontx_profile + CAP_INFO_POS, 3558 CAP_INFO_LEN); 3559 3560 /* Copy the new ie generated from MBSSID profile*/ 3561 qdf_mem_copy(new_frame + 3562 offsetof(struct wlan_bcn_frame, ie) + 3563 sizeof(struct wlan_frame_hdr), 3564 new_ie, new_ie_len); 3565 if (scan_obj->cb.inform_mbssid_bcn_prb_rsp) 3566 scan_obj->cb.inform_mbssid_bcn_prb_rsp( 3567 new_frame, new_frame_len, 3568 frm_subtype, new_bssid); 3569 3570 status = util_scan_gen_scan_entry(pdev, new_frame, 3571 new_frame_len, 3572 frm_subtype, 3573 rx_param, 3574 &mbssid_info, 3575 scan_list); 3576 if (QDF_IS_STATUS_ERROR(status)) { 3577 if (mbssid_info.split_prof_continue) { 3578 qdf_mem_free(split_prof_start); 3579 split_prof_start = NULL; 3580 split_prof_end = NULL; 3581 qdf_mem_zero(&mbssid_info, 3582 sizeof(mbssid_info)); 3583 } 3584 qdf_mem_free(new_frame); 3585 scm_debug_rl("failed to generate a scan entry " 3586 "split_prof_continue: %d", 3587 mbssid_info.split_prof_continue); 3588 break; 3589 } 3590 /* scan entry makes its own copy so free the frame*/ 3591 if (mbssid_info.split_prof_continue) { 3592 qdf_mem_free(split_prof_start); 3593 split_prof_start = NULL; 3594 split_prof_end = NULL; 3595 } 3596 qdf_mem_free(new_frame); 3597 } 3598 3599 pos = next_elem; 3600 } 3601 qdf_mem_free(new_ie); 3602 3603 if (split_prof_start) 3604 qdf_mem_free(split_prof_start); 3605 3606 return QDF_STATUS_SUCCESS; 3607 } 3608 #else 3609 static QDF_STATUS util_scan_parse_mbssid(struct wlan_objmgr_pdev *pdev, 3610 uint8_t *frame, qdf_size_t frame_len, 3611 uint32_t frm_subtype, 3612 struct mgmt_rx_event_params *rx_param, 3613 qdf_list_t *scan_list) 3614 { 3615 return QDF_STATUS_SUCCESS; 3616 } 3617 #endif 3618 3619 #if defined(WLAN_FEATURE_11BE) && defined(WLAN_FEATURE_11BE_MLO_MBSSID) 3620 /* 3621 * util_scan_gen_txvap_scan_entry() - Strip out the MBSSID tag from the received 3622 * frame and update the modified frame length before generating a scan entry. 3623 * It is redundant to have MBSSID information as part of the TX vap/ profile 3624 * specific scan entry. 3625 * 3626 * @pdev: pdev context 3627 * @frame: Unsoiled frame passed from util_scan_parse_beacon_frame() 3628 * @frame_len: Length of the unsoiled frame 3629 * @ie_list: Points to the start of IE list in parent/ unsoiled frame 3630 * @ielen: Length of the complete IE list from parent/ unsoiled frame 3631 * @frm_subtype: Frame subtype 3632 * @rx_param: host mgmt header params 3633 * @scan_list: Scan entry list of bss candidates after filtering 3634 * @mbssid_info: Data structure to carry MBSSID information 3635 * 3636 * Return: False if the scan entry generation is not successful 3637 */ 3638 static QDF_STATUS 3639 util_scan_gen_txvap_scan_entry(struct wlan_objmgr_pdev *pdev, 3640 uint8_t *frame, qdf_size_t frame_len, 3641 uint8_t *ie_list, uint32_t ielen, 3642 uint32_t frm_subtype, 3643 struct mgmt_rx_event_params *rx_param, 3644 qdf_list_t *scan_list, 3645 struct scan_mbssid_info *mbssid_info) 3646 { 3647 uint8_t *src_ie, *dest_ptr, *container; 3648 uint16_t new_frame_len, new_ie_len = 0; 3649 uint8_t *trimmed_frame, fixed_len = 0; 3650 QDF_STATUS status = QDF_STATUS_SUCCESS; 3651 3652 /* 3653 * Allocate a buffer to copy only the TX VAP information after 3654 * stripping out the MBSSID IE from the parent beacon. 3655 * The allocation size should be the size of a frame as at 3656 * this point it is unknown what would be the new frame length 3657 * after stripping the MBSSID IE. 3658 */ 3659 container = qdf_mem_malloc(frame_len); 3660 if (!container) { 3661 scm_err_rl("Malloc for container failed"); 3662 return QDF_STATUS_E_NOMEM; 3663 } 3664 3665 dest_ptr = &container[0]; 3666 fixed_len = sizeof(struct wlan_frame_hdr) + 3667 offsetof(struct wlan_bcn_frame, ie); 3668 3669 /*Copy the data till IE list before procesisng the IE one by one*/ 3670 qdf_mem_copy(dest_ptr, frame, fixed_len); 3671 3672 dest_ptr += fixed_len; 3673 src_ie = ie_list; 3674 3675 /* 3676 * Go through the IE list from the parent beacon and copy one by one. 3677 * Skip copying it to the container if it's an MBSSID tag. 3678 */ 3679 while (((src_ie + src_ie[TAG_LEN_POS] + MIN_IE_LEN) - 3680 ie_list) <= ielen) { 3681 if (src_ie[ID_POS] == WLAN_ELEMID_MULTIPLE_BSSID) { 3682 src_ie += src_ie[TAG_LEN_POS] + MIN_IE_LEN; 3683 continue; 3684 } 3685 3686 qdf_mem_copy(dest_ptr, src_ie, 3687 (src_ie[TAG_LEN_POS] + MIN_IE_LEN)); 3688 3689 dest_ptr += src_ie[TAG_LEN_POS] + MIN_IE_LEN; 3690 if (((src_ie + src_ie[TAG_LEN_POS] + 3691 MIN_IE_LEN) - ie_list) >= ielen) 3692 break; 3693 3694 src_ie += src_ie[TAG_LEN_POS] + MIN_IE_LEN; 3695 } 3696 3697 if (dest_ptr > container) 3698 new_ie_len = dest_ptr - (container + fixed_len); 3699 3700 new_frame_len = frame_len - ielen + new_ie_len; 3701 3702 /* 3703 * At the start of this handler, we have allocated a memory block 3704 * of size same as a full beacon frame size, as we are not sure 3705 * of what would be the size of the new frame. After stripping out 3706 * the MBSSID tag from the parent beacon, there are some unused 3707 * memory. Hence do another malloc of the new frame length 3708 * (length of the new frame which has only TX VAP information) 3709 * and copy the needed data from the container, then free the 3710 * memory corresponds to container. 3711 * Post copy, use the trimmed frame and the new frame length 3712 * to generate scan entry for the TX profile. 3713 */ 3714 trimmed_frame = qdf_mem_malloc(new_frame_len); 3715 if (!trimmed_frame) { 3716 scm_err_rl("Malloc for trimmed frame failed"); 3717 qdf_mem_free(container); 3718 return QDF_STATUS_E_NOMEM; 3719 } 3720 3721 qdf_mem_copy(trimmed_frame, container, new_frame_len); 3722 qdf_mem_free(container); 3723 3724 status = util_scan_gen_scan_entry(pdev, trimmed_frame, 3725 new_frame_len, 3726 frm_subtype, 3727 rx_param, 3728 mbssid_info, 3729 scan_list); 3730 3731 if (QDF_IS_STATUS_ERROR(status)) 3732 scm_debug_rl("Failed to create a scan entry"); 3733 3734 qdf_mem_free(trimmed_frame); 3735 return status; 3736 } 3737 3738 /* 3739 * util_scan_parse_eht_beacon() : This API will be executed 3740 * only for 11BE platforms as per current design. 3741 * IF MBSSID IE is present in the beacon then 3742 * scan component will create a new entry for 3743 * each BSSID found in the MBSSID 3744 * util_scan_parse_mbssid() takes care of creating 3745 * scan entries for every non tx profile present in 3746 * the MBSSID tag. 3747 * util_scan_gen_txvap_scan_entry() helps in generating 3748 * scan entry for the tx profile. 3749 */ 3750 static QDF_STATUS 3751 util_scan_parse_eht_beacon(struct wlan_objmgr_pdev *pdev, 3752 uint8_t *frame, qdf_size_t frame_len, 3753 uint8_t *ie_list, uint32_t ielen, 3754 uint32_t frm_subtype, 3755 struct mgmt_rx_event_params *rx_param, 3756 qdf_list_t *scan_list, 3757 struct scan_mbssid_info *mbssid_info, 3758 uint8_t *mbssid_ie) 3759 { 3760 QDF_STATUS status = QDF_STATUS_SUCCESS; 3761 3762 if (mbssid_ie) { 3763 status = util_scan_parse_mbssid(pdev, frame, frame_len, 3764 frm_subtype, rx_param, 3765 scan_list); 3766 3767 if (QDF_IS_STATUS_ERROR(status)) { 3768 scm_debug_rl("NonTx prof: Failed to create scan entry"); 3769 return status; 3770 } 3771 3772 status = util_scan_gen_txvap_scan_entry(pdev, frame, 3773 frame_len, ie_list, 3774 ielen, frm_subtype, 3775 rx_param, scan_list, 3776 mbssid_info); 3777 3778 if (QDF_IS_STATUS_ERROR(status)) 3779 scm_debug_rl("TX prof: Failed to create scan entry"); 3780 3781 return status; 3782 } 3783 3784 /*For Non MBSSIE case*/ 3785 status = util_scan_gen_scan_entry(pdev, frame, frame_len, 3786 frm_subtype, rx_param, 3787 mbssid_info, scan_list); 3788 3789 if (QDF_IS_STATUS_ERROR(status)) 3790 scm_debug_rl("Non-MBSSIE frame: Failed to create scan entry"); 3791 3792 return status; 3793 } 3794 3795 static bool 3796 util_scan_is_platform_eht_capable(struct wlan_objmgr_pdev *pdev) 3797 { 3798 struct wlan_objmgr_psoc *psoc = NULL; 3799 struct wlan_lmac_if_tx_ops *tx_ops = NULL; 3800 struct wlan_lmac_if_scan_tx_ops *scan_ops = NULL; 3801 uint8_t pdev_id; 3802 3803 psoc = wlan_pdev_get_psoc(pdev); 3804 if (!psoc) { 3805 scm_debug_rl("psoc is null"); 3806 return false; 3807 } 3808 tx_ops = wlan_psoc_get_lmac_if_txops(psoc); 3809 if (!tx_ops) { 3810 scm_debug_rl("tx_ops is null"); 3811 return false; 3812 } 3813 scan_ops = &tx_ops->scan; 3814 if (!scan_ops) { 3815 scm_debug_rl("scan_ops is null"); 3816 return false; 3817 } 3818 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); 3819 3820 if (scan_ops->is_platform_eht_capable) 3821 return scan_ops->is_platform_eht_capable(psoc, pdev_id); 3822 3823 return false; 3824 } 3825 #else 3826 static QDF_STATUS 3827 util_scan_parse_eht_beacon(struct wlan_objmgr_pdev *pdev, 3828 uint8_t *frame, qdf_size_t frame_len, 3829 uint8_t *ie_list, uint32_t ielen, 3830 uint32_t frm_subtype, 3831 struct mgmt_rx_event_params *rx_param, 3832 qdf_list_t *scan_list, 3833 struct scan_mbssid_info *mbssid_info, 3834 uint8_t *mbssid_ie) 3835 { 3836 return QDF_STATUS_SUCCESS; 3837 } 3838 3839 static bool 3840 util_scan_is_platform_eht_capable(struct wlan_objmgr_pdev *pdev) 3841 { 3842 return false; 3843 } 3844 #endif 3845 3846 static QDF_STATUS 3847 util_scan_parse_beacon_frame(struct wlan_objmgr_pdev *pdev, 3848 uint8_t *frame, 3849 qdf_size_t frame_len, 3850 uint32_t frm_subtype, 3851 struct mgmt_rx_event_params *rx_param, 3852 qdf_list_t *scan_list) 3853 { 3854 struct wlan_bcn_frame *bcn; 3855 struct wlan_frame_hdr *hdr; 3856 uint8_t *mbssid_ie = NULL, *extcap_ie; 3857 uint32_t ie_len = 0; 3858 QDF_STATUS status = QDF_STATUS_E_FAILURE; 3859 struct scan_mbssid_info mbssid_info = { 0 }; 3860 uint8_t *ie_list; 3861 bool eht_support = false; 3862 3863 hdr = (struct wlan_frame_hdr *)frame; 3864 bcn = (struct wlan_bcn_frame *) 3865 (frame + sizeof(struct wlan_frame_hdr)); 3866 ie_list = (uint8_t *)&bcn->ie; 3867 ie_len = (uint16_t)(frame_len - 3868 sizeof(struct wlan_frame_hdr) - 3869 offsetof(struct wlan_bcn_frame, ie)); 3870 3871 extcap_ie = util_scan_find_ie(WLAN_ELEMID_XCAPS, 3872 (uint8_t *)&bcn->ie, ie_len); 3873 /* Process MBSSID when Multiple BSSID (Bit 22) is set in Ext Caps */ 3874 if (extcap_ie && 3875 extcap_ie[1] >= 3 && extcap_ie[1] <= WLAN_EXTCAP_IE_MAX_LEN && 3876 (extcap_ie[4] & 0x40)) { 3877 mbssid_ie = util_scan_find_ie(WLAN_ELEMID_MULTIPLE_BSSID, 3878 (uint8_t *)&bcn->ie, ie_len); 3879 if (mbssid_ie) { 3880 if (mbssid_ie[1] <= 0) { 3881 scm_debug("MBSSID IE length is wrong %d", 3882 mbssid_ie[1]); 3883 return status; 3884 } 3885 qdf_mem_copy(&mbssid_info.trans_bssid, 3886 hdr->i_addr3, QDF_MAC_ADDR_SIZE); 3887 mbssid_info.profile_count = 1 << mbssid_ie[2]; 3888 } 3889 } 3890 3891 eht_support = util_scan_is_platform_eht_capable(pdev); 3892 3893 if (eht_support) { 3894 status = util_scan_parse_eht_beacon(pdev, frame, frame_len, 3895 ie_list, ie_len, 3896 frm_subtype, rx_param, 3897 scan_list, &mbssid_info, 3898 mbssid_ie); 3899 return status; 3900 } 3901 3902 status = util_scan_gen_scan_entry(pdev, frame, frame_len, 3903 frm_subtype, rx_param, 3904 &mbssid_info, 3905 scan_list); 3906 3907 if (mbssid_ie) 3908 status = util_scan_parse_mbssid(pdev, frame, frame_len, 3909 frm_subtype, rx_param, 3910 scan_list); 3911 3912 if (QDF_IS_STATUS_ERROR(status)) 3913 scm_debug_rl("Failed to create scan entry"); 3914 3915 return status; 3916 } 3917 3918 qdf_list_t * 3919 util_scan_unpack_beacon_frame(struct wlan_objmgr_pdev *pdev, uint8_t *frame, 3920 qdf_size_t frame_len, uint32_t frm_subtype, 3921 struct mgmt_rx_event_params *rx_param) 3922 { 3923 qdf_list_t *scan_list; 3924 QDF_STATUS status; 3925 3926 scan_list = qdf_mem_malloc_atomic(sizeof(*scan_list)); 3927 if (!scan_list) { 3928 scm_err("failed to allocate scan_list"); 3929 return NULL; 3930 } 3931 qdf_list_create(scan_list, MAX_SCAN_CACHE_SIZE); 3932 3933 status = util_scan_parse_beacon_frame(pdev, frame, frame_len, 3934 frm_subtype, rx_param, 3935 scan_list); 3936 if (QDF_IS_STATUS_ERROR(status)) { 3937 ucfg_scan_purge_results(scan_list); 3938 return NULL; 3939 } 3940 3941 return scan_list; 3942 } 3943 3944 QDF_STATUS 3945 util_scan_entry_update_mlme_info(struct wlan_objmgr_pdev *pdev, 3946 struct scan_cache_entry *scan_entry) 3947 { 3948 3949 if (!pdev || !scan_entry) { 3950 scm_err("pdev 0x%pK, scan_entry: 0x%pK", pdev, scan_entry); 3951 return QDF_STATUS_E_INVAL; 3952 } 3953 3954 return scm_update_scan_mlme_info(pdev, scan_entry); 3955 } 3956 3957 bool util_is_scan_completed(struct scan_event *event, bool *success) 3958 { 3959 if ((event->type == SCAN_EVENT_TYPE_COMPLETED) || 3960 (event->type == SCAN_EVENT_TYPE_DEQUEUED) || 3961 (event->type == SCAN_EVENT_TYPE_START_FAILED)) { 3962 if ((event->type == SCAN_EVENT_TYPE_COMPLETED) && 3963 (event->reason == SCAN_REASON_COMPLETED)) 3964 *success = true; 3965 else 3966 *success = false; 3967 3968 return true; 3969 } 3970 3971 *success = false; 3972 return false; 3973 } 3974 3975 #if defined(WLAN_SAE_SINGLE_PMK) && defined(WLAN_FEATURE_ROAM_OFFLOAD) 3976 bool 3977 util_scan_entry_single_pmk(struct wlan_objmgr_psoc *psoc, 3978 struct scan_cache_entry *scan_entry) 3979 { 3980 if (scan_entry->ie_list.single_pmk && 3981 wlan_mlme_is_sae_single_pmk_enabled(psoc)) 3982 return true; 3983 3984 return false; 3985 } 3986 #endif 3987