From: Steffen Klassert <klassert@mathematik.tu-chemnitz.de>

With this patch get_ethtool_stats() provides the NIC-specific extra stats. 

Signed-off-by: Steffen Klassert <klassert@mathematik.tu-chemnitz.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/drivers/net/3c59x.c |   49 ++++++++++++++++++++------------------------
 1 files changed, 23 insertions(+), 26 deletions(-)

diff -puN drivers/net/3c59x.c~3c59x-ethtool-provide-nic-specific-stats drivers/net/3c59x.c
--- 25/drivers/net/3c59x.c~3c59x-ethtool-provide-nic-specific-stats	Wed Jan 19 15:31:23 2005
+++ 25-akpm/drivers/net/3c59x.c	Wed Jan 19 15:31:23 2005
@@ -752,6 +752,12 @@ enum tx_desc_status {
 /* Chip features we care about in vp->capabilities, read from the EEPROM. */
 enum ChipCaps { CapBusMaster=0x20, CapPwrMgmt=0x2000 };
 
+struct vortex_extra_stats {
+        unsigned long tx_deferred;
+        unsigned long tx_multiple_collisions;
+        unsigned long rx_bad_ssd;
+};
+
 struct vortex_private {
 	/* The Rx and Tx rings should be quad-word-aligned. */
 	struct boom_rx_desc* rx_ring;
@@ -763,7 +769,8 @@ struct vortex_private {
 	struct sk_buff* tx_skbuff[TX_RING_SIZE];
 	unsigned int cur_rx, cur_tx;		/* The next free ring entry */
 	unsigned int dirty_rx, dirty_tx;	/* The ring entries to be free()ed. */
-	struct net_device_stats stats;
+	struct net_device_stats stats;		/* Generic stats */
+	struct vortex_extra_stats xstats;	/* NIC-specific extra stats */
 	struct sk_buff *tx_skb;				/* Packet being eaten by bus master ctrl.  */
 	dma_addr_t tx_skb_dma;				/* Allocated DMA address for bus master ctrl DMA.   */
 
@@ -854,18 +861,13 @@ static struct media_table {
 static struct {
 	const char str[ETH_GSTRING_LEN];
 } ethtool_stats_keys[] = {
-	{ "rx_packets" },
-	{ "tx_packets" },
-	{ "rx_bytes" },
-	{ "tx_bytes" },
-	{ "collisions" },
-	{ "tx_carrier_errors" },
-	{ "tx_heartbeat_errors" },
-	{ "tx_window_errors" },
+	{ "tx_deferred" },
+	{ "tx_multiple_collisions" },
+	{ "rx_bad_ssd" },
 };
 
 /* number of ETHTOOL_GSTATS u64's */
-#define VORTEX_NUM_STATS      8
+#define VORTEX_NUM_STATS     3
 
 static int vortex_probe1(struct device *gendev, long ioaddr, int irq,
 				   int chip_idx, int card_idx);
@@ -2871,23 +2873,23 @@ static void update_stats(long ioaddr, st
 	/* Switch to the stats window, and read everything. */
 	EL3WINDOW(6);
 	vp->stats.tx_carrier_errors		+= inb(ioaddr + 0);
-	vp->stats.tx_heartbeat_errors	+= inb(ioaddr + 1);
-	/* Multiple collisions. */		inb(ioaddr + 2);
+	vp->stats.tx_heartbeat_errors		+= inb(ioaddr + 1);
 	vp->stats.collisions			+= inb(ioaddr + 3);
 	vp->stats.tx_window_errors		+= inb(ioaddr + 4);
 	vp->stats.rx_fifo_errors		+= inb(ioaddr + 5);
 	vp->stats.tx_packets			+= inb(ioaddr + 6);
 	vp->stats.tx_packets			+= (inb(ioaddr + 9)&0x30) << 4;
-	/* Rx packets	*/				inb(ioaddr + 7);   /* Must read to clear */
-	/* Tx deferrals */				inb(ioaddr + 8);
+	/* Rx packets	*/			inb(ioaddr + 7);   /* Must read to clear */
 	/* Don't bother with register 9, an extension of registers 6&7.
 	   If we do use the 6&7 values the atomic update assumption above
 	   is invalid. */
-	vp->stats.rx_bytes += inw(ioaddr + 10);
-	vp->stats.tx_bytes += inw(ioaddr + 12);
-	/* New: On the Vortex we must also clear the BadSSD counter. */
+	vp->stats.rx_bytes 			+= inw(ioaddr + 10);
+	vp->stats.tx_bytes 			+= inw(ioaddr + 12);
+	/* Extra stats for get_ethtool_stats() */
+	vp->xstats.tx_multiple_collisions	+= inb(ioaddr + 2);
+	vp->xstats.tx_deferred			+= inb(ioaddr + 8);
 	EL3WINDOW(4);
-	inb(ioaddr + 12);
+	vp->xstats.rx_bad_ssd			+= inb(ioaddr + 12);
 
 	{
 		u8 up = inb(ioaddr + 13);
@@ -2980,14 +2982,9 @@ static void vortex_get_ethtool_stats(str
 	update_stats(dev->base_addr, dev);
 	spin_unlock_irqrestore(&vp->lock, flags);
 
-	data[0] = vp->stats.rx_packets;
-	data[1] = vp->stats.tx_packets;
-	data[2] = vp->stats.rx_bytes;
-	data[3] = vp->stats.tx_bytes;
-	data[4] = vp->stats.collisions;
-	data[5] = vp->stats.tx_carrier_errors;
-	data[6] = vp->stats.tx_heartbeat_errors;
-	data[7] = vp->stats.tx_window_errors;
+	data[0] = vp->xstats.tx_deferred;
+	data[1] = vp->xstats.tx_multiple_collisions;
+	data[2] = vp->xstats.rx_bad_ssd;
 }
 
 
_