netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH]: r8169: Expose hardware stats via ethtool
@ 2005-02-26 14:53 Richard Dawe
  2005-02-26 15:57 ` Jeff Garzik
                   ` (3 more replies)
  0 siblings, 4 replies; 17+ messages in thread
From: Richard Dawe @ 2005-02-26 14:53 UTC (permalink / raw)
  To: Francois Romieu, Jon Mason; +Cc: netdev

[-- Attachment #1: Type: text/plain, Size: 1559 bytes --]

Hi Francois and Jon!

Please find attached a patch that adds the hardware statistics ethtool 
operations to the r8169 driver. It's against 2.6.11-rc5.

Signed-Off-By: Richard Dawe <rich@phekda.gotadsl.co.uk>

Basically it's a port of the 8139cp stats routines to r8169. In 8139cp 
the stats buffer is in the ring buffers' DMA mapping. In this patch for 
r8169 it has its own DMA mapping.

One problem: Bogus stats are generated when I insert the module but 
don't bring it up. E.g.: if I do this on FC3 (eth0 == r8169):

   <--(Using 2.6.11-rc5's r8169 driver here)-->
   service network stop
   rmmod r8169
   insmod /path/to/new/r8169.ko
   ethtool -S eth0

I get this:

NIC statistics:
      tx_ok: 18446604436244066304
      rx_ok: 4096
      tx_err: 0
      rx_err: 0
      rx_fifo: 4
      frame_align: 1
      tx_ok_1col: 488917820
      tx_ok_mcol: 0
      rx_ok_phys: 18446604435732824074
      rx_ok_bcast: 18446744071565939505
      rx_ok_mcast: 0
      tx_abort: 18446604435732824064
      tx_underrun: 18446604436090647520

If I then bring the interface up ("ifconfig eth0 up"), I get valid stats.

Any suggestions on how to fix this? I tried a couple of things:

* Return in get_ethtool_stats if !netif_running(). Made no difference.

* Zero the stats after creating the DMA mapping with 
pci_alloc_consistent(). Made no difference.

I wonder if 8139cp has the same problem?

Thanks, bye, Rich =]

--
Richard Dawe [ http://homepages.nildram.co.uk/~phekda/richdawe/ ]

"You can't evaluate a man by logic alone."
   -- McCoy, "I, Mudd", Star Trek

[-- Attachment #2: r8169-ethtool-stats.diff --]
[-- Type: text/plain, Size: 4982 bytes --]

--- linux-2.6.11-rc5/drivers/net/r8169.c.orig	2005-02-24 16:40:30.000000000 +0000
+++ linux-2.6.11-rc5/drivers/net/r8169.c	2005-02-26 14:28:37.000000000 +0000
@@ -128,6 +128,7 @@ static int multicast_filter_limit = 32;
 #define RX_BUF_SIZE	1536	/* Rx Buffer size */
 #define R8169_TX_RING_BYTES	(NUM_TX_DESC * sizeof(struct TxDesc))
 #define R8169_RX_RING_BYTES	(NUM_RX_DESC * sizeof(struct RxDesc))
+#define R8169_STATS_BYTES	64
 
 #define RTL8169_TX_TIMEOUT	(6*HZ)
 #define RTL8169_PHY_TIMEOUT	(10*HZ)
@@ -187,6 +188,8 @@ static int use_dac;
 enum RTL8169_registers {
 	MAC0 = 0,		/* Ethernet hardware address. */
 	MAR0 = 8,		/* Multicast filter. */
+	StatsAddrLow = 0x10,
+	StatsAddrHigh = 0x14,
 	TxDescStartAddrLow = 0x20,
 	TxDescStartAddrHigh = 0x24,
 	TxHDescStartAddrLow = 0x28,
@@ -255,6 +258,9 @@ enum RTL8169_register_content {
 	Cfg9346_Lock = 0x00,
 	Cfg9346_Unlock = 0xC0,
 
+	/* StatsAddr register */
+	DumpStats = (1 << 3),
+
 	/* rx_mode_bits */
 	AcceptErr = 0x20,
 	AcceptRunt = 0x10,
@@ -380,6 +386,22 @@ struct ring_info {
 	u8		__pad[sizeof(void *) - sizeof(u32)];
 };
 
+struct rtl8169_stats {
+	u64 tx_ok;
+	u64 rx_ok;
+	u64 tx_err;
+	u32 rx_err;
+	u16 rx_fifo;
+	u16 frame_align;
+	u32 tx_ok_1col;
+	u32 tx_ok_mcol;
+	u64 rx_ok_phys;
+	u64 rx_ok_bcast;
+	u32 rx_ok_mcast;
+	u16 tx_abort;
+	u16 tx_underrun;
+} __attribute__((packed));
+
 struct rtl8169_private {
 	void __iomem *mmio_addr;	/* memory map physical address */
 	struct pci_dev *pci_dev;	/* Index of PCI device */
@@ -404,6 +426,8 @@ struct rtl8169_private {
 	u16 intr_mask;
 	int phy_auto_nego_reg;
 	int phy_1000_ctrl_reg;
+	struct rtl8169_stats *nic_stats;
+	dma_addr_t nic_stats_addr;
 #ifdef CONFIG_R8169_VLAN
 	struct vlan_group *vlgrp;
 #endif
@@ -871,6 +895,68 @@ static void rtl8169_get_regs(struct net_
         spin_unlock_irqrestore(&tp->lock, flags);
 }
 
+static const char rtl8169_gstrings_stats[][ETH_GSTRING_LEN] = {
+	"tx_ok", "rx_ok", "tx_err", "rx_err",
+	"rx_fifo", "frame_align", "tx_ok_1col", "tx_ok_mcol",
+	"rx_ok_phys", "rx_ok_bcast", "rx_ok_mcast", "tx_abort",
+	"tx_underrun",
+};
+#define RTL8169_STATS_LEN sizeof(rtl8169_gstrings_stats) / ETH_GSTRING_LEN
+
+static int rtl8169_get_stats_count(struct net_device *dev)
+{
+	return RTL8169_STATS_LEN;
+}
+
+static void rtl8169_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
+{
+	switch(stringset) {
+	case ETH_SS_STATS:
+		memcpy(data, *rtl8169_gstrings_stats, sizeof(rtl8169_gstrings_stats));
+		break;
+	}
+}
+
+static void rtl8169_get_ethtool_stats(struct net_device *netdev,
+	struct ethtool_stats *stats, u64 *data)
+{
+	struct rtl8169_private *tp = netdev_priv(netdev);
+	void __iomem *ioaddr = tp->mmio_addr;
+	int work = 100;
+	int i;
+
+	/* begin NIC statistics dump */
+	RTL_W32(StatsAddrHigh, tp->nic_stats_addr >> 32);
+	RTL_W32(StatsAddrLow, (tp->nic_stats_addr & 0xffffffff) | DumpStats);
+	RTL_R32(StatsAddrLow);
+
+	while (work-- > 0) {
+		if ((RTL_R32(StatsAddrLow) & DumpStats) == 0)
+			break;
+		cpu_relax();
+	}
+
+	if (RTL_R32(StatsAddrLow) & DumpStats)
+		return; /* no stats - took too long */
+
+	i = 0;
+	data[i++] = le64_to_cpu(tp->nic_stats->tx_ok);
+	data[i++] = le64_to_cpu(tp->nic_stats->rx_ok);
+	data[i++] = le64_to_cpu(tp->nic_stats->tx_err);
+	data[i++] = le32_to_cpu(tp->nic_stats->rx_err);
+	data[i++] = le16_to_cpu(tp->nic_stats->rx_fifo);
+	data[i++] = le16_to_cpu(tp->nic_stats->frame_align);
+	data[i++] = le32_to_cpu(tp->nic_stats->tx_ok_1col);
+	data[i++] = le32_to_cpu(tp->nic_stats->tx_ok_mcol);
+	data[i++] = le64_to_cpu(tp->nic_stats->rx_ok_phys);
+	data[i++] = le64_to_cpu(tp->nic_stats->rx_ok_bcast);
+	data[i++] = le32_to_cpu(tp->nic_stats->rx_ok_mcast);
+	data[i++] = le16_to_cpu(tp->nic_stats->tx_abort);
+	data[i++] = le16_to_cpu(tp->nic_stats->tx_underrun);
+	if (i != RTL8169_STATS_LEN)
+		BUG();
+}
+
 static struct ethtool_ops rtl8169_ethtool_ops = {
 	.get_drvinfo		= rtl8169_get_drvinfo,
 	.get_regs_len		= rtl8169_get_regs_len,
@@ -886,6 +972,9 @@ static struct ethtool_ops rtl8169_ethtoo
 	.get_tso		= ethtool_op_get_tso,
 	.set_tso		= ethtool_op_set_tso,
 	.get_regs		= rtl8169_get_regs,
+	.get_strings		= rtl8169_get_strings,
+	.get_stats_count	= rtl8169_get_stats_count,
+	.get_ethtool_stats	= rtl8169_get_ethtool_stats,
 };
 
 static void rtl8169_write_gmii_reg_bit(void __iomem *ioaddr, int reg, int bitnum,
@@ -1531,6 +1620,11 @@ static int rtl8169_open(struct net_devic
 	if (retval < 0)
 		goto err_free_rx;
 
+	tp->nic_stats = pci_alloc_consistent(pdev, R8169_STATS_BYTES,
+					     &tp->nic_stats_addr);
+	if (!tp->nic_stats)
+		goto err_free_nic_stats;
+
 	INIT_WORK(&tp->task, NULL, dev);
 
 	rtl8169_hw_start(dev);
@@ -1541,6 +1635,10 @@ static int rtl8169_open(struct net_devic
 out:
 	return retval;
 
+err_free_nic_stats:
+	pci_free_consistent(pdev, R8169_STATS_BYTES, tp->nic_stats,
+			    tp->nic_stats_addr);
+
 err_free_rx:
 	pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray,
 			    tp->RxPhyAddr);

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH]: r8169: Expose hardware stats via ethtool
  2005-02-26 14:53 [PATCH]: r8169: Expose hardware stats via ethtool Richard Dawe
@ 2005-02-26 15:57 ` Jeff Garzik
  2005-02-27 22:46   ` Richard Dawe
  2005-02-26 17:32 ` Jon Mason
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 17+ messages in thread
From: Jeff Garzik @ 2005-02-26 15:57 UTC (permalink / raw)
  To: Richard Dawe; +Cc: Francois Romieu, Jon Mason, netdev

Richard Dawe wrote:
> Hi Francois and Jon!
> 
> Please find attached a patch that adds the hardware statistics ethtool 
> operations to the r8169 driver. It's against 2.6.11-rc5.
> 
> Signed-Off-By: Richard Dawe <rich@phekda.gotadsl.co.uk>
> 
> Basically it's a port of the 8139cp stats routines to r8169. In 8139cp 
> the stats buffer is in the ring buffers' DMA mapping. In this patch for 
> r8169 it has its own DMA mapping.
> 
> One problem: Bogus stats are generated when I insert the module but 
> don't bring it up. E.g.: if I do this on FC3 (eth0 == r8169):
> 
>   <--(Using 2.6.11-rc5's r8169 driver here)-->
>   service network stop
>   rmmod r8169
>   insmod /path/to/new/r8169.ko
>   ethtool -S eth0
> 
> I get this:
> 
> NIC statistics:
>      tx_ok: 18446604436244066304
>      rx_ok: 4096
>      tx_err: 0
>      rx_err: 0
>      rx_fifo: 4
>      frame_align: 1
>      tx_ok_1col: 488917820
>      tx_ok_mcol: 0
>      rx_ok_phys: 18446604435732824074
>      rx_ok_bcast: 18446744071565939505
>      rx_ok_mcast: 0
>      tx_abort: 18446604435732824064
>      tx_underrun: 18446604436090647520
> 
> If I then bring the interface up ("ifconfig eth0 up"), I get valid stats.
> 
> Any suggestions on how to fix this? I tried a couple of things:
> 
> * Return in get_ethtool_stats if !netif_running(). Made no difference.
> 
> * Zero the stats after creating the DMA mapping with 
> pci_alloc_consistent(). Made no difference.
> 
> I wonder if 8139cp has the same problem?

No idea..  Worth checking.



> +static const char rtl8169_gstrings_stats[][ETH_GSTRING_LEN] = {
> +	"tx_ok", "rx_ok", "tx_err", "rx_err",
> +	"rx_fifo", "frame_align", "tx_ok_1col", "tx_ok_mcol",
> +	"rx_ok_phys", "rx_ok_bcast", "rx_ok_mcast", "tx_abort",
> +	"tx_underrun",
> +};

Don't needlessly reformat copied code.  It's one-string-per-line 
intentionally, for ease of maintenance and ease of adding new strings.

Also, I don't see why you renamed this from ethtool_stats_keys[].


> +	/* begin NIC statistics dump */
> +	RTL_W32(StatsAddrHigh, tp->nic_stats_addr >> 32);
> +	RTL_W32(StatsAddrLow, (tp->nic_stats_addr & 0xffffffff) | DumpStats);
> +	RTL_R32(StatsAddrLow);

This last RTL_R32() can be removed [from 8139cp too], because a flush 
immediately follows anyway:

> +	while (work-- > 0) {
> +		if ((RTL_R32(StatsAddrLow) & DumpStats) == 0)
> +			break;
> +		cpu_relax();
> +	}

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH]: r8169: Expose hardware stats via ethtool
  2005-02-26 14:53 [PATCH]: r8169: Expose hardware stats via ethtool Richard Dawe
  2005-02-26 15:57 ` Jeff Garzik
@ 2005-02-26 17:32 ` Jon Mason
  2005-02-26 18:02   ` Jeff Garzik
  2005-02-26 18:26 ` Francois Romieu
  2005-02-27 19:28 ` Jon Mason
  3 siblings, 1 reply; 17+ messages in thread
From: Jon Mason @ 2005-02-26 17:32 UTC (permalink / raw)
  To: Richard Dawe; +Cc: Francois Romieu, netdev

On Saturday 26 February 2005 08:53 am, Richard Dawe wrote:
> Hi Francois and Jon!
> 
> Please find attached a patch that adds the hardware statistics ethtool 
> operations to the r8169 driver. It's against 2.6.11-rc5.

Good Work!  I'll give it a try here in a little bit.

[...]
> If I then bring the interface up ("ifconfig eth0 up"), I get valid stats.
> 
> Any suggestions on how to fix this? I tried a couple of things:
> 
> * Return in get_ethtool_stats if !netif_running(). Made no difference.
> 
> * Zero the stats after creating the DMA mapping with 
> pci_alloc_consistent(). Made no difference.

Can you confirm that the registers are outputting these bogus values?

See comments below. 

<paste from attachment>

--- linux-2.6.11-rc5/drivers/net/r8169.c.orig   2005-02-24 16:40:30.000000000 +0000
+++ linux-2.6.11-rc5/drivers/net/r8169.c        2005-02-26 14:28:37.000000000 +0000
@@ -128,6 +128,7 @@ static int multicast_filter_limit = 32;
 #define RX_BUF_SIZE    1536    /* Rx Buffer size */
 #define R8169_TX_RING_BYTES    (NUM_TX_DESC * sizeof(struct TxDesc))
 #define R8169_RX_RING_BYTES    (NUM_RX_DESC * sizeof(struct RxDesc))
+#define R8169_STATS_BYTES      64
 
 #define RTL8169_TX_TIMEOUT     (6*HZ)
 #define RTL8169_PHY_TIMEOUT    (10*HZ)
@@ -187,6 +188,8 @@ static int use_dac;
 enum RTL8169_registers {
        MAC0 = 0,               /* Ethernet hardware address. */
        MAR0 = 8,               /* Multicast filter. */
+       StatsAddrLow = 0x10,
+       StatsAddrHigh = 0x14,
        TxDescStartAddrLow = 0x20,
        TxDescStartAddrHigh = 0x24,
        TxHDescStartAddrLow = 0x28,
@@ -255,6 +258,9 @@ enum RTL8169_register_content {
        Cfg9346_Lock = 0x00,
        Cfg9346_Unlock = 0xC0,
 
+       /* StatsAddr register */
+       DumpStats = (1 << 3),
+

Wouldn't this be better as "0x08"?  Also, RTL8169_register_content could do with a bit of tidying (values are expressed in decimal and hex, some are aligned and others not, etc).  I'll try and come-up with a patch here in a bit.



        /* rx_mode_bits */
        AcceptErr = 0x20,
        AcceptRunt = 0x10,
@@ -380,6 +386,22 @@ struct ring_info {
        u8              __pad[sizeof(void *) - sizeof(u32)];
 };
 
+struct rtl8169_stats {
+       u64 tx_ok;
+       u64 rx_ok;
+       u64 tx_err;
+       u32 rx_err;
+       u16 rx_fifo;
+       u16 frame_align;
+       u32 tx_ok_1col;
+       u32 tx_ok_mcol;
+       u64 rx_ok_phys;
+       u64 rx_ok_bcast;
+       u32 rx_ok_mcast;
+       u16 tx_abort;
+       u16 tx_underrun;
+} __attribute__((packed));
+


These could all be u64's.  It would take-up more memory (and a bit more code in the register dump), but the values would be more accurate.  Just an idea.



 struct rtl8169_private {
        void __iomem *mmio_addr;        /* memory map physical address */
        struct pci_dev *pci_dev;        /* Index of PCI device */
@@ -404,6 +426,8 @@ struct rtl8169_private {
        u16 intr_mask;
        int phy_auto_nego_reg;
        int phy_1000_ctrl_reg;
+       struct rtl8169_stats *nic_stats;
+       dma_addr_t nic_stats_addr;
 #ifdef CONFIG_R8169_VLAN
        struct vlan_group *vlgrp;
 #endif
@@ -871,6 +895,68 @@ static void rtl8169_get_regs(struct net_
         spin_unlock_irqrestore(&tp->lock, flags);
 }
 
+static const char rtl8169_gstrings_stats[][ETH_GSTRING_LEN] = {
+       "tx_ok", "rx_ok", "tx_err", "rx_err",
+       "rx_fifo", "frame_align", "tx_ok_1col", "tx_ok_mcol",
+       "rx_ok_phys", "rx_ok_bcast", "rx_ok_mcast", "tx_abort",
+       "tx_underrun",
+};
+#define RTL8169_STATS_LEN sizeof(rtl8169_gstrings_stats) / ETH_GSTRING_LEN
+
+static int rtl8169_get_stats_count(struct net_device *dev)
+{
+       return RTL8169_STATS_LEN;
+}
+
+static void rtl8169_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
+{
+       switch(stringset) {
+       case ETH_SS_STATS:
+               memcpy(data, *rtl8169_gstrings_stats, sizeof(rtl8169_gstrings_stats));
+               break;
+       }
+}
+
+static void rtl8169_get_ethtool_stats(struct net_device *netdev,
+       struct ethtool_stats *stats, u64 *data)
+{
+       struct rtl8169_private *tp = netdev_priv(netdev);
+       void __iomem *ioaddr = tp->mmio_addr;
+       int work = 100;
+       int i;
+
+       /* begin NIC statistics dump */
+       RTL_W32(StatsAddrHigh, tp->nic_stats_addr >> 32);
+       RTL_W32(StatsAddrLow, (tp->nic_stats_addr & 0xffffffff) | DumpStats);
+       RTL_R32(StatsAddrLow);
+
+       while (work-- > 0) {
+               if ((RTL_R32(StatsAddrLow) & DumpStats) == 0)
+                       break;
+               cpu_relax();
+       }
+
+       if (RTL_R32(StatsAddrLow) & DumpStats)
+               return; /* no stats - took too long */
+
+       i = 0;
+       data[i++] = le64_to_cpu(tp->nic_stats->tx_ok);
+       data[i++] = le64_to_cpu(tp->nic_stats->rx_ok);
+       data[i++] = le64_to_cpu(tp->nic_stats->tx_err);
+       data[i++] = le32_to_cpu(tp->nic_stats->rx_err);
+       data[i++] = le16_to_cpu(tp->nic_stats->rx_fifo);
+       data[i++] = le16_to_cpu(tp->nic_stats->frame_align);
+       data[i++] = le32_to_cpu(tp->nic_stats->tx_ok_1col);
+       data[i++] = le32_to_cpu(tp->nic_stats->tx_ok_mcol);
+       data[i++] = le64_to_cpu(tp->nic_stats->rx_ok_phys);
+       data[i++] = le64_to_cpu(tp->nic_stats->rx_ok_bcast);
+       data[i++] = le32_to_cpu(tp->nic_stats->rx_ok_mcast);
+       data[i++] = le16_to_cpu(tp->nic_stats->tx_abort);
+       data[i++] = le16_to_cpu(tp->nic_stats->tx_underrun);
+       if (i != RTL8169_STATS_LEN)
+               BUG();
+}
+

It seems to me that 'i' could be re-used, instead of having both 'i' and 'work'.  Also,  'u32' or 'unsigned int' is prefered to int  (see http://www.kroah.com/linux/talks/portable_kernel_code_talk_2001_10_02/mgp00022.html).  Also, changes will need to be made if it is decided to use u64 (see above)



 static struct ethtool_ops rtl8169_ethtool_ops = {
        .get_drvinfo            = rtl8169_get_drvinfo,
        .get_regs_len           = rtl8169_get_regs_len,
@@ -886,6 +972,9 @@ static struct ethtool_ops rtl8169_ethtoo
        .get_tso                = ethtool_op_get_tso,
        .set_tso                = ethtool_op_set_tso,
        .get_regs               = rtl8169_get_regs,
+       .get_strings            = rtl8169_get_strings,
+       .get_stats_count        = rtl8169_get_stats_count,
+       .get_ethtool_stats      = rtl8169_get_ethtool_stats,
 };
 
 static void rtl8169_write_gmii_reg_bit(void __iomem *ioaddr, int reg, int bitnum,
@@ -1531,6 +1620,11 @@ static int rtl8169_open(struct net_devic
        if (retval < 0)
                goto err_free_rx;
 
+       tp->nic_stats = pci_alloc_consistent(pdev, R8169_STATS_BYTES,
+                                            &tp->nic_stats_addr);
+       if (!tp->nic_stats)
+               goto err_free_nic_stats;
+
        INIT_WORK(&tp->task, NULL, dev);
 
        rtl8169_hw_start(dev);
@@ -1541,6 +1635,10 @@ static int rtl8169_open(struct net_devic
 out:
        return retval;
 
+err_free_nic_stats:
+       pci_free_consistent(pdev, R8169_STATS_BYTES, tp->nic_stats,
+                           tp->nic_stats_addr);
+
 err_free_rx:
        pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray,
                            tp->RxPhyAddr);

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH]: r8169: Expose hardware stats via ethtool
  2005-02-26 17:32 ` Jon Mason
@ 2005-02-26 18:02   ` Jeff Garzik
  2005-02-26 18:03     ` Jeff Garzik
                       ` (2 more replies)
  0 siblings, 3 replies; 17+ messages in thread
From: Jeff Garzik @ 2005-02-26 18:02 UTC (permalink / raw)
  To: Jon Mason; +Cc: Richard Dawe, Francois Romieu, netdev

Jon Mason wrote:
> On Saturday 26 February 2005 08:53 am, Richard Dawe wrote:
> 
>>Hi Francois and Jon!
>>
>>Please find attached a patch that adds the hardware statistics ethtool 
>>operations to the r8169 driver. It's against 2.6.11-rc5.
> 
> 
> Good Work!  I'll give it a try here in a little bit.
> 
> [...]
> 
>>If I then bring the interface up ("ifconfig eth0 up"), I get valid stats.
>>
>>Any suggestions on how to fix this? I tried a couple of things:
>>
>>* Return in get_ethtool_stats if !netif_running(). Made no difference.
>>
>>* Zero the stats after creating the DMA mapping with 
>>pci_alloc_consistent(). Made no difference.
> 
> 
> Can you confirm that the registers are outputting these bogus values?
> 
> See comments below. 
> 
> <paste from attachment>
> 
> --- linux-2.6.11-rc5/drivers/net/r8169.c.orig   2005-02-24 16:40:30.000000000 +0000
> +++ linux-2.6.11-rc5/drivers/net/r8169.c        2005-02-26 14:28:37.000000000 +0000
> @@ -128,6 +128,7 @@ static int multicast_filter_limit = 32;
>  #define RX_BUF_SIZE    1536    /* Rx Buffer size */
>  #define R8169_TX_RING_BYTES    (NUM_TX_DESC * sizeof(struct TxDesc))
>  #define R8169_RX_RING_BYTES    (NUM_RX_DESC * sizeof(struct RxDesc))
> +#define R8169_STATS_BYTES      64
>  
>  #define RTL8169_TX_TIMEOUT     (6*HZ)
>  #define RTL8169_PHY_TIMEOUT    (10*HZ)
> @@ -187,6 +188,8 @@ static int use_dac;
>  enum RTL8169_registers {
>         MAC0 = 0,               /* Ethernet hardware address. */
>         MAR0 = 8,               /* Multicast filter. */
> +       StatsAddrLow = 0x10,
> +       StatsAddrHigh = 0x14,
>         TxDescStartAddrLow = 0x20,
>         TxDescStartAddrHigh = 0x24,
>         TxHDescStartAddrLow = 0x28,
> @@ -255,6 +258,9 @@ enum RTL8169_register_content {
>         Cfg9346_Lock = 0x00,
>         Cfg9346_Unlock = 0xC0,
>  
> +       /* StatsAddr register */
> +       DumpStats = (1 << 3),
> +
> 
> Wouldn't this be better as "0x08"?  Also, RTL8169_register_content could do with a bit of tidying (values are expressed in decimal and hex, some are aligned and others not, etc).  I'll try and come-up with a patch here in a bit.

The form "(1 << n)" is preferred, since that form makes plain the bit 
number, with zero neural transformation required.

Use the more readable form.  Cleanup patches accepted.


>         /* rx_mode_bits */
>         AcceptErr = 0x20,
>         AcceptRunt = 0x10,
> @@ -380,6 +386,22 @@ struct ring_info {
>         u8              __pad[sizeof(void *) - sizeof(u32)];
>  };
>  
> +struct rtl8169_stats {
> +       u64 tx_ok;
> +       u64 rx_ok;
> +       u64 tx_err;
> +       u32 rx_err;
> +       u16 rx_fifo;
> +       u16 frame_align;
> +       u32 tx_ok_1col;
> +       u32 tx_ok_mcol;
> +       u64 rx_ok_phys;
> +       u64 rx_ok_bcast;
> +       u32 rx_ok_mcast;
> +       u16 tx_abort;
> +       u16 tx_underrun;
> +} __attribute__((packed));
> +
> 
> 
> These could all be u64's.  It would take-up more memory (and a bit more code in the register dump), but the values would be more accurate.  Just an idea.

No, this is the representation of the hardware DMA structure.

It is defined by the hardware, not the programmer.


> +static void rtl8169_get_ethtool_stats(struct net_device *netdev,
> +       struct ethtool_stats *stats, u64 *data)
> +{
> +       struct rtl8169_private *tp = netdev_priv(netdev);
> +       void __iomem *ioaddr = tp->mmio_addr;
> +       int work = 100;
> +       int i;
> +
> +       /* begin NIC statistics dump */
> +       RTL_W32(StatsAddrHigh, tp->nic_stats_addr >> 32);
> +       RTL_W32(StatsAddrLow, (tp->nic_stats_addr & 0xffffffff) | DumpStats);
> +       RTL_R32(StatsAddrLow);
> +
> +       while (work-- > 0) {
> +               if ((RTL_R32(StatsAddrLow) & DumpStats) == 0)
> +                       break;
> +               cpu_relax();
> +       }
> +
> +       if (RTL_R32(StatsAddrLow) & DumpStats)
> +               return; /* no stats - took too long */
> +
> +       i = 0;
> +       data[i++] = le64_to_cpu(tp->nic_stats->tx_ok);
> +       data[i++] = le64_to_cpu(tp->nic_stats->rx_ok);
> +       data[i++] = le64_to_cpu(tp->nic_stats->tx_err);
> +       data[i++] = le32_to_cpu(tp->nic_stats->rx_err);
> +       data[i++] = le16_to_cpu(tp->nic_stats->rx_fifo);
> +       data[i++] = le16_to_cpu(tp->nic_stats->frame_align);
> +       data[i++] = le32_to_cpu(tp->nic_stats->tx_ok_1col);
> +       data[i++] = le32_to_cpu(tp->nic_stats->tx_ok_mcol);
> +       data[i++] = le64_to_cpu(tp->nic_stats->rx_ok_phys);
> +       data[i++] = le64_to_cpu(tp->nic_stats->rx_ok_bcast);
> +       data[i++] = le32_to_cpu(tp->nic_stats->rx_ok_mcast);
> +       data[i++] = le16_to_cpu(tp->nic_stats->tx_abort);
> +       data[i++] = le16_to_cpu(tp->nic_stats->tx_underrun);
> +       if (i != RTL8169_STATS_LEN)
> +               BUG();
> +}
> +
> 
> It seems to me that 'i' could be re-used, instead of having both 'i' and 'work'.

No.  That's a completely useless pseudo-optimization.  Write readable 
code, and let the compiler do the rest.

Any modern compiler will see where the live range of 'work' ends, and 
'i' begins.


   Also,  'u32' or 'unsigned int' is prefered to int  (see 
http://www.kroah.com/linux/talks/portable_kernel_code_talk_2001_10_02/mgp00022.html). 
  Also, changes will need to be made if it is decided to use u64 (see above)

True, but irrelevant in this case.  The code generated by the compiler 
is the same.

	Jeff

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH]: r8169: Expose hardware stats via ethtool
  2005-02-26 18:02   ` Jeff Garzik
@ 2005-02-26 18:03     ` Jeff Garzik
  2005-02-26 18:12     ` Francois Romieu
  2005-02-26 18:36     ` Jon Mason
  2 siblings, 0 replies; 17+ messages in thread
From: Jeff Garzik @ 2005-02-26 18:03 UTC (permalink / raw)
  To: Jon Mason; +Cc: Richard Dawe, Francois Romieu, netdev

Also, please turn on word wrap in your mailer.

	Jeff

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH]: r8169: Expose hardware stats via ethtool
  2005-02-26 18:02   ` Jeff Garzik
  2005-02-26 18:03     ` Jeff Garzik
@ 2005-02-26 18:12     ` Francois Romieu
  2005-02-27 22:53       ` Richard Dawe
  2005-02-26 18:36     ` Jon Mason
  2 siblings, 1 reply; 17+ messages in thread
From: Francois Romieu @ 2005-02-26 18:12 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: Jon Mason, Richard Dawe, netdev

Jeff Garzik <jgarzik@pobox.com> :
[...]
> >+static void rtl8169_get_ethtool_stats(struct net_device *netdev,
> >+       struct ethtool_stats *stats, u64 *data)
> >+{
> >+       struct rtl8169_private *tp = netdev_priv(netdev);
> >+       void __iomem *ioaddr = tp->mmio_addr;
> >+       int work = 100;
> >+       int i;
> >+
> >+       /* begin NIC statistics dump */
> >+       RTL_W32(StatsAddrHigh, tp->nic_stats_addr >> 32);
> >+       RTL_W32(StatsAddrLow, (tp->nic_stats_addr & 0xffffffff) | 
> >DumpStats);
> >+       RTL_R32(StatsAddrLow);
> >+
> >+       while (work-- > 0) {
> >+               if ((RTL_R32(StatsAddrLow) & DumpStats) == 0)
> >+                       break;
> >+               cpu_relax();
> >+       }
> >+
> >+       if (RTL_R32(StatsAddrLow) & DumpStats)
> >+               return; /* no stats - took too long */
> >+
> >+       i = 0;
> >+       data[i++] = le64_to_cpu(tp->nic_stats->tx_ok);
[...]
> >+       data[i++] = le16_to_cpu(tp->nic_stats->tx_underrun);
> >+       if (i != RTL8169_STATS_LEN)
> >+               BUG();
> >+}
> >+
> >
> >It seems to me that 'i' could be re-used, instead of having both 'i' and 
> >'work'.
> 
> No.  That's a completely useless pseudo-optimization.  Write readable 
> code, and let the compiler do the rest.

Btw I'd simply remove the 'work' variable and schedule in an interruptible
way until the dump is done.

BUG() is a bit exagerated imho.

--
Ueimor

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH]: r8169: Expose hardware stats via ethtool
  2005-02-26 14:53 [PATCH]: r8169: Expose hardware stats via ethtool Richard Dawe
  2005-02-26 15:57 ` Jeff Garzik
  2005-02-26 17:32 ` Jon Mason
@ 2005-02-26 18:26 ` Francois Romieu
  2005-02-27 22:44   ` Richard Dawe
  2005-02-27 19:28 ` Jon Mason
  3 siblings, 1 reply; 17+ messages in thread
From: Francois Romieu @ 2005-02-26 18:26 UTC (permalink / raw)
  To: Richard Dawe; +Cc: Jon Mason, netdev, jgarzik

Richard Dawe <rich@phekda.gotadsl.co.uk> :
[...]
> @@ -1531,6 +1620,11 @@ static int rtl8169_open(struct net_devic
>  	if (retval < 0)
>  		goto err_free_rx;
>  
> +	tp->nic_stats = pci_alloc_consistent(pdev, R8169_STATS_BYTES,
> +					     &tp->nic_stats_addr);
> +	if (!tp->nic_stats)
> +		goto err_free_nic_stats;
> +
>  	INIT_WORK(&tp->task, NULL, dev);
>  
>  	rtl8169_hw_start(dev);
> @@ -1541,6 +1635,10 @@ static int rtl8169_open(struct net_devic
>  out:
>  	return retval;
>  
> +err_free_nic_stats:
> +	pci_free_consistent(pdev, R8169_STATS_BYTES, tp->nic_stats,
> +			    tp->nic_stats_addr);
> +

You don't want to free it it was not allocated. Please undo the previous
step (init_ring probably) and:
1) use the form "goto err_descriptive_name_for_the_release_work";
2) if you feel it does not protect against wrong ordering as:
   if (...)
 	goto err_foo;
   if (...)
	goto err_bar;
   [...]
   err_foo:
	...
   err_bar:
	...
   then add extra numbering:
   if (...)
	goto err_foo_0;
   if (...)
	goto err_bar_1;
   [...]
   err_bar_1:
	...
   err_foo_0:
	...
   It is not perfect but it is error proof (something the "goto err_1"
   way alone can not claim btw).

--
Ueimor

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH]: r8169: Expose hardware stats via ethtool
  2005-02-26 18:02   ` Jeff Garzik
  2005-02-26 18:03     ` Jeff Garzik
  2005-02-26 18:12     ` Francois Romieu
@ 2005-02-26 18:36     ` Jon Mason
  2 siblings, 0 replies; 17+ messages in thread
From: Jon Mason @ 2005-02-26 18:36 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: Richard Dawe, Francois Romieu, netdev

On Saturday 26 February 2005 12:02 pm, Jeff Garzik wrote:
[...]
> > @@ -255,6 +258,9 @@ enum RTL8169_register_content {
> >         Cfg9346_Lock = 0x00,
> >         Cfg9346_Unlock = 0xC0,
> >  
> > +       /* StatsAddr register */
> > +       DumpStats = (1 << 3),
> > +
> > 
> > Wouldn't this be better as "0x08"?  Also, RTL8169_register_content could 
> > do with a bit of tidying (values are expressed in decimal and hex, some 
> > are aligned and others not, etc).  I'll try and come-up with a patch here 
> > in a bit.   
> 
> The form "(1 << n)" is preferred, since that form makes plain the bit 
> number, with zero neural transformation required.
> 
> Use the more readable form.  Cleanup patches accepted.

My suggestion was based on code uniformity (as the rest of the values are 
defined as dex or decimal numbers).  Which takes presidense, uniformity or 
readablity?  If it is the latter, should the rest of thse values be redefined?

> 
> >         /* rx_mode_bits */
> >         AcceptErr = 0x20,
> >         AcceptRunt = 0x10,
> > @@ -380,6 +386,22 @@ struct ring_info {
> >         u8              __pad[sizeof(void *) - sizeof(u32)];
> >  };
> >  
> > +struct rtl8169_stats {
> > +       u64 tx_ok;
> > +       u64 rx_ok;
> > +       u64 tx_err;
> > +       u32 rx_err;
> > +       u16 rx_fifo;
> > +       u16 frame_align;
> > +       u32 tx_ok_1col;
> > +       u32 tx_ok_mcol;
> > +       u64 rx_ok_phys;
> > +       u64 rx_ok_bcast;
> > +       u32 rx_ok_mcast;
> > +       u16 tx_abort;
> > +       u16 tx_underrun;
> > +} __attribute__((packed));
> > +
> > 
> > 
> > These could all be u64's.  It would take-up more memory (and a bit more code in the register dump), but the values would be more accurate.  Just an idea.
> 
> No, this is the representation of the hardware DMA structure.
> 
> It is defined by the hardware, not the programmer.

Sorry, didn't see that on the first pass.  My apologies.
 
Jon

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH]: r8169: Expose hardware stats via ethtool
  2005-02-26 14:53 [PATCH]: r8169: Expose hardware stats via ethtool Richard Dawe
                   ` (2 preceding siblings ...)
  2005-02-26 18:26 ` Francois Romieu
@ 2005-02-27 19:28 ` Jon Mason
  3 siblings, 0 replies; 17+ messages in thread
From: Jon Mason @ 2005-02-27 19:28 UTC (permalink / raw)
  To: Richard Dawe; +Cc: Francois Romieu, netdev

On Saturday 26 February 2005 08:53 am, Richard Dawe wrote:
> Hi Francois and Jon!
> 
> Please find attached a patch that adds the hardware statistics ethtool 
> operations to the r8169 driver. It's against 2.6.11-rc5.

I tested it on my amd64 system and it works great.  

I saw the same error if stats were gathered with the interface was down.  As 
a sanity check, I preformed the same test on e1000 and it does not have this 
error.  Not sure the significance of that.

Thanks Richard!

Jon

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH]: r8169: Expose hardware stats via ethtool
  2005-02-26 18:26 ` Francois Romieu
@ 2005-02-27 22:44   ` Richard Dawe
  0 siblings, 0 replies; 17+ messages in thread
From: Richard Dawe @ 2005-02-27 22:44 UTC (permalink / raw)
  To: Francois Romieu; +Cc: Jon Mason, netdev, jgarzik

Hello.

Francois Romieu wrote:
> Richard Dawe <rich@phekda.gotadsl.co.uk> :
> [...]
> 
>>@@ -1531,6 +1620,11 @@ static int rtl8169_open(struct net_devic
>> 	if (retval < 0)
>> 		goto err_free_rx;
>> 
>>+	tp->nic_stats = pci_alloc_consistent(pdev, R8169_STATS_BYTES,
>>+					     &tp->nic_stats_addr);
>>+	if (!tp->nic_stats)
>>+		goto err_free_nic_stats;
>>+
>> 	INIT_WORK(&tp->task, NULL, dev);
>> 
>> 	rtl8169_hw_start(dev);
>>@@ -1541,6 +1635,10 @@ static int rtl8169_open(struct net_devic
>> out:
>> 	return retval;
>> 
>>+err_free_nic_stats:
>>+	pci_free_consistent(pdev, R8169_STATS_BYTES, tp->nic_stats,
>>+			    tp->nic_stats_addr);
>>+
> 
> 
> You don't want to free it it was not allocated. Please undo the previous
> step (init_ring probably) and:
[snip]

Oops, thanks for spotting that. I'll fix it for the next revision of the 
patch.

Thanks, bye, Rich =]

-- 
Richard Dawe [ http://homepages.nildram.co.uk/~phekda/richdawe/ ]

"You can't evaluate a man by logic alone."
   -- McCoy, "I, Mudd", Star Trek

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH]: r8169: Expose hardware stats via ethtool
  2005-02-26 15:57 ` Jeff Garzik
@ 2005-02-27 22:46   ` Richard Dawe
  0 siblings, 0 replies; 17+ messages in thread
From: Richard Dawe @ 2005-02-27 22:46 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: Francois Romieu, Jon Mason, netdev

Hello.

Jeff Garzik wrote:
> Richard Dawe wrote:
[snip]
>> +static const char rtl8169_gstrings_stats[][ETH_GSTRING_LEN] = {
>> +    "tx_ok", "rx_ok", "tx_err", "rx_err",
>> +    "rx_fifo", "frame_align", "tx_ok_1col", "tx_ok_mcol",
>> +    "rx_ok_phys", "rx_ok_bcast", "rx_ok_mcast", "tx_abort",
>> +    "tx_underrun",
>> +};
> 
> 
> Don't needlessly reformat copied code.  It's one-string-per-line 
> intentionally, for ease of maintenance and ease of adding new strings.

OK, I'll fix that.

> Also, I don't see why you renamed this from ethtool_stats_keys[].

I didn't copy it directly. I started off with something that looked like 
the ethtool stats code from the e100 driver. Then I noticed that 8139cp 
did the right thing for r8169.

I'll rename it.

>> +    /* begin NIC statistics dump */
>> +    RTL_W32(StatsAddrHigh, tp->nic_stats_addr >> 32);
>> +    RTL_W32(StatsAddrLow, (tp->nic_stats_addr & 0xffffffff) | 
>> DumpStats);
>> +    RTL_R32(StatsAddrLow);
> 
> 
> This last RTL_R32() can be removed [from 8139cp too], because a flush 
> immediately follows anyway:
[snip]

OK, will do.

Thanks, bye, Rich =]

-- 
Richard Dawe [ http://homepages.nildram.co.uk/~phekda/richdawe/ ]

"You can't evaluate a man by logic alone."
   -- McCoy, "I, Mudd", Star Trek

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH]: r8169: Expose hardware stats via ethtool
  2005-02-26 18:12     ` Francois Romieu
@ 2005-02-27 22:53       ` Richard Dawe
  2005-02-27 22:59         ` Jeff Garzik
  2005-02-28  2:31         ` Jon Mason
  0 siblings, 2 replies; 17+ messages in thread
From: Richard Dawe @ 2005-02-27 22:53 UTC (permalink / raw)
  To: Francois Romieu; +Cc: Jeff Garzik, Jon Mason, netdev

Hello.

Thanks for reviewing, Francois, Jon & Jeff!

Francois Romieu wrote:
[snip]
> Btw I'd simply remove the 'work' variable and schedule in an interruptible
> way until the dump is done.

OK, that will take me a bit longer to code. ;)

> BUG() is a bit exagerated imho.

It seems like a pretty good way of avoiding a buffer overrun to me. 
E.g.: you copy an extra statistic in rtl8169_get_ethtool_stats(), but 
forget to update the stats length. Is it not better to crash early, than 
encounter random behaviour later?

I can put an #ifdef RTL8169_DEBUG / #endif around it, if you'd be happier.

Thanks, bye, Rich =]

-- 
Richard Dawe [ http://homepages.nildram.co.uk/~phekda/richdawe/ ]

"You can't evaluate a man by logic alone."
   -- McCoy, "I, Mudd", Star Trek

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH]: r8169: Expose hardware stats via ethtool
  2005-02-27 22:53       ` Richard Dawe
@ 2005-02-27 22:59         ` Jeff Garzik
  2005-02-28  2:31         ` Jon Mason
  1 sibling, 0 replies; 17+ messages in thread
From: Jeff Garzik @ 2005-02-27 22:59 UTC (permalink / raw)
  To: Richard Dawe; +Cc: Francois Romieu, Jon Mason, netdev

Richard Dawe wrote:
>> BUG() is a bit exagerated imho.
> 
> 
> It seems like a pretty good way of avoiding a buffer overrun to me. 
> E.g.: you copy an extra statistic in rtl8169_get_ethtool_stats(), but 
> forget to update the stats length. Is it not better to crash early, than 
> encounter random behaviour later?


Yeah, that's why the BUG() is present in 8139cp:  force an oops rather 
than continue corrupting memory, if the programmer made an error.

	Jeff

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH]: r8169: Expose hardware stats via ethtool
  2005-02-27 22:53       ` Richard Dawe
  2005-02-27 22:59         ` Jeff Garzik
@ 2005-02-28  2:31         ` Jon Mason
  2005-02-28  2:58           ` Jeff Garzik
  1 sibling, 1 reply; 17+ messages in thread
From: Jon Mason @ 2005-02-28  2:31 UTC (permalink / raw)
  To: Richard Dawe; +Cc: Francois Romieu, netdev

I think I've found a (very hackish) way around the bad stats error.  

Tested on amd64, and "solves" the problem.

--- drivers/net/r8169.c 2005-02-27 20:27:48.000000000 -0600
+++ drivers/net/r8169.c.new     2005-02-27 20:29:29.000000000 -0600
@@ -929,8 +929,13 @@ static void rtl8169_get_ethtool_stats(st
                cpu_relax();
        }

-       if (RTL_R32(StatsAddrLow) & DumpStats)
+       if (RTL_R32(StatsAddrLow) & DumpStats) {
+               if (!netif_running(netdev)) {
+                       for (i = 0; i < 14; i++)
+                               data[i] = 0;
+               }
                return; /* no stats - took too long */
+       }

        i = 0;
        data[i++] = le64_to_cpu(tp->nic_stats->tx_ok);

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH]: r8169: Expose hardware stats via ethtool
  2005-02-28  2:31         ` Jon Mason
@ 2005-02-28  2:58           ` Jeff Garzik
  2005-02-28  4:16             ` Ben Greear
  0 siblings, 1 reply; 17+ messages in thread
From: Jeff Garzik @ 2005-02-28  2:58 UTC (permalink / raw)
  To: Jon Mason; +Cc: Richard Dawe, Francois Romieu, netdev

Jon Mason wrote:
> I think I've found a (very hackish) way around the bad stats error.  
> 
> Tested on amd64, and "solves" the problem.

Seems to me, we should instead find a way to avoid calling the stats 
function if !netif_running()

	Jeff

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH]: r8169: Expose hardware stats via ethtool
  2005-02-28  2:58           ` Jeff Garzik
@ 2005-02-28  4:16             ` Ben Greear
  2005-03-05 13:53               ` Richard Dawe
  0 siblings, 1 reply; 17+ messages in thread
From: Ben Greear @ 2005-02-28  4:16 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: Jon Mason, Richard Dawe, Francois Romieu, netdev

Jeff Garzik wrote:
> Jon Mason wrote:
> 
>> I think I've found a (very hackish) way around the bad stats error. 
>> Tested on amd64, and "solves" the problem.
> 
> 
> Seems to me, we should instead find a way to avoid calling the stats 
> function if !netif_running()

Are the stats valid in the hardware if you start it, stop it, and then read them?

Ben

-- 
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc  http://www.candelatech.com

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH]: r8169: Expose hardware stats via ethtool
  2005-02-28  4:16             ` Ben Greear
@ 2005-03-05 13:53               ` Richard Dawe
  0 siblings, 0 replies; 17+ messages in thread
From: Richard Dawe @ 2005-03-05 13:53 UTC (permalink / raw)
  To: Ben Greear; +Cc: Jeff Garzik, Jon Mason, Francois Romieu, netdev

Hello.

Ben Greear wrote:
> Jeff Garzik wrote:
> 
>> Jon Mason wrote:
>>
>>> I think I've found a (very hackish) way around the bad stats error. 
>>> Tested on amd64, and "solves" the problem.
>>
>>
>>
>> Seems to me, we should instead find a way to avoid calling the stats 
>> function if !netif_running()
> 
> 
> Are the stats valid in the hardware if you start it, stop it, and then 
> read them?

They don't seem to be. I get the same kind of garbage before starting as 
  I do after I've started and stopped it.

Bye, Rich =]

-- 
Richard Dawe [ http://homepages.nildram.co.uk/~phekda/richdawe/ ]

"You can't evaluate a man by logic alone."
   -- McCoy, "I, Mudd", Star Trek

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2005-03-05 13:53 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-02-26 14:53 [PATCH]: r8169: Expose hardware stats via ethtool Richard Dawe
2005-02-26 15:57 ` Jeff Garzik
2005-02-27 22:46   ` Richard Dawe
2005-02-26 17:32 ` Jon Mason
2005-02-26 18:02   ` Jeff Garzik
2005-02-26 18:03     ` Jeff Garzik
2005-02-26 18:12     ` Francois Romieu
2005-02-27 22:53       ` Richard Dawe
2005-02-27 22:59         ` Jeff Garzik
2005-02-28  2:31         ` Jon Mason
2005-02-28  2:58           ` Jeff Garzik
2005-02-28  4:16             ` Ben Greear
2005-03-05 13:53               ` Richard Dawe
2005-02-26 18:36     ` Jon Mason
2005-02-26 18:26 ` Francois Romieu
2005-02-27 22:44   ` Richard Dawe
2005-02-27 19:28 ` Jon Mason

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).