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