diff --git a/drivers/staging/batman-adv/hard-interface.c b/drivers/staging/batman-adv/hard-interface.c index 376ac488bf51..df6e5bd33c2b 100644 --- a/drivers/staging/batman-adv/hard-interface.c +++ b/drivers/staging/batman-adv/hard-interface.c @@ -401,6 +401,8 @@ static struct batman_if *hardif_add_interface(struct net_device *net_dev) batman_if->soft_iface = NULL; batman_if->if_status = IF_NOT_IN_USE; INIT_LIST_HEAD(&batman_if->list); + atomic_set(&batman_if->refcnt, 0); + hardif_hold(batman_if); check_known_mac_addr(batman_if->net_dev->dev_addr); @@ -433,8 +435,7 @@ static void hardif_remove_interface(struct batman_if *batman_if) list_del_rcu(&batman_if->list); synchronize_rcu(); sysfs_del_hardif(&batman_if->hardif_obj); - dev_put(batman_if->net_dev); - kfree(batman_if); + hardif_put(batman_if); } void hardif_remove_interfaces(void) diff --git a/drivers/staging/batman-adv/hard-interface.h b/drivers/staging/batman-adv/hard-interface.h index 4b49527f57ad..d5508899065b 100644 --- a/drivers/staging/batman-adv/hard-interface.h +++ b/drivers/staging/batman-adv/hard-interface.h @@ -42,4 +42,17 @@ int batman_skb_recv(struct sk_buff *skb, int hardif_min_mtu(struct net_device *soft_iface); void update_min_mtu(struct net_device *soft_iface); +static inline void hardif_hold(struct batman_if *batman_if) +{ + atomic_inc(&batman_if->refcnt); +} + +static inline void hardif_put(struct batman_if *batman_if) +{ + if (atomic_dec_and_test(&batman_if->refcnt)) { + dev_put(batman_if->net_dev); + kfree(batman_if); + } +} + #endif /* _NET_BATMAN_ADV_HARD_INTERFACE_H_ */ diff --git a/drivers/staging/batman-adv/types.h b/drivers/staging/batman-adv/types.h index b16264441ea2..bb5827f783a2 100644 --- a/drivers/staging/batman-adv/types.h +++ b/drivers/staging/batman-adv/types.h @@ -44,6 +44,7 @@ struct batman_if { unsigned char *packet_buff; int packet_len; struct kobject *hardif_obj; + atomic_t refcnt; struct packet_type batman_adv_ptype; struct net_device *soft_iface; };