aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/rt2x00/rt2800lib.c82
-rw-r--r--drivers/net/wireless/rt2x00/rt2800lib.h1
-rw-r--r--drivers/net/wireless/rt2x00/rt2800usb.c83
3 files changed, 82 insertions, 84 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index f0988d8736c3..75d2c6cc93eb 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -601,49 +601,6 @@ void rt2800_process_rxwi(struct queue_entry *entry,
601} 601}
602EXPORT_SYMBOL_GPL(rt2800_process_rxwi); 602EXPORT_SYMBOL_GPL(rt2800_process_rxwi);
603 603
604static bool rt2800_txdone_entry_check(struct queue_entry *entry, u32 reg)
605{
606 __le32 *txwi;
607 u32 word;
608 int wcid, ack, pid;
609 int tx_wcid, tx_ack, tx_pid;
610
611 wcid = rt2x00_get_field32(reg, TX_STA_FIFO_WCID);
612 ack = rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED);
613 pid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE);
614
615 /*
616 * This frames has returned with an IO error,
617 * so the status report is not intended for this
618 * frame.
619 */
620 if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) {
621 rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE);
622 return false;
623 }
624
625 /*
626 * Validate if this TX status report is intended for
627 * this entry by comparing the WCID/ACK/PID fields.
628 */
629 txwi = rt2800_drv_get_txwi(entry);
630
631 rt2x00_desc_read(txwi, 1, &word);
632 tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID);
633 tx_ack = rt2x00_get_field32(word, TXWI_W1_ACK);
634 tx_pid = rt2x00_get_field32(word, TXWI_W1_PACKETID);
635
636 if ((wcid != tx_wcid) || (ack != tx_ack) || (pid != tx_pid)) {
637 WARNING(entry->queue->rt2x00dev,
638 "TX status report missed for queue %d entry %d\n",
639 entry->queue->qid, entry->entry_idx);
640 rt2x00lib_txdone_noinfo(entry, TXDONE_UNKNOWN);
641 return false;
642 }
643
644 return true;
645}
646
647void rt2800_txdone_entry(struct queue_entry *entry, u32 status) 604void rt2800_txdone_entry(struct queue_entry *entry, u32 status)
648{ 605{
649 struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; 606 struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
@@ -726,45 +683,6 @@ void rt2800_txdone_entry(struct queue_entry *entry, u32 status)
726} 683}
727EXPORT_SYMBOL_GPL(rt2800_txdone_entry); 684EXPORT_SYMBOL_GPL(rt2800_txdone_entry);
728 685
729void rt2800_txdone(struct rt2x00_dev *rt2x00dev)
730{
731 struct data_queue *queue;
732 struct queue_entry *entry;
733 u32 reg;
734 u8 qid;
735
736 while (kfifo_get(&rt2x00dev->txstatus_fifo, &reg)) {
737
738 /* TX_STA_FIFO_PID_QUEUE is a 2-bit field, thus
739 * qid is guaranteed to be one of the TX QIDs
740 */
741 qid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_QUEUE);
742 queue = rt2x00queue_get_tx_queue(rt2x00dev, qid);
743 if (unlikely(!queue)) {
744 WARNING(rt2x00dev, "Got TX status for an unavailable "
745 "queue %u, dropping\n", qid);
746 continue;
747 }
748
749 /*
750 * Inside each queue, we process each entry in a chronological
751 * order. We first check that the queue is not empty.
752 */
753 entry = NULL;
754 while (!rt2x00queue_empty(queue)) {
755 entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
756 if (rt2800_txdone_entry_check(entry, reg))
757 break;
758 }
759
760 if (!entry || rt2x00queue_empty(queue))
761 break;
762
763 rt2800_txdone_entry(entry, reg);
764 }
765}
766EXPORT_SYMBOL_GPL(rt2800_txdone);
767
768void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc) 686void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)
769{ 687{
770 struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; 688 struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h
index f2d15941c71a..69deb3148ae7 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.h
+++ b/drivers/net/wireless/rt2x00/rt2800lib.h
@@ -152,7 +152,6 @@ void rt2800_write_tx_data(struct queue_entry *entry,
152 struct txentry_desc *txdesc); 152 struct txentry_desc *txdesc);
153void rt2800_process_rxwi(struct queue_entry *entry, struct rxdone_entry_desc *txdesc); 153void rt2800_process_rxwi(struct queue_entry *entry, struct rxdone_entry_desc *txdesc);
154 154
155void rt2800_txdone(struct rt2x00_dev *rt2x00dev);
156void rt2800_txdone_entry(struct queue_entry *entry, u32 status); 155void rt2800_txdone_entry(struct queue_entry *entry, u32 status);
157 156
158void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc); 157void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc);
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 */
460static 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
503static 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, &reg)) {
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
460static void rt2800usb_work_txdone(struct work_struct *work) 541static 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,