ramoops: move dump_oops into platform data
[linux-2.6.git] / drivers / net / ns83820.c
index 940962a..e736aec 100644 (file)
 #include <linux/delay.h>
 #include <linux/workqueue.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/ip.h>  /* for iph */
 #include <linux/in.h>  /* for IPPROTO_... */
 #include <linux/compiler.h>
 #include <linux/prefetch.h>
 #include <linux/ethtool.h>
+#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/if_vlan.h>
 #include <linux/rtnetlink.h>
 #include <linux/jiffies.h>
+#include <linux/slab.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
@@ -422,16 +425,11 @@ struct rx_info {
 
 
 struct ns83820 {
-       struct net_device_stats stats;
        u8                      __iomem *base;
 
        struct pci_dev          *pci_dev;
        struct net_device       *ndev;
 
-#ifdef NS83820_VLAN_ACCEL_SUPPORT
-       struct vlan_group       *vlgrp;
-#endif
-
        struct rx_info          rx_info;
        struct tasklet_struct   rx_tasklet;
 
@@ -492,26 +490,10 @@ static inline void kick_rx(struct net_device *ndev)
 #define start_tx_okay(dev)     \
        (((NR_TX_DESC-2 + dev->tx_done_idx - dev->tx_free_idx) % NR_TX_DESC) > MIN_TX_DESC_FREE)
 
-
-#ifdef NS83820_VLAN_ACCEL_SUPPORT
-static void ns83820_vlan_rx_register(struct net_device *ndev, struct vlan_group *grp)
-{
-       struct ns83820 *dev = PRIV(ndev);
-
-       spin_lock_irq(&dev->misc_lock);
-       spin_lock(&dev->tx_lock);
-
-       dev->vlgrp = grp;
-
-       spin_unlock(&dev->tx_lock);
-       spin_unlock_irq(&dev->misc_lock);
-}
-#endif
-
 /* Packet Receiver
  *
  * The hardware supports linked lists of receive descriptors for
- * which ownership is transfered back and forth by means of an
+ * which ownership is transferred back and forth by means of an
  * ownership bit.  While the hardware does support the use of a
  * ring for receive descriptors, we only make use of a chain in
  * an attempt to reduce bus traffic under heavy load scenarios.
@@ -647,8 +629,8 @@ static void phy_intr(struct net_device *ndev)
                dprintk("phy_intr: tbisr=%08x, tanar=%08x, tanlpar=%08x\n",
                        tbisr, tanar, tanlpar);
 
-               if ( (fullduplex = (tanlpar & TANAR_FULL_DUP)
-                     && (tanar & TANAR_FULL_DUP)) ) {
+               if ( (fullduplex = (tanlpar & TANAR_FULL_DUP) &&
+                     (tanar & TANAR_FULL_DUP)) ) {
 
                        /* both of us are full duplex */
                        writel(readl(dev->base + TXCFG)
@@ -660,12 +642,12 @@ static void phy_intr(struct net_device *ndev)
                        writel(readl(dev->base + GPIOR) | GPIOR_GP1_OUT,
                               dev->base + GPIOR);
 
-               } else if(((tanlpar & TANAR_HALF_DUP)
-                          && (tanar & TANAR_HALF_DUP))
-                       || ((tanlpar & TANAR_FULL_DUP)
-                           && (tanar & TANAR_HALF_DUP))
-                       || ((tanlpar & TANAR_HALF_DUP)
-                           && (tanar & TANAR_FULL_DUP))) {
+               } else if (((tanlpar & TANAR_HALF_DUP) &&
+                           (tanar & TANAR_HALF_DUP)) ||
+                          ((tanlpar & TANAR_FULL_DUP) &&
+                           (tanar & TANAR_HALF_DUP)) ||
+                          ((tanlpar & TANAR_HALF_DUP) &&
+                           (tanar & TANAR_FULL_DUP))) {
 
                        /* one or both of us are half duplex */
                        writel((readl(dev->base + TXCFG)
@@ -719,16 +701,16 @@ static void phy_intr(struct net_device *ndev)
 
        newlinkstate = (cfg & CFG_LNKSTS) ? LINK_UP : LINK_DOWN;
 
-       if (newlinkstate & LINK_UP
-           && dev->linkstate != newlinkstate) {
+       if (newlinkstate & LINK_UP &&
+           dev->linkstate != newlinkstate) {
                netif_start_queue(ndev);
                netif_wake_queue(ndev);
                printk(KERN_INFO "%s: link now %s mbps, %s duplex and up.\n",
                        ndev->name,
                        speeds[speed],
                        fullduplex ? "full" : "half");
-       } else if (newlinkstate & LINK_DOWN
-                  && dev->linkstate != newlinkstate) {
+       } else if (newlinkstate & LINK_DOWN &&
+                  dev->linkstate != newlinkstate) {
                netif_stop_queue(ndev);
                printk(KERN_INFO "%s: link now down.\n", ndev->name);
        }
@@ -771,7 +753,7 @@ static int ns83820_setup_rx(struct net_device *ndev)
                phy_intr(ndev);
 
                /* Okay, let it rip */
-               spin_lock_irq(&dev->misc_lock);
+               spin_lock(&dev->misc_lock);
                dev->IMR_cache |= ISR_PHY;
                dev->IMR_cache |= ISR_RXRCMP;
                //dev->IMR_cache |= ISR_RXERR;
@@ -916,29 +898,27 @@ static void rx_irq(struct net_device *ndev)
                        if (unlikely(!skb))
                                goto netdev_mangle_me_harder_failed;
                        if (cmdsts & CMDSTS_DEST_MULTI)
-                               dev->stats.multicast ++;
-                       dev->stats.rx_packets ++;
-                       dev->stats.rx_bytes += len;
+                               ndev->stats.multicast++;
+                       ndev->stats.rx_packets++;
+                       ndev->stats.rx_bytes += len;
                        if ((extsts & 0x002a0000) && !(extsts & 0x00540000)) {
                                skb->ip_summed = CHECKSUM_UNNECESSARY;
                        } else {
-                               skb->ip_summed = CHECKSUM_NONE;
+                               skb_checksum_none_assert(skb);
                        }
                        skb->protocol = eth_type_trans(skb, ndev);
 #ifdef NS83820_VLAN_ACCEL_SUPPORT
                        if(extsts & EXTSTS_VPKT) {
                                unsigned short tag;
+
                                tag = ntohs(extsts & EXTSTS_VTG_MASK);
-                               rx_rc = vlan_hwaccel_rx(skb,dev->vlgrp,tag);
-                       } else {
-                               rx_rc = netif_rx(skb);
+                               __vlan_hwaccel_put_tag(skb, tag);
                        }
-#else
-                       rx_rc = netif_rx(skb);
 #endif
+                       rx_rc = netif_rx(skb);
                        if (NET_RX_DROP == rx_rc) {
 netdev_mangle_me_harder_failed:
-                               dev->stats.rx_dropped ++;
+                               ndev->stats.rx_dropped++;
                        }
                } else {
                        kfree_skb(skb);
@@ -1006,11 +986,11 @@ static void do_tx_done(struct net_device *ndev)
                dma_addr_t addr;
 
                if (cmdsts & CMDSTS_ERR)
-                       dev->stats.tx_errors ++;
+                       ndev->stats.tx_errors++;
                if (cmdsts & CMDSTS_OK)
-                       dev->stats.tx_packets ++;
+                       ndev->stats.tx_packets++;
                if (cmdsts & CMDSTS_OK)
-                       dev->stats.tx_bytes += cmdsts & 0xffff;
+                       ndev->stats.tx_bytes += cmdsts & 0xffff;
 
                dprintk("tx_done_idx=%d free_idx=%d cmdsts=%08x\n",
                        tx_done_idx, dev->tx_free_idx, cmdsts);
@@ -1077,7 +1057,8 @@ static void ns83820_cleanup_tx(struct ns83820 *dev)
  * while trying to track down a bug in either the zero copy code or
  * the tx fifo (hence the MAX_FRAG_LEN).
  */
-static int ns83820_hard_start_xmit(struct sk_buff *skb, struct net_device *ndev)
+static netdev_tx_t ns83820_hard_start_xmit(struct sk_buff *skb,
+                                          struct net_device *ndev)
 {
        struct ns83820 *dev = PRIV(ndev);
        u32 free_idx, cmdsts, extsts;
@@ -1097,7 +1078,7 @@ again:
        if (unlikely(dev->CFG_cache & CFG_LNKSTS)) {
                netif_stop_queue(ndev);
                if (unlikely(dev->CFG_cache & CFG_LNKSTS))
-                       return 1;
+                       return NETDEV_TX_BUSY;
                netif_start_queue(ndev);
        }
 
@@ -1115,7 +1096,7 @@ again:
                        netif_start_queue(ndev);
                        goto again;
                }
-               return 1;
+               return NETDEV_TX_BUSY;
        }
 
        if (free_idx == dev->tx_intr_idx) {
@@ -1145,7 +1126,7 @@ again:
 #ifdef NS83820_VLAN_ACCEL_SUPPORT
        if(vlan_tx_tag_present(skb)) {
                /* fetch the vlan tag info out of the
-                * ancilliary data if the vlan code
+                * ancillary data if the vlan code
                 * is using hw vlan acceleration
                 */
                short tag = vlan_tx_tag_get(skb);
@@ -1209,20 +1190,21 @@ again:
 
 static void ns83820_update_stats(struct ns83820 *dev)
 {
+       struct net_device *ndev = dev->ndev;
        u8 __iomem *base = dev->base;
 
        /* the DP83820 will freeze counters, so we need to read all of them */
-       dev->stats.rx_errors            += readl(base + 0x60) & 0xffff;
-       dev->stats.rx_crc_errors        += readl(base + 0x64) & 0xffff;
-       dev->stats.rx_missed_errors     += readl(base + 0x68) & 0xffff;
-       dev->stats.rx_frame_errors      += readl(base + 0x6c) & 0xffff;
-       /*dev->stats.rx_symbol_errors +=*/ readl(base + 0x70);
-       dev->stats.rx_length_errors     += readl(base + 0x74) & 0xffff;
-       dev->stats.rx_length_errors     += readl(base + 0x78) & 0xffff;
-       /*dev->stats.rx_badopcode_errors += */ readl(base + 0x7c);
-       /*dev->stats.rx_pause_count += */  readl(base + 0x80);
-       /*dev->stats.tx_pause_count += */  readl(base + 0x84);
-       dev->stats.tx_carrier_errors    += readl(base + 0x88) & 0xff;
+       ndev->stats.rx_errors           += readl(base + 0x60) & 0xffff;
+       ndev->stats.rx_crc_errors       += readl(base + 0x64) & 0xffff;
+       ndev->stats.rx_missed_errors    += readl(base + 0x68) & 0xffff;
+       ndev->stats.rx_frame_errors     += readl(base + 0x6c) & 0xffff;
+       /*ndev->stats.rx_symbol_errors +=*/ readl(base + 0x70);
+       ndev->stats.rx_length_errors    += readl(base + 0x74) & 0xffff;
+       ndev->stats.rx_length_errors    += readl(base + 0x78) & 0xffff;
+       /*ndev->stats.rx_badopcode_errors += */ readl(base + 0x7c);
+       /*ndev->stats.rx_pause_count += */  readl(base + 0x80);
+       /*ndev->stats.tx_pause_count += */  readl(base + 0x84);
+       ndev->stats.tx_carrier_errors   += readl(base + 0x88) & 0xff;
 }
 
 static struct net_device_stats *ns83820_get_stats(struct net_device *ndev)
@@ -1234,7 +1216,7 @@ static struct net_device_stats *ns83820_get_stats(struct net_device *ndev)
        ns83820_update_stats(dev);
        spin_unlock_irq(&dev->misc_lock);
 
-       return &dev->stats;
+       return &ndev->stats;
 }
 
 /* Let ethtool retrieve info */
@@ -1243,13 +1225,12 @@ static int ns83820_get_settings(struct net_device *ndev,
 {
        struct ns83820 *dev = PRIV(ndev);
        u32 cfg, tanar, tbicr;
-       int have_optical = 0;
        int fullduplex   = 0;
 
        /*
         * Here's the list of available ethtool commands from other drivers:
         *      cmd->advertising =
-        *      cmd->speed =
+        *      ethtool_cmd_speed_set(cmd, ...)
         *      cmd->duplex =
         *      cmd->port = 0;
         *      cmd->phy_address =
@@ -1264,39 +1245,40 @@ static int ns83820_get_settings(struct net_device *ndev,
        tanar = readl(dev->base + TANAR);
        tbicr = readl(dev->base + TBICR);
 
-       if (dev->CFG_cache & CFG_TBI_EN) {
-               /* we have an optical interface */
-               have_optical = 1;
-               fullduplex = (cfg & CFG_DUPSTS) ? 1 : 0;
-
-       } else {
-               /* We have copper */
-               fullduplex = (cfg & CFG_DUPSTS) ? 1 : 0;
-        }
+       fullduplex = (cfg & CFG_DUPSTS) ? 1 : 0;
 
        cmd->supported = SUPPORTED_Autoneg;
 
-       /* we have optical interface */
        if (dev->CFG_cache & CFG_TBI_EN) {
+               /* we have optical interface */
                cmd->supported |= SUPPORTED_1000baseT_Half |
                                        SUPPORTED_1000baseT_Full |
                                        SUPPORTED_FIBRE;
                cmd->port       = PORT_FIBRE;
-       } /* TODO: else copper related  support */
+       } else {
+               /* we have copper */
+               cmd->supported |= SUPPORTED_10baseT_Half |
+                       SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half |
+                       SUPPORTED_100baseT_Full | SUPPORTED_1000baseT_Half |
+                       SUPPORTED_1000baseT_Full |
+                       SUPPORTED_MII;
+               cmd->port = PORT_MII;
+       }
 
        cmd->duplex = fullduplex ? DUPLEX_FULL : DUPLEX_HALF;
        switch (cfg / CFG_SPDSTS0 & 3) {
        case 2:
-               cmd->speed = SPEED_1000;
+               ethtool_cmd_speed_set(cmd, SPEED_1000);
                break;
        case 1:
-               cmd->speed = SPEED_100;
+               ethtool_cmd_speed_set(cmd, SPEED_100);
                break;
        default:
-               cmd->speed = SPEED_10;
+               ethtool_cmd_speed_set(cmd, SPEED_10);
                break;
        }
-       cmd->autoneg = (tbicr & TBICR_MR_AN_ENABLE) ? 1: 0;
+       cmd->autoneg = (tbicr & TBICR_MR_AN_ENABLE)
+               ? AUTONEG_ENABLE : AUTONEG_DISABLE;
        return 0;
 }
 
@@ -1402,6 +1384,13 @@ static const struct ethtool_ops ops = {
        .get_link        = ns83820_get_link
 };
 
+static inline void ns83820_disable_interrupts(struct ns83820 *dev)
+{
+       writel(0, dev->base + IMR);
+       writel(0, dev->base + IER);
+       readl(dev->base + IER);
+}
+
 /* this function is called in irq context from the ISR */
 static void ns83820_mib_isr(struct ns83820 *dev)
 {
@@ -1461,12 +1450,12 @@ static void ns83820_do_isr(struct net_device *ndev, u32 isr)
 
        if (unlikely(ISR_RXSOVR & isr)) {
                //printk("overrun: rxsovr\n");
-               dev->stats.rx_fifo_errors ++;
+               ndev->stats.rx_fifo_errors++;
        }
 
        if (unlikely(ISR_RXORN & isr)) {
                //printk("overrun: rxorn\n");
-               dev->stats.rx_fifo_errors ++;
+               ndev->stats.rx_fifo_errors++;
        }
 
        if ((ISR_RXRCMP & isr) && dev->rx_info.up)
@@ -1554,10 +1543,7 @@ static int ns83820_stop(struct net_device *ndev)
        /* FIXME: protect against interrupt handler? */
        del_timer_sync(&dev->tx_watchdog);
 
-       /* disable interrupts */
-       writel(0, dev->base + IMR);
-       writel(0, dev->base + IER);
-       readl(dev->base + IER);
+       ns83820_disable_interrupts(dev);
 
        dev->rx_info.up = 0;
        synchronize_irq(dev->pci_dev->irq);
@@ -1717,7 +1703,7 @@ static void ns83820_set_multicast(struct net_device *ndev)
        else
                and_mask &= ~(RFCR_AAU | RFCR_AAM);
 
-       if (ndev->flags & IFF_ALLMULTI || ndev->mc_count)
+       if (ndev->flags & IFF_ALLMULTI || netdev_mc_count(ndev))
                or_mask |= RFCR_AAM;
        else
                and_mask &= ~RFCR_AAM;
@@ -1953,11 +1939,8 @@ static const struct net_device_ops netdev_ops = {
        .ndo_change_mtu         = ns83820_change_mtu,
        .ndo_set_multicast_list = ns83820_set_multicast,
        .ndo_validate_addr      = eth_validate_addr,
-       .ndo_set_mac_address    = eth_mac_addr,
+       .ndo_set_mac_address    = eth_mac_addr,
        .ndo_tx_timeout         = ns83820_tx_timeout,
-#ifdef NS83820_VLAN_ACCEL_SUPPORT
-       .ndo_vlan_rx_register   = ns83820_vlan_rx_register,
-#endif
 };
 
 static int __devinit ns83820_init_one(struct pci_dev *pci_dev,
@@ -1981,12 +1964,11 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev,
        }
 
        ndev = alloc_etherdev(sizeof(struct ns83820));
-       dev = PRIV(ndev);
-
        err = -ENOMEM;
-       if (!dev)
+       if (!ndev)
                goto out;
 
+       dev = PRIV(ndev);
        dev->ndev = ndev;
 
        spin_lock_init(&dev->rx_info.lock);
@@ -2020,10 +2002,7 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev,
                dev->tx_descs, (long)dev->tx_phy_descs,
                dev->rx_info.descs, (long)dev->rx_info.phy_descs);
 
-       /* disable interrupts */
-       writel(0, dev->base + IMR);
-       writel(0, dev->base + IER);
-       readl(dev->base + IER);
+       ns83820_disable_interrupts(dev);
 
        dev->IMR_cache = 0;
 
@@ -2247,9 +2226,7 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev,
        return 0;
 
 out_cleanup:
-       writel(0, dev->base + IMR);     /* paranoia */
-       writel(0, dev->base + IER);
-       readl(dev->base + IER);
+       ns83820_disable_interrupts(dev); /* paranoia */
 out_free_irq:
        rtnl_unlock();
        free_irq(pci_dev->irq, ndev);
@@ -2274,9 +2251,7 @@ static void __devexit ns83820_remove_one(struct pci_dev *pci_dev)
        if (!ndev)                      /* paranoia */
                return;
 
-       writel(0, dev->base + IMR);     /* paranoia */
-       writel(0, dev->base + IER);
-       readl(dev->base + IER);
+       ns83820_disable_interrupts(dev); /* paranoia */
 
        unregister_netdev(ndev);
        free_irq(dev->pci_dev->irq, ndev);
@@ -2290,7 +2265,7 @@ static void __devexit ns83820_remove_one(struct pci_dev *pci_dev)
        pci_set_drvdata(pci_dev, NULL);
 }
 
-static struct pci_device_id ns83820_pci_tbl[] = {
+static DEFINE_PCI_DEVICE_TABLE(ns83820_pci_tbl) = {
        { 0x100b, 0x0022, PCI_ANY_ID, PCI_ANY_ID, 0, .driver_data = 0, },
        { 0, },
 };