[PATCH 16/24] RT2x00: Fix rt61pci interrupt handling

2006-07-26 Thread Ivo van Doorn
From Ivo van Doorn [EMAIL PROTECTED]

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 [EMAIL PROTECTED]

---

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.0 +0200
+++ wireless-dev-rt61irq/drivers/net/wireless/d80211/rt2x00/rt61pci.c   
2006-07-25 16:13:19.0 +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 

Re: [PATCH 16/24] RT2x00: Fix rt61pci interrupt handling

2006-07-26 Thread Ivo van Doorn
From Ivo van Doorn [EMAIL PROTECTED]

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 [EMAIL PROTECTED]

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.0 +0200
+++ wireless-dev-rt61irq/drivers/net/wireless/d80211/rt2x00/rt61pci.c   
2006-07-25 16:13:19.0 +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