[PATCH] AMD Au1xx0: fix Ethernet TX stats

From: Sergei Shtylylov
Date: Tue Mar 14 2006 - 13:53:43 EST


Hello.

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.
Attached is a patch that updates the TX stats when a buffer is fed to DMA.
The initial 2.4 patch was posted to linux-mips@xxxxxxxxxxxxxx by Thomas Lange 21 Jan 2005.

WBR, Sergei

PS: I'm not reading linux-net@xxxxxxxxxxxxxxx, so please CC me when replying.

Signed-off-by: Thomas Lange <thomas@xxxxxxxxxxxx>
Signed-off-by: Sergei Shtylyov <sshtylyov@xxxxxxxxxxxxx>

diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c
index cd0b1dc..a4df316 100644
--- a/drivers/net/au1000_eth.c
+++ b/drivers/net/au1000_eth.c
@@ -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);