xref: /wlan-dirver/qca-wifi-host-cmn/target_if/regulatory/src/target_if_reg.c (revision a175314c51a4ce5cec2835cc8a8c7dc0c1810915)
1 /*
2  * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved.
3  *
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20  /**
21  * DOC: target_if_reg.c
22  * This file contains regulatory target interface
23  */
24 
25 
26 #include <wmi_unified_api.h>
27 #include <reg_services_public_struct.h>
28 #include <wlan_reg_tgt_api.h>
29 #include <target_if.h>
30 #include <target_if_reg.h>
31 #include <wmi_unified_reg_api.h>
32 #include <wlan_reg_ucfg_api.h>
33 
34 static inline uint32_t get_chan_list_cc_event_id(void)
35 {
36 	return wmi_reg_chan_list_cc_event_id;
37 }
38 
39 static bool tgt_if_regulatory_is_11d_offloaded(struct wlan_objmgr_psoc
40 					       *psoc)
41 {
42 	wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
43 
44 	return wmi_service_enabled(wmi_handle,
45 				   wmi_service_11d_offload);
46 }
47 
48 static bool tgt_if_regulatory_is_regdb_offloaded(struct wlan_objmgr_psoc
49 						 *psoc)
50 {
51 	wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
52 
53 	return wmi_service_enabled(wmi_handle,
54 				   wmi_service_regulatory_db);
55 }
56 
57 static bool tgt_if_regulatory_is_there_serv_ready_extn(struct wlan_objmgr_psoc
58 						       *psoc)
59 {
60 	wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
61 
62 	return wmi_service_enabled(wmi_handle,
63 				   wmi_service_ext_msg);
64 }
65 
66 static inline struct wlan_lmac_if_reg_rx_ops *
67 target_if_regulatory_get_rx_ops(struct wlan_objmgr_psoc *psoc)
68 {
69 	return &psoc->soc_cb.rx_ops.reg_rx_ops;
70 }
71 
72 QDF_STATUS target_if_reg_set_offloaded_info(struct wlan_objmgr_psoc *psoc)
73 {
74 	struct wlan_lmac_if_reg_rx_ops *reg_rx_ops;
75 
76 	reg_rx_ops = target_if_regulatory_get_rx_ops(psoc);
77 	if (!reg_rx_ops) {
78 		target_if_err("reg_rx_ops is NULL");
79 		return QDF_STATUS_E_FAILURE;
80 	}
81 
82 	if (reg_rx_ops->reg_set_regdb_offloaded)
83 		reg_rx_ops->reg_set_regdb_offloaded(psoc,
84 				tgt_if_regulatory_is_regdb_offloaded(psoc));
85 
86 	if (reg_rx_ops->reg_set_11d_offloaded)
87 		reg_rx_ops->reg_set_11d_offloaded(psoc,
88 				tgt_if_regulatory_is_11d_offloaded(psoc));
89 
90 	return QDF_STATUS_SUCCESS;
91 }
92 
93 static int tgt_reg_chan_list_update_handler(ol_scn_t handle,
94 					    uint8_t *event_buf,
95 					    uint32_t len)
96 {
97 	struct wlan_objmgr_psoc *psoc;
98 	struct wlan_lmac_if_reg_rx_ops *reg_rx_ops;
99 	struct cur_regulatory_info *reg_info;
100 	QDF_STATUS status;
101 
102 	TARGET_IF_ENTER();
103 
104 	psoc = target_if_get_psoc_from_scn_hdl(handle);
105 	if (!psoc) {
106 		target_if_err("psoc ptr is NULL");
107 		return -EINVAL;
108 	}
109 
110 	reg_rx_ops = target_if_regulatory_get_rx_ops(psoc);
111 	if (!reg_rx_ops->master_list_handler) {
112 		target_if_err("master_list_handler is NULL");
113 		return -EINVAL;
114 	}
115 
116 	reg_info = qdf_mem_malloc(sizeof(*reg_info));
117 	if (!reg_info) {
118 		target_if_err("memory allocation failed");
119 		return -ENOMEM;
120 	}
121 
122 	if (wmi_extract_reg_chan_list_update_event(GET_WMI_HDL_FROM_PSOC(psoc),
123 						   event_buf, reg_info, len)
124 	    != QDF_STATUS_SUCCESS) {
125 
126 		target_if_err("Extraction of channel list event failed");
127 		qdf_mem_free(reg_info->reg_rules_2g_ptr);
128 		qdf_mem_free(reg_info->reg_rules_5g_ptr);
129 		qdf_mem_free(reg_info);
130 		return -EFAULT;
131 	}
132 
133 	reg_info->psoc = psoc;
134 
135 	status = reg_rx_ops->master_list_handler(reg_info);
136 	if (status != QDF_STATUS_SUCCESS) {
137 		target_if_err("Failed to process master channel list handler");
138 		qdf_mem_free(reg_info->reg_rules_2g_ptr);
139 		qdf_mem_free(reg_info->reg_rules_5g_ptr);
140 		qdf_mem_free(reg_info);
141 		return -EFAULT;
142 	}
143 
144 	qdf_mem_free(reg_info->reg_rules_2g_ptr);
145 	qdf_mem_free(reg_info->reg_rules_5g_ptr);
146 	qdf_mem_free(reg_info);
147 
148 	target_if_debug("processed regulatory channel list");
149 
150 	return 0;
151 }
152 
153 static int tgt_reg_11d_new_cc_handler(ol_scn_t handle,
154 		uint8_t *event_buf, uint32_t len)
155 {
156 	struct wlan_objmgr_psoc *psoc;
157 	struct wlan_lmac_if_reg_rx_ops *reg_rx_ops;
158 	struct reg_11d_new_country reg_11d_new_cc;
159 	QDF_STATUS status;
160 
161 	TARGET_IF_ENTER();
162 
163 	psoc = target_if_get_psoc_from_scn_hdl(handle);
164 	if (!psoc) {
165 		target_if_err("psoc ptr is NULL");
166 		return -EINVAL;
167 	}
168 
169 	reg_rx_ops = target_if_regulatory_get_rx_ops(psoc);
170 
171 	if (!reg_rx_ops->reg_11d_new_cc_handler) {
172 		target_if_err("reg_11d_new_cc_handler is NULL");
173 		return -EINVAL;
174 	}
175 
176 	if (wmi_extract_reg_11d_new_cc_event(GET_WMI_HDL_FROM_PSOC(psoc),
177 				event_buf, &reg_11d_new_cc, len) !=
178 			QDF_STATUS_SUCCESS) {
179 
180 		target_if_err("Extraction of new country event failed");
181 		return -EFAULT;
182 	}
183 
184 	status = reg_rx_ops->reg_11d_new_cc_handler(psoc, &reg_11d_new_cc);
185 	if (status != QDF_STATUS_SUCCESS) {
186 		target_if_err("Failed to process new country code event");
187 		return -EFAULT;
188 	}
189 
190 	target_if_debug("processed 11d new country code event");
191 
192 	return 0;
193 }
194 
195 static int tgt_reg_ch_avoid_event_handler(ol_scn_t handle,
196 		uint8_t *event_buf, uint32_t len)
197 {
198 	struct wlan_objmgr_psoc *psoc;
199 	struct wlan_lmac_if_reg_rx_ops *reg_rx_ops;
200 	struct ch_avoid_ind_type ch_avoid_event;
201 	QDF_STATUS status;
202 
203 	TARGET_IF_ENTER();
204 
205 	psoc = target_if_get_psoc_from_scn_hdl(handle);
206 	if (!psoc) {
207 		target_if_err("psoc ptr is NULL");
208 		return -EINVAL;
209 	}
210 
211 	reg_rx_ops = target_if_regulatory_get_rx_ops(psoc);
212 
213 	if (!reg_rx_ops->reg_ch_avoid_event_handler) {
214 		target_if_err("reg_ch_avoid_event_handler is NULL");
215 		return -EINVAL;
216 	}
217 
218 	if (wmi_extract_reg_ch_avoid_event(GET_WMI_HDL_FROM_PSOC(psoc),
219 				event_buf, &ch_avoid_event, len) !=
220 			QDF_STATUS_SUCCESS) {
221 
222 		target_if_err("Extraction of CH avoid event failed");
223 		return -EFAULT;
224 	}
225 
226 	status = reg_rx_ops->reg_ch_avoid_event_handler(psoc, &ch_avoid_event);
227 	if (status != QDF_STATUS_SUCCESS) {
228 		target_if_err("Failed to process CH avoid event");
229 		return -EFAULT;
230 	}
231 
232 	target_if_debug("processed CH avoid event");
233 
234 	return 0;
235 }
236 
237 static QDF_STATUS tgt_if_regulatory_register_master_list_handler(
238 	struct wlan_objmgr_psoc *psoc, void *arg)
239 {
240 	wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
241 
242 	return wmi_unified_register_event_handler(wmi_handle,
243 					       wmi_reg_chan_list_cc_event_id,
244 					       tgt_reg_chan_list_update_handler,
245 					       WMI_RX_UMAC_CTX);
246 
247 }
248 
249 static QDF_STATUS tgt_if_regulatory_unregister_master_list_handler(
250 	struct wlan_objmgr_psoc *psoc, void *arg)
251 {
252 	wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
253 
254 	return wmi_unified_unregister_event_handler(wmi_handle,
255 					       wmi_reg_chan_list_cc_event_id);
256 }
257 
258 static QDF_STATUS tgt_if_regulatory_set_country_code(
259 	struct wlan_objmgr_psoc *psoc, void *arg)
260 {
261 	wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
262 
263 	return wmi_unified_set_country_cmd_send(wmi_handle, arg);
264 
265 }
266 
267 static QDF_STATUS tgt_if_regulatory_set_user_country_code(
268 	struct wlan_objmgr_psoc *psoc, uint8_t pdev_id, struct cc_regdmn_s *rd)
269 {
270 	wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
271 
272 	if (wmi_unified_set_user_country_code_cmd_send(wmi_handle, pdev_id,
273 				rd) != QDF_STATUS_SUCCESS) {
274 		target_if_err("Set user country code failed");
275 		return QDF_STATUS_E_FAILURE;
276 	}
277 
278 	return QDF_STATUS_SUCCESS;
279 }
280 
281 static QDF_STATUS tgt_if_regulatory_register_11d_new_cc_handler(
282 	struct wlan_objmgr_psoc *psoc, void *arg)
283 {
284 	wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
285 
286 	return wmi_unified_register_event(wmi_handle,
287 					  wmi_11d_new_country_event_id,
288 					  tgt_reg_11d_new_cc_handler);
289 }
290 
291 static QDF_STATUS tgt_if_regulatory_unregister_11d_new_cc_handler(
292 	struct wlan_objmgr_psoc *psoc, void *arg)
293 {
294 	wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
295 
296 	return wmi_unified_unregister_event(wmi_handle,
297 					    wmi_11d_new_country_event_id);
298 }
299 
300 static QDF_STATUS tgt_if_regulatory_register_ch_avoid_event_handler(
301 	struct wlan_objmgr_psoc *psoc, void *arg)
302 {
303 	wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
304 
305 	return wmi_unified_register_event(wmi_handle,
306 					  wmi_wlan_freq_avoid_event_id,
307 					  tgt_reg_ch_avoid_event_handler);
308 }
309 
310 static QDF_STATUS tgt_if_regulatory_unregister_ch_avoid_event_handler(
311 	struct wlan_objmgr_psoc *psoc, void *arg)
312 {
313 	wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
314 
315 	return wmi_unified_unregister_event(wmi_handle,
316 			wmi_wlan_freq_avoid_event_id);
317 }
318 static QDF_STATUS tgt_if_regulatory_start_11d_scan(
319 		struct wlan_objmgr_psoc *psoc,
320 		struct reg_start_11d_scan_req *reg_start_11d_scan_req)
321 {
322 	wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
323 
324 	return wmi_unified_send_start_11d_scan_cmd(wmi_handle,
325 						   reg_start_11d_scan_req);
326 }
327 
328 static QDF_STATUS tgt_if_regulatory_stop_11d_scan(
329 		   struct wlan_objmgr_psoc *psoc,
330 		   struct reg_stop_11d_scan_req *reg_stop_11d_scan_req)
331 {
332 	wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
333 
334 	return wmi_unified_send_stop_11d_scan_cmd(wmi_handle,
335 						  reg_stop_11d_scan_req);
336 }
337 
338 QDF_STATUS tgt_if_regulatory_modify_freq_range(struct wlan_objmgr_psoc *psoc)
339 {
340 	struct wlan_psoc_host_hal_reg_capabilities_ext *reg_cap;
341 
342 	reg_cap = ucfg_reg_get_hal_reg_cap(psoc);
343 	if (!reg_cap) {
344 		target_if_err("reg cap is NULL");
345 		return QDF_STATUS_E_FAILURE;
346 	}
347 
348 	if (!(reg_cap->wireless_modes & WMI_HOST_REGDMN_MODE_11A)) {
349 		reg_cap->low_5ghz_chan = 0;
350 		reg_cap->high_5ghz_chan = 0;
351 	}
352 
353 	if (!(reg_cap->wireless_modes &
354 	     (WMI_HOST_REGDMN_MODE_11B | WMI_HOST_REGDMN_MODE_PUREG))) {
355 		reg_cap->low_2ghz_chan = 0;
356 		reg_cap->high_2ghz_chan = 0;
357 	}
358 
359 	target_if_info(
360 			"phy_id = %d - low_2ghz_chan = %d high_2ghz_chan = %d low_5ghz_chan = %d high_5ghz_chan = %d",
361 			reg_cap->phy_id,
362 			reg_cap->low_2ghz_chan,
363 			reg_cap->high_2ghz_chan,
364 			reg_cap->low_5ghz_chan,
365 			reg_cap->high_5ghz_chan);
366 
367 	return QDF_STATUS_SUCCESS;
368 }
369 
370 QDF_STATUS target_if_register_regulatory_tx_ops(struct wlan_lmac_if_tx_ops
371 						*tx_ops)
372 {
373 	struct wlan_lmac_if_reg_tx_ops *reg_ops = &tx_ops->reg_ops;
374 
375 	reg_ops->register_master_handler =
376 		tgt_if_regulatory_register_master_list_handler;
377 
378 	reg_ops->unregister_master_handler =
379 		tgt_if_regulatory_unregister_master_list_handler;
380 
381 	reg_ops->set_country_code = tgt_if_regulatory_set_country_code;
382 
383 	reg_ops->fill_umac_legacy_chanlist = NULL;
384 
385 	reg_ops->set_country_failed = NULL;
386 
387 	reg_ops->register_11d_new_cc_handler =
388 		tgt_if_regulatory_register_11d_new_cc_handler;
389 
390 	reg_ops->unregister_11d_new_cc_handler =
391 		tgt_if_regulatory_unregister_11d_new_cc_handler;
392 
393 	reg_ops->start_11d_scan = tgt_if_regulatory_start_11d_scan;
394 
395 	reg_ops->stop_11d_scan = tgt_if_regulatory_stop_11d_scan;
396 
397 	reg_ops->is_there_serv_ready_extn =
398 		tgt_if_regulatory_is_there_serv_ready_extn;
399 
400 	reg_ops->set_user_country_code =
401 		tgt_if_regulatory_set_user_country_code;
402 
403 	reg_ops->register_ch_avoid_event_handler =
404 		tgt_if_regulatory_register_ch_avoid_event_handler;
405 
406 	reg_ops->unregister_ch_avoid_event_handler =
407 		tgt_if_regulatory_unregister_ch_avoid_event_handler;
408 
409 	return QDF_STATUS_SUCCESS;
410 }
411 
412