xref: /wlan-dirver/qca-wifi-host-cmn/umac/regulatory/core/src/reg_priv_objs.c (revision 97f44cd39e4ff816eaa1710279d28cf6b9e65ad9)
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