diff options
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 = { | |||
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 | */ |
205 | struct net_device __loopback_dev = { | 205 | static 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 | |||
230 | struct net_device *loopback_dev = &__loopback_dev; | ||
231 | 229 | ||
232 | /* Setup and register the loopback device. */ | 230 | /* Setup and register the loopback device. */ |
233 | static int __init loopback_init(void) | 231 | static 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 | |||
248 | out: | ||
249 | if (err) | ||
250 | panic("loopback: Failed to register netdevice: %d\n", err); | ||
240 | return err; | 251 | return err; |
241 | }; | ||
242 | 252 | ||
243 | module_init(loopback_init); | 253 | out_free_netdev: |
254 | free_netdev(dev); | ||
255 | goto out; | ||
256 | } | ||
257 | |||
258 | fs_initcall(loopback_init); | ||
244 | 259 | ||
260 | struct net_device *loopback_dev; | ||
245 | EXPORT_SYMBOL(loopback_dev); | 261 | EXPORT_SYMBOL(loopback_dev); |