2 * HND generic pktq operation primitives
4 * Copyright (C) 1999-2016, Broadcom Corporation
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:
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.
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.
25 * <<Broadcom-WL-IPTag/Open:>>
27 * $Id: hnd_pktq.h 591283 2015-10-07 11:52:00Z $
39 /* mutex macros for thread safe */
40 #ifdef HND_PKTQ_THREAD_SAFE
41 #define HND_PKTQ_MUTEX_DECL(mutex) OSL_EXT_MUTEX_DECL(mutex)
43 #define HND_PKTQ_MUTEX_DECL(mutex)
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 */
52 #define PKTQ_MAX_PREC 16 /* Maximum precedence levels */
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 */
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
69 uint32 selfsaved; /**< packets saved,
70 because an older packet from the same queue has been dropped
72 uint32 full_dropped; /**< packets dropped,
73 because pktq is full with higher precedence packets
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
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
87 uint32 max_used; /**< the high-water mark of the queue utilisation for packets -
88 increases with use ('inverse' of max_avail)
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 */
102 pktq_counters_t* _prec_cnt[PKTQ_MAX_PREC]; /**< Counters per queue */
104 #endif /* PKTQ_LOG */
107 #define PKTQ_COMMON \
108 uint16 num_prec; /**< number of precedences in use */ \
109 uint16 hi_prec; /**< rapid dequeue hint (>= highest non-empty prec) */ \
110 uint16 max; /**< total max packets */ \
111 uint16 len; /**< total number of packets */
113 /* multi-priority pkt queue */
116 /* q array must be last since # of elements can be either PKTQ_MAX_PREC or 1 */
117 struct pktq_prec q[PKTQ_MAX_PREC];
118 HND_PKTQ_MUTEX_DECL(mutex)
124 /* simple, non-priority pkt queue */
127 /* q array must be last since # of elements can be either PKTQ_MAX_PREC or 1 */
128 struct pktq_prec q[1];
129 HND_PKTQ_MUTEX_DECL(mutex)
132 #define PKTQ_PREC_ITER(pq, prec) for (prec = (pq)->num_prec - 1; prec >= 0; prec--)
134 /* fn(pkt, arg). return true if pkt belongs to if */
135 typedef bool (*ifpkt_cb_t)(void*, int);
137 /* operations on a specific precedence in packet queue */
139 #define pktq_psetmax(pq, prec, _max) ((pq)->q[prec].max = (_max))
140 #define pktq_pmax(pq, prec) ((pq)->q[prec].max)
141 #define pktq_plen(pq, prec) ((pq)->q[prec].len)
142 #define pktq_pempty(pq, prec) ((pq)->q[prec].len == 0)
143 #define pktq_ppeek(pq, prec) ((pq)->q[prec].head)
144 #define pktq_ppeek_tail(pq, prec) ((pq)->q[prec].tail)
145 #ifdef HND_PKTQ_THREAD_SAFE
146 extern int pktq_pavail(struct pktq *pq, int prec);
147 extern bool pktq_pfull(struct pktq *pq, int prec);
149 #define pktq_pavail(pq, prec) ((pq)->q[prec].max - (pq)->q[prec].len)
150 #define pktq_pfull(pq, prec) ((pq)->q[prec].len >= (pq)->q[prec].max)
151 #endif /* HND_PKTQ_THREAD_SAFE */
153 extern void pktq_append(struct pktq *pq, int prec, struct spktq *list);
154 extern void pktq_prepend(struct pktq *pq, int prec, struct spktq *list);
156 extern void *pktq_penq(struct pktq *pq, int prec, void *p);
157 extern void *pktq_penq_head(struct pktq *pq, int prec, void *p);
158 extern void *pktq_pdeq(struct pktq *pq, int prec);
159 extern void *pktq_pdeq_prev(struct pktq *pq, int prec, void *prev_p);
160 extern void *pktq_pdeq_with_fn(struct pktq *pq, int prec, ifpkt_cb_t fn, int arg);
161 extern void *pktq_pdeq_tail(struct pktq *pq, int prec);
162 /* Empty the queue at particular precedence level */
163 extern void pktq_pflush(osl_t *osh, struct pktq *pq, int prec, bool dir,
164 ifpkt_cb_t fn, int arg);
165 /* Remove a specified packet from its queue */
166 extern bool pktq_pdel(struct pktq *pq, void *p, int prec);
168 /* operations on a set of precedences in packet queue */
170 extern int pktq_mlen(struct pktq *pq, uint prec_bmp);
171 extern void *pktq_mdeq(struct pktq *pq, uint prec_bmp, int *prec_out);
172 extern void *pktq_mpeek(struct pktq *pq, uint prec_bmp, int *prec_out);
174 /* operations on packet queue as a whole */
176 #define pktq_len(pq) ((int)(pq)->len)
177 #define pktq_max(pq) ((int)(pq)->max)
178 #define pktq_empty(pq) ((pq)->len == 0)
179 #ifdef HND_PKTQ_THREAD_SAFE
180 extern int pktq_avail(struct pktq *pq);
181 extern bool pktq_full(struct pktq *pq);
183 #define pktq_avail(pq) ((int)((pq)->max - (pq)->len))
184 #define pktq_full(pq) ((pq)->len >= (pq)->max)
185 #endif /* HND_PKTQ_THREAD_SAFE */
187 /* operations for single precedence queues */
188 #define pktenq(pq, p) pktq_penq(((struct pktq *)(void *)pq), 0, (p))
189 #define pktenq_head(pq, p) pktq_penq_head(((struct pktq *)(void *)pq), 0, (p))
190 #define pktdeq(pq) pktq_pdeq(((struct pktq *)(void *)pq), 0)
191 #define pktdeq_tail(pq) pktq_pdeq_tail(((struct pktq *)(void *)pq), 0)
192 #define pktqflush(osh, pq) pktq_flush(osh, ((struct pktq *)(void *)pq), TRUE, NULL, 0)
193 #define pktqinit(pq, len) pktq_init(((struct pktq *)(void *)pq), 1, len)
194 #define pktqdeinit(pq) pktq_deinit((struct pktq *)(void *)pq)
195 #define pktqavail(pq) pktq_avail((struct pktq *)(void *)pq)
196 #define pktqfull(pq) pktq_full((struct pktq *)(void *)pq)
198 extern bool pktq_init(struct pktq *pq, int num_prec, int max_len);
199 extern bool pktq_deinit(struct pktq *pq);
201 extern void pktq_set_max_plen(struct pktq *pq, int prec, int max_len);
203 /* prec_out may be NULL if caller is not interested in return value */
204 extern void *pktq_deq(struct pktq *pq, int *prec_out);
205 extern void *pktq_deq_tail(struct pktq *pq, int *prec_out);
206 extern void *pktq_peek(struct pktq *pq, int *prec_out);
207 extern void *pktq_peek_tail(struct pktq *pq, int *prec_out);
208 extern void pktq_flush(osl_t *osh, struct pktq *pq, bool dir, ifpkt_cb_t fn, int arg);
214 #endif /* _hnd_pktq_h_ */