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