diff options
Diffstat (limited to 'net/batman-adv/hard-interface.c')
-rw-r--r-- | net/batman-adv/hard-interface.c | 26 |
1 files changed, 23 insertions, 3 deletions
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c index f1d37cd81815..368219e026a9 100644 --- a/net/batman-adv/hard-interface.c +++ b/net/batman-adv/hard-interface.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* Copyright (C) 2007-2012 B.A.T.M.A.N. contributors: | 1 | /* Copyright (C) 2007-2013 B.A.T.M.A.N. contributors: |
2 | * | 2 | * |
3 | * Marek Lindner, Simon Wunderlich | 3 | * Marek Lindner, Simon Wunderlich |
4 | * | 4 | * |
@@ -457,6 +457,24 @@ out: | |||
457 | batadv_hardif_free_ref(primary_if); | 457 | batadv_hardif_free_ref(primary_if); |
458 | } | 458 | } |
459 | 459 | ||
460 | /** | ||
461 | * batadv_hardif_remove_interface_finish - cleans up the remains of a hardif | ||
462 | * @work: work queue item | ||
463 | * | ||
464 | * Free the parts of the hard interface which can not be removed under | ||
465 | * rtnl lock (to prevent deadlock situations). | ||
466 | */ | ||
467 | static void batadv_hardif_remove_interface_finish(struct work_struct *work) | ||
468 | { | ||
469 | struct batadv_hard_iface *hard_iface; | ||
470 | |||
471 | hard_iface = container_of(work, struct batadv_hard_iface, | ||
472 | cleanup_work); | ||
473 | |||
474 | batadv_sysfs_del_hardif(&hard_iface->hardif_obj); | ||
475 | batadv_hardif_free_ref(hard_iface); | ||
476 | } | ||
477 | |||
460 | static struct batadv_hard_iface * | 478 | static struct batadv_hard_iface * |
461 | batadv_hardif_add_interface(struct net_device *net_dev) | 479 | batadv_hardif_add_interface(struct net_device *net_dev) |
462 | { | 480 | { |
@@ -484,6 +502,9 @@ batadv_hardif_add_interface(struct net_device *net_dev) | |||
484 | hard_iface->soft_iface = NULL; | 502 | hard_iface->soft_iface = NULL; |
485 | hard_iface->if_status = BATADV_IF_NOT_IN_USE; | 503 | hard_iface->if_status = BATADV_IF_NOT_IN_USE; |
486 | INIT_LIST_HEAD(&hard_iface->list); | 504 | INIT_LIST_HEAD(&hard_iface->list); |
505 | INIT_WORK(&hard_iface->cleanup_work, | ||
506 | batadv_hardif_remove_interface_finish); | ||
507 | |||
487 | /* extra reference for return */ | 508 | /* extra reference for return */ |
488 | atomic_set(&hard_iface->refcount, 2); | 509 | atomic_set(&hard_iface->refcount, 2); |
489 | 510 | ||
@@ -518,8 +539,7 @@ static void batadv_hardif_remove_interface(struct batadv_hard_iface *hard_iface) | |||
518 | return; | 539 | return; |
519 | 540 | ||
520 | hard_iface->if_status = BATADV_IF_TO_BE_REMOVED; | 541 | hard_iface->if_status = BATADV_IF_TO_BE_REMOVED; |
521 | batadv_sysfs_del_hardif(&hard_iface->hardif_obj); | 542 | queue_work(batadv_event_workqueue, &hard_iface->cleanup_work); |
522 | batadv_hardif_free_ref(hard_iface); | ||
523 | } | 543 | } |
524 | 544 | ||
525 | void batadv_hardif_remove_interfaces(void) | 545 | void batadv_hardif_remove_interfaces(void) |