Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
[linux-2.6-microblaze.git] / net / batman-adv / originator.c
index 018b749..7486df9 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/list.h>
 #include <linux/lockdep.h>
 #include <linux/netdevice.h>
+#include <linux/rculist.h>
 #include <linux/seq_file.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
@@ -70,7 +71,7 @@ batadv_orig_node_vlan_get(struct batadv_orig_node *orig_node,
        struct batadv_orig_node_vlan *vlan = NULL, *tmp;
 
        rcu_read_lock();
-       list_for_each_entry_rcu(tmp, &orig_node->vlan_list, list) {
+       hlist_for_each_entry_rcu(tmp, &orig_node->vlan_list, list) {
                if (tmp->vid != vid)
                        continue;
 
@@ -118,7 +119,7 @@ batadv_orig_node_vlan_new(struct batadv_orig_node *orig_node,
        atomic_set(&vlan->refcount, 2);
        vlan->vid = vid;
 
-       list_add_rcu(&vlan->list, &orig_node->vlan_list);
+       hlist_add_head_rcu(&vlan->list, &orig_node->vlan_list);
 
 out:
        spin_unlock_bh(&orig_node->vlan_list_lock);
@@ -441,41 +442,6 @@ out:
        return neigh_ifinfo;
 }
 
-/**
- * batadv_neigh_node_new - create and init a new neigh_node object
- * @hard_iface: the interface where the neighbour is connected to
- * @neigh_addr: the mac address of the neighbour interface
- * @orig_node: originator object representing the neighbour
- *
- * Allocates a new neigh_node object and initialises all the generic fields.
- * Returns the new object or NULL on failure.
- */
-struct batadv_neigh_node *
-batadv_neigh_node_new(struct batadv_hard_iface *hard_iface,
-                     const uint8_t *neigh_addr,
-                     struct batadv_orig_node *orig_node)
-{
-       struct batadv_neigh_node *neigh_node;
-
-       neigh_node = kzalloc(sizeof(*neigh_node), GFP_ATOMIC);
-       if (!neigh_node)
-               goto out;
-
-       INIT_HLIST_NODE(&neigh_node->list);
-       INIT_HLIST_HEAD(&neigh_node->ifinfo_list);
-       spin_lock_init(&neigh_node->ifinfo_lock);
-
-       ether_addr_copy(neigh_node->addr, neigh_addr);
-       neigh_node->if_incoming = hard_iface;
-       neigh_node->orig_node = orig_node;
-
-       /* extra reference for return */
-       atomic_set(&neigh_node->refcount, 2);
-
-out:
-       return neigh_node;
-}
-
 /**
  * batadv_neigh_node_get - retrieve a neighbour from the list
  * @orig_node: originator which the neighbour belongs to
@@ -486,10 +452,10 @@ out:
  * which is connected through the provided hard interface.
  * Returns NULL if the neighbour is not found.
  */
-struct batadv_neigh_node *
+static struct batadv_neigh_node *
 batadv_neigh_node_get(const struct batadv_orig_node *orig_node,
                      const struct batadv_hard_iface *hard_iface,
-                     const uint8_t *addr)
+                     const u8 *addr)
 {
        struct batadv_neigh_node *tmp_neigh_node, *res = NULL;
 
@@ -512,6 +478,59 @@ batadv_neigh_node_get(const struct batadv_orig_node *orig_node,
        return res;
 }
 
+/**
+ * batadv_neigh_node_new - create and init a new neigh_node object
+ * @orig_node: originator object representing the neighbour
+ * @hard_iface: the interface where the neighbour is connected to
+ * @neigh_addr: the mac address of the neighbour interface
+ *
+ * Allocates a new neigh_node object and initialises all the generic fields.
+ * Returns the new object or NULL on failure.
+ */
+struct batadv_neigh_node *
+batadv_neigh_node_new(struct batadv_orig_node *orig_node,
+                     struct batadv_hard_iface *hard_iface,
+                     const u8 *neigh_addr)
+{
+       struct batadv_neigh_node *neigh_node;
+
+       neigh_node = batadv_neigh_node_get(orig_node, hard_iface, neigh_addr);
+       if (neigh_node)
+               goto out;
+
+       neigh_node = kzalloc(sizeof(*neigh_node), GFP_ATOMIC);
+       if (!neigh_node)
+               goto out;
+
+       if (!atomic_inc_not_zero(&hard_iface->refcount)) {
+               kfree(neigh_node);
+               neigh_node = NULL;
+               goto out;
+       }
+
+       INIT_HLIST_NODE(&neigh_node->list);
+       INIT_HLIST_HEAD(&neigh_node->ifinfo_list);
+       spin_lock_init(&neigh_node->ifinfo_lock);
+
+       ether_addr_copy(neigh_node->addr, neigh_addr);
+       neigh_node->if_incoming = hard_iface;
+       neigh_node->orig_node = orig_node;
+
+       /* extra reference for return */
+       atomic_set(&neigh_node->refcount, 2);
+
+       spin_lock_bh(&orig_node->neigh_list_lock);
+       hlist_add_head_rcu(&neigh_node->list, &orig_node->neigh_list);
+       spin_unlock_bh(&orig_node->neigh_list_lock);
+
+       batadv_dbg(BATADV_DBG_BATMAN, orig_node->bat_priv,
+                  "Creating new neighbor %pM for orig_node %pM on interface %s\n",
+                  neigh_addr, orig_node->orig, hard_iface->net_dev->name);
+
+out:
+       return neigh_node;
+}
+
 /**
  * batadv_orig_ifinfo_free_rcu - free the orig_ifinfo object
  * @rcu: rcu pointer of the orig_ifinfo object
@@ -624,7 +643,7 @@ void batadv_originator_free(struct batadv_priv *bat_priv)
        struct hlist_head *head;
        spinlock_t *list_lock; /* spinlock to protect write access */
        struct batadv_orig_node *orig_node;
-       uint32_t i;
+       u32 i;
 
        if (!hash)
                return;
@@ -659,7 +678,7 @@ void batadv_originator_free(struct batadv_priv *bat_priv)
  * Returns the newly created object or NULL on failure.
  */
 struct batadv_orig_node *batadv_orig_node_new(struct batadv_priv *bat_priv,
-                                             const uint8_t *addr)
+                                             const u8 *addr)
 {
        struct batadv_orig_node *orig_node;
        struct batadv_orig_node_vlan *vlan;
@@ -674,7 +693,7 @@ struct batadv_orig_node *batadv_orig_node_new(struct batadv_priv *bat_priv,
                return NULL;
 
        INIT_HLIST_HEAD(&orig_node->neigh_list);
-       INIT_LIST_HEAD(&orig_node->vlan_list);
+       INIT_HLIST_HEAD(&orig_node->vlan_list);
        INIT_HLIST_HEAD(&orig_node->ifinfo_list);
        spin_lock_init(&orig_node->bcast_seqno_lock);
        spin_lock_init(&orig_node->neigh_list_lock);
@@ -696,8 +715,13 @@ struct batadv_orig_node *batadv_orig_node_new(struct batadv_priv *bat_priv,
        orig_node->last_seen = jiffies;
        reset_time = jiffies - 1 - msecs_to_jiffies(BATADV_RESET_PROTECTION_MS);
        orig_node->bcast_seqno_reset = reset_time;
+
 #ifdef CONFIG_BATMAN_ADV_MCAST
        orig_node->mcast_flags = BATADV_NO_FLAGS;
+       INIT_HLIST_NODE(&orig_node->mcast_want_all_unsnoopables_node);
+       INIT_HLIST_NODE(&orig_node->mcast_want_all_ipv4_node);
+       INIT_HLIST_NODE(&orig_node->mcast_want_all_ipv6_node);
+       spin_lock_init(&orig_node->mcast_handler_lock);
 #endif
 
        /* create a vlan object for the "untagged" LAN */
@@ -976,7 +1000,7 @@ static void _batadv_purge_orig(struct batadv_priv *bat_priv)
        struct hlist_head *head;
        spinlock_t *list_lock; /* spinlock to protect write access */
        struct batadv_orig_node *orig_node;
-       uint32_t i;
+       u32 i;
 
        if (!hash)
                return;
@@ -1005,7 +1029,6 @@ static void _batadv_purge_orig(struct batadv_priv *bat_priv)
                spin_unlock_bh(list_lock);
        }
 
-       batadv_gw_node_purge(bat_priv);
        batadv_gw_election(bat_priv);
 }
 
@@ -1110,7 +1133,7 @@ int batadv_orig_hash_add_if(struct batadv_hard_iface *hard_iface,
        struct batadv_hashtable *hash = bat_priv->orig_hash;
        struct hlist_head *head;
        struct batadv_orig_node *orig_node;
-       uint32_t i;
+       u32 i;
        int ret;
 
        /* resize all orig nodes because orig_node->bcast_own(_sum) depend on
@@ -1147,7 +1170,7 @@ int batadv_orig_hash_del_if(struct batadv_hard_iface *hard_iface,
        struct batadv_hard_iface *hard_iface_tmp;
        struct batadv_orig_node *orig_node;
        struct batadv_algo_ops *bao = bat_priv->bat_algo_ops;
-       uint32_t i;
+       u32 i;
        int ret;
 
        /* resize all orig nodes because orig_node->bcast_own(_sum) depend on