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