xref: /wlan-dirver/qca-wifi-host-cmn/umac/regulatory/core/src/reg_priv_objs.c (revision 2f4b444fb7e689b83a4ab0e7b3b38f0bf4def8e0)
1 /*
2  * Copyright (c) 2014-2021 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 #ifdef CONFIG_AFC_SUPPORT
37 #include <cfg_ucfg_api.h>
38 #endif
39 
40 struct wlan_regulatory_psoc_priv_obj *reg_get_psoc_obj(
41 		struct wlan_objmgr_psoc *psoc)
42 {
43 	struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj;
44 
45 	if (!psoc) {
46 		reg_alert("psoc is NULL");
47 		return NULL;
48 	}
49 	psoc_priv_obj = wlan_objmgr_psoc_get_comp_private_obj(
50 			psoc, WLAN_UMAC_COMP_REGULATORY);
51 
52 	return psoc_priv_obj;
53 }
54 
55 struct wlan_regulatory_pdev_priv_obj *reg_get_pdev_obj(
56 		struct wlan_objmgr_pdev *pdev)
57 {
58 	struct wlan_regulatory_pdev_priv_obj *pdev_reg;
59 
60 	if (!pdev) {
61 		reg_alert("pdev is NULL");
62 		return NULL;
63 	}
64 
65 	pdev_reg = wlan_objmgr_pdev_get_comp_private_obj(
66 			pdev, WLAN_UMAC_COMP_REGULATORY);
67 
68 	return pdev_reg;
69 }
70 
71 /*
72  * reg_set_5dot9_ghz_chan_in_master_mode - Set 5.9GHz channels to operate
73  * in master mode.
74  * @soc_reg_obj - Pointer to soc_reg_obj.
75  *
76  * Return: void
77  *
78  */
79 #ifdef CONFIG_REG_CLIENT
80 static void
81 reg_set_5dot9_ghz_chan_in_master_mode(struct wlan_regulatory_psoc_priv_obj
82 				      *soc_reg_obj)
83 {
84 	soc_reg_obj->enable_5dot9_ghz_chan_in_master_mode = false;
85 }
86 #else
87 static void
88 reg_set_5dot9_ghz_chan_in_master_mode(struct wlan_regulatory_psoc_priv_obj
89 				      *soc_reg_obj)
90 {
91 	soc_reg_obj->enable_5dot9_ghz_chan_in_master_mode = true;
92 }
93 #endif
94 
95 QDF_STATUS wlan_regulatory_psoc_obj_created_notification(
96 		struct wlan_objmgr_psoc *psoc, void *arg_list)
97 {
98 	struct wlan_regulatory_psoc_priv_obj *soc_reg_obj;
99 	struct regulatory_channel *mas_chan_list;
100 	enum channel_enum chan_enum;
101 	QDF_STATUS status;
102 	uint8_t i;
103 	uint8_t phy_cnt;
104 
105 	soc_reg_obj = qdf_mem_malloc(sizeof(*soc_reg_obj));
106 	if (!soc_reg_obj)
107 		return QDF_STATUS_E_NOMEM;
108 
109 	soc_reg_obj->offload_enabled = false;
110 	soc_reg_obj->psoc_ptr = psoc;
111 	soc_reg_obj->dfs_enabled = true;
112 	soc_reg_obj->band_capability = (BIT(REG_BAND_2G) | BIT(REG_BAND_5G) |
113 					BIT(REG_BAND_6G));
114 	soc_reg_obj->enable_11d_supp = false;
115 	soc_reg_obj->indoor_chan_enabled = true;
116 	soc_reg_obj->force_ssc_disable_indoor_channel = false;
117 	soc_reg_obj->master_vdev_cnt = 0;
118 	soc_reg_obj->vdev_cnt_11d = 0;
119 	soc_reg_obj->vdev_id_for_11d_scan = INVALID_VDEV_ID;
120 	soc_reg_obj->restart_beaconing = CH_AVOID_RULE_RESTART;
121 	soc_reg_obj->enable_srd_chan_in_master_mode = 0xFF;
122 	soc_reg_obj->enable_11d_in_world_mode = false;
123 	soc_reg_obj->five_dot_nine_ghz_supported = false;
124 	reg_set_5dot9_ghz_chan_in_master_mode(soc_reg_obj);
125 	soc_reg_obj->retain_nol_across_regdmn_update = false;
126 	soc_reg_obj->is_ext_tpc_supported = false;
127 
128 	for (i = 0; i < MAX_STA_VDEV_CNT; i++)
129 		soc_reg_obj->vdev_ids_11d[i] = INVALID_VDEV_ID;
130 
131 	qdf_spinlock_create(&soc_reg_obj->cbk_list_lock);
132 
133 	for (phy_cnt = 0; phy_cnt < PSOC_MAX_PHY_REG_CAP; phy_cnt++) {
134 		mas_chan_list =
135 			soc_reg_obj->mas_chan_params[phy_cnt].mas_chan_list;
136 		soc_reg_obj->chan_list_recvd[phy_cnt] = false;
137 
138 		for (chan_enum = 0; chan_enum < NUM_CHANNELS; chan_enum++) {
139 			mas_chan_list[chan_enum].chan_flags |=
140 				REGULATORY_CHAN_DISABLED;
141 			mas_chan_list[chan_enum].state = CHANNEL_STATE_DISABLE;
142 			mas_chan_list[chan_enum].nol_chan = false;
143 		}
144 	}
145 
146 	status = wlan_objmgr_psoc_component_obj_attach(
147 			psoc, WLAN_UMAC_COMP_REGULATORY, soc_reg_obj,
148 			QDF_STATUS_SUCCESS);
149 	if (QDF_IS_STATUS_ERROR(status)) {
150 		qdf_spinlock_destroy(&soc_reg_obj->cbk_list_lock);
151 		qdf_mem_free(soc_reg_obj);
152 		reg_err("Obj attach failed");
153 		return status;
154 	}
155 
156 	reg_debug("reg psoc obj created with status %d", status);
157 
158 	return status;
159 }
160 
161 QDF_STATUS wlan_regulatory_psoc_obj_destroyed_notification(
162 	struct wlan_objmgr_psoc *psoc, void *arg_list)
163 {
164 	QDF_STATUS status;
165 	struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj;
166 
167 	psoc_priv_obj = reg_get_psoc_obj(psoc);
168 	if (!psoc_priv_obj) {
169 		reg_err_rl("NULL reg psoc priv obj");
170 		return QDF_STATUS_E_FAULT;
171 	}
172 
173 	psoc_priv_obj->psoc_ptr = NULL;
174 	qdf_spinlock_destroy(&psoc_priv_obj->cbk_list_lock);
175 
176 	status = wlan_objmgr_psoc_component_obj_detach(
177 			psoc, WLAN_UMAC_COMP_REGULATORY, psoc_priv_obj);
178 
179 	if (status != QDF_STATUS_SUCCESS)
180 		reg_err_rl("psoc_priv_obj private obj detach failed");
181 
182 	reg_debug("reg psoc obj detached");
183 
184 	qdf_mem_free(psoc_priv_obj);
185 
186 	return status;
187 }
188 
189 #ifdef DISABLE_UNII_SHARED_BANDS
190 /**
191  * reg_reset_unii_5g_bitmap() - Reset the value of unii_5g_bitmap.
192  * @pdev_priv_obj: pointer to wlan_regulatory_pdev_priv_obj.
193  *
194  * Return : void
195  */
196 static void
197 reg_reset_unii_5g_bitmap(struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj)
198 {
199 	pdev_priv_obj->unii_5g_bitmap = 0x0;
200 }
201 #else
202 static void inline
203 reg_reset_unii_5g_bitmap(struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj)
204 {
205 }
206 #endif
207 
208 #if defined(CONFIG_BAND_6GHZ)
209 #if defined(CONFIG_REG_CLIENT)
210 /**
211  * reg_init_def_client_type() - Initialize the regulatory 6G client type.
212  *
213  * @pdev_priv_obj: pointer to wlan_regulatory_pdev_priv_obj.
214  *
215  * Return : void
216  */
217 static void
218 reg_init_def_client_type(struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj)
219 {
220 	pdev_priv_obj->reg_cur_6g_client_mobility_type = REG_DEFAULT_CLIENT;
221 }
222 #else
223 static void
224 reg_init_def_client_type(struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj)
225 {
226 	pdev_priv_obj->reg_cur_6g_client_mobility_type = REG_SUBORDINATE_CLIENT;
227 }
228 #endif
229 
230 /**
231  * reg_init_6g_vars() - Initialize the regulatory 6G variables viz.
232  * AP power type, client mobility type, rnr tpe usable and unspecified ap
233  * usable.
234  * @pdev_priv_obj: pointer to wlan_regulatory_pdev_priv_obj.
235  *
236  * Return : void
237  */
238 static void
239 reg_init_6g_vars(struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj)
240 {
241 	pdev_priv_obj->reg_cur_6g_ap_pwr_type = REG_INDOOR_AP;
242 	pdev_priv_obj->reg_rnr_tpe_usable = false;
243 	pdev_priv_obj->reg_unspecified_ap_usable = false;
244 	reg_init_def_client_type(pdev_priv_obj);
245 }
246 #else
247 static void
248 reg_init_6g_vars(struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj)
249 {
250 }
251 #endif
252 
253 #ifdef CONFIG_AFC_SUPPORT
254 static void
255 reg_create_afc_cb_spinlock(struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj)
256 {
257 	qdf_spinlock_create(&pdev_priv_obj->afc_cb_lock);
258 }
259 
260 static void
261 reg_destroy_afc_cb_spinlock(struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj)
262 {
263 	qdf_spinlock_destroy(&pdev_priv_obj->afc_cb_lock);
264 }
265 
266 static void
267 reg_init_afc_vars(struct wlan_objmgr_psoc *psoc,
268 		  struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj)
269 {
270 	pdev_priv_obj->is_reg_noaction_on_afc_pwr_evt =
271 			cfg_get(psoc, CFG_OL_AFC_REG_NO_ACTION);
272 }
273 #else
274 static inline void
275 reg_create_afc_cb_spinlock(struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj)
276 {
277 }
278 
279 static inline void
280 reg_destroy_afc_cb_spinlock(struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj)
281 {
282 }
283 
284 static void
285 reg_init_afc_vars(struct wlan_objmgr_psoc *psoc,
286 		  struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj)
287 {
288 }
289 #endif
290 
291 QDF_STATUS wlan_regulatory_pdev_obj_created_notification(
292 	struct wlan_objmgr_pdev *pdev, void *arg_list)
293 {
294 	struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
295 	struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj;
296 	struct wlan_psoc_host_hal_reg_capabilities_ext *reg_cap_ptr;
297 	struct wlan_objmgr_psoc *parent_psoc;
298 	uint8_t pdev_id;
299 	uint8_t phy_id;
300 	uint32_t cnt;
301 	uint32_t range_2g_low, range_2g_high;
302 	uint32_t range_5g_low, range_5g_high;
303 	QDF_STATUS status;
304 	struct reg_rule_info *psoc_reg_rules;
305 	struct wlan_lmac_if_reg_tx_ops *tx_ops;
306 
307 	pdev_priv_obj = qdf_mem_malloc(sizeof(*pdev_priv_obj));
308 	if (!pdev_priv_obj)
309 		return QDF_STATUS_E_NOMEM;
310 
311 	parent_psoc = wlan_pdev_get_psoc(pdev);
312 	pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
313 	tx_ops = reg_get_psoc_tx_ops(parent_psoc);
314 
315 	if (tx_ops->get_phy_id_from_pdev_id)
316 		tx_ops->get_phy_id_from_pdev_id(parent_psoc, pdev_id, &phy_id);
317 	else
318 		phy_id = pdev_id;
319 
320 	psoc_priv_obj = reg_get_psoc_obj(parent_psoc);
321 	if (!psoc_priv_obj) {
322 		reg_err("reg psoc private obj is NULL");
323 		qdf_mem_free(pdev_priv_obj);
324 		return QDF_STATUS_E_FAULT;
325 	}
326 
327 	pdev_priv_obj->pdev_ptr = pdev;
328 	pdev_priv_obj->dfs_enabled = psoc_priv_obj->dfs_enabled;
329 	pdev_priv_obj->set_fcc_channel = false;
330 	pdev_priv_obj->band_capability = psoc_priv_obj->band_capability;
331 	pdev_priv_obj->indoor_chan_enabled =
332 		psoc_priv_obj->indoor_chan_enabled;
333 	pdev_priv_obj->en_chan_144 = true;
334 	reg_reset_unii_5g_bitmap(pdev_priv_obj);
335 
336 	qdf_spinlock_create(&pdev_priv_obj->reg_rules_lock);
337 	reg_create_afc_cb_spinlock(pdev_priv_obj);
338 
339 	reg_cap_ptr = psoc_priv_obj->reg_cap;
340 	pdev_priv_obj->force_ssc_disable_indoor_channel =
341 		psoc_priv_obj->force_ssc_disable_indoor_channel;
342 
343 	for (cnt = 0; cnt < PSOC_MAX_PHY_REG_CAP; cnt++) {
344 		if (!reg_cap_ptr) {
345 			qdf_mem_free(pdev_priv_obj);
346 			reg_err("reg cap ptr is NULL");
347 			return QDF_STATUS_E_FAULT;
348 		}
349 
350 		if (reg_cap_ptr->phy_id == phy_id)
351 			break;
352 		reg_cap_ptr++;
353 	}
354 
355 	if (cnt == PSOC_MAX_PHY_REG_CAP) {
356 		qdf_mem_free(pdev_priv_obj);
357 		reg_err("extended capabilities not found for pdev");
358 		return QDF_STATUS_E_FAULT;
359 	}
360 
361 	range_2g_low = reg_cap_ptr->low_2ghz_chan;
362 	range_2g_high = reg_cap_ptr->high_2ghz_chan;
363 	range_5g_low = reg_cap_ptr->low_5ghz_chan;
364 	range_5g_high = reg_cap_ptr->high_5ghz_chan;
365 
366 	pdev_priv_obj->range_2g_low = range_2g_low;
367 	pdev_priv_obj->range_2g_high = range_2g_high;
368 	pdev_priv_obj->range_5g_low = range_5g_low;
369 	pdev_priv_obj->range_5g_high = range_5g_high;
370 	pdev_priv_obj->wireless_modes = reg_cap_ptr->wireless_modes;
371 	reg_init_6g_vars(pdev_priv_obj);
372 
373 	reg_init_pdev_mas_chan_list(pdev_priv_obj,
374 				    &psoc_priv_obj->mas_chan_params[phy_id]);
375 
376 	psoc_reg_rules = &psoc_priv_obj->mas_chan_params[phy_id].reg_rules;
377 	reg_save_reg_rules_to_pdev(psoc_reg_rules, pdev_priv_obj);
378 	pdev_priv_obj->chan_list_recvd =
379 		psoc_priv_obj->chan_list_recvd[phy_id];
380 
381 	status = wlan_objmgr_pdev_component_obj_attach(
382 			pdev, WLAN_UMAC_COMP_REGULATORY, pdev_priv_obj,
383 			QDF_STATUS_SUCCESS);
384 	if (QDF_IS_STATUS_ERROR(status)) {
385 		reg_err("Obj attach failed");
386 		qdf_mem_free(pdev_priv_obj);
387 		return status;
388 	}
389 
390 	reg_compute_pdev_current_chan_list(pdev_priv_obj);
391 
392 	reg_init_afc_vars(parent_psoc, pdev_priv_obj);
393 
394 	if (!psoc_priv_obj->is_11d_offloaded)
395 		reg_11d_host_scan_init(parent_psoc);
396 
397 	reg_debug("reg pdev obj created with status %d", status);
398 
399 	return status;
400 }
401 
402 #ifdef CONFIG_AFC_SUPPORT
403 /**
404  * reg_free_chan_obj() - Free the AFC chan object and chan eirp object
405  * information
406  * @afc_chan_info: Pointer to afc_chan_info
407  *
408  * Return: void
409  */
410 static void reg_free_chan_obj(struct afc_chan_obj *afc_chan_info)
411 {
412 	if (afc_chan_info->chan_eirp_info)
413 		qdf_mem_free(afc_chan_info->chan_eirp_info);
414 }
415 
416 /**
417  * reg_free_afc_pwr_info() - Free the AFC power information object
418  * @pdev_priv_obj: Pointer to pdev_priv_obj
419  *
420  * Return: void
421  */
422 void
423 reg_free_afc_pwr_info(struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj)
424 {
425 	struct reg_fw_afc_power_event *power_info;
426 	uint8_t i;
427 
428 	power_info = pdev_priv_obj->power_info;
429 	if (!power_info)
430 		return;
431 
432 	if (power_info->afc_freq_info)
433 		qdf_mem_free(power_info->afc_freq_info);
434 
435 	if (!power_info->afc_chan_info)
436 		return;
437 
438 	for (i = 0; i < power_info->num_chan_objs; i++)
439 		reg_free_chan_obj(&power_info->afc_chan_info[i]);
440 
441 	if (power_info->afc_chan_info)
442 		qdf_mem_free(power_info->afc_chan_info);
443 
444 	qdf_mem_free(power_info);
445 }
446 #endif
447 
448 QDF_STATUS wlan_regulatory_pdev_obj_destroyed_notification(
449 		struct wlan_objmgr_pdev *pdev, void *arg_list)
450 {
451 	QDF_STATUS status;
452 	struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
453 	struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj;
454 	uint32_t pdev_id;
455 
456 	pdev_priv_obj = reg_get_pdev_obj(pdev);
457 
458 	pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
459 
460 	if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
461 		reg_err("reg pdev private obj is NULL");
462 		return QDF_STATUS_E_FAILURE;
463 	}
464 
465 	psoc_priv_obj = reg_get_psoc_obj(wlan_pdev_get_psoc(pdev));
466 	if (!IS_VALID_PSOC_REG_OBJ(psoc_priv_obj)) {
467 		reg_err("reg psoc private obj is NULL");
468 		return QDF_STATUS_E_FAILURE;
469 	}
470 
471 	if (!psoc_priv_obj->is_11d_offloaded)
472 		reg_11d_host_scan_deinit(wlan_pdev_get_psoc(pdev));
473 
474 	reg_free_afc_pwr_info(pdev_priv_obj);
475 	pdev_priv_obj->pdev_ptr = NULL;
476 
477 	status = wlan_objmgr_pdev_component_obj_detach(
478 			pdev, WLAN_UMAC_COMP_REGULATORY, pdev_priv_obj);
479 
480 	if (status != QDF_STATUS_SUCCESS)
481 		reg_err("reg pdev private obj detach failed");
482 
483 	reg_debug("reg pdev obj deleted");
484 
485 	qdf_spin_lock_bh(&pdev_priv_obj->reg_rules_lock);
486 	reg_reset_reg_rules(&pdev_priv_obj->reg_rules);
487 	qdf_spin_unlock_bh(&pdev_priv_obj->reg_rules_lock);
488 
489 	reg_destroy_afc_cb_spinlock(pdev_priv_obj);
490 	qdf_spinlock_destroy(&pdev_priv_obj->reg_rules_lock);
491 
492 	qdf_mem_free(pdev_priv_obj);
493 
494 	return status;
495 }
496