1 /* 2 * Copyright (c) 2014-2020 The Linux Foundation. All rights reserved. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for 5 * any purpose with or without fee is hereby granted, provided that the 6 * above copyright notice and this permission notice appear in all 7 * copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 16 * PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 /** 20 * DOC: reg_priv_objs.c 21 * This file defines the APIs to create regulatory private PSOC and PDEV 22 * objects. 23 */ 24 25 #include <wlan_cmn.h> 26 #include <reg_services_public_struct.h> 27 #include <wlan_objmgr_psoc_obj.h> 28 #include <wlan_objmgr_pdev_obj.h> 29 #include <qdf_lock.h> 30 #include "reg_priv_objs.h" 31 #include "reg_utils.h" 32 #include "reg_services_common.h" 33 #include "reg_build_chan_list.h" 34 #include "reg_host_11d.h" 35 #include "reg_callbacks.h" 36 37 struct wlan_regulatory_psoc_priv_obj *reg_get_psoc_obj( 38 struct wlan_objmgr_psoc *psoc) 39 { 40 struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj; 41 42 if (!psoc) { 43 reg_alert("psoc is NULL"); 44 return NULL; 45 } 46 psoc_priv_obj = wlan_objmgr_psoc_get_comp_private_obj( 47 psoc, WLAN_UMAC_COMP_REGULATORY); 48 49 return psoc_priv_obj; 50 } 51 52 struct wlan_regulatory_pdev_priv_obj *reg_get_pdev_obj( 53 struct wlan_objmgr_pdev *pdev) 54 { 55 struct wlan_regulatory_pdev_priv_obj *pdev_reg; 56 57 if (!pdev) { 58 reg_alert("pdev is NULL"); 59 return NULL; 60 } 61 62 pdev_reg = wlan_objmgr_pdev_get_comp_private_obj( 63 pdev, WLAN_UMAC_COMP_REGULATORY); 64 65 return pdev_reg; 66 } 67 68 QDF_STATUS wlan_regulatory_psoc_obj_created_notification( 69 struct wlan_objmgr_psoc *psoc, void *arg_list) 70 { 71 struct wlan_regulatory_psoc_priv_obj *soc_reg_obj; 72 struct regulatory_channel *mas_chan_list; 73 enum channel_enum chan_enum; 74 QDF_STATUS status; 75 uint8_t i; 76 uint8_t phy_cnt; 77 78 soc_reg_obj = qdf_mem_malloc(sizeof(*soc_reg_obj)); 79 if (!soc_reg_obj) 80 return QDF_STATUS_E_NOMEM; 81 82 soc_reg_obj->offload_enabled = false; 83 soc_reg_obj->psoc_ptr = psoc; 84 soc_reg_obj->dfs_enabled = true; 85 soc_reg_obj->band_capability = (BIT(REG_BAND_2G) | BIT(REG_BAND_5G) | 86 BIT(REG_BAND_6G)); 87 soc_reg_obj->enable_11d_supp = false; 88 soc_reg_obj->indoor_chan_enabled = true; 89 soc_reg_obj->force_ssc_disable_indoor_channel = false; 90 soc_reg_obj->master_vdev_cnt = 0; 91 soc_reg_obj->vdev_cnt_11d = 0; 92 soc_reg_obj->vdev_id_for_11d_scan = INVALID_VDEV_ID; 93 soc_reg_obj->restart_beaconing = CH_AVOID_RULE_RESTART; 94 soc_reg_obj->enable_srd_chan_in_master_mode = 0xFF; 95 soc_reg_obj->enable_11d_in_world_mode = false; 96 soc_reg_obj->five_dot_nine_ghz_supported = false; 97 soc_reg_obj->enable_5dot9_ghz_chan_in_master_mode = false; 98 soc_reg_obj->retain_nol_across_regdmn_update = false; 99 100 for (i = 0; i < MAX_STA_VDEV_CNT; i++) 101 soc_reg_obj->vdev_ids_11d[i] = INVALID_VDEV_ID; 102 103 qdf_spinlock_create(&soc_reg_obj->cbk_list_lock); 104 105 for (phy_cnt = 0; phy_cnt < PSOC_MAX_PHY_REG_CAP; phy_cnt++) { 106 mas_chan_list = 107 soc_reg_obj->mas_chan_params[phy_cnt].mas_chan_list; 108 soc_reg_obj->chan_list_recvd[phy_cnt] = false; 109 110 for (chan_enum = 0; chan_enum < NUM_CHANNELS; chan_enum++) { 111 mas_chan_list[chan_enum].chan_flags |= 112 REGULATORY_CHAN_DISABLED; 113 mas_chan_list[chan_enum].state = CHANNEL_STATE_DISABLE; 114 mas_chan_list[chan_enum].nol_chan = false; 115 } 116 } 117 118 status = wlan_objmgr_psoc_component_obj_attach( 119 psoc, WLAN_UMAC_COMP_REGULATORY, soc_reg_obj, 120 QDF_STATUS_SUCCESS); 121 if (QDF_IS_STATUS_ERROR(status)) { 122 qdf_spinlock_destroy(&soc_reg_obj->cbk_list_lock); 123 qdf_mem_free(soc_reg_obj); 124 reg_err("Obj attach failed"); 125 return status; 126 } 127 128 reg_debug("reg psoc obj created with status %d", status); 129 130 return status; 131 } 132 133 QDF_STATUS wlan_regulatory_psoc_obj_destroyed_notification( 134 struct wlan_objmgr_psoc *psoc, void *arg_list) 135 { 136 QDF_STATUS status; 137 struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj; 138 139 psoc_priv_obj = reg_get_psoc_obj(psoc); 140 if (!psoc_priv_obj) { 141 reg_err_rl("NULL reg psoc priv obj"); 142 return QDF_STATUS_E_FAULT; 143 } 144 145 psoc_priv_obj->psoc_ptr = NULL; 146 qdf_spinlock_destroy(&psoc_priv_obj->cbk_list_lock); 147 148 status = wlan_objmgr_psoc_component_obj_detach( 149 psoc, WLAN_UMAC_COMP_REGULATORY, psoc_priv_obj); 150 151 if (status != QDF_STATUS_SUCCESS) 152 reg_err_rl("psoc_priv_obj private obj detach failed"); 153 154 reg_debug("reg psoc obj detached"); 155 156 qdf_mem_free(psoc_priv_obj); 157 158 return status; 159 } 160 161 #ifdef DISABLE_UNII_SHARED_BANDS 162 /** 163 * reg_reset_unii_5g_bitmap() - Reset the value of unii_5g_bitmap. 164 * @pdev_priv_obj: pointer to wlan_regulatory_pdev_priv_obj. 165 * 166 * Return : void 167 */ 168 static void 169 reg_reset_unii_5g_bitmap(struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj) 170 { 171 pdev_priv_obj->unii_5g_bitmap = 0x0; 172 } 173 #else 174 static void inline 175 reg_reset_unii_5g_bitmap(struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj) 176 { 177 } 178 #endif 179 180 #if defined(CONFIG_BAND_6GHZ) 181 #if defined(CONFIG_REG_CLIENT) 182 /** 183 * reg_init_def_client_type() - Initialize the regulatory 6G client type. 184 * 185 * @pdev_priv_obj: pointer to wlan_regulatory_pdev_priv_obj. 186 * 187 * Return : void 188 */ 189 static void 190 reg_init_def_client_type(struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj) 191 { 192 pdev_priv_obj->reg_cur_6g_client_mobility_type = REG_DEFAULT_CLIENT; 193 } 194 #else 195 static void 196 reg_init_def_client_type(struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj) 197 { 198 pdev_priv_obj->reg_cur_6g_client_mobility_type = REG_SUBORDINATE_CLIENT; 199 } 200 #endif 201 202 /** 203 * reg_init_6g_vars() - Initialize the regulatory 6G variables viz. 204 * AP power type, client mobility type, rnr tpe usable and unspecified ap 205 * usable. 206 * @pdev_priv_obj: pointer to wlan_regulatory_pdev_priv_obj. 207 * 208 * Return : void 209 */ 210 static void 211 reg_init_6g_vars(struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj) 212 { 213 pdev_priv_obj->reg_cur_6g_ap_pwr_type = REG_INDOOR_AP; 214 pdev_priv_obj->reg_rnr_tpe_usable = false; 215 pdev_priv_obj->reg_unspecified_ap_usable = false; 216 reg_init_def_client_type(pdev_priv_obj); 217 } 218 #else 219 static void 220 reg_init_6g_vars(struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj) 221 { 222 } 223 #endif 224 225 QDF_STATUS wlan_regulatory_pdev_obj_created_notification( 226 struct wlan_objmgr_pdev *pdev, void *arg_list) 227 { 228 struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; 229 struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj; 230 struct wlan_psoc_host_hal_reg_capabilities_ext *reg_cap_ptr; 231 struct wlan_objmgr_psoc *parent_psoc; 232 uint8_t pdev_id; 233 uint8_t phy_id; 234 uint32_t cnt; 235 uint32_t range_2g_low, range_2g_high; 236 uint32_t range_5g_low, range_5g_high; 237 QDF_STATUS status; 238 struct reg_rule_info *psoc_reg_rules; 239 struct wlan_lmac_if_reg_tx_ops *tx_ops; 240 241 pdev_priv_obj = qdf_mem_malloc(sizeof(*pdev_priv_obj)); 242 if (!pdev_priv_obj) 243 return QDF_STATUS_E_NOMEM; 244 245 parent_psoc = wlan_pdev_get_psoc(pdev); 246 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); 247 tx_ops = reg_get_psoc_tx_ops(parent_psoc); 248 249 if (tx_ops->get_phy_id_from_pdev_id) 250 tx_ops->get_phy_id_from_pdev_id(parent_psoc, pdev_id, &phy_id); 251 else 252 phy_id = pdev_id; 253 254 psoc_priv_obj = reg_get_psoc_obj(parent_psoc); 255 if (!psoc_priv_obj) { 256 reg_err("reg psoc private obj is NULL"); 257 qdf_mem_free(pdev_priv_obj); 258 return QDF_STATUS_E_FAULT; 259 } 260 261 pdev_priv_obj->pdev_ptr = pdev; 262 pdev_priv_obj->dfs_enabled = psoc_priv_obj->dfs_enabled; 263 pdev_priv_obj->set_fcc_channel = false; 264 pdev_priv_obj->band_capability = psoc_priv_obj->band_capability; 265 pdev_priv_obj->indoor_chan_enabled = 266 psoc_priv_obj->indoor_chan_enabled; 267 pdev_priv_obj->en_chan_144 = true; 268 reg_reset_unii_5g_bitmap(pdev_priv_obj); 269 270 qdf_spinlock_create(&pdev_priv_obj->reg_rules_lock); 271 272 reg_cap_ptr = psoc_priv_obj->reg_cap; 273 pdev_priv_obj->force_ssc_disable_indoor_channel = 274 psoc_priv_obj->force_ssc_disable_indoor_channel; 275 276 for (cnt = 0; cnt < PSOC_MAX_PHY_REG_CAP; cnt++) { 277 if (!reg_cap_ptr) { 278 qdf_mem_free(pdev_priv_obj); 279 reg_err("reg cap ptr is NULL"); 280 return QDF_STATUS_E_FAULT; 281 } 282 283 if (reg_cap_ptr->phy_id == phy_id) 284 break; 285 reg_cap_ptr++; 286 } 287 288 if (cnt == PSOC_MAX_PHY_REG_CAP) { 289 qdf_mem_free(pdev_priv_obj); 290 reg_err("extended capabilities not found for pdev"); 291 return QDF_STATUS_E_FAULT; 292 } 293 294 range_2g_low = reg_cap_ptr->low_2ghz_chan; 295 range_2g_high = reg_cap_ptr->high_2ghz_chan; 296 range_5g_low = reg_cap_ptr->low_5ghz_chan; 297 range_5g_high = reg_cap_ptr->high_5ghz_chan; 298 299 pdev_priv_obj->range_2g_low = range_2g_low; 300 pdev_priv_obj->range_2g_high = range_2g_high; 301 pdev_priv_obj->range_5g_low = range_5g_low; 302 pdev_priv_obj->range_5g_high = range_5g_high; 303 pdev_priv_obj->wireless_modes = reg_cap_ptr->wireless_modes; 304 reg_init_6g_vars(pdev_priv_obj); 305 306 reg_init_pdev_mas_chan_list(pdev_priv_obj, 307 &psoc_priv_obj->mas_chan_params[phy_id]); 308 309 psoc_reg_rules = &psoc_priv_obj->mas_chan_params[phy_id].reg_rules; 310 reg_save_reg_rules_to_pdev(psoc_reg_rules, pdev_priv_obj); 311 pdev_priv_obj->chan_list_recvd = 312 psoc_priv_obj->chan_list_recvd[phy_id]; 313 314 status = wlan_objmgr_pdev_component_obj_attach( 315 pdev, WLAN_UMAC_COMP_REGULATORY, pdev_priv_obj, 316 QDF_STATUS_SUCCESS); 317 if (QDF_IS_STATUS_ERROR(status)) { 318 reg_err("Obj attach failed"); 319 qdf_mem_free(pdev_priv_obj); 320 return status; 321 } 322 323 reg_compute_pdev_current_chan_list(pdev_priv_obj); 324 325 if (!psoc_priv_obj->is_11d_offloaded) 326 reg_11d_host_scan_init(parent_psoc); 327 328 reg_debug("reg pdev obj created with status %d", status); 329 330 return status; 331 } 332 333 QDF_STATUS wlan_regulatory_pdev_obj_destroyed_notification( 334 struct wlan_objmgr_pdev *pdev, void *arg_list) 335 { 336 QDF_STATUS status; 337 struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; 338 struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj; 339 uint32_t pdev_id; 340 341 pdev_priv_obj = reg_get_pdev_obj(pdev); 342 343 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); 344 345 if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { 346 reg_err("reg pdev private obj is NULL"); 347 return QDF_STATUS_E_FAILURE; 348 } 349 350 psoc_priv_obj = reg_get_psoc_obj(wlan_pdev_get_psoc(pdev)); 351 if (!IS_VALID_PSOC_REG_OBJ(psoc_priv_obj)) { 352 reg_err("reg psoc private obj is NULL"); 353 return QDF_STATUS_E_FAILURE; 354 } 355 356 if (!psoc_priv_obj->is_11d_offloaded) 357 reg_11d_host_scan_deinit(wlan_pdev_get_psoc(pdev)); 358 359 pdev_priv_obj->pdev_ptr = NULL; 360 361 status = wlan_objmgr_pdev_component_obj_detach( 362 pdev, WLAN_UMAC_COMP_REGULATORY, pdev_priv_obj); 363 364 if (status != QDF_STATUS_SUCCESS) 365 reg_err("reg pdev private obj detach failed"); 366 367 reg_debug("reg pdev obj deleted"); 368 369 qdf_spin_lock_bh(&pdev_priv_obj->reg_rules_lock); 370 reg_reset_reg_rules(&pdev_priv_obj->reg_rules); 371 qdf_spin_unlock_bh(&pdev_priv_obj->reg_rules_lock); 372 373 qdf_spinlock_destroy(&pdev_priv_obj->reg_rules_lock); 374 375 qdf_mem_free(pdev_priv_obj); 376 377 return status; 378 } 379