1 /* 2 * Copyright (c) 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 any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 /** 19 * DOC: contains son hdd API implementation 20 */ 21 22 #include <qdf_types.h> 23 #include <wlan_hdd_main.h> 24 #include <wlan_hdd_sta_info.h> 25 #include <wlan_hdd_regulatory.h> 26 #include <os_if_son.h> 27 #include <sap_internal.h> 28 #include <wma_api.h> 29 #include <wlan_hdd_hostapd.h> 30 #include <wlan_reg_services_api.h> 31 #include <son_ucfg_api.h> 32 #include <wlan_hdd_son.h> 33 #include <wlan_hdd_object_manager.h> 34 #include <wlan_hdd_stats.h> 35 #include "wlan_cfg80211_mc_cp_stats.h" 36 37 static const struct son_chan_width { 38 enum ieee80211_cwm_width son_chwidth; 39 enum phy_ch_width phy_chwidth; 40 } son_chwidth_info[] = { 41 { 42 .son_chwidth = IEEE80211_CWM_WIDTH20, 43 .phy_chwidth = CH_WIDTH_20MHZ, 44 }, 45 { 46 .son_chwidth = IEEE80211_CWM_WIDTH40, 47 .phy_chwidth = CH_WIDTH_40MHZ, 48 }, 49 { 50 .son_chwidth = IEEE80211_CWM_WIDTH80, 51 .phy_chwidth = CH_WIDTH_80MHZ, 52 }, 53 { 54 .son_chwidth = IEEE80211_CWM_WIDTH160, 55 .phy_chwidth = CH_WIDTH_160MHZ, 56 }, 57 { 58 .son_chwidth = IEEE80211_CWM_WIDTH80_80, 59 .phy_chwidth = CH_WIDTH_80P80MHZ, 60 }, 61 #ifdef WLAN_FEATURE_11BE 62 { 63 .son_chwidth = IEEE80211_CWM_WIDTH320, 64 .phy_chwidth = CH_WIDTH_320MHZ, 65 }, 66 #endif 67 }; 68 69 /** 70 * hdd_son_is_acs_in_progress() - whether acs is in progress or not 71 * @vdev: vdev 72 * 73 * Return: true if acs is in progress 74 */ 75 static uint32_t hdd_son_is_acs_in_progress(struct wlan_objmgr_vdev *vdev) 76 { 77 struct wlan_hdd_link_info *link_info; 78 bool in_progress = false; 79 80 if (!vdev) { 81 hdd_err("null vdev"); 82 return in_progress; 83 } 84 85 link_info = wlan_hdd_get_link_info_from_objmgr(vdev); 86 if (!link_info) { 87 hdd_err("null adapter"); 88 return in_progress; 89 } 90 91 if (!hdd_adapter_is_ap(link_info->adapter)) { 92 hdd_err("vdev id %d is not AP", link_info->vdev_id); 93 return in_progress; 94 } 95 96 in_progress = qdf_atomic_read(&link_info->session.ap.acs_in_progress); 97 98 return in_progress; 99 } 100 101 /** 102 * hdd_son_chan_width_to_chan_width() - translate son chan width 103 * to mac chan width 104 * @son_chwidth: son chan width 105 * 106 * Return: mac chan width 107 */ 108 static enum eSirMacHTChannelWidth hdd_son_chan_width_to_chan_width( 109 enum ieee80211_cwm_width son_chwidth) 110 { 111 enum eSirMacHTChannelWidth chwidth; 112 113 switch (son_chwidth) { 114 case IEEE80211_CWM_WIDTH20: 115 chwidth = eHT_CHANNEL_WIDTH_20MHZ; 116 break; 117 case IEEE80211_CWM_WIDTH40: 118 chwidth = eHT_CHANNEL_WIDTH_40MHZ; 119 break; 120 case IEEE80211_CWM_WIDTH80: 121 chwidth = eHT_CHANNEL_WIDTH_80MHZ; 122 break; 123 case IEEE80211_CWM_WIDTH160: 124 chwidth = eHT_CHANNEL_WIDTH_160MHZ; 125 break; 126 case IEEE80211_CWM_WIDTH80_80: 127 chwidth = eHT_CHANNEL_WIDTH_80P80MHZ; 128 break; 129 default: 130 chwidth = eHT_MAX_CHANNEL_WIDTH; 131 } 132 133 return chwidth; 134 } 135 136 /** 137 * hdd_son_set_chwidth() - set son chan width 138 * @vdev: vdev 139 * @son_chwidth: son chan width 140 * 141 * Return: 0 on success, negative errno on failure 142 */ 143 static int hdd_son_set_chwidth(struct wlan_objmgr_vdev *vdev, 144 enum ieee80211_cwm_width son_chwidth) 145 { 146 enum eSirMacHTChannelWidth chwidth; 147 struct wlan_hdd_link_info *link_info; 148 149 if (!vdev) { 150 hdd_err("null vdev"); 151 return -EINVAL; 152 } 153 154 link_info = wlan_hdd_get_link_info_from_objmgr(vdev); 155 if (!link_info) { 156 hdd_err("null adapter"); 157 return -EINVAL; 158 } 159 160 chwidth = hdd_son_chan_width_to_chan_width(son_chwidth); 161 162 return hdd_set_mac_chan_width(link_info->adapter, chwidth); 163 } 164 165 /** 166 * hdd_chan_width_to_son_chwidth() - translate mac chan width 167 * to son chan width 168 * @chwidth: mac chan width 169 * 170 * Return: son chan width 171 */ 172 static enum ieee80211_cwm_width hdd_chan_width_to_son_chwidth( 173 enum eSirMacHTChannelWidth chwidth) 174 { 175 enum ieee80211_cwm_width son_chwidth; 176 177 switch (chwidth) { 178 case eHT_CHANNEL_WIDTH_20MHZ: 179 son_chwidth = IEEE80211_CWM_WIDTH20; 180 break; 181 case eHT_CHANNEL_WIDTH_40MHZ: 182 son_chwidth = IEEE80211_CWM_WIDTH40; 183 break; 184 case eHT_CHANNEL_WIDTH_80MHZ: 185 son_chwidth = IEEE80211_CWM_WIDTH80; 186 break; 187 case eHT_CHANNEL_WIDTH_160MHZ: 188 son_chwidth = IEEE80211_CWM_WIDTH160; 189 break; 190 case eHT_CHANNEL_WIDTH_80P80MHZ: 191 son_chwidth = IEEE80211_CWM_WIDTH80_80; 192 break; 193 default: 194 son_chwidth = IEEE80211_CWM_WIDTHINVALID; 195 } 196 197 return son_chwidth; 198 } 199 200 /** 201 * hdd_phy_chwidth_to_son_chwidth() - translate phy chan width 202 * to son chan width 203 * @chwidth: phy chan width 204 * 205 * Return: son chan width 206 */ 207 static enum ieee80211_cwm_width 208 hdd_phy_chwidth_to_son_chwidth(enum phy_ch_width chwidth) 209 { 210 int i; 211 212 for (i = 0; i < ARRAY_SIZE(son_chwidth_info); i++) { 213 if (son_chwidth_info[i].phy_chwidth == chwidth) 214 return son_chwidth_info[i].son_chwidth; 215 } 216 217 hdd_err("Unsupported channel width %d", chwidth); 218 return IEEE80211_CWM_WIDTHINVALID; 219 } 220 221 /** 222 * hdd_son_get_chwidth() - get chan width 223 * @vdev: vdev 224 * 225 * Return: son chan width 226 */ 227 static enum ieee80211_cwm_width hdd_son_get_chwidth( 228 struct wlan_objmgr_vdev *vdev) 229 { 230 struct wlan_channel *des_chan; 231 232 if (!vdev) { 233 hdd_err("null vdev"); 234 return IEEE80211_CWM_WIDTHINVALID; 235 } 236 237 des_chan = wlan_vdev_mlme_get_des_chan(vdev); 238 239 return hdd_phy_chwidth_to_son_chwidth(des_chan->ch_width); 240 } 241 242 /** 243 * hdd_son_chan_ext_offset_to_chan_type() - translate son chan extend offset 244 * to chan type 245 * @son_chan_ext_offset: son chan ext offset 246 * 247 * Return: tSirMacHTChannelType 248 */ 249 static tSirMacHTChannelType hdd_son_chan_ext_offset_to_chan_type( 250 enum sec20_chan_offset son_chan_ext_offset) 251 { 252 tSirMacHTChannelType chan_type; 253 254 switch (son_chan_ext_offset) { 255 case EXT_CHAN_OFFSET_ABOVE: 256 chan_type = eHT_CHAN_HT40PLUS; 257 break; 258 case EXT_CHAN_OFFSET_BELOW: 259 chan_type = eHT_CHAN_HT40MINUS; 260 break; 261 default: 262 chan_type = eHT_CHAN_HT20; 263 break; 264 } 265 266 return chan_type; 267 } 268 269 /** 270 * hdd_son_set_chan_ext_offset() - set son chan extend offset 271 * @vdev: vdev 272 * @son_chan_ext_offset: son chan extend offset 273 * 274 * Return: 0 on success, negative errno on failure 275 */ 276 static int hdd_son_set_chan_ext_offset( 277 struct wlan_objmgr_vdev *vdev, 278 enum sec20_chan_offset son_chan_ext_offset) 279 { 280 enum eSirMacHTChannelType chan_type; 281 QDF_STATUS status; 282 int retval = -EINVAL; 283 struct hdd_adapter *adapter; 284 285 if (!vdev) { 286 hdd_err("null vdev"); 287 return retval; 288 } 289 290 link_info = wlan_hdd_get_link_info_from_objmgr(vdev); 291 if (!link_info) { 292 hdd_err("null adapter"); 293 return retval; 294 } 295 296 if (!hdd_adapter_is_ap(link_info->adapter)) { 297 hdd_err("vdev id %d is not AP", link_info->vdev_id); 298 return retval; 299 } 300 301 retval = 0; 302 chan_type = hdd_son_chan_ext_offset_to_chan_type(son_chan_ext_offset); 303 status = hdd_set_sap_ht2040_mode(link_info->adapter, chan_type); 304 if (status != QDF_STATUS_SUCCESS) { 305 hdd_err("Cannot set SAP HT20/40 mode!"); 306 retval = -EINVAL; 307 } 308 309 return retval; 310 } 311 312 /** 313 * hdd_chan_type_to_son_chan_ext_offset() - translate tSirMacHTChannelType 314 * to son chan extend offset 315 * @chan_type: tSirMacHTChannelType 316 * 317 * Return: son chan extend offset 318 */ 319 static enum sec20_chan_offset hdd_chan_type_to_son_chan_ext_offset( 320 tSirMacHTChannelType chan_type) 321 { 322 enum sec20_chan_offset son_chan_ext_offset; 323 324 switch (chan_type) { 325 case eHT_CHAN_HT40PLUS: 326 son_chan_ext_offset = EXT_CHAN_OFFSET_ABOVE; 327 break; 328 case eHT_CHAN_HT40MINUS: 329 son_chan_ext_offset = EXT_CHAN_OFFSET_BELOW; 330 break; 331 default: 332 son_chan_ext_offset = EXT_CHAN_OFFSET_NA; 333 break; 334 } 335 336 return son_chan_ext_offset; 337 } 338 339 /** 340 * hdd_son_get_chan_ext_offset() - get chan extend offset 341 * @vdev: vdev 342 * 343 * Return: enum sec20_chan_offset 344 */ 345 static enum sec20_chan_offset hdd_son_get_chan_ext_offset( 346 struct wlan_objmgr_vdev *vdev) 347 { 348 enum eSirMacHTChannelType chan_type; 349 QDF_STATUS status; 350 struct wlan_hdd_link_info *link_info; 351 352 if (!vdev) { 353 hdd_err("null vdev"); 354 return 0; 355 } 356 357 link_info = wlan_hdd_get_link_info_from_objmgr(vdev); 358 if (!link_info) { 359 hdd_err("null adapter"); 360 return 0; 361 } 362 363 if (!hdd_adapter_is_ap(link_info->adapter)) { 364 hdd_err("vdev id %d is not AP", link_info->vdev_id); 365 return 0; 366 } 367 368 status = hdd_get_sap_ht2040_mode(link_info->adapter, &chan_type); 369 if (status != QDF_STATUS_SUCCESS) { 370 hdd_err("Cannot set SAP HT20/40 mode!"); 371 return 0; 372 } 373 374 return hdd_chan_type_to_son_chan_ext_offset(chan_type); 375 } 376 377 /** 378 * hdd_son_bandwidth_to_phymode() - get new eCsrPhyMode according 379 * to son band width 380 * @son_bandwidth: son band width 381 * @old_phymode: old eCsrPhyMode 382 * @phymode: new eCsrPhyMode to get 383 * 384 * Return: void 385 */ 386 static void hdd_son_bandwidth_to_phymode(uint32_t son_bandwidth, 387 eCsrPhyMode old_phymode, 388 eCsrPhyMode *phymode) 389 { 390 *phymode = old_phymode; 391 392 switch (son_bandwidth) { 393 case HT20: 394 case HT40: 395 *phymode = eCSR_DOT11_MODE_11n; 396 break; 397 case VHT20: 398 case VHT40: 399 case VHT80: 400 case VHT160: 401 case VHT80_80: 402 *phymode = eCSR_DOT11_MODE_11ac; 403 break; 404 case HE20: 405 case HE40: 406 case HE80: 407 case HE160: 408 case HE80_80: 409 *phymode = eCSR_DOT11_MODE_11ax; 410 break; 411 default: 412 break; 413 } 414 } 415 416 /** 417 * hdd_son_bandwidth_to_bonding_mode() - son band with to bonding mode 418 * @son_bandwidth: son band width 419 * @bonding_mode: bonding mode to get 420 * 421 * Return: void 422 */ 423 static void hdd_son_bandwidth_to_bonding_mode(uint32_t son_bandwidth, 424 uint32_t *bonding_mode) 425 { 426 switch (son_bandwidth) { 427 case HT40: 428 case VHT40: 429 case VHT80: 430 case VHT160: 431 case VHT80_80: 432 case HE40: 433 case HE80: 434 case HE160: 435 case HE80_80: 436 *bonding_mode = WNI_CFG_CHANNEL_BONDING_MODE_ENABLE; 437 break; 438 default: 439 *bonding_mode = WNI_CFG_CHANNEL_BONDING_MODE_DISABLE; 440 } 441 } 442 443 /** 444 * hdd_son_set_bandwidth() - set band width 445 * @vdev: vdev 446 * @son_bandwidth: son band width 447 * 448 * Return: 0 on success, negative errno on failure 449 */ 450 static int hdd_son_set_bandwidth(struct wlan_objmgr_vdev *vdev, 451 uint32_t son_bandwidth) 452 { 453 eCsrPhyMode phymode; 454 eCsrPhyMode old_phymode; 455 uint8_t supported_band; 456 uint32_t bonding_mode; 457 struct wlan_hdd_link_info *link_info; 458 struct hdd_context *hdd_ctx; 459 460 if (!vdev) { 461 hdd_err("null vdev"); 462 return -EINVAL; 463 } 464 465 link_info = wlan_hdd_get_link_info_from_objmgr(vdev); 466 if (!link_info) { 467 hdd_err("null adapter"); 468 return -EINVAL; 469 } 470 471 hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter); 472 if (!hdd_ctx) { 473 hdd_err("null hdd ctx"); 474 return -EINVAL; 475 } 476 old_phymode = sme_get_phy_mode(hdd_ctx->mac_handle); 477 478 hdd_son_bandwidth_to_phymode(son_bandwidth, old_phymode, &phymode); 479 480 if (wlan_reg_is_6ghz_supported(hdd_ctx->psoc)) 481 supported_band = REG_BAND_MASK_ALL; 482 else 483 supported_band = BIT(REG_BAND_2G) | BIT(REG_BAND_5G); 484 485 hdd_son_bandwidth_to_bonding_mode(son_bandwidth, &bonding_mode); 486 487 return hdd_update_phymode(link_info->adapter, phymode, 488 supported_band, bonding_mode); 489 } 490 491 /** 492 * hdd_phymode_chwidth_to_son_bandwidth() - get son bandwidth from 493 * phymode and chwidth 494 * @phymode: eCsrPhyMode 495 * @chwidth: eSirMacHTChannelWidth 496 * 497 * Return: son bandwidth 498 */ 499 static uint32_t hdd_phymode_chwidth_to_son_bandwidth( 500 eCsrPhyMode phymode, 501 enum eSirMacHTChannelWidth chwidth) 502 { 503 uint32_t son_bandwidth = NONHT; 504 505 switch (phymode) { 506 case eCSR_DOT11_MODE_abg: 507 case eCSR_DOT11_MODE_11a: 508 case eCSR_DOT11_MODE_11b: 509 case eCSR_DOT11_MODE_11g: 510 case eCSR_DOT11_MODE_11g_ONLY: 511 case eCSR_DOT11_MODE_11b_ONLY: 512 son_bandwidth = NONHT; 513 break; 514 case eCSR_DOT11_MODE_11n: 515 case eCSR_DOT11_MODE_11n_ONLY: 516 son_bandwidth = HT20; 517 if (chwidth == eHT_CHANNEL_WIDTH_40MHZ) 518 son_bandwidth = HT40; 519 break; 520 case eCSR_DOT11_MODE_11ac: 521 case eCSR_DOT11_MODE_11ac_ONLY: 522 son_bandwidth = VHT20; 523 if (chwidth == eHT_CHANNEL_WIDTH_40MHZ) 524 son_bandwidth = VHT40; 525 else if (chwidth == eHT_CHANNEL_WIDTH_80MHZ) 526 son_bandwidth = VHT80; 527 else if (chwidth == eHT_CHANNEL_WIDTH_160MHZ) 528 son_bandwidth = VHT160; 529 else if (chwidth == eHT_CHANNEL_WIDTH_80P80MHZ) 530 son_bandwidth = VHT80_80; 531 break; 532 case eCSR_DOT11_MODE_11ax: 533 case eCSR_DOT11_MODE_11ax_ONLY: 534 case eCSR_DOT11_MODE_AUTO: 535 son_bandwidth = HE20; 536 if (chwidth == eHT_CHANNEL_WIDTH_40MHZ) 537 son_bandwidth = HE40; 538 else if (chwidth == eHT_CHANNEL_WIDTH_80MHZ) 539 son_bandwidth = HE80; 540 else if (chwidth == eHT_CHANNEL_WIDTH_160MHZ) 541 son_bandwidth = HE160; 542 else if (chwidth == eHT_CHANNEL_WIDTH_80P80MHZ) 543 son_bandwidth = HE80_80; 544 break; 545 default: 546 break; 547 } 548 549 return son_bandwidth; 550 } 551 552 /** 553 * hdd_son_get_bandwidth() - get band width 554 * @vdev: vdev 555 * 556 * Return: band width 557 */ 558 static uint32_t hdd_son_get_bandwidth(struct wlan_objmgr_vdev *vdev) 559 { 560 enum eSirMacHTChannelWidth chwidth; 561 eCsrPhyMode phymode; 562 struct hdd_context *hdd_ctx; 563 struct wlan_hdd_link_info *link_info; 564 565 if (!vdev) { 566 hdd_err("null vdev"); 567 return NONHT; 568 } 569 570 link_info = wlan_hdd_get_link_info_from_objmgr(vdev); 571 if (!link_info) { 572 hdd_err("null adapter"); 573 return NONHT; 574 } 575 576 chwidth = wma_cli_get_command(link_info->vdev_id, 577 wmi_vdev_param_chwidth, VDEV_CMD); 578 579 if (chwidth < 0) { 580 hdd_err("Failed to get chwidth"); 581 return NONHT; 582 } 583 584 hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter); 585 if (!hdd_ctx) { 586 hdd_err("null hdd ctx"); 587 return -NONHT; 588 } 589 590 phymode = sme_get_phy_mode(hdd_ctx->mac_handle); 591 592 return hdd_phymode_chwidth_to_son_bandwidth(phymode, chwidth); 593 } 594 595 /** 596 * hdd_son_band_to_band() - translate SON band mode to reg_wifi_band 597 * @band: given enum wlan_band_id 598 * 599 * Return: reg_wifi_band 600 */ 601 static enum reg_wifi_band hdd_son_band_to_band(enum wlan_band_id band) 602 { 603 enum reg_wifi_band reg_band = REG_BAND_UNKNOWN; 604 605 switch (band) { 606 case WLAN_BAND_2GHZ: 607 reg_band = REG_BAND_2G; 608 break; 609 case WLAN_BAND_5GHZ: 610 reg_band = REG_BAND_5G; 611 break; 612 case WLAN_BAND_6GHZ: 613 reg_band = REG_BAND_6G; 614 break; 615 default: 616 break; 617 } 618 619 return reg_band; 620 } 621 622 /** 623 * hdd_son_set_chan() - set chan 624 * @vdev: vdev 625 * @chan: given chan 626 * @son_band: given enum wlan_band_id 627 * 628 * Return: 0 on success, negative errno on failure 629 */ 630 static int hdd_son_set_chan(struct wlan_objmgr_vdev *vdev, int chan, 631 enum wlan_band_id son_band) 632 { 633 struct wlan_hdd_link_info *link_info; 634 enum reg_wifi_band band = hdd_son_band_to_band(son_band); 635 bool status; 636 qdf_freq_t freq; 637 struct wlan_objmgr_pdev *pdev; 638 struct wlan_objmgr_psoc *psoc; 639 640 if (!vdev) { 641 hdd_err("null vdev"); 642 return -EINVAL; 643 } 644 645 link_info = wlan_hdd_get_link_info_from_objmgr(vdev); 646 if (!link_info) { 647 hdd_err("null adapter"); 648 return -EINVAL; 649 } 650 651 if (!hdd_adapter_is_ap(link_info->adapter)) { 652 hdd_err("vdev id %d is not AP", link_info->vdev_id); 653 return -ENOTSUPP; 654 } 655 656 pdev = wlan_vdev_get_pdev(vdev); 657 if (!pdev) { 658 hdd_err("null pdev"); 659 return -EINVAL; 660 } 661 662 psoc = wlan_vdev_get_psoc(vdev); 663 if (!psoc) { 664 hdd_err("null psoc"); 665 return -EINVAL; 666 } 667 668 freq = wlan_reg_chan_band_to_freq(pdev, chan, BIT(band)); 669 status = policy_mgr_is_sap_allowed_on_dfs_freq(pdev, link_info->vdev_id, 670 freq); 671 if (!status) { 672 hdd_err("sap_allowed_on_dfs_freq check fails"); 673 return -EINVAL; 674 } 675 wlan_hdd_set_sap_csa_reason(psoc, link_info->vdev_id, 676 CSA_REASON_USER_INITIATED); 677 678 return hdd_softap_set_channel_change(link_info->adapter->dev, freq, 679 CH_WIDTH_MAX, false); 680 } 681 682 /** 683 * hdd_son_set_country() - set country code 684 * @vdev: vdev 685 * @country_code:pointer to country code 686 * 687 * Return: 0 if country code is set successfully 688 */ 689 static int hdd_son_set_country(struct wlan_objmgr_vdev *vdev, 690 char *country_code) 691 { 692 struct hdd_context *hdd_ctx; 693 struct wlan_hdd_link_info *link_info; 694 695 if (!vdev) { 696 hdd_err("null vdev"); 697 return -EINVAL; 698 } 699 700 link_info = wlan_hdd_get_link_info_from_objmgr(vdev); 701 if (!link_info) { 702 hdd_err("null adapter"); 703 return -EINVAL; 704 } 705 706 hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter); 707 if (!hdd_ctx) { 708 hdd_err("null hdd ctx"); 709 return -EINVAL; 710 } 711 712 return hdd_reg_set_country(hdd_ctx, country_code); 713 } 714 715 /** 716 * hdd_son_set_candidate_freq() - set candidate freq. Switch to this freq 717 * after radar is detected 718 * @vdev: vdev 719 * @freq: candidate frequency 720 * 721 * Return: 0 if candidate freq is set successfully. 722 */ 723 static int hdd_son_set_candidate_freq(struct wlan_objmgr_vdev *vdev, 724 qdf_freq_t freq) 725 { 726 struct wlan_hdd_link_info *link_info; 727 struct sap_context *sap_ctx; 728 729 if (!vdev) { 730 hdd_err("null vdev"); 731 return -EINVAL; 732 } 733 734 link_info = wlan_hdd_get_link_info_from_objmgr(vdev); 735 if (!link_info) { 736 hdd_err("null adapter"); 737 return -EINVAL; 738 } 739 if (!hdd_adapter_is_ap(link_info->adapter)) { 740 hdd_err("vdev id %d is not AP", link_info->vdev_id); 741 return -EINVAL; 742 } 743 744 sap_ctx = WLAN_HDD_GET_SAP_CTX_PTR(link_info); 745 if (!sap_ctx) { 746 hdd_err("null sap_ctx"); 747 return -EINVAL; 748 } 749 750 sap_ctx->candidate_freq = freq; 751 752 return 0; 753 } 754 755 /** 756 * hdd_son_get_candidate_freq() - get candidate freq 757 * @vdev: vdev 758 * 759 * Return: candidate freq 760 */ 761 static qdf_freq_t hdd_son_get_candidate_freq(struct wlan_objmgr_vdev *vdev) 762 { 763 struct wlan_hdd_link_info *link_info; 764 struct sap_context *sap_ctx; 765 qdf_freq_t freq = 0; 766 767 if (!vdev) { 768 hdd_err("null vdev"); 769 return freq; 770 } 771 772 link_info = wlan_hdd_get_link_info_from_objmgr(vdev); 773 if (!link_info) { 774 hdd_err("null adapter"); 775 return freq; 776 } 777 if (!hdd_adapter_is_ap(link_info->adapter)) { 778 hdd_err("vdev id %d is not AP", link_info->vdev_id); 779 return freq; 780 } 781 782 sap_ctx = WLAN_HDD_GET_SAP_CTX_PTR(link_info); 783 if (!sap_ctx) { 784 hdd_err("null sap_ctx"); 785 return freq; 786 } 787 freq = sap_ctx->candidate_freq; 788 789 return freq; 790 } 791 792 /** 793 * hdd_son_phy_mode_to_vendor_phy_mode() - translate son phy mode to 794 * vendor_phy_mode 795 * @mode: son phy mode 796 * 797 * Return: qca_wlan_vendor_phy_mode 798 */ 799 static enum qca_wlan_vendor_phy_mode hdd_son_phy_mode_to_vendor_phy_mode( 800 enum ieee80211_phymode mode) 801 { 802 enum qca_wlan_vendor_phy_mode vendor_mode; 803 804 switch (mode) { 805 case IEEE80211_MODE_AUTO: 806 vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_AUTO; 807 break; 808 case IEEE80211_MODE_11A: 809 vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11A; 810 break; 811 case IEEE80211_MODE_11B: 812 vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11B; 813 break; 814 case IEEE80211_MODE_11G: 815 vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11G; 816 break; 817 case IEEE80211_MODE_11NA_HT20: 818 vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11NA_HT20; 819 break; 820 case IEEE80211_MODE_11NG_HT20: 821 vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11NG_HT20; 822 break; 823 case IEEE80211_MODE_11NA_HT40PLUS: 824 vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11NA_HT40PLUS; 825 break; 826 case IEEE80211_MODE_11NA_HT40MINUS: 827 vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11NA_HT40MINUS; 828 break; 829 case IEEE80211_MODE_11NG_HT40PLUS: 830 vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11NG_HT40PLUS; 831 break; 832 case IEEE80211_MODE_11NG_HT40MINUS: 833 vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11NG_HT40MINUS; 834 break; 835 case IEEE80211_MODE_11NG_HT40: 836 vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11NG_HT40; 837 break; 838 case IEEE80211_MODE_11NA_HT40: 839 vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11NA_HT40; 840 break; 841 case IEEE80211_MODE_11AC_VHT20: 842 vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT20; 843 break; 844 case IEEE80211_MODE_11AC_VHT40PLUS: 845 vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT40PLUS; 846 break; 847 case IEEE80211_MODE_11AC_VHT40MINUS: 848 vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT40MINUS; 849 break; 850 case IEEE80211_MODE_11AC_VHT40: 851 vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT40; 852 break; 853 case IEEE80211_MODE_11AC_VHT80: 854 vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT80; 855 break; 856 case IEEE80211_MODE_11AC_VHT160: 857 vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT160; 858 break; 859 case IEEE80211_MODE_11AC_VHT80_80: 860 vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT80P80; 861 break; 862 case IEEE80211_MODE_11AXA_HE20: 863 case IEEE80211_MODE_11AXG_HE20: 864 vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11AX_HE20; 865 break; 866 case IEEE80211_MODE_11AXA_HE40PLUS: 867 case IEEE80211_MODE_11AXG_HE40PLUS: 868 vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11AX_HE40PLUS; 869 break; 870 case IEEE80211_MODE_11AXA_HE40MINUS: 871 case IEEE80211_MODE_11AXG_HE40MINUS: 872 vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11AX_HE40MINUS; 873 break; 874 case IEEE80211_MODE_11AXA_HE40: 875 case IEEE80211_MODE_11AXG_HE40: 876 vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11AX_HE40; 877 break; 878 case IEEE80211_MODE_11AXA_HE80: 879 vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11AX_HE80; 880 break; 881 case IEEE80211_MODE_11AXA_HE160: 882 vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11AX_HE160; 883 break; 884 case IEEE80211_MODE_11AXA_HE80_80: 885 vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11AX_HE80P80; 886 break; 887 default: 888 hdd_err("Invalid config phy mode %d, set it as auto", mode); 889 vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_AUTO; 890 break; 891 } 892 893 return vendor_mode; 894 } 895 896 /** 897 * hdd_son_set_phymode() - set son phy mode 898 * @vdev: vdev 899 * @mode: son phy mode to set 900 * 901 * Return: 0 on success, negative errno on failure 902 */ 903 static int hdd_son_set_phymode(struct wlan_objmgr_vdev *vdev, 904 enum ieee80211_phymode mode) 905 { 906 struct wlan_hdd_link_info *link_info; 907 enum qca_wlan_vendor_phy_mode vendor_phy_mode; 908 QDF_STATUS status; 909 struct hdd_ap_ctx *hdd_ap_ctx; 910 struct sap_config *sap_config; 911 struct wlan_hdd_link_info *link_info; 912 913 if (!vdev) { 914 hdd_err("null vdev"); 915 return -EINVAL; 916 } 917 918 link_info = wlan_hdd_get_link_info_from_objmgr(vdev); 919 if (!link_info) { 920 hdd_err("Invalid VDEV %d", wlan_vdev_get_id(vdev)); 921 return -EINVAL; 922 } 923 924 if (!hdd_adapter_is_ap(link_info->adapter)) { 925 hdd_err("vdev id %d is not AP", link_info->vdev_id); 926 return -EINVAL; 927 } 928 929 vendor_phy_mode = hdd_son_phy_mode_to_vendor_phy_mode(mode); 930 931 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(link_info); 932 sap_config = &hdd_ap_ctx->sap_config; 933 status = wlansap_son_update_sap_config_phymode(vdev, sap_config, 934 vendor_phy_mode); 935 if (QDF_IS_STATUS_ERROR(status)) { 936 hdd_err("update son phy mode error"); 937 return -EINVAL; 938 } 939 940 hdd_restart_sap(link_info); 941 942 return 0; 943 } 944 945 /** 946 * hdd_wlan_phymode_to_son_phymode() - get son phymode from wlan_phymode phymode 947 * @phymode: wlan_phymode phymode 948 * 949 * Return: ieee80211_phymode 950 */ 951 static enum ieee80211_phymode hdd_wlan_phymode_to_son_phymode( 952 enum wlan_phymode phymode) 953 { 954 enum ieee80211_phymode son_phymode; 955 956 switch (phymode) { 957 case WLAN_PHYMODE_AUTO: 958 son_phymode = IEEE80211_MODE_AUTO; 959 break; 960 case WLAN_PHYMODE_11A: 961 son_phymode = IEEE80211_MODE_11A; 962 break; 963 case WLAN_PHYMODE_11B: 964 son_phymode = IEEE80211_MODE_11B; 965 break; 966 case WLAN_PHYMODE_11G: 967 case WLAN_PHYMODE_11G_ONLY: 968 son_phymode = IEEE80211_MODE_11G; 969 break; 970 case WLAN_PHYMODE_11NA_HT20: 971 son_phymode = IEEE80211_MODE_11NA_HT20; 972 break; 973 case WLAN_PHYMODE_11NG_HT20: 974 son_phymode = IEEE80211_MODE_11NG_HT20; 975 break; 976 case WLAN_PHYMODE_11NA_HT40: 977 son_phymode = IEEE80211_MODE_11NA_HT40; 978 break; 979 case WLAN_PHYMODE_11NG_HT40PLUS: 980 son_phymode = IEEE80211_MODE_11NG_HT40PLUS; 981 break; 982 case WLAN_PHYMODE_11NG_HT40MINUS: 983 son_phymode = IEEE80211_MODE_11NG_HT40MINUS; 984 break; 985 case WLAN_PHYMODE_11NG_HT40: 986 son_phymode = IEEE80211_MODE_11NG_HT40; 987 break; 988 case WLAN_PHYMODE_11AC_VHT20: 989 case WLAN_PHYMODE_11AC_VHT20_2G: 990 son_phymode = IEEE80211_MODE_11AC_VHT20; 991 break; 992 case WLAN_PHYMODE_11AC_VHT40: 993 case WLAN_PHYMODE_11AC_VHT40_2G: 994 son_phymode = IEEE80211_MODE_11AC_VHT40; 995 break; 996 case WLAN_PHYMODE_11AC_VHT40PLUS_2G: 997 son_phymode = IEEE80211_MODE_11AC_VHT40PLUS; 998 break; 999 case WLAN_PHYMODE_11AC_VHT40MINUS_2G: 1000 son_phymode = IEEE80211_MODE_11AC_VHT40MINUS; 1001 break; 1002 case WLAN_PHYMODE_11AC_VHT80: 1003 case WLAN_PHYMODE_11AC_VHT80_2G: 1004 son_phymode = IEEE80211_MODE_11AC_VHT80; 1005 break; 1006 case WLAN_PHYMODE_11AC_VHT160: 1007 son_phymode = IEEE80211_MODE_11AC_VHT160; 1008 break; 1009 case WLAN_PHYMODE_11AC_VHT80_80: 1010 son_phymode = IEEE80211_MODE_11AC_VHT80_80; 1011 break; 1012 case WLAN_PHYMODE_11AXA_HE20: 1013 son_phymode = IEEE80211_MODE_11AXA_HE20; 1014 break; 1015 case WLAN_PHYMODE_11AXG_HE20: 1016 son_phymode = IEEE80211_MODE_11AXG_HE20; 1017 break; 1018 case WLAN_PHYMODE_11AXA_HE40: 1019 son_phymode = IEEE80211_MODE_11AXA_HE40; 1020 break; 1021 case WLAN_PHYMODE_11AXG_HE40PLUS: 1022 son_phymode = IEEE80211_MODE_11AXG_HE40PLUS; 1023 break; 1024 case WLAN_PHYMODE_11AXG_HE40MINUS: 1025 son_phymode = IEEE80211_MODE_11AXG_HE40MINUS; 1026 break; 1027 case WLAN_PHYMODE_11AXG_HE40: 1028 case WLAN_PHYMODE_11AXG_HE80: 1029 son_phymode = IEEE80211_MODE_11AXG_HE40; 1030 break; 1031 case WLAN_PHYMODE_11AXA_HE80: 1032 son_phymode = IEEE80211_MODE_11AXA_HE80; 1033 break; 1034 case WLAN_PHYMODE_11AXA_HE160: 1035 son_phymode = IEEE80211_MODE_11AXA_HE160; 1036 break; 1037 case WLAN_PHYMODE_11AXA_HE80_80: 1038 son_phymode = IEEE80211_MODE_11AXA_HE80_80; 1039 break; 1040 default: 1041 son_phymode = IEEE80211_MODE_AUTO; 1042 break; 1043 } 1044 1045 return son_phymode; 1046 } 1047 1048 /** 1049 * hdd_son_get_phymode() - get son phy mode 1050 * @vdev: vdev 1051 * 1052 * Return: enum ieee80211_phymode 1053 */ 1054 static enum ieee80211_phymode hdd_son_get_phymode(struct wlan_objmgr_vdev *vdev) 1055 { 1056 struct wlan_channel *des_chan; 1057 1058 if (!vdev) { 1059 hdd_err("null vdev"); 1060 return IEEE80211_MODE_AUTO; 1061 } 1062 des_chan = wlan_vdev_mlme_get_des_chan(vdev); 1063 if (!des_chan) { 1064 hdd_err("null des_chan"); 1065 return IEEE80211_MODE_AUTO; 1066 } 1067 1068 return hdd_wlan_phymode_to_son_phymode(des_chan->ch_phymode); 1069 } 1070 1071 /** 1072 * hdd_son_per_sta_len() - get sta information length 1073 * @sta_info: pointer to hdd_station_info 1074 * 1075 * TD: Certain IE may be provided for sta info 1076 * 1077 * Return: the size which is needed for given sta info 1078 */ 1079 static uint32_t hdd_son_per_sta_len(struct hdd_station_info *sta_info) 1080 { 1081 return qdf_roundup(sizeof(struct ieee80211req_sta_info), 1082 sizeof(uint32_t)); 1083 } 1084 1085 /** 1086 * hdd_son_get_sta_space() - how many space are needed for given vdev 1087 * @vdev: vdev 1088 * 1089 * Return: space needed for given vdev to provide sta info 1090 */ 1091 static uint32_t hdd_son_get_sta_space(struct wlan_objmgr_vdev *vdev) 1092 { 1093 struct hdd_adapter *adapter; 1094 struct wlan_hdd_link_info *link_info; 1095 struct hdd_station_info *sta_info, *tmp = NULL; 1096 uint32_t space = 0; 1097 1098 if (!vdev) { 1099 hdd_err("null vdev"); 1100 return space; 1101 } 1102 1103 link_info = wlan_hdd_get_link_info_from_objmgr(vdev); 1104 if (!link_info) { 1105 hdd_err("null adapter"); 1106 return space; 1107 } 1108 1109 adapter = link_info->adapter; 1110 hdd_for_each_sta_ref_safe(adapter->sta_info_list, sta_info, tmp, 1111 STA_INFO_SOFTAP_GET_STA_INFO) { 1112 if (!qdf_is_macaddr_broadcast(&sta_info->sta_mac)) 1113 space += hdd_son_per_sta_len(sta_info); 1114 1115 hdd_put_sta_info_ref(&adapter->sta_info_list, 1116 &sta_info, true, 1117 STA_INFO_SOFTAP_GET_STA_INFO); 1118 } 1119 hdd_debug("sta list space %u", space); 1120 1121 return space; 1122 } 1123 1124 /** 1125 * hdd_son_get_sta_list() - get connected station list 1126 * @vdev: vdev 1127 * @si: pointer to ieee80211req_sta_info 1128 * @space: space left 1129 * 1130 * Return: void 1131 */ 1132 static void hdd_son_get_sta_list(struct wlan_objmgr_vdev *vdev, 1133 struct ieee80211req_sta_info *si, 1134 uint32_t *space) 1135 { 1136 struct hdd_adapter *adapter; 1137 struct wlan_hdd_link_info *link_info; 1138 struct hdd_station_info *sta_info, *tmp = NULL; 1139 uint32_t len; 1140 qdf_time_t current_ts; 1141 1142 if (!vdev) { 1143 hdd_err("null vdev"); 1144 return; 1145 } 1146 1147 link_info = wlan_hdd_get_link_info_from_objmgr(vdev); 1148 if (!link_info) { 1149 hdd_err("null adapter"); 1150 return; 1151 } 1152 1153 adapter = link_info->adapter; 1154 hdd_for_each_sta_ref_safe(adapter->sta_info_list, sta_info, tmp, 1155 STA_INFO_SOFTAP_GET_STA_INFO) { 1156 if (!qdf_is_macaddr_broadcast(&sta_info->sta_mac)) { 1157 len = hdd_son_per_sta_len(sta_info); 1158 1159 if (len > *space) { 1160 /* no more space if left */ 1161 hdd_put_sta_info_ref( 1162 &adapter->sta_info_list, 1163 &sta_info, true, 1164 STA_INFO_SOFTAP_GET_STA_INFO); 1165 1166 if (tmp) 1167 hdd_put_sta_info_ref( 1168 &adapter->sta_info_list, 1169 &tmp, true, 1170 STA_INFO_SOFTAP_GET_STA_INFO); 1171 1172 hdd_err("space %u, length %u", *space, len); 1173 1174 return; 1175 } 1176 1177 qdf_mem_copy(si->isi_macaddr, &sta_info->sta_mac, 1178 QDF_MAC_ADDR_SIZE); 1179 si->isi_ext_cap = sta_info->ext_cap; 1180 si->isi_beacon_measurement_support = 1181 !!(sta_info->capability & 1182 WLAN_CAPABILITY_RADIO_MEASURE); 1183 si->isi_operating_bands = sta_info->supported_band; 1184 si->isi_assoc_time = sta_info->assoc_ts; 1185 current_ts = qdf_system_ticks(); 1186 jiffies_to_timespec(current_ts - sta_info->assoc_ts, 1187 &si->isi_tr069_assoc_time); 1188 si->isi_rssi = sta_info->rssi; 1189 si->isi_len = len; 1190 si->isi_ie_len = 0; 1191 hdd_debug("sta " QDF_MAC_ADDR_FMT " ext_cap 0x%x op band %u rssi %d len %u, assoc ts %lu, curr ts %lu rrm %d", 1192 QDF_MAC_ADDR_REF(si->isi_macaddr), 1193 si->isi_ext_cap, si->isi_operating_bands, 1194 si->isi_rssi, si->isi_len, sta_info->assoc_ts, 1195 current_ts, 1196 si->isi_beacon_measurement_support); 1197 si = (struct ieee80211req_sta_info *)(((uint8_t *)si) + 1198 len); 1199 *space -= len; 1200 } 1201 hdd_put_sta_info_ref(&adapter->sta_info_list, 1202 &sta_info, true, 1203 STA_INFO_SOFTAP_GET_STA_INFO); 1204 } 1205 } 1206 1207 /** 1208 * hdd_son_set_acl_policy() - set son acl policy 1209 * @vdev: vdev 1210 * @son_acl_policy: enum ieee80211_acl_cmd 1211 * 1212 * Return: QDF_STATUS 1213 */ 1214 static QDF_STATUS hdd_son_set_acl_policy(struct wlan_objmgr_vdev *vdev, 1215 ieee80211_acl_cmd son_acl_policy) 1216 { 1217 struct wlan_hdd_link_info *link_info; 1218 QDF_STATUS status = QDF_STATUS_E_INVAL; 1219 struct sap_context *sap_context; 1220 1221 if (!vdev) { 1222 hdd_err("null vdev"); 1223 return status; 1224 } 1225 1226 link_info = wlan_hdd_get_link_info_from_objmgr(vdev); 1227 if (!link_info) { 1228 hdd_err("null adapter"); 1229 return status; 1230 } 1231 1232 sap_context = WLAN_HDD_GET_SAP_CTX_PTR(link_info); 1233 switch (son_acl_policy) { 1234 case IEEE80211_MACCMD_POLICY_OPEN: 1235 status = wlansap_set_acl_mode(sap_context, eSAP_ALLOW_ALL); 1236 break; 1237 case IEEE80211_MACCMD_POLICY_ALLOW: 1238 status = wlansap_set_acl_mode(sap_context, 1239 eSAP_DENY_UNLESS_ACCEPTED); 1240 break; 1241 case IEEE80211_MACCMD_POLICY_DENY: 1242 status = wlansap_set_acl_mode(sap_context, 1243 eSAP_ACCEPT_UNLESS_DENIED); 1244 break; 1245 case IEEE80211_MACCMD_FLUSH: 1246 case IEEE80211_MACCMD_DETACH: 1247 status = wlansap_clear_acl(sap_context); 1248 break; 1249 default: 1250 hdd_err("invalid son acl policy %d", son_acl_policy); 1251 break; 1252 } 1253 1254 return status; 1255 } 1256 1257 /** 1258 * hdd_acl_policy_to_son_acl_policy() - convert acl policy to son acl policy 1259 * @acl_policy: acl policy 1260 * 1261 * Return: son acl policy. enum ieee80211_acl_cmd 1262 */ 1263 static ieee80211_acl_cmd hdd_acl_policy_to_son_acl_policy( 1264 eSapMacAddrACL acl_policy) 1265 { 1266 ieee80211_acl_cmd son_acl_policy = IEEE80211_MACCMD_DETACH; 1267 1268 switch (acl_policy) { 1269 case eSAP_ACCEPT_UNLESS_DENIED: 1270 son_acl_policy = IEEE80211_MACCMD_POLICY_DENY; 1271 break; 1272 case eSAP_DENY_UNLESS_ACCEPTED: 1273 son_acl_policy = IEEE80211_MACCMD_POLICY_ALLOW; 1274 break; 1275 case eSAP_ALLOW_ALL: 1276 son_acl_policy = IEEE80211_MACCMD_POLICY_OPEN; 1277 break; 1278 default: 1279 hdd_err("invalid acl policy %d", acl_policy); 1280 break; 1281 } 1282 1283 return son_acl_policy; 1284 } 1285 1286 /** 1287 * hdd_son_get_acl_policy() - get son acl policy 1288 * @vdev: vdev 1289 * 1290 * Return: son acl policy. enum ieee80211_acl_cmd 1291 */ 1292 static ieee80211_acl_cmd hdd_son_get_acl_policy(struct wlan_objmgr_vdev *vdev) 1293 { 1294 eSapMacAddrACL acl_policy; 1295 struct wlan_hdd_link_info *link_info; 1296 ieee80211_acl_cmd son_acl_policy = IEEE80211_MACCMD_DETACH; 1297 1298 if (!vdev) { 1299 hdd_err("null vdev"); 1300 return son_acl_policy; 1301 } 1302 1303 link_info = wlan_hdd_get_link_info_from_objmgr(vdev); 1304 if (!link_info) { 1305 hdd_err("null adapter"); 1306 return son_acl_policy; 1307 } 1308 1309 wlansap_get_acl_mode(WLAN_HDD_GET_SAP_CTX_PTR(link_info), &acl_policy); 1310 1311 son_acl_policy = hdd_acl_policy_to_son_acl_policy(acl_policy); 1312 1313 return son_acl_policy; 1314 } 1315 1316 /** 1317 * hdd_son_add_acl_mac() - add mac to access control list(ACL) 1318 * @vdev: vdev 1319 * @acl_mac: mac address to add 1320 * 1321 * Return: 0 on success, negative errno on failure 1322 */ 1323 static int hdd_son_add_acl_mac(struct wlan_objmgr_vdev *vdev, 1324 struct qdf_mac_addr *acl_mac) 1325 { 1326 eSapACLType list_type; 1327 QDF_STATUS qdf_status; 1328 eSapMacAddrACL acl_policy; 1329 struct wlan_hdd_link_info *link_info; 1330 struct sap_context *sap_context; 1331 1332 if (!vdev) { 1333 hdd_err("null vdev"); 1334 return -EINVAL; 1335 } 1336 if (!acl_mac) { 1337 hdd_err("null acl_mac"); 1338 return -EINVAL; 1339 } 1340 1341 link_info = wlan_hdd_get_link_info_from_objmgr(vdev); 1342 if (!link_info) { 1343 hdd_err("null adapter"); 1344 return -EINVAL; 1345 } 1346 1347 sap_context = WLAN_HDD_GET_SAP_CTX_PTR(link_info); 1348 wlansap_get_acl_mode(sap_context, &acl_policy); 1349 1350 if (acl_policy == eSAP_ACCEPT_UNLESS_DENIED) { 1351 list_type = SAP_DENY_LIST; 1352 } else if (acl_policy == eSAP_DENY_UNLESS_ACCEPTED) { 1353 list_type = SAP_ALLOW_LIST; 1354 } else { 1355 hdd_err("Invalid ACL policy %d.", acl_policy); 1356 return -EINVAL; 1357 } 1358 qdf_status = wlansap_modify_acl(sap_context, acl_mac->bytes, list_type, 1359 ADD_STA_TO_ACL_NO_DEAUTH); 1360 if (QDF_IS_STATUS_ERROR(qdf_status)) { 1361 hdd_err("Modify ACL failed"); 1362 return -EIO; 1363 } 1364 1365 return 0; 1366 } 1367 1368 /** 1369 * hdd_son_del_acl_mac() - delete mac from acl 1370 * @vdev: vdev 1371 * @acl_mac: mac to remove 1372 * 1373 * Return: 0 on success, negative errno on failure 1374 */ 1375 static int hdd_son_del_acl_mac(struct wlan_objmgr_vdev *vdev, 1376 struct qdf_mac_addr *acl_mac) 1377 { 1378 eSapACLType list_type; 1379 QDF_STATUS qdf_status; 1380 eSapMacAddrACL acl_policy; 1381 struct wlan_hdd_link_info *link_info; 1382 struct sap_context *sap_ctx; 1383 1384 if (!vdev) { 1385 hdd_err("null vdev"); 1386 return -EINVAL; 1387 } 1388 if (!acl_mac) { 1389 hdd_err("null acl_mac"); 1390 return -EINVAL; 1391 } 1392 1393 lin_info = wlan_hdd_get_link_info_from_objmgr(vdev); 1394 if (!link_info) { 1395 hdd_err("null adapter"); 1396 return -EINVAL; 1397 } 1398 1399 sap_ctx = WLAN_HDD_GET_SAP_CTX_PTR(link_info); 1400 if (!sap_ctx) { 1401 hdd_err("null sap ctx"); 1402 return -EINVAL; 1403 } 1404 1405 wlansap_get_acl_mode(sap_ctx, &acl_policy); 1406 1407 if (acl_policy == eSAP_ACCEPT_UNLESS_DENIED) { 1408 list_type = SAP_DENY_LIST; 1409 } else if (acl_policy == eSAP_DENY_UNLESS_ACCEPTED) { 1410 list_type = SAP_ALLOW_LIST; 1411 } else { 1412 hdd_err("Invalid ACL policy %d.", acl_policy); 1413 return -EINVAL; 1414 } 1415 qdf_status = wlansap_modify_acl(sap_ctx, acl_mac->bytes, list_type, 1416 DELETE_STA_FROM_ACL_NO_DEAUTH); 1417 if (QDF_IS_STATUS_ERROR(qdf_status)) { 1418 hdd_err("Modify ACL failed"); 1419 return -EIO; 1420 } 1421 1422 return 0; 1423 } 1424 1425 /** 1426 * hdd_son_kickout_mac() - kickout sta with given mac 1427 * @vdev: vdev 1428 * @mac: sta mac to kickout 1429 * 1430 * Return: 0 on success, negative errno on failure 1431 */ 1432 static int hdd_son_kickout_mac(struct wlan_objmgr_vdev *vdev, 1433 struct qdf_mac_addr *mac) 1434 { 1435 struct wlan_hdd_link_info *link_info; 1436 1437 if (!vdev) { 1438 hdd_err("null vdev"); 1439 return -EINVAL; 1440 } 1441 1442 link_info = wlan_hdd_get_link_info_from_objmgr(vdev); 1443 if (!link_info) { 1444 hdd_err("null adapter"); 1445 return -EINVAL; 1446 } 1447 1448 if (mac) 1449 return wlan_hdd_del_station(link_info->adapter, mac->bytes); 1450 else 1451 return wlan_hdd_del_station(link_info->adapter, NULL); 1452 } 1453 1454 static uint8_t hdd_son_get_rx_nss(struct wlan_objmgr_vdev *vdev) 1455 { 1456 struct wlan_hdd_link_info *link_info; 1457 uint8_t rx_nss = 0; 1458 1459 link_info = wlan_hdd_get_link_info_from_objmgr(vdev); 1460 if (!link_info) { 1461 hdd_err("null adapter"); 1462 return 0; 1463 } 1464 1465 hdd_get_rx_nss(link_info->adapter, &rx_nss); 1466 return rx_nss; 1467 } 1468 1469 static void hdd_son_deauth_sta(struct wlan_objmgr_vdev *vdev, 1470 uint8_t *peer_mac, 1471 bool ignore_frame) 1472 { 1473 struct wlan_hdd_link_info *link_info; 1474 struct csr_del_sta_params param; 1475 QDF_STATUS status; 1476 1477 link_info = wlan_hdd_get_link_info_from_objmgr(vdev); 1478 if (!link_info) { 1479 hdd_err("null adapter"); 1480 return; 1481 } 1482 1483 qdf_mem_copy(param.peerMacAddr.bytes, peer_mac, QDF_MAC_ADDR_SIZE); 1484 param.subtype = SIR_MAC_MGMT_DEAUTH; 1485 param.reason_code = ignore_frame ? REASON_HOST_TRIGGERED_SILENT_DEAUTH 1486 : REASON_UNSPEC_FAILURE; 1487 hdd_debug("Peer - "QDF_MAC_ADDR_FMT" Ignore Frame - %u", 1488 QDF_MAC_ADDR_REF(peer_mac), ignore_frame); 1489 1490 status = hdd_softap_sta_deauth(link_info->adapter, ¶m); 1491 if (QDF_STATUS_IS_ERROR(status)) 1492 hdd_err("Error in deauthenticating peer"); 1493 } 1494 1495 static void hdd_son_modify_acl(struct wlan_objmgr_vdev *vdev, 1496 uint8_t *peer_mac, 1497 bool allow_auth) 1498 { 1499 QDF_STATUS status; 1500 struct sap_context *sap_context; 1501 struct wlan_hdd_link_info *link_info; 1502 1503 link_info = wlan_hdd_get_link_info_from_objmgr(vdev); 1504 if (!link_info) { 1505 hdd_err("null adapter"); 1506 return; 1507 } 1508 1509 hdd_debug("Peer - " QDF_MAC_ADDR_FMT " Allow Auth - %u", 1510 QDF_MAC_ADDR_REF(peer_mac), allow_auth); 1511 1512 sap_context = WLAN_HDD_GET_SAP_CTX_PTR(link_info); 1513 if (allow_auth) { 1514 status = wlansap_modify_acl(sap_context, peer_mac, 1515 SAP_DENY_LIST, DELETE_STA_FROM_ACL); 1516 status = wlansap_modify_acl(sap_context, peer_mac, 1517 SAP_ALLOW_LIST, ADD_STA_TO_ACL); 1518 } else { 1519 status = wlansap_modify_acl(sap_context, peer_mac, 1520 SAP_ALLOW_LIST, 1521 DELETE_STA_FROM_ACL); 1522 status = wlansap_modify_acl(sap_context, peer_mac, 1523 SAP_DENY_LIST, ADD_STA_TO_ACL); 1524 } 1525 } 1526 1527 static int hdd_son_send_cfg_event(struct wlan_objmgr_vdev *vdev, 1528 uint32_t event_id, 1529 uint32_t event_len, 1530 const uint8_t *event_buf) 1531 { 1532 struct hdd_adapter *adapter; 1533 struct wlan_hdd_link_info *link_info; 1534 uint32_t len; 1535 uint32_t idx; 1536 struct sk_buff *skb; 1537 1538 if (!event_buf) { 1539 hdd_err("invalid event buf"); 1540 return -EINVAL; 1541 } 1542 1543 link_info = wlan_hdd_get_link_info_from_objmgr(vdev); 1544 if (!link_info) { 1545 hdd_err("null adapter"); 1546 return -EINVAL; 1547 } 1548 1549 adapter = link_info->adapter; 1550 len = nla_total_size(sizeof(event_id)) + 1551 nla_total_size(event_len) + 1552 NLMSG_HDRLEN; 1553 idx = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_CONFIGURATION_INDEX; 1554 skb = wlan_cfg80211_vendor_event_alloc(adapter->hdd_ctx->wiphy, 1555 &adapter->wdev, 1556 len, idx, GFP_KERNEL); 1557 if (!skb) { 1558 hdd_err("failed to alloc cfg80211 vendor event"); 1559 return -EINVAL; 1560 } 1561 1562 if (nla_put_u32(skb, 1563 QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_COMMAND, 1564 event_id)) { 1565 hdd_err("failed to put attr config generic command"); 1566 wlan_cfg80211_vendor_free_skb(skb); 1567 return -EINVAL; 1568 } 1569 1570 if (nla_put(skb, 1571 QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_DATA, 1572 event_len, 1573 event_buf)) { 1574 hdd_err("failed to put attr config generic data"); 1575 wlan_cfg80211_vendor_free_skb(skb); 1576 return -EINVAL; 1577 } 1578 1579 wlan_cfg80211_vendor_event(skb, GFP_KERNEL); 1580 1581 return 0; 1582 } 1583 1584 static int hdd_son_deliver_opmode(struct wlan_objmgr_vdev *vdev, 1585 uint32_t event_len, 1586 const uint8_t *event_buf) 1587 { 1588 return hdd_son_send_cfg_event(vdev, 1589 QCA_NL80211_VENDOR_SUBCMD_OPMODE_UPDATE, 1590 event_len, 1591 event_buf); 1592 } 1593 1594 static int hdd_son_deliver_smps(struct wlan_objmgr_vdev *vdev, 1595 uint32_t event_len, 1596 const uint8_t *event_buf) 1597 { 1598 return hdd_son_send_cfg_event(vdev, 1599 QCA_NL80211_VENDOR_SUBCMD_SMPS_UPDATE, 1600 event_len, 1601 event_buf); 1602 } 1603 1604 /** 1605 * hdd_son_get_vdev_by_netdev() - get vdev from net device 1606 * @dev: struct net_device dev 1607 * 1608 * Return: vdev on success, NULL on failure 1609 */ 1610 static struct wlan_objmgr_vdev * 1611 hdd_son_get_vdev_by_netdev(struct net_device *dev) 1612 { 1613 struct hdd_adapter *adapter; 1614 struct wlan_objmgr_vdev *vdev; 1615 1616 if (!dev) 1617 return NULL; 1618 1619 adapter = WLAN_HDD_GET_PRIV_PTR(dev); 1620 if (!adapter || (adapter && adapter->delete_in_progress)) 1621 return NULL; 1622 1623 vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_SON_ID); 1624 if (!vdev) 1625 return NULL; 1626 1627 return vdev; 1628 } 1629 1630 /** 1631 * son_trigger_vdev_obj_creation() - Trigger vdev object creation 1632 * @psoc: psoc object 1633 * @object: vdev object 1634 * @arg: component id 1635 * 1636 * Return: void 1637 */ 1638 static void 1639 son_trigger_vdev_obj_creation(struct wlan_objmgr_psoc *psoc, 1640 void *object, void *arg) 1641 { 1642 QDF_STATUS ret; 1643 struct wlan_objmgr_vdev *vdev; 1644 enum wlan_umac_comp_id *id; 1645 1646 vdev = object; 1647 id = arg; 1648 1649 ret = wlan_objmgr_trigger_vdev_comp_priv_object_creation(vdev, *id); 1650 if (QDF_IS_STATUS_ERROR(ret)) 1651 hdd_err("vdev obj creation trigger failed"); 1652 } 1653 1654 /** 1655 * son_trigger_pdev_obj_creation() - Trigger pdev object creation 1656 * @psoc: psoc object 1657 * @object: pdev object 1658 * @arg: component id 1659 * 1660 * Return: void 1661 */ 1662 static void 1663 son_trigger_pdev_obj_creation(struct wlan_objmgr_psoc *psoc, 1664 void *object, void *arg) 1665 { 1666 QDF_STATUS ret; 1667 struct wlan_objmgr_pdev *pdev; 1668 enum wlan_umac_comp_id *id; 1669 1670 pdev = object; 1671 id = arg; 1672 1673 ret = wlan_objmgr_trigger_pdev_comp_priv_object_creation(pdev, *id); 1674 if (QDF_IS_STATUS_ERROR(ret)) 1675 hdd_err("pdev obj creation trigger failed"); 1676 } 1677 1678 /** 1679 * son_trigger_pdev_obj_deletion() - Trigger pdev object deletion 1680 * @psoc: psoc object 1681 * @object: pdev object 1682 * @arg: component id 1683 * 1684 * Return: void 1685 */ 1686 static void 1687 son_trigger_pdev_obj_deletion(struct wlan_objmgr_psoc *psoc, 1688 void *object, void *arg) 1689 { 1690 QDF_STATUS ret; 1691 struct wlan_objmgr_pdev *pdev; 1692 enum wlan_umac_comp_id *id; 1693 1694 pdev = object; 1695 id = arg; 1696 1697 ret = wlan_objmgr_trigger_pdev_comp_priv_object_deletion(pdev, *id); 1698 if (QDF_IS_STATUS_ERROR(ret)) 1699 hdd_err("pdev obj delete trigger failed"); 1700 } 1701 1702 /** 1703 * hdd_son_trigger_objmgr_object_creation() - Trigger objmgr object creation 1704 * @id: umac component id 1705 * 1706 * Return: QDF_STATUS_SUCCESS on success otherwise failure 1707 */ 1708 static QDF_STATUS 1709 hdd_son_trigger_objmgr_object_creation(enum wlan_umac_comp_id id) 1710 { 1711 QDF_STATUS ret; 1712 struct wlan_objmgr_psoc *psoc; 1713 1714 psoc = wlan_objmgr_get_psoc_by_id(0, WLAN_SON_ID); 1715 if (!psoc) { 1716 hdd_err("psoc null"); 1717 return QDF_STATUS_E_INVAL; 1718 } 1719 1720 ret = wlan_objmgr_trigger_psoc_comp_priv_object_creation(psoc, id); 1721 if (QDF_IS_STATUS_ERROR(ret)) { 1722 hdd_err("psoc object create trigger failed"); 1723 goto out; 1724 } 1725 1726 ret = wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP, 1727 son_trigger_pdev_obj_creation, 1728 &id, 0, id); 1729 if (QDF_IS_STATUS_ERROR(ret)) { 1730 hdd_err("pdev object create trigger failed"); 1731 goto fail; 1732 } 1733 1734 ret = wlan_objmgr_iterate_obj_list(psoc, WLAN_VDEV_OP, 1735 son_trigger_vdev_obj_creation, 1736 &id, 0, id); 1737 if (QDF_IS_STATUS_ERROR(ret)) { 1738 hdd_err("vdev object create trigger failed"); 1739 goto fail1; 1740 } 1741 wlan_objmgr_psoc_release_ref(psoc, WLAN_SON_ID); 1742 return ret; 1743 1744 fail1: 1745 ret = wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP, 1746 son_trigger_pdev_obj_deletion, 1747 &id, 0, id); 1748 if (QDF_IS_STATUS_ERROR(ret)) 1749 hdd_err("pdev object delete trigger failed"); 1750 fail: 1751 ret = wlan_objmgr_trigger_psoc_comp_priv_object_deletion(psoc, id); 1752 if (QDF_IS_STATUS_ERROR(ret)) 1753 hdd_err("psoc object delete trigger failed"); 1754 out: 1755 wlan_objmgr_psoc_release_ref(psoc, WLAN_SON_ID); 1756 return ret; 1757 } 1758 1759 /** 1760 * son_trigger_peer_obj_deletion() - Trigger peer object deletion 1761 * @psoc: psoc object 1762 * @object: peer object 1763 * @arg: component id 1764 * 1765 * Return: void 1766 */ 1767 static void 1768 son_trigger_peer_obj_deletion(struct wlan_objmgr_psoc *psoc, 1769 void *object, void *arg) 1770 { 1771 QDF_STATUS ret; 1772 struct wlan_objmgr_peer *peer; 1773 enum wlan_umac_comp_id *id; 1774 1775 peer = object; 1776 id = arg; 1777 1778 ret = wlan_objmgr_trigger_peer_comp_priv_object_deletion(peer, *id); 1779 if (QDF_IS_STATUS_ERROR(ret)) 1780 hdd_err("peer obj delete trigger failed"); 1781 } 1782 1783 /** 1784 * son_trigger_vdev_obj_deletion() - Trigger vdev object deletion 1785 * @psoc: psoc object 1786 * @object: vdev object 1787 * @arg: component id 1788 * 1789 * Return: void 1790 */ 1791 static void 1792 son_trigger_vdev_obj_deletion(struct wlan_objmgr_psoc *psoc, 1793 void *object, void *arg) 1794 { 1795 QDF_STATUS ret; 1796 struct wlan_objmgr_vdev *vdev; 1797 enum wlan_umac_comp_id *id; 1798 1799 vdev = object; 1800 id = arg; 1801 1802 ret = wlan_objmgr_trigger_vdev_comp_priv_object_deletion(vdev, *id); 1803 if (QDF_IS_STATUS_ERROR(ret)) 1804 hdd_err("vdev obj deletion trigger failed"); 1805 } 1806 1807 /** 1808 * hdd_son_trigger_objmgr_object_deletion() - Trigger objmgr object deletion 1809 * @id: umac component id 1810 * 1811 * Return: QDF_STATUS_SUCCESS on success otherwise failure 1812 */ 1813 static QDF_STATUS 1814 hdd_son_trigger_objmgr_object_deletion(enum wlan_umac_comp_id id) 1815 { 1816 QDF_STATUS ret; 1817 struct wlan_objmgr_psoc *psoc; 1818 1819 psoc = wlan_objmgr_get_psoc_by_id(0, WLAN_SON_ID); 1820 if (!psoc) { 1821 hdd_err("psoc null"); 1822 return QDF_STATUS_E_INVAL; 1823 } 1824 1825 ret = wlan_objmgr_iterate_obj_list(psoc, WLAN_PEER_OP, 1826 son_trigger_peer_obj_deletion, 1827 &id, 0, id); 1828 if (QDF_IS_STATUS_ERROR(ret)) 1829 hdd_err("peer object deletion trigger failed"); 1830 1831 ret = wlan_objmgr_iterate_obj_list(psoc, WLAN_VDEV_OP, 1832 son_trigger_vdev_obj_deletion, 1833 &id, 0, id); 1834 if (QDF_IS_STATUS_ERROR(ret)) 1835 hdd_err("vdev object deletion trigger failed"); 1836 1837 ret = wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP, 1838 son_trigger_pdev_obj_deletion, 1839 &id, 0, id); 1840 if (QDF_IS_STATUS_ERROR(ret)) 1841 hdd_err("pdev object delete trigger failed"); 1842 1843 ret = wlan_objmgr_trigger_psoc_comp_priv_object_deletion(psoc, id); 1844 if (QDF_IS_STATUS_ERROR(ret)) 1845 hdd_err("psoc object delete trigger failed"); 1846 1847 wlan_objmgr_psoc_release_ref(psoc, WLAN_SON_ID); 1848 return ret; 1849 } 1850 1851 /* 1852 * hdd_son_init_acs_channels() -initializes acs configs 1853 * 1854 * @adapter: pointer to hdd adapter 1855 * @hdd_ctx: pointer to hdd context 1856 * @acs_cfg: pointer to acs configs 1857 * 1858 * Return: QDF_STATUS_SUCCESS if ACS configuration is initialized, 1859 */ 1860 static QDF_STATUS hdd_son_init_acs_channels(struct hdd_adapter *adapter, 1861 struct hdd_context *hdd_ctx, 1862 struct sap_acs_cfg *acs_cfg) 1863 { 1864 enum policy_mgr_con_mode pm_mode; 1865 uint32_t freq_list[NUM_CHANNELS], num_channels, i; 1866 1867 if (!hdd_ctx || !acs_cfg) { 1868 hdd_err("Null pointer!!! hdd_ctx or acs_cfg"); 1869 return QDF_STATUS_E_INVAL; 1870 } 1871 if (acs_cfg->freq_list) { 1872 hdd_debug("ACS config is already there, no need to init again"); 1873 return QDF_STATUS_SUCCESS; 1874 } 1875 /* Setting ACS config */ 1876 qdf_mem_zero(acs_cfg, sizeof(*acs_cfg)); 1877 acs_cfg->ch_width = CH_WIDTH_20MHZ; 1878 policy_mgr_get_valid_chans(hdd_ctx->psoc, freq_list, &num_channels); 1879 /* convert and store channel to freq */ 1880 if (!num_channels) { 1881 hdd_err("No Valid channel for ACS"); 1882 return QDF_STATUS_E_INVAL; 1883 } 1884 acs_cfg->freq_list = qdf_mem_malloc(sizeof(*acs_cfg->freq_list) * 1885 num_channels); 1886 if (!acs_cfg->freq_list) { 1887 hdd_err("Mem-alloc failed for acs_cfg->freq_list"); 1888 return QDF_STATUS_E_NOMEM; 1889 } 1890 acs_cfg->master_freq_list = 1891 qdf_mem_malloc(sizeof(*acs_cfg->master_freq_list) * 1892 num_channels); 1893 if (!acs_cfg->master_freq_list) { 1894 hdd_err("Mem-alloc failed for acs_cfg->master_freq_list"); 1895 qdf_mem_free(acs_cfg->freq_list); 1896 acs_cfg->freq_list = NULL; 1897 return QDF_STATUS_E_NOMEM; 1898 } 1899 1900 pm_mode = 1901 policy_mgr_qdf_opmode_to_pm_con_mode(hdd_ctx->psoc, 1902 adapter->device_mode, 1903 adapter->deflink->vdev_id); 1904 /* convert channel to freq */ 1905 for (i = 0; i < num_channels; i++) { 1906 acs_cfg->freq_list[i] = freq_list[i]; 1907 acs_cfg->master_freq_list[i] = freq_list[i]; 1908 } 1909 acs_cfg->ch_list_count = num_channels; 1910 acs_cfg->master_ch_list_count = num_channels; 1911 if (policy_mgr_is_force_scc(hdd_ctx->psoc) && 1912 policy_mgr_get_connection_count(hdd_ctx->psoc)) { 1913 policy_mgr_get_pcl(hdd_ctx->psoc, pm_mode, 1914 acs_cfg->pcl_chan_freq, 1915 &acs_cfg->pcl_ch_count, 1916 acs_cfg->pcl_channels_weight_list, 1917 NUM_CHANNELS, adapter->deflink->vdev_id); 1918 wlan_hdd_trim_acs_channel_list(acs_cfg->pcl_chan_freq, 1919 acs_cfg->pcl_ch_count, 1920 acs_cfg->freq_list, 1921 &acs_cfg->ch_list_count); 1922 if (!acs_cfg->ch_list_count && acs_cfg->master_ch_list_count) 1923 wlan_hdd_handle_zero_acs_list 1924 (hdd_ctx, 1925 acs_cfg->freq_list, 1926 &acs_cfg->ch_list_count, 1927 acs_cfg->master_freq_list, 1928 acs_cfg->master_ch_list_count); 1929 } 1930 acs_cfg->start_ch_freq = acs_cfg->freq_list[0]; 1931 acs_cfg->end_ch_freq = acs_cfg->freq_list[acs_cfg->ch_list_count - 1]; 1932 acs_cfg->hw_mode = eCSR_DOT11_MODE_abg; 1933 1934 return QDF_STATUS_SUCCESS; 1935 } 1936 1937 /** 1938 * hdd_son_start_acs() -Trigers ACS 1939 * 1940 * @vdev: pointer to object mgr vdev 1941 * @enable: True to trigger ACS 1942 * 1943 * Return: 0 on success 1944 */ 1945 static int hdd_son_start_acs(struct wlan_objmgr_vdev *vdev, uint8_t enable) 1946 { 1947 struct hdd_adapter *adapter; 1948 struct wlan_hdd_link_info *link_info; 1949 struct sap_config *sap_config; 1950 struct hdd_context *hdd_ctx; 1951 1952 if (!enable) { 1953 hdd_err("ACS Start report with disabled flag"); 1954 return -EINVAL; 1955 } 1956 1957 link_info = wlan_hdd_get_link_info_from_objmgr(vdev); 1958 if (!link_info) { 1959 hdd_err("Invalid VDEV %d", wlan_vdev_get_id(vdev)); 1960 return -EINVAL; 1961 } 1962 1963 adapter = link_info->adapter; 1964 if (adapter->device_mode != QDF_SAP_MODE) { 1965 hdd_err("Invalid device mode %d", adapter->device_mode); 1966 return -EINVAL; 1967 } 1968 hdd_ctx = WLAN_HDD_GET_CTX(adapter); 1969 if (!hdd_ctx) { 1970 hdd_err("null hdd_ctx"); 1971 return -EINVAL; 1972 } 1973 if (qdf_atomic_read(&link_info->session.ap.acs_in_progress)) { 1974 hdd_err("ACS is in-progress"); 1975 return -EAGAIN; 1976 } 1977 wlan_hdd_undo_acs(link_info); 1978 sap_config = &link_info->session.ap.sap_config; 1979 hdd_debug("ACS Config country %s hw_mode %d ACS_BW: %d START_CH: %d END_CH: %d band %d", 1980 hdd_ctx->reg.alpha2, sap_config->acs_cfg.hw_mode, 1981 sap_config->acs_cfg.ch_width, 1982 sap_config->acs_cfg.start_ch_freq, 1983 sap_config->acs_cfg.end_ch_freq, sap_config->acs_cfg.band); 1984 sap_dump_acs_channel(&sap_config->acs_cfg); 1985 1986 wlan_hdd_cfg80211_start_acs(link_info); 1987 1988 return 0; 1989 } 1990 1991 #define ACS_SET_CHAN_LIST_APPEND 0xFF 1992 #define ACS_SNR_NEAR_RANGE_MIN 60 1993 #define ACS_SNR_MID_RANGE_MIN 30 1994 #define ACS_SNR_FAR_RANGE_MIN 0 1995 1996 /** 1997 * hdd_son_set_acs_channels() - Sets Channels for ACS 1998 * 1999 * @vdev: pointer to object mgr vdev 2000 * @req: target channels 2001 * 2002 * Return: 0 on success 2003 */ 2004 static int hdd_son_set_acs_channels(struct wlan_objmgr_vdev *vdev, 2005 struct ieee80211req_athdbg *req) 2006 { 2007 struct sap_config *sap_config; 2008 /* Append the new channels with existing channel list */ 2009 bool append; 2010 /* Duplicate */ 2011 bool dup; 2012 uint32_t freq_list[ACS_MAX_CHANNEL_COUNT]; 2013 uint32_t num_channels; 2014 uint32_t chan_idx = 0; 2015 uint32_t tmp; 2016 uint16_t chan_start = 0; 2017 uint16_t i, j; 2018 uint16_t acs_chan_count = 0; 2019 uint32_t *prev_acs_list; 2020 struct ieee80211_chan_def *chans = req->data.user_chanlist.chans; 2021 uint16_t nchans = req->data.user_chanlist.n_chan; 2022 struct wlan_objmgr_pdev *pdev = wlan_vdev_get_pdev(vdev); 2023 struct hdd_adapter *adapter; 2024 struct wlan_hdd_link_info *link_info; 2025 struct hdd_context *hdd_ctx; 2026 2027 link_info = wlan_hdd_get_link_info_from_objmgr(vdev); 2028 if (!link_info || !req) { 2029 hdd_err("null adapter or req"); 2030 return -EINVAL; 2031 } 2032 2033 adapter = link_info->adapter; 2034 if (adapter->device_mode != QDF_SAP_MODE) { 2035 hdd_err("Invalid device mode %d", adapter->device_mode); 2036 return -EINVAL; 2037 } 2038 if (!nchans) { 2039 hdd_err("No channels are sent to be set"); 2040 return -EINVAL; 2041 } 2042 hdd_ctx = WLAN_HDD_GET_CTX(adapter); 2043 if (!hdd_ctx) { 2044 hdd_err("null hdd_ctx"); 2045 return -EINVAL; 2046 } 2047 sap_config = &link_info->session.ap.sap_config; 2048 /* initialize with default channels */ 2049 if (hdd_son_init_acs_channels(adapter, hdd_ctx, &sap_config->acs_cfg) 2050 != QDF_STATUS_SUCCESS) { 2051 hdd_err("Failed to start the ACS"); 2052 return -EAGAIN; 2053 } 2054 append = (chans[0].chan == ACS_SET_CHAN_LIST_APPEND); 2055 if (append) { 2056 chan_start = 1; 2057 acs_chan_count = sap_config->acs_cfg.ch_list_count; 2058 } 2059 prev_acs_list = sap_config->acs_cfg.freq_list; 2060 for (i = chan_start; i < nchans; i++) { 2061 tmp = wlan_reg_legacy_chan_to_freq(pdev, chans[i].chan); 2062 if (append) { 2063 for (j = 0; j < acs_chan_count; j++) { 2064 if (prev_acs_list[j] == tmp) { 2065 dup = true; 2066 break; 2067 } 2068 } 2069 } 2070 /* Remove duplicate */ 2071 if (!dup) { 2072 freq_list[chan_idx] = tmp; 2073 chan_idx++; 2074 } else { 2075 dup = false; 2076 } 2077 } 2078 num_channels = chan_idx + acs_chan_count; 2079 sap_config->acs_cfg.ch_list_count = num_channels; 2080 sap_config->acs_cfg.freq_list = 2081 qdf_mem_malloc(num_channels * 2082 sizeof(*sap_config->acs_cfg.freq_list)); 2083 if (!sap_config->acs_cfg.freq_list) { 2084 hdd_err("Error in allocating memory, failed to set channels"); 2085 sap_config->acs_cfg.freq_list = prev_acs_list; 2086 sap_config->acs_cfg.ch_list_count = acs_chan_count; 2087 return -ENOMEM; 2088 } 2089 if (append) 2090 qdf_mem_copy(sap_config->acs_cfg.freq_list, prev_acs_list, 2091 sizeof(uint32_t) * acs_chan_count); 2092 qdf_mem_copy(&sap_config->acs_cfg.freq_list[acs_chan_count], freq_list, 2093 sizeof(uint32_t) * chan_idx); 2094 qdf_mem_free(prev_acs_list); 2095 2096 return 0; 2097 } 2098 2099 static enum wlan_band_id 2100 reg_wifi_band_to_wlan_band_id(enum reg_wifi_band reg_wifi_band) 2101 { 2102 enum wlan_band_id wlan_band; 2103 const uint32_t reg_wifi_band_to_wlan_band_id_map[] = { 2104 [REG_BAND_2G] = WLAN_BAND_2GHZ, 2105 [REG_BAND_5G] = WLAN_BAND_5GHZ, 2106 [REG_BAND_6G] = WLAN_BAND_6GHZ, 2107 [REG_BAND_UNKNOWN] = WLAN_BAND_MAX,}; 2108 2109 wlan_band = reg_wifi_band_to_wlan_band_id_map[reg_wifi_band]; 2110 if (wlan_band == WLAN_BAND_MAX) { 2111 hdd_err("Invalid wlan_band_id %d, reg_wifi_band: %d", 2112 wlan_band, reg_wifi_band); 2113 return -EINVAL; 2114 } 2115 2116 return wlan_band; 2117 } 2118 2119 /** 2120 * get_son_acs_report_values() - Gets ACS report for target channel 2121 * 2122 * @vdev: pointer to object mgr vdev 2123 * @acs_r: pointer to acs_dbg 2124 * @mac_handle: Handle to MAC 2125 * @chan_freq: Channel frequency 2126 * 2127 * Return: void 2128 */ 2129 static void get_son_acs_report_values(struct wlan_objmgr_vdev *vdev, 2130 struct ieee80211_acs_dbg *acs_r, 2131 mac_handle_t mac_handle, 2132 uint16_t chan_freq) 2133 { 2134 struct wlan_objmgr_pdev *pdev = wlan_vdev_get_pdev(vdev); 2135 struct scan_filter *filter = qdf_mem_malloc(sizeof(*filter)); 2136 struct scan_cache_node *cur_node; 2137 struct scan_cache_entry *se; 2138 enum ieee80211_phymode phymode_se; 2139 struct ieee80211_ie_hecap *hecap_ie; 2140 struct ieee80211_ie_srp_extie *srp_ie; 2141 qdf_list_node_t *cur_lst = NULL, *next_lst = NULL; 2142 uint32_t srps = 0; 2143 qdf_list_t *scan_list = NULL; 2144 uint8_t snr_se, *hecap_phy_ie; 2145 2146 if (!filter) 2147 return; 2148 filter->num_of_channels = 1; 2149 filter->chan_freq_list[0] = chan_freq; 2150 scan_list = ucfg_scan_get_result(pdev, filter); 2151 acs_r->chan_nbss = qdf_list_size(scan_list); 2152 2153 acs_r->chan_maxrssi = 0; 2154 acs_r->chan_minrssi = 0; 2155 acs_r->chan_nbss_near = 0; 2156 acs_r->chan_nbss_mid = 0; 2157 acs_r->chan_nbss_far = 0; 2158 acs_r->chan_nbss_srp = 0; 2159 qdf_list_peek_front(scan_list, &cur_lst); 2160 while (cur_lst) { 2161 qdf_list_peek_next(scan_list, cur_lst, &next_lst); 2162 cur_node = qdf_container_of(cur_lst, 2163 struct scan_cache_node, node); 2164 se = cur_node->entry; 2165 snr_se = util_scan_entry_snr(se); 2166 hecap_ie = (struct ieee80211_ie_hecap *) 2167 util_scan_entry_hecap(se); 2168 srp_ie = (struct ieee80211_ie_srp_extie *) 2169 util_scan_entry_spatial_reuse_parameter(se); 2170 phymode_se = util_scan_entry_phymode(se); 2171 2172 if (hecap_ie) { 2173 hecap_phy_ie = &hecap_ie->hecap_phyinfo[0]; 2174 srps = hecap_phy_ie[HECAP_PHYBYTE_IDX7] & 2175 HECAP_PHY_SRP_SR_BITS; 2176 } 2177 2178 if (acs_r->chan_maxrssi < snr_se) 2179 acs_r->chan_maxrssi = snr_se; 2180 else if (acs_r->chan_minrssi > snr_se) 2181 acs_r->chan_minrssi = snr_se; 2182 if (snr_se > ACS_SNR_NEAR_RANGE_MIN) 2183 acs_r->chan_nbss_near += 1; 2184 else if (snr_se > ACS_SNR_MID_RANGE_MIN) 2185 acs_r->chan_nbss_mid += 1; 2186 else 2187 acs_r->chan_nbss_far += 1; 2188 if (srp_ie && 2189 (!(srp_ie->sr_control & 2190 IEEE80211_SRP_SRCTRL_OBSS_PD_DISALLOWED_MASK) || srps)) 2191 acs_r->chan_nbss_srp++; 2192 2193 cur_lst = next_lst; 2194 next_lst = NULL; 2195 } 2196 acs_r->chan_80211_b_duration = sme_get_11b_data_duration(mac_handle, 2197 chan_freq); 2198 acs_r->chan_nbss_eff = 100 + (acs_r->chan_nbss_near * 50) 2199 + (acs_r->chan_nbss_mid * 50) 2200 + (acs_r->chan_nbss_far * 25); 2201 acs_r->chan_srp_load = acs_r->chan_nbss_srp * 4; 2202 acs_r->chan_efficiency = (1000 + acs_r->chan_grade) / 2203 acs_r->chan_nbss_eff; 2204 ucfg_scan_purge_results(scan_list); 2205 2206 qdf_mem_free(filter); 2207 } 2208 2209 /** 2210 * hdd_son_get_acs_report() - Gets ACS report 2211 * 2212 * @vdev: pointer to object mgr vdev 2213 * @acs_report: pointer to acs_dbg 2214 * 2215 * Return: 0 on success 2216 */ 2217 static int hdd_son_get_acs_report(struct wlan_objmgr_vdev *vdev, 2218 struct ieee80211_acs_dbg *acs_report) 2219 { 2220 struct hdd_adapter *adapter; 2221 struct wlan_hdd_link_info *link_info; 2222 uint8_t acs_entry_id = 0; 2223 ACS_LIST_TYPE acs_type = 0; 2224 int ret = 0, i = 0; 2225 struct sap_acs_cfg *acs_cfg; 2226 struct hdd_context *hdd_ctx; 2227 struct ieee80211_acs_dbg *acs_r = NULL; 2228 struct sap_context *sap_ctx; 2229 2230 if (!acs_report) { 2231 hdd_err("null acs_report"); 2232 ret = -EINVAL; 2233 goto end; 2234 } 2235 2236 link_info = wlan_hdd_get_link_info_from_objmgr(vdev); 2237 if (!link_info) { 2238 hdd_err("null adapter"); 2239 ret = -EINVAL; 2240 goto end; 2241 } 2242 2243 adapter = link_info->adapter; 2244 if (adapter->device_mode != QDF_SAP_MODE) { 2245 hdd_err("Invalid device mode %d", adapter->device_mode); 2246 ret = -EINVAL; 2247 goto end; 2248 } 2249 if (hdd_son_is_acs_in_progress(vdev)) { 2250 acs_report->nchans = 0; 2251 hdd_err("ACS is in-progress"); 2252 ret = -EAGAIN; 2253 goto end; 2254 } 2255 hdd_ctx = WLAN_HDD_GET_CTX(adapter); 2256 if (!hdd_ctx) { 2257 hdd_err("null hdd_ctx"); 2258 ret = -EINVAL; 2259 goto end; 2260 } 2261 acs_r = qdf_mem_malloc(sizeof(*acs_r)); 2262 if (!acs_r) { 2263 hdd_err("Failed to allocate memory"); 2264 ret = -ENOMEM; 2265 goto end; 2266 } 2267 sap_ctx = WLAN_HDD_GET_SAP_CTX_PTR(link_info); 2268 acs_cfg = &link_info->session.ap.sap_config.acs_cfg; 2269 if (!acs_cfg->freq_list && 2270 (hdd_son_init_acs_channels(adapter, hdd_ctx, 2271 acs_cfg) != QDF_STATUS_SUCCESS)) { 2272 hdd_err("Failed to start the ACS"); 2273 ret = -EAGAIN; 2274 goto end_acs_r_free; 2275 } 2276 acs_r->nchans = acs_cfg->ch_list_count; 2277 ret = copy_from_user(&acs_entry_id, &acs_report->entry_id, 2278 sizeof(acs_report->entry_id)); 2279 hdd_debug("acs entry id: %u num of channels: %u", 2280 acs_entry_id, acs_r->nchans); 2281 if (acs_entry_id > acs_r->nchans) { 2282 ret = -EINVAL; 2283 goto end_acs_r_free; 2284 } 2285 ret = copy_from_user(&acs_type, &acs_report->acs_type, 2286 sizeof(acs_report->acs_type)); 2287 2288 acs_r->acs_status = ACS_DEFAULT; 2289 acs_r->chan_freq = acs_cfg->freq_list[acs_entry_id]; 2290 acs_r->chan_band = reg_wifi_band_to_wlan_band_id 2291 (wlan_reg_freq_to_band(acs_r->chan_freq)); 2292 hdd_debug("acs type: %d", acs_type); 2293 if (acs_type == ACS_CHAN_STATS) { 2294 acs_r->ieee_chan = wlan_reg_freq_to_chan(hdd_ctx->pdev, 2295 acs_r->chan_freq); 2296 acs_r->chan_width = IEEE80211_CWM_WIDTH20; 2297 acs_r->channel_loading = 0; 2298 acs_r->chan_availability = 100; 2299 acs_r->chan_grade = 100; /* as hw_chan_grade is 100 in WIN 8 */ 2300 acs_r->sec_chan = false; 2301 acs_r->chan_radar_noise = 2302 wlansap_is_channel_in_nol_list(sap_ctx, acs_r->chan_freq, 2303 PHY_SINGLE_CHANNEL_CENTERED); 2304 get_son_acs_report_values(vdev, acs_r, hdd_ctx->mac_handle, 2305 acs_r->chan_freq); 2306 acs_r->chan_load = 0; 2307 acs_r->noisefloor = -254; /* NF_INVALID */ 2308 for (i = 0; i < SIR_MAX_NUM_CHANNELS; i++) { 2309 if (hdd_ctx->chan_info[i].freq == acs_r->chan_freq) { 2310 acs_r->noisefloor = 2311 hdd_ctx->chan_info[i].noise_floor; 2312 acs_r->chan_load = 2313 hdd_ctx->chan_info[i].rx_clear_count; 2314 break; 2315 } 2316 } 2317 copy_to_user(acs_report, acs_r, sizeof(*acs_r)); 2318 } else if (acs_type == ACS_CHAN_NF_STATS) { 2319 } else if (acs_type == ACS_NEIGHBOUR_GET_LIST_COUNT || 2320 acs_type == ACS_NEIGHBOUR_GET_LIST) { 2321 } 2322 end_acs_r_free: 2323 qdf_mem_free(acs_r); 2324 end: 2325 return ret; 2326 } 2327 2328 static const uint8_t wlanphymode2ieeephymode[WLAN_PHYMODE_MAX] = { 2329 [WLAN_PHYMODE_AUTO] = IEEE80211_MODE_AUTO, 2330 [WLAN_PHYMODE_11A] = IEEE80211_MODE_11A, 2331 [WLAN_PHYMODE_11B] = IEEE80211_MODE_11B, 2332 [WLAN_PHYMODE_11G] = IEEE80211_MODE_11G, 2333 [WLAN_PHYMODE_11G_ONLY] = IEEE80211_MODE_11G, 2334 [WLAN_PHYMODE_11NA_HT20] = IEEE80211_MODE_11NA_HT20, 2335 [WLAN_PHYMODE_11NG_HT20] = IEEE80211_MODE_11NG_HT20, 2336 [WLAN_PHYMODE_11NA_HT40] = IEEE80211_MODE_11NA_HT40, 2337 [WLAN_PHYMODE_11NG_HT40PLUS] = IEEE80211_MODE_11NG_HT40PLUS, 2338 [WLAN_PHYMODE_11NG_HT40MINUS] = IEEE80211_MODE_11NG_HT40MINUS, 2339 [WLAN_PHYMODE_11NG_HT40] = IEEE80211_MODE_11NG_HT40, 2340 [WLAN_PHYMODE_11AC_VHT20] = IEEE80211_MODE_11AC_VHT20, 2341 [WLAN_PHYMODE_11AC_VHT20_2G] = IEEE80211_MODE_11AC_VHT20, 2342 [WLAN_PHYMODE_11AC_VHT40] = IEEE80211_MODE_11AC_VHT40, 2343 [WLAN_PHYMODE_11AC_VHT40PLUS_2G] = IEEE80211_MODE_11AC_VHT40PLUS, 2344 [WLAN_PHYMODE_11AC_VHT40MINUS_2G] = IEEE80211_MODE_11AC_VHT40MINUS, 2345 [WLAN_PHYMODE_11AC_VHT40_2G] = IEEE80211_MODE_11AC_VHT40, 2346 [WLAN_PHYMODE_11AC_VHT80] = IEEE80211_MODE_11AC_VHT80, 2347 [WLAN_PHYMODE_11AC_VHT80_2G] = IEEE80211_MODE_11AC_VHT80, 2348 [WLAN_PHYMODE_11AC_VHT160] = IEEE80211_MODE_11AC_VHT160, 2349 [WLAN_PHYMODE_11AC_VHT80_80] = IEEE80211_MODE_11AC_VHT80_80, 2350 [WLAN_PHYMODE_11AXA_HE20] = IEEE80211_MODE_11AXA_HE20, 2351 [WLAN_PHYMODE_11AXG_HE20] = IEEE80211_MODE_11AXG_HE20, 2352 [WLAN_PHYMODE_11AXA_HE40] = IEEE80211_MODE_11AXA_HE40, 2353 [WLAN_PHYMODE_11AXG_HE40PLUS] = IEEE80211_MODE_11AXG_HE40PLUS, 2354 [WLAN_PHYMODE_11AXG_HE40MINUS] = IEEE80211_MODE_11AXG_HE40MINUS, 2355 [WLAN_PHYMODE_11AXG_HE40] = IEEE80211_MODE_11AXG_HE40, 2356 [WLAN_PHYMODE_11AXA_HE80] = IEEE80211_MODE_11AXA_HE80, 2357 [WLAN_PHYMODE_11AXA_HE160] = IEEE80211_MODE_11AXA_HE160, 2358 [WLAN_PHYMODE_11AXA_HE80_80] = IEEE80211_MODE_11AXA_HE80_80, 2359 #ifdef WLAN_FEATURE_11BE 2360 [WLAN_PHYMODE_11BEA_EHT20] = IEEE80211_MODE_11BEA_EHT20, 2361 [WLAN_PHYMODE_11BEG_EHT20] = IEEE80211_MODE_11BEG_EHT20, 2362 [WLAN_PHYMODE_11BEA_EHT40MINUS] = IEEE80211_MODE_11BEA_EHT40, 2363 [WLAN_PHYMODE_11BEG_EHT40PLUS] = IEEE80211_MODE_11BEG_EHT40PLUS, 2364 [WLAN_PHYMODE_11BEG_EHT40MINUS] = IEEE80211_MODE_11BEG_EHT40MINUS, 2365 [WLAN_PHYMODE_11BEG_EHT40] = IEEE80211_MODE_11BEG_EHT40, 2366 [WLAN_PHYMODE_11BEA_EHT80] = IEEE80211_MODE_11BEA_EHT80, 2367 [WLAN_PHYMODE_11BEG_EHT80] = 0, 2368 [WLAN_PHYMODE_11BEA_EHT160] = IEEE80211_MODE_11BEA_EHT160, 2369 [WLAN_PHYMODE_11BEA_EHT320] = IEEE80211_MODE_11BEA_EHT320, 2370 #endif /* WLAN_FEATURE_11BE */ 2371 }; 2372 2373 static enum ieee80211_phymode 2374 wlan_hdd_son_get_ieee_phymode(enum wlan_phymode wlan_phymode) 2375 { 2376 if (wlan_phymode >= WLAN_PHYMODE_MAX) 2377 return IEEE80211_MODE_AUTO; 2378 2379 return wlanphymode2ieeephymode[wlan_phymode]; 2380 } 2381 2382 /** 2383 * hdd_son_get_peer_tx_rate() - Get peer tx rate from FW 2384 * @vdev: pointer to object mgr vdev 2385 * @peer_macaddr: peer mac address 2386 * 2387 * Return: tx rate in Kbps 2388 */ 2389 static uint32_t hdd_son_get_peer_tx_rate(struct wlan_objmgr_vdev *vdev, 2390 uint8_t *peer_macaddr) 2391 { 2392 uint32_t tx_rate = 0; 2393 struct stats_event *stats; 2394 int retval = 0; 2395 2396 stats = wlan_cfg80211_mc_cp_stats_get_peer_stats(vdev, 2397 peer_macaddr, 2398 &retval); 2399 if (retval || !stats) { 2400 if (stats) 2401 wlan_cfg80211_mc_cp_stats_free_stats_event(stats); 2402 hdd_err("Unable to get peer tx rate from fw"); 2403 return tx_rate; 2404 } 2405 2406 tx_rate = stats->peer_stats_info_ext->tx_rate; 2407 wlan_cfg80211_mc_cp_stats_free_stats_event(stats); 2408 2409 return tx_rate; 2410 } 2411 2412 static QDF_STATUS hdd_son_get_node_info_sta(struct wlan_objmgr_vdev *vdev, 2413 uint8_t *mac_addr, 2414 wlan_node_info *node_info) 2415 { 2416 struct wlan_hdd_link_info *link_info; 2417 2418 link_info = wlan_hdd_get_link_info_from_objmgr(vdev); 2419 if (!link_info || 2420 wlan_hdd_validate_context(link_info->adapter->hdd_ctx)) 2421 return QDF_STATUS_E_FAILURE; 2422 2423 if (!hdd_cm_is_vdev_associated(link_info)) { 2424 hdd_debug_rl("STA VDEV not connected"); 2425 /* Still return success and framework will see default stats */ 2426 return QDF_STATUS_SUCCESS; 2427 } 2428 2429 node_info->tx_bitrate = hdd_son_get_peer_tx_rate(vdev, mac_addr); 2430 /* convert it to Mbps */ 2431 node_info->tx_bitrate = qdf_do_div(node_info->tx_bitrate, 1000); 2432 hdd_debug_rl("tx_bitrate %u", node_info->tx_bitrate); 2433 2434 return QDF_STATUS_SUCCESS; 2435 } 2436 2437 static QDF_STATUS hdd_son_get_node_info_sap(struct wlan_objmgr_vdev *vdev, 2438 uint8_t *mac_addr, 2439 wlan_node_info *node_info) 2440 { 2441 struct hdd_adapter *adapter; 2442 struct wlan_hdd_link_info *link_info; 2443 struct hdd_station_info *sta_info; 2444 enum wlan_phymode peer_phymode; 2445 struct wlan_objmgr_psoc *psoc; 2446 2447 link_info = wlan_hdd_get_link_info_from_objmgr(vdev); 2448 if (!link_info) { 2449 hdd_debug("NULL adapter"); 2450 return QDF_STATUS_E_FAILURE; 2451 } 2452 2453 adapter = link_info->adapter; 2454 sta_info = hdd_get_sta_info_by_mac(&adapter->sta_info_list, mac_addr, 2455 STA_INFO_SON_GET_DATRATE_INFO); 2456 if (!sta_info) { 2457 hdd_err("Sta info is null"); 2458 return QDF_STATUS_E_FAILURE; 2459 } 2460 psoc = wlan_vdev_get_psoc(vdev); 2461 if (!psoc) { 2462 hdd_err("null psoc"); 2463 return QDF_STATUS_E_FAILURE; 2464 } 2465 2466 node_info->tx_bitrate = hdd_son_get_peer_tx_rate(vdev, mac_addr); 2467 /* convert it to Mbps */ 2468 node_info->tx_bitrate = qdf_do_div(node_info->tx_bitrate, 1000); 2469 node_info->max_chwidth = 2470 hdd_chan_width_to_son_chwidth(sta_info->ch_width); 2471 node_info->num_streams = sta_info->nss; 2472 ucfg_mlme_get_peer_phymode(psoc, mac_addr, &peer_phymode); 2473 node_info->phymode = wlan_hdd_son_get_ieee_phymode(peer_phymode); 2474 node_info->max_txpower = ucfg_son_get_tx_power(sta_info->assoc_req_ies); 2475 node_info->max_MCS = sta_info->max_real_mcs_idx; 2476 if (node_info->max_MCS == INVALID_MCS_NSS_INDEX) { 2477 hdd_err("invalid mcs"); 2478 return QDF_STATUS_E_FAILURE; 2479 } 2480 if (sta_info->vht_present) 2481 node_info->is_mu_mimo_supported = 2482 sta_info->vht_caps.vht_cap_info 2483 & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE; 2484 if (sta_info->ht_present) 2485 node_info->is_static_smps = ((sta_info->ht_caps.cap_info 2486 & IEEE80211_HTCAP_C_SM_MASK) == 2487 IEEE80211_HTCAP_C_SMPOWERSAVE_STATIC); 2488 hdd_put_sta_info_ref(&adapter->sta_info_list, &sta_info, true, 2489 STA_INFO_SON_GET_DATRATE_INFO); 2490 return QDF_STATUS_SUCCESS; 2491 } 2492 2493 static QDF_STATUS hdd_son_get_node_info(struct wlan_objmgr_vdev *vdev, 2494 uint8_t *mac_addr, 2495 wlan_node_info *node_info) 2496 { 2497 struct hdd_adapter *adapter; 2498 struct wlan_hdd_link_info *link_info; 2499 2500 link_info = wlan_hdd_get_link_info_from_objmgr(vdev); 2501 if (!link_info) { 2502 hdd_debug("NULL adapter"); 2503 return QDF_STATUS_E_FAILURE; 2504 } 2505 2506 adapter = link_info->adapter; 2507 if (adapter->device_mode == QDF_STA_MODE) 2508 return hdd_son_get_node_info_sta(vdev, mac_addr, node_info); 2509 else if (adapter->device_mode == QDF_SAP_MODE) 2510 return hdd_son_get_node_info_sap(vdev, mac_addr, node_info); 2511 else 2512 return QDF_STATUS_SUCCESS; 2513 } 2514 2515 static QDF_STATUS hdd_son_get_peer_capability(struct wlan_objmgr_vdev *vdev, 2516 struct wlan_objmgr_peer *peer, 2517 wlan_peer_cap *peer_cap) 2518 { 2519 struct hdd_station_info *sta_info; 2520 struct hdd_adapter *adapter; 2521 struct wlan_hdd_link_info *link_info; 2522 bool b_meas_supported; 2523 QDF_STATUS status; 2524 2525 link_info = wlan_hdd_get_link_info_from_objmgr(vdev); 2526 if (!link_info) { 2527 hdd_err("null adapter"); 2528 return QDF_STATUS_E_FAILURE; 2529 } 2530 2531 adapter = link_info->adapter; 2532 sta_info = hdd_get_sta_info_by_mac(&adapter->sta_info_list, 2533 peer->macaddr, 2534 STA_INFO_SOFTAP_GET_STA_INFO); 2535 if (!sta_info) { 2536 hdd_err("sta_info NULL"); 2537 return QDF_STATUS_E_FAILURE; 2538 } 2539 2540 hdd_info("Getting peer capability from sta_info"); 2541 qdf_mem_copy(peer_cap->bssid, vdev->vdev_mlme.macaddr, 2542 QDF_MAC_ADDR_SIZE); 2543 peer_cap->is_BTM_Supported = !!(sta_info->ext_cap & 2544 BIT(19/*BSS_TRANSITION*/)); 2545 peer_cap->is_RRM_Supported = !!(sta_info->capability & 2546 WLAN_CAPABILITY_RADIO_MEASURE); 2547 2548 peer_cap->band_cap = sta_info->supported_band; 2549 if (sta_info->assoc_req_ies.len) { 2550 status = ucfg_son_get_peer_rrm_info(sta_info->assoc_req_ies, 2551 peer_cap->rrmcaps, 2552 &(b_meas_supported)); 2553 if (status == QDF_STATUS_SUCCESS) 2554 peer_cap->is_beacon_meas_supported = b_meas_supported; 2555 } 2556 if (sta_info->ht_present) 2557 peer_cap->htcap = sta_info->ht_caps.cap_info; 2558 if (sta_info->vht_present) 2559 peer_cap->vhtcap = sta_info->vht_caps.vht_cap_info; 2560 2561 qdf_mem_zero(&peer_cap->hecap, sizeof(wlan_client_he_capabilities)); 2562 2563 os_if_son_get_node_datarate_info(vdev, peer->macaddr, 2564 &peer_cap->info); 2565 2566 hdd_put_sta_info_ref(&adapter->sta_info_list, &sta_info, true, 2567 STA_INFO_SOFTAP_GET_STA_INFO); 2568 2569 return QDF_STATUS_SUCCESS; 2570 } 2571 2572 uint32_t hdd_son_get_peer_max_mcs_idx(struct wlan_objmgr_vdev *vdev, 2573 struct wlan_objmgr_peer *peer) 2574 { 2575 uint32_t ret = 0; 2576 struct hdd_station_info *sta_info = NULL; 2577 struct hdd_adapter *adapter; 2578 struct wlan_hdd_link_info *link_info; 2579 2580 link_info = wlan_hdd_get_link_info_from_objmgr(vdev); 2581 if (!link_info) { 2582 hdd_err("null adapter"); 2583 return ret; 2584 } 2585 2586 adapter = link_info->adapter; 2587 sta_info = hdd_get_sta_info_by_mac(&adapter->sta_info_list, 2588 peer->macaddr, 2589 STA_INFO_SOFTAP_GET_STA_INFO); 2590 if (!sta_info) { 2591 hdd_err("sta_info NULL"); 2592 return ret; 2593 } 2594 2595 ret = sta_info->max_real_mcs_idx; 2596 2597 hdd_put_sta_info_ref(&adapter->sta_info_list, &sta_info, true, 2598 STA_INFO_SOFTAP_GET_STA_INFO); 2599 hdd_debug("Peer " QDF_MAC_ADDR_FMT " max MCS index: %u", 2600 QDF_MAC_ADDR_REF(peer->macaddr), ret); 2601 2602 return ret; 2603 } 2604 2605 /** 2606 * hdd_son_get_sta_stats() - get connected sta rssi and estimated data rate 2607 * @vdev: pointer to vdev 2608 * @mac_addr: connected sta mac addr 2609 * @stats: pointer to ieee80211_nodestats 2610 * 2611 * Return: 0 on success, negative errno on failure 2612 */ 2613 static int hdd_son_get_sta_stats(struct wlan_objmgr_vdev *vdev, 2614 uint8_t *mac_addr, 2615 struct ieee80211_nodestats *stats) 2616 { 2617 struct stats_event *stats_info; 2618 int ret = 0; 2619 2620 stats_info = wlan_cfg80211_mc_cp_stats_get_peer_rssi( 2621 vdev, mac_addr, &ret); 2622 if (ret || !stats_info) { 2623 hdd_err("get peer rssi fail"); 2624 wlan_cfg80211_mc_cp_stats_free_stats_event(stats_info); 2625 return ret; 2626 } 2627 stats->ns_rssi = stats_info->peer_stats[0].peer_rssi; 2628 stats->ns_last_tx_rate = stats_info->peer_stats[0].tx_rate; 2629 stats->ns_last_rx_rate = stats_info->peer_stats[0].rx_rate; 2630 hdd_debug("sta " QDF_MAC_ADDR_FMT " rssi %d tx %u kbps, rx %u kbps", 2631 QDF_MAC_ADDR_REF(mac_addr), stats->ns_rssi, 2632 stats->ns_last_tx_rate, 2633 stats->ns_last_rx_rate); 2634 wlan_cfg80211_mc_cp_stats_free_stats_event(stats_info); 2635 2636 return ret; 2637 } 2638 2639 void hdd_son_register_callbacks(struct hdd_context *hdd_ctx) 2640 { 2641 struct son_callbacks cb_obj = {0}; 2642 2643 cb_obj.os_if_is_acs_in_progress = hdd_son_is_acs_in_progress; 2644 cb_obj.os_if_set_chan_ext_offset = hdd_son_set_chan_ext_offset; 2645 cb_obj.os_if_get_chan_ext_offset = hdd_son_get_chan_ext_offset; 2646 cb_obj.os_if_set_bandwidth = hdd_son_set_bandwidth; 2647 cb_obj.os_if_get_bandwidth = hdd_son_get_bandwidth; 2648 cb_obj.os_if_set_chan = hdd_son_set_chan; 2649 cb_obj.os_if_set_acl_policy = hdd_son_set_acl_policy; 2650 cb_obj.os_if_get_acl_policy = hdd_son_get_acl_policy; 2651 cb_obj.os_if_add_acl_mac = hdd_son_add_acl_mac; 2652 cb_obj.os_if_del_acl_mac = hdd_son_del_acl_mac; 2653 cb_obj.os_if_kickout_mac = hdd_son_kickout_mac; 2654 cb_obj.os_if_set_country_code = hdd_son_set_country; 2655 cb_obj.os_if_set_candidate_freq = hdd_son_set_candidate_freq; 2656 cb_obj.os_if_get_candidate_freq = hdd_son_get_candidate_freq; 2657 cb_obj.os_if_set_phymode = hdd_son_set_phymode; 2658 cb_obj.os_if_get_phymode = hdd_son_get_phymode; 2659 cb_obj.os_if_get_rx_nss = hdd_son_get_rx_nss; 2660 cb_obj.os_if_set_chwidth = hdd_son_set_chwidth; 2661 cb_obj.os_if_get_chwidth = hdd_son_get_chwidth; 2662 cb_obj.os_if_deauth_sta = hdd_son_deauth_sta; 2663 cb_obj.os_if_modify_acl = hdd_son_modify_acl; 2664 cb_obj.os_if_get_sta_list = hdd_son_get_sta_list; 2665 cb_obj.os_if_get_sta_space = hdd_son_get_sta_space; 2666 cb_obj.os_if_get_vdev_by_netdev = hdd_son_get_vdev_by_netdev; 2667 cb_obj.os_if_trigger_objmgr_object_creation = 2668 hdd_son_trigger_objmgr_object_creation; 2669 cb_obj.os_if_trigger_objmgr_object_deletion = 2670 hdd_son_trigger_objmgr_object_deletion; 2671 cb_obj.os_if_start_acs = hdd_son_start_acs; 2672 cb_obj.os_if_set_acs_channels = hdd_son_set_acs_channels; 2673 cb_obj.os_if_get_acs_report = hdd_son_get_acs_report; 2674 cb_obj.os_if_get_node_info = hdd_son_get_node_info; 2675 cb_obj.os_if_get_peer_capability = hdd_son_get_peer_capability; 2676 cb_obj.os_if_get_peer_max_mcs_idx = hdd_son_get_peer_max_mcs_idx; 2677 cb_obj.os_if_get_sta_stats = hdd_son_get_sta_stats; 2678 2679 os_if_son_register_hdd_callbacks(hdd_ctx->psoc, &cb_obj); 2680 2681 ucfg_son_register_deliver_opmode_cb(hdd_ctx->psoc, 2682 hdd_son_deliver_opmode); 2683 ucfg_son_register_deliver_smps_cb(hdd_ctx->psoc, 2684 hdd_son_deliver_smps); 2685 } 2686 2687 int hdd_son_deliver_acs_complete_event(struct hdd_adapter *adapter) 2688 { 2689 int ret = -EINVAL; 2690 struct wlan_objmgr_vdev *vdev; 2691 2692 vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_SON_ID); 2693 if (!vdev) { 2694 hdd_err("null vdev"); 2695 return ret; 2696 } 2697 ret = os_if_son_deliver_ald_event(vdev, NULL, MLME_EVENT_ACS_COMPLETE, 2698 NULL); 2699 hdd_objmgr_put_vdev_by_user(vdev, WLAN_SON_ID); 2700 return ret; 2701 } 2702 2703 int hdd_son_deliver_cac_status_event(struct hdd_adapter *adapter, 2704 qdf_freq_t freq, bool radar_detected) 2705 { 2706 int ret = -EINVAL; 2707 struct wlan_objmgr_vdev *vdev; 2708 struct son_ald_cac_info cac_info; 2709 2710 vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_SON_ID); 2711 if (!vdev) { 2712 hdd_err("null vdev"); 2713 return ret; 2714 } 2715 cac_info.freq = freq; 2716 cac_info.radar_detected = radar_detected; 2717 ret = os_if_son_deliver_ald_event(vdev, NULL, MLME_EVENT_CAC_STATUS, 2718 &cac_info); 2719 hdd_objmgr_put_vdev_by_user(vdev, WLAN_SON_ID); 2720 2721 return ret; 2722 } 2723 2724 int hdd_son_deliver_assoc_disassoc_event(struct hdd_adapter *adapter, 2725 struct qdf_mac_addr sta_mac, 2726 uint32_t reason_code, 2727 enum assoc_disassoc_event flag) 2728 { 2729 int ret = -EINVAL; 2730 struct son_ald_assoc_event_info info; 2731 struct wlan_objmgr_vdev *vdev; 2732 2733 qdf_mem_zero(&info, sizeof(info)); 2734 memcpy(info.macaddr, &sta_mac.bytes, QDF_MAC_ADDR_SIZE); 2735 info.flag = flag; 2736 info.reason = reason_code; 2737 2738 vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_SON_ID); 2739 if (!vdev) { 2740 hdd_err("null vdev"); 2741 return ret; 2742 } 2743 ret = os_if_son_deliver_ald_event(vdev, NULL, MLME_EVENT_ASSOC_DISASSOC, 2744 &info); 2745 hdd_objmgr_put_vdev_by_user(vdev, WLAN_SON_ID); 2746 return ret; 2747 } 2748 2749 void hdd_son_deliver_peer_authorize_event(struct wlan_hdd_link_info *link_info, 2750 uint8_t *peer_mac) 2751 { 2752 struct wlan_objmgr_peer *peer; 2753 int ret; 2754 struct wlan_objmgr_vdev *vdev; 2755 struct wlan_objmgr_psoc *psoc; 2756 2757 if (link_info->adapter->device_mode != QDF_SAP_MODE) { 2758 hdd_err("Non SAP vdev"); 2759 return; 2760 } 2761 vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_SON_ID); 2762 if (!vdev) { 2763 hdd_err("null vdev"); 2764 return; 2765 } 2766 psoc = wlan_vdev_get_psoc(vdev); 2767 if (!psoc) { 2768 hdd_err("null psoc"); 2769 hdd_objmgr_put_vdev_by_user(vdev, WLAN_SON_ID); 2770 return; 2771 } 2772 peer = wlan_objmgr_get_peer_by_mac(psoc, peer_mac, WLAN_UMAC_COMP_SON); 2773 if (!peer) { 2774 hdd_err("No peer object for sta" QDF_MAC_ADDR_FMT, 2775 QDF_MAC_ADDR_REF(peer_mac)); 2776 hdd_objmgr_put_vdev_by_user(vdev, WLAN_SON_ID); 2777 return; 2778 } 2779 2780 ret = os_if_son_deliver_ald_event(vdev, peer, 2781 MLME_EVENT_CLIENT_ASSOCIATED, NULL); 2782 if (ret) 2783 hdd_err("ALD ASSOCIATED Event failed for" QDF_MAC_ADDR_FMT, 2784 QDF_MAC_ADDR_REF(peer_mac)); 2785 2786 wlan_objmgr_peer_release_ref(peer, WLAN_UMAC_COMP_SON); 2787 hdd_objmgr_put_vdev_by_user(vdev, WLAN_SON_ID); 2788 } 2789 2790 int hdd_son_deliver_chan_change_event(struct hdd_adapter *adapter, 2791 qdf_freq_t freq) 2792 { 2793 int ret = -EINVAL; 2794 struct wlan_objmgr_vdev *vdev; 2795 struct son_ald_chan_change_info chan_info; 2796 struct wlan_objmgr_pdev *pdev; 2797 2798 if (!adapter) { 2799 hdd_err("null adapter"); 2800 return ret; 2801 } 2802 vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_SON_ID); 2803 if (!vdev) { 2804 hdd_err("null vdev"); 2805 return ret; 2806 } 2807 pdev = wlan_vdev_get_pdev(vdev); 2808 if (!pdev) { 2809 hdd_err("null pdev"); 2810 hdd_objmgr_put_vdev_by_user(vdev, WLAN_SON_ID); 2811 return ret; 2812 } 2813 chan_info.freq = freq; 2814 chan_info.chan_num = wlan_reg_freq_to_chan(pdev, freq); 2815 ret = os_if_son_deliver_ald_event(vdev, NULL, 2816 MLME_EVENT_CHAN_CHANGE, 2817 &chan_info); 2818 hdd_objmgr_put_vdev_by_user(vdev, WLAN_SON_ID); 2819 2820 return ret; 2821 } 2822 2823 int hdd_son_send_set_wifi_generic_command(struct wiphy *wiphy, 2824 struct wireless_dev *wdev, 2825 struct nlattr **tb) 2826 { 2827 return os_if_son_parse_generic_nl_cmd(wiphy, wdev, tb, 2828 OS_IF_SON_VENDOR_SET_CMD); 2829 } 2830 2831 int hdd_son_send_get_wifi_generic_command(struct wiphy *wiphy, 2832 struct wireless_dev *wdev, 2833 struct nlattr **tb) 2834 { 2835 return os_if_son_parse_generic_nl_cmd(wiphy, wdev, tb, 2836 OS_IF_SON_VENDOR_GET_CMD); 2837 } 2838