xref: /wlan-dirver/qca-wifi-host-cmn/target_if/init_deinit/src/service_ready_util.c (revision aead8c4d39dbad66dcb5598b7ffcc770562da9bd)
1 /*
2  * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for
5  * any purpose with or without fee is hereby granted, provided that the
6  * above copyright notice and this permission notice appear in all
7  * copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16  * PERFORMANCE OF THIS SOFTWARE.
17  */
18 /**
19  * DOC: service_ready_util.c
20  *
21  * Public APIs implementation source file for accessing (ext)service ready
22  * data from psoc object
23  */
24 #include "service_ready_util.h"
25 #include <wlan_reg_ucfg_api.h>
26 #include <target_type.h>
27 #include <qdf_module.h>
28 
29 QDF_STATUS init_deinit_chainmask_table_alloc(
30 		struct wlan_psoc_host_service_ext_param *ser_ext_par)
31 {
32 	int i;
33 	uint32_t alloc_size;
34 	QDF_STATUS status = QDF_STATUS_SUCCESS;
35 
36 	if (ser_ext_par->num_chainmask_tables == 0)
37 		return QDF_STATUS_E_NOSUPPORT;
38 
39 	for (i = 0; i < ser_ext_par->num_chainmask_tables; i++) {
40 		if (ser_ext_par->chainmask_table[i].num_valid_chainmasks >
41 		    (UINT_MAX / sizeof(
42 		     struct wlan_psoc_host_chainmask_capabilities))) {
43 			target_if_err("invalid valid chanmask num %d",
44 				      ser_ext_par->chainmask_table[i].
45 				      num_valid_chainmasks);
46 			status = QDF_STATUS_E_FAILURE;
47 			break;
48 		}
49 		alloc_size =
50 			(sizeof(struct wlan_psoc_host_chainmask_capabilities) *
51 			 ser_ext_par->chainmask_table[i].num_valid_chainmasks);
52 
53 		ser_ext_par->chainmask_table[i].cap_list =
54 			qdf_mem_malloc(alloc_size);
55 		if (!ser_ext_par->chainmask_table[i].cap_list) {
56 			init_deinit_chainmask_table_free(ser_ext_par);
57 			status = QDF_STATUS_E_NOMEM;
58 			break;
59 		}
60 	}
61 
62 	return status;
63 }
64 
65 qdf_export_symbol(init_deinit_chainmask_table_alloc);
66 
67 QDF_STATUS init_deinit_chainmask_table_free(
68 		struct wlan_psoc_host_service_ext_param *ser_ext_par)
69 {
70 	struct wlan_psoc_host_chainmask_table *table;
71 	int i;
72 
73 	for (i = 0; i < ser_ext_par->num_chainmask_tables; i++) {
74 		table =  &(ser_ext_par->chainmask_table[i]);
75 		if (table->cap_list) {
76 			qdf_mem_free(table->cap_list);
77 			table->cap_list = NULL;
78 		}
79 	}
80 
81 	return QDF_STATUS_SUCCESS;
82 }
83 
84 qdf_export_symbol(init_deinit_chainmask_table_free);
85 
86 int init_deinit_populate_service_bitmap(
87 		wmi_unified_t wmi_handle, uint8_t *event,
88 		uint32_t *service_bitmap)
89 {
90 	QDF_STATUS status;
91 
92 	status = wmi_save_service_bitmap(wmi_handle, event, service_bitmap);
93 	if (QDF_IS_STATUS_ERROR(status)) {
94 		target_if_err("failed to parse service bitmap");
95 		return qdf_status_to_os_return(status);
96 	}
97 
98 	return 0;
99 }
100 
101 int init_deinit_populate_fw_version_cmd(wmi_unified_t wmi_handle,
102 					uint8_t *event)
103 {
104 	QDF_STATUS status;
105 
106 	status = wmi_unified_save_fw_version_cmd(wmi_handle, event);
107 	if (QDF_IS_STATUS_ERROR(status))
108 		target_if_err("failed to save fw version");
109 
110 	return 0;
111 }
112 
113 int init_deinit_populate_target_cap(
114 		wmi_unified_t wmi_handle, uint8_t *event,
115 		struct wlan_psoc_target_capability_info *cap)
116 {
117 	QDF_STATUS status;
118 
119 	status = wmi_get_target_cap_from_service_ready(wmi_handle, event, cap);
120 	if (QDF_IS_STATUS_ERROR(status)) {
121 		target_if_err("failed to parse target cap");
122 		return qdf_status_to_os_return(status);
123 	}
124 
125 	return 0;
126 }
127 
128 int init_deinit_populate_service_ready_ext_param(
129 		wmi_unified_t handle, uint8_t *evt,
130 		struct wlan_psoc_host_service_ext_param *param)
131 {
132 	QDF_STATUS status;
133 
134 	status = wmi_extract_service_ready_ext(handle, evt, param);
135 	if (QDF_IS_STATUS_ERROR(status)) {
136 		target_if_err("failed to parse wmi service ready ext param");
137 		return qdf_status_to_os_return(status);
138 	}
139 
140 	return 0;
141 }
142 
143 int init_deinit_populate_service_ready_ext2_param(
144 		wmi_unified_t handle, uint8_t *evt,
145 		struct tgt_info *info)
146 {
147 	QDF_STATUS status;
148 
149 	status = wmi_extract_service_ready_ext2(handle, evt,
150 						&info->service_ext2_param);
151 	if (QDF_IS_STATUS_ERROR(status)) {
152 		target_if_err("failed to parse wmi service ready ext param");
153 		return qdf_status_to_os_return(status);
154 	}
155 
156 	return 0;
157 }
158 
159 int init_deinit_populate_chainmask_tables(
160 		wmi_unified_t handle, uint8_t *evt,
161 		struct wlan_psoc_host_chainmask_table *param)
162 {
163 	QDF_STATUS status;
164 
165 	status = wmi_extract_chainmask_tables(handle, evt, param);
166 	if (QDF_IS_STATUS_ERROR(status)) {
167 		target_if_err("failed to parse wmi service ready ext param");
168 		return qdf_status_to_os_return(status);
169 	}
170 
171 	return 0;
172 }
173 
174 int init_deinit_populate_mac_phy_capability(
175 	wmi_unified_t handle, uint8_t *evt,
176 	struct wlan_psoc_host_hw_mode_caps *hw_cap, struct tgt_info *info)
177 {
178 	QDF_STATUS status;
179 	uint32_t hw_mode_id;
180 	uint32_t phy_bit_map;
181 	uint8_t mac_phy_id;
182 
183 	hw_mode_id = hw_cap->hw_mode_id;
184 	phy_bit_map = hw_cap->phy_id_map;
185 	target_if_debug("hw_mode_id %d phy_bit_map 0x%x",
186 			hw_mode_id, phy_bit_map);
187 
188 	mac_phy_id = 0;
189 	while (phy_bit_map) {
190 		if (info->total_mac_phy_cnt >= PSOC_MAX_MAC_PHY_CAP) {
191 			target_if_err("total mac phy exceeds max limit %d",
192 				      info->total_mac_phy_cnt);
193 			return -EINVAL;
194 		}
195 
196 		status = wmi_extract_mac_phy_cap_service_ready_ext(handle,
197 				evt, hw_mode_id, mac_phy_id,
198 				&(info->mac_phy_cap[info->total_mac_phy_cnt]));
199 		if (QDF_IS_STATUS_ERROR(status)) {
200 			target_if_err("failed to parse mac phy capability");
201 			return qdf_status_to_os_return(status);
202 		}
203 		info->mac_phy_cap[info->total_mac_phy_cnt].hw_mode_config_type
204 					= hw_cap->hw_mode_config_type;
205 		info->total_mac_phy_cnt++;
206 		phy_bit_map &= (phy_bit_map - 1);
207 		mac_phy_id++;
208 	}
209 	target_if_debug("total_mac_phy_cnt %d", info->total_mac_phy_cnt);
210 
211 	return 0;
212 }
213 
214 static int get_hw_mode(wmi_unified_t handle, uint8_t *evt, uint8_t hw_idx,
215 		       struct wlan_psoc_host_hw_mode_caps *cap)
216 {
217 	QDF_STATUS status;
218 
219 	status = wmi_extract_hw_mode_cap_service_ready_ext(handle, evt,
220 					hw_idx, cap);
221 	if (QDF_IS_STATUS_ERROR(status)) {
222 		target_if_err("failed to parse hw mode capability");
223 		return qdf_status_to_os_return(status);
224 	}
225 
226 	return 0;
227 }
228 
229 static int get_sar_version(wmi_unified_t handle, uint8_t *evt,
230 			   struct wlan_psoc_host_service_ext_param *ext_param)
231 {
232 	QDF_STATUS status;
233 
234 	status = wmi_extract_sar_cap_service_ready_ext(handle, evt, ext_param);
235 	if (QDF_IS_STATUS_ERROR(status)) {
236 		target_if_err("failed to parse sar capability");
237 		return qdf_status_to_os_return(status);
238 	}
239 
240 	return 0;
241 }
242 
243 static bool new_hw_mode_preferred(uint32_t current_hw_mode,
244 				  uint32_t new_hw_mode)
245 {
246 	uint8_t hw_mode_id_precedence[WMI_HOST_HW_MODE_MAX + 1] = { 6, 2, 5,
247 								    4, 1, 3,
248 								    7, 0, 8};
249 
250 	if (current_hw_mode > WMI_HOST_HW_MODE_MAX ||
251 	    new_hw_mode > WMI_HOST_HW_MODE_MAX)
252 		return false;
253 
254 	/* Above precedence is defined by low to high, lower the value
255 	 * higher the precedence
256 	 */
257 	if (hw_mode_id_precedence[current_hw_mode] >
258 	    hw_mode_id_precedence[new_hw_mode])
259 		return true;
260 
261 	return false;
262 }
263 
264 /**
265  * select_preferred_mode() - Select preferred hw mode based on current mode.
266  * @tgt_hdl: target_psoc_info object
267  * @hw_mode_caps: HW mode caps of new mode id that needs to checked for
268  *                selection.
269  * @current_mode: Current mode.
270  *
271  * API to select preferred hw mode based on the current config.
272  * Based on host config for preferred mode, final mode selected as follows-
273  * 1) If preferred_mode == WMI_HOST_HW_MODE_DETECT, Then select mode from FW
274  *    supported modes such that it is a super set of all modes FW advertises.
275  *    For e.g., If FW supports DBS(2 radio) and DBS_SBS(3 radio)- Choose DBS_SBS
276  * 2) If preferred_mode == WMI_HOST_HW_MODE_MAX, Then do not select any mode
277  *    from FW advertised modes. Host needs to maintain all modes supported in FW
278  *    and can switch dynamically.
279  * 3) Else, A valid preferred_mode is set, Hence check if this is part of FW
280  *    supported modes. If it is found, then use it to bring up the device.
281  *
282  * Return: selected_mode based on the above criteria.
283  */
284 static uint32_t
285 select_preferred_hw_mode(struct target_psoc_info *tgt_hdl,
286 			 struct wlan_psoc_host_hw_mode_caps *hw_mode_caps,
287 			 uint32_t current_mode)
288 {
289 	uint32_t preferred_mode, selected_mode = current_mode;
290 	struct tgt_info *info;
291 
292 	info = &tgt_hdl->info;
293 	preferred_mode = target_psoc_get_preferred_hw_mode(tgt_hdl);
294 	if (preferred_mode == WMI_HOST_HW_MODE_DETECT) {
295 		uint32_t new_mode = hw_mode_caps->hw_mode_id;
296 
297 		/* Choose hw_mode_id based on precedence */
298 		if (new_hw_mode_preferred(selected_mode, new_mode)) {
299 			selected_mode = new_mode;
300 			qdf_mem_copy(&info->hw_mode_cap, hw_mode_caps,
301 				     sizeof(info->hw_mode_cap));
302 		}
303 	} else if ((preferred_mode != WMI_HOST_HW_MODE_MAX) &&
304 		   (preferred_mode == hw_mode_caps->hw_mode_id)) {
305 		selected_mode = preferred_mode;
306 		qdf_mem_copy(&info->hw_mode_cap, hw_mode_caps,
307 			     sizeof(info->hw_mode_cap));
308 	}
309 
310 	return selected_mode;
311 }
312 
313 #ifdef FEATURE_NO_DBS_INTRABAND_MCC_SUPPORT
314 static void init_deinit_change_def_hw_mode(struct target_psoc_info *tgt_hdl,
315 					   struct wmi_unified *wmi_handle)
316 {
317 	struct tgt_info *info = &tgt_hdl->info;
318 
319 	if ((info->hw_modes.num_modes == 1) &&
320 	    (info->hw_modes.hw_mode_ids[0] == WMI_HOST_HW_MODE_DBS) &&
321 	    !wmi_service_enabled(wmi_handle,
322 				 wmi_service_dual_band_simultaneous_support))
323 		target_psoc_set_preferred_hw_mode(tgt_hdl,
324 						  WMI_HOST_HW_MODE_DETECT);
325 }
326 #else
327 static void init_deinit_change_def_hw_mode(struct target_psoc_info *tgt_hdl,
328 					   struct wmi_unified *wmi_handle)
329 {
330 }
331 #endif
332 
333 int init_deinit_populate_hw_mode_capability(
334 		wmi_unified_t wmi_handle, uint8_t *event,
335 		struct target_psoc_info *tgt_hdl)
336 {
337 	QDF_STATUS status = QDF_STATUS_SUCCESS;
338 	uint8_t hw_idx;
339 	uint32_t num_hw_modes;
340 	struct wlan_psoc_host_hw_mode_caps hw_mode_caps[PSOC_MAX_HW_MODE];
341 	uint32_t preferred_mode, selected_mode = WMI_HOST_HW_MODE_MAX;
342 	struct tgt_info *info;
343 
344 	info = &tgt_hdl->info;
345 	num_hw_modes = info->service_ext_param.num_hw_modes;
346 	if (num_hw_modes > PSOC_MAX_HW_MODE) {
347 		target_if_err("invalid num_hw_modes %d", num_hw_modes);
348 		return -EINVAL;
349 	}
350 	target_if_debug("num_hw_modes %d", num_hw_modes);
351 
352 	qdf_mem_zero(&hw_mode_caps, sizeof(hw_mode_caps));
353 	info->hw_modes.num_modes = 0;
354 	info->hw_mode_cap.hw_mode_id = WMI_HOST_HW_MODE_MAX;
355 
356 	for (hw_idx = 0; hw_idx < num_hw_modes; hw_idx++) {
357 		status = get_hw_mode(wmi_handle, event, hw_idx,
358 						&hw_mode_caps[hw_idx]);
359 		if (status)
360 			goto return_exit;
361 
362 		if (hw_idx < WMI_HOST_HW_MODE_MAX) {
363 			info->hw_modes.hw_mode_ids[hw_idx] =
364 				hw_mode_caps[hw_idx].hw_mode_id;
365 			info->hw_modes.phy_bit_map[hw_idx] =
366 				hw_mode_caps[hw_idx].phy_id_map;
367 			info->hw_modes.num_modes++;
368 		}
369 
370 		status = init_deinit_populate_mac_phy_capability(wmi_handle,
371 				event, &hw_mode_caps[hw_idx], info);
372 		if (status)
373 			goto return_exit;
374 
375 		if (num_hw_modes == 1)
376 			init_deinit_change_def_hw_mode(tgt_hdl, wmi_handle);
377 
378 		selected_mode = select_preferred_hw_mode(tgt_hdl,
379 							 &hw_mode_caps[hw_idx],
380 							 selected_mode);
381 	}
382 
383 	preferred_mode = target_psoc_get_preferred_hw_mode(tgt_hdl);
384 	if (preferred_mode == WMI_HOST_HW_MODE_DETECT) {
385 		target_if_info("Preferred mode is not set, use mode id %d\n",
386 			       selected_mode);
387 		target_psoc_set_preferred_hw_mode(tgt_hdl, selected_mode);
388 
389 		/* Change default DBS hw mode as per selected one */
390 		info->target_caps.default_dbs_hw_mode_index = selected_mode;
391 	}
392 
393 	status = get_sar_version(wmi_handle, event, &info->service_ext_param);
394 	target_if_debug("sar version %d", info->service_ext_param.sar_version);
395 
396 return_exit:
397 	return qdf_status_to_os_return(status);
398 }
399 
400 int init_deinit_populate_dbr_ring_cap(struct wlan_objmgr_psoc *psoc,
401 				      wmi_unified_t handle, uint8_t *event,
402 				      struct tgt_info *info)
403 
404 {
405 	uint8_t cap_idx;
406 	uint32_t num_dbr_ring_caps;
407 	QDF_STATUS status = QDF_STATUS_SUCCESS;
408 
409 	num_dbr_ring_caps = info->service_ext_param.num_dbr_ring_caps;
410 	target_if_debug("Num DMA Capabilities = %d", num_dbr_ring_caps);
411 
412 	if (!num_dbr_ring_caps)
413 		return 0;
414 
415 	info->dbr_ring_cap = qdf_mem_malloc(
416 				sizeof(struct wlan_psoc_host_dbr_ring_caps) *
417 				num_dbr_ring_caps);
418 
419 	if (!info->dbr_ring_cap)
420 		return -EINVAL;
421 
422 	for (cap_idx = 0; cap_idx < num_dbr_ring_caps; cap_idx++) {
423 		status = wmi_extract_dbr_ring_cap_service_ready_ext(handle,
424 				event, cap_idx,
425 				&(info->dbr_ring_cap[cap_idx]));
426 		if (QDF_IS_STATUS_ERROR(status)) {
427 			target_if_err("Extraction of DMA cap failed");
428 			goto free_and_return;
429 		}
430 	}
431 
432 	return 0;
433 
434 free_and_return:
435 	qdf_mem_free(info->dbr_ring_cap);
436 	info->dbr_ring_cap = NULL;
437 
438 	return qdf_status_to_os_return(status);
439 }
440 
441 int init_deinit_populate_dbr_ring_cap_ext2(struct wlan_objmgr_psoc *psoc,
442 					   wmi_unified_t handle, uint8_t *event,
443 					   struct tgt_info *info)
444 
445 {
446 	uint8_t cap_idx;
447 	uint32_t num_dbr_ring_caps;
448 	QDF_STATUS status = QDF_STATUS_SUCCESS;
449 	struct wlan_psoc_host_dbr_ring_caps *param;
450 
451 	/*
452 	 * If FW had already sent this info as part of EXT event,
453 	 * we need to discard the same and use the info from EXT2.
454 	 */
455 	if (info->service_ext_param.num_dbr_ring_caps) {
456 		target_if_debug("dbr_ring_caps already populated");
457 		info->service_ext_param.num_dbr_ring_caps = 0;
458 		qdf_mem_free(info->dbr_ring_cap);
459 		info->dbr_ring_cap = NULL;
460 	}
461 
462 	num_dbr_ring_caps = info->service_ext2_param.num_dbr_ring_caps;
463 	target_if_debug("Num DMA Capabilities = %d", num_dbr_ring_caps);
464 
465 	if (!num_dbr_ring_caps)
466 		return 0;
467 
468 	info->dbr_ring_cap = qdf_mem_malloc(
469 				sizeof(struct wlan_psoc_host_dbr_ring_caps) *
470 				num_dbr_ring_caps);
471 
472 	if (!info->dbr_ring_cap)
473 		return -EINVAL;
474 
475 	for (cap_idx = 0; cap_idx < num_dbr_ring_caps; cap_idx++) {
476 		param = &info->dbr_ring_cap[cap_idx];
477 		status = wmi_extract_dbr_ring_cap_service_ready_ext2(handle,
478 								     event,
479 								     cap_idx,
480 								     param);
481 		if (QDF_IS_STATUS_ERROR(status)) {
482 			target_if_err("Extraction of DMA cap failed");
483 			goto free_and_return;
484 		}
485 	}
486 
487 	return 0;
488 
489 free_and_return:
490 	qdf_mem_free(info->dbr_ring_cap);
491 	info->dbr_ring_cap = NULL;
492 
493 	return qdf_status_to_os_return(status);
494 }
495 int init_deinit_populate_spectral_bin_scale_params(
496 			struct wlan_objmgr_psoc *psoc, wmi_unified_t handle,
497 			uint8_t *event, struct tgt_info *info)
498 
499 {
500 	uint8_t param_idx;
501 	uint32_t num_bin_scaling_params;
502 	QDF_STATUS status = QDF_STATUS_SUCCESS;
503 
504 	num_bin_scaling_params = info->service_ext_param.num_bin_scaling_params;
505 
506 	if (!num_bin_scaling_params)
507 		return 0;
508 
509 	info->scaling_params = qdf_mem_malloc(
510 		sizeof(struct wlan_psoc_host_spectral_scaling_params) *
511 		num_bin_scaling_params);
512 
513 	if (!info->scaling_params) {
514 		target_if_err("Mem alloc for bin scaling params failed");
515 		return -EINVAL;
516 	}
517 
518 	for (param_idx = 0; param_idx < num_bin_scaling_params; param_idx++) {
519 		status = wmi_extract_spectral_scaling_params_service_ready_ext(
520 				handle,
521 				event, param_idx,
522 				&info->scaling_params[param_idx]);
523 		if (QDF_IS_STATUS_ERROR(status)) {
524 			target_if_err("Extraction of scaling params failed");
525 			goto free_and_return;
526 		}
527 	}
528 
529 	return 0;
530 
531 free_and_return:
532 	qdf_mem_free(info->scaling_params);
533 	info->scaling_params = NULL;
534 
535 	return qdf_status_to_os_return(status);
536 }
537 
538 #ifdef WLAN_SUPPORT_TWT
539 int init_deinit_populate_twt_cap_ext2(struct wlan_objmgr_psoc *psoc,
540 				      wmi_unified_t handle, uint8_t *event,
541 				      struct tgt_info *info)
542 {
543 	struct wmi_twt_cap_bitmap_params param;
544 	struct target_psoc_info *psoc_info;
545 	QDF_STATUS status = QDF_STATUS_SUCCESS;
546 
547 	status = wmi_extract_twt_cap_service_ready_ext2(handle, event,
548 							&param);
549 	if (QDF_IS_STATUS_ERROR(status)) {
550 		target_if_err("Extraction of twt capability failed");
551 		goto exit;
552 	}
553 
554 	psoc_info = wlan_psoc_get_tgt_if_handle(psoc);
555 
556 	target_psoc_set_twt_ack_cap(psoc_info, param.twt_ack_support_cap);
557 
558 exit:
559 	return qdf_status_to_os_return(status);
560 }
561 #endif
562 
563 QDF_STATUS init_deinit_dbr_ring_cap_free(
564 		struct target_psoc_info *tgt_psoc_info)
565 {
566 	QDF_STATUS status = QDF_STATUS_SUCCESS;
567 
568 	if (tgt_psoc_info->info.dbr_ring_cap) {
569 		qdf_mem_free(tgt_psoc_info->info.dbr_ring_cap);
570 		tgt_psoc_info->info.dbr_ring_cap = NULL;
571 	}
572 
573 	return status;
574 }
575 qdf_export_symbol(init_deinit_dbr_ring_cap_free);
576 
577 QDF_STATUS init_deinit_spectral_scaling_params_free(
578 		struct target_psoc_info *tgt_psoc_info)
579 {
580 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
581 
582 	if (tgt_psoc_info->info.scaling_params) {
583 		qdf_mem_free(tgt_psoc_info->info.scaling_params);
584 		tgt_psoc_info->info.scaling_params = NULL;
585 		status = QDF_STATUS_SUCCESS;
586 	}
587 
588 	return status;
589 }
590 
591 qdf_export_symbol(init_deinit_spectral_scaling_params_free);
592 
593 #ifdef DBS_SBS_BAND_LIMITATION_WAR
594 #define phy0               0
595 #define phy2               2
596 #define NUM_RF_MODES       2 /* (DBS + DBS_SBS) */
597 /**
598  * init_deinit_update_phy_reg_cap() - Update the low/high frequency for phy0.
599  * @psoc: PSOC common object
600  * @info: FW or lower layer related info
601  * @wlan_psoc_host_hal_reg_capabilities_ext: Reg caps per PHY
602  *
603  * For the DBS_SBS capable board, update the low or high frequency
604  * for phy0 by leveraging the frequency populated for phy2
605  * depending on whether it is mapped to upper or lower 5G band by
606  * FW/HAL-PHY.
607  */
608 static void init_deinit_update_phy_reg_cap(struct wlan_objmgr_psoc *psoc,
609 					struct tgt_info *info,
610 					struct wlan_psoc_host_hal_reg_capabilities_ext *reg_cap)
611 {
612 	struct target_psoc_info *tgt_hdl;
613 	enum wmi_host_hw_mode_config_type mode;
614 	uint32_t num_hw_modes;
615 	uint8_t idx;
616 
617 	tgt_hdl = (struct target_psoc_info *)wlan_psoc_get_tgt_if_handle(
618 						psoc);
619 	if (!tgt_hdl) {
620 		target_if_err("target_psoc_info is null in service ready ev");
621 		return;
622 	}
623 
624 	mode = target_psoc_get_preferred_hw_mode(tgt_hdl);
625 
626 	num_hw_modes = info->hw_modes.num_modes;
627 
628 	if ((mode != WMI_HOST_HW_MODE_DBS) || (num_hw_modes < NUM_RF_MODES))
629 		return;
630 
631 	for (idx = 0; idx < num_hw_modes; idx++)
632 		if (info->hw_modes.hw_mode_ids[idx] ==
633 			WMI_HOST_HW_MODE_DBS_SBS) {
634 			if (reg_cap[phy0].low_5ghz_chan >
635 					reg_cap[phy2].low_5ghz_chan)
636 				reg_cap[phy0].low_5ghz_chan =
637 				    reg_cap[phy2].low_5ghz_chan;
638 			else if (reg_cap[phy0].high_5ghz_chan <
639 					reg_cap[phy2].high_5ghz_chan)
640 				reg_cap[phy0].high_5ghz_chan =
641 				    reg_cap[phy2].high_5ghz_chan;
642 			break;
643 		}
644 }
645 #else
646 static void init_deinit_update_phy_reg_cap(struct wlan_objmgr_psoc *psoc,
647 					struct tgt_info *info,
648 					struct wlan_psoc_host_hal_reg_capabilities_ext *reg_cap)
649 {
650 }
651 #endif
652 
653 /**
654  * init_deinit_fill_host_reg_cap() - Fill the host regulatory cap
655  * with target hal reg capabilities.
656  * @cap: Pointer to wlan_psoc_hal_reg_capability where FW capabilities
657  * are extracted.
658  * @reg_cap: Pointer to wlan_psoc_host_hal_reg_capabilities_ext, host reg
659  * capabilities to be filled.
660  *
661  * Return - None
662  */
663 static void
664 init_deinit_fill_host_reg_cap(struct wlan_psoc_hal_reg_capability *cap,
665 			      struct wlan_psoc_host_hal_reg_capabilities_ext
666 			      *reg_cap)
667 {
668 	reg_cap->phy_id = 0;
669 	reg_cap->eeprom_reg_domain = cap->eeprom_rd;
670 	reg_cap->eeprom_reg_domain_ext = cap->eeprom_rd_ext;
671 	reg_cap->regcap1 = cap->regcap1;
672 	reg_cap->regcap2 = cap->regcap2;
673 	reg_cap->wireless_modes = (uint64_t)cap->wireless_modes;
674 	reg_cap->low_2ghz_chan = cap->low_2ghz_chan;
675 	reg_cap->high_2ghz_chan = cap->high_2ghz_chan;
676 	reg_cap->low_5ghz_chan = cap->low_5ghz_chan;
677 	reg_cap->high_5ghz_chan = cap->high_5ghz_chan;
678 }
679 
680 int init_deinit_populate_phy_reg_cap(struct wlan_objmgr_psoc *psoc,
681 				     wmi_unified_t handle, uint8_t *event,
682 				     struct tgt_info *info,
683 				     bool service_ready)
684 {
685 	uint8_t reg_idx;
686 	uint32_t num_phy_reg_cap;
687 	QDF_STATUS status = QDF_STATUS_SUCCESS;
688 	struct wlan_psoc_hal_reg_capability cap;
689 	struct wlan_psoc_host_hal_reg_capabilities_ext
690 				reg_cap[PSOC_MAX_PHY_REG_CAP] = {{0} };
691 
692 	if (service_ready) {
693 		status = wmi_extract_hal_reg_cap(handle, event, &cap);
694 		if (QDF_IS_STATUS_ERROR(status)) {
695 			target_if_err("failed to parse hal reg cap");
696 			return qdf_status_to_os_return(status);
697 		}
698 		info->service_ext_param.num_phy = 1;
699 		num_phy_reg_cap = 1;
700 		init_deinit_fill_host_reg_cap(&cap, &reg_cap[0]);
701 		target_if_debug("FW wireless modes 0x%llx",
702 				reg_cap[0].wireless_modes);
703 	} else {
704 		num_phy_reg_cap = info->service_ext_param.num_phy;
705 		if (num_phy_reg_cap > PSOC_MAX_PHY_REG_CAP) {
706 			target_if_err("Invalid num_phy_reg_cap %d",
707 				      num_phy_reg_cap);
708 			return -EINVAL;
709 		}
710 		target_if_debug("num_phy_reg_cap %d", num_phy_reg_cap);
711 
712 		for (reg_idx = 0; reg_idx < num_phy_reg_cap; reg_idx++) {
713 			status = wmi_extract_reg_cap_service_ready_ext(handle,
714 					event, reg_idx, &(reg_cap[reg_idx]));
715 			if (QDF_IS_STATUS_ERROR(status)) {
716 				target_if_err("failed to parse reg cap");
717 				return qdf_status_to_os_return(status);
718 			}
719 		}
720 	}
721 
722 	init_deinit_update_phy_reg_cap(psoc, info, reg_cap);
723 	status = ucfg_reg_set_hal_reg_cap(psoc, reg_cap, num_phy_reg_cap);
724 
725 	return qdf_status_to_os_return(status);
726 }
727 
728 int init_deinit_populate_mac_phy_cap_ext2(wmi_unified_t wmi_handle,
729 					  uint8_t *event,
730 					  struct tgt_info *info)
731 {
732 	uint32_t num_hw_modes;
733 	uint8_t hw_idx;
734 	uint32_t hw_mode_id;
735 	uint32_t phy_bit_map;
736 	uint8_t phy_id;
737 	uint8_t mac_phy_count = 0;
738 	QDF_STATUS status = QDF_STATUS_SUCCESS;
739 	struct wlan_psoc_host_mac_phy_caps *mac_phy_cap;
740 	struct wlan_psoc_host_mac_phy_caps_ext2 *mac_phy_caps_ext2;
741 
742 	if (!event)
743 		return -EINVAL;
744 
745 	num_hw_modes = info->hw_modes.num_modes;
746 
747 	for (hw_idx = 0; hw_idx < num_hw_modes; hw_idx++) {
748 		hw_mode_id = info->hw_modes.hw_mode_ids[hw_idx];
749 		phy_bit_map = info->hw_modes.phy_bit_map[hw_idx];
750 
751 		phy_id = info->mac_phy_cap[mac_phy_count].phy_id;
752 		while (phy_bit_map) {
753 			if (mac_phy_count >= info->total_mac_phy_cnt) {
754 				target_if_err("total MAC PHY count exceeds max limit %d, mac_phy_count = %d",
755 					      info->total_mac_phy_cnt,
756 					      mac_phy_count);
757 				return -EINVAL;
758 			}
759 
760 			mac_phy_cap = &info->mac_phy_cap[mac_phy_count];
761 			mac_phy_caps_ext2 =
762 				&info->mac_phy_caps_ext2[mac_phy_count];
763 			status = wmi_extract_mac_phy_cap_service_ready_ext2(
764 					wmi_handle, event, hw_mode_id, phy_id,
765 					mac_phy_cap->phy_idx,
766 					mac_phy_caps_ext2);
767 
768 			if (QDF_IS_STATUS_ERROR(status)) {
769 				target_if_err("failed to parse mac phy capability ext2");
770 				return qdf_status_to_os_return(status);
771 			}
772 
773 			mac_phy_cap->reg_cap_ext.wireless_modes |=
774 				mac_phy_caps_ext2[phy_id].wireless_modes_ext;
775 
776 			mac_phy_count++;
777 			phy_bit_map &= (phy_bit_map - 1);
778 			phy_id++;
779 		}
780 	}
781 
782 	return 0;
783 }
784 
785 int init_deinit_populate_hal_reg_cap_ext2(wmi_unified_t wmi_handle,
786 					  uint8_t *event,
787 					  struct tgt_info *info)
788 {
789 	struct wlan_psoc_host_hal_reg_capabilities_ext2
790 		reg_cap[PSOC_MAX_PHY_REG_CAP] = {{0} };
791 	struct wlan_objmgr_psoc *psoc;
792 	uint32_t num_phy_reg_cap;
793 	uint8_t reg_idx;
794 	QDF_STATUS status = QDF_STATUS_SUCCESS;
795 
796 	if (!event) {
797 		target_if_err("event buffer is null");
798 		return -EINVAL;
799 	}
800 
801 	psoc = target_if_get_psoc_from_scn_hdl(wmi_handle->scn_handle);
802 	if (!psoc) {
803 		target_if_err("psoc is null");
804 		return -EINVAL;
805 	}
806 
807 	num_phy_reg_cap = info->service_ext_param.num_phy;
808 	if (num_phy_reg_cap > PSOC_MAX_PHY_REG_CAP) {
809 		target_if_err("Invalid num_phy_reg_cap %d", num_phy_reg_cap);
810 		return -EINVAL;
811 	}
812 
813 	for (reg_idx = 0; reg_idx < num_phy_reg_cap; reg_idx++) {
814 		status = wmi_extract_hal_reg_cap_ext2(
815 				wmi_handle, event, reg_idx, &reg_cap[reg_idx]);
816 		if (QDF_IS_STATUS_ERROR(status)) {
817 			target_if_err("failed to parse hal reg cap ext2");
818 			return qdf_status_to_os_return(status);
819 		}
820 
821 		status = ucfg_reg_update_hal_reg_cap(
822 				psoc, reg_cap[reg_idx].wireless_modes_ext,
823 				reg_idx);
824 		if (QDF_IS_STATUS_ERROR(status)) {
825 			target_if_err("Failed to update hal reg cap");
826 			return qdf_status_to_os_return(status);
827 		}
828 	}
829 
830 	return 0;
831 }
832 
833 int init_deinit_populate_scan_radio_cap_ext2(wmi_unified_t wmi_handle,
834 					     uint8_t *event,
835 					     struct tgt_info *info)
836 {
837 	struct wlan_psoc_host_scan_radio_caps *param;
838 	uint32_t num_scan_radio_caps;
839 	uint8_t cap_idx;
840 	QDF_STATUS status;
841 
842 	if (!event) {
843 		target_if_err("Invalid event buffer");
844 		return -EINVAL;
845 	}
846 
847 	num_scan_radio_caps = info->service_ext2_param.num_scan_radio_caps;
848 	target_if_debug("num scan radio capabilities = %d",
849 			num_scan_radio_caps);
850 
851 	if (!num_scan_radio_caps)
852 		return 0;
853 
854 	info->scan_radio_caps = qdf_mem_malloc(
855 				sizeof(struct wlan_psoc_host_scan_radio_caps) *
856 				num_scan_radio_caps);
857 
858 	if (!info->scan_radio_caps) {
859 		target_if_err("Failed to allocate memory for scan radio caps");
860 		return -EINVAL;
861 	}
862 
863 	for (cap_idx = 0; cap_idx < num_scan_radio_caps; cap_idx++) {
864 		param = &info->scan_radio_caps[cap_idx];
865 		status = wmi_extract_scan_radio_cap_service_ready_ext2(
866 				wmi_handle, event, cap_idx, param);
867 		if (QDF_IS_STATUS_ERROR(status)) {
868 			target_if_err("Extraction of scan radio cap failed");
869 			goto free_and_return;
870 		}
871 	}
872 
873 	return 0;
874 
875 free_and_return:
876 	qdf_mem_free(info->scan_radio_caps);
877 	info->scan_radio_caps = NULL;
878 
879 	return qdf_status_to_os_return(status);
880 }
881 
882 QDF_STATUS init_deinit_scan_radio_cap_free(
883 		struct target_psoc_info *tgt_psoc_info)
884 {
885 	qdf_mem_free(tgt_psoc_info->info.scan_radio_caps);
886 	tgt_psoc_info->info.scan_radio_caps = NULL;
887 
888 	return QDF_STATUS_SUCCESS;
889 }
890 
891 qdf_export_symbol(init_deinit_scan_radio_cap_free);
892 
893 static bool init_deinit_regdmn_160mhz_support(
894 		struct wlan_psoc_host_hal_reg_capabilities_ext *hal_cap)
895 {
896 	return ((hal_cap->wireless_modes &
897 		HOST_REGDMN_MODE_11AC_VHT160) != 0);
898 }
899 
900 static bool init_deinit_regdmn_80p80mhz_support(
901 		struct wlan_psoc_host_hal_reg_capabilities_ext *hal_cap)
902 {
903 	return ((hal_cap->wireless_modes &
904 			HOST_REGDMN_MODE_11AC_VHT80_80) != 0);
905 }
906 
907 static bool init_deinit_vht_160mhz_is_supported(uint32_t vhtcap)
908 {
909 	return ((vhtcap & WLAN_VHTCAP_SUP_CHAN_WIDTH_160) != 0);
910 }
911 
912 static bool init_deinit_vht_80p80mhz_is_supported(uint32_t vhtcap)
913 {
914 	return ((vhtcap & WLAN_VHTCAP_SUP_CHAN_WIDTH_80_160) != 0);
915 }
916 
917 static bool init_deinit_vht_160mhz_shortgi_is_supported(uint32_t vhtcap)
918 {
919 	return ((vhtcap & WLAN_VHTCAP_SHORTGI_160) != 0);
920 }
921 
922 QDF_STATUS init_deinit_validate_160_80p80_fw_caps(
923 		 struct wlan_objmgr_psoc *psoc,
924 		 struct target_psoc_info *tgt_hdl)
925 {
926 	bool wireless_mode_160mhz = false;
927 	bool wireless_mode_80p80mhz = false;
928 	bool vhtcap_160mhz = false;
929 	bool vhtcap_80p80_160mhz = false;
930 	bool vhtcap_160mhz_sgi = false;
931 	bool valid = false;
932 	struct wlan_psoc_host_hal_reg_capabilities_ext *reg_cap;
933 	struct wmi_unified *wmi_handle;
934 
935 	if (!tgt_hdl) {
936 		target_if_err(
937 		"target_psoc_info is null in validate 160n80p80 cap check");
938 		return QDF_STATUS_E_INVAL;
939 	}
940 
941 	wmi_handle = target_psoc_get_wmi_hdl(tgt_hdl);
942 
943 	if ((tgt_hdl->info.target_type == TARGET_TYPE_QCA8074) ||
944 	    (tgt_hdl->info.target_type == TARGET_TYPE_QCA8074V2) ||
945 	    (tgt_hdl->info.target_type == TARGET_TYPE_QCN6122) ||
946 	    (tgt_hdl->info.target_type == TARGET_TYPE_QCA6290)) {
947 		/**
948 		 * Return true for now. This is not available in
949 		 * qca8074 fw yet
950 		 */
951 		return QDF_STATUS_SUCCESS;
952 	}
953 
954 	reg_cap = ucfg_reg_get_hal_reg_cap(psoc);
955 	if (!reg_cap) {
956 		target_if_err("reg cap is NULL");
957 		return QDF_STATUS_E_FAILURE;
958 	}
959 
960 	/* NOTE: Host driver gets vht capability and supported channel
961 	 * width / channel frequency range from FW/HALPHY and obeys it.
962 	 * Host driver is unaware of any physical filters or any other
963 	 * hardware factors that can impact these capabilities.
964 	 * These need to be correctly determined by firmware.
965 	 */
966 
967 	/*This table lists all valid and invalid combinations
968 	 * WMODE160 WMODE80_80  VHTCAP_160 VHTCAP_80+80_160  IsCombinationvalid?
969 	 *      0         0           0              0                 YES
970 	 *      0         0           0              1                 NO
971 	 *      0         0           1              0                 NO
972 	 *      0         0           1              1                 NO
973 	 *      0         1           0              0                 NO
974 	 *      0         1           0              1                 NO
975 	 *      0         1           1              0                 NO
976 	 *      0         1           1              1                 NO
977 	 *      1         0           0              0                 NO
978 	 *      1         0           0              1                 NO
979 	 *      1         0           1              0                 YES
980 	 *      1         0           1              1                 NO
981 	 *      1         1           0              0                 NO
982 	 *      1         1           0              1                 YES
983 	 *      1         1           1              0                 NO
984 	 *      1         1           1              1                 NO
985 	 */
986 
987 	/* NOTE: Last row in above table is invalid because value corresponding
988 	 * to both VHTCAP_160 and VHTCAP_80+80_160 being set is reserved as per
989 	 * 802.11ac. Only one of them can be set at a time.
990 	 */
991 
992 	wireless_mode_160mhz = init_deinit_regdmn_160mhz_support(reg_cap);
993 	wireless_mode_80p80mhz = init_deinit_regdmn_80p80mhz_support(reg_cap);
994 	vhtcap_160mhz = init_deinit_vht_160mhz_is_supported(
995 				tgt_hdl->info.target_caps.vht_cap_info);
996 	vhtcap_80p80_160mhz = init_deinit_vht_80p80mhz_is_supported(
997 				tgt_hdl->info.target_caps.vht_cap_info);
998 	vhtcap_160mhz_sgi = init_deinit_vht_160mhz_shortgi_is_supported(
999 				tgt_hdl->info.target_caps.vht_cap_info);
1000 
1001 	if (!(wireless_mode_160mhz || wireless_mode_80p80mhz ||
1002 	      vhtcap_160mhz || vhtcap_80p80_160mhz)) {
1003 		valid = QDF_STATUS_SUCCESS;
1004 	} else if (wireless_mode_160mhz && !wireless_mode_80p80mhz &&
1005 		   vhtcap_160mhz && !vhtcap_80p80_160mhz) {
1006 		valid = QDF_STATUS_SUCCESS;
1007 	} else if (wireless_mode_160mhz && wireless_mode_80p80mhz &&
1008 		   !vhtcap_160mhz && vhtcap_160mhz_sgi) {
1009 		valid = QDF_STATUS_SUCCESS;
1010 	}
1011 
1012 	if (valid == QDF_STATUS_SUCCESS) {
1013 		/*
1014 		 * Ensure short GI for 160 MHz is enabled
1015 		 * only if 160/80+80 is supported.
1016 		 */
1017 		if (vhtcap_160mhz_sgi &&
1018 		    !(vhtcap_160mhz || vhtcap_80p80_160mhz)) {
1019 			valid = QDF_STATUS_E_FAILURE;
1020 		}
1021 	}
1022 
1023 	/* Invalid config specified by FW */
1024 	if (valid != QDF_STATUS_SUCCESS) {
1025 		target_if_err("Invalid 160/80+80 MHz config specified by FW. Take care of it first");
1026 		target_if_err("wireless_mode_160mhz: %d, wireless_mode_80p80mhz: %d",
1027 			      wireless_mode_160mhz, wireless_mode_80p80mhz);
1028 		target_if_err("vhtcap_160mhz: %d, vhtcap_80p80_160mhz: %d,vhtcap_160mhz_sgi: %d",
1029 			      vhtcap_160mhz, vhtcap_80p80_160mhz,
1030 			      vhtcap_160mhz_sgi);
1031 	}
1032 	return valid;
1033 }
1034 
1035 void init_deinit_chainmask_config(
1036 		 struct wlan_objmgr_psoc *psoc,
1037 		 struct target_psoc_info *tgt_hdl)
1038 {
1039 	tgt_hdl->info.wlan_res_cfg.tx_chain_mask =
1040 		((1 << tgt_hdl->info.target_caps.num_rf_chains) - 1);
1041 	tgt_hdl->info.wlan_res_cfg.rx_chain_mask =
1042 		((1 << tgt_hdl->info.target_caps.num_rf_chains) - 1);
1043 }
1044 
1045 QDF_STATUS init_deinit_is_service_ext_msg(
1046 		 struct wlan_objmgr_psoc *psoc,
1047 		 struct target_psoc_info *tgt_hdl)
1048 {
1049 	struct wmi_unified *wmi_handle;
1050 
1051 	if (!tgt_hdl) {
1052 		target_if_err(
1053 			"psoc target_psoc_info is null in service ext msg");
1054 		return QDF_STATUS_E_INVAL;
1055 	}
1056 
1057 	wmi_handle = target_psoc_get_wmi_hdl(tgt_hdl);
1058 
1059 	if (wmi_service_enabled(wmi_handle, wmi_service_ext_msg))
1060 		return QDF_STATUS_SUCCESS;
1061 	else
1062 		return QDF_STATUS_E_FAILURE;
1063 }
1064 
1065 bool init_deinit_is_preferred_hw_mode_supported(
1066 		 struct wlan_objmgr_psoc *psoc,
1067 		 struct target_psoc_info *tgt_hdl)
1068 {
1069 	uint16_t i;
1070 	struct tgt_info *info;
1071 
1072 	if (!tgt_hdl) {
1073 		target_if_err(
1074 			"psoc target_psoc_info is null in service ext msg");
1075 		return FALSE;
1076 	}
1077 
1078 	info = &tgt_hdl->info;
1079 
1080 	if (info->preferred_hw_mode == WMI_HOST_HW_MODE_MAX)
1081 		return TRUE;
1082 
1083 	if (wlan_psoc_nif_feat_cap_get(psoc, WLAN_SOC_F_DYNAMIC_HW_MODE)) {
1084 		if (!wlan_psoc_nif_fw_ext_cap_get(psoc,
1085 					WLAN_SOC_CEXT_DYNAMIC_HW_MODE)) {
1086 			target_if_err(
1087 			"WMI service bit for DYNAMIC HW mode is not set!");
1088 			return FALSE;
1089 		}
1090 	}
1091 
1092 	for (i = 0; i < target_psoc_get_total_mac_phy_cnt(tgt_hdl); i++) {
1093 		if (info->mac_phy_cap[i].hw_mode_id == info->preferred_hw_mode)
1094 			return TRUE;
1095 	}
1096 
1097 	return FALSE;
1098 }
1099 
1100 void init_deinit_wakeup_host_wait(
1101 		 struct wlan_objmgr_psoc *psoc,
1102 		 struct target_psoc_info *tgt_hdl)
1103 {
1104 	if (!tgt_hdl) {
1105 		target_if_err("psoc target_psoc_info is null in target ready");
1106 		return;
1107 	}
1108 	qdf_event_set(&tgt_hdl->info.event);
1109 }
1110