veth: prevent oops caused by netdev destructor
[safe/jmp/linux-2.6] / drivers / net / 3c509.c
index 54dac06..fbb3719 100644 (file)
@@ -40,7 +40,7 @@
                v1.14 10/15/97 Avoided waiting..discard message for fast machines -djb
                v1.15 1/31/98 Faster recovery for Tx errors. -djb
                v1.16 2/3/98 Different ID port handling to avoid sound cards. -djb
-               v1.18 12Mar2001 Andrew Morton <andrewm@uow.edu.au>
+               v1.18 12Mar2001 Andrew Morton
                        - Avoid bogus detect of 3c590's (Andrzej Krzysztofowicz)
                        - Reviewed against 1.18 from scyld.com
                v1.18a 17Nov2001 Jeff Garzik <jgarzik@pobox.com>
@@ -94,7 +94,7 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 
-static char version[] __initdata = DRV_NAME ".c:" DRV_VERSION " " DRV_RELDATE " becker@scyld.com\n";
+static char version[] __devinitdata = DRV_NAME ".c:" DRV_VERSION " " DRV_RELDATE " becker@scyld.com\n";
 
 #ifdef EL3_DEBUG
 static int el3_debug = EL3_DEBUG;
@@ -167,7 +167,6 @@ enum RxFilter {
 enum el3_cardtype { EL3_ISA, EL3_PNP, EL3_MCA, EL3_EISA };
 
 struct el3_private {
-       struct net_device_stats stats;
        spinlock_t lock;
        /* skb send-queue */
        int head, size;
@@ -187,7 +186,7 @@ static int max_interrupt_work = 10;
 static int nopnp;
 #endif
 
-static int __init el3_common_init(struct net_device *dev);
+static int __devinit el3_common_init(struct net_device *dev);
 static void el3_common_remove(struct net_device *dev);
 static ushort id_read_eeprom(int index);
 static ushort read_eeprom(int ioaddr, int index);
@@ -414,7 +413,7 @@ static int __devinit el3_pnp_probe(struct pnp_dev *pdev,
 {
        short i;
        int ioaddr, irq, if_port;
-       u16 phys_addr[3];
+       __be16 phys_addr[3];
        struct net_device *dev = NULL;
        int err;
 
@@ -538,11 +537,25 @@ static struct mca_driver el3_mca_driver = {
 static int mca_registered;
 #endif /* CONFIG_MCA */
 
-static int __init el3_common_init(struct net_device *dev)
+static const struct net_device_ops netdev_ops = {
+       .ndo_open               = el3_open,
+       .ndo_stop               = el3_close,
+       .ndo_start_xmit         = el3_start_xmit,
+       .ndo_get_stats          = el3_get_stats,
+       .ndo_set_multicast_list = set_multicast_list,
+       .ndo_tx_timeout         = el3_tx_timeout,
+       .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    = el3_poll_controller,
+#endif
+};
+
+static int __devinit el3_common_init(struct net_device *dev)
 {
        struct el3_private *lp = netdev_priv(dev);
        int err;
-       DECLARE_MAC_BUF(mac);
        const char *if_names[] = {"10baseT", "AUI", "undefined", "BNC"};
 
        spin_lock_init(&lp->lock);
@@ -555,16 +568,8 @@ static int __init el3_common_init(struct net_device *dev)
        }
 
        /* The EL3-specific entries in the device structure. */
-       dev->open = &el3_open;
-       dev->hard_start_xmit = &el3_start_xmit;
-       dev->stop = &el3_close;
-       dev->get_stats = &el3_get_stats;
-       dev->set_multicast_list = &set_multicast_list;
-       dev->tx_timeout = el3_tx_timeout;
+       dev->netdev_ops = &netdev_ops;
        dev->watchdog_timeo = TX_TIMEOUT;
-#ifdef CONFIG_NET_POLL_CONTROLLER
-       dev->poll_controller = el3_poll_controller;
-#endif
        SET_ETHTOOL_OPS(dev, &ethtool_ops);
 
        err = register_netdev(dev);
@@ -576,9 +581,9 @@ static int __init el3_common_init(struct net_device *dev)
        }
 
        printk(KERN_INFO "%s: 3c5x9 found at %#3.3lx, %s port, "
-              "address %s, IRQ %d.\n",
+              "address %pM, IRQ %d.\n",
               dev->name, dev->base_addr, if_names[(dev->if_port & 0x03)],
-              print_mac(mac, dev->dev_addr), dev->irq);
+              dev->dev_addr, dev->irq);
 
        if (el3_debug > 0)
                printk(KERN_INFO "%s", version);
@@ -606,7 +611,7 @@ static int __init el3_mca_probe(struct device *device)
 
        short i;
        int ioaddr, irq, if_port;
-       u16 phys_addr[3];
+       __be16 phys_addr[3];
        struct net_device *dev = NULL;
        u_char pos4, pos5;
        struct mca_device *mdev = to_mca_device(device);
@@ -636,14 +641,13 @@ static int __init el3_mca_probe(struct device *device)
                        printk(KERN_DEBUG "3c529: irq %d  ioaddr 0x%x  ifport %d\n", irq, ioaddr, if_port);
        }
        EL3WINDOW(0);
-       for (i = 0; i < 3; i++) {
-                       phys_addr[i] = htons(read_eeprom(ioaddr, i));
-       }
+       for (i = 0; i < 3; i++)
+               phys_addr[i] = htons(read_eeprom(ioaddr, i));
 
        dev = alloc_etherdev(sizeof (struct el3_private));
        if (dev == NULL) {
-                       release_region(ioaddr, EL3_IO_EXTENT);
-                       return -ENOMEM;
+               release_region(ioaddr, EL3_IO_EXTENT);
+               return -ENOMEM;
        }
 
        netdev_boot_setup_check(dev);
@@ -669,7 +673,7 @@ static int __init el3_eisa_probe (struct device *device)
 {
        short i;
        int ioaddr, irq, if_port;
-       u16 phys_addr[3];
+       __be16 phys_addr[3];
        struct net_device *dev = NULL;
        struct eisa_device *edev;
        int err;
@@ -794,7 +798,6 @@ el3_open(struct net_device *dev)
 static void
 el3_tx_timeout (struct net_device *dev)
 {
-       struct el3_private *lp = netdev_priv(dev);
        int ioaddr = dev->base_addr;
 
        /* Transmitter timeout, serious problems. */
@@ -802,7 +805,7 @@ el3_tx_timeout (struct net_device *dev)
                   "Tx FIFO room %d.\n",
                   dev->name, inb(ioaddr + TX_STATUS), inw(ioaddr + EL3_STATUS),
                   inw(ioaddr + TX_FREE));
-       lp->stats.tx_errors++;
+       dev->stats.tx_errors++;
        dev->trans_start = jiffies;
        /* Issue TX_RESET and TX_START commands. */
        outw(TxReset, ioaddr + EL3_CMD);
@@ -820,7 +823,7 @@ el3_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
        netif_stop_queue (dev);
 
-       lp->stats.tx_bytes += skb->len;
+       dev->stats.tx_bytes += skb->len;
 
        if (el3_debug > 4) {
                printk(KERN_DEBUG "%s: el3_start_xmit(length = %u) called, status %4.4x.\n",
@@ -881,7 +884,7 @@ el3_start_xmit(struct sk_buff *skb, struct net_device *dev)
                int i = 4;
 
                while (--i > 0  &&      (tx_status = inb(ioaddr + TX_STATUS)) > 0) {
-                       if (tx_status & 0x38) lp->stats.tx_aborted_errors++;
+                       if (tx_status & 0x38) dev->stats.tx_aborted_errors++;
                        if (tx_status & 0x30) outw(TxReset, ioaddr + EL3_CMD);
                        if (tx_status & 0x3C) outw(TxEnable, ioaddr + EL3_CMD);
                        outb(0x00, ioaddr + TX_STATUS); /* Pop the status stack. */
@@ -931,12 +934,11 @@ el3_interrupt(int irq, void *dev_id)
                                outw(AckIntr | RxEarly, ioaddr + EL3_CMD);
                        }
                        if (status & TxComplete) {                      /* Really Tx error. */
-                               struct el3_private *lp = netdev_priv(dev);
                                short tx_status;
                                int i = 4;
 
                                while (--i>0 && (tx_status = inb(ioaddr + TX_STATUS)) > 0) {
-                                       if (tx_status & 0x38) lp->stats.tx_aborted_errors++;
+                                       if (tx_status & 0x38) dev->stats.tx_aborted_errors++;
                                        if (tx_status & 0x30) outw(TxReset, ioaddr + EL3_CMD);
                                        if (tx_status & 0x3C) outw(TxEnable, ioaddr + EL3_CMD);
                                        outb(0x00, ioaddr + TX_STATUS); /* Pop the status stack. */
@@ -1002,7 +1004,7 @@ el3_get_stats(struct net_device *dev)
        spin_lock_irqsave(&lp->lock, flags);
        update_stats(dev);
        spin_unlock_irqrestore(&lp->lock, flags);
-       return &lp->stats;
+       return &dev->stats;
 }
 
 /*  Update statistics.  We change to register window 6, so this should be run
@@ -1012,7 +1014,6 @@ el3_get_stats(struct net_device *dev)
        */
 static void update_stats(struct net_device *dev)
 {
-       struct el3_private *lp = netdev_priv(dev);
        int ioaddr = dev->base_addr;
 
        if (el3_debug > 5)
@@ -1021,13 +1022,13 @@ static void update_stats(struct net_device *dev)
        outw(StatsDisable, ioaddr + EL3_CMD);
        /* Switch to the stats window, and read everything. */
        EL3WINDOW(6);
-       lp->stats.tx_carrier_errors     += inb(ioaddr + 0);
-       lp->stats.tx_heartbeat_errors   += inb(ioaddr + 1);
+       dev->stats.tx_carrier_errors    += inb(ioaddr + 0);
+       dev->stats.tx_heartbeat_errors  += inb(ioaddr + 1);
        /* Multiple collisions. */         inb(ioaddr + 2);
-       lp->stats.collisions            += inb(ioaddr + 3);
-       lp->stats.tx_window_errors      += inb(ioaddr + 4);
-       lp->stats.rx_fifo_errors        += inb(ioaddr + 5);
-       lp->stats.tx_packets            += inb(ioaddr + 6);
+       dev->stats.collisions           += inb(ioaddr + 3);
+       dev->stats.tx_window_errors     += inb(ioaddr + 4);
+       dev->stats.rx_fifo_errors       += inb(ioaddr + 5);
+       dev->stats.tx_packets           += inb(ioaddr + 6);
        /* Rx packets   */                 inb(ioaddr + 7);
        /* Tx deferrals */                 inb(ioaddr + 8);
        inw(ioaddr + 10);       /* Total Rx and Tx octets. */
@@ -1042,7 +1043,6 @@ static void update_stats(struct net_device *dev)
 static int
 el3_rx(struct net_device *dev)
 {
-       struct el3_private *lp = netdev_priv(dev);
        int ioaddr = dev->base_addr;
        short rx_status;
 
@@ -1054,21 +1054,20 @@ el3_rx(struct net_device *dev)
                        short error = rx_status & 0x3800;
 
                        outw(RxDiscard, ioaddr + EL3_CMD);
-                       lp->stats.rx_errors++;
+                       dev->stats.rx_errors++;
                        switch (error) {
-                       case 0x0000:            lp->stats.rx_over_errors++; break;
-                       case 0x0800:            lp->stats.rx_length_errors++; break;
-                       case 0x1000:            lp->stats.rx_frame_errors++; break;
-                       case 0x1800:            lp->stats.rx_length_errors++; break;
-                       case 0x2000:            lp->stats.rx_frame_errors++; break;
-                       case 0x2800:            lp->stats.rx_crc_errors++; break;
+                       case 0x0000:            dev->stats.rx_over_errors++; break;
+                       case 0x0800:            dev->stats.rx_length_errors++; break;
+                       case 0x1000:            dev->stats.rx_frame_errors++; break;
+                       case 0x1800:            dev->stats.rx_length_errors++; break;
+                       case 0x2000:            dev->stats.rx_frame_errors++; break;
+                       case 0x2800:            dev->stats.rx_crc_errors++; break;
                        }
                } else {
                        short pkt_len = rx_status & 0x7ff;
                        struct sk_buff *skb;
 
                        skb = dev_alloc_skb(pkt_len+5);
-                       lp->stats.rx_bytes += pkt_len;
                        if (el3_debug > 4)
                                printk("Receiving packet size %d status %4.4x.\n",
                                           pkt_len, rx_status);
@@ -1082,12 +1081,12 @@ el3_rx(struct net_device *dev)
                                outw(RxDiscard, ioaddr + EL3_CMD); /* Pop top Rx packet. */
                                skb->protocol = eth_type_trans(skb,dev);
                                netif_rx(skb);
-                               dev->last_rx = jiffies;
-                               lp->stats.rx_packets++;
+                               dev->stats.rx_bytes += pkt_len;
+                               dev->stats.rx_packets++;
                                continue;
                        }
                        outw(RxDiscard, ioaddr + EL3_CMD);
-                       lp->stats.rx_dropped++;
+                       dev->stats.rx_dropped++;
                        if (el3_debug)
                                printk("%s: Couldn't allocate a sk_buff of size %d.\n",
                                           dev->name, pkt_len);
@@ -1483,6 +1482,7 @@ el3_resume(struct device *pdev)
        spin_lock_irqsave(&lp->lock, flags);
 
        outw(PowerUp, ioaddr + EL3_CMD);
+       EL3WINDOW(0);
        el3_up(dev);
 
        if (netif_running(dev))