X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fnet%2Fsis190.c;h=abc63b0663be9ec83854da1a5b79feeefe6d4e66;hb=63f5abb0959337db0d5bece9cefba03cdcadec51;hp=0b22e75633a29e86b1e2910d0ed95c1b19f589a1;hpb=47e4781544aaf2916170ef5516786fbb19447600;p=linux-2.6-omap-h63xx.git diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c index 0b22e75633a..abc63b0663b 100644 --- a/drivers/net/sis190.c +++ b/drivers/net/sis190.c @@ -212,6 +212,12 @@ enum _DescStatusBit { THOL2 = 0x20000000, THOL1 = 0x10000000, THOL0 = 0x00000000, + + WND = 0x00080000, + TABRT = 0x00040000, + FIFO = 0x00020000, + LINK = 0x00010000, + ColCountMask = 0x0000ffff, /* RxDesc.status */ IPON = 0x20000000, TCPON = 0x10000000, @@ -653,9 +659,31 @@ static void sis190_unmap_tx_skb(struct pci_dev *pdev, struct sk_buff *skb, memset(desc, 0x00, sizeof(*desc)); } +static inline int sis190_tx_pkt_err(u32 status, struct net_device_stats *stats) +{ +#define TxErrMask (WND | TABRT | FIFO | LINK) + + if (!unlikely(status & TxErrMask)) + return 0; + + if (status & WND) + stats->tx_window_errors++; + if (status & TABRT) + stats->tx_aborted_errors++; + if (status & FIFO) + stats->tx_fifo_errors++; + if (status & LINK) + stats->tx_carrier_errors++; + + stats->tx_errors++; + + return -1; +} + static void sis190_tx_interrupt(struct net_device *dev, struct sis190_private *tp, void __iomem *ioaddr) { + struct net_device_stats *stats = &dev->stats; u32 pending, dirty_tx = tp->dirty_tx; /* * It would not be needed if queueing was allowed to be enabled @@ -670,15 +698,19 @@ static void sis190_tx_interrupt(struct net_device *dev, for (; pending; pending--, dirty_tx++) { unsigned int entry = dirty_tx % NUM_TX_DESC; struct TxDesc *txd = tp->TxDescRing + entry; + u32 status = le32_to_cpu(txd->status); struct sk_buff *skb; - if (le32_to_cpu(txd->status) & OWNbit) + if (status & OWNbit) break; skb = tp->Tx_skbuff[entry]; - dev->stats.tx_packets++; - dev->stats.tx_bytes += skb->len; + if (likely(sis190_tx_pkt_err(status, stats) == 0)) { + stats->tx_packets++; + stats->tx_bytes += skb->len; + stats->collisions += ((status & ColCountMask) - 1); + } sis190_unmap_tx_skb(tp->pci_dev, skb, txd); tp->Tx_skbuff[entry] = NULL; @@ -899,10 +931,9 @@ static void sis190_phy_task(struct work_struct *work) mod_timer(&tp->timer, jiffies + HZ/10); } else if (!(mdio_read_latched(ioaddr, phy_id, MII_BMSR) & BMSR_ANEGCOMPLETE)) { - net_link(tp, KERN_WARNING "%s: PHY reset until link up.\n", - dev->name); netif_carrier_off(dev); - mdio_write(ioaddr, phy_id, MII_BMCR, val | BMCR_RESET); + net_link(tp, KERN_WARNING "%s: auto-negotiating...\n", + dev->name); mod_timer(&tp->timer, jiffies + SIS190_PHY_TIMEOUT); } else { /* Rejoice ! */