Commit 4e39f29b authored by Stephen Hemminger's avatar Stephen Hemminger

[NET]: Loopback device simplification.

Now that all the magic chain of static devices is gone from Space.c
The initialization of the one remaining static device (ie the loopback driver)
can be simplified.

One small change was to reduce possibility of failing the initialization if
allocation of private data failed by just going without statistics.
parent 4976b816
......@@ -39,9 +39,6 @@
#include <linux/netlink.h>
#include <linux/divert.h>
#define NEXT_DEV NULL
/* A unified ethernet device probe. This is the easiest way to have every
ethernet adaptor have the name "eth[0123...]".
*/
......@@ -438,11 +435,23 @@ static __init int trif_probe(void)
}
#endif
/*
* The loopback device is global so it can be directly referenced
* by the network code. Also, it must be first on device list.
*/
extern int loopback_init(void);
/* Statically configured drivers -- order matters here. */
void __init probe_old_netdevs(void)
{
int num;
if (loopback_init()) {
printk(KERN_ERR "Network loopback device setup failed\n");
}
#ifdef CONFIG_SBNI
for (num = 0; num < 8; ++num)
if (sbni_probe())
......@@ -477,18 +486,6 @@ static struct net_device dev_ltpc = {
#undef NEXT_DEV
#define NEXT_DEV (&dev_ltpc)
#endif /* LTPC */
/*
* The loopback device is global so it can be directly referenced
* by the network code. Also, it must be first on device list.
*/
extern int loopback_init(struct net_device *dev);
struct net_device loopback_dev = {
.name = "lo",
.next = NEXT_DEV,
.init = loopback_init
};
/*
* The @dev_base list is protected by @dev_base_lock and the rtln
......@@ -509,6 +506,6 @@ struct net_device loopback_dev = {
* unregister_netdevice(), which must be called with the rtnl
* semaphore held.
*/
struct net_device *dev_base = &loopback_dev;
struct net_device *dev_base;
rwlock_t dev_base_lock = RW_LOCK_UNLOCKED;
......@@ -55,6 +55,7 @@
#include <linux/ip.h>
#include <linux/tcp.h>
#define LOOPBACK_OVERHEAD (128 + MAX_HEADER + 16 + 16)
/* KISS: just allocate small chunks and copy bits.
......@@ -152,10 +153,12 @@ static int loopback_xmit(struct sk_buff *skb, struct net_device *dev)
}
dev->last_rx = jiffies;
stats->rx_bytes+=skb->len;
stats->tx_bytes+=skb->len;
stats->rx_packets++;
stats->tx_packets++;
if (likely(stats)) {
stats->rx_bytes+=skb->len;
stats->tx_bytes+=skb->len;
stats->rx_packets++;
stats->tx_packets++;
}
netif_rx(skb);
......@@ -167,36 +170,35 @@ static struct net_device_stats *get_stats(struct net_device *dev)
return (struct net_device_stats *)dev->priv;
}
/* Initialize the rest of the LOOPBACK device. */
int __init loopback_init(struct net_device *dev)
{
dev->mtu = (16 * 1024) + 20 + 20 + 12;
dev->hard_start_xmit = loopback_xmit;
dev->hard_header = eth_header;
dev->hard_header_cache = eth_header_cache;
dev->header_cache_update= eth_header_cache_update;
dev->hard_header_len = ETH_HLEN; /* 14 */
dev->addr_len = ETH_ALEN; /* 6 */
dev->tx_queue_len = 0;
dev->type = ARPHRD_LOOPBACK; /* 0x0001 */
dev->rebuild_header = eth_rebuild_header;
dev->flags = IFF_LOOPBACK;
dev->features = NETIF_F_SG|NETIF_F_FRAGLIST|NETIF_F_NO_CSUM|NETIF_F_HIGHDMA;
/* Current netfilter will die with oom linearizing large skbs,
* however this will be cured before 2.5.x is done.
*/
dev->features |= NETIF_F_TSO;
dev->priv = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL);
if (dev->priv == NULL)
return -ENOMEM;
memset(dev->priv, 0, sizeof(struct net_device_stats));
dev->get_stats = get_stats;
struct net_device loopback_dev = {
.name = "lo",
.mtu = (16 * 1024) + 20 + 20 + 12,
.hard_start_xmit = loopback_xmit,
.hard_header = eth_header,
.hard_header_cache = eth_header_cache,
.header_cache_update = eth_header_cache_update,
.hard_header_len = ETH_HLEN, /* 14 */
.addr_len = ETH_ALEN, /* 6 */
.tx_queue_len = 0,
.type = ARPHRD_LOOPBACK, /* 0x0001*/
.rebuild_header = eth_rebuild_header,
.flags = IFF_LOOPBACK,
.features = NETIF_F_SG|NETIF_F_FRAGLIST
|NETIF_F_NO_CSUM|NETIF_F_HIGHDMA|NETIF_F_TSO,
};
/*
* Fill in the generic fields of the device structure.
*/
return(0);
/* Setup and register the of the LOOPBACK device. */
int __init loopback_init(void)
{
struct net_device_stats *stats;
/* Can survive without statistics */
stats = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL);
if (stats) {
memset(stats, 0, sizeof(struct net_device_stats));
loopback_dev.priv = stats;
loopback_dev.get_stats = &get_stats;
}
return register_netdev(&loopback_dev);
};
......@@ -2981,7 +2981,6 @@ int unregister_netdevice(struct net_device *dev)
*/
static int __init net_dev_init(void)
{
struct net_device *dev, **dp;
int i, rc = -ENOMEM;
BUG_ON(!dev_boot_phase);
......@@ -3027,75 +3026,6 @@ static int __init net_dev_init(void)
add_timer(&samp_timer);
#endif
/*
* Add the devices.
* If the call to dev->init fails, the dev is removed
* from the chain disconnecting the device until the
* next reboot.
*
* NB At boot phase networking is dead. No locking is required.
* But we still preserve dev_base_lock for sanity.
*/
dp = &dev_base;
while ((dev = *dp) != NULL) {
spin_lock_init(&dev->queue_lock);
spin_lock_init(&dev->xmit_lock);
#ifdef CONFIG_NET_FASTROUTE
dev->fastpath_lock = RW_LOCK_UNLOCKED;
#endif
dev->xmit_lock_owner = -1;
dev->iflink = -1;
dev_hold(dev);
/*
* Allocate name. If the init() fails
* the name will be reissued correctly.
*/
if (strchr(dev->name, '%'))
dev_alloc_name(dev, dev->name);
/*
* Check boot time settings for the device.
*/
netdev_boot_setup_check(dev);
if ( (dev->init && dev->init(dev)) ||
netdev_register_sysfs(dev) ) {
/*
* It failed to come up. It will be unhooked later.
* dev_alloc_name can now advance to next suitable
* name that is checked next.
*/
dp = &dev->next;
} else {
dp = &dev->next;
dev->ifindex = dev_new_index();
dev->reg_state = NETREG_REGISTERED;
if (dev->iflink == -1)
dev->iflink = dev->ifindex;
if (!dev->rebuild_header)
dev->rebuild_header = default_rebuild_header;
dev_init_scheduler(dev);
set_bit(__LINK_STATE_PRESENT, &dev->state);
}
}
/*
* Unhook devices that failed to come up
*/
dp = &dev_base;
while ((dev = *dp) != NULL) {
if (dev->reg_state != NETREG_REGISTERED) {
write_lock_bh(&dev_base_lock);
*dp = dev->next;
write_unlock_bh(&dev_base_lock);
dev_put(dev);
} else {
dp = &dev->next;
}
}
dev_boot_phase = 0;
probe_old_netdevs();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment