aboutsummaryrefslogtreecommitdiffstats
path: root/net/batman-adv/hard-interface.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/batman-adv/hard-interface.c')
-rw-r--r--net/batman-adv/hard-interface.c26
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 */
467static 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
460static struct batadv_hard_iface * 478static struct batadv_hard_iface *
461batadv_hardif_add_interface(struct net_device *net_dev) 479batadv_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
525void batadv_hardif_remove_interfaces(void) 545void batadv_hardif_remove_interfaces(void)