netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Ivo van Doorn <ivdoorn@gmail.com>
To: netdev@vger.kernel.org
Cc: linville@tuxdriver.com
Subject: Re: [PATCH 16/24] RT2x00: Fix rt61pci interrupt handling
Date: Wed, 26 Jul 2006 20:29:30 +0200	[thread overview]
Message-ID: <200607262029.30542.IvDoorn@gmail.com> (raw)
In-Reply-To: <200607261905.36712.IvDoorn@gmail.com>

>From Ivo van Doorn <IvDoorn@gmail.com>

rt61pci irq is a bit different compared to the others,
when the irq is raised, we should read from the register which
ring and which entry has been send. And this entry should
be processed. Using a for loop to go through all entries
is no longer working since we require certain statistics
from the registers.

Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>

diff -rU3 wireless-dev-ringentry/drivers/net/wireless/d80211/rt2x00/rt61pci.c wireless-dev-rt61irq/drivers/net/wireless/d80211/rt2x00/rt61pci.c
--- wireless-dev-ringentry/drivers/net/wireless/d80211/rt2x00/rt61pci.c	2006-07-25 14:55:25.000000000 +0200
+++ wireless-dev-rt61irq/drivers/net/wireless/d80211/rt2x00/rt61pci.c	2006-07-25 16:13:19.000000000 +0200
@@ -1473,72 +1473,119 @@
 	rt61pci_activity_led(rt2x00dev, total_rssi);
 }
 
-static void rt61pci_txdone(void *data)
+static void rt61pci_txdone_entry(struct data_entry *entry, u32 sta_csr4)
 {
-	struct data_ring *ring = data;
-	struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(ring->net_dev);
-	struct data_entry *entry;
+	struct rt2x00_dev *rt2x00dev =
+		ieee80211_dev_hw_data(entry->ring->net_dev);
 	struct txd *txd;
 	int tx_status;
 	int ack;
-	int reg;
 	int ring_full;
 
+	txd = rt2x00pci_desc_addr(entry);
+
+	if (rt2x00_get_field32(txd->word0, TXD_W0_OWNER_NIC) ||
+	    !rt2x00_get_field32(txd->word0, TXD_W0_VALID))
+		return;
+
+	ack = rt2x00_get_field32(txd->word0, TXD_W0_ACK);
+
 	/*
-	 * Store the current status of the ring.
+	 * TODO: How can te below field be set correctly?
 	 */
-	ring_full = rt2x00_ring_full(ring);
+	entry->tx_status.tx_filtered = 0;
 
-	while (!rt2x00_ring_empty(ring)) {
-		entry = rt2x00_get_data_entry_done(ring);
-		txd = rt2x00pci_desc_addr(entry);
+	entry->tx_status.queue_length = entry->ring->stats.limit;
 
-		rt2x00_register_read(rt2x00dev, STA_CSR4, &reg);
+	/*
+	 * The TXD_W0_RESULT field will only be set when
+	 * we had requested an ACK. So we have received an
+	 * ACK response when ACK was requested and status
+	 * was succesfull.
+	 */
+	tx_status = rt2x00_get_field32(sta_csr4, STA_CSR4_TX_RESULT);
+	entry->tx_status.ack = 0;
+	if (ack && (tx_status == TX_SUCCESS ||
+	    tx_status == TX_SUCCESS_RETRY))
+		entry->tx_status.ack = 1;
+	else if (ack && tx_status == TX_FAIL_RETRY) {
+		rt2x00dev->low_level_stats.dot11ACKFailureCount++;
+		entry->tx_status.excessive_retries++;
+	}
 
-		if (rt2x00_get_field32(txd->word0, TXD_W0_OWNER_NIC) ||
-		    !rt2x00_get_field32(txd->word0, TXD_W0_VALID) ||
-		    !rt2x00_get_field32(reg, STA_CSR4_VALID))
-			break;
+	rt2x00_bbp_read(rt2x00dev, 32,
+		(u8*)&entry->tx_status.ack_signal);
 
-		ack = rt2x00_get_field32(txd->word0, TXD_W0_ACK);
+	entry->tx_status.retry_count = rt2x00_get_field32(
+		sta_csr4, STA_CSR4_RETRY_COUNT);
 
-		/*
-		 * TODO: How can te below field be set correctly?
-		 */
-		entry->tx_status.tx_filtered = 0;
+	if (!GET_FLAG(entry, ENTRY_RTS_FRAME))
+		ieee80211_tx_status(entry->ring->net_dev,
+			entry->skb, &entry->tx_status);
 
-		entry->tx_status.queue_length = ring->stats.limit;
+	rt2x00_set_field32(&txd->word0, TXD_W0_VALID, 0);
+	entry->skb = NULL;
 
-		/*
-		 * The TXD_W0_RESULT field will only be set when
-		 * we had requested an ACK. So we have received an
-		 * ACK response when ACK was requested and status
-		 * was succesfull.
-		 */
-		tx_status = rt2x00_get_field32(reg, STA_CSR4_TX_RESULT);
-		entry->tx_status.ack = 0;
-		if (ack && (tx_status == TX_SUCCESS ||
-		    tx_status == TX_SUCCESS_RETRY))
-			entry->tx_status.ack = 1;
-		else if (ack && tx_status == TX_FAIL_RETRY) {
-			rt2x00dev->low_level_stats.dot11ACKFailureCount++;
-			entry->tx_status.excessive_retries++;
-		}
+	/*
+	 * Store the current status of the ring.
+	 */
+	ring_full = rt2x00_ring_full(entry->ring);
 
-		rt2x00_bbp_read(rt2x00dev, 32,
-			(u8*)&entry->tx_status.ack_signal);
+	rt2x00_ring_index_done_inc(entry->ring);
 
-		entry->tx_status.retry_count = rt2x00_get_field32(
-			reg, STA_CSR4_RETRY_COUNT);
+	/*
+	 * If the data ring was full before the txdone handler
+	 * we must make sure the packet queue in the d80211 stack
+	 * is reenabled when the txdone handler has finished.
+	 */
+	if (ring_full && !rt2x00_ring_full(entry->ring))
+		ieee80211_wake_queue(entry->ring->net_dev,
+			entry->tx_status.control.queue);
+}
 
-		if (!GET_FLAG(entry, ENTRY_RTS_FRAME))
-			ieee80211_tx_status(ring->net_dev,
-				entry->skb, &entry->tx_status);
+static void rt61pci_txdone(void *data)
+{
+	struct data_ring *ring = data;
+	struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(ring->net_dev);
+	int index;
+	int reg;
 
-		rt2x00_set_field32(&txd->word0, TXD_W0_VALID, 0);
-		entry->skb = NULL;
+	/*
+	 * Keep looping while STA_CSR4 contains value data.
+	 * at each read the value will be reset to a new value,
+	 * which we should check since it contains the ring
+	 * and index number of the entry which has been
+	 * completely transmitted.
+	 */
+	while (1) {
+		/*
+		 * Stop looping when the entry is invalid.
+		 */
+		rt2x00_register_read(rt2x00dev, STA_CSR4, &reg);
+		if (!rt2x00_get_field32(reg, STA_CSR4_VALID))
+			break;
 
-		rt2x00_ring_index_done_inc(ring);
+		/*
+		 * Skip this entry when it contains an invalid
+		 * ring identication number.
+		 */
+		ring = rt2x00_get_ring(rt2x00dev,
+			rt2x00_get_field32(reg, STA_CSR4_PID_TYPE));
+		if (unlikely(!ring))
+			continue;
+
+		/*
+		 * Skip this entry when it contains an invalid
+		 * index number.
+		 */
+		index = rt2x00_get_field32(reg, STA_CSR4_PID_SUBTYPE);
+		if (unlikely(index >= ring->stats.limit))
+			continue;
+
+		/*
+		 * Packet received correctly, we can now process it.
+		 */
+		rt61pci_txdone_entry(&ring->entry[index], reg);
 	}
 
 	/*
@@ -1554,16 +1601,6 @@
 		rt2x00dev->scan->status = SCANNING_READY;
 		complete(&rt2x00dev->scan->completion);
 	}
-
-	/*
-	 * If the data ring was full before the txdone handler
-	 * we must make sure the packet queue in the d80211 stack
-	 * is reenabled when the txdone handler has finished.
-	 */
-	entry = ring->entry;
-	if (ring_full && !rt2x00_ring_full(ring))
-		ieee80211_wake_queue(ring->net_dev,
-			entry->tx_status.control.queue);
 }
 
 static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance,
@@ -1966,6 +2003,8 @@
 		rt2x00_set_field32(&txd->word1, TXD_W1_BUFFER_COUNT, 1);
 		rt2x00_set_field32(&txd->word6, TXD_W6_BUFFER_PHYSICAL_ADDRESS,
 			ring->entry[i].data_dma);
+		rt2x00_set_field32(&txd->word5, TXD_W5_PID_TYPE, ring->type);
+		rt2x00_set_field32(&txd->word5, TXD_W5_PID_SUBTYPE, i);
 	}
 
 	rt2x00_ring_index_clear(ring);
diff -rU3 wireless-dev-ringentry/drivers/net/wireless/d80211/rt2x00/rt61pci.h wireless-dev-rt61irq/drivers/net/wireless/d80211/rt2x00/rt61pci.h
--- wireless-dev-ringentry/drivers/net/wireless/d80211/rt2x00/rt61pci.h	2006-07-25 10:09:44.000000000 +0200
+++ wireless-dev-rt61irq/drivers/net/wireless/d80211/rt2x00/rt61pci.h	2006-07-25 16:10:20.000000000 +0200
@@ -633,8 +633,8 @@
 #define STA_CSR4_VALID			FIELD32(0x00000001)
 #define STA_CSR4_TX_RESULT		FIELD32(0x0000000e)
 #define STA_CSR4_RETRY_COUNT		FIELD32(0x000000f0)
-#define STA_CSR4_PID_SUBTYPE		FIELD32(0x00003f00)
-#define STA_CSR4_PID_TYPE		FIELD32(0x0000c000)
+#define STA_CSR4_PID_SUBTYPE		FIELD32(0x00001f00)
+#define STA_CSR4_PID_TYPE		FIELD32(0x0000e000)
 #define STA_CSR4_TXRATE			FIELD32(0x000f0000)
 
 /*
@@ -1172,13 +1172,15 @@
 /*
  * WORD5
  * FRAME_OFFSET: Frame start offset inside ASIC TXFIFO (after TXINFO field).
- * PACKET_ID: Driver assigned packet ID to categorize TXResult in interrupt.
+ * TXD_W5_PID_SUBTYPE: Driver assigned packet ID index for txdone handler.
+ * TXD_W5_PID_TYPE: Driver assigned packet ID type for txdone handler.
  * WAITING_DMA_DONE_INT: TXD been filled with data
  * and waiting for TxDoneISR housekeeping.
  */
 	__le32 word5;
 #define TXD_W5_FRAME_OFFSET		FIELD32(0x000000ff)
-#define TXD_W5_PACKET_ID		FIELD32(0x0000ff00)
+#define TXD_W5_PID_SUBTYPE		FIELD32(0x00001f00)
+#define TXD_W5_PID_TYPE			FIELD32(0x0000e000)
 #define TXD_W5_TX_POWER			FIELD32(0x00ff0000)
 #define TXD_W5_WAITING_DMA_DONE_INT	FIELD32(0x01000000)
 

      reply	other threads:[~2006-07-26 18:29 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-07-26 17:05 [PATCH 16/24] RT2x00: Fix rt61pci interrupt handling Ivo van Doorn
2006-07-26 18:29 ` Ivo van Doorn [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=200607262029.30542.IvDoorn@gmail.com \
    --to=ivdoorn@gmail.com \
    --cc=linville@tuxdriver.com \
    --cc=netdev@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).