diff options
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2800usb.c')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2800usb.c | 83 |
1 files changed, 82 insertions, 1 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index ba82c972703a..6e9229830a29 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c | |||
@@ -457,6 +457,87 @@ static int rt2800usb_get_tx_data_len(struct queue_entry *entry) | |||
457 | /* | 457 | /* |
458 | * TX control handlers | 458 | * TX control handlers |
459 | */ | 459 | */ |
460 | static bool rt2800usb_txdone_entry_check(struct queue_entry *entry, u32 reg) | ||
461 | { | ||
462 | __le32 *txwi; | ||
463 | u32 word; | ||
464 | int wcid, ack, pid; | ||
465 | int tx_wcid, tx_ack, tx_pid; | ||
466 | |||
467 | wcid = rt2x00_get_field32(reg, TX_STA_FIFO_WCID); | ||
468 | ack = rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED); | ||
469 | pid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE); | ||
470 | |||
471 | /* | ||
472 | * This frames has returned with an IO error, | ||
473 | * so the status report is not intended for this | ||
474 | * frame. | ||
475 | */ | ||
476 | if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) { | ||
477 | rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE); | ||
478 | return false; | ||
479 | } | ||
480 | |||
481 | /* | ||
482 | * Validate if this TX status report is intended for | ||
483 | * this entry by comparing the WCID/ACK/PID fields. | ||
484 | */ | ||
485 | txwi = rt2800usb_get_txwi(entry); | ||
486 | |||
487 | rt2x00_desc_read(txwi, 1, &word); | ||
488 | tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID); | ||
489 | tx_ack = rt2x00_get_field32(word, TXWI_W1_ACK); | ||
490 | tx_pid = rt2x00_get_field32(word, TXWI_W1_PACKETID); | ||
491 | |||
492 | if ((wcid != tx_wcid) || (ack != tx_ack) || (pid != tx_pid)) { | ||
493 | WARNING(entry->queue->rt2x00dev, | ||
494 | "TX status report missed for queue %d entry %d\n", | ||
495 | entry->queue->qid, entry->entry_idx); | ||
496 | rt2x00lib_txdone_noinfo(entry, TXDONE_UNKNOWN); | ||
497 | return false; | ||
498 | } | ||
499 | |||
500 | return true; | ||
501 | } | ||
502 | |||
503 | static void rt2800usb_txdone(struct rt2x00_dev *rt2x00dev) | ||
504 | { | ||
505 | struct data_queue *queue; | ||
506 | struct queue_entry *entry; | ||
507 | u32 reg; | ||
508 | u8 qid; | ||
509 | |||
510 | while (kfifo_get(&rt2x00dev->txstatus_fifo, ®)) { | ||
511 | |||
512 | /* TX_STA_FIFO_PID_QUEUE is a 2-bit field, thus | ||
513 | * qid is guaranteed to be one of the TX QIDs | ||
514 | */ | ||
515 | qid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_QUEUE); | ||
516 | queue = rt2x00queue_get_tx_queue(rt2x00dev, qid); | ||
517 | if (unlikely(!queue)) { | ||
518 | WARNING(rt2x00dev, "Got TX status for an unavailable " | ||
519 | "queue %u, dropping\n", qid); | ||
520 | continue; | ||
521 | } | ||
522 | |||
523 | /* | ||
524 | * Inside each queue, we process each entry in a chronological | ||
525 | * order. We first check that the queue is not empty. | ||
526 | */ | ||
527 | entry = NULL; | ||
528 | while (!rt2x00queue_empty(queue)) { | ||
529 | entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); | ||
530 | if (rt2800usb_txdone_entry_check(entry, reg)) | ||
531 | break; | ||
532 | } | ||
533 | |||
534 | if (!entry || rt2x00queue_empty(queue)) | ||
535 | break; | ||
536 | |||
537 | rt2800_txdone_entry(entry, reg); | ||
538 | } | ||
539 | } | ||
540 | |||
460 | static void rt2800usb_work_txdone(struct work_struct *work) | 541 | static void rt2800usb_work_txdone(struct work_struct *work) |
461 | { | 542 | { |
462 | struct rt2x00_dev *rt2x00dev = | 543 | struct rt2x00_dev *rt2x00dev = |
@@ -464,7 +545,7 @@ static void rt2800usb_work_txdone(struct work_struct *work) | |||
464 | struct data_queue *queue; | 545 | struct data_queue *queue; |
465 | struct queue_entry *entry; | 546 | struct queue_entry *entry; |
466 | 547 | ||
467 | rt2800_txdone(rt2x00dev); | 548 | rt2800usb_txdone(rt2x00dev); |
468 | 549 | ||
469 | /* | 550 | /* |
470 | * Process any trailing TX status reports for IO failures, | 551 | * Process any trailing TX status reports for IO failures, |