xref: /wlan-dirver/qca-wifi-host-cmn/target_if/regulatory/src/target_if_reg.c (revision 1f55ed1a9f5050d8da228aa8dd3fff7c0242aa71)
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 	if (!wmi_handle)
45 		return false;
46 
47 	return wmi_service_enabled(wmi_handle,
48 				   wmi_service_11d_offload);
49 }
50 
51 static bool tgt_if_regulatory_is_regdb_offloaded(struct wlan_objmgr_psoc
52 						 *psoc)
53 {
54 	wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
55 
56 	if (!wmi_handle)
57 		return false;
58 
59 	return wmi_service_enabled(wmi_handle,
60 				   wmi_service_regulatory_db);
61 }
62 
63 static bool tgt_if_regulatory_is_there_serv_ready_extn(struct wlan_objmgr_psoc
64 						       *psoc)
65 {
66 	wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
67 
68 	if (!wmi_handle)
69 		return false;
70 
71 	return wmi_service_enabled(wmi_handle,
72 				   wmi_service_ext_msg);
73 }
74 
75 static inline struct wlan_lmac_if_reg_rx_ops *
76 target_if_regulatory_get_rx_ops(struct wlan_objmgr_psoc *psoc)
77 {
78 	return &psoc->soc_cb.rx_ops.reg_rx_ops;
79 }
80 
81 QDF_STATUS target_if_reg_set_offloaded_info(struct wlan_objmgr_psoc *psoc)
82 {
83 	struct wlan_lmac_if_reg_rx_ops *reg_rx_ops;
84 
85 	reg_rx_ops = target_if_regulatory_get_rx_ops(psoc);
86 	if (!reg_rx_ops) {
87 		target_if_err("reg_rx_ops is NULL");
88 		return QDF_STATUS_E_FAILURE;
89 	}
90 
91 	if (reg_rx_ops->reg_set_regdb_offloaded)
92 		reg_rx_ops->reg_set_regdb_offloaded(psoc,
93 				tgt_if_regulatory_is_regdb_offloaded(psoc));
94 
95 	if (reg_rx_ops->reg_set_11d_offloaded)
96 		reg_rx_ops->reg_set_11d_offloaded(psoc,
97 				tgt_if_regulatory_is_11d_offloaded(psoc));
98 
99 	return QDF_STATUS_SUCCESS;
100 }
101 
102 static int tgt_reg_chan_list_update_handler(ol_scn_t handle,
103 					    uint8_t *event_buf,
104 					    uint32_t len)
105 {
106 	struct wlan_objmgr_psoc *psoc;
107 	struct wlan_lmac_if_reg_rx_ops *reg_rx_ops;
108 	struct cur_regulatory_info *reg_info;
109 	QDF_STATUS status;
110 	struct wmi_unified *wmi_handle;
111 	int ret_val = 0;
112 
113 	TARGET_IF_ENTER();
114 
115 	psoc = target_if_get_psoc_from_scn_hdl(handle);
116 	if (!psoc) {
117 		target_if_err("psoc ptr is NULL");
118 		return -EINVAL;
119 	}
120 
121 	reg_rx_ops = target_if_regulatory_get_rx_ops(psoc);
122 	if (!reg_rx_ops->master_list_handler) {
123 		target_if_err("master_list_handler is NULL");
124 		return -EINVAL;
125 	}
126 
127 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
128 	if (!wmi_handle) {
129 		target_if_err("invalid wmi handle");
130 		return -EINVAL;
131 	}
132 
133 	reg_info = qdf_mem_malloc(sizeof(*reg_info));
134 	if (!reg_info) {
135 		target_if_err("memory allocation failed");
136 		return -ENOMEM;
137 	}
138 
139 	if (wmi_extract_reg_chan_list_update_event(wmi_handle,
140 						   event_buf, reg_info, len)
141 	    != QDF_STATUS_SUCCESS) {
142 		target_if_err("Extraction of channel list event failed");
143 		ret_val = -EFAULT;
144 		goto clean;
145 	}
146 
147 	if (reg_info->phy_id >= PSOC_MAX_PHY_REG_CAP) {
148 		target_if_err_rl("phy_id %d is out of bounds",
149 				 reg_info->phy_id);
150 		ret_val = -EFAULT;
151 		goto clean;
152 	}
153 
154 	reg_info->psoc = psoc;
155 
156 	status = reg_rx_ops->master_list_handler(reg_info);
157 	if (status != QDF_STATUS_SUCCESS) {
158 		target_if_err("Failed to process master channel list handler");
159 		ret_val = -EFAULT;
160 	}
161 
162 clean:
163 	qdf_mem_free(reg_info->reg_rules_2g_ptr);
164 	qdf_mem_free(reg_info->reg_rules_5g_ptr);
165 	qdf_mem_free(reg_info);
166 
167 	target_if_debug("processed reg channel list ret_val %d", ret_val);
168 
169 	return ret_val;
170 }
171 
172 static int tgt_reg_11d_new_cc_handler(ol_scn_t handle,
173 		uint8_t *event_buf, uint32_t len)
174 {
175 	struct wlan_objmgr_psoc *psoc;
176 	struct wlan_lmac_if_reg_rx_ops *reg_rx_ops;
177 	struct reg_11d_new_country reg_11d_new_cc;
178 	QDF_STATUS status;
179 	struct wmi_unified *wmi_handle;
180 
181 	TARGET_IF_ENTER();
182 
183 	psoc = target_if_get_psoc_from_scn_hdl(handle);
184 	if (!psoc) {
185 		target_if_err("psoc ptr is NULL");
186 		return -EINVAL;
187 	}
188 
189 	reg_rx_ops = target_if_regulatory_get_rx_ops(psoc);
190 
191 	if (!reg_rx_ops->reg_11d_new_cc_handler) {
192 		target_if_err("reg_11d_new_cc_handler is NULL");
193 		return -EINVAL;
194 	}
195 
196 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
197 	if (!wmi_handle) {
198 		target_if_err("Invalid WMI handle");
199 		return -EINVAL;
200 	}
201 	if (wmi_extract_reg_11d_new_cc_event(wmi_handle, event_buf,
202 					     &reg_11d_new_cc, len)
203 	    != QDF_STATUS_SUCCESS) {
204 
205 		target_if_err("Extraction of new country event failed");
206 		return -EFAULT;
207 	}
208 
209 	status = reg_rx_ops->reg_11d_new_cc_handler(psoc, &reg_11d_new_cc);
210 	if (status != QDF_STATUS_SUCCESS) {
211 		target_if_err("Failed to process new country code event");
212 		return -EFAULT;
213 	}
214 
215 	target_if_debug("processed 11d new country code event");
216 
217 	return 0;
218 }
219 
220 static int tgt_reg_ch_avoid_event_handler(ol_scn_t handle,
221 		uint8_t *event_buf, uint32_t len)
222 {
223 	struct wlan_objmgr_psoc *psoc;
224 	struct wlan_lmac_if_reg_rx_ops *reg_rx_ops;
225 	struct ch_avoid_ind_type ch_avoid_event;
226 	QDF_STATUS status;
227 	struct wmi_unified *wmi_handle;
228 
229 	TARGET_IF_ENTER();
230 
231 	psoc = target_if_get_psoc_from_scn_hdl(handle);
232 	if (!psoc) {
233 		target_if_err("psoc ptr is NULL");
234 		return -EINVAL;
235 	}
236 
237 	reg_rx_ops = target_if_regulatory_get_rx_ops(psoc);
238 
239 	if (!reg_rx_ops->reg_ch_avoid_event_handler) {
240 		target_if_err("reg_ch_avoid_event_handler is NULL");
241 		return -EINVAL;
242 	}
243 
244 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
245 	if (!wmi_handle) {
246 		target_if_err("Invalid WMI handle");
247 		return -EINVAL;
248 	}
249 	if (wmi_extract_reg_ch_avoid_event(wmi_handle, event_buf,
250 					   &ch_avoid_event, len)
251 	    != QDF_STATUS_SUCCESS) {
252 
253 		target_if_err("Extraction of CH avoid event failed");
254 		return -EFAULT;
255 	}
256 
257 	status = reg_rx_ops->reg_ch_avoid_event_handler(psoc, &ch_avoid_event);
258 	if (status != QDF_STATUS_SUCCESS) {
259 		target_if_err("Failed to process CH avoid event");
260 		return -EFAULT;
261 	}
262 
263 	target_if_debug("processed CH avoid event");
264 
265 	return 0;
266 }
267 
268 static QDF_STATUS tgt_if_regulatory_register_master_list_handler(
269 	struct wlan_objmgr_psoc *psoc, void *arg)
270 {
271 	wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
272 
273 	if (!wmi_handle)
274 		return QDF_STATUS_E_FAILURE;
275 
276 	return wmi_unified_register_event_handler(wmi_handle,
277 					       wmi_reg_chan_list_cc_event_id,
278 					       tgt_reg_chan_list_update_handler,
279 					       WMI_RX_UMAC_CTX);
280 
281 }
282 
283 static QDF_STATUS tgt_if_regulatory_unregister_master_list_handler(
284 	struct wlan_objmgr_psoc *psoc, void *arg)
285 {
286 	wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
287 
288 	if (!wmi_handle)
289 		return QDF_STATUS_E_FAILURE;
290 
291 	return wmi_unified_unregister_event_handler(wmi_handle,
292 					       wmi_reg_chan_list_cc_event_id);
293 }
294 
295 static QDF_STATUS tgt_if_regulatory_set_country_code(
296 	struct wlan_objmgr_psoc *psoc, void *arg)
297 {
298 	wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
299 
300 	if (!wmi_handle)
301 		return QDF_STATUS_E_FAILURE;
302 
303 	return wmi_unified_set_country_cmd_send(wmi_handle, arg);
304 
305 }
306 
307 static QDF_STATUS tgt_if_regulatory_set_user_country_code(
308 	struct wlan_objmgr_psoc *psoc, uint8_t pdev_id, struct cc_regdmn_s *rd)
309 {
310 	wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
311 
312 	if (!wmi_handle)
313 		return QDF_STATUS_E_FAILURE;
314 
315 	if (wmi_unified_set_user_country_code_cmd_send(wmi_handle, pdev_id,
316 				rd) != QDF_STATUS_SUCCESS) {
317 		target_if_err("Set user country code failed");
318 		return QDF_STATUS_E_FAILURE;
319 	}
320 
321 	return QDF_STATUS_SUCCESS;
322 }
323 
324 static QDF_STATUS tgt_if_regulatory_register_11d_new_cc_handler(
325 	struct wlan_objmgr_psoc *psoc, void *arg)
326 {
327 	wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
328 
329 	if (!wmi_handle)
330 		return QDF_STATUS_E_FAILURE;
331 
332 	return wmi_unified_register_event(wmi_handle,
333 					  wmi_11d_new_country_event_id,
334 					  tgt_reg_11d_new_cc_handler);
335 }
336 
337 static QDF_STATUS tgt_if_regulatory_unregister_11d_new_cc_handler(
338 	struct wlan_objmgr_psoc *psoc, void *arg)
339 {
340 	wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
341 
342 	if (!wmi_handle)
343 		return QDF_STATUS_E_FAILURE;
344 
345 	return wmi_unified_unregister_event(wmi_handle,
346 					    wmi_11d_new_country_event_id);
347 }
348 
349 static QDF_STATUS tgt_if_regulatory_register_ch_avoid_event_handler(
350 	struct wlan_objmgr_psoc *psoc, void *arg)
351 {
352 	wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
353 
354 	if (!wmi_handle)
355 		return QDF_STATUS_E_FAILURE;
356 
357 	return wmi_unified_register_event(wmi_handle,
358 					  wmi_wlan_freq_avoid_event_id,
359 					  tgt_reg_ch_avoid_event_handler);
360 }
361 
362 static QDF_STATUS tgt_if_regulatory_unregister_ch_avoid_event_handler(
363 	struct wlan_objmgr_psoc *psoc, void *arg)
364 {
365 	wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
366 
367 	if (!wmi_handle)
368 		return QDF_STATUS_E_FAILURE;
369 
370 	return wmi_unified_unregister_event(wmi_handle,
371 			wmi_wlan_freq_avoid_event_id);
372 }
373 static QDF_STATUS tgt_if_regulatory_start_11d_scan(
374 		struct wlan_objmgr_psoc *psoc,
375 		struct reg_start_11d_scan_req *reg_start_11d_scan_req)
376 {
377 	wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
378 
379 	if (!wmi_handle)
380 		return QDF_STATUS_E_FAILURE;
381 
382 	return wmi_unified_send_start_11d_scan_cmd(wmi_handle,
383 						   reg_start_11d_scan_req);
384 }
385 
386 static QDF_STATUS tgt_if_regulatory_stop_11d_scan(
387 		   struct wlan_objmgr_psoc *psoc,
388 		   struct reg_stop_11d_scan_req *reg_stop_11d_scan_req)
389 {
390 	wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
391 
392 	if (!wmi_handle)
393 		return QDF_STATUS_E_FAILURE;
394 
395 	return wmi_unified_send_stop_11d_scan_cmd(wmi_handle,
396 						  reg_stop_11d_scan_req);
397 }
398 
399 QDF_STATUS tgt_if_regulatory_modify_freq_range(struct wlan_objmgr_psoc *psoc)
400 {
401 	struct wlan_psoc_host_hal_reg_capabilities_ext *reg_cap;
402 
403 	reg_cap = ucfg_reg_get_hal_reg_cap(psoc);
404 	if (!reg_cap) {
405 		target_if_err("reg cap is NULL");
406 		return QDF_STATUS_E_FAILURE;
407 	}
408 
409 	if (!(reg_cap->wireless_modes & WMI_HOST_REGDMN_MODE_11A)) {
410 		reg_cap->low_5ghz_chan = 0;
411 		reg_cap->high_5ghz_chan = 0;
412 	}
413 
414 	if (!(reg_cap->wireless_modes &
415 	     (WMI_HOST_REGDMN_MODE_11B | WMI_HOST_REGDMN_MODE_PUREG))) {
416 		reg_cap->low_2ghz_chan = 0;
417 		reg_cap->high_2ghz_chan = 0;
418 	}
419 
420 	target_if_debug("phy_id = %d - low_2ghz_chan = %d high_2ghz_chan = %d low_5ghz_chan = %d high_5ghz_chan = %d",
421 			reg_cap->phy_id,
422 			reg_cap->low_2ghz_chan,
423 			reg_cap->high_2ghz_chan,
424 			reg_cap->low_5ghz_chan,
425 			reg_cap->high_5ghz_chan);
426 
427 	return QDF_STATUS_SUCCESS;
428 }
429 
430 QDF_STATUS target_if_register_regulatory_tx_ops(struct wlan_lmac_if_tx_ops
431 						*tx_ops)
432 {
433 	struct wlan_lmac_if_reg_tx_ops *reg_ops = &tx_ops->reg_ops;
434 
435 	reg_ops->register_master_handler =
436 		tgt_if_regulatory_register_master_list_handler;
437 
438 	reg_ops->unregister_master_handler =
439 		tgt_if_regulatory_unregister_master_list_handler;
440 
441 	reg_ops->set_country_code = tgt_if_regulatory_set_country_code;
442 
443 	reg_ops->fill_umac_legacy_chanlist = NULL;
444 
445 	reg_ops->set_country_failed = NULL;
446 
447 	reg_ops->register_11d_new_cc_handler =
448 		tgt_if_regulatory_register_11d_new_cc_handler;
449 
450 	reg_ops->unregister_11d_new_cc_handler =
451 		tgt_if_regulatory_unregister_11d_new_cc_handler;
452 
453 	reg_ops->start_11d_scan = tgt_if_regulatory_start_11d_scan;
454 
455 	reg_ops->stop_11d_scan = tgt_if_regulatory_stop_11d_scan;
456 
457 	reg_ops->is_there_serv_ready_extn =
458 		tgt_if_regulatory_is_there_serv_ready_extn;
459 
460 	reg_ops->set_user_country_code =
461 		tgt_if_regulatory_set_user_country_code;
462 
463 	reg_ops->register_ch_avoid_event_handler =
464 		tgt_if_regulatory_register_ch_avoid_event_handler;
465 
466 	reg_ops->unregister_ch_avoid_event_handler =
467 		tgt_if_regulatory_unregister_ch_avoid_event_handler;
468 
469 	return QDF_STATUS_SUCCESS;
470 }
471 
472