netdev
[Top] [All Lists]

Re: alloc_etherdev breaks ether=

To: Jeff Garzik <jgarzik@xxxxxxxxxxxxxxxx>
Subject: Re: alloc_etherdev breaks ether=
From: Andrew Morton <andrewm@xxxxxxxxxx>
Date: Sun, 01 Jul 2001 23:37:59 +1000
Cc: "David S. Miller" <davem@xxxxxxxxxx>, netdev@xxxxxxxxxxx, Alan Cox <alan@xxxxxxxxxxxxxxxxxxx>, Linus Torvalds <torvalds@xxxxxxxxxxxxx>, Russell King <rmk@xxxxxxxxxxxxxxxx>, ionut@xxxxxxxxxxxxxxx, Manfred Spraul <manfred@xxxxxxxxxxxxxxxx>, hfhsu@xxxxxxxxxx, p_gortmaker@xxxxxxxxx, tori@xxxxxxxxxxxxxxx, breed@xxxxxxxxxxxxxxxxxxxxx, linux-tr@xxxxxxxxxxx
References: <3B3C0137.1896A895@uow.edu.au> <3B3C9089.D85A26@mandrakesoft.com>
Sender: owner-netdev@xxxxxxxxxxx
OK, here's a first cut at fixing this.

background for newcomers: the new alloc_etherdev() API
broke the `ether=' boot option because the name of the
netdevice is not know at the start of probing.

Patch is tested fairly thoroughly with 3c59x.  The /sbin/hotplug
stuff works OK.  Modular and statically-linked drivers see the
`ether=' commandline correctly.  Failure of probe() works OK.

The patch does the following:

- Makes alloc_etherdev() instantiate the device name, and registers
  it in `hidden' state.  So the device is on the dev_base list,
  but is not visible to open() attempts.  This also has the effect of
  making the final device name known at the start of probe(), and
  reserves it from other, parallel probe methods.

  When a device is registered in `hidden' state we do *not* run
  /sbin/hotplug or the protocol notification.  The device isn't ready yet.

- Create new `publish_netdev()' API function.  This unhides the
  previously registered device and runs /sbin/hotplug and the
  protocol notifier.

- If the probe function fails, the prober must call unregister_netdev()
  on the device, then kfree it.  Consequently:

- unregister_netdev() will not run /sbin/hotplug and the protocol
  notifiers for a hidden device: it assumes the device has never
  really existed, and that the initial /sbin/hotplug and notifier
  cals were never made.

- Converts all users of alloc_etherdev() and alloc_trdev() to use
  the new scheme.

- Goes through all the (many) places where we traverse the dev_base
  list and tests `netif_device_hidden()' where it seems necessary
  to do so.  If this is simply too putrid we can put together a
  `for_each_netdevice' macro.

The "new scheme" is:

xxx_probe()
{
        dev = alloc_etherdev(sizeof(private));  /* allocates final name, 
reserves
                                                   it, registers the device in
                                                   `hidden' mode. Does not run 
/sbin/hotplug */
        if (dev == 0)
                return -ESOMETHING;
        <initialise stuff>
        if (initialise_more_stuff() < 0)
                goto out_free_dev;

        publish_netdev(dev);                    /* Make device available to 
open,
                                                   run /sbin/hotplug and 
protocol notifiers */
        return 0;
out_free_dev:
        unregister_netdev(dev);                 /* Does not run /sbin/hotplug, 
notifier */
        kfree(dev);
        return -ESOMETHINGELSE;
}

A few things I noticed going through the various files:


- tulip_core.c:tulip_mwi_config() local variable csr0 was used uninitialised.
  Took a punt and set it to zero.

- fealnx.c: fealnx_pci_tbl[] __devinitdata was in the wrong place.

- starfire.c was calling unregister_netdevice() on the output
  of alloc_etherdev().  This *used* to be incorrect.

- drivers/net/Config.in allows me to select drivers/net/am79c961a.c
  on x86 platform.  It'll only compile on ARM.  I didn't fix this.

- 8139too's setup scheme is a little different from the others.
  Jeff, please check carefully...

- I did *not* go through the affected drivers making them use
  dev->name in their printk's again.  Later.

- I adopted the convention that publish_netdev() is called
  immediately prior to successful return from probe().
  Fortunately it cannot fail, so there was a bit of cleaning
  up permitted in various drivers.

- The 3c59x.c patch contains some extra stuff:

  - Instead of disabling scatter/gather if CONFIG_HIGHMEM is
    turned on, do it at runtime by checking the return value of
    nr_high_freepages().  This has the effect of permitting
    zerocopy to be used on highmem kernels if they're running
    on non-highmem hardware.

  - Decrease verbosity of boot messages from ~7 lines to two:

        3c59x: Donald Becker and others. www.scyld.com/network/vortex.html
        eth0: 3Com PCI 3c980 Cyclone at 0xd400. Vers LK1.1.16

    They can be restored by increasing the debug level.

  - debug level can be increased from `ether=' option, as per
    the docco.


   --- linux-2.4.6-pre8/include/linux/netdevice.h       Wed May  2 22:00:07 2001
+++ linux-akpm/include/linux/netdevice.h        Sun Jul  1 23:24:18 2001
@@ -202,7 +202,8 @@ enum netdev_state_t
        __LINK_STATE_START,
        __LINK_STATE_PRESENT,
        __LINK_STATE_SCHED,
-       __LINK_STATE_NOCARRIER
+       __LINK_STATE_NOCARRIER,
+       __LINK_STATE_HIDDEN,    /* Exists, but may not be opened */
 };
 
 
@@ -626,6 +627,11 @@ static inline void netif_device_attach(s
        }
 }
 
+static inline int netif_device_hidden(struct net_device *dev)
+{
+       return test_bit(__LINK_STATE_HIDDEN, &dev->state);
+}
+
 /* These functions live elsewhere (drivers/net/net_init.c, but related) */
 
 extern void            ether_setup(struct net_device *dev);
@@ -636,6 +642,7 @@ extern void         fc_freedev(struct net_devic
 /* Support for loadable net-drivers */
 extern int             register_netdev(struct net_device *dev);
 extern void            unregister_netdev(struct net_device *dev);
+extern void            publish_netdev(struct net_device *dev);
 /* Functions used for multicast support */
 extern void            dev_mc_upload(struct net_device *dev);
 extern int             dev_mc_delete(struct net_device *dev, void *addr, int 
alen, int all);
--- linux-2.4.6-pre8/drivers/net/net_init.c     Mon May 28 13:31:47 2001
+++ linux-akpm/drivers/net/net_init.c   Sun Jul  1 22:08:19 2001
@@ -29,6 +29,8 @@
                        allocation setups. Abolished the 16 card limits.
        03/19/2000 - jgarzik and Urban Widmark: init_etherdev 32-byte align
        03/21/2001 - jgarzik: alloc_etherdev and friends
+       07/01/2001 - akpm: adjust alloc_etherdev() to register the device
+                    in `hidden' mode.
 
 */
 
@@ -70,8 +72,7 @@
 */
 
 
-static struct net_device *alloc_netdev(int sizeof_priv, const char *mask,
-                                      void (*setup)(struct net_device *))
+static struct net_device *init_alloc_dev(int sizeof_priv)
 {
        struct net_device *dev;
        int alloc_size;
@@ -91,32 +92,27 @@ static struct net_device *alloc_netdev(i
        if (sizeof_priv)
                dev->priv = (void *) (((long)(dev + 1) + 31) & ~31);
 
-       setup(dev);
-       strcpy(dev->name, mask);
-
        return dev;
 }
 
-static struct net_device *init_alloc_dev(int sizeof_priv)
+static struct net_device *alloc_netdev(int sizeof_priv, const char *mask,
+                                      void (*setup)(struct net_device *))
 {
        struct net_device *dev;
-       int alloc_size;
-
-       /* ensure 32-byte alignment of the private area */
-       alloc_size = sizeof (*dev) + sizeof_priv + 31;
 
-       dev = (struct net_device *) kmalloc (alloc_size, GFP_KERNEL);
-       if (dev == NULL)
-       {
-               printk(KERN_ERR "alloc_dev: Unable to allocate device 
memory.\n");
-               return NULL;
+       dev = init_alloc_dev(sizeof_priv);
+       if (dev) {
+               set_bit(__LINK_STATE_HIDDEN, &dev->state);
+               /* register_netdev() will allocate the final interface name */
+               if (register_netdev(dev) < 0) {
+                       kfree(dev);
+                       dev = NULL;
+                       goto out;
+               }
+               netdev_boot_setup_check(dev);
+               (*setup)(dev);
        }
-
-       memset(dev, 0, alloc_size);
-
-       if (sizeof_priv)
-               dev->priv = (void *) (((long)(dev + 1) + 31) & ~31);
-
+out:
        return dev;
 }
 
@@ -210,7 +206,9 @@ struct net_device *init_etherdev(struct 
  *     for this ethernet device
  *
  * Fill in the fields of the device structure with ethernet-generic
- * values. Basically does everything except registering the device.
+ * values. The device is then registered so that its name is known
+ * and reserved.  However it remains in `hidden' state until it is
+ * made available to opens via publish_netdev().
  *
  * Constructs a new net device, complete with a private data area of
  * size @sizeof_priv.  A 32-byte (not bit) alignment is enforced for
--- linux-2.4.6-pre8/net/core/dev.c     Sun Jul  1 16:11:26 2001
+++ linux-akpm/net/core/dev.c   Sun Jul  1 21:05:52 2001
@@ -399,17 +399,25 @@ __setup("netdev=", netdev_boot_setup);
  */
  
 
-struct net_device *__dev_get_by_name(const char *name)
+static struct net_device *____dev_get_by_name(const char *name, int 
allow_hidden)
 {
        struct net_device *dev;
 
        for (dev = dev_base; dev != NULL; dev = dev->next) {
-               if (strncmp(dev->name, name, IFNAMSIZ) == 0)
+               if (strncmp(dev->name, name, IFNAMSIZ) == 0) {
+                       if (!allow_hidden && netif_device_hidden(dev))
+                               continue;
                        return dev;
+               }
        }
        return NULL;
 }
 
+struct net_device *__dev_get_by_name(const char *name)
+{
+       return ____dev_get_by_name(name, 0);
+}
+
 /**
  *     dev_get_by_name         - find a device by its name
  *     @name: name to find
@@ -479,7 +487,7 @@ struct net_device * __dev_get_by_index(i
        struct net_device *dev;
 
        for (dev = dev_base; dev != NULL; dev = dev->next) {
-               if (dev->ifindex == ifindex)
+               if (dev->ifindex == ifindex && !netif_device_hidden(dev))
                        return dev;
        }
        return NULL;
@@ -530,7 +538,8 @@ struct net_device *dev_getbyhwaddr(unsig
 
        for (dev = dev_base; dev != NULL; dev = dev->next) {
                if (dev->type == type &&
-                   memcmp(dev->dev_addr, ha, dev->addr_len) == 0)
+                   memcmp(dev->dev_addr, ha, dev->addr_len) == 0 &&
+                   !netif_device_hidden(dev))
                        return dev;
        }
        return NULL;
@@ -558,7 +567,7 @@ int dev_alloc_name(struct net_device *de
         */
        for (i = 0; i < 100; i++) {
                sprintf(buf,name,i);
-               if (__dev_get_by_name(buf) == NULL) {
+               if (____dev_get_by_name(buf, 1) == NULL) {
                        strcpy(dev->name, buf);
                        return i;
                }
@@ -1624,6 +1633,8 @@ static int dev_ifconf(char *arg)
 
        total = 0;
        for (dev = dev_base; dev != NULL; dev = dev->next) {
+               if (netif_device_hidden(dev))
+                       continue;
                for (i=0; i<NPROTO; i++) {
                        if (gifconf_list[i]) {
                                int done;
@@ -2373,7 +2384,8 @@ static int dev_boot_phase = 1;
  *     @dev: device to register
  *     
  *     Take a completed network device structure and add it to the kernel
- *     interfaces. A %NETDEV_REGISTER message is sent to the netdev notifier
+ *     interfaces.  If the device is not in the `hidden' state then a
+ *     %NETDEV_REGISTER message is sent to the netdev notifier
  *     chain. 0 is returned on success. A negative errno code is returned
  *     on a failure to set up the device, or if the name is a duplicate.
  *
@@ -2450,14 +2462,39 @@ int register_netdevice(struct net_device
        dev->deadbeaf = 0;
        write_unlock_bh(&dev_base_lock);
 
+       if (!netif_device_hidden(dev)) {
+               /* Notify protocols, that a new device appeared. */
+               notifier_call_chain(&netdev_chain, NETDEV_REGISTER, dev);
+               net_run_sbin_hotplug(dev, "register");
+       }
+       return 0;
+}
+
+/**
+ *     publish_netdev  - publish a registered but hidden netdevice
+ *     @dev: device to register
+ *     
+ *     Take a completed network device structure and make it available for
+ *     opening. A %NETDEV_REGISTER message is sent to the netdev notifier
+ *     chain. 0 is returned on success. A negative errno code is returned
+ *     on a failure.
+ */
+
+void publish_netdev(struct net_device *dev)
+{
+       rtnl_lock();
+       if (!netif_device_hidden(dev)) {
+               printk(KERN_ERR "Unhidden device `%s' passed to "
+                       __FUNCTION__ "\n", dev->name);
+       }
+       clear_bit(__LINK_STATE_HIDDEN, &dev->state);
        /* Notify protocols, that a new device appeared. */
        notifier_call_chain(&netdev_chain, NETDEV_REGISTER, dev);
-
        net_run_sbin_hotplug(dev, "register");
-
-       return 0;
+       rtnl_unlock();
 }
 
+
 /**
  *     netdev_finish_unregister - complete unregistration
  *     @dev: device
@@ -2538,13 +2575,15 @@ int unregister_netdevice(struct net_devi
                /* Shutdown queueing discipline. */
                dev_shutdown(dev);
 
-               net_run_sbin_hotplug(dev, "unregister");
-
-               /* Notify protocols, that we are about to destroy
-                  this device. They should clean all the things.
-                */
-               notifier_call_chain(&netdev_chain, NETDEV_UNREGISTER, dev);
+               if (!netif_device_hidden(dev)) {
+                       net_run_sbin_hotplug(dev, "unregister");
 
+                       /* Notify protocols, that we are about to destroy
+                        * this device. They should clean all the things.
+                        */
+                       notifier_call_chain(&netdev_chain,
+                                       NETDEV_UNREGISTER, dev);
+               }
                /*
                 *      Flush the multicast chain
                 */
--- linux-2.4.6-pre8/net/core/dev_mcast.c       Tue Oct 17 06:43:50 2000
+++ linux-akpm/net/core/dev_mcast.c     Sun Jul  1 23:12:36 2001
@@ -228,6 +228,8 @@ static int dev_mc_read_proc(char *buffer
 
        read_lock(&dev_base_lock);
        for (dev = dev_base; dev; dev = dev->next) {
+               if (netif_device_hidden(dev))
+                       continue;
                spin_lock_bh(&dev->xmit_lock);
                for (m = dev->mc_list; m; m = m->next) {
                        int i;
--- linux-2.4.6-pre8/net/core/rtnetlink.c       Mon Feb 28 13:45:10 2000
+++ linux-akpm/net/core/rtnetlink.c     Sun Jul  1 23:13:08 2001
@@ -215,6 +215,8 @@ int rtnetlink_dump_ifinfo(struct sk_buff
 
        read_lock(&dev_base_lock);
        for (dev=dev_base, idx=0; dev; dev = dev->next, idx++) {
+               if (netif_device_hidden(dev))
+                       continue;
                if (idx < s_idx)
                        continue;
                if (rtnetlink_fill_ifinfo(skb, dev, RTM_NEWLINK, 
NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, 0) <= 0)
--- linux-2.4.6-pre8/net/ipv4/igmp.c    Wed May  2 22:00:08 2001
+++ linux-akpm/net/ipv4/igmp.c  Sun Jul  1 23:15:22 2001
@@ -787,9 +787,14 @@ int ip_mc_procinfo(char *buffer, char **
 
        read_lock(&dev_base_lock);
        for(dev = dev_base; dev; dev = dev->next) {
-               struct in_device *in_dev = in_dev_get(dev);
-               char   *querier = "NONE";
+               struct in_device *in_dev;
+               char   *querier;
 
+               if (netif_device_hidden(dev))
+                       continue;
+
+               in_dev = in_dev_get(dev);
+               querier = "NONE";
                if (in_dev == NULL)
                        continue;
 
--- linux-2.4.6-pre8/net/ipv4/devinet.c Mon May 28 13:31:50 2001
+++ linux-akpm/net/ipv4/devinet.c       Sun Jul  1 23:25:26 2001
@@ -731,6 +731,9 @@ u32 inet_select_addr(const struct net_de
        read_lock(&dev_base_lock);
        read_lock(&inetdev_lock);
        for (dev=dev_base; dev; dev=dev->next) {
+               /* typecast avoids a compiler constness warning */
+               if (netif_device_hidden((struct net_device *)dev))
+                       continue;
                if ((in_dev=__in_dev_get(dev)) == NULL)
                        continue;
 
@@ -878,6 +881,8 @@ static int inet_dump_ifaddr(struct sk_bu
        s_ip_idx = ip_idx = cb->args[1];
        read_lock(&dev_base_lock);
        for (dev=dev_base, idx=0; dev; dev = dev->next, idx++) {
+               if (netif_device_hidden(dev))
+                       continue;
                if (idx < s_idx)
                        continue;
                if (idx > s_idx)
@@ -982,6 +987,8 @@ void inet_forward_change()
        read_lock(&dev_base_lock);
        for (dev = dev_base; dev; dev = dev->next) {
                struct in_device *in_dev;
+               if (netif_device_hidden(dev))
+                       continue;
                read_lock(&inetdev_lock);
                in_dev = __in_dev_get(dev);
                if (in_dev)
--- linux-2.4.6-pre8/net/sched/sch_api.c        Tue Jan  2 04:57:08 2001
+++ linux-akpm/net/sched/sch_api.c      Sun Jul  1 23:19:47 2001
@@ -804,6 +804,8 @@ static int tc_dump_qdisc(struct sk_buff 
        s_q_idx = q_idx = cb->args[1];
        read_lock(&dev_base_lock);
        for (dev=dev_base, idx=0; dev; dev = dev->next, idx++) {
+               if (netif_device_hidden(dev))
+                       continue;
                if (idx < s_idx)
                        continue;
                if (idx > s_idx)
--- linux-2.4.6-pre8/arch/sparc64/solaris/ioctl.c       Wed Nov 29 16:53:44 2000
+++ linux-akpm/arch/sparc64/solaris/ioctl.c     Sun Jul  1 23:21:40 2001
@@ -670,7 +670,11 @@ static inline int solaris_i(unsigned int
                        int i = 0;
                        
                        read_lock_bh(&dev_base_lock);
-                       for (d = dev_base; d; d = d->next) i++;
+                       for (d = dev_base; d; d = d->next) {
+                               if (netif_device_hidden(dev))
+                                       continue;
+                               i++;
+                       }
                        read_unlock_bh(&dev_base_lock);
 
                        if (put_user (i, (int *)A(arg)))
--- linux-2.4.6-pre8/net/netsyms.c      Sun Jul  1 16:11:26 2001
+++ linux-akpm/net/netsyms.c    Sun Jul  1 20:43:06 2001
@@ -456,6 +456,7 @@ EXPORT_SYMBOL(unregister_netdevice_notif
 EXPORT_SYMBOL(loopback_dev);
 EXPORT_SYMBOL(register_netdevice);
 EXPORT_SYMBOL(unregister_netdevice);
+EXPORT_SYMBOL(publish_netdev);
 EXPORT_SYMBOL(netdev_state_change);
 EXPORT_SYMBOL(dev_new_index);
 EXPORT_SYMBOL(dev_get_by_index);
--- linux-2.4.6-pre8/drivers/net/3c59x.c        Sun Jul  1 16:11:24 2001
+++ linux-akpm/drivers/net/3c59x.c      Sun Jul  1 23:07:11 2001
@@ -149,6 +149,11 @@
     - Implemented alloc_etherdev() API
     - Special-case the 'Tx error 82' message.
 
+   LK1.1.16 1 July 2001 akpm
+    - Make NETIF_F_SG dependent upon nr_free_highpages(), not on CONFIG_HIGHMEM
+    - Lessen verbosity of bootup messages
+    - Use publish_netdev() API
+
     - See http://www.uow.edu.au/~andrewm/linux/#3c59x-2.3 for more details.
     - Also see Documentation/networking/vortex.txt
 */
@@ -164,8 +169,8 @@
 
 
 #define DRV_NAME       "3c59x"
-#define DRV_VERSION    "LK1.1.15"
-#define DRV_RELDATE    "6 June 2001"
+#define DRV_VERSION    "LK1.1.16"
+#define DRV_RELDATE    "29 June 2001"
 
 
 
@@ -223,6 +228,7 @@ static int vortex_debug = 1;
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/ethtool.h>
+#include <linux/highmem.h>
 #include <asm/irq.h>                   /* For NR_IRQS only. */
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -237,10 +243,11 @@ static int vortex_debug = 1;
 
 
 static char version[] __devinitdata =
-DRV_NAME ".c:" DRV_VERSION " " DRV_RELDATE "  Donald Becker and others. 
http://www.scyld.com/network/vortex.html\n";;
+DRV_NAME ": Donald Becker and others. www.scyld.com/network/vortex.html\n";
 
 MODULE_AUTHOR("Donald Becker <becker@xxxxxxxxx>");
-MODULE_DESCRIPTION("3Com 3c59x/3c90x/3c575 series Vortex/Boomerang/Cyclone 
driver");
+MODULE_DESCRIPTION("3Com 3c59x/3c9xx ethernet driver "
+                                       DRV_VERSION " " DRV_RELDATE);
 MODULE_PARM(debug, "i");
 MODULE_PARM(options, "1-" __MODULE_STRING(8) "i");
 MODULE_PARM(full_duplex, "1-" __MODULE_STRING(8) "i");
@@ -953,16 +960,13 @@ static int __devinit vortex_probe1(struc
        static int printed_version;
        int retval;
        struct vortex_chip_info * const vci = &vortex_info_tbl[chip_idx];
-       char *print_name;
+       int print_info;
 
        if (!printed_version) {
                printk (KERN_INFO "%s", version);
-               printk (KERN_INFO "See Documentation/networking/vortex.txt\n");
                printed_version = 1;
        }
 
-       print_name = pdev ? pdev->slot_name : "3c59x";
-
        dev = alloc_etherdev(sizeof(*vp));
        retval = -ENOMEM;
        if (!dev) {
@@ -971,8 +975,32 @@ static int __devinit vortex_probe1(struc
        }
        SET_MODULE_OWNER(dev);
 
-       printk(KERN_INFO "%s: 3Com %s %s at 0x%lx, ",
-              print_name,
+       /* The lower four bits are the media type. */
+       if (dev->mem_start) {
+               /*
+                * The 'options' param is passed in as the third arg to the
+                * LILO 'ether=' argument for non-modular use
+                */
+               option = dev->mem_start;
+       }
+       else if (card_idx < MAX_UNITS)
+               option = options[card_idx];
+       else
+               option = -1;
+
+       if (option > 0) {
+               if (option & 0x0400)
+                       vortex_debug = 2;
+               if (option & 0x0800)
+                       vortex_debug = 7;
+       }
+
+       print_info = (vortex_debug > 1);
+       if (print_info)
+               printk (KERN_INFO "See Documentation/networking/vortex.txt\n");
+
+       printk(KERN_INFO "%s: 3Com %s %s at 0x%lx. Vers " DRV_VERSION "\n",
+              dev->name,
               pdev ? "PCI" : "EISA",
               vci->name,
               ioaddr);
@@ -996,7 +1024,7 @@ static int __devinit vortex_probe1(struc
        if (pdev) {
                /* EISA resources already marked, so only PCI needs to do this 
here */
                /* Ignore return value, because Cardbus drivers already 
allocate for us */
-               if (request_region(ioaddr, vci->io_size, print_name) != NULL)
+               if (request_region(ioaddr, vci->io_size, dev->name) != NULL)
                        vp->must_free_region = 1;
 
                /* enable bus-mastering if necessary */         
@@ -1015,7 +1043,7 @@ static int __devinit vortex_probe1(struc
                        if (pci_latency < new_latency) {
                                printk(KERN_INFO "%s: Overriding PCI latency"
                                        " timer (CFLT) setting of %d, new value 
is %d.\n",
-                                       print_name, pci_latency, new_latency);
+                                       dev->name, pci_latency, new_latency);
                                        pci_write_config_byte(pdev, 
PCI_LATENCY_TIMER, new_latency);
                        }
                }
@@ -1041,19 +1069,6 @@ static int __devinit vortex_probe1(struc
        if (pdev)
                pci_set_drvdata(pdev, dev);
 
-       /* The lower four bits are the media type. */
-       if (dev->mem_start) {
-               /*
-                * AKPM: ewww..  The 'options' param is passed in as the third 
arg to the
-                * LILO 'ether=' argument for non-modular use
-                */
-               option = dev->mem_start;
-       }
-       else if (card_idx < MAX_UNITS)
-               option = options[card_idx];
-       else
-               option = -1;
-
        vp->media_override = 7;
        if (option >= 0) {
                vp->media_override = ((option & 7) == 2)  ?  0  :  option & 15;
@@ -1110,27 +1125,33 @@ static int __devinit vortex_probe1(struc
                printk(" ***INVALID CHECKSUM %4.4x*** ", checksum);
        for (i = 0; i < 3; i++)
                ((u16 *)dev->dev_addr)[i] = htons(eeprom[i + 10]);
-       for (i = 0; i < 6; i++)
-               printk("%c%2.2x", i ? ':' : ' ', dev->dev_addr[i]);
+       if (print_info) {
+               for (i = 0; i < 6; i++)
+                       printk("%c%2.2x", i ? ':' : ' ', dev->dev_addr[i]);
+       }
        EL3WINDOW(2);
        for (i = 0; i < 6; i++)
                outb(dev->dev_addr[i], ioaddr + i);
 
 #ifdef __sparc__
-       printk(", IRQ %s\n", __irq_itoa(dev->irq));
+       if (print_info)
+               printk(", IRQ %s\n", __irq_itoa(dev->irq));
 #else
-       printk(", IRQ %d\n", dev->irq);
+       if (print_info)
+               printk(", IRQ %d\n", dev->irq);
        /* Tell them about an invalid IRQ. */
-       if (vortex_debug && (dev->irq <= 0 || dev->irq >= NR_IRQS))
+       if (dev->irq <= 0 || dev->irq >= NR_IRQS)
                printk(KERN_WARNING " *** Warning: IRQ %d is unlikely to work! 
***\n",
                           dev->irq);
 #endif
 
        EL3WINDOW(4);
        step = (inb(ioaddr + Wn4_NetDiag) & 0x1e) >> 1;
-       printk(KERN_INFO "  product code %02x%02x rev %02x.%d date %02d-"
-                  "%02d-%02d\n", eeprom[6]&0xff, eeprom[6]>>8, eeprom[0x14],
-                  step, (eeprom[4]>>5) & 15, eeprom[4] & 31, eeprom[4]>>9);
+       if (print_info) {
+               printk(KERN_INFO "  product code %02x%02x rev %02x.%d date 
%02d-"
+                       "%02d-%02d\n", eeprom[6]&0xff, eeprom[6]>>8, 
eeprom[0x14],
+                       step, (eeprom[4]>>5) & 15, eeprom[4] & 31, 
eeprom[4]>>9);
+       }
 
 
        if (pdev && vci->drv_flags & HAS_CB_FNS) {
@@ -1144,8 +1165,10 @@ static int __devinit vortex_probe1(struc
                        if (!vp->cb_fn_base)
                                goto free_ring;
                }
-               printk(KERN_INFO "%s: CardBus functions mapped %8.8lx->%p\n",
-                          print_name, fn_st_addr, vp->cb_fn_base);
+               if (print_info) {
+                       printk(KERN_INFO "%s: CardBus functions mapped 
%8.8lx->%p\n",
+                               dev->name, fn_st_addr, vp->cb_fn_base);
+               }
                EL3WINDOW(2);
 
                n = inw(ioaddr + Wn2_ResetOptions) & ~0x4010;
@@ -1163,7 +1186,8 @@ static int __devinit vortex_probe1(struc
 
        if (vp->info1 & 0x8000) {
                vp->full_duplex = 1;
-               printk(KERN_INFO "Full duplex capable\n");
+               if (print_info)
+                       printk(KERN_INFO "Full duplex capable\n");
        }
 
        {
@@ -1174,16 +1198,17 @@ static int __devinit vortex_probe1(struc
                if ((vp->available_media & 0xff) == 0)          /* Broken 3c916 
*/
                        vp->available_media = 0x40;
                config = inl(ioaddr + Wn3_Config);
-               if (vortex_debug > 1)
+               if (print_info) {
                        printk(KERN_DEBUG "  Internal config register is %4.4x, 
"
                                   "transceivers %#x.\n", config, inw(ioaddr + 
Wn3_Options));
-               printk(KERN_INFO "  %dK %s-wide RAM %s Rx:Tx split, %s%s 
interface.\n",
-                          8 << RAM_SIZE(config),
-                          RAM_WIDTH(config) ? "word" : "byte",
-                          ram_split[RAM_SPLIT(config)],
-                          AUTOSELECT(config) ? "autoselect/" : "",
-                          XCVR(config) > XCVR_ExtMII ? "<invalid transceiver>" 
:
-                          media_tbl[XCVR(config)].name);
+                       printk(KERN_INFO "  %dK %s-wide RAM %s Rx:Tx split, 
%s%s interface.\n",
+                                  8 << RAM_SIZE(config),
+                                  RAM_WIDTH(config) ? "word" : "byte",
+                                  ram_split[RAM_SPLIT(config)],
+                                  AUTOSELECT(config) ? "autoselect/" : "",
+                                  XCVR(config) > XCVR_ExtMII ? "<invalid 
transceiver>" :
+                                  media_tbl[XCVR(config)].name);
+               }
                vp->default_media = XCVR(config);
                if (vp->default_media == XCVR_NWAY)
                        vp->has_nway = 1;
@@ -1191,8 +1216,9 @@ static int __devinit vortex_probe1(struc
        }
 
        if (vp->media_override != 7) {
-               printk(KERN_INFO "  Media override to transceiver type %d 
(%s).\n",
-                          vp->media_override, 
media_tbl[vp->media_override].name);
+               printk(KERN_INFO "%s:  Media override to transceiver type %d 
(%s).\n",
+                               dev->name, vp->media_override,
+                               media_tbl[vp->media_override].name);
                dev->if_port = vp->media_override;
        } else
                dev->if_port = vp->default_media;
@@ -1219,8 +1245,10 @@ static int __devinit vortex_probe1(struc
                        mii_status = mdio_read(dev, phyx, 1);
                        if (mii_status  &&  mii_status != 0xffff) {
                                vp->phys[phy_idx++] = phyx;
-                               printk(KERN_INFO "  MII transceiver found at 
address %d,"
-                                          " status %4x.\n", phyx, mii_status);
+                               if (print_info) {
+                                       printk(KERN_INFO "  MII transceiver 
found at address %d,"
+                                               " status %4x.\n", phyx, 
mii_status);
+                               }
                                if ((mii_status & 0x0040) == 0)
                                        mii_preamble_required++;
                        }
@@ -1244,8 +1272,10 @@ static int __devinit vortex_probe1(struc
 
        if (vp->capabilities & CapBusMaster) {
                vp->full_bus_master_tx = 1;
-               printk(KERN_INFO"  Enabling bus-master transmits and %s 
receives.\n",
-                          (vp->info2 & 1) ? "early" : "whole-frame" );
+               if (print_info) {
+                       printk(KERN_INFO "  Enabling bus-master transmits and 
%s receives.\n",
+                       (vp->info2 & 1) ? "early" : "whole-frame" );
+               }
                vp->full_bus_master_rx = (vp->info2 & 1) ? 1 : 2;
                vp->bus_master = 0;             /* AKPM: vortex only */
        }
@@ -1254,10 +1284,10 @@ static int __devinit vortex_probe1(struc
        dev->open = vortex_open;
        if (vp->full_bus_master_tx) {
                dev->hard_start_xmit = boomerang_start_xmit;
-#ifndef CONFIG_HIGHMEM
-               /* Actually, it still should work with iommu. */
-               dev->features |= NETIF_F_SG;
-#endif
+               if (nr_free_highpages() == 0) {
+                       /* Actually, it still should work with iommu. */
+                       dev->features |= NETIF_F_SG;
+               }
                if (((hw_checksums[card_idx] == -1) && (vp->drv_flags & 
HAS_HWCKSM)) ||
                                        (hw_checksums[card_idx] == 1)) {
                                dev->features |= NETIF_F_IP_CSUM;
@@ -1266,9 +1296,9 @@ static int __devinit vortex_probe1(struc
                dev->hard_start_xmit = vortex_start_xmit;
        }
 
-       if (vortex_debug > 0) {
+       if (print_info) {
                printk(KERN_INFO "%s: scatter/gather %sabled. h/w checksums 
%sabled\n",
-                               print_name,
+                               dev->name,
                                (dev->features & NETIF_F_SG) ? "en":"dis",
                                (dev->features & NETIF_F_IP_CSUM) ? "en":"dis");
        }
@@ -1279,9 +1309,8 @@ static int __devinit vortex_probe1(struc
        dev->set_multicast_list = set_rx_mode;
        dev->tx_timeout = vortex_tx_timeout;
        dev->watchdog_timeo = (watchdog * HZ) / 1000;
-       retval = register_netdev(dev);
-       if (retval == 0)
-               return 0;
+       publish_netdev(dev);
+       return 0;
 
 free_ring:
        pci_free_consistent(pdev,
@@ -1292,6 +1321,7 @@ free_ring:
 free_region:
        if (vp->must_free_region)
                release_region(ioaddr, vci->io_size);
+       unregister_netdev(dev);
        kfree (dev);
        printk(KERN_ERR PFX "vortex_probe1 fails.  Returns %d\n", retval);
 out:
@@ -1345,19 +1375,23 @@ vortex_up(struct net_device *dev)
                dev->if_port = vp->media_override;
        } else if (vp->autoselect) {
                if (vp->has_nway) {
-                       printk(KERN_INFO "%s: using NWAY device table, not 
%d\n", dev->name, dev->if_port);
+                       if (vortex_debug > 1)
+                               printk(KERN_INFO "%s: using NWAY device table, 
not %d\n",
+                                                               dev->name, 
dev->if_port);
                        dev->if_port = XCVR_NWAY;
                } else {
                        /* Find first available media type, starting with 
100baseTx. */
                        dev->if_port = XCVR_100baseTx;
                        while (! (vp->available_media & 
media_tbl[dev->if_port].mask))
                                dev->if_port = media_tbl[dev->if_port].next;
-                       printk(KERN_INFO "%s: first available media type: %s\n",
+                       if (vortex_debug > 1)
+                               printk(KERN_INFO "%s: first available media 
type: %s\n",
                                        dev->name, 
media_tbl[dev->if_port].name);
                }
        } else {
                dev->if_port = vp->default_media;
-               printk(KERN_INFO "%s: using default media %s\n",
+               if (vortex_debug > 1)
+                       printk(KERN_INFO "%s: using default media %s\n",
                                dev->name, media_tbl[dev->if_port].name);
        }
 
--- linux-2.4.6-pre8/drivers/net/starfire.c     Sun Jul  1 16:11:24 2001
+++ linux-akpm/drivers/net/starfire.c   Sun Jul  1 22:01:34 2001
@@ -731,10 +731,6 @@ static int __devinit starfire_init_one(s
        if (mtu)
                dev->mtu = mtu;
 
-       i = register_netdev(dev);
-       if (i)
-               goto err_out_cleardev;
-
        printk(KERN_INFO "%s: %s at 0x%lx, ",
                   dev->name, netdrv_tbl[chip_idx].name, ioaddr);
        for (i = 0; i < 5; i++)
@@ -769,11 +765,9 @@ static int __devinit starfire_init_one(s
                np->phy_cnt = phy_idx;
        }
 
+       publish_netdev(dev);
        return 0;
 
-err_out_cleardev:
-       pci_set_drvdata(pdev, NULL);
-       iounmap((void *)ioaddr);
 err_out_free_res:
        pci_release_regions (pdev);
 err_out_free_netdev:
--- linux-2.4.6-pre8/drivers/net/via-rhine.c    Sun Jul  1 16:11:24 2001
+++ linux-akpm/drivers/net/via-rhine.c  Sun Jul  1 22:01:47 2001
@@ -640,10 +640,6 @@ static int __devinit via_rhine_init_one 
        dev->do_ioctl = mii_ioctl;
        dev->tx_timeout = via_rhine_tx_timeout;
        dev->watchdog_timeo = TX_TIMEOUT;
-       
-       i = register_netdev(dev);
-       if (i)
-               goto err_out_unmap;
 
        printk(KERN_INFO "%s: %s at 0x%lx, ",
                   dev->name, via_rhine_chip_info[chip_id].name, ioaddr);
@@ -694,6 +690,7 @@ static int __devinit via_rhine_init_one 
                }
        }
 
+       publish_netdev(dev);
        return 0;
 
 err_out_unmap:
@@ -703,6 +700,7 @@ err_out_free_res:
 #endif
        pci_release_regions(pdev);
 err_out_free_netdev:
+       unregister_netdev(dev);
        kfree (dev);
 err_out:
        return -ENODEV;
--- linux-2.4.6-pre8/drivers/net/yellowfin.c    Sun Jul  1 16:11:25 2001
+++ linux-akpm/drivers/net/yellowfin.c  Sun Jul  1 22:01:56 2001
@@ -496,10 +496,6 @@ static int __devinit yellowfin_init_one(
        if (mtu)
                dev->mtu = mtu;
 
-       i = register_netdev(dev);
-       if (i)
-               goto err_out_cleardev;
-
        printk(KERN_INFO "%s: %s type %8x at 0x%lx, ",
                   dev->name, pci_id_tbl[chip_idx].name, inl(ioaddr + ChipRev), 
ioaddr);
        for (i = 0; i < 5; i++)
@@ -523,6 +519,7 @@ static int __devinit yellowfin_init_one(
 
        find_cnt++;
        
+       publish_netdev(dev);
        return 0;
 
 err_out_cleardev:
@@ -533,6 +530,7 @@ err_out_free_res:
 #endif
        pci_release_regions(pdev);
 err_out_free_netdev:
+       unregister_netdev(dev);
        kfree (dev);
        return -ENODEV;
 }
--- linux-2.4.6-pre8/drivers/net/sis900.c       Sun Jul  1 16:11:24 2001
+++ linux-akpm/drivers/net/sis900.c     Sun Jul  1 22:02:04 2001
@@ -362,10 +362,6 @@ static int __devinit sis900_probe (struc
        net_dev->do_ioctl = &mii_ioctl;
        net_dev->tx_timeout = sis900_tx_timeout;
        net_dev->watchdog_timeo = TX_TIMEOUT;
-       
-       ret = register_netdev(net_dev);
-       if (ret)
-               goto err_out_cleardev;
                
        /* Get Mac address according to the chip revision */
        pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &revision);
@@ -380,13 +376,13 @@ static int __devinit sis900_probe (struc
 
        if (ret == 0) {
                ret = -ENODEV;
-               goto err_out_unregister;
+               goto err_out_cleardev;
        }
 
        /* probe for mii transciver */
        if (sis900_mii_probe(net_dev) == 0) {
                ret = -ENODEV;
-               goto err_out_unregister;
+               goto err_out_cleardev;
        }
 
        /* print some information about our NIC */
@@ -396,14 +392,14 @@ static int __devinit sis900_probe (struc
                printk("%2.2x:", (u8)net_dev->dev_addr[i]);
        printk("%2.2x.\n", net_dev->dev_addr[i]);
 
+       publish_netdev(net_dev);
        return 0;
 
- err_out_unregister:
-       unregister_netdev(net_dev);
  err_out_cleardev:
        pci_set_drvdata(pci_dev, NULL);
        pci_release_regions(pci_dev);
  err_out:
+       unregister_netdev(net_dev);
        kfree(net_dev);
        return ret;
 }
--- linux-2.4.6-pre8/drivers/net/epic100.c      Sun Jul  1 16:11:24 2001
+++ linux-akpm/drivers/net/epic100.c    Sun Jul  1 22:02:10 2001
@@ -520,16 +520,13 @@ static int __devinit epic_init_one (stru
        dev->watchdog_timeo = TX_TIMEOUT;
        dev->tx_timeout = &epic_tx_timeout;
 
-       i = register_netdev(dev);
-       if (i)
-               goto err_out_unmap_tx;
-
        printk(KERN_INFO "%s: %s at %#lx, IRQ %d, ",
                   dev->name, pci_id_tbl[chip_idx].name, ioaddr, dev->irq);
        for (i = 0; i < 5; i++)
                printk("%2.2x:", dev->dev_addr[i]);
        printk("%2.2x.\n", dev->dev_addr[i]);
 
+       publish_netdev(dev);
        return 0;
 
 err_out_unmap_tx:
@@ -541,6 +538,7 @@ err_out_free_res:
 #endif
        pci_release_regions(pdev);
 err_out_free_netdev:
+       unregister_netdev(dev);
        kfree(dev);
        return -ENODEV;
 }
--- linux-2.4.6-pre8/drivers/net/ne2k-pci.c     Sun Jul  1 16:11:24 2001
+++ linux-akpm/drivers/net/ne2k-pci.c   Sun Jul  1 22:02:16 2001
@@ -361,10 +361,6 @@ static int __devinit ne2k_pci_init_one (
        dev->do_ioctl = &netdev_ioctl;
        NS8390_init(dev, 0);
 
-       i = register_netdev(dev);
-       if (i)
-               goto err_out_free_8390;
-
        printk("%s: %s found at %#lx, IRQ %d, ",
                   dev->name, pci_clone_list[chip_idx].name, ioaddr, dev->irq);
        for(i = 0; i < 6; i++) {
@@ -372,11 +368,13 @@ static int __devinit ne2k_pci_init_one (
                dev->dev_addr[i] = SA_prom[i];
        }
 
+       publish_netdev(dev);
        return 0;
 
 err_out_free_8390:
        kfree(dev->priv);
 err_out_free_netdev:
+       unregister_netdev(dev);
        kfree (dev);
 err_out_free_res:
        release_region (ioaddr, NE_IO_EXTENT);
--- linux-2.4.6-pre8/drivers/net/dmfe.c Sun Jul  1 16:11:24 2001
+++ linux-akpm/drivers/net/dmfe.c       Sun Jul  1 22:02:22 2001
@@ -496,9 +496,6 @@ static int __devinit dmfe_init_one (stru
        for (i = 0; i < 6; i++)
                dev->dev_addr[i] = db->srom[20 + i];
 
-       i = register_netdev (dev);
-       if (i) goto err_out;
-
        printk(KERN_INFO "%s: Davicom DM%04lx at 0x%lx,",
               dev->name,
               ent->driver_data >> 16,
@@ -507,10 +504,12 @@ static int __devinit dmfe_init_one (stru
                printk("%c%02x", i ? ':' : ' ', dev->dev_addr[i]);
        printk(", IRQ %d\n", pci_irqline);
 
+       publish_netdev (dev);
        return 0;
 
 err_out:
        pci_set_drvdata(pdev, NULL);
+       unregister_netdev(dev);
        kfree(dev);
        return -ENODEV;
 }
--- linux-2.4.6-pre8/drivers/net/8139too.c      Sun Jul  1 16:11:24 2001
+++ linux-akpm/drivers/net/8139too.c    Sun Jul  1 23:29:00 2001
@@ -898,6 +898,7 @@ match:
        return 0;
 
 err_out:
+       unregister_netdev(dev);
        __rtl8139_cleanup_dev (dev);
        DPRINTK ("EXIT, returning %d\n", rc);
        return rc;
@@ -971,11 +972,6 @@ static int __devinit rtl8139_init_one (s
        init_waitqueue_head (&tp->thr_wait);
        init_MUTEX_LOCKED (&tp->thr_exited);
 
-       /* dev is fully set up and ready to use now */
-       DPRINTK("about to register device named %s (%p)...\n", dev->name, dev);
-       i = register_netdev (dev);
-       if (i) goto err_out;
-
        pci_set_drvdata (pdev, dev);
 
        printk (KERN_INFO "%s: %s at 0x%lx, "
@@ -1047,10 +1043,13 @@ static int __devinit rtl8139_init_one (s
        if (rtl_chip_info[tp->chipset].flags & HasHltClk)
                RTL_W8 (HltClk, 'H');   /* 'R' would leave the clock running. */
 
+       /* dev is fully set up and ready to use now */
+       DPRINTK("about to publish device named %s (%p)...\n", dev->name, dev);
+       publish_netdev (dev);
+
        DPRINTK ("EXIT - returning 0\n");
        return 0;
 
-err_out:
        __rtl8139_cleanup_dev (dev);
        DPRINTK ("EXIT - returning %d\n", i);
        return i;
--- linux-2.4.6-pre8/drivers/net/tulip/tulip_core.c     Sun Jul  1 16:11:24 2001
+++ linux-akpm/drivers/net/tulip/tulip_core.c   Sun Jul  1 22:14:18 2001
@@ -1253,7 +1253,7 @@ static void __devinit tulip_mwi_config (
        if (tulip_debug > 3)
                printk(KERN_DEBUG "%s: tulip_mwi_config()\n", pdev->slot_name);
 
-       tp->csr0 = 0;
+       tp->csr0 = csr0 = 0;
 
        /* check for sane cache line size. from acenic.c. */
        pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &cache);
@@ -1314,7 +1314,6 @@ static void __devinit tulip_mwi_config (
        tp->csr0 = csr0;
        goto out;
        
-early_out:
        if (csr0 & MWI) {
                pci_command &= ~PCI_COMMAND_INVALIDATE;
                pci_write_config_word(pdev, PCI_COMMAND, pci_command);
@@ -1657,9 +1656,6 @@ static int __devinit tulip_init_one (str
        dev->do_ioctl = private_ioctl;
        dev->set_multicast_list = set_rx_mode;
 
-       if (register_netdev(dev))
-               goto err_out_free_ring;
-
        printk(KERN_INFO "%s: %s rev %d at %#3lx,",
               dev->name, tulip_tbl[chip_idx].chip_name, chip_rev, ioaddr);
        pci_set_drvdata(pdev, dev);
@@ -1742,6 +1738,7 @@ static int __devinit tulip_init_one (str
        /* put the chip in snooze mode until opened */
        tulip_set_power_state (tp, 0, 1);
 
+       publish_netdev(dev);
        return 0;
 
 err_out_free_ring:
@@ -1761,6 +1758,7 @@ err_out_free_res:
        pci_release_regions (pdev);
 
 err_out_free_netdev:
+       unregister_netdev(dev);
        kfree (dev);
        return -ENODEV;
 }
--- linux-2.4.6-pre8/drivers/net/tulip/ChangeLog        Sun Jul  1 16:11:24 2001
+++ linux-akpm/drivers/net/tulip/ChangeLog      Sun Jul  1 21:50:24 2001
@@ -1,3 +1,9 @@
+2001-07-01  Andrew Morton <andrewm@xxxxxxxxxx>
+
+        * tulip_core.c:
+       Use new publish_netdev() API.
+       Only publish the device after all initialisation has completed.
+
 2001-06-16  Jeff Garzik  <jgarzik@xxxxxxxxxxxxxxxx>
 
        * tulip.h, tulip_core.c:
--- linux-2.4.6-pre8/drivers/net/pcmcia/xircom_tulip_cb.c       Sun Jul  1 
16:11:24 2001
+++ linux-akpm/drivers/net/pcmcia/xircom_tulip_cb.c     Sun Jul  1 22:03:40 2001
@@ -765,15 +765,6 @@ static struct net_device *tulip_probe1(s
                break;
        }
 
-       if (register_netdev(dev)) {
-               request_region(ioaddr, tulip_tbl[chip_idx].io_size, 
"xircom_tulip_cb");
-               if (tp->mtable)
-                       kfree(tp->mtable);
-               kfree(dev->priv);
-               kfree(dev);
-               return NULL;
-       }
-
        printk(KERN_INFO "%s: %s rev %d at %#3lx,",
               dev->name, tulip_tbl[chip_idx].chip_name, chip_rev, ioaddr);
        for (i = 0; i < 6; i++)
@@ -781,6 +772,7 @@ static struct net_device *tulip_probe1(s
                       last_phys_addr[i] = dev->dev_addr[i]);
        printk(", IRQ %d.\n", irq);
 
+       publish_netdev(dev);
        return dev;
 }
 
--- linux-2.4.6-pre8/drivers/net/sundance.c     Sun Jul  1 16:11:24 2001
+++ linux-akpm/drivers/net/sundance.c   Sun Jul  1 22:25:21 2001
@@ -470,10 +470,6 @@ static int __devinit sundance_probe1 (st
        if (mtu)
                dev->mtu = mtu;
 
-       i = register_netdev(dev);
-       if (i)
-               goto err_out_cleardev;
-
        printk(KERN_INFO "%s: %s at 0x%lx, ",
                   dev->name, pci_id_tbl[chip_idx].name, ioaddr);
        for (i = 0; i < 5; i++)
@@ -508,16 +504,16 @@ static int __devinit sundance_probe1 (st
                printk("ASIC Control is now %x.\n", readl(ioaddr + ASICCtrl));
 
        card_idx++;
+       publish_netdev(dev);
        return 0;
 
-err_out_cleardev:
-       pci_set_drvdata(pdev, NULL);
 #ifndef USE_IO_OPS
        iounmap((void *)ioaddr);
 err_out_res:
 #endif
        pci_release_regions(pdev);
 err_out_netdev:
+       unregister_netdev(dev);
        kfree (dev);
        return -ENODEV;
 }
--- linux-2.4.6-pre8/drivers/net/hamachi.c      Sun Jul  1 16:11:24 2001
+++ linux-akpm/drivers/net/hamachi.c    Sun Jul  1 21:53:50 2001
@@ -712,15 +712,6 @@ static int __init hamachi_init_one (stru
        if (mtu)
                dev->mtu = mtu;
 
-       i = register_netdev(dev);
-       if (i) {
-               kfree(dev);
-               iounmap((char *)ioaddr);
-               pci_release_regions(pdev);
-               pci_set_drvdata(pdev, NULL);
-               return i;
-       }
-
        printk(KERN_INFO "%s: %s type %x at 0x%lx, ",
                   dev->name, chip_tbl[chip_id].name, readl(ioaddr + ChipRev),
                   ioaddr);
@@ -755,6 +746,7 @@ static int __init hamachi_init_one (stru
        writew(0x1000, ioaddr + ANCtrl);                        /* Enable 
negotiation */
 
        card_idx++;
+       publish_netdev(dev);
        return 0;
 }
 
--- linux-2.4.6-pre8/drivers/net/natsemi.c      Sun Jul  1 16:11:24 2001
+++ linux-akpm/drivers/net/natsemi.c    Sun Jul  1 21:56:15 2001
@@ -457,18 +457,13 @@ static int __devinit natsemi_probe1 (str
        SET_MODULE_OWNER(dev);
 
        i = pci_request_regions(pdev, dev->name);
-       if (i) {
-               kfree(dev);
-               return i;
-       }
+       if (i)
+               goto out_release_dev;
 
        {
                void *mmio = ioremap (ioaddr, iosize);
-               if (!mmio) {
-                       pci_release_regions(pdev);
-                       kfree(dev);
-                       return -ENOMEM;
-               }
+               if (!mmio)
+                       goto out_release_regions;
                ioaddr = (unsigned long) mmio;
        }
 
@@ -521,15 +516,6 @@ static int __devinit natsemi_probe1 (str
        if (mtu)
                dev->mtu = mtu;
 
-       i = register_netdev(dev);
-       if (i) {
-               pci_release_regions(pdev);
-               unregister_netdev(dev);
-               kfree(dev);
-               pci_set_drvdata(pdev, NULL);
-               return i;
-       }
-
        printk(KERN_INFO "%s: %s at 0x%lx, ",
                   dev->name, natsemi_pci_info[chip_idx].name, ioaddr);
        for (i = 0; i < ETH_ALEN-1; i++)
@@ -548,8 +534,13 @@ static int __devinit natsemi_probe1 (str
        }
        printk(KERN_INFO "%s: Transceiver status 0x%4.4x advertising %4.4x.\n",
                   dev->name, (int)readl(ioaddr + 0x84), np->advertising);
-
+       publish_netdev(dev);
        return 0;
+out_release_regions:
+       pci_release_regions(pdev);
+out_release_dev:
+       kfree(dev);
+       return -ENOMEM;
 }
 
 
--- linux-2.4.6-pre8/drivers/net/winbond-840.c  Sun Jul  1 16:11:24 2001
+++ linux-akpm/drivers/net/winbond-840.c        Sun Jul  1 22:24:52 2001
@@ -470,10 +470,6 @@ static int __devinit w840_probe1 (struct
        dev->tx_timeout = &tx_timeout;
        dev->watchdog_timeo = TX_TIMEOUT;
 
-       i = register_netdev(dev);
-       if (i)
-               goto err_out_cleardev;
-
        printk(KERN_INFO "%s: %s at 0x%lx, ",
                   dev->name, pci_id_tbl[chip_idx].name, ioaddr);
        for (i = 0; i < 5; i++)
@@ -500,16 +496,16 @@ static int __devinit w840_probe1 (struct
        }
 
        find_cnt++;
+       publish_netdev(dev);
        return 0;
 
-err_out_cleardev:
-       pci_set_drvdata(pdev, NULL);
 #ifndef USE_IO_OPS
        iounmap((void *)ioaddr);
 err_out_free_res:
 #endif
        pci_release_regions(pdev);
 err_out_netdev:
+       unregister_netdev(dev);
        kfree (dev);
        return -ENODEV;
 }
--- linux-2.4.6-pre8/drivers/net/pci-skeleton.c Sun Jul  1 16:11:24 2001
+++ linux-akpm/drivers/net/pci-skeleton.c       Sun Jul  1 21:57:47 2001
@@ -710,13 +710,10 @@ match:
                tp->chipset,
                rtl_chip_info[tp->chipset].name);
 
-       i = register_netdev (dev);
-       if (i)
-               goto err_out_unmap;
-
        DPRINTK ("EXIT, returning 0\n");
        *ioaddr_out = ioaddr;
        *dev_out = dev;
+       publish_netdev (dev);
        return 0;
 
 err_out_unmap:
@@ -726,6 +723,7 @@ err_out_free_res:
 #endif
        pci_release_regions (pdev);
 err_out:
+       unregister_netdev(dev);
        kfree (dev);
        DPRINTK ("EXIT, returning %d\n", rc);
        return rc;
--- linux-2.4.6-pre8/drivers/net/fealnx.c       Sun Jul  1 16:11:24 2001
+++ linux-akpm/drivers/net/fealnx.c     Sun Jul  1 22:20:56 2001
@@ -650,23 +650,20 @@ static int __devinit fealnx_init_one(str
        dev->tx_timeout = tx_timeout;
        dev->watchdog_timeo = TX_TIMEOUT;
        
-       err = register_netdev(dev);
-       if (err)
-               goto err_out_free_tx;
-
        printk(KERN_INFO "%s: %s at 0x%lx, ",
               dev->name, skel_netdrv_tbl[chip_id].chip_name, ioaddr);
        for (i = 0; i < 5; i++)
                printk("%2.2x:", dev->dev_addr[i]);
        printk("%2.2x, IRQ %d.\n", dev->dev_addr[i], irq);
 
+       publish_netdev(dev);
        return 0;
 
-err_out_free_tx:
        pci_free_consistent(pdev, TX_TOTAL_SIZE, np->tx_ring, np->tx_ring_dma);
 err_out_free_rx:
        pci_free_consistent(pdev, RX_TOTAL_SIZE, np->rx_ring, np->rx_ring_dma);
 err_out_free_dev:
+       unregister_netdev(dev);
        kfree(dev);
 err_out_unmap:
 #ifndef USE_IO_OPS
@@ -1808,7 +1805,7 @@ static int netdev_close(struct net_devic
        return 0;
 }
 
-static struct pci_device_id fealnx_pci_tbl[] = __devinitdata {
+static struct pci_device_id fealnx_pci_tbl[] __devinitdata = {
        {0x1516, 0x0800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
        {0x1516, 0x0803, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
        {0x1516, 0x0891, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2},
--- linux-2.4.6-pre8/drivers/net/wireless/airo.c        Sun Jul  1 16:11:24 2001
+++ linux-akpm/drivers/net/wireless/airo.c      Sun Jul  1 22:01:09 2001
@@ -1024,6 +1024,7 @@ struct net_device *init_airo_card( unsig
                printk(KERN_ERR "airo:  Couldn't alloc_etherdev\n");
                return NULL;
         }
+       SET_MODULE_OWNER(dev);
        ai = dev->priv;
        ai->registered = 1;
         ai->dev = dev;
@@ -1051,15 +1052,11 @@ struct net_device *init_airo_card( unsig
        dev->irq = irq;
        dev->base_addr = port;
        
-       rc = register_netdev(dev);
-       if (rc)
-               goto err_out_unlink;
-       
        rc = request_irq( dev->irq, airo_interrupt, 
                          SA_SHIRQ | SA_INTERRUPT, dev->name, dev );
        if (rc) {
                printk(KERN_ERR "airo: register interrupt %d failed, rc %d\n", 
irq, rc );
-               goto err_out_unregister;
+               goto err_out_unlink;
        }
        if (!is_pcmcia) {
                if (!request_region( dev->base_addr, 64, dev->name )) {
@@ -1085,7 +1082,7 @@ struct net_device *init_airo_card( unsig
 
        setup_proc_entry( dev, dev->priv ); /* XXX check for failure */
        netif_start_queue(dev);
-       SET_MODULE_OWNER(dev);
+       publish_netdev(dev);
        return dev;
 
 err_out_res:
@@ -1093,11 +1090,10 @@ err_out_res:
                release_region( dev->base_addr, 64 );
 err_out_irq:
        free_irq(dev->irq, dev);
-err_out_unregister:
-       unregister_netdev(dev);
 err_out_unlink:
        del_airo_dev(dev);
 err_out_free:
+       unregister_netdev(dev);
        kfree(dev);
        return NULL;
 }
--- linux-2.4.6-pre8/drivers/net/tokenring/olympic.c    Sun Jul  1 16:11:24 2001
+++ linux-akpm/drivers/net/tokenring/olympic.c  Sun Jul  1 22:06:24 2001
@@ -51,6 +51,8 @@
  * 
  * 06/02/01 - Clean up, copy skb for small packets
  *
+ * 07/01/01 - Use publish_netdev() (andrewm@xxxxxxxxxx)
+ *
  *  To Do:
  *
  *          Complete full Cardbus / hot-swap support.
@@ -235,6 +237,7 @@ static int __devinit olympic_probe(struc
        if((i = olympic_init(dev))) {
                iounmap(olympic_priv->olympic_mmio) ; 
                iounmap(olympic_priv->olympic_lap) ; 
+               unregister_netdev(dev) ;
                kfree(dev) ; 
                pci_release_regions(pdev) ; 
                return i ; 
@@ -251,7 +254,6 @@ static int __devinit olympic_probe(struc
        SET_MODULE_OWNER(dev) ; 
 
        pci_set_drvdata(pdev,dev) ; 
-       register_netdev(dev) ; 
        printk("Olympic: %s registered as: 
%s\n",olympic_priv->olympic_card_name,dev->name);
        if (olympic_priv->olympic_network_monitor) { /* Must go after 
register_netdev as we need the device name */ 
                char proc_name[20] ; 
@@ -260,6 +262,7 @@ static int __devinit olympic_probe(struc
                create_proc_read_entry(proc_name,0,0,olympic_proc_info,(void 
*)dev) ; 
                printk("Olympic: Network Monitor information: 
/proc/%s\n",proc_name); 
        }
+       publish_netdev(dev);
        return  0 ;
 }
 
--- linux-2.4.6-pre8/Documentation/networking/vortex.txt        Sun Jul  1 
16:11:21 2001
+++ linux-akpm/Documentation/networking/vortex.txt      Fri Jun 29 13:26:54 2001
@@ -104,6 +104,8 @@ options=N1,N2,N3,...
   When generating a value for the 'options' setting, the above media
   selection values may be OR'ed (or added to) the following:
 
+  2048 (0x800)  Set driver debugging level to 7
+  1024 (0x400)  Set driver debugging level to 2
   512  (0x200) Force full duplex mode.
   16   (0x10)  Bus-master enable bit (Old Vortex cards only)

<Prev in Thread] Current Thread [Next in Thread>