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