Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[linux-2.6] / drivers / net / wireless / rt2x00 / rt2x00queue.c
1 /*
2         Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
3         <http://rt2x00.serialmonkey.com>
4
5         This program is free software; you can redistribute it and/or modify
6         it under the terms of the GNU General Public License as published by
7         the Free Software Foundation; either version 2 of the License, or
8         (at your option) any later version.
9
10         This program is distributed in the hope that it will be useful,
11         but WITHOUT ANY WARRANTY; without even the implied warranty of
12         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13         GNU General Public License for more details.
14
15         You should have received a copy of the GNU General Public License
16         along with this program; if not, write to the
17         Free Software Foundation, Inc.,
18         59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19  */
20
21 /*
22         Module: rt2x00lib
23         Abstract: rt2x00 queue specific routines.
24  */
25
26 #include <linux/kernel.h>
27 #include <linux/module.h>
28
29 #include "rt2x00.h"
30 #include "rt2x00lib.h"
31
32 struct data_queue *rt2x00queue_get_queue(struct rt2x00_dev *rt2x00dev,
33                                          const unsigned int queue)
34 {
35         int atim = test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
36
37         if (queue < rt2x00dev->hw->queues && rt2x00dev->tx)
38                 return &rt2x00dev->tx[queue];
39
40         if (!rt2x00dev->bcn)
41                 return NULL;
42
43         if (queue == RT2X00_BCN_QUEUE_BEACON)
44                 return &rt2x00dev->bcn[0];
45         else if (queue == RT2X00_BCN_QUEUE_ATIM && atim)
46                 return &rt2x00dev->bcn[1];
47
48         return NULL;
49 }
50 EXPORT_SYMBOL_GPL(rt2x00queue_get_queue);
51
52 struct queue_entry *rt2x00queue_get_entry(struct data_queue *queue,
53                                           enum queue_index index)
54 {
55         struct queue_entry *entry;
56
57         if (unlikely(index >= Q_INDEX_MAX)) {
58                 ERROR(queue->rt2x00dev,
59                       "Entry requested from invalid index type (%d)\n", index);
60                 return NULL;
61         }
62
63         spin_lock(&queue->lock);
64
65         entry = &queue->entries[queue->index[index]];
66
67         spin_unlock(&queue->lock);
68
69         return entry;
70 }
71 EXPORT_SYMBOL_GPL(rt2x00queue_get_entry);
72
73 void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index)
74 {
75         if (unlikely(index >= Q_INDEX_MAX)) {
76                 ERROR(queue->rt2x00dev,
77                       "Index change on invalid index type (%d)\n", index);
78                 return;
79         }
80
81         spin_lock(&queue->lock);
82
83         queue->index[index]++;
84         if (queue->index[index] >= queue->limit)
85                 queue->index[index] = 0;
86
87         if (index == Q_INDEX) {
88                 queue->length++;
89         } else if (index == Q_INDEX_DONE) {
90                 queue->length--;
91                 queue->count ++;
92         }
93
94         spin_unlock(&queue->lock);
95 }
96 EXPORT_SYMBOL_GPL(rt2x00queue_index_inc);
97
98 static void rt2x00queue_reset(struct data_queue *queue)
99 {
100         spin_lock(&queue->lock);
101
102         queue->count = 0;
103         queue->length = 0;
104         memset(queue->index, 0, sizeof(queue->index));
105
106         spin_unlock(&queue->lock);
107 }
108
109 void rt2x00queue_init_rx(struct rt2x00_dev *rt2x00dev)
110 {
111         struct data_queue *queue = rt2x00dev->rx;
112         unsigned int i;
113
114         rt2x00queue_reset(queue);
115
116         if (!rt2x00dev->ops->lib->init_rxentry)
117                 return;
118
119         for (i = 0; i < queue->limit; i++)
120                 rt2x00dev->ops->lib->init_rxentry(rt2x00dev,
121                                                   &queue->entries[i]);
122 }
123
124 void rt2x00queue_init_tx(struct rt2x00_dev *rt2x00dev)
125 {
126         struct data_queue *queue;
127         unsigned int i;
128
129         txall_queue_for_each(rt2x00dev, queue) {
130                 rt2x00queue_reset(queue);
131
132                 if (!rt2x00dev->ops->lib->init_txentry)
133                         continue;
134
135                 for (i = 0; i < queue->limit; i++)
136                         rt2x00dev->ops->lib->init_txentry(rt2x00dev,
137                                                           &queue->entries[i]);
138         }
139 }
140
141 static int rt2x00queue_alloc_entries(struct data_queue *queue,
142                                      const struct data_queue_desc *qdesc)
143 {
144         struct queue_entry *entries;
145         unsigned int entry_size;
146         unsigned int i;
147
148         rt2x00queue_reset(queue);
149
150         queue->limit = qdesc->entry_num;
151         queue->data_size = qdesc->data_size;
152         queue->desc_size = qdesc->desc_size;
153
154         /*
155          * Allocate all queue entries.
156          */
157         entry_size = sizeof(*entries) + qdesc->priv_size;
158         entries = kzalloc(queue->limit * entry_size, GFP_KERNEL);
159         if (!entries)
160                 return -ENOMEM;
161
162 #define QUEUE_ENTRY_PRIV_OFFSET(__base, __index, __limit, __esize, __psize) \
163         ( ((char *)(__base)) + ((__limit) * (__esize)) + \
164             ((__index) * (__psize)) )
165
166         for (i = 0; i < queue->limit; i++) {
167                 entries[i].flags = 0;
168                 entries[i].queue = queue;
169                 entries[i].skb = NULL;
170                 entries[i].entry_idx = i;
171                 entries[i].priv_data =
172                     QUEUE_ENTRY_PRIV_OFFSET(entries, i, queue->limit,
173                                             sizeof(*entries), qdesc->priv_size);
174         }
175
176 #undef QUEUE_ENTRY_PRIV_OFFSET
177
178         queue->entries = entries;
179
180         return 0;
181 }
182
183 int rt2x00queue_initialize(struct rt2x00_dev *rt2x00dev)
184 {
185         struct data_queue *queue;
186         int status;
187
188
189         status = rt2x00queue_alloc_entries(rt2x00dev->rx, rt2x00dev->ops->rx);
190         if (status)
191                 goto exit;
192
193         tx_queue_for_each(rt2x00dev, queue) {
194                 status = rt2x00queue_alloc_entries(queue, rt2x00dev->ops->tx);
195                 if (status)
196                         goto exit;
197         }
198
199         status = rt2x00queue_alloc_entries(rt2x00dev->bcn, rt2x00dev->ops->bcn);
200         if (status)
201                 goto exit;
202
203         if (!test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags))
204                 return 0;
205
206         status = rt2x00queue_alloc_entries(&rt2x00dev->bcn[1],
207                                            rt2x00dev->ops->atim);
208         if (status)
209                 goto exit;
210
211         return 0;
212
213 exit:
214         ERROR(rt2x00dev, "Queue entries allocation failed.\n");
215
216         rt2x00queue_uninitialize(rt2x00dev);
217
218         return status;
219 }
220
221 void rt2x00queue_uninitialize(struct rt2x00_dev *rt2x00dev)
222 {
223         struct data_queue *queue;
224
225         queue_for_each(rt2x00dev, queue) {
226                 kfree(queue->entries);
227                 queue->entries = NULL;
228         }
229 }
230
231 static void rt2x00queue_init(struct rt2x00_dev *rt2x00dev,
232                              struct data_queue *queue, enum data_queue_qid qid)
233 {
234         spin_lock_init(&queue->lock);
235
236         queue->rt2x00dev = rt2x00dev;
237         queue->qid = qid;
238         queue->aifs = 2;
239         queue->cw_min = 5;
240         queue->cw_max = 10;
241 }
242
243 int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev)
244 {
245         struct data_queue *queue;
246         enum data_queue_qid qid;
247         unsigned int req_atim =
248             !!test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
249
250         /*
251          * We need the following queues:
252          * RX: 1
253          * TX: hw->queues
254          * Beacon: 1
255          * Atim: 1 (if required)
256          */
257         rt2x00dev->data_queues = 2 + rt2x00dev->hw->queues + req_atim;
258
259         queue = kzalloc(rt2x00dev->data_queues * sizeof(*queue), GFP_KERNEL);
260         if (!queue) {
261                 ERROR(rt2x00dev, "Queue allocation failed.\n");
262                 return -ENOMEM;
263         }
264
265         /*
266          * Initialize pointers
267          */
268         rt2x00dev->rx = queue;
269         rt2x00dev->tx = &queue[1];
270         rt2x00dev->bcn = &queue[1 + rt2x00dev->hw->queues];
271
272         /*
273          * Initialize queue parameters.
274          * RX: qid = QID_RX
275          * TX: qid = QID_AC_BE + index
276          * TX: cw_min: 2^5 = 32.
277          * TX: cw_max: 2^10 = 1024.
278          * BCN & Atim: qid = QID_MGMT
279          */
280         rt2x00queue_init(rt2x00dev, rt2x00dev->rx, QID_RX);
281
282         qid = QID_AC_BE;
283         tx_queue_for_each(rt2x00dev, queue)
284                 rt2x00queue_init(rt2x00dev, queue, qid++);
285
286         rt2x00queue_init(rt2x00dev, &rt2x00dev->bcn[0], QID_MGMT);
287         if (req_atim)
288                 rt2x00queue_init(rt2x00dev, &rt2x00dev->bcn[1], QID_MGMT);
289
290         return 0;
291 }
292
293 void rt2x00queue_free(struct rt2x00_dev *rt2x00dev)
294 {
295         kfree(rt2x00dev->rx);
296         rt2x00dev->rx = NULL;
297         rt2x00dev->tx = NULL;
298         rt2x00dev->bcn = NULL;
299 }