369 lines
9.6 KiB
C
369 lines
9.6 KiB
C
#ifndef __RWNX_INTF_SKBUFF_H_
|
|
#define __RWNX_INTF_SKBUFF_H_
|
|
|
|
//#include "common/bk_typedef.h"
|
|
#include "wifi_spinlock.h"
|
|
//#include "dbg_assert.h"
|
|
#include "rw_msdu.h"
|
|
|
|
extern int32_t skb_cnt;
|
|
/*
|
|
* These inlines deal with timer wrapping correctly. You are
|
|
* strongly encouraged to use them
|
|
* 1. Because people otherwise forget
|
|
* 2. Because if the timer wrap changes in future you won't have to
|
|
* alter your driver code.
|
|
*
|
|
* time_after(a,b) returns true if the time a is after time b.
|
|
*
|
|
* Do this with "<0" and ">=0" to only test the sign of the result. A
|
|
* good compiler would generate better code (and a really good compiler
|
|
* wouldn't care). Gcc is currently neither.
|
|
*/
|
|
#define time_after(a,b) \
|
|
((int64_t)((b) - (a)) < 0)
|
|
#define time_before(a,b) time_after(b,a)
|
|
|
|
#define time_after_eq(a,b) \
|
|
((int64_t)((a) - (b)) >= 0)
|
|
#define time_before_eq(a,b) time_after_eq(b,a)
|
|
|
|
/*
|
|
* Calculate whether a is in the range of [b, c].
|
|
*/
|
|
#define time_in_range(a,b,c) \
|
|
(time_after_eq(a,b) && \
|
|
time_before_eq(a,c))
|
|
|
|
/*
|
|
* Calculate whether a is in the range of [b, c).
|
|
*/
|
|
#define time_in_range_open(a,b,c) \
|
|
(time_after_eq(a,b) && \
|
|
time_before(a,c))
|
|
|
|
struct sk_buff_head {
|
|
/* These two members must be first. */
|
|
struct sk_buff *next;
|
|
struct sk_buff *prev;
|
|
|
|
__u32 qlen;
|
|
spinlock_t lock;
|
|
};
|
|
|
|
|
|
/**
|
|
* skb_queue_len - get queue length
|
|
* @list_: list to measure
|
|
*
|
|
* Return the length of an &sk_buff queue.
|
|
*/
|
|
static inline uint32_t skb_queue_len(const struct sk_buff_head *list_)
|
|
{
|
|
return list_->qlen;
|
|
}
|
|
|
|
/**
|
|
* __skb_queue_head_init - initialize non-spinlock portions of sk_buff_head
|
|
* @list: queue to initialize
|
|
*
|
|
* This initializes only the list and queue length aspects of
|
|
* an sk_buff_head object. This allows to initialize the list
|
|
* aspects of an sk_buff_head without reinitializing things like
|
|
* the spinlock. It can also be used for on-stack sk_buff_head
|
|
* objects where the spinlock is known to not be used.
|
|
*/
|
|
static inline void __skb_queue_head_init(struct sk_buff_head *list)
|
|
{
|
|
list->prev = list->next = (struct sk_buff *)list;
|
|
list->qlen = 0;
|
|
}
|
|
|
|
/*
|
|
* This function creates a split out lock class for each invocation;
|
|
* this is needed for now since a whole lot of users of the skb-queue
|
|
* infrastructure in drivers have different locking usage (in hardirq)
|
|
* than the networking core (in softirq only). In the long run either the
|
|
* network layer or drivers should need annotation to consolidate the
|
|
* main types of usage into 3 classes.
|
|
*/
|
|
static inline void skb_queue_head_init(struct sk_buff_head *list)
|
|
{
|
|
spin_lock_init(&list->lock);
|
|
__skb_queue_head_init(list);
|
|
}
|
|
|
|
/*
|
|
* remove sk_buff from list. _Must_ be called atomically, and with
|
|
* the list known..
|
|
*/
|
|
static inline void __skb_unlink(struct sk_buff *skb, struct sk_buff_head *list)
|
|
{
|
|
struct sk_buff *next, *prev;
|
|
|
|
list->qlen--;
|
|
next = skb->next;
|
|
prev = skb->prev;
|
|
skb->next = skb->prev = NULL;
|
|
next->prev = prev;
|
|
prev->next = next;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* skb_queue_empty - check if a queue is empty
|
|
* @list: queue head
|
|
*
|
|
* Returns true if the queue is empty, false otherwise.
|
|
*/
|
|
static inline int skb_queue_empty(const struct sk_buff_head *list)
|
|
{
|
|
return list->next == (const struct sk_buff *) list;
|
|
}
|
|
|
|
/**
|
|
* skb_peek - peek at the head of an &sk_buff_head
|
|
* @list_: list to peek at
|
|
*
|
|
* Peek an &sk_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.
|
|
*/
|
|
static inline struct sk_buff *skb_peek(const struct sk_buff_head *list_)
|
|
{
|
|
struct sk_buff *skb = list_->next;
|
|
|
|
if (skb == (struct sk_buff *)list_)
|
|
skb = NULL;
|
|
return skb;
|
|
}
|
|
|
|
/**
|
|
* __skb_peek - peek at the head of a non-empty &sk_buff_head
|
|
* @list_: list to peek at
|
|
*
|
|
* Like skb_peek(), but the caller knows that the list is not empty.
|
|
*/
|
|
static inline struct sk_buff *__skb_peek(const struct sk_buff_head *list_)
|
|
{
|
|
return list_->next;
|
|
}
|
|
|
|
/**
|
|
* skb_peek_next - peek skb following the given one from a queue
|
|
* @skb: skb to start from
|
|
* @list_: list to peek at
|
|
*
|
|
* Returns %NULL when the end of the list is met or a pointer to the
|
|
* next element. The reference count is not incremented and the
|
|
* reference is therefore volatile. Use with caution.
|
|
*/
|
|
static inline struct sk_buff *skb_peek_next(struct sk_buff *skb,
|
|
const struct sk_buff_head *list_)
|
|
{
|
|
struct sk_buff *next = skb->next;
|
|
|
|
if (next == (struct sk_buff *)list_)
|
|
next = NULL;
|
|
return next;
|
|
}
|
|
|
|
/**
|
|
* skb_peek_tail - peek at the tail of an &sk_buff_head
|
|
* @list_: list to peek at
|
|
*
|
|
* Peek an &sk_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 inline struct sk_buff *skb_peek_tail(const struct sk_buff_head *list_)
|
|
{
|
|
struct sk_buff *skb = list_->prev;
|
|
|
|
if (skb == (struct sk_buff *)list_)
|
|
skb = NULL;
|
|
return skb;
|
|
|
|
}
|
|
|
|
/*
|
|
* Insert an sk_buff on a list.
|
|
*
|
|
* The "__skb_xxxx()" functions are the non-atomic ones that
|
|
* can only be called with interrupts disabled.
|
|
*/
|
|
static inline void __skb_insert(struct sk_buff *newsk,
|
|
struct sk_buff *prev, struct sk_buff *next,
|
|
struct sk_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 inline void __skb_queue_after(struct sk_buff_head *list,
|
|
struct sk_buff *prev,
|
|
struct sk_buff *newsk)
|
|
{
|
|
__skb_insert(newsk, prev, prev->next, list);
|
|
}
|
|
|
|
static inline void __skb_queue_before(struct sk_buff_head *list,
|
|
struct sk_buff *next,
|
|
struct sk_buff *newsk)
|
|
{
|
|
__skb_insert(newsk, next->prev, next, list);
|
|
}
|
|
|
|
/**
|
|
* __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 inline void __skb_queue_tail(struct sk_buff_head *list,
|
|
struct sk_buff *newsk)
|
|
{
|
|
__skb_queue_before(list, (struct sk_buff *)list, newsk);
|
|
}
|
|
|
|
/**
|
|
* __skb_queue_head - queue a buffer at the list head
|
|
* @list: list to use
|
|
* @newsk: buffer to queue
|
|
*
|
|
* Queue a buffer at the start 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 inline void __skb_queue_head(struct sk_buff_head *list,
|
|
struct sk_buff *newsk)
|
|
{
|
|
__skb_queue_after(list, (struct sk_buff *)list, newsk);
|
|
}
|
|
|
|
|
|
static inline void __skb_queue_splice(const struct sk_buff_head *list,
|
|
struct sk_buff *prev,
|
|
struct sk_buff *next)
|
|
{
|
|
struct sk_buff *first = list->next;
|
|
struct sk_buff *last = list->prev;
|
|
|
|
first->prev = prev;
|
|
prev->next = first;
|
|
|
|
last->next = next;
|
|
next->prev = last;
|
|
}
|
|
|
|
/**
|
|
* skb_queue_splice_init - join two skb lists and reinitialise the emptied list
|
|
* @list: the new list to add
|
|
* @head: the place to add it in the first list
|
|
*
|
|
* The list at @list is reinitialised
|
|
*/
|
|
static inline void skb_queue_splice_init(struct sk_buff_head *list,
|
|
struct sk_buff_head *head)
|
|
{
|
|
if (!skb_queue_empty(list)) {
|
|
__skb_queue_splice(list, (struct sk_buff *) head, head->next);
|
|
head->qlen += list->qlen;
|
|
__skb_queue_head_init(list);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* __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 inline struct sk_buff *__skb_dequeue(struct sk_buff_head *list)
|
|
{
|
|
struct sk_buff *skb = skb_peek(list);
|
|
if (skb)
|
|
__skb_unlink(skb, list);
|
|
return skb;
|
|
}
|
|
|
|
/**
|
|
* increase the pending skb count
|
|
*/
|
|
static inline void skb_inc_pending_cnt(void)
|
|
{
|
|
skb_cnt++;
|
|
}
|
|
/**
|
|
* decrease the pending skb count
|
|
*/
|
|
static inline void skb_dec_pending_cnt(void)
|
|
{
|
|
skb_cnt--;
|
|
}
|
|
/**
|
|
* get the pending skb count
|
|
*/
|
|
static inline int32_t skb_get_pending_cnt(void)
|
|
{
|
|
return skb_cnt;
|
|
}
|
|
|
|
#define skb_queue_walk(queue, skb) \
|
|
for (skb = (queue)->next; \
|
|
skb != (struct sk_buff *)(queue); \
|
|
skb = skb->next)
|
|
|
|
#define skb_queue_walk_safe(queue, skb, tmp) \
|
|
for (skb = (queue)->next, tmp = skb->next; \
|
|
skb != (struct sk_buff *)(queue); \
|
|
skb = tmp, tmp = skb->next)
|
|
|
|
|
|
void skb_unlink(struct sk_buff *skb, struct sk_buff_head *list);
|
|
void skb_append(struct sk_buff *old, struct sk_buff *newsk, struct sk_buff_head *list);
|
|
void skb_queue_tail(struct sk_buff_head *list, struct sk_buff *newsk);
|
|
void skb_queue_head(struct sk_buff_head *list, struct sk_buff *newsk);
|
|
void dev_kfree_skb_any(struct sk_buff *skb);
|
|
struct sk_buff *alloc_skb(UINT32 len, int layer);
|
|
struct sk_buff *alloc_skb_for_tx_mgmt(UINT32 len);
|
|
struct sk_buff *alloc_skb_with_pbuf(struct pbuf *p);
|
|
void kfree_skb(struct sk_buff *skb);
|
|
|
|
|
|
#endif
|
|
|