1 /* 2 * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved. 3 * 4 * 5 * Permission to use, copy, modify, and/or distribute this software for 6 * any purpose with or without fee is hereby granted, provided that the 7 * above copyright notice and this permission notice appear in all 8 * copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 /** 21 * DOC: target_if_reg.c 22 * This file contains regulatory target interfaces. 23 */ 24 25 #include <wmi_unified_api.h> 26 #include <reg_services_public_struct.h> 27 #include <wlan_reg_tgt_api.h> 28 #include <target_if.h> 29 #include <target_if_reg.h> 30 #include <wmi_unified_reg_api.h> 31 #include <qdf_platform.h> 32 #include <target_if_reg_11d.h> 33 #include <target_if_reg_lte.h> 34 #include <wlan_reg_ucfg_api.h> 35 36 /** 37 * get_chan_list_cc_event_id() - Get chan_list_cc event i 38 * 39 * Return: Event id 40 */ 41 static inline uint32_t get_chan_list_cc_event_id(void) 42 { 43 return wmi_reg_chan_list_cc_event_id; 44 } 45 46 /** 47 * tgt_if_regulatory_is_regdb_offloaded() - Check if regdb is offloaded 48 * @psoc: Pointer to psoc 49 * 50 * Return: true if regdb if offloaded, else false 51 */ 52 static bool tgt_if_regulatory_is_regdb_offloaded(struct wlan_objmgr_psoc *psoc) 53 { 54 struct wlan_lmac_if_reg_rx_ops *reg_rx_ops; 55 56 wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 57 58 reg_rx_ops = target_if_regulatory_get_rx_ops(psoc); 59 if (!reg_rx_ops) { 60 target_if_err("reg_rx_ops is NULL"); 61 return false; 62 } 63 64 if (!wmi_handle) 65 return false; 66 67 if (reg_rx_ops->reg_ignore_fw_reg_offload_ind && 68 reg_rx_ops->reg_ignore_fw_reg_offload_ind(psoc)) { 69 target_if_debug("User disabled regulatory offload from ini"); 70 return 0; 71 } 72 73 return wmi_service_enabled(wmi_handle, wmi_service_regulatory_db); 74 } 75 76 /** 77 * tgt_if_regulatory_is_6ghz_supported() - Check if 6ghz is supported 78 * @psoc: Pointer to psoc 79 * 80 * Return: true if regdb if offloaded, else false 81 */ 82 static bool tgt_if_regulatory_is_6ghz_supported(struct wlan_objmgr_psoc *psoc) 83 { 84 wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 85 86 if (!wmi_handle) 87 return false; 88 89 return wmi_service_enabled(wmi_handle, wmi_service_6ghz_support); 90 } 91 92 /** 93 * tgt_if_regulatory_is_5dot9_ghz_supported() - Check if 5.9ghz is supported 94 * @psoc: Pointer to psoc 95 * 96 * Return: true if regdb if offloaded, else false 97 */ 98 static bool 99 tgt_if_regulatory_is_5dot9_ghz_supported(struct wlan_objmgr_psoc *psoc) 100 { 101 wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 102 103 if (!wmi_handle) 104 return false; 105 106 return wmi_service_enabled(wmi_handle, wmi_service_5dot9_ghz_support); 107 } 108 109 /** 110 * tgt_if_regulatory_is_there_serv_ready_extn() - Check for service ready 111 * extension 112 * @psoc: Pointer to psoc object 113 * 114 * Return: true if service ready extension is present, else false. 115 */ 116 static bool tgt_if_regulatory_is_there_serv_ready_extn( 117 struct wlan_objmgr_psoc *psoc) 118 { 119 wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 120 121 if (!wmi_handle) 122 return false; 123 124 return wmi_service_enabled(wmi_handle, wmi_service_ext_msg); 125 } 126 127 /** 128 * target_if_regulatory_get_rx_ops() - Get regdb rx ops 129 * @psoc: Pointer to psoc object 130 * 131 * Return: Reg rx_ops 132 */ 133 struct wlan_lmac_if_reg_rx_ops * 134 target_if_regulatory_get_rx_ops(struct wlan_objmgr_psoc *psoc) 135 { 136 struct wlan_lmac_if_rx_ops *rx_ops; 137 138 rx_ops = wlan_psoc_get_lmac_if_rxops(psoc); 139 if (!rx_ops) { 140 target_if_err("rx_ops is NULL"); 141 return NULL; 142 } 143 144 return &rx_ops->reg_rx_ops; 145 } 146 147 QDF_STATUS target_if_reg_set_offloaded_info(struct wlan_objmgr_psoc *psoc) 148 { 149 struct wlan_lmac_if_reg_rx_ops *reg_rx_ops; 150 151 reg_rx_ops = target_if_regulatory_get_rx_ops(psoc); 152 if (!reg_rx_ops) { 153 target_if_err("reg_rx_ops is NULL"); 154 return QDF_STATUS_E_FAILURE; 155 } 156 157 if (reg_rx_ops->reg_set_regdb_offloaded) 158 reg_rx_ops->reg_set_regdb_offloaded( 159 psoc, 160 tgt_if_regulatory_is_regdb_offloaded(psoc)); 161 162 if (reg_rx_ops->reg_set_11d_offloaded) 163 reg_rx_ops->reg_set_11d_offloaded( 164 psoc, tgt_if_regulatory_is_11d_offloaded(psoc)); 165 166 return QDF_STATUS_SUCCESS; 167 } 168 169 QDF_STATUS target_if_reg_set_6ghz_info(struct wlan_objmgr_psoc *psoc) 170 { 171 struct wlan_lmac_if_reg_rx_ops *reg_rx_ops; 172 173 reg_rx_ops = target_if_regulatory_get_rx_ops(psoc); 174 if (!reg_rx_ops) { 175 target_if_err("reg_rx_ops is NULL"); 176 return QDF_STATUS_E_FAILURE; 177 } 178 179 if (reg_rx_ops->reg_set_6ghz_supported) 180 reg_rx_ops->reg_set_6ghz_supported( 181 psoc, 182 tgt_if_regulatory_is_6ghz_supported(psoc)); 183 184 return QDF_STATUS_SUCCESS; 185 } 186 187 QDF_STATUS target_if_reg_set_5dot9_ghz_info(struct wlan_objmgr_psoc *psoc) 188 { 189 struct wlan_lmac_if_reg_rx_ops *reg_rx_ops; 190 191 reg_rx_ops = target_if_regulatory_get_rx_ops(psoc); 192 if (!reg_rx_ops) { 193 target_if_err("reg_rx_ops is NULL"); 194 return QDF_STATUS_E_FAILURE; 195 } 196 197 if (reg_rx_ops->reg_set_5dot9_ghz_supported) 198 reg_rx_ops->reg_set_5dot9_ghz_supported( 199 psoc, 200 tgt_if_regulatory_is_5dot9_ghz_supported(psoc)); 201 202 return QDF_STATUS_SUCCESS; 203 } 204 205 /** 206 * tgt_reg_chan_list_update_handler() - Channel list update handler 207 * @handle: scn handle 208 * @event_buf: pointer to event buffer 209 * @len: buffer length 210 * 211 * Return: 0 on success 212 */ 213 static int tgt_reg_chan_list_update_handler(ol_scn_t handle, uint8_t *event_buf, 214 uint32_t len) 215 { 216 struct wlan_objmgr_psoc *psoc; 217 struct wlan_lmac_if_reg_rx_ops *reg_rx_ops; 218 struct cur_regulatory_info *reg_info; 219 QDF_STATUS status; 220 struct wmi_unified *wmi_handle; 221 int ret_val = 0; 222 223 TARGET_IF_ENTER(); 224 225 psoc = target_if_get_psoc_from_scn_hdl(handle); 226 if (!psoc) { 227 target_if_err("psoc ptr is NULL"); 228 return -EINVAL; 229 } 230 231 reg_rx_ops = target_if_regulatory_get_rx_ops(psoc); 232 if (!reg_rx_ops) { 233 target_if_err("reg_rx_ops is NULL"); 234 return -EINVAL; 235 } 236 237 if (!reg_rx_ops->master_list_handler) { 238 target_if_err("master_list_handler is NULL"); 239 return -EINVAL; 240 } 241 242 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 243 if (!wmi_handle) { 244 target_if_err("invalid wmi handle"); 245 return -EINVAL; 246 } 247 248 reg_info = qdf_mem_malloc(sizeof(*reg_info)); 249 if (!reg_info) 250 return -ENOMEM; 251 252 if (wmi_extract_reg_chan_list_update_event(wmi_handle, 253 event_buf, reg_info, len) 254 != QDF_STATUS_SUCCESS) { 255 target_if_err("Extraction of channel list event failed"); 256 ret_val = -EFAULT; 257 goto clean; 258 } 259 260 if (reg_info->phy_id >= PSOC_MAX_PHY_REG_CAP) { 261 target_if_err_rl("phy_id %d is out of bounds", 262 reg_info->phy_id); 263 ret_val = -EFAULT; 264 goto clean; 265 } 266 267 reg_info->psoc = psoc; 268 269 status = reg_rx_ops->master_list_handler(reg_info); 270 if (status != QDF_STATUS_SUCCESS) { 271 target_if_err("Failed to process master channel list handler"); 272 ret_val = -EFAULT; 273 } 274 275 clean: 276 qdf_mem_free(reg_info->reg_rules_2g_ptr); 277 qdf_mem_free(reg_info->reg_rules_5g_ptr); 278 qdf_mem_free(reg_info); 279 280 TARGET_IF_EXIT(); 281 282 return ret_val; 283 } 284 285 /** 286 * tgt_if_regulatory_register_master_list_handler() - Register master channel 287 * list 288 * @psoc: Pointer to psoc 289 * @arg: Pointer to argument list 290 * 291 * Return: QDF_STATUS 292 */ 293 static QDF_STATUS tgt_if_regulatory_register_master_list_handler( 294 struct wlan_objmgr_psoc *psoc, void *arg) 295 { 296 wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 297 298 if (!wmi_handle) 299 return QDF_STATUS_E_FAILURE; 300 301 return wmi_unified_register_event_handler( 302 wmi_handle, wmi_reg_chan_list_cc_event_id, 303 tgt_reg_chan_list_update_handler, WMI_RX_WORK_CTX); 304 } 305 306 /** 307 * tgt_if_regulatory_unregister_master_list_handler() - Unregister master 308 * channel list 309 * @psoc: Pointer to psoc 310 * @arg: Pointer to argument list 311 * 312 * Return: QDF_STATUS 313 */ 314 static QDF_STATUS tgt_if_regulatory_unregister_master_list_handler( 315 struct wlan_objmgr_psoc *psoc, void *arg) 316 { 317 wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 318 319 if (!wmi_handle) 320 return QDF_STATUS_E_FAILURE; 321 322 return wmi_unified_unregister_event_handler( 323 wmi_handle, wmi_reg_chan_list_cc_event_id); 324 } 325 326 /** 327 * tgt_if_regulatory_set_country_code() - Set country code 328 * @psoc: Pointer to psoc 329 * @arg: Pointer to argument list 330 * 331 * Return: QDF_STATUS 332 */ 333 static QDF_STATUS tgt_if_regulatory_set_country_code( 334 struct wlan_objmgr_psoc *psoc, void *arg) 335 { 336 wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 337 338 if (!wmi_handle) 339 return QDF_STATUS_E_FAILURE; 340 341 return wmi_unified_set_country_cmd_send(wmi_handle, arg); 342 } 343 344 /** 345 * tgt_if_regulatory_set_user_country_code() - Set user country code 346 * @psoc: Pointer to psoc 347 * @pdev_id: Pdev id 348 * @rd: Pointer to regdomain structure 349 * 350 * Return: QDF_STATUS 351 */ 352 static QDF_STATUS tgt_if_regulatory_set_user_country_code( 353 struct wlan_objmgr_psoc *psoc, uint8_t pdev_id, struct cc_regdmn_s *rd) 354 { 355 wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 356 357 if (!wmi_handle) 358 return QDF_STATUS_E_FAILURE; 359 360 if (wmi_unified_set_user_country_code_cmd_send( 361 wmi_handle, pdev_id, rd) != QDF_STATUS_SUCCESS 362 ) { 363 target_if_err("Set user country code failed"); 364 return QDF_STATUS_E_FAILURE; 365 } 366 367 return QDF_STATUS_SUCCESS; 368 } 369 370 QDF_STATUS tgt_if_regulatory_modify_freq_range(struct wlan_objmgr_psoc *psoc) 371 { 372 struct wlan_psoc_host_hal_reg_capabilities_ext *reg_cap; 373 374 reg_cap = ucfg_reg_get_hal_reg_cap(psoc); 375 if (!reg_cap) { 376 target_if_err("reg cap is NULL"); 377 return QDF_STATUS_E_FAILURE; 378 } 379 380 if (!(reg_cap->wireless_modes & WMI_HOST_REGDMN_MODE_11A)) { 381 reg_cap->low_5ghz_chan = 0; 382 reg_cap->high_5ghz_chan = 0; 383 } 384 385 if (!(reg_cap->wireless_modes & 386 (WMI_HOST_REGDMN_MODE_11B | WMI_HOST_REGDMN_MODE_PUREG))) { 387 reg_cap->low_2ghz_chan = 0; 388 reg_cap->high_2ghz_chan = 0; 389 } 390 391 target_if_debug("phy_id = %d - low_2ghz_chan = %d high_2ghz_chan = %d low_5ghz_chan = %d high_5ghz_chan = %d", 392 reg_cap->phy_id, 393 reg_cap->low_2ghz_chan, 394 reg_cap->high_2ghz_chan, 395 reg_cap->low_5ghz_chan, 396 reg_cap->high_5ghz_chan); 397 398 return QDF_STATUS_SUCCESS; 399 } 400 401 #ifdef CONFIG_REG_CLIENT 402 /** 403 * tgt_if_regulatory_send_ctl_info() - Send CTL info to firmware 404 * @psoc: Pointer to psoc 405 * @params: Pointer to reg control params 406 * 407 * Return: QDF_STATUS 408 */ 409 static QDF_STATUS 410 tgt_if_regulatory_send_ctl_info(struct wlan_objmgr_psoc *psoc, 411 struct reg_ctl_params *params) 412 { 413 wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 414 415 if (!wmi_handle) 416 return QDF_STATUS_E_FAILURE; 417 418 return wmi_unified_send_regdomain_info_to_fw_cmd(wmi_handle, 419 params->regd, 420 params->regd_2g, 421 params->regd_5g, 422 params->ctl_2g, 423 params->ctl_5g); 424 } 425 #else 426 static QDF_STATUS 427 tgt_if_regulatory_send_ctl_info(struct wlan_objmgr_psoc *psoc, 428 struct reg_ctl_params *params) 429 { 430 return QDF_STATUS_SUCCESS; 431 } 432 #endif 433 434 /** 435 * tgt_if_regulatory_get_phy_id_from_pdev_id() - Get phy_id from pdev_id 436 * @psoc: Pointer to psoc 437 * @pdev_id: Pdev id 438 * @phy_id: phy_id 439 * 440 * Return: QDF_STATUS 441 */ 442 static QDF_STATUS tgt_if_regulatory_get_phy_id_from_pdev_id( 443 struct wlan_objmgr_psoc *psoc, uint8_t pdev_id, uint8_t *phy_id) 444 { 445 struct target_psoc_info *tgt_if_handle = psoc->tgt_if_handle; 446 uint8_t ret; 447 448 if (pdev_id >= WLAN_UMAC_MAX_PDEVS) { 449 target_if_err("pdev_id is greater than WLAN_UMAC_MAX_PDEVS"); 450 return QDF_STATUS_E_FAILURE; 451 } 452 453 /* By default pdev_id and phy_id have one to one mapping */ 454 *phy_id = pdev_id; 455 456 if (!(tgt_if_handle && 457 tgt_if_handle->info.is_pdevid_to_phyid_map)) 458 return QDF_STATUS_SUCCESS; 459 460 ret = tgt_if_handle->info.pdev_id_to_phy_id_map[pdev_id]; 461 462 if (ret < PSOC_MAX_PHY_REG_CAP) { 463 *phy_id = ret; 464 } else { 465 target_if_err("phy_id is greater than PSOC_MAX_PHY_REG_CAP"); 466 return QDF_STATUS_E_FAILURE; 467 } 468 469 return QDF_STATUS_SUCCESS; 470 } 471 472 /** 473 * tgt_if_regulatory_get_pdev_id_from_phy_id() - Get pdev_id for phy_id 474 * @psoc: Pointer to psoc 475 * @phy_id: Phy id 476 * @pdev_id: Pdev id 477 * 478 * Return: QDF_STATUS 479 */ 480 static QDF_STATUS tgt_if_regulatory_get_pdev_id_from_phy_id( 481 struct wlan_objmgr_psoc *psoc, uint8_t phy_id, uint8_t *pdev_id) 482 { 483 struct target_psoc_info *tgt_if_handle = psoc->tgt_if_handle; 484 uint8_t i; 485 486 if (phy_id >= PSOC_MAX_PHY_REG_CAP) { 487 target_if_err("phy_id is greater than PSOC_MAX_PHY_REG_CAP"); 488 return QDF_STATUS_E_FAILURE; 489 } 490 491 /* By default pdev_id and phy_id have one to one mapping */ 492 *pdev_id = phy_id; 493 494 if (!(tgt_if_handle && 495 tgt_if_handle->info.is_pdevid_to_phyid_map)) 496 return QDF_STATUS_SUCCESS; 497 498 for (i = 0; i < WLAN_UMAC_MAX_PDEVS; i++) { 499 if (tgt_if_handle->info.pdev_id_to_phy_id_map[i] == phy_id) 500 break; 501 } 502 503 if (i < WLAN_UMAC_MAX_PDEVS) { 504 *pdev_id = i; 505 } else { 506 target_if_err("pdev_id is greater than WLAN_UMAC_MAX_PDEVS"); 507 return QDF_STATUS_E_FAILURE; 508 } 509 510 return QDF_STATUS_SUCCESS; 511 } 512 513 QDF_STATUS target_if_register_regulatory_tx_ops( 514 struct wlan_lmac_if_tx_ops *tx_ops) 515 { 516 struct wlan_lmac_if_reg_tx_ops *reg_ops = &tx_ops->reg_ops; 517 518 reg_ops->register_master_handler = 519 tgt_if_regulatory_register_master_list_handler; 520 521 reg_ops->unregister_master_handler = 522 tgt_if_regulatory_unregister_master_list_handler; 523 524 reg_ops->set_country_code = tgt_if_regulatory_set_country_code; 525 526 reg_ops->fill_umac_legacy_chanlist = NULL; 527 528 reg_ops->set_country_failed = NULL; 529 530 reg_ops->register_11d_new_cc_handler = 531 tgt_if_regulatory_register_11d_new_cc_handler; 532 533 reg_ops->unregister_11d_new_cc_handler = 534 tgt_if_regulatory_unregister_11d_new_cc_handler; 535 536 reg_ops->start_11d_scan = tgt_if_regulatory_start_11d_scan; 537 538 reg_ops->stop_11d_scan = tgt_if_regulatory_stop_11d_scan; 539 540 reg_ops->is_there_serv_ready_extn = 541 tgt_if_regulatory_is_there_serv_ready_extn; 542 543 reg_ops->set_user_country_code = 544 tgt_if_regulatory_set_user_country_code; 545 546 reg_ops->register_ch_avoid_event_handler = 547 tgt_if_regulatory_register_ch_avoid_event_handler; 548 549 reg_ops->unregister_ch_avoid_event_handler = 550 tgt_if_regulatory_unregister_ch_avoid_event_handler; 551 552 reg_ops->send_ctl_info = tgt_if_regulatory_send_ctl_info; 553 554 reg_ops->get_phy_id_from_pdev_id = 555 tgt_if_regulatory_get_phy_id_from_pdev_id; 556 557 reg_ops->get_pdev_id_from_phy_id = 558 tgt_if_regulatory_get_pdev_id_from_phy_id; 559 560 return QDF_STATUS_SUCCESS; 561 } 562