1 /*
2  * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
3  * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 /**
19  * DOC: This file init/deint functions for dcs module.
20  */
21 
22 #include "wlan_dcs_init_deinit_api.h"
23 #include "../../core/src/wlan_dcs.h"
24 #include "cfg_dcs.h"
25 #include "cfg_ucfg_api.h"
26 
27 /**
28  * wlan_dcs_psoc_obj_create_notification() - dcs psoc create handler
29  * @psoc: psoc object
30  * @arg_list: Argument list
31  *
32  * return: QDF_STATUS_SUCCESS for success or error code
33  */
34 static QDF_STATUS
wlan_dcs_psoc_obj_create_notification(struct wlan_objmgr_psoc * psoc,void * arg_list)35 wlan_dcs_psoc_obj_create_notification(struct wlan_objmgr_psoc *psoc,
36 				      void *arg_list)
37 {
38 	QDF_STATUS status;
39 	struct dcs_psoc_priv_obj *dcs_psoc_obj;
40 	uint8_t loop;
41 
42 	dcs_psoc_obj = qdf_mem_malloc(sizeof(*dcs_psoc_obj));
43 
44 	if (!dcs_psoc_obj)
45 		return QDF_STATUS_E_NOMEM;
46 
47 	for (loop = 0; loop < WLAN_DCS_MAX_PDEVS; loop++)
48 		qdf_spinlock_create(&dcs_psoc_obj->dcs_pdev_priv[loop].lock);
49 
50 	status = wlan_objmgr_psoc_component_obj_attach(psoc,
51 						       WLAN_UMAC_COMP_DCS,
52 						       dcs_psoc_obj,
53 						       QDF_STATUS_SUCCESS);
54 
55 	if (QDF_IS_STATUS_ERROR(status)) {
56 		dcs_err("dcs pdev obj attach failed");
57 		qdf_mem_free(dcs_psoc_obj);
58 		return status;
59 	}
60 
61 	dcs_info("dcs psoc object attached");
62 
63 	return status;
64 }
65 
66 /**
67  * wlan_dcs_psoc_obj_destroy_notification() - dcs psoc destroy handler
68  * @psoc: psoc object
69  * @arg_list: Argument list
70  *
71  * return: QDF_STATUS_SUCCESS for success or error code
72  */
73 static QDF_STATUS
wlan_dcs_psoc_obj_destroy_notification(struct wlan_objmgr_psoc * psoc,void * arg_list)74 wlan_dcs_psoc_obj_destroy_notification(struct wlan_objmgr_psoc *psoc,
75 				       void *arg_list)
76 {
77 	QDF_STATUS status;
78 	uint8_t loop;
79 	struct dcs_psoc_priv_obj *dcs_psoc_obj =
80 		wlan_objmgr_psoc_get_comp_private_obj(psoc, WLAN_UMAC_COMP_DCS);
81 
82 	if (!dcs_psoc_obj) {
83 		dcs_err("invalid wifi dcs obj");
84 		return QDF_STATUS_E_FAULT;
85 	}
86 
87 	status = wlan_objmgr_psoc_component_obj_detach(psoc,
88 						       WLAN_UMAC_COMP_DCS,
89 						       dcs_psoc_obj);
90 	for (loop = 0; loop < WLAN_DCS_MAX_PDEVS; loop++) {
91 		qdf_timer_free(&dcs_psoc_obj->dcs_pdev_priv[loop].
92 							dcs_disable_timer);
93 		qdf_spinlock_destroy(&dcs_psoc_obj->dcs_pdev_priv[loop].lock);
94 	}
95 	qdf_mem_free(dcs_psoc_obj);
96 
97 	return status;
98 }
99 
wlan_dcs_init(void)100 QDF_STATUS wlan_dcs_init(void)
101 {
102 	QDF_STATUS status = QDF_STATUS_SUCCESS;
103 
104 	status = wlan_objmgr_register_psoc_create_handler(
105 			WLAN_UMAC_COMP_DCS,
106 			wlan_dcs_psoc_obj_create_notification,
107 			NULL);
108 
109 	if (QDF_IS_STATUS_ERROR(status))
110 		goto err_psoc_create;
111 
112 	status = wlan_objmgr_register_psoc_destroy_handler(
113 			WLAN_UMAC_COMP_DCS,
114 			wlan_dcs_psoc_obj_destroy_notification,
115 			NULL);
116 
117 	if (QDF_IS_STATUS_ERROR(status))
118 		goto err_psoc_delete;
119 
120 	return QDF_STATUS_SUCCESS;
121 
122 err_psoc_delete:
123 	wlan_objmgr_unregister_psoc_create_handler(
124 			WLAN_UMAC_COMP_DCS,
125 			wlan_dcs_psoc_obj_create_notification,
126 			NULL);
127 err_psoc_create:
128 	return status;
129 }
130 
wlan_dcs_deinit(void)131 QDF_STATUS wlan_dcs_deinit(void)
132 {
133 	QDF_STATUS status = QDF_STATUS_SUCCESS;
134 
135 	status = wlan_objmgr_unregister_psoc_create_handler(
136 			WLAN_UMAC_COMP_DCS,
137 			wlan_dcs_psoc_obj_create_notification,
138 			NULL);
139 
140 	if (QDF_IS_STATUS_ERROR(status))
141 		return QDF_STATUS_E_FAILURE;
142 
143 	status = wlan_objmgr_unregister_psoc_destroy_handler(
144 			WLAN_UMAC_COMP_DCS,
145 			wlan_dcs_psoc_obj_destroy_notification,
146 			NULL);
147 
148 	if (QDF_IS_STATUS_ERROR(status))
149 		return QDF_STATUS_E_FAILURE;
150 
151 	return QDF_STATUS_SUCCESS;
152 }
153 
wlan_dcs_enable(struct wlan_objmgr_psoc * psoc)154 QDF_STATUS wlan_dcs_enable(struct wlan_objmgr_psoc *psoc)
155 {
156 	return wlan_dcs_attach(psoc);
157 }
158 
wlan_dcs_disable(struct wlan_objmgr_psoc * psoc)159 QDF_STATUS wlan_dcs_disable(struct wlan_objmgr_psoc *psoc)
160 {
161 	return wlan_dcs_detach(psoc);
162 }
163 
wlan_dcs_psoc_open(struct wlan_objmgr_psoc * psoc)164 QDF_STATUS wlan_dcs_psoc_open(struct wlan_objmgr_psoc *psoc)
165 {
166 	struct dcs_psoc_priv_obj *dcs_psoc_obj;
167 	struct dcs_pdev_priv_obj *dcs_pdev_priv;
168 	uint8_t loop;
169 
170 	if (!psoc) {
171 		dcs_err("psoc is NULL");
172 		return QDF_STATUS_E_INVAL;
173 	}
174 
175 	dcs_psoc_obj = wlan_objmgr_psoc_get_comp_private_obj(
176 			psoc, WLAN_UMAC_COMP_DCS);
177 	if (!dcs_psoc_obj) {
178 		dcs_err("dcs psoc private object is NULL");
179 		return QDF_STATUS_E_FAILURE;
180 	}
181 
182 	for (loop = 0; loop < WLAN_DCS_MAX_PDEVS; loop++) {
183 		dcs_pdev_priv = &dcs_psoc_obj->dcs_pdev_priv[loop];
184 		dcs_pdev_priv->dcs_host_params.dcs_enable_cfg =
185 					cfg_get(psoc, CFG_DCS_ENABLE);
186 		dcs_pdev_priv->dcs_host_params.dcs_algorithm_process = false;
187 		dcs_pdev_priv->dcs_host_params.dcs_debug =
188 					cfg_get(psoc, CFG_DCS_DEBUG);
189 		dcs_pdev_priv->dcs_host_params.phy_err_penalty =
190 				cfg_get(psoc, CFG_DCS_PHY_ERR_PENALTY);
191 		dcs_pdev_priv->dcs_host_params.phy_err_threshold =
192 				cfg_get(psoc, CFG_DCS_PHY_ERR_THRESHOLD);
193 		dcs_pdev_priv->dcs_host_params.radar_err_threshold =
194 				cfg_get(psoc, CFG_DCS_RADAR_ERR_THRESHOLD);
195 		dcs_pdev_priv->dcs_host_params.coch_intfr_threshold =
196 				cfg_get(psoc, CFG_DCS_COCH_INTFR_THRESHOLD);
197 		dcs_pdev_priv->dcs_host_params.user_max_cu =
198 				cfg_get(psoc, CFG_DCS_USER_MAX_CU);
199 		dcs_pdev_priv->dcs_host_params.intfr_detection_threshold =
200 			cfg_get(psoc, CFG_DCS_INTFR_DETECTION_THRESHOLD);
201 		dcs_pdev_priv->dcs_host_params.intfr_detection_window =
202 				cfg_get(psoc, CFG_DCS_INTFR_DETECTION_WINDOW);
203 		dcs_pdev_priv->dcs_host_params.tx_err_threshold =
204 				cfg_get(psoc, CFG_DCS_TX_ERR_THRESHOLD);
205 		dcs_pdev_priv->dcs_host_params.force_disable_algorithm =
206 				cfg_get(psoc, CFG_DCS_DISABLE_ALGORITHM);
207 		dcs_pdev_priv->dcs_freq_ctrl_params.
208 					disable_threshold_per_5mins =
209 			cfg_get(psoc, CFG_DCS_DISABLE_THRESHOLD_PER_5MINS);
210 		dcs_pdev_priv->dcs_freq_ctrl_params.restart_delay =
211 				cfg_get(psoc, CFG_DCS_RESTART_DELAY);
212 
213 		qdf_timer_init(NULL, &dcs_pdev_priv->dcs_disable_timer,
214 			       wlan_dcs_disable_timer_fn,
215 			       &dcs_pdev_priv->dcs_timer_args,
216 			       QDF_TIMER_TYPE_WAKE_APPS);
217 	}
218 
219 	return QDF_STATUS_SUCCESS;
220 }
221