aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Lezcano <dlezcano@fr.ibm.com>2007-09-25 19:18:04 -0700
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 16:52:15 -0700
commit854d8363f37491c955b0edc60d37b62f3d71bb67 (patch)
treefd8f1a2de2c60ca8abcac0b8117cdc5e293c2ac4
parentde3cb747ffac5f2a4a6bb156e7e2fd5229e688e5 (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>
-rw-r--r--drivers/net/loopback.c72
1 files changed, 44 insertions, 28 deletions
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
index 588092e1318..4b6f7b2abea 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);