Subject: [PATCH 14/26] rt2x00: Add more statistics readin

From: Ivo van Doorn <[email-masked]>
Date: Sun, 3 Dec 2006 19:19:01 +0100

Make sure all statistics the d80211 stack requires.
Some of this requires values to be read during
interrupt process (add a new function to handle this).
And other fields can be read from the registers at
request time.
Note that rt61pci and rt73usb had an invalid registername
the legacy drivers are suggesting the CRC_ERROR count is
actually the FCS_ERROR count.

Signed-off-by Ivo van Doorn <[email-masked]>

---

diff -rU3 wireless-dev-signal/drivers/net/wireless/d80211/rt2x00/rt2400pci.c wireless-dev-stats/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-signal/drivers/net/wireless/d80211/rt2x00/rt2400pci.c	2006-12-03 13:49:47.000000000 +0100
+++ wireless-dev-stats/drivers/net/wireless/d80211/rt2x00/rt2400pci.c	2006-12-03 14:03:05.000000000 +0100
@@ -1624,14 +1624,7 @@
 		    !rt2x00_get_field32(word, TXD_W0_VALID))
 			break;
 
-		ack = rt2x00_get_field32(word, TXD_W0_ACK);
-
-		entry->tx_status.flags  = 0;
-		/*
-		 * TODO: How can bit IEEE80211_TX_STATUS_TX_FILTERED of
-		 * entry->tx_status.flags be set correctly?
-		 */
-
+		entry->tx_status.flags = 0;
 		entry->tx_status.queue_length = ring->stats.limit;
 		entry->tx_status.queue_number = entry->tx_status.control.queue;
 
@@ -1641,15 +1634,11 @@
 		 * ACK response when ACK was requested and status
 		 * was succesfull.
 		 */
+		ack = rt2x00_get_field32(word, TXD_W0_ACK);
+		rts = GET_FLAG(entry, ENTRY_RTS_FRAME);
 		tx_status = rt2x00_get_field32(word, TXD_W0_RESULT);
-		entry->tx_status.excessive_retries = 0;
-		if (ack && (tx_status == TX_SUCCESS ||
-		    tx_status == TX_SUCCESS_RETRY))
-			entry->tx_status.flags |= IEEE80211_TX_STATUS_ACK;
-		else if (ack && tx_status == TX_FAIL_RETRY) {
-			rt2x00dev->low_level_stats.dot11ACKFailureCount++;
-			entry->tx_status.excessive_retries = 1;
-		}
+		rt2x00_update_tx_stats(rt2x00dev, &entry->tx_status, tx_status,
+			ack, rts);
 
 		rt2x00_bbp_read(rt2x00dev, 32,
 			(u8*)&entry->tx_status.ack_signal);
@@ -2183,10 +2172,8 @@
 
 	/*
 	 * Update FCS error count from register.
-	 * The dot11ACKFailureCount is updated in interrupt time.
-	 * TODO: dot11RTSFailureCount and dot11RTSSuccessCount
-	 * are never updated, we need to find a method to see
-	 * where we can update those statistics from.
+	 * The dot11ACKFailureCount, dot11RTSFailureCount and
+	 * dot11RTSSuccessCount are updated in interrupt time.
 	 */
 	rt2x00_register_read(rt2x00dev, CNT0, &reg);
 	rt2x00dev->low_level_stats.dot11FCSErrorCount +=
diff -rU3 wireless-dev-signal/drivers/net/wireless/d80211/rt2x00/rt2500pci.c wireless-dev-stats/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-signal/drivers/net/wireless/d80211/rt2x00/rt2500pci.c	2006-12-03 13:52:24.000000000 +0100
+++ wireless-dev-stats/drivers/net/wireless/d80211/rt2x00/rt2500pci.c	2006-12-03 14:00:23.000000000 +0100
@@ -1787,14 +1787,7 @@
 		    !rt2x00_get_field32(word, TXD_W0_VALID))
 			break;
 
-		ack = rt2x00_get_field32(word, TXD_W0_ACK);
-
 		entry->tx_status.flags = 0;
-		/*
-		 * TODO: How can the IEEE80211_TX_STATUS_TX_FILTERED bit of
-		 * entry->tx_status.flags be set correctly?
-		 */
-
 		entry->tx_status.queue_length = ring->stats.limit;
 		entry->tx_status.queue_number = entry->tx_status.control.queue;
 
@@ -1804,15 +1797,11 @@
 		 * ACK response when ACK was requested and status
 		 * was succesfull.
 		 */
+		ack = rt2x00_get_field32(word, TXD_W0_ACK);
+		rts = GET_FLAG(entry, ENTRY_RTS_FRAME);
 		tx_status = rt2x00_get_field32(word, TXD_W0_RESULT);
-		entry->tx_status.excessive_retries = 0;
-		if (ack && (tx_status == TX_SUCCESS ||
-		    tx_status == TX_SUCCESS_RETRY))
-			entry->tx_status.flags |= IEEE80211_TX_STATUS_ACK;
-		else if (ack && tx_status == TX_FAIL_RETRY) {
-			rt2x00dev->low_level_stats.dot11ACKFailureCount++;
-			entry->tx_status.excessive_retries = 1;
-		}
+		rt2x00_update_tx_stats(rt2x00dev, &entry->tx_status, tx_status,
+			ack, rts);
 
 		rt2x00_bbp_read(rt2x00dev, 32,
 			(u8*)&entry->tx_status.ack_signal);
@@ -2342,10 +2331,8 @@
 
 	/*
 	 * Update FCS error count from register.
-	 * The dot11ACKFailureCount is updated in interrupt time.
-	 * TODO: dot11RTSFailureCount and dot11RTSSuccessCount
-	 * are never updated, we need to find a method to see
-	 * where we can update those statistics from.
+	 * The dot11ACKFailureCount, dot11RTSFailureCount and
+	 * dot11RTSSuccessCount are updated in interrupt time.
 	 */
 	rt2x00_register_read(rt2x00dev, CNT0, &reg);
 	rt2x00dev->low_level_stats.dot11FCSErrorCount +=
diff -rU3 wireless-dev-signal/drivers/net/wireless/d80211/rt2x00/rt2500usb.c wireless-dev-stats/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
--- wireless-dev-signal/drivers/net/wireless/d80211/rt2x00/rt2500usb.c	2006-12-03 13:52:23.000000000 +0100
+++ wireless-dev-stats/drivers/net/wireless/d80211/rt2x00/rt2500usb.c	2006-12-03 14:00:12.000000000 +0100
@@ -1744,14 +1744,7 @@
 		if (GET_FLAG(entry, ENTRY_OWNER_NIC))
 			break;
 
-		ack = rt2x00_get_field32(word, TXD_W0_ACK);
-
 		entry->tx_status.flags = 0;
-		/*
-		 * TODO: How can bit IEEE80211_TX_STATUS_TX_FILTERED of
-		 * entry->tx_status.flags be set correctly?
-		 */
-
 		entry->tx_status.queue_length = entry->ring->stats.limit;
 		entry->tx_status.queue_number = entry->tx_status.control.queue;
 
@@ -1760,13 +1753,11 @@
 		 * ACK response when ACK was requested and status
 		 * was succesfull.
 		 */
-		entry->tx_status.excessive_retries = 0;
-		if (ack && (urb->status == TX_SUCCESS))
-			entry->tx_status.flags |= IEEE80211_TX_STATUS_ACK;
-		else if (ack && urb->status == TX_FAIL_OTHER) {
-			rt2x00dev->low_level_stats.dot11ACKFailureCount++;
-			entry->tx_status.excessive_retries = 1;
-		}
+		ack = rt2x00_get_field32(word, TXD_W0_ACK);
+		rts = GET_FLAG(entry, ENTRY_RTS_FRAME);
+		tx_status = !urb->status ? TX_SUCCESS : TX_FAIL_RETRY;
+		rt2x00_update_tx_stats(rt2x00dev, &entry->tx_status, tx_status,
+			ack, rts);
 
 		rt2x00_bbp_read(rt2x00dev, 0,
 			(u8*)&entry->tx_status.ack_signal);
@@ -2241,10 +2232,8 @@
 
 	/*
 	 * Update FCS error count from register.
-	 * The dot11ACKFailureCount is updated in interrupt time.
-	 * TODO: dot11RTSFailureCount and dot11RTSSuccessCount
-	 * are never updated, we need to find a method to see
-	 * where we can update those statistics from.
+	 * The dot11ACKFailureCount, dot11RTSFailureCount and
+	 * dot11RTSSuccessCount are updated in interrupt time.
 	 */
 	rt2x00_register_read(rt2x00dev, STA_CSR0, &reg);
 	rt2x00dev->low_level_stats.dot11FCSErrorCount +=
diff -rU3 wireless-dev-signal/drivers/net/wireless/d80211/rt2x00/rt2x00.h wireless-dev-stats/drivers/net/wireless/d80211/rt2x00/rt2x00.h
--- wireless-dev-signal/drivers/net/wireless/d80211/rt2x00/rt2x00.h	2006-12-03 13:48:57.000000000 +0100
+++ wireless-dev-stats/drivers/net/wireless/d80211/rt2x00/rt2x00.h	2006-12-03 13:55:51.000000000 +0100
@@ -1040,6 +1040,26 @@
 	return NULL;
 }
 
+static inline void rt2x00_update_tx_stats(struct rt2x00_dev *rt2x00dev,
+	struct ieee80211_tx_status *tx_status, const int status,
+	const int is_ack, const int is_rts)
+{
+	struct ieee80211_low_level_stats *stats = &rt2x00dev->low_level_stats;
+
+	if (is_ack)
+		tx_status->flags |= IEEE80211_TX_STATUS_ACK;
+	tx_status->excessive_retries = (status == TX_FAIL_RETRY);
+
+	if (!is_ack && status == TX_FAIL_RETRY)
+		stats->dot11ACKFailureCount++;
+
+	if (is_rts) {
+		if (status == TX_SUCCESS || status == TX_SUCCESS_RETRY)
+			stats->dot11RTSSuccessCount++;
+		else
+			stats->dot11RTSFailureCount++;
+	}
+}
 /*
  * Device specific rate value.
  * We will have to create the device specific rate value
diff -rU3 wireless-dev-signal/drivers/net/wireless/d80211/rt2x00/rt61pci.c wireless-dev-stats/drivers/net/wireless/d80211/rt2x00/rt61pci.c
--- wireless-dev-signal/drivers/net/wireless/d80211/rt2x00/rt61pci.c	2006-12-03 13:52:24.000000000 +0100
+++ wireless-dev-stats/drivers/net/wireless/d80211/rt2x00/rt61pci.c	2006-12-03 14:00:36.000000000 +0100
@@ -2238,11 +2238,6 @@
 	ack = rt2x00_get_field32(word, TXD_W0_ACK);
 
 	entry->tx_status.flags = 0;
-	/*
-	 * TODO: How can the IEEE80211_TX_STATUS_TX_FILTERED bit of
-	 * entry->tx_status.flags be set correctly?
-	 */
-
 	entry->tx_status.queue_length = entry->ring->stats.limit;
 	entry->tx_status.queue_number = entry->tx_status.control.queue;
 
@@ -2252,15 +2247,11 @@
 	 * ACK response when ACK was requested and status
 	 * was succesfull.
 	 */
+	ack = rt2x00_get_field32(word, TXD_W0_ACK);
+	rts = GET_FLAG(entry, ENTRY_RTS_FRAME);
 	tx_status = rt2x00_get_field32(sta_csr4, STA_CSR4_TX_RESULT);
-	entry->tx_status.excessive_retries = 0;
-	if (ack && (tx_status == TX_SUCCESS ||
-	    tx_status == TX_SUCCESS_RETRY))
-		entry->tx_status.flags |= IEEE80211_TX_STATUS_ACK;
-	else if (ack && tx_status == TX_FAIL_RETRY) {
-		rt2x00dev->low_level_stats.dot11ACKFailureCount++;
-		entry->tx_status.excessive_retries = 1;
-	}
+	rt2x00_update_tx_stats(rt2x00dev, &entry->tx_status, tx_status,
+		ack, rts);
 
 	rt2x00_bbp_read(rt2x00dev, 32,
 		(u8*)&entry->tx_status.ack_signal);
@@ -2825,14 +2816,17 @@
 	struct ieee80211_low_level_stats *stats)
 {
 	struct rt2x00_dev *rt2x00dev = hw->priv;
+	u32 reg;
 
 	/*
-	 * The dot11ACKFailureCount is updated in interrupt time.
-	 * TODO: dot11FCSErrorCount, dot11RTSFailureCount and
-	 * dot11RTSSuccessCount are never updated,
-	 * we need to find a method to see where we can update
-	 * those statistics from.
-	 */
+	 * Update FCS error count from register.
+	 * The dot11ACKFailureCount, dot11RTSFailureCount and
+	 * dot11RTSSuccessCount are updated in interrupt time.
+	 */
+	rt2x00_register_read(rt2x00dev, STA_CSR0, &reg);
+	rt2x00dev->low_level_stats.dot11FCSErrorCount +=
+		rt2x00_get_field32(reg, STA_CSR0_FCS_ERROR);
+
 	memcpy(stats, &rt2x00dev->low_level_stats, sizeof(*stats));
 
 	return 0;
diff -rU3 wireless-dev-signal/drivers/net/wireless/d80211/rt2x00/rt61pci.h wireless-dev-stats/drivers/net/wireless/d80211/rt2x00/rt61pci.h
--- wireless-dev-signal/drivers/net/wireless/d80211/rt2x00/rt61pci.h	2006-12-03 13:04:29.000000000 +0100
+++ wireless-dev-stats/drivers/net/wireless/d80211/rt2x00/rt61pci.h	2006-12-03 14:01:38.000000000 +0100
@@ -604,10 +604,10 @@
  */
 
 /*
- * STA_CSR0: RX PLCP error count & RX CRC error count.
+ * STA_CSR0: RX PLCP error count & RX FCS error count.
  */
 #define STA_CSR0			0x30c0
-#define STA_CSR0_CRC_ERROR		FIELD32(0x0000ffff)
+#define STA_CSR0_FCS_ERROR		FIELD32(0x0000ffff)
 #define STA_CSR0_PLCP_ERROR		FIELD32(0xffff0000)
 
 /*
diff -rU3 wireless-dev-signal/drivers/net/wireless/d80211/rt2x00/rt73usb.c wireless-dev-stats/drivers/net/wireless/d80211/rt2x00/rt73usb.c
--- wireless-dev-signal/drivers/net/wireless/d80211/rt2x00/rt73usb.c	2006-12-03 13:52:23.000000000 +0100
+++ wireless-dev-stats/drivers/net/wireless/d80211/rt2x00/rt73usb.c	2006-12-03 14:00:46.000000000 +0100
@@ -2025,14 +2025,7 @@
 		if (GET_FLAG(entry, ENTRY_OWNER_NIC))
 			break;
 
-		ack = rt2x00_get_field32(word, TXD_W0_ACK);
-
 		entry->tx_status.flags = 0;
-		/*
-		 * TODO: How can bit IEEE80211_TX_STATUS_TX_FILTERED of
-		 * entry->tx_status.flags be set correctly?
-		 */
-
 		entry->tx_status.queue_length = entry->ring->stats.limit;
 		entry->tx_status.queue_number = entry->tx_status.control.queue;
 
@@ -2041,13 +2034,11 @@
 		 * ACK response when ACK was requested and status
 		 * was succesfull.
 		 */
-		entry->tx_status.excessive_retries = 0;
-		if (ack && (urb->status == TX_SUCCESS))
-			entry->tx_status.flags |= IEEE80211_TX_STATUS_ACK;
-		else {
-			rt2x00dev->low_level_stats.dot11ACKFailureCount++;
-			entry->tx_status.excessive_retries = 1;
-		}
+		ack = rt2x00_get_field32(word, TXD_W0_ACK);
+		rts = GET_FLAG(entry, ENTRY_RTS_FRAME);
+		tx_status = !urb->status ? TX_SUCCESS : TX_FAIL_RETRY;
+		rt2x00_update_tx_stats(rt2x00dev, &entry->tx_status, tx_status,
+			ack, rts);
 
 		rt2x00_bbp_read(rt2x00dev, 32,
 			(u8*)&entry->tx_status.ack_signal);
@@ -2517,14 +2508,17 @@
 	struct ieee80211_low_level_stats *stats)
 {
 	struct rt2x00_dev *rt2x00dev = hw->priv;
+	u32 reg;
 
 	/*
-	 * The dot11ACKFailureCount is updated in interrupt time.
-	 * TODO: dot11FCSErrorCount, dot11RTSFailureCount and
-	 * dot11RTSSuccessCount are never updated,
-	 * we need to find a method to see where we can update
-	 * those statistics from.
-	 */
+	 * Update FCS error count from register.
+	 * The dot11ACKFailureCount, dot11RTSFailureCount and
+	 * dot11RTSSuccessCount are updated in interrupt time.
+	 */
+	rt2x00_register_read(rt2x00dev, STA_CSR0, &reg);
+	rt2x00dev->low_level_stats.dot11FCSErrorCount +=
+		rt2x00_get_field32(reg, STA_CSR0_FCS_ERROR);
+
 	memcpy(stats, &rt2x00dev->low_level_stats, sizeof(*stats));
 
 	return 0;
diff -rU3 wireless-dev-signal/drivers/net/wireless/d80211/rt2x00/rt73usb.h wireless-dev-stats/drivers/net/wireless/d80211/rt2x00/rt73usb.h
--- wireless-dev-signal/drivers/net/wireless/d80211/rt2x00/rt73usb.h	2006-12-03 13:04:31.000000000 +0100
+++ wireless-dev-stats/drivers/net/wireless/d80211/rt2x00/rt73usb.h	2006-12-03 14:01:58.000000000 +0100
@@ -504,10 +504,10 @@
  */
 
 /*
- * STA_CSR0: RX PLCP error count & RX CRC error count.
+ * STA_CSR0: RX PLCP error count & RX FCS error count.
  */
 #define STA_CSR0			0x30c0
-#define STA_CSR0_CRC_ERROR		FIELD32(0x0000ffff)
+#define STA_CSR0_FCS_ERROR		FIELD32(0x0000ffff)
 #define STA_CSR0_PLCP_ERROR		FIELD32(0xffff0000)
 
 /*