hc
2023-11-06 15ade055295d13f95d49e3d99b09f3bbfb4a43e7
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * HND generic pktq operation primitives
 *
 * Copyright (C) 1999-2019, Broadcom Corporation
 * 
 *      Unless you and Broadcom execute a separate written software license
 * agreement governing use of this software, this software is licensed to you
 * under the terms of the GNU General Public License version 2 (the "GPL"),
 * available at http://www.broadcom.com/licenses/GPLv2.php, with the
 * following added to such license:
 * 
 *      As a special exception, the copyright holders of this software give you
 * permission to link this software with independent modules, and to copy and
 * distribute the resulting executable under terms of your choice, provided that
 * you also meet, for each linked independent module, the terms and conditions of
 * the license of that module.  An independent module is a module which is not
 * derived from this software.  The special exception does not apply to any
 * modifications of the software.
 * 
 *      Notwithstanding the above, under no circumstances may you combine this
 * software in any way with any other Broadcom software provided under a license
 * other than the GPL, without Broadcom's express prior written consent.
 *
 *
 * <<Broadcom-WL-IPTag/Open:>>
 *
 * $Id$
 */
 
#ifndef _hnd_pktq_h_
#define _hnd_pktq_h_
 
#include <osl_ext.h>
 
#ifdef __cplusplus
extern "C" {
#endif
 
/* mutex macros for thread safe */
#ifdef HND_PKTQ_THREAD_SAFE
#define HND_PKTQ_MUTEX_DECL(mutex)        OSL_EXT_MUTEX_DECL(mutex)
#else
#define HND_PKTQ_MUTEX_DECL(mutex)
#endif
 
/* osl multi-precedence packet queue */
#define PKTQ_LEN_MAX            0xFFFF  /* Max uint16 65535 packets */
#ifndef PKTQ_LEN_DEFAULT
#define PKTQ_LEN_DEFAULT        128    /* Max 128 packets */
#endif
#ifndef PKTQ_MAX_PREC
#define PKTQ_MAX_PREC           16    /* Maximum precedence levels */
#endif
 
typedef struct pktq_prec {
   void *head;     /**< first packet to dequeue */
   void *tail;     /**< last packet to dequeue */
   uint16 len;     /**< number of queued packets */
   uint16 max;     /**< maximum number of queued packets */
} pktq_prec_t;
 
#ifdef PKTQ_LOG
typedef struct {
   uint32 requested;    /**< packets requested to be stored */
   uint32 stored;         /**< packets stored */
   uint32 saved;         /**< packets saved,
                               because a lowest priority queue has given away one packet
                         */
   uint32 selfsaved;    /**< packets saved,
                               because an older packet from the same queue has been dropped
                         */
   uint32 full_dropped; /**< packets dropped,
                               because pktq is full with higher precedence packets
                         */
   uint32 dropped;      /**< packets dropped because pktq per that precedence is full */
   uint32 sacrificed;   /**< packets dropped,
                               in order to save one from a queue of a highest priority
                         */
   uint32 busy;         /**< packets droped because of hardware/transmission error */
   uint32 retry;        /**< packets re-sent because they were not received */
   uint32 ps_retry;     /**< packets retried again prior to moving power save mode */
   uint32 suppress;     /**< packets which were suppressed and not transmitted */
   uint32 retry_drop;   /**< packets finally dropped after retry limit */
   uint32 max_avail;    /**< the high-water mark of the queue capacity for packets -
                               goes to zero as queue fills
                         */
   uint32 max_used;     /**< the high-water mark of the queue utilisation for packets -
                               increases with use ('inverse' of max_avail)
                         */
   uint32 queue_capacity; /**< the maximum capacity of the queue */
   uint32 rtsfail;        /**< count of rts attempts that failed to receive cts */
   uint32 acked;          /**< count of packets sent (acked) successfully */
   uint32 txrate_succ;    /**< running total of phy rate of packets sent successfully */
   uint32 txrate_main;    /**< running totoal of primary phy rate of all packets */
   uint32 throughput;     /**< actual data transferred successfully */
   uint32 airtime;        /**< cumulative total medium access delay in useconds */
   uint32  _logtime;      /**< timestamp of last counter clear  */
} pktq_counters_t;
 
typedef struct {
   uint32                  _prec_log;
   pktq_counters_t*        _prec_cnt[PKTQ_MAX_PREC];     /**< Counters per queue  */
} pktq_log_t;
#endif /* PKTQ_LOG */
 
 
#define PKTQ_COMMON    \
   uint16 num_prec;        /**< number of precedences in use */            \
   uint16 hi_prec;         /**< rapid dequeue hint (>= highest non-empty prec) */    \
   uint16 max;             /**< total max packets */                    \
   uint16 len;             /**< total number of packets */
 
/* multi-priority pkt queue */
struct pktq {
   PKTQ_COMMON
   /* q array must be last since # of elements can be either PKTQ_MAX_PREC or 1 */
   struct pktq_prec q[PKTQ_MAX_PREC];
   HND_PKTQ_MUTEX_DECL(mutex)
#ifdef PKTQ_LOG
   pktq_log_t*      pktqlog;
#endif
};
 
/* simple, non-priority pkt queue */
struct spktq {
   PKTQ_COMMON
   /* q array must be last since # of elements can be either PKTQ_MAX_PREC or 1 */
   struct pktq_prec q[1];
   HND_PKTQ_MUTEX_DECL(mutex)
};
 
#define PKTQ_PREC_ITER(pq, prec)        for (prec = (pq)->num_prec - 1; prec >= 0; prec--)
 
/* fn(pkt, arg).  return true if pkt belongs to if */
typedef bool (*ifpkt_cb_t)(void*, int);
 
/* operations on a specific precedence in packet queue */
 
#define pktq_psetmax(pq, prec, _max)    ((pq)->q[prec].max = (_max))
#define pktq_pmax(pq, prec)        ((pq)->q[prec].max)
#define pktq_plen(pq, prec)        ((pq)->q[prec].len)
#define pktq_pempty(pq, prec)        ((pq)->q[prec].len == 0)
#define pktq_ppeek(pq, prec)        ((pq)->q[prec].head)
#define pktq_ppeek_tail(pq, prec)    ((pq)->q[prec].tail)
#ifdef HND_PKTQ_THREAD_SAFE
extern int pktq_pavail(struct pktq *pq, int prec);
extern bool pktq_pfull(struct pktq *pq, int prec);
#else
#define pktq_pavail(pq, prec)    ((pq)->q[prec].max - (pq)->q[prec].len)
#define pktq_pfull(pq, prec)    ((pq)->q[prec].len >= (pq)->q[prec].max)
#endif    /* HND_PKTQ_THREAD_SAFE */
 
extern void  pktq_append(struct pktq *pq, int prec, struct spktq *list);
extern void  pktq_prepend(struct pktq *pq, int prec, struct spktq *list);
 
extern void *pktq_penq(struct pktq *pq, int prec, void *p);
extern void *pktq_penq_head(struct pktq *pq, int prec, void *p);
extern void *pktq_pdeq(struct pktq *pq, int prec);
extern void *pktq_pdeq_prev(struct pktq *pq, int prec, void *prev_p);
extern void *pktq_pdeq_with_fn(struct pktq *pq, int prec, ifpkt_cb_t fn, int arg);
extern void *pktq_pdeq_tail(struct pktq *pq, int prec);
/* Empty the queue at particular precedence level */
extern void pktq_pflush(osl_t *osh, struct pktq *pq, int prec, bool dir,
   ifpkt_cb_t fn, int arg);
/* Remove a specified packet from its queue */
extern bool pktq_pdel(struct pktq *pq, void *p, int prec);
 
/* operations on a set of precedences in packet queue */
 
extern int pktq_mlen(struct pktq *pq, uint prec_bmp);
extern void *pktq_mdeq(struct pktq *pq, uint prec_bmp, int *prec_out);
extern void *pktq_mpeek(struct pktq *pq, uint prec_bmp, int *prec_out);
 
/* operations on packet queue as a whole */
 
#define pktq_len(pq)        ((int)(pq)->len)
#define pktq_max(pq)        ((int)(pq)->max)
#define pktq_empty(pq)        ((pq)->len == 0)
#ifdef HND_PKTQ_THREAD_SAFE
extern int pktq_avail(struct pktq *pq);
extern bool pktq_full(struct pktq *pq);
#else
#define pktq_avail(pq)        ((int)((pq)->max - (pq)->len))
#define pktq_full(pq)        ((pq)->len >= (pq)->max)
#endif    /* HND_PKTQ_THREAD_SAFE */
 
/* operations for single precedence queues */
#define pktenq(pq, p)        pktq_penq(((struct pktq *)(void *)pq), 0, (p))
#define pktenq_head(pq, p)    pktq_penq_head(((struct pktq *)(void *)pq), 0, (p))
#define pktdeq(pq)        pktq_pdeq(((struct pktq *)(void *)pq), 0)
#define pktdeq_tail(pq)        pktq_pdeq_tail(((struct pktq *)(void *)pq), 0)
#define pktqflush(osh, pq)    pktq_flush(osh, ((struct pktq *)(void *)pq), TRUE, NULL, 0)
#define pktqinit(pq, len)    pktq_init(((struct pktq *)(void *)pq), 1, len)
#define pktqdeinit(pq)        pktq_deinit((struct pktq *)(void *)pq)
#define pktqavail(pq)        pktq_avail((struct pktq *)(void *)pq)
#define pktqfull(pq)        pktq_full((struct pktq *)(void *)pq)
 
extern bool pktq_init(struct pktq *pq, int num_prec, int max_len);
extern bool pktq_deinit(struct pktq *pq);
 
extern void pktq_set_max_plen(struct pktq *pq, int prec, int max_len);
 
/* prec_out may be NULL if caller is not interested in return value */
extern void *pktq_deq(struct pktq *pq, int *prec_out);
extern void *pktq_deq_tail(struct pktq *pq, int *prec_out);
extern void *pktq_peek(struct pktq *pq, int *prec_out);
extern void *pktq_peek_tail(struct pktq *pq, int *prec_out);
extern void pktq_flush(osl_t *osh, struct pktq *pq, bool dir, ifpkt_cb_t fn, int arg);
 
#ifdef __cplusplus
   }
#endif
 
#endif /* _hnd_pktq_h_ */