aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/rt2x00/rt2800lib.c73
1 files changed, 50 insertions, 23 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 7c68bf35951..1a8170068b1 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -581,6 +581,49 @@ void rt2800_process_rxwi(struct queue_entry *entry,
581} 581}
582EXPORT_SYMBOL_GPL(rt2800_process_rxwi); 582EXPORT_SYMBOL_GPL(rt2800_process_rxwi);
583 583
584static bool rt2800_txdone_entry_check(struct queue_entry *entry, u32 reg)
585{
586 __le32 *txwi;
587 u32 word;
588 int wcid, ack, pid;
589 int tx_wcid, tx_ack, tx_pid;
590
591 wcid = rt2x00_get_field32(reg, TX_STA_FIFO_WCID);
592 ack = rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED);
593 pid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE);
594
595 /*
596 * This frames has returned with an IO error,
597 * so the status report is not intended for this
598 * frame.
599 */
600 if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) {
601 rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE);
602 return false;
603 }
604
605 /*
606 * Validate if this TX status report is intended for
607 * this entry by comparing the WCID/ACK/PID fields.
608 */
609 txwi = rt2800_drv_get_txwi(entry);
610
611 rt2x00_desc_read(txwi, 1, &word);
612 tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID);
613 tx_ack = rt2x00_get_field32(word, TXWI_W1_ACK);
614 tx_pid = rt2x00_get_field32(word, TXWI_W1_PACKETID);
615
616 if ((wcid != tx_wcid) || (ack != tx_ack) || (pid != tx_pid)) {
617 WARNING(entry->queue->rt2x00dev,
618 "TX status report missed for queue %d entry %d\n",
619 entry->queue->qid, entry->entry_idx);
620 rt2x00lib_txdone_noinfo(entry, TXDONE_UNKNOWN);
621 return false;
622 }
623
624 return true;
625}
626
584void rt2800_txdone(struct rt2x00_dev *rt2x00dev) 627void rt2800_txdone(struct rt2x00_dev *rt2x00dev)
585{ 628{
586 struct data_queue *queue; 629 struct data_queue *queue;
@@ -589,8 +632,8 @@ void rt2800_txdone(struct rt2x00_dev *rt2x00dev)
589 struct txdone_entry_desc txdesc; 632 struct txdone_entry_desc txdesc;
590 u32 word; 633 u32 word;
591 u32 reg; 634 u32 reg;
592 int wcid, ack, pid, tx_wcid, tx_ack, tx_pid;
593 u16 mcs, real_mcs; 635 u16 mcs, real_mcs;
636 u8 pid;
594 int i; 637 int i;
595 638
596 /* 639 /*
@@ -607,18 +650,15 @@ void rt2800_txdone(struct rt2x00_dev *rt2x00dev)
607 if (!rt2x00_get_field32(reg, TX_STA_FIFO_VALID)) 650 if (!rt2x00_get_field32(reg, TX_STA_FIFO_VALID))
608 break; 651 break;
609 652
610 wcid = rt2x00_get_field32(reg, TX_STA_FIFO_WCID);
611 ack = rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED);
612 pid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE);
613
614 /* 653 /*
615 * Skip this entry when it contains an invalid 654 * Skip this entry when it contains an invalid
616 * queue identication number. 655 * queue identication number.
617 */ 656 */
618 if (pid <= 0 || pid > QID_RX) 657 pid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE) - 1;
658 if (pid >= QID_RX)
619 continue; 659 continue;
620 660
621 queue = rt2x00queue_get_queue(rt2x00dev, pid - 1); 661 queue = rt2x00queue_get_queue(rt2x00dev, pid);
622 if (unlikely(!queue)) 662 if (unlikely(!queue))
623 continue; 663 continue;
624 664
@@ -627,35 +667,22 @@ void rt2800_txdone(struct rt2x00_dev *rt2x00dev)
627 * order. We first check that the queue is not empty. 667 * order. We first check that the queue is not empty.
628 */ 668 */
629 entry = NULL; 669 entry = NULL;
670 txwi = NULL;
630 while (!rt2x00queue_empty(queue)) { 671 while (!rt2x00queue_empty(queue)) {
631 entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); 672 entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
632 if (!test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) 673 if (rt2800_txdone_entry_check(entry, reg))
633 break; 674 break;
634
635 rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE);
636 } 675 }
637 676
638 if (!entry || rt2x00queue_empty(queue)) 677 if (!entry || rt2x00queue_empty(queue))
639 break; 678 break;
640 679
641 /*
642 * Check if we got a match by looking at WCID/ACK/PID
643 * fields
644 */
645 txwi = rt2800_drv_get_txwi(entry);
646
647 rt2x00_desc_read(txwi, 1, &word);
648 tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID);
649 tx_ack = rt2x00_get_field32(word, TXWI_W1_ACK);
650 tx_pid = rt2x00_get_field32(word, TXWI_W1_PACKETID);
651
652 if ((wcid != tx_wcid) || (ack != tx_ack) || (pid != tx_pid))
653 WARNING(rt2x00dev, "invalid TX_STA_FIFO content");
654 680
655 /* 681 /*
656 * Obtain the status about this packet. 682 * Obtain the status about this packet.
657 */ 683 */
658 txdesc.flags = 0; 684 txdesc.flags = 0;
685 txwi = rt2800_drv_get_txwi(entry);
659 rt2x00_desc_read(txwi, 0, &word); 686 rt2x00_desc_read(txwi, 0, &word);
660 mcs = rt2x00_get_field32(word, TXWI_W0_MCS); 687 mcs = rt2x00_get_field32(word, TXWI_W0_MCS);
661 real_mcs = rt2x00_get_field32(reg, TX_STA_FIFO_MCS); 688 real_mcs = rt2x00_get_field32(reg, TX_STA_FIFO_MCS);