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