Files
luban-lite/bsp/peripheral/wireless/atbm603x/hal/atbm_skbuf.c
刘可亮 8bca5e8332 v1.0.4
2024-04-03 16:40:57 +08:00

378 lines
11 KiB
C

/**************************************************************************************************************
* altobeam RTOS wifi hmac source code
*
* Copyright (c) 2018, altobeam.inc All rights reserved.
*
* The source code contains proprietary information of AltoBeam, and shall not be distributed,
* copied, reproduced, or disclosed in whole or in part without prior written permission of AltoBeam.
*****************************************************************************************************************/
#include "atbm_hal.h"
int atbm_skb_cnt =0;
int atbm_skb_free =0;
static struct atbm_buff * __atbm_pbuf_alloc(atbm_uint16 length)
{
struct atbm_buff *p;
atbm_uint32 size;
atbm_skb_cnt++;
size=ATBM_MEM_ALIGN_SIZE(sizeof(struct atbm_buff) + ATBM_HWBUF_EXTERN_HEADROM_LEN + ATBM_HWBUF_EXTERN_TAILROM_LEN+ length);
/* If atbm_buff is to be allocated in RAM, allocate memory for it. */
p = (struct atbm_buff*) atbm_kzalloc(size,GFP_KERNEL);
if (p == ATBM_NULL) {
ATBM_WARN("__atbm_pbuf_alloc fail \n");
return ATBM_NULL;
}
/* Set up internal structure of the atbm_buff. */
ATBM_OS_SKB_DATA(p) = ATBM_MEM_ALIGN((atbm_void *)((atbm_uint8 *)p + sizeof(struct atbm_buff) + ATBM_HWBUF_EXTERN_HEADROM_LEN));
ATBM_OS_SKB_HEAD(p) = ATBM_MEM_ALIGN((atbm_uint8 *)(p+1));
//p->dlen =length+ HWBUF_EXTERN_TAILROM_LEN;
p->ref = 1;
p->totalLen = ATBM_MEM_ALIGN_SIZE(ATBM_HWBUF_EXTERN_HEADROM_LEN + ATBM_HWBUF_EXTERN_TAILROM_LEN + length);
p->bufferLen = ATBM_MEM_ALIGN_SIZE(ATBM_HWBUF_EXTERN_HEADROM_LEN + ATBM_HWBUF_EXTERN_TAILROM_LEN +length);
//wifi_printk(WIFI_ALWAYS,"****************size*****************=%d:%d:%d\n",size,p->totalLen,p->bufferLen);
/*add for wifi*/
ATBM_OS_SKB_LEN(p) = 0;
p->Tail = ATBM_OS_SKB_DATA(p);
return p;
}
atbm_void atbm_skb_reinit(struct atbm_buff *skb)
{
//clear skb struct to 0
ATBM_OS_SKB_DATA(skb) = ATBM_MEM_ALIGN((atbm_void *)((atbm_uint8 *)skb + sizeof(struct atbm_buff) + ATBM_HWBUF_EXTERN_HEADROM_LEN));
ATBM_OS_SKB_HEAD(skb) = (atbm_uint8 *)(skb+1);
skb->bufferLen = skb->totalLen;
//skb->ref = 1;
//skb->totalLen = (ATBM_MEM_ALIGN_SIZE(sizeof(struct atbm_buff) + HWBUF_EXTERN_HEADROM_LEN + HWBUF_EXTERN_TAILROM_LEN) + ATBM_MEM_ALIGN_SIZE(length));
/*add for wifi*/
ATBM_OS_SKB_LEN(skb) = 0;
skb->Tail = ATBM_OS_SKB_DATA(skb);
}
static atbm_void __atbm_pbuf_free(struct atbm_buff *p)
{
atbm_skb_free++;
ATBM_ASSERT(p->ref == 1);
p->ref--;
atbm_kfree(p);
}
struct atbm_buff * atbm_dev_alloc_skb(atbm_int32 len)
{
struct atbm_buff * skb;
skb = __atbm_pbuf_alloc(len);
if(skb == ATBM_NULL){
ATBM_BUG_ON(1);
return ATBM_NULL;
}
return skb;
}
struct atbm_buff * atbm_dev_alloc_skbhdr(void)
{
struct atbm_buff *p;
/* If atbm_buff is to be allocated in RAM, allocate memory for it. */
p = (struct atbm_buff*) __atbm_pbuf_alloc(0);
if (p == ATBM_NULL) {
ATBM_WARN("atbm_dev_alloc_skbhdr fail \n");
return ATBM_NULL;
}
return p;
}
atbm_int32 atbm_dev_kfree_skb(struct atbm_buff * skb)
{
#if defined (WLAN_ZERO_COPY1)
atbm_dev_free_os_skb(skb);
#endif //#if defined (WLAN_ZERO_COPY1)
__atbm_pbuf_free(skb);
return 1;
}
/*
* Add data to an atbm_buff
*/
atbm_uint8 *atbm_skb_put(struct atbm_buff *skb, atbm_uint32 len)
{
atbm_uint8 *tmp = skb->Tail;
skb->Tail += len;
ATBM_OS_SKB_LEN(skb) += len;
return tmp;
}
atbm_uint8 *atbm_skb_push(struct atbm_buff *skb, atbm_uint32 len)
{
ATBM_OS_SKB_DATA(skb) -= len;
ATBM_OS_SKB_LEN(skb) += len;
return ATBM_OS_SKB_DATA(skb);
}
atbm_uint8 * atbm_skb_pull(struct atbm_buff *skb, atbm_uint32 len)
{
ATBM_OS_SKB_LEN(skb) -= len;
return ATBM_OS_SKB_DATA(skb) += len;
}
/**
* atbm_skb_headroom - bytes at buffer head
* @skb: buffer to check
*
* Return the number of bytes of free space at the head of an &atbm_buff.
*/
atbm_uint32 atbm_skb_headroom(const struct atbm_buff *skb)
{
return ATBM_OS_SKB_DATA(skb) - (atbm_uint8 *)ATBM_OS_SKB_HEAD(skb);
}
/**
* skb_tailroom - bytes at buffer end
* @skb: buffer to check
*
* Return the number of bytes of free space at the tail of an atbm_buff
*/
atbm_int32 atbm_skb_tailroom(const struct atbm_buff *skb)
{
return ((atbm_uint8 *)ATBM_OS_SKB_HEAD(skb)+ skb->bufferLen) - (atbm_uint8 *)skb->Tail;
}
/**
* skb_reserve - adjust headroom
* @skb: buffer to alter
* @len: bytes to move
*
* Increase the headroom of an empty &atbm_buff by reducing the tail
* room. This is only allowed for an empty buffer.
*/
atbm_int32 atbm_skb_reserve(struct atbm_buff *skb, atbm_int32 len)
{
//atbm_uint8 * buf = OS_SKB_DATA(skb);
//ATBM_WARN_ON_FUNC(OS_SKB_LEN(skb) > 0);
//if(skb->dlen < len){
// return -1;
//}
ATBM_OS_SKB_DATA(skb) += len;
skb->Tail = ATBM_OS_SKB_DATA(skb);
//skb->tot_len -= len;
//skb->dlen -= len;
return 0;
}
atbm_void atbm_skb_set_tail_pointer(struct atbm_buff *skb, const atbm_int32 offset)
{
skb->Tail = ATBM_OS_SKB_DATA(skb) + offset;
}
atbm_void atbm_skb_trim(struct atbm_buff *skb, atbm_uint32 len)
{
ATBM_OS_SKB_LEN(skb) = len;
atbm_skb_set_tail_pointer(skb, len);
}
static atbm_void __atbm_skb_insert(struct atbm_buff *newsk,
struct atbm_buff *prev, struct atbm_buff *next,
struct atbm_buff_head *list)
{
newsk->next = next;
newsk->prev = prev;
next->prev = prev->next = newsk;
list->qlen++;
}
/**
* __skb_queue_after_ - queue a buffer at the list head
* @list: list to use
* @prev: place after this buffer
* @newsk: buffer to queue
*
* Queue a buffer int the middle of a list. This function takes no locks
* and you must therefore hold required locks before calling it.
*
* A buffer cannot be placed on two lists at the same time.
*/
/*
static atbm_void __skb_queue_after_(struct atbm_buff_head *list,
struct atbm_buff *prev,
struct atbm_buff *newsk)
{
__atbm_skb_insert(newsk, prev, prev->next, list);
}
*/
static atbm_void __skb_queue_before_(struct atbm_buff_head *list,
struct atbm_buff *next,
struct atbm_buff *newsk)
{
__atbm_skb_insert(newsk, next->prev, next, list);
}
/*
static atbm_void __skb_queue_head_(struct atbm_buff_head *list,
struct atbm_buff *newsk)
{
__skb_queue_after_(list, (struct atbm_buff *)list, newsk);
}
*/
/**
* __skb_queue_tail_ - queue a buffer at the list tail
* @list: list to use
* @newsk: buffer to queue
*
* Queue a buffer at the end of a list. This function takes no locks
* and you must therefore hold required locks before calling it.
*
* A buffer cannot be placed on two lists at the same time.
*/
static atbm_void __skb_queue_tail_(struct atbm_buff_head *list,
struct atbm_buff *newsk)
{
__skb_queue_before_(list, (struct atbm_buff *)list, newsk);
}
static atbm_void __skb_unlink_(struct atbm_buff *skb, struct atbm_buff_head *list)
{
struct atbm_buff *next, *prev;
list->qlen--;
next = skb->next;
prev = skb->prev;
skb->next = skb->prev = ATBM_NULL;
next->prev = prev;
prev->next = next;
}
/**
* atbm_skb_peek_tail - peek at the tail of an &atbm_buff_head
* @list_: list to peek at
*
* Peek an &atbm_buff. Unlike most other operations you _MUST_
* be careful with this one. A peek leaves the buffer on the
* list and someone else may run off with it. You must hold
* the appropriate locks or have a private queue to do this.
*
* Returns %NULL for an empty list or a pointer to the tail element.
* The reference count is not incremented and the reference is therefore
* volatile. Use with caution.
*/
/*
static struct atbm_buff *atbm_skb_peek_tail(struct atbm_buff_head *list_)
{
struct atbm_buff *list = ((struct atbm_buff *)list_)->prev;
if (list == (struct atbm_buff *)list_)
list = ATBM_NULL;
return list;
}
*/
/**
* atbm_skb_peek - peek at the head of an &atbm_buff_head
* @list_: list to peek at
*
* Peek an &atbm_buff. Unlike most other operations you _MUST_
* be careful with this one. A peek leaves the buffer on the
* list and someone else may run off with it. You must hold
* the appropriate locks or have a private queue to do this.
*
* Returns %NULL for an empty list or a pointer to the head element.
* The reference count is not incremented and the reference is therefore
* volatile. Use with caution.
*/
struct atbm_buff *atbm_skb_peek(struct atbm_buff_head *list_)
{
struct atbm_buff *list = ((struct atbm_buff *)list_)->next;
if (list == (struct atbm_buff *)list_)
list = ATBM_NULL;
return list;
}
/**
* __skb_dequeue_tail_ - remove from the tail of the queue
* @list: list to dequeue from
*
* Remove the tail of the list. This function does not take any locks
* so must be used with appropriate locks held only. The tail item is
* returned or %NULL if the list is empty.
*/
/*
static struct atbm_buff *__skb_dequeue_tail_(struct atbm_buff_head *list)
{
struct atbm_buff *skb = atbm_skb_peek_tail(list);
if (skb)
__skb_unlink_(skb, list);
return skb;
}
*/
/**
* __skb_dequeue_ - remove from the head of the queue
* @list: list to dequeue from
*
* Remove the head of the list. This function does not take any locks
* so must be used with appropriate locks held only. The head item is
* returned or %NULL if the list is empty.
*/
static struct atbm_buff *__skb_dequeue_(struct atbm_buff_head *list)
{
struct atbm_buff *skb = atbm_skb_peek(list);
if (skb)
__skb_unlink_(skb, list);
return skb;
}
/**
* skb_dequeue - remove from the head of the queue
* @list: list to dequeue from
*
* Remove the head of the list. The list lock is taken so the function
* may be used safely with other locking list functions. The head item is
* returned or %NULL if the list is empty.
*/
struct atbm_buff *atbm_skb_dequeue(struct atbm_buff_head *list)
{
unsigned long flags;
struct atbm_buff *result;
atbm_spin_lock_irqsave(&list->lock, &flags);
wifi_printk(WIFI_DBG_MSG,"atbm: atbm_skb_dequeue(), start.\n");
result = __skb_dequeue_(list);
wifi_printk(WIFI_DBG_MSG,"atbm: atbm_skb_dequeue(), end.\n");
atbm_spin_unlock_irqrestore(&list->lock, flags);
return result;
}
atbm_void atbm_skb_queue_tail(struct atbm_buff_head *list, struct atbm_buff *newsk)
{
unsigned long flags;
atbm_spin_lock_irqsave(&list->lock, &flags);
wifi_printk(WIFI_DBG_MSG,"atbm: atbm_skb_queue_tail(), start.\n");
__skb_queue_tail_(list, newsk);
wifi_printk(WIFI_DBG_MSG,"atbm: atbm_skb_queue_tail(), end.\n");
atbm_spin_unlock_irqrestore(&list->lock, flags);
}
/**
* skb_queue_purge - empty a list
* @list: list to empty
*
* Delete all buffers on an &atbm_buff list. Each buffer is removed from
* the list and one reference dropped. This function takes the list
* lock and is atomic with respect to other list locking functions.
*/
atbm_void atbm_skb_queue_purge(struct atbm_buff_head *list)
{
struct atbm_buff *skb;
while ((skb = atbm_skb_dequeue(list)) != ATBM_NULL)
atbm_dev_kfree_skb(skb);
}