[rt2x00-users] [PATCH 06/12] rt2x00: Fix rt2800pci use of WCID.

Benoit PAPILLAULT benoit.papillault at free.fr
Fri Aug 14 22:06:12 UTC 2009


Fixed the crypto bug introduced ealier when using WCID incorrectly. We now use
WCID as before (ie with the crypto key index). The process done in
rt2800pci_txdone() has been changed to only process the last descriptor of the
specified queue. We use WCID/ACK/PID fields for checking the TX_STA_FIFO
content (it's not perfect thought).

Signed-off-by: Benoit PAPILLAULT <benoit.papillault at free.fr>
---
 drivers/net/wireless/rt2x00/rt2800pci.c |  105 ++++++++++++++++++-------------
 1 files changed, 60 insertions(+), 45 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index 8626a71..05f1bce 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -2114,8 +2114,10 @@ static void rt2800pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
 	__le32 *txd = skbdesc->desc;
 	__le32 *txwi = (__le32 *)(skb->data - rt2x00dev->hw->extra_tx_headroom);
 	u32 word;
-	int wcid = skbdesc->entry->entry_idx + 1;
-	int pid = skbdesc->entry->queue->qid + 1;
+	int tx_wcid = test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags) ?
+		txdesc->key_idx : 0xff;
+	int tx_ack = test_bit(ENTRY_TXD_ACK, &txdesc->flags);
+	int tx_pid = skbdesc->entry->queue->qid + 1;
 
 	/*
 	 * Initialize TX Info descriptor
@@ -2141,21 +2143,28 @@ static void rt2800pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
 	rt2x00_desc_write(txwi, 0, word);
 
 	word = 0;
-	rt2x00_set_field32(&word, TXWI_W1_ACK,
-			   test_bit(ENTRY_TXD_ACK, &txdesc->flags));
+	rt2x00_set_field32(&word, TXWI_W1_ACK, tx_ack);
 	rt2x00_set_field32(&word, TXWI_W1_NSEQ,
 			   test_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags));
 	rt2x00_set_field32(&word, TXWI_W1_BW_WIN_SIZE, txdesc->ba_size);
-	rt2x00_set_field32(&word, TXWI_W1_WIRELESS_CLI_ID, wcid);
+	rt2x00_set_field32(&word, TXWI_W1_WIRELESS_CLI_ID, tx_wcid);
 	rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT,
 			   skb->len - txdesc->l2pad);
+
+	printk("%s: queue=%p entry=%p entry->skb=%p skb->data=%p\n",
+	       __func__,
+	       skbdesc->entry->queue,
+	       skbdesc->entry,
+	       skbdesc->entry->skb,
+	       skbdesc->entry->skb->data);
+
 	printk("%s: skb=%p skb->data=%p skb->len=%d MPDU_TOTAL_BYTE_COUNT=%d\n",
 	       __func__, skb, skb->data, skb->len, skb->len - txdesc->l2pad);
-	rt2x00_set_field32(&word, TXWI_W1_PACKETID, pid);
+	rt2x00_set_field32(&word, TXWI_W1_PACKETID, tx_pid);
 	rt2x00_desc_write(txwi, 1, word);
 
-	printk("%s: ACK=%d WCID=%d PID=%d\n", __func__, 
-	       test_bit(ENTRY_TXD_ACK, &txdesc->flags), wcid, pid);
+	printk("%s: TXWI WCID=%d ACK=%d PID=%d\n",
+	       __func__, tx_wcid, tx_ack, tx_pid);
 
 	/*
 	 * Always write 0 to IV/EIV fields, hardware will insert the IV
@@ -2404,13 +2413,12 @@ static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev)
 {
 	struct data_queue *queue;
 	struct queue_entry *entry;
-	struct queue_entry *entry_done;
-	struct queue_entry_priv_pci *entry_priv;
+	__le32 *txwi;
 	struct txdone_entry_desc txdesc;
 	u32 word;
 	u32 reg;
 	int i;
-	int wcid, pid;
+	int wcid, ack, pid, tx_wcid, tx_ack, tx_pid;
 
 	/*
 	 * To avoid an endlees loop, we only read the TX_STA_FIFO register up
@@ -2424,65 +2432,72 @@ static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev)
 		if (!rt2x00_get_field32(reg, TX_STA_FIFO_VALID))
 			break;
 
-		pid  = rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE);
-		wcid = rt2x00_get_field32(reg, TX_STA_FIFO_WCID);
+		wcid	= rt2x00_get_field32(reg, TX_STA_FIFO_WCID);
+		ack	= rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED);
+		pid	= rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE);
 
-		printk("%s: TX_STA_FIFO=%08x VALID=1 WCID=%d PID=%d\n",
-		       __func__, reg, wcid, pid);
+		printk("%s: TX_STA_FIFO=%08x WCID=%d ACK=%d PID=%d\n",
+		       __func__, reg, wcid, ack, pid);
 
 		/*
 		 * Skip this entry when it contains an invalid
 		 * queue identication number.
 		 */
-		if (pid < 1)
+		if (pid < 1) {
+			printk("%s: invalid PID=%d\n", __func__, pid);
 			continue;
+		}
 
 		queue = rt2x00queue_get_queue(rt2x00dev, pid - 1);
-		if (unlikely(!queue))
+		if (unlikely(!queue)) {
+			printk("%s: invalid PID=%d\n", __func__, pid);
 			continue;
-
-		printk("%s: queue=%p\n", __func__, queue);
+		}
 
 		/*
-		 * Skip this entry when it contains an invalid
-		 * index number. We must have :
-		 * 0 <= wcid - 1 < queue->limit
+		 * Inside each queue, we process each entry in a chronological
+		 * order
 		 */
-		if (unlikely(wcid < 1))
-			continue;
-		if (unlikely(wcid > queue->limit))
+		if (queue->length == 0) {
+			printk("%s: invalid queue %p empty\n", __func__, queue);
 			continue;
+		}
+		entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
+
+		printk("%s: queue=%p entry=%p entry->skb=%p skb->data=%p\n",
+		       __func__,
+		       queue,
+		       entry, entry->skb, entry->skb->data);
+
+		/* Check if we got a match : HOW ? */
+		txwi = (__le32 *)(entry->skb->data - 
+				  rt2x00dev->hw->extra_tx_headroom);
+
+		rt2x00_desc_read(txwi, 1, &word);
+		tx_wcid	= rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID);
+		tx_ack	= rt2x00_get_field32(word, TXWI_W1_ACK);
+		tx_pid	= rt2x00_get_field32(word, TXWI_W1_PACKETID);
 
-		entry = &queue->entries[wcid-1];
-		entry_priv = entry->priv_data;
-		rt2x00_desc_read((__le32 *)entry->skb->data, 0, &word);
-
-		entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
-		while (entry != entry_done) {
-			/*
-			 * Catch up.
-			 * Just report any entries we missed as failed.
-			 */
-			WARNING(rt2x00dev,
-				"TX status report missed for entry %d\n",
-				entry_done->entry_idx);
-
-			txdesc.flags = 0;
-			__set_bit(TXDONE_UNKNOWN, &txdesc.flags);
-			txdesc.retry = 0;
-
-			rt2x00lib_txdone(entry_done, &txdesc);
-			entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
+		printk("%s: TXWI WCID=%d ACK=%d PID=%d\n",
+		       __func__, tx_wcid, tx_ack, tx_pid);
+
+		if ((wcid != tx_wcid) || (ack != tx_ack) || (pid != tx_pid)) {
+			printk("%s: invalid WCID/ACK/PID\n",
+			       __func__);
 		}
 
 		/*
 		 * Obtain the status about this packet.
 		 */
+
+
 		txdesc.flags = 0;
 		if (rt2x00_get_field32(reg, TX_STA_FIFO_TX_SUCCESS))
 			__set_bit(TXDONE_SUCCESS, &txdesc.flags);
 		else
 			__set_bit(TXDONE_FAILURE, &txdesc.flags);
+
+		rt2x00_desc_read(txwi, 0, &word);
 		txdesc.retry = rt2x00_get_field32(word, TXWI_W0_MCS);
 
 		rt2x00lib_txdone(entry, &txdesc);
-- 
1.6.2.4




More information about the users mailing list