diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/veth.c | 53 |
1 files changed, 40 insertions, 13 deletions
diff --git a/drivers/net/veth.c b/drivers/net/veth.c index 3f67a29593bc..e2ad98bee6e7 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c | |||
@@ -244,18 +244,6 @@ static int veth_open(struct net_device *dev) | |||
244 | return 0; | 244 | return 0; |
245 | } | 245 | } |
246 | 246 | ||
247 | static int veth_close(struct net_device *dev) | ||
248 | { | ||
249 | struct veth_priv *priv; | ||
250 | |||
251 | if (netif_carrier_ok(dev)) { | ||
252 | priv = netdev_priv(dev); | ||
253 | netif_carrier_off(dev); | ||
254 | netif_carrier_off(priv->peer); | ||
255 | } | ||
256 | return 0; | ||
257 | } | ||
258 | |||
259 | static int veth_dev_init(struct net_device *dev) | 247 | static int veth_dev_init(struct net_device *dev) |
260 | { | 248 | { |
261 | struct veth_net_stats *stats; | 249 | struct veth_net_stats *stats; |
@@ -286,13 +274,50 @@ static void veth_setup(struct net_device *dev) | |||
286 | dev->hard_start_xmit = veth_xmit; | 274 | dev->hard_start_xmit = veth_xmit; |
287 | dev->get_stats = veth_get_stats; | 275 | dev->get_stats = veth_get_stats; |
288 | dev->open = veth_open; | 276 | dev->open = veth_open; |
289 | dev->stop = veth_close; | ||
290 | dev->ethtool_ops = &veth_ethtool_ops; | 277 | dev->ethtool_ops = &veth_ethtool_ops; |
291 | dev->features |= NETIF_F_LLTX; | 278 | dev->features |= NETIF_F_LLTX; |
292 | dev->init = veth_dev_init; | 279 | dev->init = veth_dev_init; |
293 | dev->destructor = veth_dev_free; | 280 | dev->destructor = veth_dev_free; |
294 | } | 281 | } |
295 | 282 | ||
283 | static void veth_change_state(struct net_device *dev) | ||
284 | { | ||
285 | struct net_device *peer; | ||
286 | struct veth_priv *priv; | ||
287 | |||
288 | priv = netdev_priv(dev); | ||
289 | peer = priv->peer; | ||
290 | |||
291 | if (netif_carrier_ok(peer)) { | ||
292 | if (!netif_carrier_ok(dev)) | ||
293 | netif_carrier_on(dev); | ||
294 | } else { | ||
295 | if (netif_carrier_ok(dev)) | ||
296 | netif_carrier_off(dev); | ||
297 | } | ||
298 | } | ||
299 | |||
300 | static int veth_device_event(struct notifier_block *unused, | ||
301 | unsigned long event, void *ptr) | ||
302 | { | ||
303 | struct net_device *dev = ptr; | ||
304 | |||
305 | if (dev->open != veth_open) | ||
306 | goto out; | ||
307 | |||
308 | switch (event) { | ||
309 | case NETDEV_CHANGE: | ||
310 | veth_change_state(dev); | ||
311 | break; | ||
312 | } | ||
313 | out: | ||
314 | return NOTIFY_DONE; | ||
315 | } | ||
316 | |||
317 | static struct notifier_block veth_notifier_block __read_mostly = { | ||
318 | .notifier_call = veth_device_event, | ||
319 | }; | ||
320 | |||
296 | /* | 321 | /* |
297 | * netlink interface | 322 | * netlink interface |
298 | */ | 323 | */ |
@@ -454,12 +479,14 @@ static struct rtnl_link_ops veth_link_ops = { | |||
454 | 479 | ||
455 | static __init int veth_init(void) | 480 | static __init int veth_init(void) |
456 | { | 481 | { |
482 | register_netdevice_notifier(&veth_notifier_block); | ||
457 | return rtnl_link_register(&veth_link_ops); | 483 | return rtnl_link_register(&veth_link_ops); |
458 | } | 484 | } |
459 | 485 | ||
460 | static __exit void veth_exit(void) | 486 | static __exit void veth_exit(void) |
461 | { | 487 | { |
462 | rtnl_link_unregister(&veth_link_ops); | 488 | rtnl_link_unregister(&veth_link_ops); |
489 | unregister_netdevice_notifier(&veth_notifier_block); | ||
463 | } | 490 | } |
464 | 491 | ||
465 | module_init(veth_init); | 492 | module_init(veth_init); |