|
@@ -30,6 +30,7 @@
|
|
|
#include <linux/if_vlan.h>
|
|
|
#include <linux/jiffies.h>
|
|
|
#include <linux/kernel.h>
|
|
|
+#include <linux/kref.h>
|
|
|
#include <linux/list.h>
|
|
|
#include <linux/lockdep.h>
|
|
|
#include <linux/netdevice.h>
|
|
@@ -477,9 +478,27 @@ out:
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * batadv_softif_vlan_release - release vlan from lists and queue for free after
|
|
|
+ * rcu grace period
|
|
|
+ * @ref: kref pointer of the vlan object
|
|
|
+ */
|
|
|
+static void batadv_softif_vlan_release(struct kref *ref)
|
|
|
+{
|
|
|
+ struct batadv_softif_vlan *vlan;
|
|
|
+
|
|
|
+ vlan = container_of(ref, struct batadv_softif_vlan, refcount);
|
|
|
+
|
|
|
+ spin_lock_bh(&vlan->bat_priv->softif_vlan_list_lock);
|
|
|
+ hlist_del_rcu(&vlan->list);
|
|
|
+ spin_unlock_bh(&vlan->bat_priv->softif_vlan_list_lock);
|
|
|
+
|
|
|
+ kfree_rcu(vlan, rcu);
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* batadv_softif_vlan_free_ref - decrease the vlan object refcounter and
|
|
|
- * possibly free it
|
|
|
+ * possibly release it
|
|
|
* @vlan: the vlan object to release
|
|
|
*/
|
|
|
void batadv_softif_vlan_free_ref(struct batadv_softif_vlan *vlan)
|
|
@@ -487,13 +506,7 @@ void batadv_softif_vlan_free_ref(struct batadv_softif_vlan *vlan)
|
|
|
if (!vlan)
|
|
|
return;
|
|
|
|
|
|
- if (atomic_dec_and_test(&vlan->refcount)) {
|
|
|
- spin_lock_bh(&vlan->bat_priv->softif_vlan_list_lock);
|
|
|
- hlist_del_rcu(&vlan->list);
|
|
|
- spin_unlock_bh(&vlan->bat_priv->softif_vlan_list_lock);
|
|
|
-
|
|
|
- kfree_rcu(vlan, rcu);
|
|
|
- }
|
|
|
+ kref_put(&vlan->refcount, batadv_softif_vlan_release);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -514,7 +527,7 @@ struct batadv_softif_vlan *batadv_softif_vlan_get(struct batadv_priv *bat_priv,
|
|
|
if (vlan_tmp->vid != vid)
|
|
|
continue;
|
|
|
|
|
|
- if (!atomic_inc_not_zero(&vlan_tmp->refcount))
|
|
|
+ if (!kref_get_unless_zero(&vlan_tmp->refcount))
|
|
|
continue;
|
|
|
|
|
|
vlan = vlan_tmp;
|
|
@@ -549,7 +562,7 @@ int batadv_softif_create_vlan(struct batadv_priv *bat_priv, unsigned short vid)
|
|
|
|
|
|
vlan->bat_priv = bat_priv;
|
|
|
vlan->vid = vid;
|
|
|
- atomic_set(&vlan->refcount, 1);
|
|
|
+ kref_init(&vlan->refcount);
|
|
|
|
|
|
atomic_set(&vlan->ap_isolation, 0);
|
|
|
|