diff options
author | Daniel Lezcano <dlezcano@fr.ibm.com> | 2007-09-25 19:18:04 -0700 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-10-10 16:52:15 -0700 |
commit | 854d8363f37491c955b0edc60d37b62f3d71bb67 (patch) | |
tree | fd8f1a2de2c60ca8abcac0b8117cdc5e293c2ac4 /drivers/net/loopback.c | |
parent | de3cb747ffac5f2a4a6bb156e7e2fd5229e688e5 (diff) |
[NET]: Dynamically allocate the loopback device, part 2.
Doing this makes loopback.c a better example of how to do a
simple network device, and it removes the special case
single static allocation of a struct net_device, hopefully
making maintenance easier.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>
Acked-By: Kirill Korotaev <dev@sw.ru>
Acked-by: Benjamin Thery <benjamin.thery@bull.net>
Diffstat (limited to 'drivers/net/loopback.c')
-rw-r--r-- | drivers/net/loopback.c | 72 |
1 files changed, 44 insertions, 28 deletions
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index 588092e13186..4b6f7b2abea5 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c @@ -202,44 +202,60 @@ static const struct ethtool_ops loopback_ethtool_ops = { * The loopback device is special. There is only one instance and * it is statically allocated. Don't do this for other devices. */ -struct net_device __loopback_dev = { - .name = "lo", - .get_stats = &get_stats, - .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 +static void loopback_setup(struct net_device *dev) +{ + dev->get_stats = &get_stats; + 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 #ifdef LOOPBACK_TSO - | NETIF_F_TSO + | NETIF_F_TSO #endif - | NETIF_F_NO_CSUM | NETIF_F_HIGHDMA - | NETIF_F_LLTX - | NETIF_F_NETNS_LOCAL, - .ethtool_ops = &loopback_ethtool_ops, - .nd_net = &init_net, -}; - -struct net_device *loopback_dev = &__loopback_dev; + | NETIF_F_NO_CSUM + | NETIF_F_HIGHDMA + | NETIF_F_LLTX + | NETIF_F_NETNS_LOCAL, + dev->ethtool_ops = &loopback_ethtool_ops; +} /* Setup and register the loopback device. */ static int __init loopback_init(void) { - int err = register_netdev(loopback_dev); + struct net_device *dev; + int err; + + err = -ENOMEM; + dev = alloc_netdev(0, "lo", loopback_setup); + if (!dev) + goto out; + err = register_netdev(dev); if (err) - panic("loopback: Failed to register netdevice: %d\n", err); + goto out_free_netdev; + err = 0; + loopback_dev = dev; + +out: + if (err) + panic("loopback: Failed to register netdevice: %d\n", err); return err; -}; -module_init(loopback_init); +out_free_netdev: + free_netdev(dev); + goto out; +} + +fs_initcall(loopback_init); +struct net_device *loopback_dev; EXPORT_SYMBOL(loopback_dev); |