bnx2: Fix problem of using wrong IRQ handler.
[safe/jmp/linux-2.6] / drivers / net / sis190.c
index 20f4829..a973268 100644 (file)
@@ -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,
@@ -311,6 +317,7 @@ static struct mii_chip_info {
         unsigned int type;
        u32 feature;
 } mii_chip_table[] = {
+       { "Atheros PHY AR8012",   { 0x004d, 0xd020 }, LAN, 0 },
        { "Broadcom PHY BCM5461", { 0x0020, 0x60c0 }, LAN, F_PHY_BCM5461 },
        { "Broadcom PHY AC131",   { 0x0143, 0xbc70 }, LAN, 0 },
        { "Agere PHY ET1101B",    { 0x0282, 0xf010 }, LAN, 0 },
@@ -620,7 +627,6 @@ static int sis190_rx_interrupt(struct net_device *dev,
 
                        sis190_rx_skb(skb);
 
-                       dev->last_rx = jiffies;
                        stats->rx_packets++;
                        stats->rx_bytes += pkt_size;
                        if ((status & BCAST) == MCAST)
@@ -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;
@@ -1624,7 +1656,7 @@ static inline void sis190_init_rxfilter(struct net_device *dev)
        SIS_PCI_COMMIT();
 }
 
-static int __devinit sis190_get_mac_addr(struct pci_dev *pdev, 
+static int __devinit sis190_get_mac_addr(struct pci_dev *pdev,
                                         struct net_device *dev)
 {
        int rc;
@@ -1750,6 +1782,21 @@ static int sis190_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
                generic_mii_ioctl(&tp->mii_if, if_mii(ifr), cmd, NULL);
 }
 
+static const struct net_device_ops sis190_netdev_ops = {
+       .ndo_open               = sis190_open,
+       .ndo_stop               = sis190_close,
+       .ndo_do_ioctl           = sis190_ioctl,
+       .ndo_start_xmit         = sis190_start_xmit,
+       .ndo_tx_timeout         = sis190_tx_timeout,
+       .ndo_set_multicast_list = sis190_set_rx_mode,
+       .ndo_change_mtu         = eth_change_mtu,
+       .ndo_set_mac_address    = eth_mac_addr,
+       .ndo_validate_addr      = eth_validate_addr,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       .ndo_poll_controller     = sis190_netpoll,
+#endif
+};
+
 static int __devinit sis190_init_one(struct pci_dev *pdev,
                                     const struct pci_device_id *ent)
 {
@@ -1758,7 +1805,6 @@ static int __devinit sis190_init_one(struct pci_dev *pdev,
        struct net_device *dev;
        void __iomem *ioaddr;
        int rc;
-       DECLARE_MAC_BUF(mac);
 
        if (!printed_version) {
                net_drv(&debug, KERN_INFO SIS190_DRIVER_NAME " loaded.\n");
@@ -1784,19 +1830,12 @@ static int __devinit sis190_init_one(struct pci_dev *pdev,
 
        INIT_WORK(&tp->phy_task, sis190_phy_task);
 
-       dev->open = sis190_open;
-       dev->stop = sis190_close;
-       dev->do_ioctl = sis190_ioctl;
-       dev->tx_timeout = sis190_tx_timeout;
-       dev->watchdog_timeo = SIS190_TX_TIMEOUT;
-       dev->hard_start_xmit = sis190_start_xmit;
-#ifdef CONFIG_NET_POLL_CONTROLLER
-       dev->poll_controller = sis190_netpoll;
-#endif
-       dev->set_multicast_list = sis190_set_rx_mode;
+       dev->netdev_ops = &sis190_netdev_ops;
+
        SET_ETHTOOL_OPS(dev, &sis190_ethtool_ops);
        dev->irq = pdev->irq;
        dev->base_addr = (unsigned long) 0xdead;
+       dev->watchdog_timeo = SIS190_TX_TIMEOUT;
 
        spin_lock_init(&tp->lock);
 
@@ -1808,10 +1847,9 @@ static int __devinit sis190_init_one(struct pci_dev *pdev,
        if (rc < 0)
                goto err_remove_mii;
 
-       net_probe(tp, KERN_INFO "%s: %s at %p (IRQ: %d), "
-                 "%s\n",
+       net_probe(tp, KERN_INFO "%s: %s at %p (IRQ: %d), %pM\n",
                  pci_name(pdev), sis_chip_info[ent->driver_data].name,
-                 ioaddr, dev->irq, print_mac(mac, dev->dev_addr));
+                 ioaddr, dev->irq, dev->dev_addr);
 
        net_probe(tp, KERN_INFO "%s: %s mode.\n", dev->name,
                  (tp->features & F_HAS_RGMII) ? "RGMII" : "GMII");