aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Lezcano <dlezcano@fr.ibm.com>2007-09-25 22:18:04 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 19:52:15 -0400
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 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 = {
202 * The loopback device is special. There is only one instance and 202 * The loopback device is special. There is only one instance and
203 * it is statically allocated. Don't do this for other devices. 203 * it is statically allocated. Don't do this for other devices.
204 */ 204 */
205struct net_device __loopback_dev = { 205static void loopback_setup(struct net_device *dev)
206 .name = "lo", 206{
207 .get_stats = &get_stats, 207 dev->get_stats = &get_stats;
208 .mtu = (16 * 1024) + 20 + 20 + 12, 208 dev->mtu = (16 * 1024) + 20 + 20 + 12;
209 .hard_start_xmit = loopback_xmit, 209 dev->hard_start_xmit = loopback_xmit;
210 .hard_header = eth_header, 210 dev->hard_header = eth_header;
211 .hard_header_cache = eth_header_cache, 211 dev->hard_header_cache = eth_header_cache;
212 .header_cache_update = eth_header_cache_update, 212 dev->header_cache_update = eth_header_cache_update;
213 .hard_header_len = ETH_HLEN, /* 14 */ 213 dev->hard_header_len = ETH_HLEN; /* 14 */
214 .addr_len = ETH_ALEN, /* 6 */ 214 dev->addr_len = ETH_ALEN; /* 6 */
215 .tx_queue_len = 0, 215 dev->tx_queue_len = 0;
216 .type = ARPHRD_LOOPBACK, /* 0x0001*/ 216 dev->type = ARPHRD_LOOPBACK; /* 0x0001*/
217 .rebuild_header = eth_rebuild_header, 217 dev->rebuild_header = eth_rebuild_header;
218 .flags = IFF_LOOPBACK, 218 dev->flags = IFF_LOOPBACK;
219 .features = NETIF_F_SG | NETIF_F_FRAGLIST 219 dev->features = NETIF_F_SG | NETIF_F_FRAGLIST
220#ifdef LOOPBACK_TSO 220#ifdef LOOPBACK_TSO
221 | NETIF_F_TSO 221 | NETIF_F_TSO
222#endif 222#endif
223 | NETIF_F_NO_CSUM | NETIF_F_HIGHDMA 223 | NETIF_F_NO_CSUM
224 | NETIF_F_LLTX 224 | NETIF_F_HIGHDMA
225 | NETIF_F_NETNS_LOCAL, 225 | NETIF_F_LLTX
226 .ethtool_ops = &loopback_ethtool_ops, 226 | NETIF_F_NETNS_LOCAL,
227 .nd_net = &init_net, 227 dev->ethtool_ops = &loopback_ethtool_ops;
228}; 228}
229
230struct net_device *loopback_dev = &__loopback_dev;
231 229
232/* Setup and register the loopback device. */ 230/* Setup and register the loopback device. */
233static int __init loopback_init(void) 231static int __init loopback_init(void)
234{ 232{
235 int err = register_netdev(loopback_dev); 233 struct net_device *dev;
234 int err;
235
236 err = -ENOMEM;
237 dev = alloc_netdev(0, "lo", loopback_setup);
238 if (!dev)
239 goto out;
236 240
241 err = register_netdev(dev);
237 if (err) 242 if (err)
238 panic("loopback: Failed to register netdevice: %d\n", err); 243 goto out_free_netdev;
239 244
245 err = 0;
246 loopback_dev = dev;
247
248out:
249 if (err)
250 panic("loopback: Failed to register netdevice: %d\n", err);
240 return err; 251 return err;
241};
242 252
243module_init(loopback_init); 253out_free_netdev:
254 free_netdev(dev);
255 goto out;
256}
257
258fs_initcall(loopback_init);
244 259
260struct net_device *loopback_dev;
245EXPORT_SYMBOL(loopback_dev); 261EXPORT_SYMBOL(loopback_dev);