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