1 /* 2 * Copyright (c) 2014-2019 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 36 struct wlan_regulatory_psoc_priv_obj *reg_get_psoc_obj( 37 struct wlan_objmgr_psoc *psoc) 38 { 39 struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj; 40 41 if (!psoc) { 42 reg_alert("psoc is NULL"); 43 return NULL; 44 } 45 psoc_priv_obj = wlan_objmgr_psoc_get_comp_private_obj( 46 psoc, WLAN_UMAC_COMP_REGULATORY); 47 48 return psoc_priv_obj; 49 } 50 51 struct wlan_regulatory_pdev_priv_obj *reg_get_pdev_obj( 52 struct wlan_objmgr_pdev *pdev) 53 { 54 struct wlan_regulatory_pdev_priv_obj *pdev_reg; 55 56 if (!pdev) { 57 reg_alert("pdev is NULL"); 58 return NULL; 59 } 60 61 pdev_reg = wlan_objmgr_pdev_get_comp_private_obj( 62 pdev, WLAN_UMAC_COMP_REGULATORY); 63 64 return pdev_reg; 65 } 66 67 QDF_STATUS wlan_regulatory_psoc_obj_created_notification( 68 struct wlan_objmgr_psoc *psoc, void *arg_list) 69 { 70 struct wlan_regulatory_psoc_priv_obj *soc_reg_obj; 71 struct regulatory_channel *mas_chan_list; 72 enum channel_enum chan_enum; 73 QDF_STATUS status; 74 uint8_t i; 75 uint8_t pdev_cnt; 76 77 soc_reg_obj = qdf_mem_malloc(sizeof(*soc_reg_obj)); 78 if (!soc_reg_obj) { 79 reg_alert("Mem alloc failed for reg psoc priv obj"); 80 return QDF_STATUS_E_NOMEM; 81 } 82 83 soc_reg_obj->offload_enabled = false; 84 soc_reg_obj->psoc_ptr = psoc; 85 soc_reg_obj->dfs_enabled = true; 86 soc_reg_obj->band_capability = BAND_ALL; 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 = false; 95 soc_reg_obj->enable_11d_in_world_mode = false; 96 soc_reg_obj->def_pdev_id = -1; 97 98 for (i = 0; i < MAX_STA_VDEV_CNT; i++) 99 soc_reg_obj->vdev_ids_11d[i] = INVALID_VDEV_ID; 100 101 qdf_spinlock_create(&soc_reg_obj->cbk_list_lock); 102 103 for (pdev_cnt = 0; pdev_cnt < PSOC_MAX_PHY_REG_CAP; pdev_cnt++) { 104 mas_chan_list = 105 soc_reg_obj->mas_chan_params[pdev_cnt].mas_chan_list; 106 107 for (chan_enum = 0; chan_enum < NUM_CHANNELS; chan_enum++) { 108 mas_chan_list[chan_enum].chan_flags |= 109 REGULATORY_CHAN_DISABLED; 110 mas_chan_list[chan_enum].state = CHANNEL_STATE_DISABLE; 111 mas_chan_list[chan_enum].nol_chan = false; 112 } 113 } 114 115 status = wlan_objmgr_psoc_component_obj_attach( 116 psoc, WLAN_UMAC_COMP_REGULATORY, soc_reg_obj, 117 QDF_STATUS_SUCCESS); 118 if (QDF_IS_STATUS_ERROR(status)) { 119 qdf_spinlock_destroy(&soc_reg_obj->cbk_list_lock); 120 qdf_mem_free(soc_reg_obj); 121 reg_err("Obj attach failed"); 122 return status; 123 } 124 125 reg_debug("reg psoc obj created with status %d", status); 126 127 return status; 128 } 129 130 QDF_STATUS wlan_regulatory_psoc_obj_destroyed_notification( 131 struct wlan_objmgr_psoc *psoc, void *arg_list) 132 { 133 QDF_STATUS status; 134 struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj; 135 136 psoc_priv_obj = reg_get_psoc_obj(psoc); 137 if (!psoc_priv_obj) { 138 reg_err("reg psoc private obj is NULL"); 139 return QDF_STATUS_E_FAULT; 140 } 141 142 psoc_priv_obj->psoc_ptr = NULL; 143 qdf_spinlock_destroy(&psoc_priv_obj->cbk_list_lock); 144 145 status = wlan_objmgr_psoc_component_obj_detach( 146 psoc, WLAN_UMAC_COMP_REGULATORY, psoc_priv_obj); 147 148 if (status != QDF_STATUS_SUCCESS) 149 reg_err("psoc_priv_obj private obj detach failed"); 150 151 reg_debug("reg psoc obj detached with status %d", status); 152 153 qdf_mem_free(psoc_priv_obj); 154 155 return status; 156 } 157 158 QDF_STATUS wlan_regulatory_pdev_obj_created_notification( 159 struct wlan_objmgr_pdev *pdev, void *arg_list) 160 { 161 struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; 162 struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj; 163 struct wlan_psoc_host_hal_reg_capabilities_ext *reg_cap_ptr; 164 struct wlan_objmgr_psoc *parent_psoc; 165 uint32_t pdev_id; 166 uint32_t cnt; 167 uint32_t range_2g_low, range_2g_high; 168 uint32_t range_5g_low, range_5g_high; 169 QDF_STATUS status; 170 struct reg_rule_info *psoc_reg_rules; 171 172 pdev_priv_obj = qdf_mem_malloc(sizeof(*pdev_priv_obj)); 173 if (!pdev_priv_obj) { 174 reg_alert("Mem alloc failed for pdev priv obj"); 175 return QDF_STATUS_E_NOMEM; 176 } 177 178 parent_psoc = wlan_pdev_get_psoc(pdev); 179 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); 180 181 psoc_priv_obj = reg_get_psoc_obj(parent_psoc); 182 if (!psoc_priv_obj) { 183 reg_err("reg psoc private obj is NULL"); 184 qdf_mem_free(pdev_priv_obj); 185 return QDF_STATUS_E_FAULT; 186 } 187 188 if (psoc_priv_obj->def_pdev_id == -1) 189 psoc_priv_obj->def_pdev_id = pdev_id; 190 else 191 reg_err("reg cannot handle more than one pdev"); 192 193 pdev_priv_obj->pdev_ptr = pdev; 194 pdev_priv_obj->dfs_enabled = psoc_priv_obj->dfs_enabled; 195 pdev_priv_obj->set_fcc_channel = false; 196 pdev_priv_obj->band_capability = psoc_priv_obj->band_capability; 197 pdev_priv_obj->indoor_chan_enabled = 198 psoc_priv_obj->indoor_chan_enabled; 199 pdev_priv_obj->en_chan_144 = true; 200 201 qdf_spinlock_create(&pdev_priv_obj->reg_rules_lock); 202 203 reg_cap_ptr = psoc_priv_obj->reg_cap; 204 pdev_priv_obj->force_ssc_disable_indoor_channel = 205 psoc_priv_obj->force_ssc_disable_indoor_channel; 206 207 for (cnt = 0; cnt < PSOC_MAX_PHY_REG_CAP; cnt++) { 208 if (!reg_cap_ptr) { 209 qdf_mem_free(pdev_priv_obj); 210 reg_err("reg cap ptr is NULL"); 211 return QDF_STATUS_E_FAULT; 212 } 213 214 if (reg_cap_ptr->phy_id == pdev_id) 215 break; 216 reg_cap_ptr++; 217 } 218 219 if (cnt == PSOC_MAX_PHY_REG_CAP) { 220 qdf_mem_free(pdev_priv_obj); 221 reg_err("extended capabilities not found for pdev"); 222 return QDF_STATUS_E_FAULT; 223 } 224 225 range_2g_low = reg_cap_ptr->low_2ghz_chan; 226 range_2g_high = reg_cap_ptr->high_2ghz_chan; 227 range_5g_low = reg_cap_ptr->low_5ghz_chan; 228 range_5g_high = reg_cap_ptr->high_5ghz_chan; 229 230 pdev_priv_obj->range_2g_low = range_2g_low; 231 pdev_priv_obj->range_2g_high = range_2g_high; 232 pdev_priv_obj->range_5g_low = range_5g_low; 233 pdev_priv_obj->range_5g_high = range_5g_high; 234 pdev_priv_obj->wireless_modes = reg_cap_ptr->wireless_modes; 235 236 reg_init_pdev_mas_chan_list(pdev_priv_obj, 237 &psoc_priv_obj->mas_chan_params[pdev_id]); 238 239 reg_compute_pdev_current_chan_list(pdev_priv_obj); 240 241 psoc_reg_rules = &psoc_priv_obj->mas_chan_params[pdev_id].reg_rules; 242 reg_save_reg_rules_to_pdev(psoc_reg_rules, pdev_priv_obj); 243 244 status = wlan_objmgr_pdev_component_obj_attach( 245 pdev, WLAN_UMAC_COMP_REGULATORY, pdev_priv_obj, 246 QDF_STATUS_SUCCESS); 247 if (QDF_IS_STATUS_ERROR(status)) { 248 reg_err("Obj attach failed"); 249 qdf_mem_free(pdev_priv_obj); 250 return status; 251 } 252 if (!psoc_priv_obj->is_11d_offloaded) 253 reg_11d_host_scan_init(parent_psoc); 254 255 reg_debug("reg pdev obj created with status %d", status); 256 257 return status; 258 } 259 260 QDF_STATUS wlan_regulatory_pdev_obj_destroyed_notification( 261 struct wlan_objmgr_pdev *pdev, void *arg_list) 262 { 263 QDF_STATUS status; 264 struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; 265 struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj; 266 267 pdev_priv_obj = reg_get_pdev_obj(pdev); 268 269 if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { 270 reg_err("reg pdev private obj is NULL"); 271 return QDF_STATUS_E_FAILURE; 272 } 273 274 psoc_priv_obj = reg_get_psoc_obj(wlan_pdev_get_psoc(pdev)); 275 if (!IS_VALID_PSOC_REG_OBJ(psoc_priv_obj)) { 276 reg_err("reg psoc private obj is NULL"); 277 return QDF_STATUS_E_FAILURE; 278 } 279 280 if (!psoc_priv_obj->is_11d_offloaded) 281 reg_11d_host_scan_deinit(wlan_pdev_get_psoc(pdev)); 282 283 pdev_priv_obj->pdev_ptr = NULL; 284 285 status = wlan_objmgr_pdev_component_obj_detach( 286 pdev, WLAN_UMAC_COMP_REGULATORY, pdev_priv_obj); 287 288 if (status != QDF_STATUS_SUCCESS) 289 reg_err("reg pdev private obj detach failed"); 290 291 reg_debug("reg pdev obj deleted with status %d", status); 292 293 qdf_spin_lock_bh(&pdev_priv_obj->reg_rules_lock); 294 reg_reset_reg_rules(&pdev_priv_obj->reg_rules); 295 qdf_spin_unlock_bh(&pdev_priv_obj->reg_rules_lock); 296 297 qdf_spinlock_destroy(&pdev_priv_obj->reg_rules_lock); 298 299 qdf_mem_free(pdev_priv_obj); 300 301 return status; 302 } 303