From: Sergei Shtylylov With Au1xx0 Ethernet driver, TX bytes/packets always remain zero. The problem seems to be that when packet has been transmitted, the length word in DMA buffer is zero. The patch updates the TX stats when a buffer is fed to DMA. The initial 2.4 patch was posted to linux-mips@linux-mips.org by Thomas Lange 21 Jan 2005. Signed-off-by: Thomas Lange Signed-off-by: Sergei Shtylyov Cc: Jordan Crouse Cc: Jeff Garzik Signed-off-by: Andrew Morton --- drivers/net/au1000_eth.c | 15 ++++++++------- 1 files changed, 8 insertions(+), 7 deletions(-) diff -puN drivers/net/au1000_eth.c~amd-au1xx0-fix-ethernet-tx-stats drivers/net/au1000_eth.c --- 25/drivers/net/au1000_eth.c~amd-au1xx0-fix-ethernet-tx-stats Wed Mar 15 14:35:53 2006 +++ 25-akpm/drivers/net/au1000_eth.c Wed Mar 15 14:35:53 2006 @@ -90,7 +90,7 @@ static void au1000_tx_timeout(struct net static int au1000_set_config(struct net_device *dev, struct ifmap *map); static void set_rx_mode(struct net_device *); static struct net_device_stats *au1000_get_stats(struct net_device *); -static inline void update_tx_stats(struct net_device *, u32, u32); +static inline void update_tx_stats(struct net_device *, u32); static inline void update_rx_stats(struct net_device *, u32); static void au1000_timer(unsigned long); static int au1000_ioctl(struct net_device *, struct ifreq *, int); @@ -1827,14 +1827,11 @@ static void __exit au1000_cleanup_module static inline void -update_tx_stats(struct net_device *dev, u32 status, u32 pkt_len) +update_tx_stats(struct net_device *dev, u32 status) { struct au1000_private *aup = (struct au1000_private *) dev->priv; struct net_device_stats *ps = &aup->stats; - ps->tx_packets++; - ps->tx_bytes += pkt_len; - if (status & TX_FRAME_ABORTED) { if (dev->if_port == IF_PORT_100BASEFX) { if (status & (TX_JAB_TIMEOUT | TX_UNDERRUN)) { @@ -1867,7 +1864,7 @@ static void au1000_tx_ack(struct net_dev ptxd = aup->tx_dma_ring[aup->tx_tail]; while (ptxd->buff_stat & TX_T_DONE) { - update_tx_stats(dev, ptxd->status, ptxd->len & 0x3ff); + update_tx_stats(dev, ptxd->status); ptxd->buff_stat &= ~TX_T_DONE; ptxd->len = 0; au_sync(); @@ -1889,6 +1886,7 @@ static void au1000_tx_ack(struct net_dev static int au1000_tx(struct sk_buff *skb, struct net_device *dev) { struct au1000_private *aup = (struct au1000_private *) dev->priv; + struct net_device_stats *ps = &aup->stats; volatile tx_dma_t *ptxd; u32 buff_stat; db_dest_t *pDB; @@ -1908,7 +1906,7 @@ static int au1000_tx(struct sk_buff *skb return 1; } else if (buff_stat & TX_T_DONE) { - update_tx_stats(dev, ptxd->status, ptxd->len & 0x3ff); + update_tx_stats(dev, ptxd->status); ptxd->len = 0; } @@ -1928,6 +1926,9 @@ static int au1000_tx(struct sk_buff *skb else ptxd->len = skb->len; + ps->tx_packets++; + ps->tx_bytes += ptxd->len; + ptxd->buff_stat = pDB->dma_addr | TX_DMA_ENABLE; au_sync(); dev_kfree_skb(skb); _