1 /*
2  * Copyright (c) 2020, The Linux Foundation. All rights reserved.
3  * Copyright (c) 2022-2023 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: contains definitions for coex core functions
20  */
21 
22 #include <wlan_coex_ucfg_api.h>
23 #include <wlan_coex_tgt_api.h>
24 #include <wlan_coex_main.h>
25 
wlan_coex_psoc_created_notification(struct wlan_objmgr_psoc * psoc,void * arg_list)26 QDF_STATUS wlan_coex_psoc_created_notification(struct wlan_objmgr_psoc *psoc,
27 					       void *arg_list)
28 {
29 	struct coex_psoc_obj *psoc_obj;
30 	QDF_STATUS status;
31 
32 	psoc_obj = qdf_mem_malloc(sizeof(*psoc_obj));
33 	if (!psoc_obj)
34 		return QDF_STATUS_E_NOMEM;
35 
36 	psoc_obj->btc_chain_mode = WLAN_COEX_BTC_CHAIN_MODE_UNSETTLED;
37 
38 	/* Attach scan private date to psoc */
39 	status = wlan_objmgr_psoc_component_obj_attach(psoc,
40 						       WLAN_UMAC_COMP_COEX,
41 						       psoc_obj,
42 						       QDF_STATUS_SUCCESS);
43 	if (QDF_IS_STATUS_ERROR(status)) {
44 		coex_err("Failed to attach psoc coex component");
45 		qdf_mem_free(psoc_obj);
46 	} else {
47 		coex_debug("Coex object attach to psoc successful");
48 	}
49 
50 	return status;
51 }
52 
wlan_coex_psoc_destroyed_notification(struct wlan_objmgr_psoc * psoc,void * arg_list)53 QDF_STATUS wlan_coex_psoc_destroyed_notification(struct wlan_objmgr_psoc *psoc,
54 						 void *arg_list)
55 {
56 	void *psoc_obj;
57 	QDF_STATUS status;
58 
59 	psoc_obj = wlan_psoc_get_coex_obj(psoc);
60 	if (!psoc_obj)
61 		return QDF_STATUS_E_FAILURE;
62 
63 	status = wlan_objmgr_psoc_component_obj_detach(psoc,
64 						       WLAN_UMAC_COMP_COEX,
65 						       psoc_obj);
66 	if (QDF_IS_STATUS_ERROR(status))
67 		coex_err("Failed to detach psoc coex component");
68 
69 	qdf_mem_free(psoc_obj);
70 
71 	return status;
72 }
73 
74 QDF_STATUS
wlan_coex_psoc_init(struct wlan_objmgr_psoc * psoc)75 wlan_coex_psoc_init(struct wlan_objmgr_psoc *psoc)
76 {
77 	return QDF_STATUS_SUCCESS;
78 }
79 
80 QDF_STATUS
wlan_coex_psoc_deinit(struct wlan_objmgr_psoc * psoc)81 wlan_coex_psoc_deinit(struct wlan_objmgr_psoc *psoc)
82 {
83 	return QDF_STATUS_SUCCESS;
84 }
85 
wlan_coex_config_send(struct wlan_objmgr_vdev * vdev,struct coex_config_params * param)86 QDF_STATUS wlan_coex_config_send(struct wlan_objmgr_vdev *vdev,
87 				 struct coex_config_params *param)
88 {
89 	QDF_STATUS status;
90 
91 	status = tgt_send_coex_config(vdev, param);
92 	if (QDF_IS_STATUS_ERROR(status))
93 		coex_err("failed to send coex config");
94 
95 	return status;
96 }
97 
wlan_coex_multi_config_send(struct wlan_objmgr_vdev * vdev,struct coex_multi_config * param)98 QDF_STATUS wlan_coex_multi_config_send(struct wlan_objmgr_vdev *vdev,
99 				       struct coex_multi_config *param)
100 {
101 	struct wlan_objmgr_psoc *psoc;
102 	struct coex_config_params one_param;
103 	QDF_STATUS status, ret = QDF_STATUS_SUCCESS;
104 	uint32_t i;
105 
106 	if (!vdev) {
107 		coex_err("Null vdev");
108 		return QDF_STATUS_E_INVAL;
109 	}
110 
111 	psoc = wlan_vdev_get_psoc(vdev);
112 	if (!psoc) {
113 		coex_err("failed to get coex_obj");
114 		return QDF_STATUS_E_INVAL;
115 	}
116 
117 	if (tgt_get_coex_multi_config_support(psoc))
118 		return tgt_send_coex_multi_config(vdev, param);
119 
120 	for (i = 0; i < param->num_configs; i++) {
121 		one_param.vdev_id = param->vdev_id;
122 		one_param.config_type = param->cfg_items[i].config_type;
123 		one_param.config_arg1 = param->cfg_items[i].config_arg1;
124 		one_param.config_arg2 = param->cfg_items[i].config_arg2;
125 		one_param.config_arg3 = param->cfg_items[i].config_arg3;
126 		one_param.config_arg4 = param->cfg_items[i].config_arg4;
127 		one_param.config_arg5 = param->cfg_items[i].config_arg5;
128 		one_param.config_arg6 = param->cfg_items[i].config_arg6;
129 		status = tgt_send_coex_config(vdev, &one_param);
130 		if (QDF_IS_STATUS_ERROR(status)) {
131 			coex_err("fail to send one coex config");
132 			ret = status;
133 		}
134 	}
135 
136 	return ret;
137 }
138 
139 QDF_STATUS
wlan_coex_config_updated(struct wlan_objmgr_vdev * vdev,uint8_t type)140 wlan_coex_config_updated(struct wlan_objmgr_vdev *vdev, uint8_t type)
141 {
142 	struct wlan_objmgr_psoc *psoc;
143 	struct coex_psoc_obj *coex_obj;
144 	QDF_STATUS status = QDF_STATUS_SUCCESS;
145 
146 	if (!vdev) {
147 		coex_err("NULL vdev");
148 		return QDF_STATUS_E_INVAL;
149 	}
150 
151 	if (type >= COEX_CONFIG_TYPE_MAX) {
152 		coex_err("config type out of range: %d", type);
153 		return QDF_STATUS_E_INVAL;
154 	}
155 
156 	psoc = wlan_vdev_get_psoc(vdev);
157 	if (!psoc) {
158 		coex_err("NULL psoc");
159 		return QDF_STATUS_E_INVAL;
160 	}
161 
162 	coex_obj = wlan_psoc_get_coex_obj(psoc);
163 	if (!coex_obj)
164 		return QDF_STATUS_E_INVAL;
165 
166 	if (coex_obj->coex_config_updated[type])
167 		status = coex_obj->coex_config_updated[type](vdev);
168 
169 	return status;
170 }
171 
172 QDF_STATUS
wlan_coex_psoc_set_btc_chain_mode(struct wlan_objmgr_psoc * psoc,enum coex_btc_chain_mode val)173 wlan_coex_psoc_set_btc_chain_mode(struct wlan_objmgr_psoc *psoc,
174 				  enum coex_btc_chain_mode val)
175 {
176 	struct coex_psoc_obj *coex_obj;
177 
178 	coex_obj = wlan_psoc_get_coex_obj(psoc);
179 	if (!coex_obj)
180 		return QDF_STATUS_E_INVAL;
181 
182 	coex_obj->btc_chain_mode = val;
183 
184 	return QDF_STATUS_SUCCESS;
185 }
186 
187 QDF_STATUS
wlan_coex_psoc_get_btc_chain_mode(struct wlan_objmgr_psoc * psoc,enum coex_btc_chain_mode * val)188 wlan_coex_psoc_get_btc_chain_mode(struct wlan_objmgr_psoc *psoc,
189 				  enum coex_btc_chain_mode *val)
190 {
191 	struct coex_psoc_obj *coex_obj;
192 
193 	if (!val) {
194 		coex_err("invalid param for getting btc chain mode");
195 		return QDF_STATUS_E_INVAL;
196 	}
197 
198 	coex_obj = wlan_psoc_get_coex_obj(psoc);
199 	if (!coex_obj)
200 		return QDF_STATUS_E_INVAL;
201 
202 	*val = coex_obj->btc_chain_mode;
203 	return QDF_STATUS_SUCCESS;
204 }
205 
206 #ifdef WLAN_FEATURE_DBAM_CONFIG
wlan_dbam_config_send(struct wlan_objmgr_vdev * vdev,struct coex_dbam_config_params * param)207 QDF_STATUS wlan_dbam_config_send(struct wlan_objmgr_vdev *vdev,
208 				 struct coex_dbam_config_params *param)
209 {
210 	QDF_STATUS status;
211 
212 	status = tgt_send_dbam_config(vdev, param);
213 	if (QDF_IS_STATUS_ERROR(status))
214 		coex_err("failed to send dbam config");
215 
216 	return status;
217 }
218 
wlan_dbam_attach(struct wlan_objmgr_psoc * psoc)219 QDF_STATUS wlan_dbam_attach(struct wlan_objmgr_psoc *psoc)
220 {
221 	struct wlan_lmac_if_dbam_tx_ops *dbam_tx_ops;
222 
223 	if (!psoc) {
224 		coex_err("psoc is Null");
225 		return QDF_STATUS_E_NULL_VALUE;
226 	}
227 
228 	dbam_tx_ops = wlan_psoc_get_dbam_tx_ops(psoc);
229 	if (!dbam_tx_ops) {
230 		coex_err("dbam_tx_ops is Null");
231 		return QDF_STATUS_E_NULL_VALUE;
232 	}
233 
234 	if (!dbam_tx_ops->dbam_event_attach) {
235 		coex_err("dbam_event_attach function is Null");
236 		return QDF_STATUS_E_NULL_VALUE;
237 	}
238 
239 	return dbam_tx_ops->dbam_event_attach(psoc);
240 }
241 
wlan_dbam_detach(struct wlan_objmgr_psoc * psoc)242 QDF_STATUS wlan_dbam_detach(struct wlan_objmgr_psoc *psoc)
243 {
244 	struct wlan_lmac_if_dbam_tx_ops *dbam_tx_ops;
245 
246 	if (!psoc) {
247 		coex_err("psoc is Null");
248 		return QDF_STATUS_E_NULL_VALUE;
249 	}
250 
251 	dbam_tx_ops = wlan_psoc_get_dbam_tx_ops(psoc);
252 	if (!dbam_tx_ops) {
253 		coex_err("dbam_tx_ops is Null");
254 		return QDF_STATUS_E_NULL_VALUE;
255 	}
256 
257 	if (!dbam_tx_ops->dbam_event_detach) {
258 		coex_err("dbam_event_detach function is Null");
259 		return QDF_STATUS_E_NULL_VALUE;
260 	}
261 
262 	return dbam_tx_ops->dbam_event_detach(psoc);
263 }
264 #endif
265