xref: /OK3568_Linux_fs/external/rkwifibt/drivers/bcmdhd/include/hnd_pktq.h (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * HND generic pktq operation primitives
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Copyright (C) 2020, Broadcom.
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  *      Unless you and Broadcom execute a separate written software license
7*4882a593Smuzhiyun  * agreement governing use of this software, this software is licensed to you
8*4882a593Smuzhiyun  * under the terms of the GNU General Public License version 2 (the "GPL"),
9*4882a593Smuzhiyun  * available at http://www.broadcom.com/licenses/GPLv2.php, with the
10*4882a593Smuzhiyun  * following added to such license:
11*4882a593Smuzhiyun  *
12*4882a593Smuzhiyun  *      As a special exception, the copyright holders of this software give you
13*4882a593Smuzhiyun  * permission to link this software with independent modules, and to copy and
14*4882a593Smuzhiyun  * distribute the resulting executable under terms of your choice, provided that
15*4882a593Smuzhiyun  * you also meet, for each linked independent module, the terms and conditions of
16*4882a593Smuzhiyun  * the license of that module.  An independent module is a module which is not
17*4882a593Smuzhiyun  * derived from this software.  The special exception does not apply to any
18*4882a593Smuzhiyun  * modifications of the software.
19*4882a593Smuzhiyun  *
20*4882a593Smuzhiyun  *
21*4882a593Smuzhiyun  * <<Broadcom-WL-IPTag/Dual:>>
22*4882a593Smuzhiyun  */
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun #ifndef _hnd_pktq_h_
25*4882a593Smuzhiyun #define _hnd_pktq_h_
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun #include <osl.h>
28*4882a593Smuzhiyun #include <osl_ext.h>
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun #ifdef __cplusplus
31*4882a593Smuzhiyun extern "C" {
32*4882a593Smuzhiyun #endif
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun /* mutex macros for thread safe */
35*4882a593Smuzhiyun #ifdef HND_PKTQ_THREAD_SAFE
36*4882a593Smuzhiyun #define HND_PKTQ_MUTEX_DECL(mutex)		OSL_EXT_MUTEX_DECL(mutex)
37*4882a593Smuzhiyun #else
38*4882a593Smuzhiyun #define HND_PKTQ_MUTEX_DECL(mutex)
39*4882a593Smuzhiyun #endif
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun /* osl multi-precedence packet queue */
42*4882a593Smuzhiyun #define PKTQ_LEN_MAX            0xFFFFu  /* Max uint16 65535 packets */
43*4882a593Smuzhiyun #ifndef PKTQ_LEN_DEFAULT
44*4882a593Smuzhiyun #define PKTQ_LEN_DEFAULT        128u	/* Max 128 packets */
45*4882a593Smuzhiyun #endif
46*4882a593Smuzhiyun #ifndef PKTQ_MAX_PREC
47*4882a593Smuzhiyun #define PKTQ_MAX_PREC           16	/* Maximum precedence levels */
48*4882a593Smuzhiyun #endif
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun /** Queue for a single precedence level */
51*4882a593Smuzhiyun typedef struct pktq_prec {
52*4882a593Smuzhiyun 	void *head;     /**< first packet to dequeue */
53*4882a593Smuzhiyun 	void *tail;     /**< last packet to dequeue */
54*4882a593Smuzhiyun 	uint16 n_pkts;       /**< number of queued packets */
55*4882a593Smuzhiyun 	uint16 max_pkts;     /**< maximum number of queued packets */
56*4882a593Smuzhiyun 	uint16 stall_count;    /**< # seconds since no packets are dequeued  */
57*4882a593Smuzhiyun 	uint16 dequeue_count;  /**< # of packets dequeued in last 1 second */
58*4882a593Smuzhiyun } pktq_prec_t;
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun #ifdef PKTQ_LOG
61*4882a593Smuzhiyun typedef struct {
62*4882a593Smuzhiyun 	uint32 requested;    /**< packets requested to be stored */
63*4882a593Smuzhiyun 	uint32 stored;	     /**< packets stored */
64*4882a593Smuzhiyun 	uint32 saved;	     /**< packets saved,
65*4882a593Smuzhiyun 	                            because a lowest priority queue has given away one packet
66*4882a593Smuzhiyun 	                      */
67*4882a593Smuzhiyun 	uint32 selfsaved;    /**< packets saved,
68*4882a593Smuzhiyun 	                            because an older packet from the same queue has been dropped
69*4882a593Smuzhiyun 	                      */
70*4882a593Smuzhiyun 	uint32 full_dropped; /**< packets dropped,
71*4882a593Smuzhiyun 	                            because pktq is full with higher precedence packets
72*4882a593Smuzhiyun 	                      */
73*4882a593Smuzhiyun 	uint32 dropped;      /**< packets dropped because pktq per that precedence is full */
74*4882a593Smuzhiyun 	uint32 sacrificed;   /**< packets dropped,
75*4882a593Smuzhiyun 	                            in order to save one from a queue of a highest priority
76*4882a593Smuzhiyun 	                      */
77*4882a593Smuzhiyun 	uint32 busy;         /**< packets droped because of hardware/transmission error */
78*4882a593Smuzhiyun 	uint32 retry;        /**< packets re-sent because they were not received */
79*4882a593Smuzhiyun 	uint32 ps_retry;     /**< packets retried again prior to moving power save mode */
80*4882a593Smuzhiyun 	uint32 suppress;     /**< packets which were suppressed and not transmitted */
81*4882a593Smuzhiyun 	uint32 retry_drop;   /**< packets finally dropped after retry limit */
82*4882a593Smuzhiyun 	uint32 max_avail;    /**< the high-water mark of the queue capacity for packets -
83*4882a593Smuzhiyun 	                            goes to zero as queue fills
84*4882a593Smuzhiyun 	                      */
85*4882a593Smuzhiyun 	uint32 max_used;     /**< the high-water mark of the queue utilisation for packets -
86*4882a593Smuzhiyun 						        increases with use ('inverse' of max_avail)
87*4882a593Smuzhiyun 				          */
88*4882a593Smuzhiyun 	uint32 queue_capacity; /**< the maximum capacity of the queue */
89*4882a593Smuzhiyun 	uint32 rtsfail;        /**< count of rts attempts that failed to receive cts */
90*4882a593Smuzhiyun 	uint32 acked;          /**< count of packets sent (acked) successfully */
91*4882a593Smuzhiyun 	uint32 txrate_succ;    /**< running total of phy rate of packets sent successfully */
92*4882a593Smuzhiyun 	uint32 txrate_main;    /**< running totoal of primary phy rate of all packets */
93*4882a593Smuzhiyun 	uint32 throughput;     /**< actual data transferred successfully */
94*4882a593Smuzhiyun 	uint32 airtime;        /**< cumulative total medium access delay in useconds */
95*4882a593Smuzhiyun 	uint32  _logtime;      /**< timestamp of last counter clear  */
96*4882a593Smuzhiyun } pktq_counters_t;
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun #define PKTQ_LOG_COMMON \
99*4882a593Smuzhiyun 	uint32			pps_time;	/**< time spent in ps pretend state */ \
100*4882a593Smuzhiyun 	uint32                  _prec_log;
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun typedef struct {
103*4882a593Smuzhiyun 	PKTQ_LOG_COMMON
104*4882a593Smuzhiyun 	pktq_counters_t*        _prec_cnt[PKTQ_MAX_PREC];     /**< Counters per queue  */
105*4882a593Smuzhiyun } pktq_log_t;
106*4882a593Smuzhiyun #else
107*4882a593Smuzhiyun typedef struct pktq_log pktq_log_t;
108*4882a593Smuzhiyun #endif /* PKTQ_LOG */
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun /** multi-priority packet queue */
111*4882a593Smuzhiyun struct pktq {
112*4882a593Smuzhiyun 	HND_PKTQ_MUTEX_DECL(mutex)
113*4882a593Smuzhiyun 	pktq_log_t *pktqlog;
114*4882a593Smuzhiyun 	uint16 num_prec;        /**< number of precedences in use */
115*4882a593Smuzhiyun 	uint16 hi_prec;         /**< rapid dequeue hint (>= highest non-empty prec) */
116*4882a593Smuzhiyun 	uint16 max_pkts;        /**< max  packets */
117*4882a593Smuzhiyun 	uint16 n_pkts_tot;      /**< total (cummulative over all precedences) number of packets */
118*4882a593Smuzhiyun 	/* q array must be last since # of elements can be either PKTQ_MAX_PREC or 1 */
119*4882a593Smuzhiyun 	struct pktq_prec q[PKTQ_MAX_PREC];
120*4882a593Smuzhiyun };
121*4882a593Smuzhiyun 
122*4882a593Smuzhiyun /** simple, non-priority packet queue */
123*4882a593Smuzhiyun struct spktq {
124*4882a593Smuzhiyun 	HND_PKTQ_MUTEX_DECL(mutex)
125*4882a593Smuzhiyun 	struct pktq_prec q;
126*4882a593Smuzhiyun };
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun #define PKTQ_PREC_ITER(pq, prec)        for (prec = (pq)->num_prec - 1; prec >= 0; prec--)
129*4882a593Smuzhiyun 
130*4882a593Smuzhiyun /* fn(pkt, arg).  return true if pkt belongs to bsscfg */
131*4882a593Smuzhiyun typedef bool (*ifpkt_cb_t)(void*, int);
132*4882a593Smuzhiyun 
133*4882a593Smuzhiyun /*
134*4882a593Smuzhiyun  * pktq filter support
135*4882a593Smuzhiyun  */
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun /** filter function return values */
138*4882a593Smuzhiyun typedef enum {
139*4882a593Smuzhiyun 	PKT_FILTER_NOACTION = 0,    /**< restore the pkt to its position in the queue */
140*4882a593Smuzhiyun 	PKT_FILTER_DELETE = 1,      /**< delete the pkt */
141*4882a593Smuzhiyun 	PKT_FILTER_REMOVE = 2,      /**< do not restore the pkt to the queue,
142*4882a593Smuzhiyun 	                             *   filter fn has taken ownership of the pkt
143*4882a593Smuzhiyun 	                             */
144*4882a593Smuzhiyun } pktq_filter_result_t;
145*4882a593Smuzhiyun 
146*4882a593Smuzhiyun /**
147*4882a593Smuzhiyun  * Caller supplied filter function to pktq_pfilter(), pktq_filter().
148*4882a593Smuzhiyun  * Function filter(ctx, pkt) is called with its ctx pointer on each pkt in the
149*4882a593Smuzhiyun  * pktq.  When the filter function is called, the supplied pkt will have been
150*4882a593Smuzhiyun  * unlinked from the pktq.  The filter function returns a pktq_filter_result_t
151*4882a593Smuzhiyun  * result specifying the action pktq_filter()/pktq_pfilter() should take for
152*4882a593Smuzhiyun  * the pkt.
153*4882a593Smuzhiyun  * Here are the actions taken by pktq_filter/pfilter() based on the supplied
154*4882a593Smuzhiyun  * filter function's return value:
155*4882a593Smuzhiyun  *
156*4882a593Smuzhiyun  * PKT_FILTER_NOACTION - The filter will re-link the pkt at its
157*4882a593Smuzhiyun  *     previous location.
158*4882a593Smuzhiyun  *
159*4882a593Smuzhiyun  * PKT_FILTER_DELETE - The filter will not relink the pkt and will
160*4882a593Smuzhiyun  *     call the user supplied defer_free_pkt fn on the packet.
161*4882a593Smuzhiyun  *
162*4882a593Smuzhiyun  * PKT_FILTER_REMOVE - The filter will not relink the pkt. The supplied
163*4882a593Smuzhiyun  *     filter fn took ownership (or deleted) the pkt.
164*4882a593Smuzhiyun  *
165*4882a593Smuzhiyun  * WARNING: pkts inserted by the user (in pkt_filter and/or flush callbacks
166*4882a593Smuzhiyun  * and chains) in the prec queue will not be seen by the filter, and the prec
167*4882a593Smuzhiyun  * queue will be temporarily be removed from the queue hence there're side
168*4882a593Smuzhiyun  * effects including pktq_n_pkts_tot() on the queue won't reflect the correct number
169*4882a593Smuzhiyun  * of packets in the queue.
170*4882a593Smuzhiyun  */
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun typedef pktq_filter_result_t (*pktq_filter_t)(void* ctx, void* pkt);
173*4882a593Smuzhiyun 
174*4882a593Smuzhiyun /**
175*4882a593Smuzhiyun  * The defer_free_pkt callback is invoked when the the pktq_filter callback
176*4882a593Smuzhiyun  * returns PKT_FILTER_DELETE decision, which allows the user to deposite
177*4882a593Smuzhiyun  * the packet appropriately based on the situation (free the packet or
178*4882a593Smuzhiyun  * save it in a temporary queue etc.).
179*4882a593Smuzhiyun  */
180*4882a593Smuzhiyun typedef void (*defer_free_pkt_fn_t)(void *ctx, void *pkt);
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun /**
183*4882a593Smuzhiyun  * The flush_free_pkt callback is invoked when all packets in the pktq
184*4882a593Smuzhiyun  * are processed.
185*4882a593Smuzhiyun  */
186*4882a593Smuzhiyun typedef void (*flush_free_pkt_fn_t)(void *ctx);
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun #if defined(PROP_TXSTATUS)
189*4882a593Smuzhiyun /* this callback will be invoked when in low_txq_scb flush()
190*4882a593Smuzhiyun  *  two back-to-back pkts has same epoch value.
191*4882a593Smuzhiyun  */
192*4882a593Smuzhiyun typedef void (*flip_epoch_t)(void *ctx, void *pkt, uint8 *flipEpoch, uint8 *lastEpoch);
193*4882a593Smuzhiyun #endif /* defined(PROP_TXSTATUS) */
194*4882a593Smuzhiyun 
195*4882a593Smuzhiyun /** filter a pktq, using the caller supplied filter/deposition/flush functions */
196*4882a593Smuzhiyun extern void  pktq_filter(struct pktq *pq, pktq_filter_t fn, void* arg,
197*4882a593Smuzhiyun 	defer_free_pkt_fn_t defer, void *defer_ctx, flush_free_pkt_fn_t flush, void *flush_ctx);
198*4882a593Smuzhiyun /** filter a particular precedence in pktq, using the caller supplied filter function */
199*4882a593Smuzhiyun extern void  pktq_pfilter(struct pktq *pq, int prec, pktq_filter_t fn, void* arg,
200*4882a593Smuzhiyun 	defer_free_pkt_fn_t defer, void *defer_ctx, flush_free_pkt_fn_t flush, void *flush_ctx);
201*4882a593Smuzhiyun /** filter a simple non-precedence in spktq, using the caller supplied filter function */
202*4882a593Smuzhiyun extern void spktq_filter(struct spktq *spq, pktq_filter_t fltr, void* fltr_ctx,
203*4882a593Smuzhiyun 	defer_free_pkt_fn_t defer, void *defer_ctx, flush_free_pkt_fn_t flush, void *flush_ctx);
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun /* operations on a specific precedence in packet queue */
206*4882a593Smuzhiyun #define pktqprec_max_pkts(pq, prec)		((pq)->q[prec].max_pkts)
207*4882a593Smuzhiyun #define pktqprec_n_pkts(pq, prec)		((pq)->q[prec].n_pkts)
208*4882a593Smuzhiyun #define pktqprec_empty(pq, prec)		((pq)->q[prec].n_pkts == 0)
209*4882a593Smuzhiyun #define pktqprec_peek(pq, prec)			((pq)->q[prec].head)
210*4882a593Smuzhiyun #define pktqprec_peek_tail(pq, prec)	((pq)->q[prec].tail)
211*4882a593Smuzhiyun #define spktq_peek_tail(pq)		((pq)->q.tail)
212*4882a593Smuzhiyun #ifdef HND_PKTQ_THREAD_SAFE
213*4882a593Smuzhiyun extern int pktqprec_avail_pkts(struct pktq *pq, int prec);
214*4882a593Smuzhiyun extern bool pktqprec_full(struct pktq *pq, int prec);
215*4882a593Smuzhiyun #else
216*4882a593Smuzhiyun #define pktqprec_avail_pkts(pq, prec)	((pq)->q[prec].max_pkts - (pq)->q[prec].n_pkts)
217*4882a593Smuzhiyun #define pktqprec_full(pq, prec)	((pq)->q[prec].n_pkts >= (pq)->q[prec].max_pkts)
218*4882a593Smuzhiyun #endif	/* HND_PKTQ_THREAD_SAFE */
219*4882a593Smuzhiyun 
220*4882a593Smuzhiyun extern void  pktq_append(struct pktq *pq, int prec, struct spktq *list);
221*4882a593Smuzhiyun extern void  spktq_append(struct spktq *spq, struct spktq *list);
222*4882a593Smuzhiyun extern void  pktq_prepend(struct pktq *pq, int prec, struct spktq *list);
223*4882a593Smuzhiyun extern void  spktq_prepend(struct spktq *spq, struct spktq *list);
224*4882a593Smuzhiyun extern void *pktq_penq(struct pktq *pq, int prec, void *p);
225*4882a593Smuzhiyun extern void *pktq_penq_head(struct pktq *pq, int prec, void *p);
226*4882a593Smuzhiyun extern void *pktq_pdeq(struct pktq *pq, int prec);
227*4882a593Smuzhiyun extern void *pktq_pdeq_prev(struct pktq *pq, int prec, void *prev_p);
228*4882a593Smuzhiyun extern void *pktq_pdeq_with_fn(struct pktq *pq, int prec, ifpkt_cb_t fn, int arg);
229*4882a593Smuzhiyun extern void *pktq_pdeq_tail(struct pktq *pq, int prec);
230*4882a593Smuzhiyun /** Remove a specified packet from its queue */
231*4882a593Smuzhiyun extern bool pktq_pdel(struct pktq *pq, void *p, int prec);
232*4882a593Smuzhiyun 
233*4882a593Smuzhiyun /* For single precedence queues */
234*4882a593Smuzhiyun extern void *spktq_enq_chain(struct spktq *dspq, struct spktq *sspq);
235*4882a593Smuzhiyun extern void *spktq_enq(struct spktq *spq, void *p);
236*4882a593Smuzhiyun extern void *spktq_enq_head(struct spktq *spq, void *p);
237*4882a593Smuzhiyun extern void *spktq_deq(struct spktq *spq);
238*4882a593Smuzhiyun extern void *spktq_deq_virt(struct spktq *spq);
239*4882a593Smuzhiyun extern void *spktq_deq_tail(struct spktq *spq);
240*4882a593Smuzhiyun 
241*4882a593Smuzhiyun /* operations on a set of precedences in packet queue */
242*4882a593Smuzhiyun 
243*4882a593Smuzhiyun extern int pktq_mlen(struct pktq *pq, uint prec_bmp);
244*4882a593Smuzhiyun extern void *pktq_mdeq(struct pktq *pq, uint prec_bmp, int *prec_out);
245*4882a593Smuzhiyun extern void *pktq_mpeek(struct pktq *pq, uint prec_bmp, int *prec_out);
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun /* operations on packet queue as a whole */
248*4882a593Smuzhiyun 
249*4882a593Smuzhiyun #define pktq_n_pkts_tot(pq)	((int)(pq)->n_pkts_tot)
250*4882a593Smuzhiyun #define pktq_max(pq)		((int)(pq)->max_pkts)
251*4882a593Smuzhiyun #define pktq_empty(pq)		((pq)->n_pkts_tot == 0)
252*4882a593Smuzhiyun #define spktq_n_pkts(spq)	((int)(spq)->q.n_pkts)
253*4882a593Smuzhiyun #define spktq_empty(spq)	((spq)->q.n_pkts == 0)
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun #define spktq_max(spq)		((int)(spq)->q.max_pkts)
256*4882a593Smuzhiyun #define spktq_empty(spq)	((spq)->q.n_pkts == 0)
257*4882a593Smuzhiyun #ifdef HND_PKTQ_THREAD_SAFE
258*4882a593Smuzhiyun extern int pktq_avail(struct pktq *pq);
259*4882a593Smuzhiyun extern bool pktq_full(struct pktq *pq);
260*4882a593Smuzhiyun extern int spktq_avail(struct spktq *spq);
261*4882a593Smuzhiyun extern bool spktq_full(struct spktq *spq);
262*4882a593Smuzhiyun #else
263*4882a593Smuzhiyun #define pktq_avail(pq)		((int)((pq)->max_pkts - (pq)->n_pkts_tot))
264*4882a593Smuzhiyun #define pktq_full(pq)		((pq)->n_pkts_tot >= (pq)->max_pkts)
265*4882a593Smuzhiyun #define spktq_avail(spq)	((int)((spq)->q.max_pkts - (spq)->q.n_pkts))
266*4882a593Smuzhiyun #define spktq_full(spq)		((spq)->q.n_pkts >= (spq)->q.max_pkts)
267*4882a593Smuzhiyun #endif	/* HND_PKTQ_THREAD_SAFE */
268*4882a593Smuzhiyun 
269*4882a593Smuzhiyun /* operations for single precedence queues */
270*4882a593Smuzhiyun #define pktenq(pq, p)		pktq_penq((pq), 0, (p))
271*4882a593Smuzhiyun #define pktenq_head(pq, p)	pktq_penq_head((pq), 0, (p))
272*4882a593Smuzhiyun #define pktdeq(pq)		pktq_pdeq((pq), 0)
273*4882a593Smuzhiyun #define pktdeq_tail(pq)		pktq_pdeq_tail((pq), 0)
274*4882a593Smuzhiyun #define pktqflush(osh, pq, dir)	pktq_pflush(osh, (pq), 0, (dir))
275*4882a593Smuzhiyun #define pktqinit(pq, max_pkts)	pktq_init((pq), 1, (max_pkts))
276*4882a593Smuzhiyun #define pktqdeinit(pq)		pktq_deinit((pq))
277*4882a593Smuzhiyun #define pktqavail(pq)		pktq_avail((pq))
278*4882a593Smuzhiyun #define pktqfull(pq)		pktq_full((pq))
279*4882a593Smuzhiyun #define pktqfilter(pq, fltr, fltr_ctx, defer, defer_ctx, flush, flush_ctx) \
280*4882a593Smuzhiyun 	pktq_pfilter((pq), 0, (fltr), (fltr_ctx), (defer), (defer_ctx), (flush), (flush_ctx))
281*4882a593Smuzhiyun 
282*4882a593Smuzhiyun /* operations for simple non-precedence queues */
283*4882a593Smuzhiyun #define spktenq(spq, p)			spktq_enq((spq), (p))
284*4882a593Smuzhiyun #define spktenq_head(spq, p)		spktq_enq_head((spq), (p))
285*4882a593Smuzhiyun #define spktdeq(spq)			spktq_deq((spq))
286*4882a593Smuzhiyun #define spktdeq_tail(spq)		spktq_deq_tail((spq))
287*4882a593Smuzhiyun #define spktqflush(osh, spq, dir)	spktq_flush((osh), (spq), (dir))
288*4882a593Smuzhiyun #define spktqinit(spq, max_pkts)	spktq_init((spq), (max_pkts))
289*4882a593Smuzhiyun #define spktqdeinit(spq)		spktq_deinit((spq))
290*4882a593Smuzhiyun #define spktqavail(spq)			spktq_avail((spq))
291*4882a593Smuzhiyun #define spktqfull(spq)			spktq_full((spq))
292*4882a593Smuzhiyun 
293*4882a593Smuzhiyun #define spktqfilter(spq, fltr, fltr_ctx, defer, defer_ctx, flush, flush_ctx) \
294*4882a593Smuzhiyun 	spktq_filter((spq), (fltr), (fltr_ctx), (defer), (defer_ctx), (flush), (flush_ctx))
295*4882a593Smuzhiyun extern bool pktq_init(struct pktq *pq, int num_prec, uint max_pkts);
296*4882a593Smuzhiyun extern bool pktq_deinit(struct pktq *pq);
297*4882a593Smuzhiyun extern bool spktq_init(struct spktq *spq, uint max_pkts);
298*4882a593Smuzhiyun extern bool spktq_init_list(struct spktq *spq, uint max_pkts,
299*4882a593Smuzhiyun 	void *head, void *tail, uint16 n_pkts);
300*4882a593Smuzhiyun extern bool spktq_deinit(struct spktq *spq);
301*4882a593Smuzhiyun 
302*4882a593Smuzhiyun extern void pktq_set_max_plen(struct pktq *pq, int prec, uint max_pkts);
303*4882a593Smuzhiyun 
304*4882a593Smuzhiyun /* prec_out may be NULL if caller is not interested in return value */
305*4882a593Smuzhiyun extern void *pktq_deq(struct pktq *pq, int *prec_out);
306*4882a593Smuzhiyun extern void *pktq_deq_tail(struct pktq *pq, int *prec_out);
307*4882a593Smuzhiyun extern void *pktq_peek(struct pktq *pq, int *prec_out);
308*4882a593Smuzhiyun extern void *spktq_peek(struct spktq *spq);
309*4882a593Smuzhiyun extern void *pktq_peek_tail(struct pktq *pq, int *prec_out);
310*4882a593Smuzhiyun 
311*4882a593Smuzhiyun /** flush pktq */
312*4882a593Smuzhiyun extern void pktq_flush(osl_t *osh, struct pktq *pq, bool dir);
313*4882a593Smuzhiyun /* single precedence queue with callback before deleting a packet */
314*4882a593Smuzhiyun extern void spktq_flush_ext(osl_t *osh, struct spktq *spq, bool dir,
315*4882a593Smuzhiyun 	void (*pktq_flush_cb)(void *ctx, void *pkt), void *pktq_flush_ctx);
316*4882a593Smuzhiyun /* single precedence queue */
317*4882a593Smuzhiyun #define spktq_flush(osh, spq, dir) spktq_flush_ext(osh, spq, dir, NULL, NULL)
318*4882a593Smuzhiyun /** Empty the queue at particular precedence level */
319*4882a593Smuzhiyun extern void pktq_pflush(osl_t *osh, struct pktq *pq, int prec, bool dir);
320*4882a593Smuzhiyun 
321*4882a593Smuzhiyun typedef void (*spktq_cb_t)(void *arg, struct spktq *spq);
322*4882a593Smuzhiyun extern void spktq_free_register(spktq_cb_t cb, void *arg);
323*4882a593Smuzhiyun extern void spktq_cb(void *spq);
324*4882a593Smuzhiyun #define SPKTQFREE	spktq_cb
325*4882a593Smuzhiyun 
326*4882a593Smuzhiyun #ifdef __cplusplus
327*4882a593Smuzhiyun }
328*4882a593Smuzhiyun #endif
329*4882a593Smuzhiyun 
330*4882a593Smuzhiyun #endif /* _hnd_pktq_h_ */
331