xref: /wlan-dirver/qca-wifi-host-cmn/target_if/direct_buf_rx/src/target_if_direct_buf_rx_main.c (revision 3149adf58a329e17232a4c0e58d460d025edd55a)
1 /*
2  * Copyright (c) 2017-2018 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 #include "target_if.h"
20 #include "wmi_unified_api.h"
21 #include "wlan_lmac_if_def.h"
22 #include "target_if_direct_buf_rx_main.h"
23 #include <target_if_direct_buf_rx_api.h>
24 #include "hal_api.h"
25 #include <service_ready_util.h>
26 #include <init_deinit_ucfg.h>
27 
28 static uint8_t get_num_dbr_modules_per_pdev(struct wlan_objmgr_pdev *pdev)
29 {
30 	struct wlan_objmgr_psoc *psoc;
31 	struct wlan_psoc_host_dbr_ring_caps *dbr_ring_cap;
32 	uint8_t num_dbr_ring_caps, cap_idx, pdev_id, num_modules;
33 	struct target_psoc_info *tgt_psoc_info;
34 	struct wlan_psoc_host_service_ext_param *ext_svc_param;
35 
36 	psoc = wlan_pdev_get_psoc(pdev);
37 
38 	if (psoc == NULL) {
39 		direct_buf_rx_err("psoc is null");
40 		return 0;
41 	}
42 
43 	tgt_psoc_info = wlan_psoc_get_tgt_if_handle(psoc);
44 	if (tgt_psoc_info == NULL) {
45 		direct_buf_rx_err("target_psoc_info is null");
46 		return 0;
47 	}
48 	ext_svc_param = target_psoc_get_service_ext_param(tgt_psoc_info);
49 	num_dbr_ring_caps = ext_svc_param->num_dbr_ring_caps;
50 	dbr_ring_cap = target_psoc_get_dbr_ring_caps(tgt_psoc_info);
51 	pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
52 	num_modules = 0;
53 
54 	for (cap_idx = 0; cap_idx < num_dbr_ring_caps; cap_idx++) {
55 		if (dbr_ring_cap[cap_idx].pdev_id == pdev_id)
56 			num_modules++;
57 	}
58 
59 	return num_modules;
60 }
61 
62 static QDF_STATUS populate_dbr_cap_mod_param(struct wlan_objmgr_pdev *pdev,
63 			struct direct_buf_rx_module_param *mod_param)
64 {
65 	struct wlan_objmgr_psoc *psoc;
66 	struct wlan_psoc_host_dbr_ring_caps *dbr_ring_cap;
67 	uint8_t cap_idx;
68 	bool cap_found = false;
69 	enum DBR_MODULE mod_id = mod_param->mod_id;
70 	uint32_t num_dbr_ring_caps, pdev_id;
71 	struct target_psoc_info *tgt_psoc_info;
72 	struct wlan_psoc_host_service_ext_param *ext_svc_param;
73 
74 	psoc = wlan_pdev_get_psoc(pdev);
75 
76 	if (psoc == NULL) {
77 		direct_buf_rx_err("psoc is null");
78 		return QDF_STATUS_E_INVAL;
79 	}
80 
81 	tgt_psoc_info = wlan_psoc_get_tgt_if_handle(psoc);
82 	if (tgt_psoc_info == NULL) {
83 		direct_buf_rx_err("target_psoc_info is null");
84 		return QDF_STATUS_E_INVAL;
85 	}
86 
87 	ext_svc_param = target_psoc_get_service_ext_param(tgt_psoc_info);
88 	num_dbr_ring_caps = ext_svc_param->num_dbr_ring_caps;
89 	dbr_ring_cap = target_psoc_get_dbr_ring_caps(tgt_psoc_info);
90 	pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
91 
92 	for (cap_idx = 0; cap_idx < num_dbr_ring_caps; cap_idx++) {
93 		if (dbr_ring_cap[cap_idx].pdev_id == pdev_id) {
94 			if (dbr_ring_cap[cap_idx].mod_id == mod_id) {
95 				mod_param->dbr_ring_cap->ring_elems_min =
96 					dbr_ring_cap[cap_idx].ring_elems_min;
97 				mod_param->dbr_ring_cap->min_buf_size =
98 					dbr_ring_cap[cap_idx].min_buf_size;
99 				mod_param->dbr_ring_cap->min_buf_align =
100 					dbr_ring_cap[cap_idx].min_buf_align;
101 				cap_found = true;
102 			}
103 		}
104 	}
105 
106 	if (!cap_found) {
107 		direct_buf_rx_err("No cap found for module %d in pdev %d",
108 				  mod_id, pdev_id);
109 		return QDF_STATUS_E_FAILURE;
110 	}
111 
112 	return QDF_STATUS_SUCCESS;
113 }
114 
115 QDF_STATUS target_if_direct_buf_rx_pdev_create_handler(
116 	struct wlan_objmgr_pdev *pdev, void *data)
117 {
118 	struct direct_buf_rx_pdev_obj *dbr_pdev_obj;
119 	struct wlan_objmgr_psoc *psoc;
120 	uint8_t num_modules;
121 	QDF_STATUS status;
122 
123 	direct_buf_rx_enter();
124 
125 	if (pdev == NULL) {
126 		direct_buf_rx_err("pdev context passed is null");
127 		return QDF_STATUS_E_INVAL;
128 	}
129 
130 	psoc = wlan_pdev_get_psoc(pdev);
131 
132 	if (psoc == NULL) {
133 		direct_buf_rx_err("psoc is null");
134 		return QDF_STATUS_E_INVAL;
135 	}
136 
137 	dbr_pdev_obj = qdf_mem_malloc(sizeof(*dbr_pdev_obj));
138 
139 	if (dbr_pdev_obj == NULL) {
140 		direct_buf_rx_err("Failed to allocate dir buf rx pdev obj");
141 		return QDF_STATUS_E_NOMEM;
142 	}
143 
144 	direct_buf_rx_info("Dbr pdev obj %pK", dbr_pdev_obj);
145 
146 	status = wlan_objmgr_pdev_component_obj_attach(pdev,
147 					WLAN_TARGET_IF_COMP_DIRECT_BUF_RX,
148 					dbr_pdev_obj, QDF_STATUS_SUCCESS);
149 
150 	if (status != QDF_STATUS_SUCCESS) {
151 		direct_buf_rx_err("Failed to attach dir buf rx component %d",
152 				  status);
153 		qdf_mem_free(dbr_pdev_obj);
154 		return status;
155 	}
156 
157 	num_modules = get_num_dbr_modules_per_pdev(pdev);
158 	direct_buf_rx_info("Number of modules = %d pdev %d", num_modules,
159 			   wlan_objmgr_pdev_get_pdev_id(pdev));
160 	dbr_pdev_obj->num_modules = num_modules;
161 
162 	if (!dbr_pdev_obj->num_modules) {
163 		direct_buf_rx_info("Number of modules = %d", num_modules);
164 		return QDF_STATUS_SUCCESS;
165 	}
166 
167 	dbr_pdev_obj->dbr_mod_param = qdf_mem_malloc(num_modules *
168 				sizeof(struct direct_buf_rx_module_param));
169 
170 	if (dbr_pdev_obj->dbr_mod_param == NULL) {
171 		direct_buf_rx_err("Failed to allocate dir buf rx mod param");
172 		wlan_objmgr_pdev_component_obj_detach(pdev,
173 					WLAN_TARGET_IF_COMP_DIRECT_BUF_RX,
174 					dbr_pdev_obj);
175 		qdf_mem_free(dbr_pdev_obj);
176 		return QDF_STATUS_E_NOMEM;
177 	}
178 
179 
180 	return QDF_STATUS_SUCCESS;
181 }
182 
183 QDF_STATUS target_if_direct_buf_rx_pdev_destroy_handler(
184 	struct wlan_objmgr_pdev *pdev, void *data)
185 {
186 	struct direct_buf_rx_pdev_obj *dbr_pdev_obj;
187 	QDF_STATUS status;
188 	uint8_t num_modules, mod_idx;
189 
190 	if (pdev == NULL) {
191 		direct_buf_rx_err("pdev context passed is null");
192 		return QDF_STATUS_E_INVAL;
193 	}
194 
195 	dbr_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj(pdev,
196 				WLAN_TARGET_IF_COMP_DIRECT_BUF_RX);
197 
198 	if (dbr_pdev_obj == NULL) {
199 		direct_buf_rx_err("dir buf rx object is null");
200 		return QDF_STATUS_E_FAILURE;
201 	}
202 
203 	num_modules = dbr_pdev_obj->num_modules;
204 	for (mod_idx = 0; mod_idx < num_modules; mod_idx++)
205 		target_if_deinit_dbr_ring(pdev, dbr_pdev_obj, mod_idx);
206 
207 	status = wlan_objmgr_pdev_component_obj_detach(pdev,
208 					WLAN_TARGET_IF_COMP_DIRECT_BUF_RX,
209 					dbr_pdev_obj);
210 
211 	if (status != QDF_STATUS_SUCCESS) {
212 		direct_buf_rx_err("failed to detach dir buf rx component %d",
213 				  status);
214 	}
215 
216 	qdf_mem_free(dbr_pdev_obj);
217 
218 	return status;
219 }
220 
221 QDF_STATUS target_if_direct_buf_rx_psoc_create_handler(
222 	struct wlan_objmgr_psoc *psoc, void *data)
223 {
224 	struct direct_buf_rx_psoc_obj *dbr_psoc_obj;
225 	QDF_STATUS status;
226 
227 	direct_buf_rx_enter();
228 
229 	if (psoc == NULL) {
230 		direct_buf_rx_err("psoc context passed is null");
231 		return QDF_STATUS_E_INVAL;
232 	}
233 
234 	dbr_psoc_obj = qdf_mem_malloc(sizeof(*dbr_psoc_obj));
235 
236 	if (!dbr_psoc_obj) {
237 		direct_buf_rx_err("failed to alloc dir buf rx psoc obj");
238 		return QDF_STATUS_E_NOMEM;
239 	}
240 
241 	direct_buf_rx_info("Dbr psoc obj %pK", dbr_psoc_obj);
242 
243 	status = wlan_objmgr_psoc_component_obj_attach(psoc,
244 			WLAN_TARGET_IF_COMP_DIRECT_BUF_RX, dbr_psoc_obj,
245 			QDF_STATUS_SUCCESS);
246 
247 	if (status != QDF_STATUS_SUCCESS) {
248 		direct_buf_rx_err("Failed to attach dir buf rx component %d",
249 				  status);
250 		goto attach_error;
251 	}
252 
253 	return status;
254 
255 attach_error:
256 	qdf_mem_free(dbr_psoc_obj);
257 
258 	return status;
259 }
260 
261 QDF_STATUS target_if_direct_buf_rx_psoc_destroy_handler(
262 	struct wlan_objmgr_psoc *psoc, void *data)
263 {
264 	QDF_STATUS status;
265 	struct direct_buf_rx_psoc_obj *dbr_psoc_obj;
266 
267 	direct_buf_rx_enter();
268 
269 	dbr_psoc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc,
270 				WLAN_TARGET_IF_COMP_DIRECT_BUF_RX);
271 
272 	if (!dbr_psoc_obj) {
273 		direct_buf_rx_err("dir buf rx psoc obj is null");
274 		return QDF_STATUS_E_FAILURE;
275 	}
276 
277 	status = wlan_objmgr_psoc_component_obj_detach(psoc,
278 				WLAN_TARGET_IF_COMP_DIRECT_BUF_RX,
279 				dbr_psoc_obj);
280 
281 	if (status != QDF_STATUS_SUCCESS) {
282 		direct_buf_rx_err("failed to detach dir buf rx component %d",
283 				  status);
284 	}
285 
286 	qdf_mem_free(dbr_psoc_obj);
287 
288 	return status;
289 }
290 
291 static QDF_STATUS target_if_dbr_replenish_ring(struct wlan_objmgr_pdev *pdev,
292 			struct direct_buf_rx_module_param *mod_param,
293 			void *aligned_vaddr, uint8_t cookie)
294 {
295 	uint64_t *ring_entry;
296 	uint32_t dw_lo, dw_hi = 0, map_status;
297 	void *hal_soc, *srng;
298 	qdf_dma_addr_t paddr;
299 	struct wlan_objmgr_psoc *psoc;
300 	struct direct_buf_rx_psoc_obj *dbr_psoc_obj;
301 	struct direct_buf_rx_ring_cfg *dbr_ring_cfg;
302 	struct direct_buf_rx_ring_cap *dbr_ring_cap;
303 	struct direct_buf_rx_buf_info *dbr_buf_pool;
304 	QDF_STATUS status;
305 
306 	direct_buf_rx_enter();
307 
308 	dbr_ring_cfg = mod_param->dbr_ring_cfg;
309 	dbr_ring_cap = mod_param->dbr_ring_cap;
310 	dbr_buf_pool = mod_param->dbr_buf_pool;
311 
312 	psoc = wlan_pdev_get_psoc(pdev);
313 
314 	if (!psoc) {
315 		direct_buf_rx_err("psoc is null");
316 		return QDF_STATUS_E_FAILURE;
317 	}
318 
319 	dbr_psoc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc,
320 				WLAN_TARGET_IF_COMP_DIRECT_BUF_RX);
321 
322 	if (dbr_psoc_obj == NULL) {
323 		direct_buf_rx_err("dir buf rx psoc object is null");
324 		return QDF_STATUS_E_FAILURE;
325 	}
326 
327 	hal_soc = dbr_psoc_obj->hal_soc;
328 	srng = dbr_ring_cfg->srng;
329 	if (!aligned_vaddr) {
330 		direct_buf_rx_err("aligned vaddr is null");
331 		return QDF_STATUS_SUCCESS;
332 	}
333 
334 	map_status = qdf_mem_map_nbytes_single(dbr_psoc_obj->osdev,
335 					       aligned_vaddr,
336 					       QDF_DMA_FROM_DEVICE,
337 					       dbr_ring_cap->min_buf_size,
338 					       &paddr);
339 	if (map_status) {
340 		direct_buf_rx_err("mem map failed status = %d", status);
341 		return QDF_STATUS_E_FAILURE;
342 	}
343 
344 	QDF_ASSERT(!((uint64_t)paddr & dbr_ring_cap->min_buf_align));
345 	dbr_buf_pool[cookie].paddr = paddr;
346 
347 	hal_srng_access_start(hal_soc, srng);
348 	ring_entry = hal_srng_src_get_next(hal_soc, srng);
349 	QDF_ASSERT(ring_entry != NULL);
350 	dw_lo = (uint64_t)paddr & 0xFFFFFFFF;
351 	WMI_HOST_DBR_RING_ADDR_HI_SET(dw_hi, (uint64_t)paddr >> 32);
352 	WMI_HOST_DBR_DATA_ADDR_HI_HOST_DATA_SET(dw_hi, cookie);
353 	direct_buf_rx_info("Cookie = %d", cookie);
354 	direct_buf_rx_info("dw_lo = %x dw_hi = %x", dw_lo, dw_hi);
355 	*ring_entry = (uint64_t)dw_hi << 32 | dw_lo;
356 	direct_buf_rx_info("Valid ring entry");
357 	hal_srng_access_end(hal_soc, srng);
358 
359 	return QDF_STATUS_SUCCESS;
360 }
361 
362 static QDF_STATUS target_if_dbr_fill_ring(struct wlan_objmgr_pdev *pdev,
363 			  struct direct_buf_rx_module_param *mod_param)
364 {
365 	uint8_t idx;
366 	void *buf, *buf_aligned;
367 	struct direct_buf_rx_ring_cfg *dbr_ring_cfg;
368 	struct direct_buf_rx_ring_cap *dbr_ring_cap;
369 	struct direct_buf_rx_buf_info *dbr_buf_pool;
370 	QDF_STATUS status;
371 
372 	direct_buf_rx_enter();
373 
374 	dbr_ring_cfg = mod_param->dbr_ring_cfg;
375 	dbr_ring_cap = mod_param->dbr_ring_cap;
376 	dbr_buf_pool = mod_param->dbr_buf_pool;
377 
378 	for (idx = 0; idx < dbr_ring_cfg->num_ptr - 1; idx++) {
379 		buf = qdf_mem_malloc(dbr_ring_cap->min_buf_size +
380 				dbr_ring_cap->min_buf_align - 1);
381 		if (!buf) {
382 			direct_buf_rx_err("dir buf rx ring buf alloc failed");
383 			return QDF_STATUS_E_NOMEM;
384 		}
385 		dbr_buf_pool[idx].vaddr = buf;
386 		buf_aligned = (void *)(uintptr_t)qdf_roundup(
387 				(uint64_t)(uintptr_t)buf, DBR_RING_BASE_ALIGN);
388 		dbr_buf_pool[idx].offset = buf_aligned - buf;
389 		dbr_buf_pool[idx].cookie = idx;
390 		status = target_if_dbr_replenish_ring(pdev, mod_param,
391 						      buf_aligned, idx);
392 		if (QDF_IS_STATUS_ERROR(status)) {
393 			direct_buf_rx_err("replenish failed with status : %d",
394 					  status);
395 			qdf_mem_free(buf);
396 			return QDF_STATUS_E_FAILURE;
397 		}
398 	}
399 
400 	return QDF_STATUS_SUCCESS;
401 }
402 
403 static QDF_STATUS target_if_dbr_init_ring(struct wlan_objmgr_pdev *pdev,
404 			struct direct_buf_rx_module_param *mod_param)
405 {
406 	void *srng;
407 	uint32_t num_entries, ring_alloc_size, max_entries, entry_size;
408 	qdf_dma_addr_t paddr;
409 	struct hal_srng_params ring_params = {0};
410 	struct wlan_objmgr_psoc *psoc;
411 	struct direct_buf_rx_psoc_obj *dbr_psoc_obj;
412 	struct direct_buf_rx_ring_cap *dbr_ring_cap;
413 	struct direct_buf_rx_ring_cfg *dbr_ring_cfg;
414 	QDF_STATUS status;
415 
416 	direct_buf_rx_enter();
417 
418 	psoc = wlan_pdev_get_psoc(pdev);
419 
420 	if (!psoc) {
421 		direct_buf_rx_err("psoc is null");
422 		return QDF_STATUS_E_FAILURE;
423 	}
424 
425 	dbr_psoc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc,
426 				WLAN_TARGET_IF_COMP_DIRECT_BUF_RX);
427 
428 	if (dbr_psoc_obj == NULL) {
429 		direct_buf_rx_err("dir buf rx psoc object is null");
430 		return QDF_STATUS_E_FAILURE;
431 	}
432 
433 	if (dbr_psoc_obj->hal_soc == NULL ||
434 	    dbr_psoc_obj->osdev == NULL) {
435 		direct_buf_rx_err("dir buf rx target attach failed");
436 		return QDF_STATUS_E_FAILURE;
437 	}
438 
439 	max_entries = hal_srng_max_entries(dbr_psoc_obj->hal_soc,
440 					   DIR_BUF_RX_DMA_SRC);
441 	entry_size = hal_srng_get_entrysize(dbr_psoc_obj->hal_soc,
442 					    DIR_BUF_RX_DMA_SRC);
443 	direct_buf_rx_info("Max Entries = %d", max_entries);
444 	direct_buf_rx_info("Entry Size = %d", entry_size);
445 
446 	status = populate_dbr_cap_mod_param(pdev, mod_param);
447 	if (QDF_IS_STATUS_ERROR(status)) {
448 		direct_buf_rx_err("Module cap population failed");
449 		return QDF_STATUS_E_FAILURE;
450 	}
451 
452 	dbr_ring_cap = mod_param->dbr_ring_cap;
453 	dbr_ring_cfg = mod_param->dbr_ring_cfg;
454 	num_entries = dbr_ring_cap->ring_elems_min > max_entries ?
455 			max_entries : dbr_ring_cap->ring_elems_min;
456 	direct_buf_rx_info("Num entries = %d", num_entries);
457 	dbr_ring_cfg->num_ptr = num_entries;
458 	mod_param->dbr_buf_pool = qdf_mem_malloc(num_entries * sizeof(
459 				struct direct_buf_rx_buf_info));
460 	if (!mod_param->dbr_buf_pool) {
461 		direct_buf_rx_err("dir buf rx buf pool alloc failed");
462 		return QDF_STATUS_E_NOMEM;
463 	}
464 
465 	ring_alloc_size = (num_entries * entry_size) + DBR_RING_BASE_ALIGN - 1;
466 	dbr_ring_cfg->ring_alloc_size = ring_alloc_size;
467 	direct_buf_rx_info("dbr_psoc_obj %pK", dbr_psoc_obj);
468 	dbr_ring_cfg->base_vaddr_unaligned = qdf_mem_alloc_consistent(
469 		dbr_psoc_obj->osdev, dbr_psoc_obj->osdev->dev, ring_alloc_size,
470 		&paddr);
471 	direct_buf_rx_info("vaddr aligned allocated");
472 	dbr_ring_cfg->base_paddr_unaligned = paddr;
473 	if (!dbr_ring_cfg->base_vaddr_unaligned) {
474 		direct_buf_rx_err("dir buf rx vaddr alloc failed");
475 		qdf_mem_free(mod_param->dbr_buf_pool);
476 		return QDF_STATUS_E_NOMEM;
477 	}
478 
479 	/* Alignment is defined to 8 for now. Will be advertised by FW */
480 	dbr_ring_cfg->base_vaddr_aligned = (void *)(uintptr_t)qdf_roundup(
481 		(uint64_t)(uintptr_t)dbr_ring_cfg->base_vaddr_unaligned,
482 		DBR_RING_BASE_ALIGN);
483 	ring_params.ring_base_vaddr = dbr_ring_cfg->base_vaddr_aligned;
484 	dbr_ring_cfg->base_paddr_aligned = qdf_roundup(
485 		(uint64_t)dbr_ring_cfg->base_paddr_unaligned,
486 		DBR_RING_BASE_ALIGN);
487 	ring_params.ring_base_paddr =
488 		(qdf_dma_addr_t)dbr_ring_cfg->base_paddr_aligned;
489 	ring_params.num_entries = num_entries;
490 	srng = hal_srng_setup(dbr_psoc_obj->hal_soc, DIR_BUF_RX_DMA_SRC, 0,
491 			      wlan_objmgr_pdev_get_pdev_id(pdev), &ring_params);
492 
493 	if (!srng) {
494 		direct_buf_rx_err("srng setup failed");
495 		qdf_mem_free(mod_param->dbr_buf_pool);
496 		qdf_mem_free_consistent(dbr_psoc_obj->osdev,
497 					dbr_psoc_obj->osdev->dev,
498 					ring_alloc_size,
499 					dbr_ring_cfg->base_vaddr_unaligned,
500 			(qdf_dma_addr_t)dbr_ring_cfg->base_paddr_unaligned, 0);
501 		return QDF_STATUS_E_FAILURE;
502 	}
503 	dbr_ring_cfg->srng = srng;
504 	dbr_ring_cfg->tail_idx_addr =
505 		hal_srng_get_tp_addr(dbr_psoc_obj->hal_soc, srng);
506 	dbr_ring_cfg->head_idx_addr =
507 		hal_srng_get_hp_addr(dbr_psoc_obj->hal_soc, srng);
508 	dbr_ring_cfg->buf_size = dbr_ring_cap->min_buf_size;
509 
510 	return target_if_dbr_fill_ring(pdev, mod_param);
511 }
512 
513 static QDF_STATUS target_if_dbr_init_srng(struct wlan_objmgr_pdev *pdev,
514 			struct direct_buf_rx_module_param *mod_param)
515 {
516 	QDF_STATUS status;
517 
518 	direct_buf_rx_info("Init DBR srng");
519 
520 	if (!mod_param) {
521 		direct_buf_rx_err("dir buf rx module param is null");
522 		return QDF_STATUS_E_INVAL;
523 	}
524 
525 	mod_param->dbr_ring_cap = qdf_mem_malloc(sizeof(
526 					struct direct_buf_rx_ring_cap));
527 
528 	if (!mod_param->dbr_ring_cap) {
529 		direct_buf_rx_err("Ring cap alloc failed");
530 		return QDF_STATUS_E_NOMEM;
531 	}
532 
533 	/* Allocate memory for DBR Ring Config */
534 	mod_param->dbr_ring_cfg = qdf_mem_malloc(sizeof(
535 					struct direct_buf_rx_ring_cfg));
536 
537 	if (!mod_param->dbr_ring_cfg) {
538 		direct_buf_rx_err("Ring config alloc failed");
539 		qdf_mem_free(mod_param->dbr_ring_cap);
540 		return QDF_STATUS_E_NOMEM;
541 	}
542 
543 	status = target_if_dbr_init_ring(pdev, mod_param);
544 
545 	if (QDF_IS_STATUS_ERROR(status)) {
546 		direct_buf_rx_err("DBR ring init failed");
547 		qdf_mem_free(mod_param->dbr_ring_cfg);
548 		qdf_mem_free(mod_param->dbr_ring_cap);
549 		return QDF_STATUS_E_FAILURE;
550 	}
551 
552 	return QDF_STATUS_SUCCESS;
553 }
554 
555 static QDF_STATUS target_if_dbr_cfg_tgt(struct wlan_objmgr_pdev *pdev,
556 			struct direct_buf_rx_module_param *mod_param)
557 {
558 	QDF_STATUS status;
559 	struct wlan_objmgr_psoc *psoc;
560 	void *wmi_hdl;
561 	struct direct_buf_rx_cfg_req dbr_cfg_req = {0};
562 	struct direct_buf_rx_ring_cfg *dbr_ring_cfg;
563 	struct direct_buf_rx_ring_cap *dbr_ring_cap;
564 
565 	direct_buf_rx_enter();
566 
567 	psoc = wlan_pdev_get_psoc(pdev);
568 	if (!psoc) {
569 		direct_buf_rx_err("psoc is null");
570 		return QDF_STATUS_E_FAILURE;
571 	}
572 
573 	dbr_ring_cfg = mod_param->dbr_ring_cfg;
574 	dbr_ring_cap = mod_param->dbr_ring_cap;
575 	wmi_hdl = ucfg_get_pdev_wmi_handle(pdev);
576 	if (!wmi_hdl) {
577 		direct_buf_rx_err("WMI handle null. Can't send WMI CMD");
578 		return QDF_STATUS_E_INVAL;
579 	}
580 
581 	direct_buf_rx_debug("Sending DBR Ring CFG to target");
582 	dbr_cfg_req.pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
583 	/* Module ID numbering starts from 1 in FW. need to fix it */
584 	dbr_cfg_req.mod_id = mod_param->mod_id;
585 	dbr_cfg_req.base_paddr_lo = (uint64_t)dbr_ring_cfg->base_paddr_aligned
586 						& 0xFFFFFFFF;
587 	dbr_cfg_req.base_paddr_hi = (uint64_t)dbr_ring_cfg->base_paddr_aligned
588 						& 0xFFFFFFFF00000000;
589 	dbr_cfg_req.head_idx_paddr_lo = (uint64_t)dbr_ring_cfg->head_idx_addr
590 						& 0xFFFFFFFF;
591 	dbr_cfg_req.head_idx_paddr_hi = (uint64_t)dbr_ring_cfg->head_idx_addr
592 						& 0xFFFFFFFF00000000;
593 	dbr_cfg_req.tail_idx_paddr_lo = (uint64_t)dbr_ring_cfg->tail_idx_addr
594 						& 0xFFFFFFFF;
595 	dbr_cfg_req.tail_idx_paddr_hi = (uint64_t)dbr_ring_cfg->tail_idx_addr
596 						& 0xFFFFFFFF00000000;
597 	dbr_cfg_req.num_elems = dbr_ring_cap->ring_elems_min;
598 	dbr_cfg_req.buf_size = dbr_ring_cap->min_buf_size;
599 	dbr_cfg_req.num_resp_per_event = DBR_NUM_RESP_PER_EVENT;
600 	dbr_cfg_req.event_timeout_ms = DBR_EVENT_TIMEOUT_IN_MS;
601 	direct_buf_rx_info("pdev id %d mod id %d base addr lo %x\n"
602 			   "base addr hi %x head idx addr lo %x\n"
603 			   "head idx addr hi %x tail idx addr lo %x\n"
604 			   "tail idx addr hi %x num ptr %d\n"
605 			   "num resp %d event timeout %d\n",
606 			   dbr_cfg_req.pdev_id, dbr_cfg_req.mod_id,
607 			   dbr_cfg_req.base_paddr_lo, dbr_cfg_req.base_paddr_hi,
608 			   dbr_cfg_req.head_idx_paddr_lo,
609 			   dbr_cfg_req.head_idx_paddr_hi,
610 			   dbr_cfg_req.tail_idx_paddr_lo,
611 			   dbr_cfg_req.tail_idx_paddr_hi,
612 			   dbr_cfg_req.num_elems,
613 			   dbr_cfg_req.num_resp_per_event,
614 			   dbr_cfg_req.event_timeout_ms);
615 	status = wmi_unified_dbr_ring_cfg(wmi_hdl, &dbr_cfg_req);
616 
617 	return status;
618 }
619 
620 static QDF_STATUS target_if_init_dbr_ring(struct wlan_objmgr_pdev *pdev,
621 				struct direct_buf_rx_pdev_obj *dbr_pdev_obj,
622 				enum DBR_MODULE mod_id)
623 {
624 	QDF_STATUS status = QDF_STATUS_SUCCESS;
625 	struct direct_buf_rx_module_param *mod_param;
626 
627 	direct_buf_rx_info("Init DBR ring for module %d", mod_id);
628 
629 	if (!dbr_pdev_obj) {
630 		direct_buf_rx_err("dir buf rx object is null");
631 		return QDF_STATUS_E_INVAL;
632 	}
633 
634 	mod_param = &(dbr_pdev_obj->dbr_mod_param[mod_id]);
635 
636 	if (!mod_param) {
637 		direct_buf_rx_err("dir buf rx module param is null");
638 		return QDF_STATUS_E_FAILURE;
639 	}
640 
641 	direct_buf_rx_info("mod_param %pK", mod_param);
642 
643 	mod_param->mod_id = mod_id;
644 
645 	/* Initialize DMA ring now */
646 	status = target_if_dbr_init_srng(pdev, mod_param);
647 	if (QDF_IS_STATUS_ERROR(status)) {
648 		direct_buf_rx_err("DBR ring init failed %d", status);
649 		return status;
650 	}
651 
652 	/* Send CFG request command to firmware */
653 	status = target_if_dbr_cfg_tgt(pdev, mod_param);
654 	if (QDF_IS_STATUS_ERROR(status)) {
655 		direct_buf_rx_err("DBR config to target failed %d", status);
656 		goto dbr_srng_init_failed;
657 	}
658 
659 	return QDF_STATUS_SUCCESS;
660 
661 dbr_srng_init_failed:
662 	target_if_deinit_dbr_ring(pdev, dbr_pdev_obj, mod_id);
663 	return status;
664 }
665 
666 QDF_STATUS target_if_direct_buf_rx_module_register(
667 			struct wlan_objmgr_pdev *pdev, uint8_t mod_id,
668 			int (*dbr_rsp_handler)(struct wlan_objmgr_pdev *pdev,
669 				struct direct_buf_rx_data *dbr_data))
670 {
671 	QDF_STATUS status;
672 	struct direct_buf_rx_pdev_obj *dbr_pdev_obj;
673 
674 	if (pdev == NULL) {
675 		direct_buf_rx_err("pdev context passed is null");
676 		return QDF_STATUS_E_INVAL;
677 	}
678 
679 	if (dbr_rsp_handler == NULL) {
680 		direct_buf_rx_err("Response handler is null");
681 		return QDF_STATUS_E_INVAL;
682 	}
683 
684 	if (mod_id >= DBR_MODULE_MAX) {
685 		direct_buf_rx_err("Invalid module id");
686 		return QDF_STATUS_E_INVAL;
687 	}
688 
689 	dbr_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj(pdev,
690 				WLAN_TARGET_IF_COMP_DIRECT_BUF_RX);
691 
692 	if (dbr_pdev_obj == NULL) {
693 		direct_buf_rx_err("dir buf rx object is null");
694 		return QDF_STATUS_E_FAILURE;
695 	}
696 	direct_buf_rx_info("Dbr pdev obj %pK", dbr_pdev_obj);
697 
698 	dbr_pdev_obj->dbr_mod_param[mod_id].dbr_rsp_handler =
699 			dbr_rsp_handler;
700 
701 	status = target_if_init_dbr_ring(pdev, dbr_pdev_obj,
702 					 (enum DBR_MODULE)mod_id);
703 
704 	return status;
705 }
706 
707 static void *target_if_dbr_vaddr_lookup(
708 			struct direct_buf_rx_module_param *mod_param,
709 			qdf_dma_addr_t paddr, uint32_t cookie)
710 {
711 	struct direct_buf_rx_buf_info *dbr_buf_pool;
712 
713 	dbr_buf_pool = mod_param->dbr_buf_pool;
714 
715 	if (dbr_buf_pool[cookie].paddr == paddr) {
716 		return dbr_buf_pool[cookie].vaddr +
717 				dbr_buf_pool[cookie].offset;
718 	}
719 
720 	direct_buf_rx_err("Incorrect paddr found on cookie slot");
721 	return NULL;
722 }
723 
724 static QDF_STATUS target_if_get_dbr_data(struct wlan_objmgr_pdev *pdev,
725 			struct direct_buf_rx_module_param *mod_param,
726 			struct direct_buf_rx_rsp *dbr_rsp,
727 			struct direct_buf_rx_data *dbr_data,
728 			uint8_t idx, uint32_t *cookie)
729 {
730 	qdf_dma_addr_t paddr = 0;
731 	uint32_t addr_hi;
732 	struct direct_buf_rx_psoc_obj *dbr_psoc_obj;
733 	struct direct_buf_rx_ring_cap *dbr_ring_cap;
734 	struct wlan_objmgr_psoc *psoc;
735 
736 	psoc = wlan_pdev_get_psoc(pdev);
737 	if (!psoc) {
738 		direct_buf_rx_err("psoc is null");
739 		return QDF_STATUS_E_FAILURE;
740 	}
741 
742 	dbr_psoc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc,
743 				WLAN_TARGET_IF_COMP_DIRECT_BUF_RX);
744 
745 	if (dbr_psoc_obj == NULL) {
746 		direct_buf_rx_err("dir buf rx psoc object is null");
747 		return QDF_STATUS_E_FAILURE;
748 	}
749 
750 	dbr_ring_cap = mod_param->dbr_ring_cap;
751 	addr_hi = (uint64_t)WMI_HOST_DBR_DATA_ADDR_HI_GET(
752 				dbr_rsp->dbr_entries[idx].paddr_hi);
753 	paddr = (qdf_dma_addr_t)((uint64_t)addr_hi << 32 |
754 				  dbr_rsp->dbr_entries[idx].paddr_lo);
755 	*cookie = WMI_HOST_DBR_DATA_ADDR_HI_HOST_DATA_GET(
756 				dbr_rsp->dbr_entries[idx].paddr_hi);
757 	direct_buf_rx_info("Cookie = %d", *cookie);
758 	dbr_data->vaddr = target_if_dbr_vaddr_lookup(mod_param, paddr, *cookie);
759 	direct_buf_rx_info("Vaddr look up = %x", dbr_data->vaddr);
760 	dbr_data->dbr_len = dbr_rsp->dbr_entries[idx].len;
761 	qdf_mem_unmap_nbytes_single(dbr_psoc_obj->osdev, (qdf_dma_addr_t)paddr,
762 				    QDF_DMA_FROM_DEVICE,
763 				    dbr_ring_cap->min_buf_size);
764 
765 	return QDF_STATUS_SUCCESS;
766 }
767 
768 static int target_if_direct_buf_rx_rsp_event_handler(ol_scn_t scn,
769 						uint8_t *data_buf,
770 						uint32_t data_len)
771 {
772 	int ret;
773 	uint8_t i = 0;
774 	QDF_STATUS status;
775 	uint32_t cookie = 0;
776 	struct direct_buf_rx_rsp dbr_rsp = {0};
777 	struct direct_buf_rx_data dbr_data = {0};
778 	struct wlan_objmgr_psoc *psoc;
779 	struct wlan_objmgr_pdev *pdev;
780 	struct direct_buf_rx_buf_info *dbr_buf_pool;
781 	struct direct_buf_rx_pdev_obj *dbr_pdev_obj;
782 	struct direct_buf_rx_module_param *mod_param;
783 
784 	direct_buf_rx_enter();
785 
786 	psoc = target_if_get_psoc_from_scn_hdl(scn);
787 	if (!psoc) {
788 		direct_buf_rx_err("psoc is null");
789 		return QDF_STATUS_E_FAILURE;
790 	}
791 
792 	if (wmi_extract_dbr_buf_release_fixed(GET_WMI_HDL_FROM_PSOC(psoc),
793 			data_buf, &dbr_rsp) != QDF_STATUS_SUCCESS) {
794 		direct_buf_rx_err("unable to extract DBR rsp fixed param");
795 		return QDF_STATUS_E_FAILURE;
796 	}
797 
798 	direct_buf_rx_info("Num buf release entry = %d",
799 			   dbr_rsp.num_buf_release_entry);
800 
801 	pdev = wlan_objmgr_get_pdev_by_id(psoc, dbr_rsp.pdev_id,
802 					  WLAN_DIRECT_BUF_RX_ID);
803 	if (!pdev) {
804 		direct_buf_rx_err("pdev is null");
805 		wlan_objmgr_pdev_release_ref(pdev, WLAN_DIRECT_BUF_RX_ID);
806 		return QDF_STATUS_E_INVAL;
807 	}
808 
809 	dbr_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj(pdev,
810 				WLAN_TARGET_IF_COMP_DIRECT_BUF_RX);
811 
812 	if (dbr_pdev_obj == NULL) {
813 		direct_buf_rx_err("dir buf rx object is null");
814 		wlan_objmgr_pdev_release_ref(pdev, WLAN_DIRECT_BUF_RX_ID);
815 		return QDF_STATUS_E_FAILURE;
816 	}
817 
818 	mod_param = &(dbr_pdev_obj->dbr_mod_param[dbr_rsp.mod_id]);
819 
820 	if (!mod_param) {
821 		direct_buf_rx_err("dir buf rx module param is null");
822 		wlan_objmgr_pdev_release_ref(pdev, WLAN_DIRECT_BUF_RX_ID);
823 		return QDF_STATUS_E_FAILURE;
824 	}
825 
826 	dbr_buf_pool = mod_param->dbr_buf_pool;
827 	dbr_rsp.dbr_entries = qdf_mem_malloc(dbr_rsp.num_buf_release_entry *
828 					sizeof(struct direct_buf_rx_entry));
829 
830 	for (i = 0; i < dbr_rsp.num_buf_release_entry; i++) {
831 		if (wmi_extract_dbr_buf_release_entry(
832 			GET_WMI_HDL_FROM_PSOC(psoc), data_buf, i,
833 			&dbr_rsp.dbr_entries[i]) != QDF_STATUS_SUCCESS) {
834 			direct_buf_rx_err("Unable to extract DBR buf entry %d",
835 					  i+1);
836 			wlan_objmgr_pdev_release_ref(pdev,
837 						     WLAN_DIRECT_BUF_RX_ID);
838 			return QDF_STATUS_E_FAILURE;
839 		}
840 		status = target_if_get_dbr_data(pdev, mod_param, &dbr_rsp,
841 						&dbr_data, i, &cookie);
842 
843 		if (QDF_IS_STATUS_ERROR(status)) {
844 			direct_buf_rx_err("DBR data get failed");
845 			wlan_objmgr_pdev_release_ref(pdev,
846 						     WLAN_DIRECT_BUF_RX_ID);
847 			return QDF_STATUS_E_FAILURE;
848 		}
849 		ret = mod_param->dbr_rsp_handler(pdev, &dbr_data);
850 		status = target_if_dbr_replenish_ring(pdev, mod_param,
851 						      dbr_data.vaddr, cookie);
852 		if (QDF_IS_STATUS_ERROR(status)) {
853 			direct_buf_rx_err("dir buf rx ring replenish failed");
854 			wlan_objmgr_pdev_release_ref(pdev,
855 						     WLAN_DIRECT_BUF_RX_ID);
856 			return QDF_STATUS_E_FAILURE;
857 		}
858 	}
859 
860 	wlan_objmgr_pdev_release_ref(pdev, WLAN_DIRECT_BUF_RX_ID);
861 
862 	return ret;
863 }
864 
865 static QDF_STATUS target_if_dbr_empty_ring(struct wlan_objmgr_pdev *pdev,
866 			struct direct_buf_rx_psoc_obj *dbr_psoc_obj,
867 			struct direct_buf_rx_module_param *mod_param)
868 {
869 	uint8_t idx;
870 	struct direct_buf_rx_ring_cfg *dbr_ring_cfg;
871 	struct direct_buf_rx_ring_cap *dbr_ring_cap;
872 	struct direct_buf_rx_buf_info *dbr_buf_pool;
873 
874 	direct_buf_rx_enter();
875 	dbr_ring_cfg = mod_param->dbr_ring_cfg;
876 	dbr_ring_cap = mod_param->dbr_ring_cap;
877 	dbr_buf_pool = mod_param->dbr_buf_pool;
878 
879 	direct_buf_rx_info("dbr_ring_cfg %pK, dbr_ring_cap %pK dbr_buf_pool %pK",
880 			   dbr_ring_cfg, dbr_ring_cap, dbr_buf_pool);
881 
882 	for (idx = 0; idx < dbr_ring_cfg->num_ptr - 1; idx++) {
883 		direct_buf_rx_info("dbr buf pool unmap and free for ptr %d",
884 				   idx);
885 		qdf_mem_unmap_nbytes_single(dbr_psoc_obj->osdev,
886 			(qdf_dma_addr_t)dbr_buf_pool[idx].paddr,
887 			QDF_DMA_FROM_DEVICE,
888 			dbr_ring_cap->min_buf_size);
889 		qdf_mem_free(dbr_buf_pool[idx].vaddr);
890 	}
891 
892 	return QDF_STATUS_SUCCESS;
893 }
894 
895 static QDF_STATUS target_if_dbr_deinit_ring(struct wlan_objmgr_pdev *pdev,
896 			struct direct_buf_rx_module_param *mod_param)
897 {
898 	struct wlan_objmgr_psoc *psoc;
899 	struct direct_buf_rx_psoc_obj *dbr_psoc_obj;
900 	struct direct_buf_rx_ring_cfg *dbr_ring_cfg;
901 
902 	direct_buf_rx_enter();
903 	psoc = wlan_pdev_get_psoc(pdev);
904 	if (!psoc) {
905 		direct_buf_rx_err("psoc is null");
906 		return QDF_STATUS_E_FAILURE;
907 	}
908 
909 	dbr_psoc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc,
910 				WLAN_TARGET_IF_COMP_DIRECT_BUF_RX);
911 
912 	if (dbr_psoc_obj == NULL) {
913 		direct_buf_rx_err("dir buf rx psoc object is null");
914 		return QDF_STATUS_E_FAILURE;
915 	}
916 	direct_buf_rx_info("dbr_psoc_obj %pK", dbr_psoc_obj);
917 
918 	dbr_ring_cfg = mod_param->dbr_ring_cfg;
919 	if (dbr_ring_cfg) {
920 		target_if_dbr_empty_ring(pdev, dbr_psoc_obj, mod_param);
921 		hal_srng_cleanup(dbr_psoc_obj->hal_soc, dbr_ring_cfg->srng);
922 		qdf_mem_free_consistent(dbr_psoc_obj->osdev,
923 					dbr_psoc_obj->osdev->dev,
924 					dbr_ring_cfg->ring_alloc_size,
925 					dbr_ring_cfg->base_vaddr_unaligned,
926 			(qdf_dma_addr_t)dbr_ring_cfg->base_paddr_unaligned, 0);
927 	}
928 
929 	return QDF_STATUS_SUCCESS;
930 }
931 
932 static QDF_STATUS target_if_dbr_deinit_srng(
933 			struct wlan_objmgr_pdev *pdev,
934 			struct direct_buf_rx_module_param *mod_param)
935 {
936 	struct direct_buf_rx_buf_info *dbr_buf_pool;
937 
938 	direct_buf_rx_enter();
939 	dbr_buf_pool = mod_param->dbr_buf_pool;
940 	direct_buf_rx_info("dbr buf pool %pK", dbr_buf_pool);
941 	target_if_dbr_deinit_ring(pdev, mod_param);
942 	qdf_mem_free(dbr_buf_pool);
943 	dbr_buf_pool = NULL;
944 
945 	return QDF_STATUS_SUCCESS;
946 }
947 
948 QDF_STATUS target_if_deinit_dbr_ring(struct wlan_objmgr_pdev *pdev,
949 			struct direct_buf_rx_pdev_obj *dbr_pdev_obj,
950 			enum DBR_MODULE mod_id)
951 {
952 	struct direct_buf_rx_module_param *mod_param;
953 	struct direct_buf_rx_ring_cap *dbr_ring_cap;
954 	QDF_STATUS status;
955 
956 	direct_buf_rx_enter();
957 	mod_param = &(dbr_pdev_obj->dbr_mod_param[mod_id]);
958 
959 	if (!mod_param) {
960 		direct_buf_rx_err("dir buf rx module param is null");
961 		return QDF_STATUS_E_FAILURE;
962 	}
963 	direct_buf_rx_info("mod_param %pK", mod_param);
964 
965 	dbr_ring_cap = mod_param->dbr_ring_cap;
966 	direct_buf_rx_info("dbr_ring_cap %pK", dbr_ring_cap);
967 	target_if_dbr_deinit_srng(pdev, mod_param);
968 	qdf_mem_free(dbr_ring_cap);
969 	dbr_ring_cap = NULL;
970 	qdf_mem_free(mod_param);
971 	mod_param = NULL;
972 
973 	return status;
974 }
975 
976 QDF_STATUS target_if_direct_buf_rx_register_events(
977 				struct wlan_objmgr_psoc *psoc)
978 {
979 	int ret;
980 
981 	if (!psoc || !GET_WMI_HDL_FROM_PSOC(psoc)) {
982 		direct_buf_rx_err("psoc or psoc->tgt_if_handle is null");
983 		return QDF_STATUS_E_INVAL;
984 	}
985 
986 	ret = wmi_unified_register_event_handler(GET_WMI_HDL_FROM_PSOC(psoc),
987 				wmi_dma_buf_release_event_id,
988 				target_if_direct_buf_rx_rsp_event_handler,
989 				WMI_RX_UMAC_CTX);
990 
991 	if (ret)
992 		direct_buf_rx_info("event handler not supported", ret);
993 
994 	return QDF_STATUS_SUCCESS;
995 }
996 
997 QDF_STATUS target_if_direct_buf_rx_unregister_events(
998 				struct wlan_objmgr_psoc *psoc)
999 {
1000 	if (!psoc || !GET_WMI_HDL_FROM_PSOC(psoc)) {
1001 		direct_buf_rx_err("psoc or psoc->tgt_if_handle is null");
1002 		return QDF_STATUS_E_INVAL;
1003 	}
1004 
1005 	wmi_unified_unregister_event_handler(GET_WMI_HDL_FROM_PSOC(psoc),
1006 					     wmi_dma_buf_release_event_id);
1007 
1008 	return QDF_STATUS_SUCCESS;
1009 }
1010