qcacmn: Add support for WBUFF module
Introduce a new module WBUFF, which maintains a pre-allocated pool of skbs for each registered module and allocates skbs when requeted from these pre-allocated pools. The module exposes the following APIs: 1) wbuff_module_init 2) wbuff_module_deinit 3) wbuff_module_register 4) wbuff_module_deregister 5) wbuff_buff_get 6) wbuff_buff_put Change-Id: Icab723ce29a9a364c822756dee78a0dae1006180 CRs-Fixed: 2313443
This commit is contained in:

committed by
nshrivas

parent
2c3e194509
commit
9cee4926f9
151
wbuff/inc/wbuff.h
Normal file
151
wbuff/inc/wbuff.h
Normal file
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* Copyright (c) 2018 The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for
|
||||
* any purpose with or without fee is hereby granted, provided that the
|
||||
* above copyright notice and this permission notice appear in all
|
||||
* copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* DOC: wbuff.h
|
||||
* wbuff buffer management APIs
|
||||
*/
|
||||
|
||||
#ifndef _WBUFF_H
|
||||
#define _WBUFF_H
|
||||
|
||||
#include <qdf_status.h>
|
||||
#include <qdf_nbuf.h>
|
||||
|
||||
/* wbuff available pools */
|
||||
/* Pool of nbuf size 256 bytes */
|
||||
#define WBUFF_POOL_0 0
|
||||
/* Pool of nbuf size 512 bytes */
|
||||
#define WBUFF_POOL_1 1
|
||||
/* Pool of nbuf size 1024 bytes */
|
||||
#define WBUFF_POOL_2 2
|
||||
/* Pool of nbuf 2048 bytes */
|
||||
#define WBUFF_POOL_3 3
|
||||
|
||||
/**
|
||||
* struct wbuff_alloc_request - allocation structure for registering each
|
||||
* pool for wbuff module.
|
||||
* @slot: pool_slot identifier
|
||||
* @size: number of buffers for @pool_slot
|
||||
*/
|
||||
struct wbuff_alloc_request {
|
||||
uint8_t slot;
|
||||
uint16_t size;
|
||||
};
|
||||
|
||||
/* Opaque handle for wbuff */
|
||||
struct wbuff_mod_handle;
|
||||
|
||||
#ifdef WLAN_FEATURE_WBUFF
|
||||
/**
|
||||
* wbuff_module_init() - Initializes the wbuff module
|
||||
*
|
||||
* Return: QDF_STATUS_SUCCESS - init success
|
||||
* QDF_STATUS_E_NOSUPPORT - init failure
|
||||
*/
|
||||
QDF_STATUS wbuff_module_init(void);
|
||||
|
||||
/**
|
||||
* wbuff_module_deinit() - De-initializes the wbuff module
|
||||
*
|
||||
* Return: QDF_STATUS_SUCCESS - de-init success
|
||||
* QDF_STATUS_E_INVAL - de-init failure (wbuff not initialized)
|
||||
*/
|
||||
QDF_STATUS wbuff_module_deinit(void);
|
||||
|
||||
/**
|
||||
* wbuff_module_register() - Registers a module with wbuff
|
||||
* @req: allocation request from registered module
|
||||
* @num: number of pools required
|
||||
* @reserve: nbuf headroom to start with
|
||||
* @align: alignment for the nbuf
|
||||
*
|
||||
* Return: Handle if registration success
|
||||
* NULL if registration failure
|
||||
*/
|
||||
struct wbuff_mod_handle *
|
||||
wbuff_module_register(struct wbuff_alloc_request *req, uint8_t num,
|
||||
int reserve, int align);
|
||||
|
||||
/**
|
||||
* wbuff_module_deregister() - De-registers a module with wbuff
|
||||
* @hdl: wbuff_handle corresponding to the module
|
||||
*
|
||||
* Return: QDF_STATUS_SUCCESS - deregistration success
|
||||
* QDF_STATUS_E_INVAL - deregistration failure
|
||||
*/
|
||||
QDF_STATUS wbuff_module_deregister(struct wbuff_mod_handle *hdl);
|
||||
|
||||
/**
|
||||
* wbuff_buff_get() - return buffer to the requester
|
||||
* @handle: wbuff_handle corresponding to the module
|
||||
* @len: length of buffer requested
|
||||
*
|
||||
* Return: Network buffer if success
|
||||
* NULL if failure
|
||||
*/
|
||||
qdf_nbuf_t wbuff_buff_get(struct wbuff_mod_handle *hdl, uint32_t len);
|
||||
|
||||
/**
|
||||
* wbuff_buff_put() - put the buffer back to wbuff pool
|
||||
* @hdl: wbuff_handle corresponding to the module
|
||||
* @buf: pointer to network buffer
|
||||
*
|
||||
* Return: NULL if success (buffer consumed)
|
||||
* @buf if failure (buffer not consumed)
|
||||
*/
|
||||
qdf_nbuf_t wbuff_buff_put(qdf_nbuf_t buf);
|
||||
|
||||
#else
|
||||
|
||||
static inline QDF_STATUS wbuff_module_init(void)
|
||||
{
|
||||
return QDF_STATUS_E_NOSUPPORT;
|
||||
}
|
||||
|
||||
static inline QDF_STATUS wbuff_module_deinit(void)
|
||||
{
|
||||
return QDF_STATUS_E_NOSUPPORT;
|
||||
}
|
||||
|
||||
static inline struct wbuff_mod_handle *
|
||||
wbuff_module_register(struct wbuff_alloc_request *req, uint8_t num,
|
||||
int reserve, int align)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline QDF_STATUS wbuff_module_deregister(struct wbuff_mod_handle *hdl)
|
||||
{
|
||||
return QDF_STATUS_E_NOSUPPORT;
|
||||
}
|
||||
|
||||
static inline qdf_nbuf_t
|
||||
wbuff_buff_get(struct wbuff_mod_handle *hdl, uint32_t len)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline qdf_nbuf_t
|
||||
wbuff_buff_put(qdf_nbuf_t buf)
|
||||
{
|
||||
return buf;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* _WBUFF_H */
|
103
wbuff/src/i_wbuff.h
Normal file
103
wbuff/src/i_wbuff.h
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (c) 2018 The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for
|
||||
* any purpose with or without fee is hereby granted, provided that the
|
||||
* above copyright notice and this permission notice appear in all
|
||||
* copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* DOC: i_wbuff.h
|
||||
* wbuff private
|
||||
*/
|
||||
|
||||
#ifndef _I_WBUFF_H
|
||||
#define _I_WBUFF_H
|
||||
|
||||
#include <qdf_nbuf.h>
|
||||
|
||||
/* Number of modules supported by wbuff */
|
||||
#define WBUFF_MAX_MODULES 4
|
||||
|
||||
/* Number of pools supported per module */
|
||||
#define WBUFF_MAX_POOLS 4
|
||||
|
||||
/* Max buffer size supported by wbuff in bytes */
|
||||
#define WBUFF_MAX_BUFFER_SIZE 2048
|
||||
|
||||
/* wbuff pool buffer lengths in bytes*/
|
||||
#define WBUFF_LEN_POOL0 256
|
||||
#define WBUFF_LEN_POOL1 512
|
||||
#define WBUFF_LEN_POOL2 1024
|
||||
#define WBUFF_LEN_POOL3 2048
|
||||
|
||||
/* wbuff max pool sizes */
|
||||
/* Allocation of size 256 bytes */
|
||||
#define WBUFF_POOL_0_MAX 256
|
||||
/* Allocation of size 512 bytes */
|
||||
#define WBUFF_POOL_1_MAX 128
|
||||
/* Allocation of size 1024 bytes */
|
||||
#define WBUFF_POOL_2_MAX 64
|
||||
/* Allocation of size 2048 bytes */
|
||||
#define WBUFF_POOL_3_MAX 32
|
||||
|
||||
#define WBUFF_MSLOT_SHIFT 4
|
||||
#define WBUFF_MSLOT_BITMASK 0xF0
|
||||
|
||||
#define WBUFF_PSLOT_SHIFT 1
|
||||
#define WBUFF_PSLOT_BITMASK 0xE
|
||||
|
||||
/* Comparison array for maximum allocation per pool*/
|
||||
uint16_t wbuff_alloc_max[WBUFF_MAX_POOLS] = {WBUFF_POOL_0_MAX,
|
||||
WBUFF_POOL_1_MAX,
|
||||
WBUFF_POOL_2_MAX,
|
||||
WBUFF_POOL_3_MAX};
|
||||
|
||||
/**
|
||||
* struct wbuff_handle - wbuff handle to the registered module
|
||||
* @id: the identifier for the registered module.
|
||||
*/
|
||||
struct wbuff_handle {
|
||||
uint8_t id;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct wbuff_module - allocation holder for wbuff registered module
|
||||
* @registered: To identify whether module is registered
|
||||
* @pending_returns: Number of buffers pending to be returned to
|
||||
* wbuff by the module
|
||||
* @lock: Lock for accessing per module buffer slots
|
||||
* @handle: wbuff handle for the registered module
|
||||
* @reserve: nbuf headroom to start with
|
||||
* @align: alignment for the nbuf
|
||||
* @pool[]: pools for all available buffers for the module
|
||||
*/
|
||||
struct wbuff_module {
|
||||
bool registered;
|
||||
uint16_t pending_returns;
|
||||
qdf_spinlock_t lock;
|
||||
struct wbuff_handle handle;
|
||||
int reserve;
|
||||
int align;
|
||||
qdf_nbuf_t pool[WBUFF_MAX_POOLS];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct wbuff_holder - allocation holder for wbuff
|
||||
* @initialized: to identified whether module is initialized
|
||||
*/
|
||||
struct wbuff_holder {
|
||||
bool initialized;
|
||||
struct wbuff_module mod[WBUFF_MAX_MODULES];
|
||||
};
|
||||
#endif /* _WBUFF_H */
|
357
wbuff/src/wbuff.c
Normal file
357
wbuff/src/wbuff.c
Normal file
@@ -0,0 +1,357 @@
|
||||
/*
|
||||
* Copyright (c) 2018 The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for
|
||||
* any purpose with or without fee is hereby granted, provided that the
|
||||
* above copyright notice and this permission notice appear in all
|
||||
* copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* DOC: wbuff.c
|
||||
* wbuff buffer management APIs
|
||||
*/
|
||||
|
||||
#include <wbuff.h>
|
||||
#include "i_wbuff.h"
|
||||
|
||||
/**
|
||||
* Allocation holder array for all wbuff registered modules
|
||||
*/
|
||||
struct wbuff_holder wbuff;
|
||||
|
||||
/**
|
||||
* wbuff_get_pool_slot_from_len() - get pool_slot from length
|
||||
* @len: length of the buffer
|
||||
*
|
||||
* Return: pool slot
|
||||
*/
|
||||
static uint8_t wbuff_get_pool_slot_from_len(uint16_t len)
|
||||
{
|
||||
if ((len > 0) && (len <= WBUFF_LEN_POOL0))
|
||||
return WBUFF_POOL_0;
|
||||
else if ((len > WBUFF_LEN_POOL0) && (len <= WBUFF_LEN_POOL1))
|
||||
return WBUFF_POOL_1;
|
||||
else if ((len > WBUFF_LEN_POOL1) && (len <= WBUFF_LEN_POOL2))
|
||||
return WBUFF_POOL_2;
|
||||
else
|
||||
return WBUFF_POOL_3;
|
||||
}
|
||||
|
||||
/**
|
||||
* wbuff_get_len_from_pool_slot() - get len from pool slot
|
||||
* @pool_slot: wbuff pool_slot
|
||||
*
|
||||
* Return: nbuf length from pool slot
|
||||
*/
|
||||
static uint32_t wbuff_get_len_from_pool_slot(uint16_t pool_slot)
|
||||
{
|
||||
uint32_t len = 0;
|
||||
|
||||
switch (pool_slot) {
|
||||
case 0:
|
||||
len = WBUFF_LEN_POOL0;
|
||||
break;
|
||||
case 1:
|
||||
len = WBUFF_LEN_POOL1;
|
||||
break;
|
||||
case 2:
|
||||
len = WBUFF_LEN_POOL2;
|
||||
break;
|
||||
case 3:
|
||||
len = WBUFF_LEN_POOL3;
|
||||
break;
|
||||
default:
|
||||
len = 0;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* wbuff_get_free_mod_slot() - get free module slot
|
||||
*
|
||||
* Return: module slot
|
||||
*/
|
||||
static uint8_t wbuff_get_free_mod_slot(void)
|
||||
{
|
||||
uint8_t mslot = 0;
|
||||
|
||||
for (mslot = 0; mslot < WBUFF_MAX_MODULES; mslot++) {
|
||||
qdf_spin_lock_bh(&wbuff.mod[mslot].lock);
|
||||
if (!wbuff.mod[mslot].registered) {
|
||||
wbuff.mod[mslot].registered = true;
|
||||
qdf_spin_unlock_bh(&wbuff.mod[mslot].lock);
|
||||
break;
|
||||
}
|
||||
qdf_spin_unlock_bh(&wbuff.mod[mslot].lock);
|
||||
}
|
||||
|
||||
return mslot;
|
||||
}
|
||||
|
||||
/**
|
||||
* wbuff_is_valid_alloc_req() - validate alloc request
|
||||
* @req: allocation request from registered module
|
||||
* @num: number of pools required
|
||||
*
|
||||
* Return: true if valid wbuff_alloc_request
|
||||
* false if invalid wbuff_alloc_request
|
||||
*/
|
||||
static bool wbuff_is_valid_alloc_req(struct wbuff_alloc_request *req,
|
||||
uint8_t num)
|
||||
{
|
||||
uint16_t psize = 0;
|
||||
uint8_t alloc = 0, pslot = 0;
|
||||
|
||||
for (alloc = 0; alloc < num; alloc++) {
|
||||
pslot = req[alloc].slot;
|
||||
psize = req[alloc].size;
|
||||
if ((pslot > WBUFF_MAX_POOLS - 1) ||
|
||||
(psize > wbuff_alloc_max[pslot]))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* wbuff_prepare_nbuf() - allocate nbuf
|
||||
* @mslot: module slot
|
||||
* @pslot: pool slot
|
||||
* @len: length of the buffer
|
||||
* @reserve: nbuf headroom to start with
|
||||
* @align: alignment for the nbuf
|
||||
*
|
||||
* Return: nbuf if success
|
||||
* NULL if failure
|
||||
*/
|
||||
static qdf_nbuf_t wbuff_prepare_nbuf(uint8_t mslot, uint8_t pslot,
|
||||
uint32_t len, int reserve, int align)
|
||||
{
|
||||
qdf_nbuf_t buf;
|
||||
unsigned long dev_scratch = 0;
|
||||
|
||||
buf = qdf_nbuf_alloc(NULL, roundup(len + reserve, align), reserve,
|
||||
align, false);
|
||||
if (!buf)
|
||||
return NULL;
|
||||
dev_scratch = mslot;
|
||||
dev_scratch <<= WBUFF_MSLOT_SHIFT;
|
||||
dev_scratch |= ((pslot << WBUFF_PSLOT_SHIFT) | 1);
|
||||
qdf_nbuf_set_dev_scratch(buf, dev_scratch);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* wbuff_is_valid_handle() - validate wbuff handle
|
||||
* @handle: wbuff handle passed by module
|
||||
*
|
||||
* Return: true - valid wbuff_handle
|
||||
* false - invalid wbuff_handle
|
||||
*/
|
||||
static bool wbuff_is_valid_handle(struct wbuff_handle *handle)
|
||||
{
|
||||
if ((handle) && (handle->id < WBUFF_MAX_MODULES) &&
|
||||
(wbuff.mod[handle->id].registered))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
QDF_STATUS wbuff_module_init(void)
|
||||
{
|
||||
struct wbuff_module *mod = NULL;
|
||||
uint8_t mslot = 0, pslot = 0;
|
||||
|
||||
if (!qdf_nbuf_is_dev_scratch_supported()) {
|
||||
wbuff.initialized = false;
|
||||
return QDF_STATUS_E_NOSUPPORT;
|
||||
}
|
||||
|
||||
for (mslot = 0; mslot < WBUFF_MAX_MODULES; mslot++) {
|
||||
mod = &wbuff.mod[mslot];
|
||||
qdf_spinlock_create(&mod->lock);
|
||||
for (pslot = 0; pslot < WBUFF_MAX_POOLS; pslot++)
|
||||
mod->pool[pslot] = NULL;
|
||||
mod->registered = false;
|
||||
}
|
||||
wbuff.initialized = true;
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
QDF_STATUS wbuff_module_deinit(void)
|
||||
{
|
||||
struct wbuff_module *mod = NULL;
|
||||
uint8_t mslot = 0;
|
||||
|
||||
if (!wbuff.initialized)
|
||||
return QDF_STATUS_E_INVAL;
|
||||
|
||||
wbuff.initialized = false;
|
||||
for (mslot = 0; mslot < WBUFF_MAX_MODULES; mslot++) {
|
||||
mod = &wbuff.mod[mslot];
|
||||
if (mod->registered)
|
||||
wbuff_module_deregister((struct wbuff_mod_handle *)
|
||||
&mod->handle);
|
||||
qdf_spinlock_destroy(&mod->lock);
|
||||
}
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
struct wbuff_mod_handle *
|
||||
wbuff_module_register(struct wbuff_alloc_request *req, uint8_t num,
|
||||
int reserve, int align)
|
||||
{
|
||||
struct wbuff_module *mod = NULL;
|
||||
qdf_nbuf_t buf = NULL;
|
||||
uint32_t len = 0;
|
||||
uint16_t idx = 0, psize = 0;
|
||||
uint8_t alloc = 0, mslot = 0, pslot = 0;
|
||||
|
||||
if (!wbuff.initialized)
|
||||
return NULL;
|
||||
|
||||
if ((num == 0) || (num > WBUFF_MAX_POOLS))
|
||||
return NULL;
|
||||
|
||||
if (!wbuff_is_valid_alloc_req(req, num))
|
||||
return NULL;
|
||||
|
||||
mslot = wbuff_get_free_mod_slot();
|
||||
if (mslot == WBUFF_MAX_MODULES)
|
||||
return NULL;
|
||||
|
||||
mod = &wbuff.mod[mslot];
|
||||
|
||||
mod->handle.id = mslot;
|
||||
|
||||
for (alloc = 0; alloc < num; alloc++) {
|
||||
pslot = req[alloc].slot;
|
||||
psize = req[alloc].size;
|
||||
len = wbuff_get_len_from_pool_slot(pslot);
|
||||
/**
|
||||
* Allocate pool_cnt number of buffers for
|
||||
* the pool given by pslot
|
||||
*/
|
||||
for (idx = 0; idx < psize; idx++) {
|
||||
buf = wbuff_prepare_nbuf(mslot, pslot, len, reserve,
|
||||
align);
|
||||
if (!buf)
|
||||
continue;
|
||||
if (!mod->pool[pslot]) {
|
||||
qdf_nbuf_set_next(buf, NULL);
|
||||
mod->pool[pslot] = buf;
|
||||
} else {
|
||||
qdf_nbuf_set_next(buf, mod->pool[pslot]);
|
||||
mod->pool[pslot] = buf;
|
||||
}
|
||||
}
|
||||
}
|
||||
mod->reserve = reserve;
|
||||
mod->align = align;
|
||||
|
||||
return (struct wbuff_mod_handle *)&mod->handle;
|
||||
}
|
||||
|
||||
QDF_STATUS wbuff_module_deregister(struct wbuff_mod_handle *hdl)
|
||||
{
|
||||
struct wbuff_handle *handle;
|
||||
struct wbuff_module *mod = NULL;
|
||||
uint8_t mslot = 0, pslot = 0;
|
||||
qdf_nbuf_t first = NULL, buf = NULL;
|
||||
|
||||
handle = (struct wbuff_handle *)hdl;
|
||||
|
||||
if ((!wbuff.initialized) || (!wbuff_is_valid_handle(handle)))
|
||||
return QDF_STATUS_E_INVAL;
|
||||
|
||||
mslot = handle->id;
|
||||
mod = &wbuff.mod[mslot];
|
||||
|
||||
qdf_spin_lock_bh(&mod->lock);
|
||||
for (pslot = 0; pslot < WBUFF_MAX_POOLS; pslot++) {
|
||||
first = mod->pool[pslot];
|
||||
while (first) {
|
||||
buf = first;
|
||||
first = qdf_nbuf_next(buf);
|
||||
qdf_nbuf_free(buf);
|
||||
}
|
||||
}
|
||||
mod->registered = false;
|
||||
qdf_spin_unlock_bh(&mod->lock);
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
qdf_nbuf_t wbuff_buff_get(struct wbuff_mod_handle *hdl, uint32_t len)
|
||||
{
|
||||
struct wbuff_handle *handle;
|
||||
struct wbuff_module *mod = NULL;
|
||||
uint8_t mslot = 0;
|
||||
uint8_t pslot = 0;
|
||||
qdf_nbuf_t buf = NULL;
|
||||
|
||||
handle = (struct wbuff_handle *)hdl;
|
||||
|
||||
if ((!wbuff.initialized) || (!wbuff_is_valid_handle(handle)) || !len ||
|
||||
(len > WBUFF_MAX_BUFFER_SIZE))
|
||||
return NULL;
|
||||
|
||||
mslot = handle->id;
|
||||
pslot = wbuff_get_pool_slot_from_len(len);
|
||||
mod = &wbuff.mod[mslot];
|
||||
|
||||
qdf_spin_lock_bh(&mod->lock);
|
||||
if (mod->pool[pslot]) {
|
||||
buf = mod->pool[pslot];
|
||||
mod->pool[pslot] = qdf_nbuf_next(buf);
|
||||
mod->pending_returns++;
|
||||
}
|
||||
qdf_spin_unlock_bh(&mod->lock);
|
||||
if (buf)
|
||||
qdf_nbuf_set_next(buf, NULL);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
qdf_nbuf_t wbuff_buff_put(qdf_nbuf_t buf)
|
||||
{
|
||||
qdf_nbuf_t buffer = buf;
|
||||
unsigned long slot_info = 0;
|
||||
uint8_t mslot = 0, pslot = 0;
|
||||
|
||||
if (!wbuff.initialized)
|
||||
return buffer;
|
||||
|
||||
slot_info = qdf_nbuf_get_dev_scratch(buf);
|
||||
if (!slot_info)
|
||||
return buffer;
|
||||
|
||||
mslot = (slot_info & WBUFF_MSLOT_BITMASK) >> WBUFF_MSLOT_SHIFT;
|
||||
pslot = (slot_info & WBUFF_PSLOT_BITMASK) >> WBUFF_PSLOT_SHIFT;
|
||||
qdf_nbuf_reset(buffer, wbuff.mod[mslot].reserve, wbuff.mod[mslot].
|
||||
align);
|
||||
qdf_spin_lock_bh(&wbuff.mod[mslot].lock);
|
||||
if (wbuff.mod[mslot].registered) {
|
||||
qdf_nbuf_set_next(buffer, wbuff.mod[mslot].pool[pslot]);
|
||||
wbuff.mod[mslot].pool[pslot] = buffer;
|
||||
wbuff.mod[mslot].pending_returns--;
|
||||
buffer = NULL;
|
||||
}
|
||||
qdf_spin_unlock_bh(&wbuff.mod[mslot].lock);
|
||||
|
||||
return buffer;
|
||||
}
|
Reference in New Issue
Block a user