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