1 /* 2 * Copyright (c) 2017-2018 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 interface 23 */ 24 25 26 #include <wmi_unified_api.h> 27 #include <reg_services_public_struct.h> 28 #include <wlan_reg_tgt_api.h> 29 #include <target_if.h> 30 #include <target_if_reg.h> 31 #include <wmi_unified_reg_api.h> 32 #include <wlan_reg_ucfg_api.h> 33 34 static inline uint32_t get_chan_list_cc_event_id(void) 35 { 36 return wmi_reg_chan_list_cc_event_id; 37 } 38 39 static bool tgt_if_regulatory_is_11d_offloaded(struct wlan_objmgr_psoc 40 *psoc) 41 { 42 wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 43 44 if (!wmi_handle) 45 return false; 46 47 return wmi_service_enabled(wmi_handle, 48 wmi_service_11d_offload); 49 } 50 51 static bool tgt_if_regulatory_is_regdb_offloaded(struct wlan_objmgr_psoc 52 *psoc) 53 { 54 wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 55 56 if (!wmi_handle) 57 return false; 58 59 return wmi_service_enabled(wmi_handle, 60 wmi_service_regulatory_db); 61 } 62 63 static bool tgt_if_regulatory_is_there_serv_ready_extn(struct wlan_objmgr_psoc 64 *psoc) 65 { 66 wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 67 68 if (!wmi_handle) 69 return false; 70 71 return wmi_service_enabled(wmi_handle, 72 wmi_service_ext_msg); 73 } 74 75 static inline struct wlan_lmac_if_reg_rx_ops * 76 target_if_regulatory_get_rx_ops(struct wlan_objmgr_psoc *psoc) 77 { 78 return &psoc->soc_cb.rx_ops.reg_rx_ops; 79 } 80 81 QDF_STATUS target_if_reg_set_offloaded_info(struct wlan_objmgr_psoc *psoc) 82 { 83 struct wlan_lmac_if_reg_rx_ops *reg_rx_ops; 84 85 reg_rx_ops = target_if_regulatory_get_rx_ops(psoc); 86 if (!reg_rx_ops) { 87 target_if_err("reg_rx_ops is NULL"); 88 return QDF_STATUS_E_FAILURE; 89 } 90 91 if (reg_rx_ops->reg_set_regdb_offloaded) 92 reg_rx_ops->reg_set_regdb_offloaded(psoc, 93 tgt_if_regulatory_is_regdb_offloaded(psoc)); 94 95 if (reg_rx_ops->reg_set_11d_offloaded) 96 reg_rx_ops->reg_set_11d_offloaded(psoc, 97 tgt_if_regulatory_is_11d_offloaded(psoc)); 98 99 return QDF_STATUS_SUCCESS; 100 } 101 102 static int tgt_reg_chan_list_update_handler(ol_scn_t handle, 103 uint8_t *event_buf, 104 uint32_t len) 105 { 106 struct wlan_objmgr_psoc *psoc; 107 struct wlan_lmac_if_reg_rx_ops *reg_rx_ops; 108 struct cur_regulatory_info *reg_info; 109 QDF_STATUS status; 110 struct wmi_unified *wmi_handle; 111 int ret_val = 0; 112 113 TARGET_IF_ENTER(); 114 115 psoc = target_if_get_psoc_from_scn_hdl(handle); 116 if (!psoc) { 117 target_if_err("psoc ptr is NULL"); 118 return -EINVAL; 119 } 120 121 reg_rx_ops = target_if_regulatory_get_rx_ops(psoc); 122 if (!reg_rx_ops->master_list_handler) { 123 target_if_err("master_list_handler is NULL"); 124 return -EINVAL; 125 } 126 127 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 128 if (!wmi_handle) { 129 target_if_err("invalid wmi handle"); 130 return -EINVAL; 131 } 132 133 reg_info = qdf_mem_malloc(sizeof(*reg_info)); 134 if (!reg_info) { 135 target_if_err("memory allocation failed"); 136 return -ENOMEM; 137 } 138 139 if (wmi_extract_reg_chan_list_update_event(wmi_handle, 140 event_buf, reg_info, len) 141 != QDF_STATUS_SUCCESS) { 142 target_if_err("Extraction of channel list event failed"); 143 ret_val = -EFAULT; 144 goto clean; 145 } 146 147 if (reg_info->phy_id >= PSOC_MAX_PHY_REG_CAP) { 148 target_if_err_rl("phy_id %d is out of bounds", 149 reg_info->phy_id); 150 ret_val = -EFAULT; 151 goto clean; 152 } 153 154 reg_info->psoc = psoc; 155 156 status = reg_rx_ops->master_list_handler(reg_info); 157 if (status != QDF_STATUS_SUCCESS) { 158 target_if_err("Failed to process master channel list handler"); 159 ret_val = -EFAULT; 160 } 161 162 clean: 163 qdf_mem_free(reg_info->reg_rules_2g_ptr); 164 qdf_mem_free(reg_info->reg_rules_5g_ptr); 165 qdf_mem_free(reg_info); 166 167 target_if_debug("processed reg channel list ret_val %d", ret_val); 168 169 return ret_val; 170 } 171 172 static int tgt_reg_11d_new_cc_handler(ol_scn_t handle, 173 uint8_t *event_buf, uint32_t len) 174 { 175 struct wlan_objmgr_psoc *psoc; 176 struct wlan_lmac_if_reg_rx_ops *reg_rx_ops; 177 struct reg_11d_new_country reg_11d_new_cc; 178 QDF_STATUS status; 179 struct wmi_unified *wmi_handle; 180 181 TARGET_IF_ENTER(); 182 183 psoc = target_if_get_psoc_from_scn_hdl(handle); 184 if (!psoc) { 185 target_if_err("psoc ptr is NULL"); 186 return -EINVAL; 187 } 188 189 reg_rx_ops = target_if_regulatory_get_rx_ops(psoc); 190 191 if (!reg_rx_ops->reg_11d_new_cc_handler) { 192 target_if_err("reg_11d_new_cc_handler is NULL"); 193 return -EINVAL; 194 } 195 196 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 197 if (!wmi_handle) { 198 target_if_err("Invalid WMI handle"); 199 return -EINVAL; 200 } 201 if (wmi_extract_reg_11d_new_cc_event(wmi_handle, event_buf, 202 ®_11d_new_cc, len) 203 != QDF_STATUS_SUCCESS) { 204 205 target_if_err("Extraction of new country event failed"); 206 return -EFAULT; 207 } 208 209 status = reg_rx_ops->reg_11d_new_cc_handler(psoc, ®_11d_new_cc); 210 if (status != QDF_STATUS_SUCCESS) { 211 target_if_err("Failed to process new country code event"); 212 return -EFAULT; 213 } 214 215 target_if_debug("processed 11d new country code event"); 216 217 return 0; 218 } 219 220 static int tgt_reg_ch_avoid_event_handler(ol_scn_t handle, 221 uint8_t *event_buf, uint32_t len) 222 { 223 struct wlan_objmgr_psoc *psoc; 224 struct wlan_lmac_if_reg_rx_ops *reg_rx_ops; 225 struct ch_avoid_ind_type ch_avoid_event; 226 QDF_STATUS status; 227 struct wmi_unified *wmi_handle; 228 229 TARGET_IF_ENTER(); 230 231 psoc = target_if_get_psoc_from_scn_hdl(handle); 232 if (!psoc) { 233 target_if_err("psoc ptr is NULL"); 234 return -EINVAL; 235 } 236 237 reg_rx_ops = target_if_regulatory_get_rx_ops(psoc); 238 239 if (!reg_rx_ops->reg_ch_avoid_event_handler) { 240 target_if_err("reg_ch_avoid_event_handler is NULL"); 241 return -EINVAL; 242 } 243 244 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 245 if (!wmi_handle) { 246 target_if_err("Invalid WMI handle"); 247 return -EINVAL; 248 } 249 if (wmi_extract_reg_ch_avoid_event(wmi_handle, event_buf, 250 &ch_avoid_event, len) 251 != QDF_STATUS_SUCCESS) { 252 253 target_if_err("Extraction of CH avoid event failed"); 254 return -EFAULT; 255 } 256 257 status = reg_rx_ops->reg_ch_avoid_event_handler(psoc, &ch_avoid_event); 258 if (status != QDF_STATUS_SUCCESS) { 259 target_if_err("Failed to process CH avoid event"); 260 return -EFAULT; 261 } 262 263 target_if_debug("processed CH avoid event"); 264 265 return 0; 266 } 267 268 static QDF_STATUS tgt_if_regulatory_register_master_list_handler( 269 struct wlan_objmgr_psoc *psoc, void *arg) 270 { 271 wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 272 273 if (!wmi_handle) 274 return QDF_STATUS_E_FAILURE; 275 276 return wmi_unified_register_event_handler(wmi_handle, 277 wmi_reg_chan_list_cc_event_id, 278 tgt_reg_chan_list_update_handler, 279 WMI_RX_UMAC_CTX); 280 281 } 282 283 static QDF_STATUS tgt_if_regulatory_unregister_master_list_handler( 284 struct wlan_objmgr_psoc *psoc, void *arg) 285 { 286 wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 287 288 if (!wmi_handle) 289 return QDF_STATUS_E_FAILURE; 290 291 return wmi_unified_unregister_event_handler(wmi_handle, 292 wmi_reg_chan_list_cc_event_id); 293 } 294 295 static QDF_STATUS tgt_if_regulatory_set_country_code( 296 struct wlan_objmgr_psoc *psoc, void *arg) 297 { 298 wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 299 300 if (!wmi_handle) 301 return QDF_STATUS_E_FAILURE; 302 303 return wmi_unified_set_country_cmd_send(wmi_handle, arg); 304 305 } 306 307 static QDF_STATUS tgt_if_regulatory_set_user_country_code( 308 struct wlan_objmgr_psoc *psoc, uint8_t pdev_id, struct cc_regdmn_s *rd) 309 { 310 wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 311 312 if (!wmi_handle) 313 return QDF_STATUS_E_FAILURE; 314 315 if (wmi_unified_set_user_country_code_cmd_send(wmi_handle, pdev_id, 316 rd) != QDF_STATUS_SUCCESS) { 317 target_if_err("Set user country code failed"); 318 return QDF_STATUS_E_FAILURE; 319 } 320 321 return QDF_STATUS_SUCCESS; 322 } 323 324 static QDF_STATUS tgt_if_regulatory_register_11d_new_cc_handler( 325 struct wlan_objmgr_psoc *psoc, void *arg) 326 { 327 wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 328 329 if (!wmi_handle) 330 return QDF_STATUS_E_FAILURE; 331 332 return wmi_unified_register_event(wmi_handle, 333 wmi_11d_new_country_event_id, 334 tgt_reg_11d_new_cc_handler); 335 } 336 337 static QDF_STATUS tgt_if_regulatory_unregister_11d_new_cc_handler( 338 struct wlan_objmgr_psoc *psoc, void *arg) 339 { 340 wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 341 342 if (!wmi_handle) 343 return QDF_STATUS_E_FAILURE; 344 345 return wmi_unified_unregister_event(wmi_handle, 346 wmi_11d_new_country_event_id); 347 } 348 349 static QDF_STATUS tgt_if_regulatory_register_ch_avoid_event_handler( 350 struct wlan_objmgr_psoc *psoc, void *arg) 351 { 352 wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 353 354 if (!wmi_handle) 355 return QDF_STATUS_E_FAILURE; 356 357 return wmi_unified_register_event(wmi_handle, 358 wmi_wlan_freq_avoid_event_id, 359 tgt_reg_ch_avoid_event_handler); 360 } 361 362 static QDF_STATUS tgt_if_regulatory_unregister_ch_avoid_event_handler( 363 struct wlan_objmgr_psoc *psoc, void *arg) 364 { 365 wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 366 367 if (!wmi_handle) 368 return QDF_STATUS_E_FAILURE; 369 370 return wmi_unified_unregister_event(wmi_handle, 371 wmi_wlan_freq_avoid_event_id); 372 } 373 static QDF_STATUS tgt_if_regulatory_start_11d_scan( 374 struct wlan_objmgr_psoc *psoc, 375 struct reg_start_11d_scan_req *reg_start_11d_scan_req) 376 { 377 wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 378 379 if (!wmi_handle) 380 return QDF_STATUS_E_FAILURE; 381 382 return wmi_unified_send_start_11d_scan_cmd(wmi_handle, 383 reg_start_11d_scan_req); 384 } 385 386 static QDF_STATUS tgt_if_regulatory_stop_11d_scan( 387 struct wlan_objmgr_psoc *psoc, 388 struct reg_stop_11d_scan_req *reg_stop_11d_scan_req) 389 { 390 wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 391 392 if (!wmi_handle) 393 return QDF_STATUS_E_FAILURE; 394 395 return wmi_unified_send_stop_11d_scan_cmd(wmi_handle, 396 reg_stop_11d_scan_req); 397 } 398 399 QDF_STATUS tgt_if_regulatory_modify_freq_range(struct wlan_objmgr_psoc *psoc) 400 { 401 struct wlan_psoc_host_hal_reg_capabilities_ext *reg_cap; 402 403 reg_cap = ucfg_reg_get_hal_reg_cap(psoc); 404 if (!reg_cap) { 405 target_if_err("reg cap is NULL"); 406 return QDF_STATUS_E_FAILURE; 407 } 408 409 if (!(reg_cap->wireless_modes & WMI_HOST_REGDMN_MODE_11A)) { 410 reg_cap->low_5ghz_chan = 0; 411 reg_cap->high_5ghz_chan = 0; 412 } 413 414 if (!(reg_cap->wireless_modes & 415 (WMI_HOST_REGDMN_MODE_11B | WMI_HOST_REGDMN_MODE_PUREG))) { 416 reg_cap->low_2ghz_chan = 0; 417 reg_cap->high_2ghz_chan = 0; 418 } 419 420 target_if_debug("phy_id = %d - low_2ghz_chan = %d high_2ghz_chan = %d low_5ghz_chan = %d high_5ghz_chan = %d", 421 reg_cap->phy_id, 422 reg_cap->low_2ghz_chan, 423 reg_cap->high_2ghz_chan, 424 reg_cap->low_5ghz_chan, 425 reg_cap->high_5ghz_chan); 426 427 return QDF_STATUS_SUCCESS; 428 } 429 430 QDF_STATUS target_if_register_regulatory_tx_ops(struct wlan_lmac_if_tx_ops 431 *tx_ops) 432 { 433 struct wlan_lmac_if_reg_tx_ops *reg_ops = &tx_ops->reg_ops; 434 435 reg_ops->register_master_handler = 436 tgt_if_regulatory_register_master_list_handler; 437 438 reg_ops->unregister_master_handler = 439 tgt_if_regulatory_unregister_master_list_handler; 440 441 reg_ops->set_country_code = tgt_if_regulatory_set_country_code; 442 443 reg_ops->fill_umac_legacy_chanlist = NULL; 444 445 reg_ops->set_country_failed = NULL; 446 447 reg_ops->register_11d_new_cc_handler = 448 tgt_if_regulatory_register_11d_new_cc_handler; 449 450 reg_ops->unregister_11d_new_cc_handler = 451 tgt_if_regulatory_unregister_11d_new_cc_handler; 452 453 reg_ops->start_11d_scan = tgt_if_regulatory_start_11d_scan; 454 455 reg_ops->stop_11d_scan = tgt_if_regulatory_stop_11d_scan; 456 457 reg_ops->is_there_serv_ready_extn = 458 tgt_if_regulatory_is_there_serv_ready_extn; 459 460 reg_ops->set_user_country_code = 461 tgt_if_regulatory_set_user_country_code; 462 463 reg_ops->register_ch_avoid_event_handler = 464 tgt_if_regulatory_register_ch_avoid_event_handler; 465 466 reg_ops->unregister_ch_avoid_event_handler = 467 tgt_if_regulatory_unregister_ch_avoid_event_handler; 468 469 return QDF_STATUS_SUCCESS; 470 } 471 472