diff options
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2x00usb.c')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00usb.c | 126 |
1 files changed, 105 insertions, 21 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 36f388f97d65..cb208d589ff8 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c | |||
@@ -165,6 +165,56 @@ int rt2x00usb_regbusy_read(struct rt2x00_dev *rt2x00dev, | |||
165 | } | 165 | } |
166 | EXPORT_SYMBOL_GPL(rt2x00usb_regbusy_read); | 166 | EXPORT_SYMBOL_GPL(rt2x00usb_regbusy_read); |
167 | 167 | ||
168 | |||
169 | struct rt2x00_async_read_data { | ||
170 | __le32 reg; | ||
171 | struct usb_ctrlrequest cr; | ||
172 | struct rt2x00_dev *rt2x00dev; | ||
173 | void (*callback)(struct rt2x00_dev *,int,u32); | ||
174 | }; | ||
175 | |||
176 | static void rt2x00usb_register_read_async_cb(struct urb *urb) | ||
177 | { | ||
178 | struct rt2x00_async_read_data *rd = urb->context; | ||
179 | rd->callback(rd->rt2x00dev, urb->status, le32_to_cpu(rd->reg)); | ||
180 | kfree(urb->context); | ||
181 | } | ||
182 | |||
183 | void rt2x00usb_register_read_async(struct rt2x00_dev *rt2x00dev, | ||
184 | const unsigned int offset, | ||
185 | void (*callback)(struct rt2x00_dev*,int,u32)) | ||
186 | { | ||
187 | struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); | ||
188 | struct urb *urb; | ||
189 | struct rt2x00_async_read_data *rd; | ||
190 | |||
191 | rd = kmalloc(sizeof(*rd), GFP_ATOMIC); | ||
192 | if (!rd) | ||
193 | return; | ||
194 | |||
195 | urb = usb_alloc_urb(0, GFP_ATOMIC); | ||
196 | if (!urb) { | ||
197 | kfree(rd); | ||
198 | return; | ||
199 | } | ||
200 | |||
201 | rd->rt2x00dev = rt2x00dev; | ||
202 | rd->callback = callback; | ||
203 | rd->cr.bRequestType = USB_VENDOR_REQUEST_IN; | ||
204 | rd->cr.bRequest = USB_MULTI_READ; | ||
205 | rd->cr.wValue = 0; | ||
206 | rd->cr.wIndex = cpu_to_le16(offset); | ||
207 | rd->cr.wLength = cpu_to_le16(sizeof(u32)); | ||
208 | |||
209 | usb_fill_control_urb(urb, usb_dev, usb_rcvctrlpipe(usb_dev, 0), | ||
210 | (unsigned char *)(&rd->cr), &rd->reg, sizeof(rd->reg), | ||
211 | rt2x00usb_register_read_async_cb, rd); | ||
212 | if (usb_submit_urb(urb, GFP_ATOMIC) < 0) | ||
213 | kfree(rd); | ||
214 | usb_free_urb(urb); | ||
215 | } | ||
216 | EXPORT_SYMBOL_GPL(rt2x00usb_register_read_async); | ||
217 | |||
168 | /* | 218 | /* |
169 | * TX data handlers. | 219 | * TX data handlers. |
170 | */ | 220 | */ |
@@ -212,6 +262,9 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb) | |||
212 | if (!test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) | 262 | if (!test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) |
213 | return; | 263 | return; |
214 | 264 | ||
265 | if (rt2x00dev->ops->lib->tx_dma_done) | ||
266 | rt2x00dev->ops->lib->tx_dma_done(entry); | ||
267 | |||
215 | /* | 268 | /* |
216 | * Report the frame as DMA done | 269 | * Report the frame as DMA done |
217 | */ | 270 | */ |
@@ -227,10 +280,12 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb) | |||
227 | * Schedule the delayed work for reading the TX status | 280 | * Schedule the delayed work for reading the TX status |
228 | * from the device. | 281 | * from the device. |
229 | */ | 282 | */ |
230 | queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work); | 283 | if (!test_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags) || |
284 | !kfifo_is_empty(&rt2x00dev->txstatus_fifo)) | ||
285 | queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work); | ||
231 | } | 286 | } |
232 | 287 | ||
233 | static void rt2x00usb_kick_tx_entry(struct queue_entry *entry) | 288 | static bool rt2x00usb_kick_tx_entry(struct queue_entry *entry, void* data) |
234 | { | 289 | { |
235 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | 290 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; |
236 | struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); | 291 | struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); |
@@ -240,7 +295,7 @@ static void rt2x00usb_kick_tx_entry(struct queue_entry *entry) | |||
240 | 295 | ||
241 | if (!test_and_clear_bit(ENTRY_DATA_PENDING, &entry->flags) || | 296 | if (!test_and_clear_bit(ENTRY_DATA_PENDING, &entry->flags) || |
242 | test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags)) | 297 | test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags)) |
243 | return; | 298 | return true; |
244 | 299 | ||
245 | /* | 300 | /* |
246 | * USB devices cannot blindly pass the skb->len as the | 301 | * USB devices cannot blindly pass the skb->len as the |
@@ -261,6 +316,8 @@ static void rt2x00usb_kick_tx_entry(struct queue_entry *entry) | |||
261 | set_bit(ENTRY_DATA_IO_FAILED, &entry->flags); | 316 | set_bit(ENTRY_DATA_IO_FAILED, &entry->flags); |
262 | rt2x00lib_dmadone(entry); | 317 | rt2x00lib_dmadone(entry); |
263 | } | 318 | } |
319 | |||
320 | return false; | ||
264 | } | 321 | } |
265 | 322 | ||
266 | /* | 323 | /* |
@@ -323,7 +380,7 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb) | |||
323 | queue_work(rt2x00dev->workqueue, &rt2x00dev->rxdone_work); | 380 | queue_work(rt2x00dev->workqueue, &rt2x00dev->rxdone_work); |
324 | } | 381 | } |
325 | 382 | ||
326 | static void rt2x00usb_kick_rx_entry(struct queue_entry *entry) | 383 | static bool rt2x00usb_kick_rx_entry(struct queue_entry *entry, void* data) |
327 | { | 384 | { |
328 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | 385 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; |
329 | struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); | 386 | struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); |
@@ -332,7 +389,7 @@ static void rt2x00usb_kick_rx_entry(struct queue_entry *entry) | |||
332 | 389 | ||
333 | if (test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) || | 390 | if (test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) || |
334 | test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags)) | 391 | test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags)) |
335 | return; | 392 | return true; |
336 | 393 | ||
337 | rt2x00lib_dmastart(entry); | 394 | rt2x00lib_dmastart(entry); |
338 | 395 | ||
@@ -348,6 +405,8 @@ static void rt2x00usb_kick_rx_entry(struct queue_entry *entry) | |||
348 | set_bit(ENTRY_DATA_IO_FAILED, &entry->flags); | 405 | set_bit(ENTRY_DATA_IO_FAILED, &entry->flags); |
349 | rt2x00lib_dmadone(entry); | 406 | rt2x00lib_dmadone(entry); |
350 | } | 407 | } |
408 | |||
409 | return false; | ||
351 | } | 410 | } |
352 | 411 | ||
353 | void rt2x00usb_kick_queue(struct data_queue *queue) | 412 | void rt2x00usb_kick_queue(struct data_queue *queue) |
@@ -358,12 +417,18 @@ void rt2x00usb_kick_queue(struct data_queue *queue) | |||
358 | case QID_AC_BE: | 417 | case QID_AC_BE: |
359 | case QID_AC_BK: | 418 | case QID_AC_BK: |
360 | if (!rt2x00queue_empty(queue)) | 419 | if (!rt2x00queue_empty(queue)) |
361 | rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, | 420 | rt2x00queue_for_each_entry(queue, |
421 | Q_INDEX_DONE, | ||
422 | Q_INDEX, | ||
423 | NULL, | ||
362 | rt2x00usb_kick_tx_entry); | 424 | rt2x00usb_kick_tx_entry); |
363 | break; | 425 | break; |
364 | case QID_RX: | 426 | case QID_RX: |
365 | if (!rt2x00queue_full(queue)) | 427 | if (!rt2x00queue_full(queue)) |
366 | rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, | 428 | rt2x00queue_for_each_entry(queue, |
429 | Q_INDEX_DONE, | ||
430 | Q_INDEX, | ||
431 | NULL, | ||
367 | rt2x00usb_kick_rx_entry); | 432 | rt2x00usb_kick_rx_entry); |
368 | break; | 433 | break; |
369 | default: | 434 | default: |
@@ -372,14 +437,14 @@ void rt2x00usb_kick_queue(struct data_queue *queue) | |||
372 | } | 437 | } |
373 | EXPORT_SYMBOL_GPL(rt2x00usb_kick_queue); | 438 | EXPORT_SYMBOL_GPL(rt2x00usb_kick_queue); |
374 | 439 | ||
375 | static void rt2x00usb_flush_entry(struct queue_entry *entry) | 440 | static bool rt2x00usb_flush_entry(struct queue_entry *entry, void* data) |
376 | { | 441 | { |
377 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | 442 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; |
378 | struct queue_entry_priv_usb *entry_priv = entry->priv_data; | 443 | struct queue_entry_priv_usb *entry_priv = entry->priv_data; |
379 | struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data; | 444 | struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data; |
380 | 445 | ||
381 | if (!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) | 446 | if (!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) |
382 | return; | 447 | return true; |
383 | 448 | ||
384 | usb_kill_urb(entry_priv->urb); | 449 | usb_kill_urb(entry_priv->urb); |
385 | 450 | ||
@@ -387,17 +452,20 @@ static void rt2x00usb_flush_entry(struct queue_entry *entry) | |||
387 | * Kill guardian urb (if required by driver). | 452 | * Kill guardian urb (if required by driver). |
388 | */ | 453 | */ |
389 | if ((entry->queue->qid == QID_BEACON) && | 454 | if ((entry->queue->qid == QID_BEACON) && |
390 | (test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags))) | 455 | (test_bit(REQUIRE_BEACON_GUARD, &rt2x00dev->cap_flags))) |
391 | usb_kill_urb(bcn_priv->guardian_urb); | 456 | usb_kill_urb(bcn_priv->guardian_urb); |
457 | |||
458 | return false; | ||
392 | } | 459 | } |
393 | 460 | ||
394 | void rt2x00usb_flush_queue(struct data_queue *queue) | 461 | void rt2x00usb_flush_queue(struct data_queue *queue, bool drop) |
395 | { | 462 | { |
396 | struct work_struct *completion; | 463 | struct work_struct *completion; |
397 | unsigned int i; | 464 | unsigned int i; |
398 | 465 | ||
399 | rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, | 466 | if (drop) |
400 | rt2x00usb_flush_entry); | 467 | rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, NULL, |
468 | rt2x00usb_flush_entry); | ||
401 | 469 | ||
402 | /* | 470 | /* |
403 | * Obtain the queue completion handler | 471 | * Obtain the queue completion handler |
@@ -416,7 +484,7 @@ void rt2x00usb_flush_queue(struct data_queue *queue) | |||
416 | return; | 484 | return; |
417 | } | 485 | } |
418 | 486 | ||
419 | for (i = 0; i < 20; i++) { | 487 | for (i = 0; i < 10; i++) { |
420 | /* | 488 | /* |
421 | * Check if the driver is already done, otherwise we | 489 | * Check if the driver is already done, otherwise we |
422 | * have to sleep a little while to give the driver/hw | 490 | * have to sleep a little while to give the driver/hw |
@@ -456,15 +524,31 @@ static void rt2x00usb_watchdog_tx_status(struct data_queue *queue) | |||
456 | queue_work(queue->rt2x00dev->workqueue, &queue->rt2x00dev->txdone_work); | 524 | queue_work(queue->rt2x00dev->workqueue, &queue->rt2x00dev->txdone_work); |
457 | } | 525 | } |
458 | 526 | ||
527 | static int rt2x00usb_status_timeout(struct data_queue *queue) | ||
528 | { | ||
529 | struct queue_entry *entry; | ||
530 | |||
531 | entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); | ||
532 | return rt2x00queue_status_timeout(entry); | ||
533 | } | ||
534 | |||
535 | static int rt2x00usb_dma_timeout(struct data_queue *queue) | ||
536 | { | ||
537 | struct queue_entry *entry; | ||
538 | |||
539 | entry = rt2x00queue_get_entry(queue, Q_INDEX_DMA_DONE); | ||
540 | return rt2x00queue_dma_timeout(entry); | ||
541 | } | ||
542 | |||
459 | void rt2x00usb_watchdog(struct rt2x00_dev *rt2x00dev) | 543 | void rt2x00usb_watchdog(struct rt2x00_dev *rt2x00dev) |
460 | { | 544 | { |
461 | struct data_queue *queue; | 545 | struct data_queue *queue; |
462 | 546 | ||
463 | tx_queue_for_each(rt2x00dev, queue) { | 547 | tx_queue_for_each(rt2x00dev, queue) { |
464 | if (!rt2x00queue_empty(queue)) { | 548 | if (!rt2x00queue_empty(queue)) { |
465 | if (rt2x00queue_dma_timeout(queue)) | 549 | if (rt2x00usb_dma_timeout(queue)) |
466 | rt2x00usb_watchdog_tx_dma(queue); | 550 | rt2x00usb_watchdog_tx_dma(queue); |
467 | if (rt2x00queue_status_timeout(queue)) | 551 | if (rt2x00usb_status_timeout(queue)) |
468 | rt2x00usb_watchdog_tx_status(queue); | 552 | rt2x00usb_watchdog_tx_status(queue); |
469 | } | 553 | } |
470 | } | 554 | } |
@@ -489,7 +573,7 @@ void rt2x00usb_clear_entry(struct queue_entry *entry) | |||
489 | entry->flags = 0; | 573 | entry->flags = 0; |
490 | 574 | ||
491 | if (entry->queue->qid == QID_RX) | 575 | if (entry->queue->qid == QID_RX) |
492 | rt2x00usb_kick_rx_entry(entry); | 576 | rt2x00usb_kick_rx_entry(entry, NULL); |
493 | } | 577 | } |
494 | EXPORT_SYMBOL_GPL(rt2x00usb_clear_entry); | 578 | EXPORT_SYMBOL_GPL(rt2x00usb_clear_entry); |
495 | 579 | ||
@@ -583,7 +667,7 @@ static int rt2x00usb_alloc_entries(struct data_queue *queue) | |||
583 | * then we are done. | 667 | * then we are done. |
584 | */ | 668 | */ |
585 | if (queue->qid != QID_BEACON || | 669 | if (queue->qid != QID_BEACON || |
586 | !test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags)) | 670 | !test_bit(REQUIRE_BEACON_GUARD, &rt2x00dev->cap_flags)) |
587 | return 0; | 671 | return 0; |
588 | 672 | ||
589 | for (i = 0; i < queue->limit; i++) { | 673 | for (i = 0; i < queue->limit; i++) { |
@@ -618,7 +702,7 @@ static void rt2x00usb_free_entries(struct data_queue *queue) | |||
618 | * then we are done. | 702 | * then we are done. |
619 | */ | 703 | */ |
620 | if (queue->qid != QID_BEACON || | 704 | if (queue->qid != QID_BEACON || |
621 | !test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags)) | 705 | !test_bit(REQUIRE_BEACON_GUARD, &rt2x00dev->cap_flags)) |
622 | return; | 706 | return; |
623 | 707 | ||
624 | for (i = 0; i < queue->limit; i++) { | 708 | for (i = 0; i < queue->limit; i++) { |
@@ -707,10 +791,9 @@ exit: | |||
707 | } | 791 | } |
708 | 792 | ||
709 | int rt2x00usb_probe(struct usb_interface *usb_intf, | 793 | int rt2x00usb_probe(struct usb_interface *usb_intf, |
710 | const struct usb_device_id *id) | 794 | const struct rt2x00_ops *ops) |
711 | { | 795 | { |
712 | struct usb_device *usb_dev = interface_to_usbdev(usb_intf); | 796 | struct usb_device *usb_dev = interface_to_usbdev(usb_intf); |
713 | struct rt2x00_ops *ops = (struct rt2x00_ops *)id->driver_info; | ||
714 | struct ieee80211_hw *hw; | 797 | struct ieee80211_hw *hw; |
715 | struct rt2x00_dev *rt2x00dev; | 798 | struct rt2x00_dev *rt2x00dev; |
716 | int retval; | 799 | int retval; |
@@ -735,6 +818,7 @@ int rt2x00usb_probe(struct usb_interface *usb_intf, | |||
735 | 818 | ||
736 | INIT_WORK(&rt2x00dev->rxdone_work, rt2x00usb_work_rxdone); | 819 | INIT_WORK(&rt2x00dev->rxdone_work, rt2x00usb_work_rxdone); |
737 | INIT_WORK(&rt2x00dev->txdone_work, rt2x00usb_work_txdone); | 820 | INIT_WORK(&rt2x00dev->txdone_work, rt2x00usb_work_txdone); |
821 | init_timer(&rt2x00dev->txstatus_timer); | ||
738 | 822 | ||
739 | retval = rt2x00usb_alloc_reg(rt2x00dev); | 823 | retval = rt2x00usb_alloc_reg(rt2x00dev); |
740 | if (retval) | 824 | if (retval) |