xref: /wlan-driver/qca-wifi-host-cmn/wbuff/src/wbuff.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1*5113495bSYour Name /*
2*5113495bSYour Name  * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
3*5113495bSYour Name  * Copyright (c) 2021, 2023 Qualcomm Innovation Center, Inc. All rights reserved.
4*5113495bSYour Name  *
5*5113495bSYour Name  * Permission to use, copy, modify, and/or distribute this software for
6*5113495bSYour Name  * any purpose with or without fee is hereby granted, provided that the
7*5113495bSYour Name  * above copyright notice and this permission notice appear in all
8*5113495bSYour Name  * copies.
9*5113495bSYour Name  *
10*5113495bSYour Name  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11*5113495bSYour Name  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12*5113495bSYour Name  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13*5113495bSYour Name  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14*5113495bSYour Name  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15*5113495bSYour Name  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16*5113495bSYour Name  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17*5113495bSYour Name  * PERFORMANCE OF THIS SOFTWARE.
18*5113495bSYour Name  */
19*5113495bSYour Name 
20*5113495bSYour Name /**
21*5113495bSYour Name  * DOC: wbuff.c
22*5113495bSYour Name  * wbuff buffer management APIs
23*5113495bSYour Name  */
24*5113495bSYour Name 
25*5113495bSYour Name #include <wbuff.h>
26*5113495bSYour Name #include <linux/debugfs.h>
27*5113495bSYour Name #include <linux/seq_file.h>
28*5113495bSYour Name #include <qdf_debugfs.h>
29*5113495bSYour Name #include "i_wbuff.h"
30*5113495bSYour Name 
31*5113495bSYour Name /*
32*5113495bSYour Name  * Allocation holder array for all wbuff registered modules
33*5113495bSYour Name  */
34*5113495bSYour Name struct wbuff_holder wbuff;
35*5113495bSYour Name 
36*5113495bSYour Name /**
37*5113495bSYour Name  * wbuff_get_pool_slot_from_len() - get pool_id from length
38*5113495bSYour Name  * @mod: wbuff module reference
39*5113495bSYour Name  * @len: length of the buffer
40*5113495bSYour Name  *
41*5113495bSYour Name  * Return: pool_id
42*5113495bSYour Name  */
43*5113495bSYour Name static uint8_t
wbuff_get_pool_slot_from_len(struct wbuff_module * mod,uint16_t len)44*5113495bSYour Name wbuff_get_pool_slot_from_len(struct wbuff_module *mod, uint16_t len)
45*5113495bSYour Name {
46*5113495bSYour Name 	struct wbuff_pool *pool;
47*5113495bSYour Name 	uint16_t prev_buf_size = 0;
48*5113495bSYour Name 	int i;
49*5113495bSYour Name 
50*5113495bSYour Name 	for (i = 0; i < WBUFF_MAX_POOLS; i++) {
51*5113495bSYour Name 		pool = &mod->wbuff_pool[i];
52*5113495bSYour Name 
53*5113495bSYour Name 		if (!pool->initialized)
54*5113495bSYour Name 			continue;
55*5113495bSYour Name 
56*5113495bSYour Name 		if ((len > prev_buf_size) && (len <= pool->buffer_size))
57*5113495bSYour Name 			break;
58*5113495bSYour Name 
59*5113495bSYour Name 		prev_buf_size = mod->wbuff_pool[i].buffer_size;
60*5113495bSYour Name 	}
61*5113495bSYour Name 
62*5113495bSYour Name 	return i;
63*5113495bSYour Name }
64*5113495bSYour Name 
65*5113495bSYour Name /**
66*5113495bSYour Name  * wbuff_is_valid_alloc_req() - validate alloc  request
67*5113495bSYour Name  * @req: allocation request from registered module
68*5113495bSYour Name  * @num: number of pools required
69*5113495bSYour Name  *
70*5113495bSYour Name  * Return: true if valid wbuff_alloc_request
71*5113495bSYour Name  *         false if invalid wbuff_alloc_request
72*5113495bSYour Name  */
73*5113495bSYour Name static bool
wbuff_is_valid_alloc_req(struct wbuff_alloc_request * req,uint8_t num)74*5113495bSYour Name wbuff_is_valid_alloc_req(struct wbuff_alloc_request *req, uint8_t num)
75*5113495bSYour Name {
76*5113495bSYour Name 	int i;
77*5113495bSYour Name 
78*5113495bSYour Name 	for (i = 0; i < num; i++) {
79*5113495bSYour Name 		if (req[i].pool_id >= WBUFF_MAX_POOLS)
80*5113495bSYour Name 			return false;
81*5113495bSYour Name 	}
82*5113495bSYour Name 
83*5113495bSYour Name 	return true;
84*5113495bSYour Name }
85*5113495bSYour Name 
86*5113495bSYour Name /**
87*5113495bSYour Name  * wbuff_prepare_nbuf() - allocate nbuf
88*5113495bSYour Name  * @module_id: module ID
89*5113495bSYour Name  * @pool_id: pool ID
90*5113495bSYour Name  * @len: length of the buffer
91*5113495bSYour Name  * @reserve: nbuf headroom to start with
92*5113495bSYour Name  * @align: alignment for the nbuf
93*5113495bSYour Name  *
94*5113495bSYour Name  * Return: nbuf if success
95*5113495bSYour Name  *         NULL if failure
96*5113495bSYour Name  */
wbuff_prepare_nbuf(uint8_t module_id,uint8_t pool_id,uint32_t len,int reserve,int align)97*5113495bSYour Name static qdf_nbuf_t wbuff_prepare_nbuf(uint8_t module_id, uint8_t pool_id,
98*5113495bSYour Name 				     uint32_t len, int reserve, int align)
99*5113495bSYour Name {
100*5113495bSYour Name 	qdf_nbuf_t buf;
101*5113495bSYour Name 	unsigned long dev_scratch = 0;
102*5113495bSYour Name 	struct wbuff_module *mod = &wbuff.mod[module_id];
103*5113495bSYour Name 	struct wbuff_pool *wbuff_pool = &mod->wbuff_pool[pool_id];
104*5113495bSYour Name 
105*5113495bSYour Name 	buf = qdf_nbuf_page_frag_alloc(NULL, len, reserve, align,
106*5113495bSYour Name 				       &wbuff.pf_cache);
107*5113495bSYour Name 	if (!buf)
108*5113495bSYour Name 		return NULL;
109*5113495bSYour Name 	dev_scratch = module_id;
110*5113495bSYour Name 	dev_scratch <<= WBUFF_MODULE_ID_SHIFT;
111*5113495bSYour Name 	dev_scratch |= ((pool_id << WBUFF_POOL_ID_SHIFT) | 1);
112*5113495bSYour Name 	qdf_nbuf_set_dev_scratch(buf, dev_scratch);
113*5113495bSYour Name 
114*5113495bSYour Name 	wbuff_pool->mem_alloc += qdf_nbuf_get_allocsize(buf);
115*5113495bSYour Name 
116*5113495bSYour Name 	return buf;
117*5113495bSYour Name }
118*5113495bSYour Name 
119*5113495bSYour Name /**
120*5113495bSYour Name  * wbuff_is_valid_handle() - validate wbuff handle
121*5113495bSYour Name  * @handle: wbuff handle passed by module
122*5113495bSYour Name  *
123*5113495bSYour Name  * Return: true - valid wbuff_handle
124*5113495bSYour Name  *         false - invalid wbuff_handle
125*5113495bSYour Name  */
wbuff_is_valid_handle(struct wbuff_handle * handle)126*5113495bSYour Name static bool wbuff_is_valid_handle(struct wbuff_handle *handle)
127*5113495bSYour Name {
128*5113495bSYour Name 	if ((handle) && (handle->id < WBUFF_MAX_MODULES) &&
129*5113495bSYour Name 	    (wbuff.mod[handle->id].registered))
130*5113495bSYour Name 		return true;
131*5113495bSYour Name 
132*5113495bSYour Name 	return false;
133*5113495bSYour Name }
134*5113495bSYour Name 
wbuff_get_mod_name(enum wbuff_module_id module_id)135*5113495bSYour Name static char *wbuff_get_mod_name(enum wbuff_module_id module_id)
136*5113495bSYour Name {
137*5113495bSYour Name 	char *str;
138*5113495bSYour Name 
139*5113495bSYour Name 	switch (module_id) {
140*5113495bSYour Name 	case WBUFF_MODULE_WMI_TX:
141*5113495bSYour Name 		str = "WBUFF_MODULE_WMI_TX";
142*5113495bSYour Name 		break;
143*5113495bSYour Name 	case WBUFF_MODULE_CE_RX:
144*5113495bSYour Name 		str = "WBUFF_MODULE_CE_RX";
145*5113495bSYour Name 		break;
146*5113495bSYour Name 	default:
147*5113495bSYour Name 		str = "Invalid Module ID";
148*5113495bSYour Name 		break;
149*5113495bSYour Name 	}
150*5113495bSYour Name 
151*5113495bSYour Name 	return str;
152*5113495bSYour Name }
153*5113495bSYour Name 
wbuff_debugfs_print(qdf_debugfs_file_t file,const char * fmt,...)154*5113495bSYour Name static void wbuff_debugfs_print(qdf_debugfs_file_t file, const char *fmt, ...)
155*5113495bSYour Name {
156*5113495bSYour Name 	va_list args;
157*5113495bSYour Name 
158*5113495bSYour Name 	va_start(args, fmt);
159*5113495bSYour Name 	seq_vprintf(file, fmt, args);
160*5113495bSYour Name 	va_end(args);
161*5113495bSYour Name }
162*5113495bSYour Name 
wbuff_stats_debugfs_show(qdf_debugfs_file_t file,void * data)163*5113495bSYour Name static int wbuff_stats_debugfs_show(qdf_debugfs_file_t file, void *data)
164*5113495bSYour Name {
165*5113495bSYour Name 	struct wbuff_module *mod;
166*5113495bSYour Name 	struct wbuff_pool *wbuff_pool;
167*5113495bSYour Name 	int i, j;
168*5113495bSYour Name 
169*5113495bSYour Name 	wbuff_debugfs_print(file, "WBUFF POOL STATS:\n");
170*5113495bSYour Name 	wbuff_debugfs_print(file, "=================\n");
171*5113495bSYour Name 
172*5113495bSYour Name 	for (i = 0; i < WBUFF_MAX_MODULES; i++) {
173*5113495bSYour Name 		mod = &wbuff.mod[i];
174*5113495bSYour Name 
175*5113495bSYour Name 		if (!mod->registered)
176*5113495bSYour Name 			continue;
177*5113495bSYour Name 
178*5113495bSYour Name 		wbuff_debugfs_print(file, "Module (%d) : %s\n", i,
179*5113495bSYour Name 				    wbuff_get_mod_name(i));
180*5113495bSYour Name 
181*5113495bSYour Name 		wbuff_debugfs_print(file, "%s %25s %20s %20s\n", "Pool ID",
182*5113495bSYour Name 				    "Mem Allocated (In Bytes)",
183*5113495bSYour Name 				    "Wbuff Success Count",
184*5113495bSYour Name 				    "Wbuff Fail Count");
185*5113495bSYour Name 
186*5113495bSYour Name 		for (j = 0; j < WBUFF_MAX_POOLS; j++) {
187*5113495bSYour Name 			wbuff_pool = &mod->wbuff_pool[j];
188*5113495bSYour Name 
189*5113495bSYour Name 			if (!wbuff_pool->initialized)
190*5113495bSYour Name 				continue;
191*5113495bSYour Name 
192*5113495bSYour Name 			wbuff_debugfs_print(file, "%d %30llu %20llu %20llu\n",
193*5113495bSYour Name 					    j, wbuff_pool->mem_alloc,
194*5113495bSYour Name 					    wbuff_pool->alloc_success,
195*5113495bSYour Name 					    wbuff_pool->alloc_fail);
196*5113495bSYour Name 		}
197*5113495bSYour Name 		wbuff_debugfs_print(file, "\n");
198*5113495bSYour Name 	}
199*5113495bSYour Name 
200*5113495bSYour Name 	return 0;
201*5113495bSYour Name }
202*5113495bSYour Name 
wbuff_stats_debugfs_open(struct inode * inode,struct file * file)203*5113495bSYour Name static int wbuff_stats_debugfs_open(struct inode *inode, struct file *file)
204*5113495bSYour Name {
205*5113495bSYour Name 	return single_open(file, wbuff_stats_debugfs_show,
206*5113495bSYour Name 			   inode->i_private);
207*5113495bSYour Name }
208*5113495bSYour Name 
209*5113495bSYour Name static const struct file_operations wbuff_stats_fops = {
210*5113495bSYour Name 	.owner          = THIS_MODULE,
211*5113495bSYour Name 	.open           = wbuff_stats_debugfs_open,
212*5113495bSYour Name 	.release        = single_release,
213*5113495bSYour Name 	.read           = seq_read,
214*5113495bSYour Name 	.llseek         = seq_lseek,
215*5113495bSYour Name };
216*5113495bSYour Name 
wbuff_debugfs_init(void)217*5113495bSYour Name static QDF_STATUS wbuff_debugfs_init(void)
218*5113495bSYour Name {
219*5113495bSYour Name 	wbuff.wbuff_debugfs_dir =
220*5113495bSYour Name 		qdf_debugfs_create_dir("wbuff", NULL);
221*5113495bSYour Name 
222*5113495bSYour Name 	if (!wbuff.wbuff_debugfs_dir)
223*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
224*5113495bSYour Name 
225*5113495bSYour Name 	wbuff.wbuff_stats_dentry =
226*5113495bSYour Name 		qdf_debugfs_create_entry("wbuff_stats", QDF_FILE_USR_READ,
227*5113495bSYour Name 					 wbuff.wbuff_debugfs_dir, NULL,
228*5113495bSYour Name 					 &wbuff_stats_fops);
229*5113495bSYour Name 	if (!wbuff.wbuff_stats_dentry)
230*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
231*5113495bSYour Name 
232*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
233*5113495bSYour Name }
234*5113495bSYour Name 
wbuff_debugfs_exit(void)235*5113495bSYour Name static void wbuff_debugfs_exit(void)
236*5113495bSYour Name {
237*5113495bSYour Name 	if (!wbuff.wbuff_debugfs_dir)
238*5113495bSYour Name 		return;
239*5113495bSYour Name 
240*5113495bSYour Name 	debugfs_remove_recursive(wbuff.wbuff_debugfs_dir);
241*5113495bSYour Name 	wbuff.wbuff_debugfs_dir = NULL;
242*5113495bSYour Name }
243*5113495bSYour Name 
wbuff_module_init(void)244*5113495bSYour Name QDF_STATUS wbuff_module_init(void)
245*5113495bSYour Name {
246*5113495bSYour Name 	struct wbuff_module *mod = NULL;
247*5113495bSYour Name 	uint8_t module_id = 0, pool_id = 0;
248*5113495bSYour Name 
249*5113495bSYour Name 	if (!qdf_nbuf_is_dev_scratch_supported()) {
250*5113495bSYour Name 		wbuff.initialized = false;
251*5113495bSYour Name 		return QDF_STATUS_E_NOSUPPORT;
252*5113495bSYour Name 	}
253*5113495bSYour Name 
254*5113495bSYour Name 	for (module_id = 0; module_id < WBUFF_MAX_MODULES; module_id++) {
255*5113495bSYour Name 		mod = &wbuff.mod[module_id];
256*5113495bSYour Name 		qdf_spinlock_create(&mod->lock);
257*5113495bSYour Name 		for (pool_id = 0; pool_id < WBUFF_MAX_POOLS; pool_id++)
258*5113495bSYour Name 			mod->wbuff_pool[pool_id].pool = NULL;
259*5113495bSYour Name 		mod->registered = false;
260*5113495bSYour Name 	}
261*5113495bSYour Name 
262*5113495bSYour Name 	wbuff_debugfs_init();
263*5113495bSYour Name 
264*5113495bSYour Name 	wbuff.initialized = true;
265*5113495bSYour Name 
266*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
267*5113495bSYour Name }
268*5113495bSYour Name 
wbuff_module_deinit(void)269*5113495bSYour Name QDF_STATUS wbuff_module_deinit(void)
270*5113495bSYour Name {
271*5113495bSYour Name 	struct wbuff_module *mod = NULL;
272*5113495bSYour Name 	uint8_t module_id = 0;
273*5113495bSYour Name 
274*5113495bSYour Name 	if (!wbuff.initialized)
275*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
276*5113495bSYour Name 
277*5113495bSYour Name 	wbuff.initialized = false;
278*5113495bSYour Name 	wbuff_debugfs_exit();
279*5113495bSYour Name 
280*5113495bSYour Name 	for (module_id = 0; module_id < WBUFF_MAX_MODULES; module_id++) {
281*5113495bSYour Name 		mod = &wbuff.mod[module_id];
282*5113495bSYour Name 		if (mod->registered)
283*5113495bSYour Name 			wbuff_module_deregister((struct wbuff_mod_handle *)
284*5113495bSYour Name 						&mod->handle);
285*5113495bSYour Name 		qdf_spinlock_destroy(&mod->lock);
286*5113495bSYour Name 	}
287*5113495bSYour Name 
288*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
289*5113495bSYour Name }
290*5113495bSYour Name 
291*5113495bSYour Name struct wbuff_mod_handle *
wbuff_module_register(struct wbuff_alloc_request * req,uint8_t num_pools,int reserve,int align,enum wbuff_module_id module_id)292*5113495bSYour Name wbuff_module_register(struct wbuff_alloc_request *req, uint8_t num_pools,
293*5113495bSYour Name 		      int reserve, int align, enum wbuff_module_id module_id)
294*5113495bSYour Name {
295*5113495bSYour Name 	struct wbuff_module *mod = NULL;
296*5113495bSYour Name 	struct wbuff_pool *wbuff_pool;
297*5113495bSYour Name 	qdf_nbuf_t buf = NULL;
298*5113495bSYour Name 	uint32_t len;
299*5113495bSYour Name 	uint16_t pool_size;
300*5113495bSYour Name 	uint8_t pool_id;
301*5113495bSYour Name 	int i;
302*5113495bSYour Name 	int j;
303*5113495bSYour Name 
304*5113495bSYour Name 	if (!wbuff.initialized)
305*5113495bSYour Name 		return NULL;
306*5113495bSYour Name 
307*5113495bSYour Name 	if ((num_pools == 0) || (num_pools > WBUFF_MAX_POOLS))
308*5113495bSYour Name 		return NULL;
309*5113495bSYour Name 
310*5113495bSYour Name 	if (module_id >= WBUFF_MAX_MODULES)
311*5113495bSYour Name 		return NULL;
312*5113495bSYour Name 
313*5113495bSYour Name 	if (!wbuff_is_valid_alloc_req(req, num_pools))
314*5113495bSYour Name 		return NULL;
315*5113495bSYour Name 
316*5113495bSYour Name 	mod = &wbuff.mod[module_id];
317*5113495bSYour Name 	if (mod->registered)
318*5113495bSYour Name 		return NULL;
319*5113495bSYour Name 
320*5113495bSYour Name 	mod->handle.id = module_id;
321*5113495bSYour Name 
322*5113495bSYour Name 	for (i = 0; i < num_pools; i++) {
323*5113495bSYour Name 		pool_id = req[i].pool_id;
324*5113495bSYour Name 		pool_size = req[i].pool_size;
325*5113495bSYour Name 		len = req[i].buffer_size;
326*5113495bSYour Name 		wbuff_pool = &mod->wbuff_pool[pool_id];
327*5113495bSYour Name 
328*5113495bSYour Name 		if (!pool_size)
329*5113495bSYour Name 			continue;
330*5113495bSYour Name 
331*5113495bSYour Name 		/**
332*5113495bSYour Name 		 * Allocate pool_size number of buffers for
333*5113495bSYour Name 		 * the pool given by pool_id
334*5113495bSYour Name 		 */
335*5113495bSYour Name 		for (j = 0; j < pool_size; j++) {
336*5113495bSYour Name 			buf = wbuff_prepare_nbuf(module_id, pool_id, len,
337*5113495bSYour Name 						 reserve, align);
338*5113495bSYour Name 			if (!buf)
339*5113495bSYour Name 				continue;
340*5113495bSYour Name 
341*5113495bSYour Name 			if (!wbuff_pool->pool)
342*5113495bSYour Name 				qdf_nbuf_set_next(buf, NULL);
343*5113495bSYour Name 			else
344*5113495bSYour Name 				qdf_nbuf_set_next(buf, wbuff_pool->pool);
345*5113495bSYour Name 
346*5113495bSYour Name 			wbuff_pool->pool = buf;
347*5113495bSYour Name 		}
348*5113495bSYour Name 
349*5113495bSYour Name 		wbuff_pool->pool_id = pool_id;
350*5113495bSYour Name 		wbuff_pool->buffer_size = len;
351*5113495bSYour Name 		wbuff_pool->initialized = true;
352*5113495bSYour Name 	}
353*5113495bSYour Name 
354*5113495bSYour Name 	mod->reserve = reserve;
355*5113495bSYour Name 	mod->align = align;
356*5113495bSYour Name 	mod->registered = true;
357*5113495bSYour Name 
358*5113495bSYour Name 
359*5113495bSYour Name 	return (struct wbuff_mod_handle *)&mod->handle;
360*5113495bSYour Name }
361*5113495bSYour Name 
wbuff_module_deregister(struct wbuff_mod_handle * hdl)362*5113495bSYour Name QDF_STATUS wbuff_module_deregister(struct wbuff_mod_handle *hdl)
363*5113495bSYour Name {
364*5113495bSYour Name 	struct wbuff_handle *handle;
365*5113495bSYour Name 	struct wbuff_module *mod = NULL;
366*5113495bSYour Name 	uint8_t module_id = 0, pool_id = 0;
367*5113495bSYour Name 	qdf_nbuf_t first = NULL, buf = NULL;
368*5113495bSYour Name 	struct wbuff_pool *wbuff_pool;
369*5113495bSYour Name 
370*5113495bSYour Name 	handle = (struct wbuff_handle *)hdl;
371*5113495bSYour Name 
372*5113495bSYour Name 	if ((!wbuff.initialized) || (!wbuff_is_valid_handle(handle)))
373*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
374*5113495bSYour Name 
375*5113495bSYour Name 	module_id = handle->id;
376*5113495bSYour Name 
377*5113495bSYour Name 	if (module_id >= WBUFF_MAX_MODULES)
378*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
379*5113495bSYour Name 
380*5113495bSYour Name 	mod = &wbuff.mod[module_id];
381*5113495bSYour Name 
382*5113495bSYour Name 	qdf_spin_lock_bh(&mod->lock);
383*5113495bSYour Name 	for (pool_id = 0; pool_id < WBUFF_MAX_POOLS; pool_id++) {
384*5113495bSYour Name 		wbuff_pool = &mod->wbuff_pool[pool_id];
385*5113495bSYour Name 
386*5113495bSYour Name 		if (!wbuff_pool->initialized)
387*5113495bSYour Name 			continue;
388*5113495bSYour Name 
389*5113495bSYour Name 		first = wbuff_pool->pool;
390*5113495bSYour Name 		while (first) {
391*5113495bSYour Name 			buf = first;
392*5113495bSYour Name 			first = qdf_nbuf_next(buf);
393*5113495bSYour Name 			qdf_nbuf_free(buf);
394*5113495bSYour Name 		}
395*5113495bSYour Name 
396*5113495bSYour Name 		wbuff_pool->mem_alloc = 0;
397*5113495bSYour Name 		wbuff_pool->alloc_success = 0;
398*5113495bSYour Name 		wbuff_pool->alloc_fail = 0;
399*5113495bSYour Name 
400*5113495bSYour Name 	}
401*5113495bSYour Name 	mod->registered = false;
402*5113495bSYour Name 	qdf_spin_unlock_bh(&mod->lock);
403*5113495bSYour Name 
404*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
405*5113495bSYour Name }
406*5113495bSYour Name 
407*5113495bSYour Name qdf_nbuf_t
wbuff_buff_get(struct wbuff_mod_handle * hdl,uint8_t pool_id,uint32_t len,const char * func_name,uint32_t line_num)408*5113495bSYour Name wbuff_buff_get(struct wbuff_mod_handle *hdl, uint8_t pool_id, uint32_t len,
409*5113495bSYour Name 	       const char *func_name, uint32_t line_num)
410*5113495bSYour Name {
411*5113495bSYour Name 	struct wbuff_handle *handle;
412*5113495bSYour Name 	struct wbuff_module *mod = NULL;
413*5113495bSYour Name 	struct wbuff_pool *wbuff_pool;
414*5113495bSYour Name 	uint8_t module_id = 0;
415*5113495bSYour Name 	qdf_nbuf_t buf = NULL;
416*5113495bSYour Name 
417*5113495bSYour Name 	handle = (struct wbuff_handle *)hdl;
418*5113495bSYour Name 
419*5113495bSYour Name 	if ((!wbuff.initialized) || (!wbuff_is_valid_handle(handle)) ||
420*5113495bSYour Name 	    ((pool_id >= WBUFF_MAX_POOL_ID && !len)))
421*5113495bSYour Name 		return NULL;
422*5113495bSYour Name 
423*5113495bSYour Name 	module_id = handle->id;
424*5113495bSYour Name 
425*5113495bSYour Name 	if (module_id >= WBUFF_MAX_MODULES)
426*5113495bSYour Name 		return NULL;
427*5113495bSYour Name 
428*5113495bSYour Name 	mod = &wbuff.mod[module_id];
429*5113495bSYour Name 
430*5113495bSYour Name 	if (pool_id == WBUFF_MAX_POOL_ID && len)
431*5113495bSYour Name 		pool_id = wbuff_get_pool_slot_from_len(mod, len);
432*5113495bSYour Name 
433*5113495bSYour Name 	if (pool_id >= WBUFF_MAX_POOLS)
434*5113495bSYour Name 		return NULL;
435*5113495bSYour Name 
436*5113495bSYour Name 	wbuff_pool = &mod->wbuff_pool[pool_id];
437*5113495bSYour Name 	if (!wbuff_pool->initialized)
438*5113495bSYour Name 		return NULL;
439*5113495bSYour Name 
440*5113495bSYour Name 	qdf_spin_lock_bh(&mod->lock);
441*5113495bSYour Name 	if (wbuff_pool->pool) {
442*5113495bSYour Name 		buf = wbuff_pool->pool;
443*5113495bSYour Name 		wbuff_pool->pool = qdf_nbuf_next(buf);
444*5113495bSYour Name 		mod->pending_returns++;
445*5113495bSYour Name 	}
446*5113495bSYour Name 	qdf_spin_unlock_bh(&mod->lock);
447*5113495bSYour Name 
448*5113495bSYour Name 	if (buf) {
449*5113495bSYour Name 		qdf_nbuf_set_next(buf, NULL);
450*5113495bSYour Name 		qdf_net_buf_debug_update_node(buf, func_name, line_num);
451*5113495bSYour Name 		wbuff_pool->alloc_success++;
452*5113495bSYour Name 	} else {
453*5113495bSYour Name 		wbuff_pool->alloc_fail++;
454*5113495bSYour Name 	}
455*5113495bSYour Name 
456*5113495bSYour Name 	return buf;
457*5113495bSYour Name }
458*5113495bSYour Name 
wbuff_buff_put(qdf_nbuf_t buf)459*5113495bSYour Name qdf_nbuf_t wbuff_buff_put(qdf_nbuf_t buf)
460*5113495bSYour Name {
461*5113495bSYour Name 	qdf_nbuf_t buffer = buf;
462*5113495bSYour Name 	unsigned long pool_info = 0;
463*5113495bSYour Name 	uint8_t module_id = 0, pool_id = 0;
464*5113495bSYour Name 	struct wbuff_pool *wbuff_pool;
465*5113495bSYour Name 
466*5113495bSYour Name 	if (qdf_nbuf_get_users(buffer) > 1)
467*5113495bSYour Name 		return buffer;
468*5113495bSYour Name 
469*5113495bSYour Name 	if (!wbuff.initialized)
470*5113495bSYour Name 		return buffer;
471*5113495bSYour Name 
472*5113495bSYour Name 	pool_info = qdf_nbuf_get_dev_scratch(buf);
473*5113495bSYour Name 	if (!pool_info)
474*5113495bSYour Name 		return buffer;
475*5113495bSYour Name 
476*5113495bSYour Name 	module_id = (pool_info & WBUFF_MODULE_ID_BITMASK) >>
477*5113495bSYour Name 			WBUFF_MODULE_ID_SHIFT;
478*5113495bSYour Name 	pool_id = (pool_info & WBUFF_POOL_ID_BITMASK) >> WBUFF_POOL_ID_SHIFT;
479*5113495bSYour Name 
480*5113495bSYour Name 	if (module_id >= WBUFF_MAX_MODULES || pool_id >= WBUFF_MAX_POOLS)
481*5113495bSYour Name 		return buffer;
482*5113495bSYour Name 
483*5113495bSYour Name 	wbuff_pool = &wbuff.mod[module_id].wbuff_pool[pool_id];
484*5113495bSYour Name 	if (!wbuff_pool->initialized)
485*5113495bSYour Name 		return buffer;
486*5113495bSYour Name 
487*5113495bSYour Name 	qdf_nbuf_reset(buffer, wbuff.mod[module_id].reserve,
488*5113495bSYour Name 		       wbuff.mod[module_id].align);
489*5113495bSYour Name 
490*5113495bSYour Name 	qdf_spin_lock_bh(&wbuff.mod[module_id].lock);
491*5113495bSYour Name 	if (wbuff.mod[module_id].registered) {
492*5113495bSYour Name 		qdf_nbuf_set_next(buffer, wbuff_pool->pool);
493*5113495bSYour Name 		wbuff_pool->pool = buffer;
494*5113495bSYour Name 		wbuff.mod[module_id].pending_returns--;
495*5113495bSYour Name 		buffer = NULL;
496*5113495bSYour Name 	}
497*5113495bSYour Name 	qdf_spin_unlock_bh(&wbuff.mod[module_id].lock);
498*5113495bSYour Name 
499*5113495bSYour Name 	return buffer;
500*5113495bSYour Name }
501