1 /*
2 * Copyright (c) 2017-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
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 #include <qdf_status.h>
21 #include <target_if_direct_buf_rx_api.h>
22 #include <wlan_objmgr_cmn.h>
23 #include <wlan_objmgr_global_obj.h>
24 #include <wlan_objmgr_psoc_obj.h>
25 #include <wlan_objmgr_cmn.h>
26 #include "target_if_direct_buf_rx_main.h"
27 #include <qdf_module.h>
28 #include <wlan_lmac_if_def.h>
29
30 #if defined(WLAN_DEBUGFS) && defined(DIRECT_BUF_RX_DEBUG)
31 /* Base debugfs entry for DBR module */
32 qdf_dentry_t dbr_debugfs_entry;
33
34 static inline void
target_if_direct_buf_rx_debugfs_init(void)35 target_if_direct_buf_rx_debugfs_init(void)
36 {
37 dbr_debugfs_entry = qdf_debugfs_create_dir("dbr_ring_debug", NULL);
38
39 if (!dbr_debugfs_entry)
40 direct_buf_rx_err("error while creating direct_buf rx debugfs dir");
41 }
42
43 static inline void
target_if_direct_buf_rx_debugfs_deinit(void)44 target_if_direct_buf_rx_debugfs_deinit(void)
45 {
46 if (dbr_debugfs_entry) {
47 qdf_debugfs_remove_dir_recursive(dbr_debugfs_entry);
48 dbr_debugfs_entry = NULL;
49 }
50 }
51 #else
52 static inline void
target_if_direct_buf_rx_debugfs_init(void)53 target_if_direct_buf_rx_debugfs_init(void)
54 {
55 }
56
57 static inline void
target_if_direct_buf_rx_debugfs_deinit(void)58 target_if_direct_buf_rx_debugfs_deinit(void)
59 {
60 }
61 #endif /* WLAN_DEBUGFS && DIRECT_BUF_RX_DEBUG */
62
direct_buf_rx_init(void)63 QDF_STATUS direct_buf_rx_init(void)
64 {
65 QDF_STATUS status;
66
67 status = wlan_objmgr_register_psoc_create_handler(
68 WLAN_TARGET_IF_COMP_DIRECT_BUF_RX,
69 target_if_direct_buf_rx_psoc_create_handler,
70 NULL);
71
72 if (QDF_IS_STATUS_ERROR(status)) {
73 direct_buf_rx_err("Failed to register psoc create handler");
74 return status;
75 }
76
77 status = wlan_objmgr_register_psoc_destroy_handler(
78 WLAN_TARGET_IF_COMP_DIRECT_BUF_RX,
79 target_if_direct_buf_rx_psoc_destroy_handler,
80 NULL);
81
82 if (QDF_IS_STATUS_ERROR(status)) {
83 direct_buf_rx_err("Failed to register psoc destroy handler");
84 goto dbr_unreg_psoc_create;
85 }
86
87 status = wlan_objmgr_register_pdev_create_handler(
88 WLAN_TARGET_IF_COMP_DIRECT_BUF_RX,
89 target_if_direct_buf_rx_pdev_create_handler,
90 NULL);
91
92 if (QDF_IS_STATUS_ERROR(status)) {
93 direct_buf_rx_err("Failed to register pdev create handler");
94 goto dbr_unreg_psoc_destroy;
95 }
96
97 status = wlan_objmgr_register_pdev_destroy_handler(
98 WLAN_TARGET_IF_COMP_DIRECT_BUF_RX,
99 target_if_direct_buf_rx_pdev_destroy_handler,
100 NULL);
101
102 if (QDF_IS_STATUS_ERROR(status)) {
103 direct_buf_rx_err("Failed to register pdev destroy handler");
104 goto dbr_unreg_pdev_create;
105 }
106
107 target_if_direct_buf_rx_debugfs_init();
108
109 direct_buf_rx_info("Direct Buffer RX pdev,psoc create and destroy handlers registered");
110
111 return QDF_STATUS_SUCCESS;
112
113 dbr_unreg_pdev_create:
114 status = wlan_objmgr_unregister_pdev_create_handler(
115 WLAN_TARGET_IF_COMP_DIRECT_BUF_RX,
116 target_if_direct_buf_rx_pdev_create_handler,
117 NULL);
118
119 dbr_unreg_psoc_destroy:
120 status = wlan_objmgr_unregister_psoc_destroy_handler(
121 WLAN_TARGET_IF_COMP_DIRECT_BUF_RX,
122 target_if_direct_buf_rx_psoc_destroy_handler,
123 NULL);
124
125 dbr_unreg_psoc_create:
126 status = wlan_objmgr_unregister_psoc_create_handler(
127 WLAN_TARGET_IF_COMP_DIRECT_BUF_RX,
128 target_if_direct_buf_rx_psoc_create_handler,
129 NULL);
130
131 return QDF_STATUS_E_FAILURE;
132 }
133 qdf_export_symbol(direct_buf_rx_init);
134
direct_buf_rx_deinit(void)135 QDF_STATUS direct_buf_rx_deinit(void)
136 {
137 QDF_STATUS status;
138
139 target_if_direct_buf_rx_debugfs_deinit();
140
141 status = wlan_objmgr_unregister_pdev_destroy_handler(
142 WLAN_TARGET_IF_COMP_DIRECT_BUF_RX,
143 target_if_direct_buf_rx_pdev_destroy_handler,
144 NULL);
145
146 if (QDF_IS_STATUS_ERROR(status))
147 direct_buf_rx_err("Failed to unregister pdev destroy handler");
148
149 status = wlan_objmgr_unregister_pdev_create_handler(
150 WLAN_TARGET_IF_COMP_DIRECT_BUF_RX,
151 target_if_direct_buf_rx_pdev_create_handler,
152 NULL);
153
154 if (QDF_IS_STATUS_ERROR(status))
155 direct_buf_rx_err("Failed to unregister pdev create handler");
156
157 status = wlan_objmgr_unregister_psoc_destroy_handler(
158 WLAN_TARGET_IF_COMP_DIRECT_BUF_RX,
159 target_if_direct_buf_rx_psoc_destroy_handler,
160 NULL);
161
162 if (QDF_IS_STATUS_ERROR(status))
163 direct_buf_rx_err("Failed to unregister psoc destroy handler");
164
165 status = wlan_objmgr_unregister_psoc_create_handler(
166 WLAN_TARGET_IF_COMP_DIRECT_BUF_RX,
167 target_if_direct_buf_rx_psoc_create_handler,
168 NULL);
169
170 if (QDF_IS_STATUS_ERROR(status))
171 direct_buf_rx_err("Failed to unregister psoc create handler");
172
173 direct_buf_rx_debug("Direct Buffer RX pdev,psoc create and destroy handlers unregistered");
174
175 return status;
176 }
177 qdf_export_symbol(direct_buf_rx_deinit);
178
direct_buf_rx_target_attach(struct wlan_objmgr_psoc * psoc,void * hal_soc,qdf_device_t osdev)179 QDF_STATUS direct_buf_rx_target_attach(struct wlan_objmgr_psoc *psoc,
180 void *hal_soc, qdf_device_t osdev)
181 {
182 struct direct_buf_rx_psoc_obj *dbr_psoc_obj;
183
184 if (!hal_soc || !osdev) {
185 direct_buf_rx_err("hal soc or osdev is null");
186 return QDF_STATUS_E_INVAL;
187 }
188
189 dbr_psoc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc,
190 WLAN_TARGET_IF_COMP_DIRECT_BUF_RX);
191
192 direct_buf_rx_debug("Dbr psoc obj %pK", dbr_psoc_obj);
193
194 if (!dbr_psoc_obj) {
195 direct_buf_rx_err("dir buf rx psoc obj is null");
196 return QDF_STATUS_E_FAILURE;
197 }
198
199 dbr_psoc_obj->hal_soc = hal_soc;
200 dbr_psoc_obj->osdev = osdev;
201
202 return QDF_STATUS_SUCCESS;
203 }
204
205 #ifdef DIRECT_BUF_RX_DEBUG
206 static inline void
target_if_direct_buf_rx_debug_register_tx_ops(struct wlan_lmac_if_tx_ops * tx_ops)207 target_if_direct_buf_rx_debug_register_tx_ops(
208 struct wlan_lmac_if_tx_ops *tx_ops)
209 {
210 tx_ops->dbr_tx_ops.direct_buf_rx_start_ring_debug =
211 target_if_dbr_start_ring_debug;
212 tx_ops->dbr_tx_ops.direct_buf_rx_stop_ring_debug =
213 target_if_dbr_stop_ring_debug;
214 tx_ops->dbr_tx_ops.direct_buf_rx_start_buffer_poisoning =
215 target_if_dbr_start_buffer_poisoning;
216 tx_ops->dbr_tx_ops.direct_buf_rx_stop_buffer_poisoning =
217 target_if_dbr_stop_buffer_poisoning;
218 }
219 #else
220 static inline void
target_if_direct_buf_rx_debug_register_tx_ops(struct wlan_lmac_if_tx_ops * tx_ops)221 target_if_direct_buf_rx_debug_register_tx_ops(
222 struct wlan_lmac_if_tx_ops *tx_ops)
223 {
224 }
225 #endif /* DIRECT_BUF_RX_DEBUG */
226
target_if_direct_buf_rx_register_tx_ops(struct wlan_lmac_if_tx_ops * tx_ops)227 void target_if_direct_buf_rx_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops)
228 {
229 tx_ops->dbr_tx_ops.direct_buf_rx_module_register =
230 target_if_direct_buf_rx_module_register;
231 tx_ops->dbr_tx_ops.direct_buf_rx_module_unregister =
232 target_if_direct_buf_rx_module_unregister;
233 tx_ops->dbr_tx_ops.direct_buf_rx_register_events =
234 target_if_direct_buf_rx_register_events;
235 tx_ops->dbr_tx_ops.direct_buf_rx_unregister_events =
236 target_if_direct_buf_rx_unregister_events;
237 tx_ops->dbr_tx_ops.direct_buf_rx_print_ring_stat =
238 target_if_direct_buf_rx_print_ring_stat;
239 tx_ops->dbr_tx_ops.direct_buf_rx_get_ring_params =
240 target_if_direct_buf_rx_get_ring_params;
241 target_if_direct_buf_rx_debug_register_tx_ops(tx_ops);
242 }
243 qdf_export_symbol(target_if_direct_buf_rx_register_tx_ops);
244
target_if_dbr_update_pdev_for_hw_mode_change(struct wlan_objmgr_pdev * pdev,int phy_idx)245 QDF_STATUS target_if_dbr_update_pdev_for_hw_mode_change(
246 struct wlan_objmgr_pdev *pdev, int phy_idx)
247 {
248 struct wlan_objmgr_psoc *psoc;
249 struct direct_buf_rx_psoc_obj *dbr_psoc_obj;
250
251 psoc = wlan_pdev_get_psoc(pdev);
252 if (!psoc) {
253 direct_buf_rx_err("psoc is null");
254 return QDF_STATUS_E_NULL_VALUE;
255 }
256
257 dbr_psoc_obj = wlan_objmgr_psoc_get_comp_private_obj(
258 psoc, WLAN_TARGET_IF_COMP_DIRECT_BUF_RX);
259 if (!dbr_psoc_obj) {
260 direct_buf_rx_err("dir buf rx psoc object is null");
261 return QDF_STATUS_E_NULL_VALUE;
262 }
263
264 /* Update DBR object in pdev */
265 pdev->pdev_comp_priv_obj[WLAN_TARGET_IF_COMP_DIRECT_BUF_RX] =
266 (void *)dbr_psoc_obj->dbr_pdev_obj[phy_idx];
267
268 return QDF_STATUS_SUCCESS;
269 }
270
target_if_dbr_set_event_handler_ctx(struct wlan_objmgr_psoc * psoc,enum wmi_rx_exec_ctx event_handler_ctx)271 QDF_STATUS target_if_dbr_set_event_handler_ctx(
272 struct wlan_objmgr_psoc *psoc,
273 enum wmi_rx_exec_ctx event_handler_ctx)
274 {
275 struct direct_buf_rx_psoc_obj *dbr_psoc_obj;
276
277 if (!psoc) {
278 direct_buf_rx_err("psoc is null");
279 return QDF_STATUS_E_NULL_VALUE;
280 }
281
282 if (event_handler_ctx != WMI_RX_UMAC_CTX &&
283 event_handler_ctx != WMI_RX_WORK_CTX) {
284 qdf_err("DBR handler context: Invalid context");
285 return QDF_STATUS_E_INVAL;
286 }
287
288 dbr_psoc_obj = wlan_objmgr_psoc_get_comp_private_obj(
289 psoc, WLAN_TARGET_IF_COMP_DIRECT_BUF_RX);
290 if (!dbr_psoc_obj) {
291 direct_buf_rx_err("dir buf rx psoc object is null");
292 return QDF_STATUS_E_NULL_VALUE;
293 }
294
295 dbr_psoc_obj->handler_ctx = event_handler_ctx;
296
297 direct_buf_rx_info("DBR handler context: %d",
298 dbr_psoc_obj->handler_ctx);
299
300 return QDF_STATUS_SUCCESS;
301 }
302