summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/rt2x00/rt2x00ring.h
blob: 5b32f3ef2a7356c0ccc7616bdfec72c979b85e22 (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
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
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
/*
	Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
	<http://rt2x00.serialmonkey.com>

	This program is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 2 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the
	Free Software Foundation, Inc.,
	59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

/*
	Module: rt2x00
	Abstract: rt2x00 ring datastructures and routines
 */

#ifndef RT2X00RING_H
#define RT2X00RING_H

/*
 * skb_desc
 * Descriptor information for the skb buffer
 */
struct skb_desc {
	unsigned int frame_type;

	unsigned int desc_len;
	unsigned int data_len;

	void *desc;
	void *data;

	struct data_ring *ring;
	struct data_entry *entry;
};

static inline struct skb_desc* get_skb_desc(struct sk_buff *skb)
{
	return (struct skb_desc*)&skb->cb[0];
}

/*
 * rxdata_entry_desc
 * Summary of information that has been read from the
 * RX frame descriptor.
 */
struct rxdata_entry_desc {
	int signal;
	int rssi;
	int ofdm;
	int size;
	int flags;
};

/*
 * txdata_entry_desc
 * Summary of information that should be written into the
 * descriptor for sending a TX frame.
 */
struct txdata_entry_desc {
	unsigned long flags;
#define ENTRY_TXDONE		1
#define ENTRY_TXD_RTS_FRAME	2
#define ENTRY_TXD_OFDM_RATE	3
#define ENTRY_TXD_MORE_FRAG	4
#define ENTRY_TXD_REQ_TIMESTAMP	5
#define ENTRY_TXD_BURST		6
#define ENTRY_TXD_ACK		7

/*
 * Queue ID. ID's 0-4 are data TX rings
 */
	int queue;
#define QUEUE_MGMT		13
#define QUEUE_RX		14
#define QUEUE_OTHER		15

	/*
	 * PLCP values.
	 */
	u16 length_high;
	u16 length_low;
	u16 signal;
	u16 service;

	/*
	 * Timing information
	 */
	int aifs;
	int ifs;
	int cw_min;
	int cw_max;
};

/*
 * data_entry
 * The data ring is a list of data entries.
 * Each entry holds a reference to the descriptor
 * and the data buffer. For TX rings the reference to the
 * sk_buff of the packet being transmitted is also stored here.
 */
struct data_entry {
	/*
	 * Status flags
	 */
	unsigned long flags;
#define ENTRY_OWNER_NIC		1

	/*
	 * Ring we belong to.
	 */
	struct data_ring *ring;

	/*
	 * sk_buff for the packet which is being transmitted
	 * in this entry (Only used with TX related rings).
	 */
	struct sk_buff *skb;

	/*
	 * Store a ieee80211_tx_status structure in each
	 * ring entry, this will optimize the txdone
	 * handler.
	 */
	struct ieee80211_tx_status tx_status;

	/*
	 * private pointer specific to driver.
	 */
	void *priv;

	/*
	 * Data address for this entry.
	 */
	void *data_addr;
	dma_addr_t data_dma;
};

/*
 * data_ring
 * Data rings are used by the device to send and receive packets.
 * The data_addr is the base address of the data memory.
 * To determine at which point in the ring we are,
 * have to use the rt2x00_ring_index_*() functions.
 */
struct data_ring {
	/*
	 * Pointer to main rt2x00dev structure where this
	 * ring belongs to.
	 */
	struct rt2x00_dev *rt2x00dev;

	/*
	 * Base address for the device specific data entries.
	 */
	struct data_entry *entry;

	/*
	 * TX queue statistic info.
	 */
	struct ieee80211_tx_queue_stats_data stats;

	/*
	 * TX Queue parameters.
	 */
	struct ieee80211_tx_queue_params tx_params;

	/*
	 * Base address for data ring.
	 */
	dma_addr_t data_dma;
	void *data_addr;

	/*
	 * Index variables.
	 */
	u16 index;
	u16 index_done;

	/*
	 * Size of packet and descriptor in bytes.
	 */
	u16 data_size;
	u16 desc_size;
};

/*
 * Handlers to determine the address of the current device specific
 * data entry, where either index or index_done points to.
 */
static inline struct data_entry *rt2x00_get_data_entry(struct data_ring *ring)
{
	return &ring->entry[ring->index];
}

static inline struct data_entry *rt2x00_get_data_entry_done(struct data_ring
							    *ring)
{
	return &ring->entry[ring->index_done];
}

/*
 * Total ring memory
 */
static inline int rt2x00_get_ring_size(struct data_ring *ring)
{
	return ring->stats.limit * (ring->desc_size + ring->data_size);
}

/*
 * Ring index manipulation functions.
 */
static inline void rt2x00_ring_index_inc(struct data_ring *ring)
{
	ring->index++;
	if (ring->index >= ring->stats.limit)
		ring->index = 0;
	ring->stats.len++;
}

static inline void rt2x00_ring_index_done_inc(struct data_ring *ring)
{
	ring->index_done++;
	if (ring->index_done >= ring->stats.limit)
		ring->index_done = 0;
	ring->stats.len--;
	ring->stats.count++;
}

static inline void rt2x00_ring_index_clear(struct data_ring *ring)
{
	ring->index = 0;
	ring->index_done = 0;
	ring->stats.len = 0;
	ring->stats.count = 0;
}

static inline int rt2x00_ring_empty(struct data_ring *ring)
{
	return ring->stats.len == 0;
}

static inline int rt2x00_ring_full(struct data_ring *ring)
{
	return ring->stats.len == ring->stats.limit;
}

static inline int rt2x00_ring_free(struct data_ring *ring)
{
	return ring->stats.limit - ring->stats.len;
}

/*
 * TX/RX Descriptor access functions.
 */
static inline void rt2x00_desc_read(__le32 *desc,
				    const u8 word, u32 *value)
{
	*value = le32_to_cpu(desc[word]);
}

static inline void rt2x00_desc_write(__le32 *desc,
				     const u8 word, const u32 value)
{
	desc[word] = cpu_to_le32(value);
}

#endif /* RT2X00RING_H */