patch-2.3.27 linux/drivers/net/net_init.c
Next file: linux/drivers/net/pcmcia/3c574_cs.c
Previous file: linux/drivers/net/ne2k-pci.c
Back to the patch index
Back to the overall index
- Lines: 622
- Date:
Tue Nov 9 08:23:04 1999
- Orig file:
v2.3.26/linux/drivers/net/net_init.c
- Orig date:
Tue Aug 31 17:29:14 1999
diff -u --recursive --new-file v2.3.26/linux/drivers/net/net_init.c linux/drivers/net/net_init.c
@@ -23,6 +23,10 @@
14/06/96 - Paul Gortmaker: Add generic eth_change_mtu() function.
24/09/96 - Paul Norton: Add token-ring variants of the netdev functions.
+
+ 08/11/99 - Alan Cox: Got fed up of the mess in this file and cleaned it
+ up. We now share common code and have regularised name
+ allocation setups. Abolished the 16 card limits.
*/
#include <linux/config.h>
@@ -61,79 +65,66 @@
and a space waste]
*/
-/* The list of used and available "eth" slots (for "eth0", "eth1", etc.) */
-#define MAX_ETH_CARDS 16
-static struct net_device *ethdev_index[MAX_ETH_CARDS];
-
-/* Fill in the fields of the device structure with ethernet-generic values.
-
- If no device structure is passed, a new one is constructed, complete with
- a SIZEOF_PRIVATE private data area.
+static struct net_device *init_alloc_dev(int sizeof_priv)
+{
+ struct net_device *dev;
+ int alloc_size = sizeof(struct net_device) + IFNAMSIZ
+ + sizeof_priv + 3;
+ alloc_size &= ~3; /* Round to dword boundary. */
+ 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;
+ }
+ memset(dev, 0, alloc_size);
+ if (sizeof_priv)
+ dev->priv = (void *) (dev + 1);
+ dev->name = sizeof_priv + (char *)(dev + 1);
+ return dev;
+}
- If an empty string area is passed as dev->name, or a new structure is made,
- a new name string is constructed. The passed string area should be 8 bytes
- long.
+/*
+ * Create and name a device from a prototype, then perform any needed
+ * setup.
*/
-struct net_device *
-init_etherdev(struct net_device *dev, int sizeof_priv)
+static struct net_device *init_netdev(struct net_device *dev, int sizeof_priv, char *mask, void (*setup)(struct net_device *))
{
int new_device = 0;
- int i;
- /* Use an existing correctly named device in Space.c:dev_base. */
+ /*
+ * Allocate a device if one is not provided.
+ */
+
if (dev == NULL) {
- int alloc_size = sizeof(struct net_device) + IFNAMSIZ
- + sizeof_priv + 3;
- struct net_device *cur_dev;
- char pname[8]; /* Putative name for the device. */
-
- for (i = 0; i < MAX_ETH_CARDS; ++i)
- if (ethdev_index[i] == NULL) {
- sprintf(pname, "eth%d", i);
- read_lock_bh(&dev_base_lock);
- for (cur_dev = dev_base; cur_dev; cur_dev = cur_dev->next) {
- if (strcmp(pname, cur_dev->name) == 0) {
- dev = cur_dev;
- read_unlock_bh(&dev_base_lock);
- dev->init = NULL;
- sizeof_priv = (sizeof_priv + 3) & ~3;
- dev->priv = sizeof_priv
- ? kmalloc(sizeof_priv, GFP_KERNEL)
- : NULL;
- if (dev->priv) memset(dev->priv, 0, sizeof_priv);
- goto found;
- }
- }
- read_unlock_bh(&dev_base_lock);
- }
-
- alloc_size &= ~3; /* Round to dword boundary. */
-
- dev = (struct net_device *)kmalloc(alloc_size, GFP_KERNEL);
+ dev=init_alloc_dev(sizeof_priv);
if(dev==NULL)
return NULL;
- memset(dev, 0, alloc_size);
- if (sizeof_priv)
- dev->priv = (void *) (dev + 1);
- dev->name = sizeof_priv + (char *)(dev + 1);
new_device = 1;
}
-found: /* From the double loop above. */
-
- if (dev->name &&
- ((dev->name[0] == '\0') || (dev->name[0] == ' '))) {
- for (i = 0; i < MAX_ETH_CARDS; ++i)
- if (ethdev_index[i] == NULL) {
- sprintf(dev->name, "eth%d", i);
- ethdev_index[i] = dev;
- break;
- }
+ /*
+ * Allocate a name
+ */
+
+ if (dev->name && (dev->name[0] == '\0' || dev->name[0] == ' '))
+ {
+ if(dev_alloc_name(dev, mask)<0)
+ {
+ if(new_device)
+ kfree(dev);
+ return NULL;
+ }
}
-
- ether_setup(dev); /* Hmmm, should this be called here? */
+
+ /*
+ * Configure via the caller provided setup function then
+ * register if needed.
+ */
+
+ setup(dev);
if (new_device) {
rtnl_lock();
@@ -143,6 +134,21 @@
return dev;
}
+/* Fill in the fields of the device structure with ethernet-generic values.
+
+ If no device structure is passed, a new one is constructed, complete with
+ a SIZEOF_PRIVATE private data area.
+
+ If an empty string area is passed as dev->name, or a new structure is made,
+ a new name string is constructed. The passed string area should be 8 bytes
+ long.
+ */
+
+struct net_device *init_etherdev(struct net_device *dev, int sizeof_priv)
+{
+ return init_netdev(dev, sizeof_priv, "eth%d", ether_setup);
+}
+
static int eth_mac_addr(struct net_device *dev, void *p)
{
@@ -174,8 +180,6 @@
#endif
#ifdef CONFIG_HIPPI
-#define MAX_HIP_CARDS 4
-static struct net_device *hipdev_index[MAX_HIP_CARDS];
static int hippi_change_mtu(struct net_device *dev, int new_mtu)
{
@@ -205,82 +209,14 @@
struct net_device *init_hippi_dev(struct net_device *dev, int sizeof_priv)
{
- int new_device = 0;
- int i;
-
- /* Use an existing correctly named device in Space.c:dev_base. */
- if (dev == NULL) {
- int alloc_size = sizeof(struct net_device) + IFNAMSIZ
- + sizeof_priv + 3;
- struct net_device *cur_dev;
- char pname[8];
-
- for (i = 0; i < MAX_HIP_CARDS; ++i)
- if (hipdev_index[i] == NULL) {
- sprintf(pname, "hip%d", i);
- read_lock_bh(&dev_base_lock);
- for (cur_dev = dev_base; cur_dev; cur_dev = cur_dev->next) {
- if (strcmp(pname, cur_dev->name) == 0) {
- dev = cur_dev;
- read_unlock_bh(&dev_base_lock);
- dev->init = NULL;
- sizeof_priv = (sizeof_priv + 3) & ~3;
- dev->priv = sizeof_priv
- ? kmalloc(sizeof_priv, GFP_KERNEL)
- : NULL;
- if (dev->priv) memset(dev->priv, 0, sizeof_priv);
- goto hipfound;
- }
- }
- read_unlock_bh(&dev_base_lock);
- }
-
- alloc_size &= ~3; /* Round to dword boundary. */
-
- dev = (struct net_device *)kmalloc(alloc_size, GFP_KERNEL);
- if(dev==NULL)
- return NULL;
- memset(dev, 0, alloc_size);
- if (sizeof_priv)
- dev->priv = (void *) (dev + 1);
- dev->name = sizeof_priv + (char *)(dev + 1);
- new_device = 1;
- }
-
-hipfound: /* From the double loop above. */
-
- if (dev->name &&
- ((dev->name[0] == '\0') || (dev->name[0] == ' '))) {
- for (i = 0; i < MAX_HIP_CARDS; ++i)
- if (hipdev_index[i] == NULL) {
- sprintf(dev->name, "hip%d", i);
- hipdev_index[i] = dev;
- break;
- }
- }
-
- hippi_setup(dev);
-
- if (new_device) {
- rtnl_lock();
- register_netdevice(dev);
- rtnl_unlock();
- }
- return dev;
+ return init_netdev(dev, sizeof_priv, "hip%d", hippi_setup);
}
void unregister_hipdev(struct net_device *dev)
{
- int i;
rtnl_lock();
unregister_netdevice(dev);
- for (i = 0; i < MAX_HIP_CARDS; ++i) {
- if (hipdev_index[i] == dev) {
- hipdev_index[i] = NULL;
- break;
- }
- }
rtnl_unlock();
}
@@ -303,23 +239,9 @@
void ether_setup(struct net_device *dev)
{
- int i;
/* Fill in the fields of the device structure with ethernet-generic values.
This should be in a common file instead of per-driver. */
- /* register boot-defined "eth" devices */
- if (dev->name && (strncmp(dev->name, "eth", 3) == 0)) {
- i = simple_strtoul(dev->name + 3, NULL, 0);
- if (ethdev_index[i] == NULL) {
- ethdev_index[i] = dev;
- }
- else if (dev != ethdev_index[i]) {
- /* Really shouldn't happen! */
- printk("ether_setup: Ouch! Someone else took %s\n",
- dev->name);
- }
- }
-
dev->change_mtu = eth_change_mtu;
dev->hard_header = eth_header;
dev->rebuild_header = eth_rebuild_header;
@@ -376,19 +298,6 @@
#ifdef CONFIG_HIPPI
void hippi_setup(struct net_device *dev)
{
- int i;
-
- if (dev->name && (strncmp(dev->name, "hip", 3) == 0)) {
- i = simple_strtoul(dev->name + 3, NULL, 0);
- if (hipdev_index[i] == NULL) {
- hipdev_index[i] = dev;
- }
- else if (dev != hipdev_index[i]) {
- printk("hippi_setup: Ouch! Someone else took %s\n",
- dev->name);
- }
- }
-
dev->set_multicast_list = NULL;
dev->change_mtu = hippi_change_mtu;
dev->hard_header = hippi_header;
@@ -478,45 +387,33 @@
return 0;
}
-static int etherdev_get_index(struct net_device *dev)
-{
- int i=MAX_ETH_CARDS;
-
- for (i = 0; i < MAX_ETH_CARDS; ++i) {
- if (ethdev_index[i] == NULL) {
- sprintf(dev->name, "eth%d", i);
-/* printk("loading device '%s'...\n", dev->name);*/
- ethdev_index[i] = dev;
- return i;
- }
- }
- return -1;
-}
-
-static void etherdev_put_index(struct net_device *dev)
-{
- int i;
- for (i = 0; i < MAX_ETH_CARDS; ++i) {
- if (ethdev_index[i] == dev) {
- ethdev_index[i] = NULL;
- break;
- }
- }
-}
-
int register_netdev(struct net_device *dev)
{
- int i=-1;
-
rtnl_lock();
- if (dev->name &&
- (dev->name[0] == '\0' || dev->name[0] == ' '))
- i = etherdev_get_index(dev);
-
+ /*
+ * If the name is a format string the caller wants us to
+ * do a name allocation
+ */
+
+ if (dev->name && strchr(dev->name, '%'))
+ {
+ if(dev_alloc_name(dev, dev->name)<0)
+ return -EBUSY;
+ }
+
+ /*
+ * Back compatibility hook. Kill this one in 2.5
+ */
+
+ if (dev->name && (dev->name[0]==0 || dev->name[0]==' '))
+ {
+ if(dev_alloc_name(dev, "eth%d")<0)
+ return -EBUSY;
+ }
+
+
if (register_netdevice(dev)) {
- if (i >= 0)
- etherdev_put_index(dev);
rtnl_unlock();
return -EIO;
}
@@ -528,120 +425,40 @@
{
rtnl_lock();
unregister_netdevice(dev);
- etherdev_put_index(dev);
rtnl_unlock();
}
#ifdef CONFIG_TR
-/* The list of used and available "tr" slots */
-#define MAX_TR_CARDS 16
-static struct net_device *trdev_index[MAX_TR_CARDS];
-struct net_device *init_trdev(struct net_device *dev, int sizeof_priv)
+static void tr_configure(struct net_device *dev)
{
- int new_device = 0;
- int i;
-
- /* Use an existing correctly named device in Space.c:dev_base. */
- if (dev == NULL) {
- int alloc_size = sizeof(struct net_device) + IFNAMSIZ
- + sizeof_priv + 3;
- struct net_device *cur_dev;
- char pname[8]; /* Putative name for the device. */
-
- for (i = 0; i < MAX_TR_CARDS; ++i)
- if (trdev_index[i] == NULL) {
- sprintf(pname, "tr%d", i);
- read_lock_bh(&dev_base_lock);
- for (cur_dev = dev_base; cur_dev; cur_dev = cur_dev->next) {
- if (strcmp(pname, cur_dev->name) == 0) {
- dev = cur_dev;
- read_unlock_bh(&dev_base_lock);
- dev->init = NULL;
- sizeof_priv = (sizeof_priv + 3) & ~3;
- dev->priv = sizeof_priv
- ? kmalloc(sizeof_priv, GFP_KERNEL)
- : NULL;
- if (dev->priv) memset(dev->priv, 0, sizeof_priv);
- goto trfound;
- }
- }
- read_unlock_bh(&dev_base_lock);
- }
-
- alloc_size &= ~3; /* Round to dword boundary. */
- dev = (struct net_device *)kmalloc(alloc_size, GFP_KERNEL);
- if(dev==NULL)
- return NULL;
- memset(dev, 0, alloc_size);
- if (sizeof_priv)
- dev->priv = (void *) (dev + 1);
- dev->name = sizeof_priv + (char *)(dev + 1);
- new_device = 1;
- }
-
-trfound: /* From the double loop above. */
-
- for (i = 0; i < MAX_TR_CARDS; ++i)
- if (trdev_index[i] == NULL) {
- sprintf(dev->name, "tr%d", i);
- trdev_index[i] = dev;
- break;
- }
-
-
- dev->hard_header = tr_header;
- dev->rebuild_header = tr_rebuild_header;
+ /*
+ * Configure and register
+ */
+
+ dev->hard_header = tr_header;
+ dev->rebuild_header = tr_rebuild_header;
- dev->type = ARPHRD_IEEE802;
- dev->hard_header_len = TR_HLEN;
- dev->mtu = 2000; /* bug in fragmenter...*/
- dev->addr_len = TR_ALEN;
- dev->tx_queue_len = 100; /* Long queues on tr */
+ dev->type = ARPHRD_IEEE802_TR;
+ dev->hard_header_len = TR_HLEN;
+ dev->mtu = 2000;
+ dev->addr_len = TR_ALEN;
+ dev->tx_queue_len = 100; /* Long queues on tr */
memset(dev->broadcast,0xFF, TR_ALEN);
/* New-style flags. */
- dev->flags = IFF_BROADCAST;
-
- if (new_device) {
- rtnl_lock();
- register_netdevice(dev);
- rtnl_unlock();
- }
- return dev;
+ dev->flags = IFF_BROADCAST | IFF_MULTICAST ;
}
-void tr_setup(struct net_device *dev)
+struct net_device *init_trdev(struct net_device *dev, int sizeof_priv)
{
- int i;
-
- /* register boot-defined "tr" devices */
- if (dev->name && (strncmp(dev->name, "tr", 2) == 0)) {
- i = simple_strtoul(dev->name + 2, NULL, 0);
- if (trdev_index[i] == NULL) {
- trdev_index[i] = dev;
- }
- else if (dev != trdev_index[i]) {
- /* Really shouldn't happen! */
- printk("tr_setup: Ouch! Someone else took %s\n",
- dev->name);
- }
- }
+ return init_netdev(dev, sizeof_priv, "tr%d", tr_configure);
}
-void tr_freedev(struct net_device *dev)
+void tr_setup(struct net_device *dev)
{
- int i;
- for (i = 0; i < MAX_TR_CARDS; ++i)
- {
- if (trdev_index[i] == dev)
- {
- trdev_index[i] = NULL;
- break;
- }
- }
}
int register_trdev(struct net_device *dev)
@@ -660,33 +477,14 @@
rtnl_lock();
unregister_netdevice(dev);
rtnl_unlock();
- tr_freedev(dev);
}
#endif
#ifdef CONFIG_NET_FC
-#define MAX_FC_CARDS 2
-static struct net_device *fcdev_index[MAX_FC_CARDS];
-
void fc_setup(struct net_device *dev)
{
-int i;
-
- /* register boot-defined "fc" devices */
- if (dev->name && (strncmp(dev->name, "fc", 2) == 0)) {
- i = simple_strtoul(dev->name + 2, NULL, 0);
- if (fcdev_index[i] == NULL) {
- fcdev_index[i] = dev;
- }
- else if (dev != fcdev_index[i]) {
- /* Really shouldn't happen! */
- printk("fc_setup: Ouch! Someone else took %s\n",
- dev->name);
- }
- }
-
dev->hard_header = fc_header;
dev->rebuild_header = fc_rebuild_header;
@@ -700,76 +498,16 @@
/* New-style flags. */
dev->flags = IFF_BROADCAST;
- dev_init_buffers(dev);
+ dev_init_buffers(dev);
return;
}
struct net_device *init_fcdev(struct net_device *dev, int sizeof_priv)
{
-int new_device = 0;
-int i;
- /* Use an existing correctly named device in Space.c:dev_base. */
- if (dev == NULL) {
- int alloc_size = sizeof(struct net_device) + sizeof("fc%d ") + sizeof_priv + 3;
- struct net_device *cur_dev;
- char pname[8]; /* Putative name for the device. */
-
- for (i = 0; i < MAX_FC_CARDS; ++i)
- if (fcdev_index[i] == NULL) {
- sprintf(pname, "fc%d", i);
- for (cur_dev = dev_base; cur_dev; cur_dev = cur_dev->next)
- if (strcmp(pname, cur_dev->name) == 0) {
- dev = cur_dev;
- dev->init = NULL;
- sizeof_priv = (sizeof_priv + 3) &~3;
- dev->priv = sizeof_priv
- ? kmalloc(sizeof_priv, GFP_KERNEL)
- : NULL;
- if (dev->priv) memset(dev->priv, 0, sizeof_priv);
- goto fcfound;
- }
- }
-
- alloc_size &= ~3; /* Round to dword boundary. */
- dev = (struct net_device *)kmalloc(alloc_size, GFP_KERNEL);
- memset(dev, 0, alloc_size);
- if (sizeof_priv)
- dev->priv = (void *) (dev + 1);
- dev->name = sizeof_priv + (char *)(dev + 1);
- new_device = 1;
- }
-
-fcfound: /* From the double loop */
-
- for (i = 0; i < MAX_FC_CARDS; ++i)
- if (fcdev_index[i] == NULL) {
- sprintf(dev->name, "fc%d", i);
- fcdev_index[i] = dev;
- break;
- }
-
- fc_setup(dev);
- if (new_device) {
- rtnl_lock();
- register_netdevice(dev);
- rtnl_unlock();
- }
- return dev;
+ return init_netdev(dev, sizeof_priv, "fc%d", fc_setup);
}
-void fc_freedev(struct net_device *dev)
-{
-int i;
- for (i = 0; i < MAX_FC_CARDS; ++i) {
- if (fcdev_index[i] == dev) {
- fcdev_index[i] = NULL;
- break;
- }
- }
-}
-
-
int register_fcdev(struct net_device *dev)
{
dev_init_buffers(dev);
@@ -785,7 +523,6 @@
rtnl_lock();
unregister_netdevice(dev);
rtnl_unlock();
- fc_freedev(dev);
}
#endif /* CONFIG_NET_FC */
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)