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