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