Commit | Line | Data |
---|---|---|
95ea3627 | 1 | /* |
811aa9ca | 2 | Copyright (C) 2004 - 2008 rt2x00 SourceForge Project |
95ea3627 ID |
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: rt2x00usb | |
23 | Abstract: rt2x00 generic usb device routines. | |
24 | */ | |
25 | ||
95ea3627 ID |
26 | #include <linux/kernel.h> |
27 | #include <linux/module.h> | |
28 | #include <linux/usb.h> | |
3d82346c | 29 | #include <linux/bug.h> |
95ea3627 ID |
30 | |
31 | #include "rt2x00.h" | |
32 | #include "rt2x00usb.h" | |
33 | ||
34 | /* | |
35 | * Interfacing with the HW. | |
36 | */ | |
0e14f6d3 | 37 | int rt2x00usb_vendor_request(struct rt2x00_dev *rt2x00dev, |
95ea3627 ID |
38 | const u8 request, const u8 requesttype, |
39 | const u16 offset, const u16 value, | |
40 | void *buffer, const u16 buffer_length, | |
e9136550 | 41 | const int timeout) |
95ea3627 | 42 | { |
181d6902 | 43 | struct usb_device *usb_dev = rt2x00dev_usb_dev(rt2x00dev); |
95ea3627 ID |
44 | int status; |
45 | unsigned int i; | |
46 | unsigned int pipe = | |
47 | (requesttype == USB_VENDOR_REQUEST_IN) ? | |
48 | usb_rcvctrlpipe(usb_dev, 0) : usb_sndctrlpipe(usb_dev, 0); | |
49 | ||
3d82346c | 50 | |
95ea3627 ID |
51 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { |
52 | status = usb_control_msg(usb_dev, pipe, request, requesttype, | |
53 | value, offset, buffer, buffer_length, | |
54 | timeout); | |
55 | if (status >= 0) | |
56 | return 0; | |
57 | ||
58 | /* | |
e9136550 | 59 | * Check for errors |
95ea3627 | 60 | * -ENODEV: Device has disappeared, no point continuing. |
e9136550 | 61 | * All other errors: Try again. |
95ea3627 | 62 | */ |
95ea3627 ID |
63 | else if (status == -ENODEV) |
64 | break; | |
65 | } | |
66 | ||
67 | ERROR(rt2x00dev, | |
68 | "Vendor Request 0x%02x failed for offset 0x%04x with error %d.\n", | |
69 | request, offset, status); | |
70 | ||
71 | return status; | |
72 | } | |
73 | EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request); | |
74 | ||
3d82346c AB |
75 | int rt2x00usb_vendor_req_buff_lock(struct rt2x00_dev *rt2x00dev, |
76 | const u8 request, const u8 requesttype, | |
77 | const u16 offset, void *buffer, | |
78 | const u16 buffer_length, const int timeout) | |
95ea3627 ID |
79 | { |
80 | int status; | |
81 | ||
3d82346c AB |
82 | BUG_ON(!mutex_is_locked(&rt2x00dev->usb_cache_mutex)); |
83 | ||
95ea3627 ID |
84 | /* |
85 | * Check for Cache availability. | |
86 | */ | |
21795094 | 87 | if (unlikely(!rt2x00dev->csr.cache || buffer_length > CSR_CACHE_SIZE)) { |
95ea3627 ID |
88 | ERROR(rt2x00dev, "CSR cache not available.\n"); |
89 | return -ENOMEM; | |
90 | } | |
91 | ||
92 | if (requesttype == USB_VENDOR_REQUEST_OUT) | |
21795094 | 93 | memcpy(rt2x00dev->csr.cache, buffer, buffer_length); |
95ea3627 ID |
94 | |
95 | status = rt2x00usb_vendor_request(rt2x00dev, request, requesttype, | |
21795094 | 96 | offset, 0, rt2x00dev->csr.cache, |
95ea3627 ID |
97 | buffer_length, timeout); |
98 | ||
99 | if (!status && requesttype == USB_VENDOR_REQUEST_IN) | |
21795094 | 100 | memcpy(buffer, rt2x00dev->csr.cache, buffer_length); |
95ea3627 ID |
101 | |
102 | return status; | |
103 | } | |
3d82346c AB |
104 | EXPORT_SYMBOL_GPL(rt2x00usb_vendor_req_buff_lock); |
105 | ||
106 | int rt2x00usb_vendor_request_buff(struct rt2x00_dev *rt2x00dev, | |
107 | const u8 request, const u8 requesttype, | |
108 | const u16 offset, void *buffer, | |
109 | const u16 buffer_length, const int timeout) | |
110 | { | |
111 | int status; | |
112 | ||
113 | mutex_lock(&rt2x00dev->usb_cache_mutex); | |
114 | ||
115 | status = rt2x00usb_vendor_req_buff_lock(rt2x00dev, request, | |
116 | requesttype, offset, buffer, | |
117 | buffer_length, timeout); | |
118 | ||
119 | mutex_unlock(&rt2x00dev->usb_cache_mutex); | |
120 | ||
121 | return status; | |
122 | } | |
95ea3627 ID |
123 | EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request_buff); |
124 | ||
125 | /* | |
126 | * TX data handlers. | |
127 | */ | |
128 | static void rt2x00usb_interrupt_txdone(struct urb *urb) | |
129 | { | |
181d6902 ID |
130 | struct queue_entry *entry = (struct queue_entry *)urb->context; |
131 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | |
132 | struct queue_entry_priv_usb_tx *priv_tx = entry->priv_data; | |
133 | struct txdone_entry_desc txdesc; | |
4bd7c452 | 134 | __le32 *txd = (__le32 *)entry->skb->data; |
95ea3627 | 135 | u32 word; |
95ea3627 ID |
136 | |
137 | if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) || | |
181d6902 | 138 | !__test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) |
95ea3627 ID |
139 | return; |
140 | ||
141 | rt2x00_desc_read(txd, 0, &word); | |
142 | ||
143 | /* | |
144 | * Remove the descriptor data from the buffer. | |
145 | */ | |
181d6902 | 146 | skb_pull(entry->skb, entry->queue->desc_size); |
95ea3627 ID |
147 | |
148 | /* | |
149 | * Obtain the status about this packet. | |
150 | */ | |
181d6902 ID |
151 | txdesc.status = !urb->status ? TX_SUCCESS : TX_FAIL_RETRY; |
152 | txdesc.retry = 0; | |
153 | txdesc.control = &priv_tx->control; | |
95ea3627 | 154 | |
181d6902 | 155 | rt2x00lib_txdone(entry, &txdesc); |
95ea3627 ID |
156 | |
157 | /* | |
158 | * Make this entry available for reuse. | |
159 | */ | |
160 | entry->flags = 0; | |
181d6902 | 161 | rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE); |
95ea3627 ID |
162 | |
163 | /* | |
181d6902 | 164 | * If the data queue was full before the txdone handler |
95ea3627 ID |
165 | * we must make sure the packet queue in the mac80211 stack |
166 | * is reenabled when the txdone handler has finished. | |
167 | */ | |
181d6902 ID |
168 | if (!rt2x00queue_full(entry->queue)) |
169 | ieee80211_wake_queue(rt2x00dev->hw, priv_tx->control.queue); | |
95ea3627 ID |
170 | } |
171 | ||
172 | int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev, | |
181d6902 | 173 | struct data_queue *queue, struct sk_buff *skb, |
95ea3627 ID |
174 | struct ieee80211_tx_control *control) |
175 | { | |
181d6902 ID |
176 | struct usb_device *usb_dev = rt2x00dev_usb_dev(rt2x00dev); |
177 | struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX); | |
178 | struct queue_entry_priv_usb_tx *priv_tx = entry->priv_data; | |
179 | struct skb_frame_desc *skbdesc; | |
dd9fa2d2 | 180 | u32 length; |
95ea3627 | 181 | |
181d6902 | 182 | if (rt2x00queue_full(queue)) |
95ea3627 | 183 | return -EINVAL; |
95ea3627 | 184 | |
181d6902 | 185 | if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) { |
95ea3627 ID |
186 | ERROR(rt2x00dev, |
187 | "Arrived at non-free entry in the non-full queue %d.\n" | |
188 | "Please file bug report to %s.\n", | |
e58c6aca | 189 | entry->queue->qid, DRV_PROJECT); |
95ea3627 ID |
190 | return -EINVAL; |
191 | } | |
192 | ||
193 | /* | |
194 | * Add the descriptor in front of the skb. | |
195 | */ | |
181d6902 ID |
196 | skb_push(skb, queue->desc_size); |
197 | memset(skb->data, 0, queue->desc_size); | |
95ea3627 | 198 | |
08992f7f ID |
199 | /* |
200 | * Fill in skb descriptor | |
201 | */ | |
181d6902 | 202 | skbdesc = get_skb_frame_desc(skb); |
181d6902 | 203 | skbdesc->data = skb->data + queue->desc_size; |
647d0ca9 | 204 | skbdesc->data_len = skb->len - queue->desc_size; |
181d6902 ID |
205 | skbdesc->desc = skb->data; |
206 | skbdesc->desc_len = queue->desc_size; | |
207 | skbdesc->entry = entry; | |
08992f7f | 208 | |
92f5ac63 | 209 | memcpy(&priv_tx->control, control, sizeof(priv_tx->control)); |
08992f7f | 210 | rt2x00lib_write_tx_desc(rt2x00dev, skb, control); |
95ea3627 ID |
211 | |
212 | /* | |
dd9fa2d2 ID |
213 | * USB devices cannot blindly pass the skb->len as the |
214 | * length of the data to usb_fill_bulk_urb. Pass the skb | |
215 | * to the driver to determine what the length should be. | |
95ea3627 | 216 | */ |
b242e891 | 217 | length = rt2x00dev->ops->lib->get_tx_data_len(rt2x00dev, skb); |
95ea3627 | 218 | |
dd9fa2d2 ID |
219 | /* |
220 | * Initialize URB and send the frame to the device. | |
221 | */ | |
181d6902 ID |
222 | __set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); |
223 | usb_fill_bulk_urb(priv_tx->urb, usb_dev, usb_sndbulkpipe(usb_dev, 1), | |
95ea3627 | 224 | skb->data, length, rt2x00usb_interrupt_txdone, entry); |
181d6902 | 225 | usb_submit_urb(priv_tx->urb, GFP_ATOMIC); |
95ea3627 | 226 | |
181d6902 | 227 | rt2x00queue_index_inc(queue, Q_INDEX); |
95ea3627 | 228 | |
95ea3627 ID |
229 | return 0; |
230 | } | |
231 | EXPORT_SYMBOL_GPL(rt2x00usb_write_tx_data); | |
232 | ||
233 | /* | |
234 | * RX data handlers. | |
235 | */ | |
181d6902 ID |
236 | static struct sk_buff* rt2x00usb_alloc_rxskb(struct data_queue *queue) |
237 | { | |
238 | struct sk_buff *skb; | |
239 | unsigned int frame_size; | |
240 | ||
241 | /* | |
242 | * As alignment we use 2 and not NET_IP_ALIGN because we need | |
243 | * to be sure we have 2 bytes room in the head. (NET_IP_ALIGN | |
244 | * can be 0 on some hardware). We use these 2 bytes for frame | |
245 | * alignment later, we assume that the chance that | |
246 | * header_size % 4 == 2 is bigger then header_size % 2 == 0 | |
247 | * and thus optimize alignment by reserving the 2 bytes in | |
248 | * advance. | |
249 | */ | |
250 | frame_size = queue->data_size + queue->desc_size; | |
f855c10b | 251 | skb = dev_alloc_skb(queue->desc_size + frame_size + 2); |
181d6902 ID |
252 | if (!skb) |
253 | return NULL; | |
254 | ||
f855c10b | 255 | skb_reserve(skb, queue->desc_size + 2); |
181d6902 ID |
256 | skb_put(skb, frame_size); |
257 | ||
258 | return skb; | |
259 | } | |
260 | ||
95ea3627 ID |
261 | static void rt2x00usb_interrupt_rxdone(struct urb *urb) |
262 | { | |
181d6902 ID |
263 | struct queue_entry *entry = (struct queue_entry *)urb->context; |
264 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | |
95ea3627 | 265 | struct sk_buff *skb; |
181d6902 ID |
266 | struct skb_frame_desc *skbdesc; |
267 | struct rxdone_entry_desc rxdesc; | |
f855c10b | 268 | int header_size; |
95ea3627 ID |
269 | |
270 | if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) || | |
181d6902 | 271 | !test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) |
95ea3627 ID |
272 | return; |
273 | ||
274 | /* | |
275 | * Check if the received data is simply too small | |
276 | * to be actually valid, or if the urb is signaling | |
277 | * a problem. | |
278 | */ | |
181d6902 | 279 | if (urb->actual_length < entry->queue->desc_size || urb->status) |
95ea3627 ID |
280 | goto skip_entry; |
281 | ||
40561b84 ID |
282 | /* |
283 | * Fill in skb descriptor | |
284 | */ | |
181d6902 ID |
285 | skbdesc = get_skb_frame_desc(entry->skb); |
286 | memset(skbdesc, 0, sizeof(*skbdesc)); | |
40561b84 ID |
287 | skbdesc->entry = entry; |
288 | ||
181d6902 ID |
289 | memset(&rxdesc, 0, sizeof(rxdesc)); |
290 | rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc); | |
95ea3627 | 291 | |
f855c10b ID |
292 | /* |
293 | * The data behind the ieee80211 header must be | |
294 | * aligned on a 4 byte boundary. | |
295 | */ | |
296 | header_size = ieee80211_get_hdrlen_from_skb(entry->skb); | |
297 | if (header_size % 4 == 0) { | |
298 | skb_push(entry->skb, 2); | |
299 | memmove(entry->skb->data, entry->skb->data + 2, | |
300 | entry->skb->len - 2); | |
301 | skbdesc->data = entry->skb->data; | |
fd07e063 | 302 | skb_trim(entry->skb,entry->skb->len - 2); |
f855c10b ID |
303 | } |
304 | ||
95ea3627 ID |
305 | /* |
306 | * Allocate a new sk buffer to replace the current one. | |
307 | * If allocation fails, we should drop the current frame | |
308 | * so we can recycle the existing sk buffer for the new frame. | |
309 | */ | |
181d6902 | 310 | skb = rt2x00usb_alloc_rxskb(entry->queue); |
95ea3627 ID |
311 | if (!skb) |
312 | goto skip_entry; | |
313 | ||
95ea3627 ID |
314 | /* |
315 | * Send the frame to rt2x00lib for further processing. | |
316 | */ | |
181d6902 | 317 | rt2x00lib_rxdone(entry, &rxdesc); |
95ea3627 ID |
318 | |
319 | /* | |
320 | * Replace current entry's skb with the newly allocated one, | |
321 | * and reinitialize the urb. | |
322 | */ | |
323 | entry->skb = skb; | |
324 | urb->transfer_buffer = entry->skb->data; | |
325 | urb->transfer_buffer_length = entry->skb->len; | |
326 | ||
327 | skip_entry: | |
181d6902 ID |
328 | if (test_bit(DEVICE_ENABLED_RADIO, &entry->queue->rt2x00dev->flags)) { |
329 | __set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); | |
95ea3627 ID |
330 | usb_submit_urb(urb, GFP_ATOMIC); |
331 | } | |
332 | ||
181d6902 | 333 | rt2x00queue_index_inc(entry->queue, Q_INDEX); |
95ea3627 ID |
334 | } |
335 | ||
336 | /* | |
337 | * Radio handlers | |
338 | */ | |
95ea3627 ID |
339 | void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev) |
340 | { | |
181d6902 ID |
341 | struct queue_entry_priv_usb_rx *priv_rx; |
342 | struct queue_entry_priv_usb_tx *priv_tx; | |
330e3f95 | 343 | struct queue_entry_priv_usb_bcn *priv_bcn; |
181d6902 | 344 | struct data_queue *queue; |
95ea3627 ID |
345 | unsigned int i; |
346 | ||
bd394a74 | 347 | rt2x00usb_vendor_request_sw(rt2x00dev, USB_RX_CONTROL, 0, 0, |
95ea3627 ID |
348 | REGISTER_TIMEOUT); |
349 | ||
350 | /* | |
181d6902 | 351 | * Cancel all queues. |
95ea3627 | 352 | */ |
181d6902 ID |
353 | for (i = 0; i < rt2x00dev->rx->limit; i++) { |
354 | priv_rx = rt2x00dev->rx->entries[i].priv_data; | |
355 | usb_kill_urb(priv_rx->urb); | |
356 | } | |
357 | ||
330e3f95 | 358 | tx_queue_for_each(rt2x00dev, queue) { |
181d6902 ID |
359 | for (i = 0; i < queue->limit; i++) { |
360 | priv_tx = queue->entries[i].priv_data; | |
361 | usb_kill_urb(priv_tx->urb); | |
362 | } | |
95ea3627 | 363 | } |
330e3f95 ID |
364 | |
365 | for (i = 0; i < rt2x00dev->bcn->limit; i++) { | |
366 | priv_bcn = rt2x00dev->bcn->entries[i].priv_data; | |
367 | usb_kill_urb(priv_bcn->urb); | |
368 | ||
369 | if (priv_bcn->guardian_urb) | |
370 | usb_kill_urb(priv_bcn->guardian_urb); | |
371 | } | |
372 | ||
373 | if (!test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags)) | |
374 | return; | |
375 | ||
376 | for (i = 0; i < rt2x00dev->bcn[1].limit; i++) { | |
377 | priv_tx = rt2x00dev->bcn[1].entries[i].priv_data; | |
378 | usb_kill_urb(priv_tx->urb); | |
379 | } | |
95ea3627 ID |
380 | } |
381 | EXPORT_SYMBOL_GPL(rt2x00usb_disable_radio); | |
382 | ||
383 | /* | |
384 | * Device initialization handlers. | |
385 | */ | |
837e7f24 | 386 | void rt2x00usb_init_rxentry(struct rt2x00_dev *rt2x00dev, |
181d6902 | 387 | struct queue_entry *entry) |
837e7f24 | 388 | { |
181d6902 ID |
389 | struct usb_device *usb_dev = rt2x00dev_usb_dev(rt2x00dev); |
390 | struct queue_entry_priv_usb_rx *priv_rx = entry->priv_data; | |
837e7f24 | 391 | |
181d6902 | 392 | usb_fill_bulk_urb(priv_rx->urb, usb_dev, |
837e7f24 ID |
393 | usb_rcvbulkpipe(usb_dev, 1), |
394 | entry->skb->data, entry->skb->len, | |
395 | rt2x00usb_interrupt_rxdone, entry); | |
396 | ||
181d6902 ID |
397 | __set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); |
398 | usb_submit_urb(priv_rx->urb, GFP_ATOMIC); | |
837e7f24 ID |
399 | } |
400 | EXPORT_SYMBOL_GPL(rt2x00usb_init_rxentry); | |
401 | ||
402 | void rt2x00usb_init_txentry(struct rt2x00_dev *rt2x00dev, | |
181d6902 | 403 | struct queue_entry *entry) |
837e7f24 ID |
404 | { |
405 | entry->flags = 0; | |
406 | } | |
407 | EXPORT_SYMBOL_GPL(rt2x00usb_init_txentry); | |
408 | ||
95ea3627 | 409 | static int rt2x00usb_alloc_urb(struct rt2x00_dev *rt2x00dev, |
181d6902 | 410 | struct data_queue *queue) |
95ea3627 | 411 | { |
181d6902 ID |
412 | struct queue_entry_priv_usb_rx *priv_rx; |
413 | struct queue_entry_priv_usb_tx *priv_tx; | |
414 | struct queue_entry_priv_usb_bcn *priv_bcn; | |
415 | struct urb *urb; | |
416 | unsigned int guardian = | |
417 | test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags); | |
95ea3627 ID |
418 | unsigned int i; |
419 | ||
420 | /* | |
421 | * Allocate the URB's | |
422 | */ | |
181d6902 ID |
423 | for (i = 0; i < queue->limit; i++) { |
424 | urb = usb_alloc_urb(0, GFP_KERNEL); | |
425 | if (!urb) | |
95ea3627 | 426 | return -ENOMEM; |
181d6902 ID |
427 | |
428 | if (queue->qid == QID_RX) { | |
429 | priv_rx = queue->entries[i].priv_data; | |
430 | priv_rx->urb = urb; | |
431 | } else if (queue->qid == QID_MGMT && guardian) { | |
432 | priv_bcn = queue->entries[i].priv_data; | |
433 | priv_bcn->urb = urb; | |
434 | ||
435 | urb = usb_alloc_urb(0, GFP_KERNEL); | |
436 | if (!urb) | |
437 | return -ENOMEM; | |
438 | ||
439 | priv_bcn->guardian_urb = urb; | |
440 | } else { | |
441 | priv_tx = queue->entries[i].priv_data; | |
442 | priv_tx->urb = urb; | |
443 | } | |
95ea3627 ID |
444 | } |
445 | ||
446 | return 0; | |
447 | } | |
448 | ||
449 | static void rt2x00usb_free_urb(struct rt2x00_dev *rt2x00dev, | |
181d6902 | 450 | struct data_queue *queue) |
95ea3627 | 451 | { |
181d6902 ID |
452 | struct queue_entry_priv_usb_rx *priv_rx; |
453 | struct queue_entry_priv_usb_tx *priv_tx; | |
454 | struct queue_entry_priv_usb_bcn *priv_bcn; | |
455 | struct urb *urb; | |
456 | unsigned int guardian = | |
457 | test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags); | |
95ea3627 ID |
458 | unsigned int i; |
459 | ||
181d6902 | 460 | if (!queue->entries) |
95ea3627 ID |
461 | return; |
462 | ||
181d6902 ID |
463 | for (i = 0; i < queue->limit; i++) { |
464 | if (queue->qid == QID_RX) { | |
465 | priv_rx = queue->entries[i].priv_data; | |
466 | urb = priv_rx->urb; | |
467 | } else if (queue->qid == QID_MGMT && guardian) { | |
468 | priv_bcn = queue->entries[i].priv_data; | |
469 | ||
470 | usb_kill_urb(priv_bcn->guardian_urb); | |
471 | usb_free_urb(priv_bcn->guardian_urb); | |
472 | ||
473 | urb = priv_bcn->urb; | |
474 | } else { | |
475 | priv_tx = queue->entries[i].priv_data; | |
476 | urb = priv_tx->urb; | |
477 | } | |
478 | ||
479 | usb_kill_urb(urb); | |
480 | usb_free_urb(urb); | |
481 | if (queue->entries[i].skb) | |
482 | kfree_skb(queue->entries[i].skb); | |
95ea3627 ID |
483 | } |
484 | } | |
485 | ||
486 | int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev) | |
487 | { | |
181d6902 | 488 | struct data_queue *queue; |
95ea3627 ID |
489 | struct sk_buff *skb; |
490 | unsigned int entry_size; | |
491 | unsigned int i; | |
73738001 | 492 | int uninitialized_var(status); |
95ea3627 ID |
493 | |
494 | /* | |
495 | * Allocate DMA | |
496 | */ | |
181d6902 ID |
497 | queue_for_each(rt2x00dev, queue) { |
498 | status = rt2x00usb_alloc_urb(rt2x00dev, queue); | |
95ea3627 ID |
499 | if (status) |
500 | goto exit; | |
501 | } | |
502 | ||
503 | /* | |
181d6902 | 504 | * For the RX queue, skb's should be allocated. |
95ea3627 ID |
505 | */ |
506 | entry_size = rt2x00dev->rx->data_size + rt2x00dev->rx->desc_size; | |
181d6902 ID |
507 | for (i = 0; i < rt2x00dev->rx->limit; i++) { |
508 | skb = rt2x00usb_alloc_rxskb(rt2x00dev->rx); | |
95ea3627 ID |
509 | if (!skb) |
510 | goto exit; | |
511 | ||
181d6902 | 512 | rt2x00dev->rx->entries[i].skb = skb; |
95ea3627 ID |
513 | } |
514 | ||
515 | return 0; | |
516 | ||
517 | exit: | |
518 | rt2x00usb_uninitialize(rt2x00dev); | |
519 | ||
520 | return status; | |
521 | } | |
522 | EXPORT_SYMBOL_GPL(rt2x00usb_initialize); | |
523 | ||
524 | void rt2x00usb_uninitialize(struct rt2x00_dev *rt2x00dev) | |
525 | { | |
181d6902 | 526 | struct data_queue *queue; |
95ea3627 | 527 | |
181d6902 ID |
528 | queue_for_each(rt2x00dev, queue) |
529 | rt2x00usb_free_urb(rt2x00dev, queue); | |
95ea3627 ID |
530 | } |
531 | EXPORT_SYMBOL_GPL(rt2x00usb_uninitialize); | |
532 | ||
533 | /* | |
534 | * USB driver handlers. | |
535 | */ | |
536 | static void rt2x00usb_free_reg(struct rt2x00_dev *rt2x00dev) | |
537 | { | |
538 | kfree(rt2x00dev->rf); | |
539 | rt2x00dev->rf = NULL; | |
540 | ||
541 | kfree(rt2x00dev->eeprom); | |
542 | rt2x00dev->eeprom = NULL; | |
543 | ||
21795094 ID |
544 | kfree(rt2x00dev->csr.cache); |
545 | rt2x00dev->csr.cache = NULL; | |
95ea3627 ID |
546 | } |
547 | ||
548 | static int rt2x00usb_alloc_reg(struct rt2x00_dev *rt2x00dev) | |
549 | { | |
21795094 ID |
550 | rt2x00dev->csr.cache = kzalloc(CSR_CACHE_SIZE, GFP_KERNEL); |
551 | if (!rt2x00dev->csr.cache) | |
95ea3627 ID |
552 | goto exit; |
553 | ||
554 | rt2x00dev->eeprom = kzalloc(rt2x00dev->ops->eeprom_size, GFP_KERNEL); | |
555 | if (!rt2x00dev->eeprom) | |
556 | goto exit; | |
557 | ||
558 | rt2x00dev->rf = kzalloc(rt2x00dev->ops->rf_size, GFP_KERNEL); | |
559 | if (!rt2x00dev->rf) | |
560 | goto exit; | |
561 | ||
562 | return 0; | |
563 | ||
564 | exit: | |
565 | ERROR_PROBE("Failed to allocate registers.\n"); | |
566 | ||
567 | rt2x00usb_free_reg(rt2x00dev); | |
568 | ||
569 | return -ENOMEM; | |
570 | } | |
571 | ||
572 | int rt2x00usb_probe(struct usb_interface *usb_intf, | |
573 | const struct usb_device_id *id) | |
574 | { | |
575 | struct usb_device *usb_dev = interface_to_usbdev(usb_intf); | |
576 | struct rt2x00_ops *ops = (struct rt2x00_ops *)id->driver_info; | |
577 | struct ieee80211_hw *hw; | |
578 | struct rt2x00_dev *rt2x00dev; | |
579 | int retval; | |
580 | ||
581 | usb_dev = usb_get_dev(usb_dev); | |
582 | ||
583 | hw = ieee80211_alloc_hw(sizeof(struct rt2x00_dev), ops->hw); | |
584 | if (!hw) { | |
585 | ERROR_PROBE("Failed to allocate hardware.\n"); | |
586 | retval = -ENOMEM; | |
587 | goto exit_put_device; | |
588 | } | |
589 | ||
590 | usb_set_intfdata(usb_intf, hw); | |
591 | ||
592 | rt2x00dev = hw->priv; | |
593 | rt2x00dev->dev = usb_intf; | |
594 | rt2x00dev->ops = ops; | |
595 | rt2x00dev->hw = hw; | |
3d82346c | 596 | mutex_init(&rt2x00dev->usb_cache_mutex); |
95ea3627 | 597 | |
b242e891 ID |
598 | rt2x00dev->usb_maxpacket = |
599 | usb_maxpacket(usb_dev, usb_sndbulkpipe(usb_dev, 1), 1); | |
600 | if (!rt2x00dev->usb_maxpacket) | |
601 | rt2x00dev->usb_maxpacket = 1; | |
602 | ||
95ea3627 ID |
603 | retval = rt2x00usb_alloc_reg(rt2x00dev); |
604 | if (retval) | |
605 | goto exit_free_device; | |
606 | ||
607 | retval = rt2x00lib_probe_dev(rt2x00dev); | |
608 | if (retval) | |
609 | goto exit_free_reg; | |
610 | ||
611 | return 0; | |
612 | ||
613 | exit_free_reg: | |
614 | rt2x00usb_free_reg(rt2x00dev); | |
615 | ||
616 | exit_free_device: | |
617 | ieee80211_free_hw(hw); | |
618 | ||
619 | exit_put_device: | |
620 | usb_put_dev(usb_dev); | |
621 | ||
622 | usb_set_intfdata(usb_intf, NULL); | |
623 | ||
624 | return retval; | |
625 | } | |
626 | EXPORT_SYMBOL_GPL(rt2x00usb_probe); | |
627 | ||
628 | void rt2x00usb_disconnect(struct usb_interface *usb_intf) | |
629 | { | |
630 | struct ieee80211_hw *hw = usb_get_intfdata(usb_intf); | |
631 | struct rt2x00_dev *rt2x00dev = hw->priv; | |
632 | ||
633 | /* | |
634 | * Free all allocated data. | |
635 | */ | |
636 | rt2x00lib_remove_dev(rt2x00dev); | |
637 | rt2x00usb_free_reg(rt2x00dev); | |
638 | ieee80211_free_hw(hw); | |
639 | ||
640 | /* | |
641 | * Free the USB device data. | |
642 | */ | |
643 | usb_set_intfdata(usb_intf, NULL); | |
644 | usb_put_dev(interface_to_usbdev(usb_intf)); | |
645 | } | |
646 | EXPORT_SYMBOL_GPL(rt2x00usb_disconnect); | |
647 | ||
648 | #ifdef CONFIG_PM | |
649 | int rt2x00usb_suspend(struct usb_interface *usb_intf, pm_message_t state) | |
650 | { | |
651 | struct ieee80211_hw *hw = usb_get_intfdata(usb_intf); | |
652 | struct rt2x00_dev *rt2x00dev = hw->priv; | |
653 | int retval; | |
654 | ||
655 | retval = rt2x00lib_suspend(rt2x00dev, state); | |
656 | if (retval) | |
657 | return retval; | |
658 | ||
659 | rt2x00usb_free_reg(rt2x00dev); | |
660 | ||
661 | /* | |
662 | * Decrease usbdev refcount. | |
663 | */ | |
664 | usb_put_dev(interface_to_usbdev(usb_intf)); | |
665 | ||
666 | return 0; | |
667 | } | |
668 | EXPORT_SYMBOL_GPL(rt2x00usb_suspend); | |
669 | ||
670 | int rt2x00usb_resume(struct usb_interface *usb_intf) | |
671 | { | |
672 | struct ieee80211_hw *hw = usb_get_intfdata(usb_intf); | |
673 | struct rt2x00_dev *rt2x00dev = hw->priv; | |
674 | int retval; | |
675 | ||
676 | usb_get_dev(interface_to_usbdev(usb_intf)); | |
677 | ||
678 | retval = rt2x00usb_alloc_reg(rt2x00dev); | |
679 | if (retval) | |
680 | return retval; | |
681 | ||
682 | retval = rt2x00lib_resume(rt2x00dev); | |
683 | if (retval) | |
684 | goto exit_free_reg; | |
685 | ||
686 | return 0; | |
687 | ||
688 | exit_free_reg: | |
689 | rt2x00usb_free_reg(rt2x00dev); | |
690 | ||
691 | return retval; | |
692 | } | |
693 | EXPORT_SYMBOL_GPL(rt2x00usb_resume); | |
694 | #endif /* CONFIG_PM */ | |
695 | ||
696 | /* | |
181d6902 | 697 | * rt2x00usb module information. |
95ea3627 ID |
698 | */ |
699 | MODULE_AUTHOR(DRV_PROJECT); | |
700 | MODULE_VERSION(DRV_VERSION); | |
181d6902 | 701 | MODULE_DESCRIPTION("rt2x00 usb library"); |
95ea3627 | 702 | MODULE_LICENSE("GPL"); |