aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/batman-adv/hard-interface.c24
-rw-r--r--net/batman-adv/soft-interface.c32
-rw-r--r--net/batman-adv/types.h6
3 files changed, 57 insertions, 5 deletions
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c
index f1d37cd81815..cb3191fe60fc 100644
--- a/net/batman-adv/hard-interface.c
+++ b/net/batman-adv/hard-interface.c
@@ -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)
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
index 3d6816667bfc..c9962fee44b1 100644
--- a/net/batman-adv/soft-interface.c
+++ b/net/batman-adv/soft-interface.c
@@ -449,6 +449,30 @@ static void batadv_interface_setup(struct net_device *dev)
449 memset(priv, 0, sizeof(*priv)); 449 memset(priv, 0, sizeof(*priv));
450} 450}
451 451
452/**
453 * batadv_softif_destroy_finish - cleans up the remains of a softif
454 * @work: work queue item
455 *
456 * Free the parts of the soft interface which can not be removed under
457 * rtnl lock (to prevent deadlock situations).
458 */
459static void batadv_softif_destroy_finish(struct work_struct *work)
460{
461 struct batadv_priv *bat_priv;
462 struct net_device *soft_iface;
463
464 bat_priv = container_of(work, struct batadv_priv,
465 cleanup_work);
466 soft_iface = bat_priv->soft_iface;
467
468 batadv_debugfs_del_meshif(soft_iface);
469 batadv_sysfs_del_meshif(soft_iface);
470
471 rtnl_lock();
472 unregister_netdevice(soft_iface);
473 rtnl_unlock();
474}
475
452struct net_device *batadv_softif_create(const char *name) 476struct net_device *batadv_softif_create(const char *name)
453{ 477{
454 struct net_device *soft_iface; 478 struct net_device *soft_iface;
@@ -463,6 +487,8 @@ struct net_device *batadv_softif_create(const char *name)
463 goto out; 487 goto out;
464 488
465 bat_priv = netdev_priv(soft_iface); 489 bat_priv = netdev_priv(soft_iface);
490 bat_priv->soft_iface = soft_iface;
491 INIT_WORK(&bat_priv->cleanup_work, batadv_softif_destroy_finish);
466 492
467 /* batadv_interface_stats() needs to be available as soon as 493 /* batadv_interface_stats() needs to be available as soon as
468 * register_netdevice() has been called 494 * register_netdevice() has been called
@@ -551,10 +577,10 @@ out:
551 577
552void batadv_softif_destroy(struct net_device *soft_iface) 578void batadv_softif_destroy(struct net_device *soft_iface)
553{ 579{
554 batadv_debugfs_del_meshif(soft_iface); 580 struct batadv_priv *bat_priv = netdev_priv(soft_iface);
555 batadv_sysfs_del_meshif(soft_iface); 581
556 batadv_mesh_free(soft_iface); 582 batadv_mesh_free(soft_iface);
557 unregister_netdevice(soft_iface); 583 queue_work(batadv_event_workqueue, &bat_priv->cleanup_work);
558} 584}
559 585
560int batadv_softif_is_valid(const struct net_device *net_dev) 586int batadv_softif_is_valid(const struct net_device *net_dev)
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index 03197f5ebf6c..8d4a16c0ed50 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -68,6 +68,7 @@ struct batadv_hard_iface_bat_iv {
68 * @soft_iface: the batman-adv interface which uses this network interface 68 * @soft_iface: the batman-adv interface which uses this network interface
69 * @rcu: struct used for freeing in an RCU-safe manner 69 * @rcu: struct used for freeing in an RCU-safe manner
70 * @bat_iv: BATMAN IV specific per hard interface data 70 * @bat_iv: BATMAN IV specific per hard interface data
71 * @cleanup_work: work queue callback item for hard interface deinit
71 */ 72 */
72struct batadv_hard_iface { 73struct batadv_hard_iface {
73 struct list_head list; 74 struct list_head list;
@@ -81,6 +82,7 @@ struct batadv_hard_iface {
81 struct net_device *soft_iface; 82 struct net_device *soft_iface;
82 struct rcu_head rcu; 83 struct rcu_head rcu;
83 struct batadv_hard_iface_bat_iv bat_iv; 84 struct batadv_hard_iface_bat_iv bat_iv;
85 struct work_struct cleanup_work;
84}; 86};
85 87
86/** 88/**
@@ -428,6 +430,7 @@ struct batadv_priv_dat {
428/** 430/**
429 * struct batadv_priv - per mesh interface data 431 * struct batadv_priv - per mesh interface data
430 * @mesh_state: current status of the mesh (inactive/active/deactivating) 432 * @mesh_state: current status of the mesh (inactive/active/deactivating)
433 * @soft_iface: net device which holds this struct as private data
431 * @stats: structure holding the data for the ndo_get_stats() call 434 * @stats: structure holding the data for the ndo_get_stats() call
432 * @bat_counters: mesh internal traffic statistic counters (see batadv_counters) 435 * @bat_counters: mesh internal traffic statistic counters (see batadv_counters)
433 * @aggregated_ogms: bool indicating whether OGM aggregation is enabled 436 * @aggregated_ogms: bool indicating whether OGM aggregation is enabled
@@ -457,6 +460,7 @@ struct batadv_priv_dat {
457 * @forw_bat_list_lock: lock protecting forw_bat_list 460 * @forw_bat_list_lock: lock protecting forw_bat_list
458 * @forw_bcast_list_lock: lock protecting forw_bcast_list 461 * @forw_bcast_list_lock: lock protecting forw_bcast_list
459 * @orig_work: work queue callback item for orig node purging 462 * @orig_work: work queue callback item for orig node purging
463 * @cleanup_work: work queue callback item for soft interface deinit
460 * @primary_if: one of the hard interfaces assigned to this mesh interface 464 * @primary_if: one of the hard interfaces assigned to this mesh interface
461 * becomes the primary interface 465 * becomes the primary interface
462 * @bat_algo_ops: routing algorithm used by this mesh interface 466 * @bat_algo_ops: routing algorithm used by this mesh interface
@@ -469,6 +473,7 @@ struct batadv_priv_dat {
469 */ 473 */
470struct batadv_priv { 474struct batadv_priv {
471 atomic_t mesh_state; 475 atomic_t mesh_state;
476 struct net_device *soft_iface;
472 struct net_device_stats stats; 477 struct net_device_stats stats;
473 uint64_t __percpu *bat_counters; /* Per cpu counters */ 478 uint64_t __percpu *bat_counters; /* Per cpu counters */
474 atomic_t aggregated_ogms; 479 atomic_t aggregated_ogms;
@@ -502,6 +507,7 @@ struct batadv_priv {
502 spinlock_t forw_bat_list_lock; /* protects forw_bat_list */ 507 spinlock_t forw_bat_list_lock; /* protects forw_bat_list */
503 spinlock_t forw_bcast_list_lock; /* protects forw_bcast_list */ 508 spinlock_t forw_bcast_list_lock; /* protects forw_bcast_list */
504 struct delayed_work orig_work; 509 struct delayed_work orig_work;
510 struct work_struct cleanup_work;
505 struct batadv_hard_iface __rcu *primary_if; /* rcu protected pointer */ 511 struct batadv_hard_iface __rcu *primary_if; /* rcu protected pointer */
506 struct batadv_algo_ops *bat_algo_ops; 512 struct batadv_algo_ops *bat_algo_ops;
507#ifdef CONFIG_BATMAN_ADV_BLA 513#ifdef CONFIG_BATMAN_ADV_BLA