summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/bcmdhd/include/hnd_pktq.h
blob: c27a21d581bab5a3300f6df9b754fa03e0894db8 (plain)
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
/*
 * HND generic pktq operation primitives
 *
 * $Copyright Open Broadcom Corporation$
 *
 * $Id: $
 */

#ifndef _hnd_pktq_h_
#define _hnd_pktq_h_

#ifdef __cplusplus
extern "C" {
#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];
#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];
};

#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_pavail(pq, prec)		((pq)->q[prec].max - (pq)->q[prec].len)
#define pktq_pfull(pq, prec)		((pq)->q[prec].len >= (pq)->q[prec].max)
#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)

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_avail(pq)		((int)((pq)->max - (pq)->len))
#define pktq_full(pq)		((pq)->len >= (pq)->max)
#define pktq_empty(pq)		((pq)->len == 0)

/* 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)

extern void pktq_init(struct pktq *pq, int num_prec, int max_len);
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_ */