• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * HND generic pktq operation primitives
3  *
4  * Copyright (C) 1999-2017, Broadcom Corporation
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 641285 2016-06-02 02:33:55Z $
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
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
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
51 #ifndef PKTQ_MAX_PREC
52 #define PKTQ_MAX_PREC           16    /* Maximum precedence levels */
53 #endif
54 
55 typedef struct pktq_prec {
56     void *head;     /**< first packet to dequeue */
57     void *tail;     /**< last packet to dequeue */
58     uint16 len;     /**< number of queued packets */
59     uint16 max;     /**< maximum number of queued packets */
60 } pktq_prec_t;
61 
62 #ifdef PKTQ_LOG
63 typedef struct {
64     uint32 requested;    /**< packets requested to be stored */
65     uint32 stored;         /**< packets stored */
66     uint32 saved;         /**< packets saved,
67                                 because a lowest priority queue has given away one packet
68                           */
69     uint32 selfsaved;    /**< packets saved,
70                                 because an older packet from the same queue has been dropped
71                           */
72     uint32 full_dropped; /**< packets dropped,
73                                 because pktq is full with higher precedence packets
74                           */
75     uint32 dropped;      /**< packets dropped because pktq per that precedence is full */
76     uint32 sacrificed;   /**< packets dropped,
77                                 in order to save one from a queue of a highest priority
78                           */
79     uint32 busy;         /**< packets droped because of hardware/transmission error */
80     uint32 retry;        /**< packets re-sent because they were not received */
81     uint32 ps_retry;     /**< packets retried again prior to moving power save mode */
82     uint32 suppress;     /**< packets which were suppressed and not transmitted */
83     uint32 retry_drop;   /**< packets finally dropped after retry limit */
84     uint32 max_avail;    /**< the high-water mark of the queue capacity for packets -
85                                 goes to zero as queue fills
86                           */
87     uint32 max_used;     /**< the high-water mark of the queue utilisation for packets -
88                                 increases with use ('inverse' of max_avail)
89                           */
90     uint32 queue_capacity; /**< the maximum capacity of the queue */
91     uint32 rtsfail;        /**< count of rts attempts that failed to receive cts */
92     uint32 acked;          /**< count of packets sent (acked) successfully */
93     uint32 txrate_succ;    /**< running total of phy rate of packets sent successfully */
94     uint32 txrate_main;    /**< running totoal of primary phy rate of all packets */
95     uint32 throughput;     /**< actual data transferred successfully */
96     uint32 airtime;        /**< cumulative total medium access delay in useconds */
97     uint32  _logtime;      /**< timestamp of last counter clear  */
98 } pktq_counters_t;
99 
100 #define PKTQ_LOG_COMMON \
101     uint32            pps_time;    /**< time spent in ps pretend state */ \
102     uint32                  _prec_log;
103 
104 typedef struct {
105     PKTQ_LOG_COMMON
106     pktq_counters_t*        _prec_cnt[PKTQ_MAX_PREC];     /**< Counters per queue  */
107 } pktq_log_t;
108 #else
109 typedef struct pktq_log pktq_log_t;
110 #endif /* PKTQ_LOG */
111 
112 
113 #define PKTQ_COMMON    \
114     HND_PKTQ_MUTEX_DECL(mutex)                            \
115     pktq_log_t *pktqlog;                                \
116     uint16 num_prec;        /**< number of precedences in use */            \
117     uint16 hi_prec;         /**< rapid dequeue hint (>= highest non-empty prec) */    \
118     uint16 max;             /**< total max packets */                \
119     uint16 len;             /**< total number of packets */
120 
121 /* multi-priority pkt queue */
122 struct pktq {
123     PKTQ_COMMON
124     /* q array must be last since # of elements can be either PKTQ_MAX_PREC or 1 */
125     struct pktq_prec q[PKTQ_MAX_PREC];
126 };
127 
128 /* simple, non-priority pkt queue */
129 struct spktq {
130     PKTQ_COMMON
131     /* q array must be last since # of elements can be either PKTQ_MAX_PREC or 1 */
132     struct pktq_prec q[1];
133 };
134 
135 #define PKTQ_PREC_ITER(pq, prec)        for (prec = (pq)->num_prec - 1; prec >= 0; prec--)
136 
137 /* fn(pkt, arg).  return true if pkt belongs to bsscfg */
138 typedef bool (*ifpkt_cb_t)(void*, int);
139 
140 /*
141  * pktq filter support
142  */
143 
144 /* filter function return values */
145 typedef enum {
146     PKT_FILTER_NOACTION = 0,    /**< restore the pkt to its position in the queue */
147     PKT_FILTER_DELETE = 1,      /**< delete the pkt */
148     PKT_FILTER_REMOVE = 2,      /**< do not restore the pkt to the queue,
149                                  *   filter fn has taken ownership of the pkt
150                                  */
151 } pktq_filter_result_t;
152 
153 /**
154  * Caller supplied filter function to pktq_pfilter(), pktq_filter().
155  * Function filter(ctx, pkt) is called with its ctx pointer on each pkt in the
156  * pktq.  When the filter function is called, the supplied pkt will have been
157  * unlinked from the pktq.  The filter function returns a pktq_filter_result_t
158  * result specifying the action pktq_filter()/pktq_pfilter() should take for
159  * the pkt.
160  * Here are the actions taken by pktq_filter/pfilter() based on the supplied
161  * filter function's return value:
162  *
163  * PKT_FILTER_NOACTION - The filter will re-link the pkt at its
164  *     previous location.
165  *
166  * PKT_FILTER_DELETE - The filter will not relink the pkt and will
167  *     call the user supplied defer_free_pkt fn on the packet.
168  *
169  * PKT_FILTER_REMOVE - The filter will not relink the pkt. The supplied
170  *     filter fn took ownership (or deleted) the pkt.
171  *
172  * WARNING: pkts inserted by the user (in pkt_filter and/or flush callbacks
173  * and chains) in the prec queue will not be seen by the filter, and the prec
174  * queue will be temporarily be removed from the queue hence there're side
175  * effects including pktq_len() on the queue won't reflect the correct number
176  * of packets in the queue.
177  */
178 typedef pktq_filter_result_t (*pktq_filter_t)(void* ctx, void* pkt);
179 
180 /* The defer_free_pkt callback is invoked when the the pktq_filter callback
181  * returns PKT_FILTER_DELETE decision, which allows the user to deposite
182  * the packet appropriately based on the situation (free the packet or
183  * save it in a temporary queue etc.).
184  */
185 typedef void (*defer_free_pkt_fn_t)(void *ctx, void *pkt);
186 
187 /* The flush_free_pkt callback is invoked when all packets in the pktq
188  * are processed.
189  */
190 typedef void (*flush_free_pkt_fn_t)(void *ctx);
191 
192 /* filter a pktq, using the caller supplied filter/deposition/flush functions */
193 extern void  pktq_filter(struct pktq *pq, pktq_filter_t fn, void* arg,
194     defer_free_pkt_fn_t defer, void *defer_ctx, flush_free_pkt_fn_t flush, void *flush_ctx);
195 /* filter a particular precedence in pktq, using the caller supplied filter function */
196 extern void  pktq_pfilter(struct pktq *pq, int prec, pktq_filter_t fn, void* arg,
197     defer_free_pkt_fn_t defer, void *defer_ctx, flush_free_pkt_fn_t flush, void *flush_ctx);
198 
199 /* operations on a specific precedence in packet queue */
200 
201 #define pktq_psetmax(pq, prec, _max)    ((pq)->q[prec].max = (_max))
202 #define pktq_pmax(pq, prec)        ((pq)->q[prec].max)
203 #define pktq_plen(pq, prec)        ((pq)->q[prec].len)
204 #define pktq_pempty(pq, prec)        ((pq)->q[prec].len == 0)
205 #define pktq_ppeek(pq, prec)        ((pq)->q[prec].head)
206 #define pktq_ppeek_tail(pq, prec)    ((pq)->q[prec].tail)
207 #ifdef HND_PKTQ_THREAD_SAFE
208 extern int pktq_pavail(struct pktq *pq, int prec);
209 extern bool pktq_pfull(struct pktq *pq, int prec);
210 #else
211 #define pktq_pavail(pq, prec)    ((pq)->q[prec].max - (pq)->q[prec].len)
212 #define pktq_pfull(pq, prec)    ((pq)->q[prec].len >= (pq)->q[prec].max)
213 #endif    /* HND_PKTQ_THREAD_SAFE */
214 
215 extern void  pktq_append(struct pktq *pq, int prec, struct spktq *list);
216 extern void  pktq_prepend(struct pktq *pq, int prec, struct spktq *list);
217 
218 extern void *pktq_penq(struct pktq *pq, int prec, void *p);
219 extern void *pktq_penq_head(struct pktq *pq, int prec, void *p);
220 extern void *pktq_pdeq(struct pktq *pq, int prec);
221 extern void *pktq_pdeq_prev(struct pktq *pq, int prec, void *prev_p);
222 extern void *pktq_pdeq_with_fn(struct pktq *pq, int prec, ifpkt_cb_t fn, int arg);
223 extern void *pktq_pdeq_tail(struct pktq *pq, int prec);
224 /* Remove a specified packet from its queue */
225 extern bool pktq_pdel(struct pktq *pq, void *p, int prec);
226 
227 /* operations on a set of precedences in packet queue */
228 
229 extern int pktq_mlen(struct pktq *pq, uint prec_bmp);
230 extern void *pktq_mdeq(struct pktq *pq, uint prec_bmp, int *prec_out);
231 extern void *pktq_mpeek(struct pktq *pq, uint prec_bmp, int *prec_out);
232 
233 /* operations on packet queue as a whole */
234 
235 #define pktq_len(pq)        ((int)(pq)->len)
236 #define pktq_max(pq)        ((int)(pq)->max)
237 #define pktq_empty(pq)        ((pq)->len == 0)
238 #ifdef HND_PKTQ_THREAD_SAFE
239 extern int pktq_avail(struct pktq *pq);
240 extern bool pktq_full(struct pktq *pq);
241 #else
242 #define pktq_avail(pq)        ((int)((pq)->max - (pq)->len))
243 #define pktq_full(pq)        ((pq)->len >= (pq)->max)
244 #endif    /* HND_PKTQ_THREAD_SAFE */
245 
246 /* operations for single precedence queues */
247 #define pktenq(pq, p)        pktq_penq(((struct pktq *)(void *)pq), 0, (p))
248 #define pktenq_head(pq, p)    pktq_penq_head(((struct pktq *)(void *)pq), 0, (p))
249 #define pktdeq(pq)        pktq_pdeq(((struct pktq *)(void *)pq), 0)
250 #define pktdeq_tail(pq)        pktq_pdeq_tail(((struct pktq *)(void *)pq), 0)
251 #define pktqflush(osh, pq, dir)    pktq_pflush(osh, ((struct pktq *)(void *)pq), 0, dir)
252 #define pktqinit(pq, len)    pktq_init(((struct pktq *)(void *)pq), 1, len)
253 #define pktqdeinit(pq)        pktq_deinit((struct pktq *)(void *)pq)
254 #define pktqavail(pq)        pktq_avail((struct pktq *)(void *)pq)
255 #define pktqfull(pq)        pktq_full((struct pktq *)(void *)pq)
256 #define pktqfilter(pq, fltr, fltr_ctx, defer, defer_ctx, flush, flush_ctx) \
257     pktq_pfilter((struct pktq *)pq, 0, fltr, fltr_ctx, defer, defer_ctx, flush, flush_ctx)
258 
259 /* wrap macros for modules in components use */
260 #define spktqinit(pq, max_pkts) pktqinit(pq, max_pkts)
261 #define spktenq(pq, p)          pktenq(pq, p)
262 #define spktdeq(pq)             pktdeq(pq)
263 
264 extern bool pktq_init(struct pktq *pq, int num_prec, int max_len);
265 extern bool pktq_deinit(struct pktq *pq);
266 
267 extern void pktq_set_max_plen(struct pktq *pq, int prec, int max_len);
268 
269 /* prec_out may be NULL if caller is not interested in return value */
270 extern void *pktq_deq(struct pktq *pq, int *prec_out);
271 extern void *pktq_deq_tail(struct pktq *pq, int *prec_out);
272 extern void *pktq_peek(struct pktq *pq, int *prec_out);
273 extern void *pktq_peek_tail(struct pktq *pq, int *prec_out);
274 
275 /* flush pktq */
276 extern void pktq_flush(osl_t *osh, struct pktq *pq, bool dir);
277 /* Empty the queue at particular precedence level */
278 extern void pktq_pflush(osl_t *osh, struct pktq *pq, int prec, bool dir);
279 
280 #ifdef __cplusplus
281 }
282 #endif
283 
284 #endif /* _hnd_pktq_h_ */
285