]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - net/batman-adv/translation-table.c
Merge tag 'v2.6.38' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[mv-sheeva.git] / net / batman-adv / translation-table.c
similarity index 67%
rename from drivers/staging/batman-adv/translation-table.c
rename to net/batman-adv/translation-table.c
index 681ccbda3eac1b0f060d29d60d9fc1acc0ab5479..a633b5a435e2ca21f4ef6062cbf62a2c1f8619c8 100644 (file)
@@ -24,6 +24,7 @@
 #include "soft-interface.h"
 #include "types.h"
 #include "hash.h"
+#include "originator.h"
 
 static void hna_local_purge(struct work_struct *work);
 static void _hna_global_del_orig(struct bat_priv *bat_priv,
@@ -41,7 +42,7 @@ int hna_local_init(struct bat_priv *bat_priv)
        if (bat_priv->hna_local_hash)
                return 1;
 
-       bat_priv->hna_local_hash = hash_new(128, compare_orig, choose_orig);
+       bat_priv->hna_local_hash = hash_new(1024);
 
        if (!bat_priv->hna_local_hash)
                return 0;
@@ -57,15 +58,14 @@ void hna_local_add(struct net_device *soft_iface, uint8_t *addr)
        struct bat_priv *bat_priv = netdev_priv(soft_iface);
        struct hna_local_entry *hna_local_entry;
        struct hna_global_entry *hna_global_entry;
-       struct hashtable_t *swaphash;
-       unsigned long flags;
        int required_bytes;
 
-       spin_lock_irqsave(&bat_priv->hna_lhash_lock, flags);
+       spin_lock_bh(&bat_priv->hna_lhash_lock);
        hna_local_entry =
                ((struct hna_local_entry *)hash_find(bat_priv->hna_local_hash,
+                                                    compare_orig, choose_orig,
                                                     addr));
-       spin_unlock_irqrestore(&bat_priv->hna_lhash_lock, flags);
+       spin_unlock_bh(&bat_priv->hna_lhash_lock);
 
        if (hna_local_entry) {
                hna_local_entry->last_seen = jiffies;
@@ -79,7 +79,7 @@ void hna_local_add(struct net_device *soft_iface, uint8_t *addr)
        required_bytes += BAT_PACKET_LEN;
 
        if ((required_bytes > ETH_DATA_LEN) ||
-           (atomic_read(&bat_priv->aggregation_enabled) &&
+           (atomic_read(&bat_priv->aggregated_ogms) &&
             required_bytes > MAX_AGGREGATION_BYTES) ||
            (bat_priv->num_local_hna + 1 > 255)) {
                bat_dbg(DBG_ROUTES, bat_priv,
@@ -105,75 +105,76 @@ void hna_local_add(struct net_device *soft_iface, uint8_t *addr)
        else
                hna_local_entry->never_purge = 0;
 
-       spin_lock_irqsave(&bat_priv->hna_lhash_lock, flags);
+       spin_lock_bh(&bat_priv->hna_lhash_lock);
 
-       hash_add(bat_priv->hna_local_hash, hna_local_entry);
+       hash_add(bat_priv->hna_local_hash, compare_orig, choose_orig,
+                hna_local_entry);
        bat_priv->num_local_hna++;
        atomic_set(&bat_priv->hna_local_changed, 1);
 
-       if (bat_priv->hna_local_hash->elements * 4 >
-                                       bat_priv->hna_local_hash->size) {
-               swaphash = hash_resize(bat_priv->hna_local_hash,
-                                      bat_priv->hna_local_hash->size * 2);
-
-               if (!swaphash)
-                       pr_err("Couldn't resize local hna hash table\n");
-               else
-                       bat_priv->hna_local_hash = swaphash;
-       }
-
-       spin_unlock_irqrestore(&bat_priv->hna_lhash_lock, flags);
+       spin_unlock_bh(&bat_priv->hna_lhash_lock);
 
        /* remove address from global hash if present */
-       spin_lock_irqsave(&bat_priv->hna_ghash_lock, flags);
+       spin_lock_bh(&bat_priv->hna_ghash_lock);
 
        hna_global_entry = ((struct hna_global_entry *)
-                               hash_find(bat_priv->hna_global_hash, addr));
+                               hash_find(bat_priv->hna_global_hash,
+                                         compare_orig, choose_orig, addr));
 
        if (hna_global_entry)
                _hna_global_del_orig(bat_priv, hna_global_entry,
                                     "local hna received");
 
-       spin_unlock_irqrestore(&bat_priv->hna_ghash_lock, flags);
+       spin_unlock_bh(&bat_priv->hna_ghash_lock);
 }
 
 int hna_local_fill_buffer(struct bat_priv *bat_priv,
                          unsigned char *buff, int buff_len)
 {
+       struct hashtable_t *hash = bat_priv->hna_local_hash;
        struct hna_local_entry *hna_local_entry;
-       HASHIT(hashit);
-       int i = 0;
-       unsigned long flags;
+       struct element_t *bucket;
+       int i;
+       struct hlist_node *walk;
+       struct hlist_head *head;
+       int count = 0;
 
-       spin_lock_irqsave(&bat_priv->hna_lhash_lock, flags);
+       spin_lock_bh(&bat_priv->hna_lhash_lock);
 
-       while (hash_iterate(bat_priv->hna_local_hash, &hashit)) {
+       for (i = 0; i < hash->size; i++) {
+               head = &hash->table[i];
 
-               if (buff_len < (i + 1) * ETH_ALEN)
-                       break;
+               hlist_for_each_entry(bucket, walk, head, hlist) {
 
-               hna_local_entry = hashit.bucket->data;
-               memcpy(buff + (i * ETH_ALEN), hna_local_entry->addr, ETH_ALEN);
+                       if (buff_len < (count + 1) * ETH_ALEN)
+                               break;
+
+                       hna_local_entry = bucket->data;
+                       memcpy(buff + (count * ETH_ALEN), hna_local_entry->addr,
+                              ETH_ALEN);
 
-               i++;
+                       count++;
+               }
        }
 
        /* if we did not get all new local hnas see you next time  ;-) */
-       if (i == bat_priv->num_local_hna)
+       if (count == bat_priv->num_local_hna)
                atomic_set(&bat_priv->hna_local_changed, 0);
 
-       spin_unlock_irqrestore(&bat_priv->hna_lhash_lock, flags);
-       return i;
+       spin_unlock_bh(&bat_priv->hna_lhash_lock);
+       return count;
 }
 
 int hna_local_seq_print_text(struct seq_file *seq, void *offset)
 {
        struct net_device *net_dev = (struct net_device *)seq->private;
        struct bat_priv *bat_priv = netdev_priv(net_dev);
+       struct hashtable_t *hash = bat_priv->hna_local_hash;
        struct hna_local_entry *hna_local_entry;
-       HASHIT(hashit);
-       HASHIT(hashit_count);
-       unsigned long flags;
+       int i;
+       struct hlist_node *walk;
+       struct hlist_head *head;
+       struct element_t *bucket;
        size_t buf_size, pos;
        char *buff;
 
@@ -187,29 +188,37 @@ int hna_local_seq_print_text(struct seq_file *seq, void *offset)
                   "announced via HNA:\n",
                   net_dev->name);
 
-       spin_lock_irqsave(&bat_priv->hna_lhash_lock, flags);
+       spin_lock_bh(&bat_priv->hna_lhash_lock);
 
        buf_size = 1;
        /* Estimate length for: " * xx:xx:xx:xx:xx:xx\n" */
-       while (hash_iterate(bat_priv->hna_local_hash, &hashit_count))
-               buf_size += 21;
+       for (i = 0; i < hash->size; i++) {
+               head = &hash->table[i];
+
+               hlist_for_each(walk, head)
+                       buf_size += 21;
+       }
 
        buff = kmalloc(buf_size, GFP_ATOMIC);
        if (!buff) {
-               spin_unlock_irqrestore(&bat_priv->hna_lhash_lock, flags);
+               spin_unlock_bh(&bat_priv->hna_lhash_lock);
                return -ENOMEM;
        }
        buff[0] = '\0';
        pos = 0;
 
-       while (hash_iterate(bat_priv->hna_local_hash, &hashit)) {
-               hna_local_entry = hashit.bucket->data;
+       for (i = 0; i < hash->size; i++) {
+               head = &hash->table[i];
+
+               hlist_for_each_entry(bucket, walk, head, hlist) {
+                       hna_local_entry = bucket->data;
 
-               pos += snprintf(buff + pos, 22, " * %pM\n",
-                               hna_local_entry->addr);
+                       pos += snprintf(buff + pos, 22, " * %pM\n",
+                                       hna_local_entry->addr);
+               }
        }
 
-       spin_unlock_irqrestore(&bat_priv->hna_lhash_lock, flags);
+       spin_unlock_bh(&bat_priv->hna_lhash_lock);
 
        seq_printf(seq, "%s", buff);
        kfree(buff);
@@ -232,7 +241,8 @@ static void hna_local_del(struct bat_priv *bat_priv,
        bat_dbg(DBG_ROUTES, bat_priv, "Deleting local hna entry (%pM): %s\n",
                hna_local_entry->addr, message);
 
-       hash_remove(bat_priv->hna_local_hash, hna_local_entry->addr);
+       hash_remove(bat_priv->hna_local_hash, compare_orig, choose_orig,
+                   hna_local_entry->addr);
        _hna_local_del(hna_local_entry, bat_priv);
 }
 
@@ -240,16 +250,17 @@ void hna_local_remove(struct bat_priv *bat_priv,
                      uint8_t *addr, char *message)
 {
        struct hna_local_entry *hna_local_entry;
-       unsigned long flags;
 
-       spin_lock_irqsave(&bat_priv->hna_lhash_lock, flags);
+       spin_lock_bh(&bat_priv->hna_lhash_lock);
 
        hna_local_entry = (struct hna_local_entry *)
-               hash_find(bat_priv->hna_local_hash, addr);
+               hash_find(bat_priv->hna_local_hash, compare_orig, choose_orig,
+                         addr);
+
        if (hna_local_entry)
                hna_local_del(bat_priv, hna_local_entry, message);
 
-       spin_unlock_irqrestore(&bat_priv->hna_lhash_lock, flags);
+       spin_unlock_bh(&bat_priv->hna_lhash_lock);
 }
 
 static void hna_local_purge(struct work_struct *work)
@@ -258,25 +269,33 @@ static void hna_local_purge(struct work_struct *work)
                container_of(work, struct delayed_work, work);
        struct bat_priv *bat_priv =
                container_of(delayed_work, struct bat_priv, hna_work);
+       struct hashtable_t *hash = bat_priv->hna_local_hash;
        struct hna_local_entry *hna_local_entry;
-       HASHIT(hashit);
-       unsigned long flags;
+       int i;
+       struct hlist_node *walk, *safe;
+       struct hlist_head *head;
+       struct element_t *bucket;
        unsigned long timeout;
 
-       spin_lock_irqsave(&bat_priv->hna_lhash_lock, flags);
+       spin_lock_bh(&bat_priv->hna_lhash_lock);
 
-       while (hash_iterate(bat_priv->hna_local_hash, &hashit)) {
-               hna_local_entry = hashit.bucket->data;
+       for (i = 0; i < hash->size; i++) {
+               head = &hash->table[i];
 
-               timeout = hna_local_entry->last_seen + LOCAL_HNA_TIMEOUT * HZ;
+               hlist_for_each_entry_safe(bucket, walk, safe, head, hlist) {
+                       hna_local_entry = bucket->data;
 
-               if ((!hna_local_entry->never_purge) &&
-                   time_after(jiffies, timeout))
-                       hna_local_del(bat_priv, hna_local_entry,
-                                     "address timed out");
+                       timeout = hna_local_entry->last_seen;
+                       timeout += LOCAL_HNA_TIMEOUT * HZ;
+
+                       if ((!hna_local_entry->never_purge) &&
+                           time_after(jiffies, timeout))
+                               hna_local_del(bat_priv, hna_local_entry,
+                                       "address timed out");
+               }
        }
 
-       spin_unlock_irqrestore(&bat_priv->hna_lhash_lock, flags);
+       spin_unlock_bh(&bat_priv->hna_lhash_lock);
        hna_local_start_timer(bat_priv);
 }
 
@@ -295,7 +314,7 @@ int hna_global_init(struct bat_priv *bat_priv)
        if (bat_priv->hna_global_hash)
                return 1;
 
-       bat_priv->hna_global_hash = hash_new(128, compare_orig, choose_orig);
+       bat_priv->hna_global_hash = hash_new(1024);
 
        if (!bat_priv->hna_global_hash)
                return 0;
@@ -309,21 +328,19 @@ void hna_global_add_orig(struct bat_priv *bat_priv,
 {
        struct hna_global_entry *hna_global_entry;
        struct hna_local_entry *hna_local_entry;
-       struct hashtable_t *swaphash;
        int hna_buff_count = 0;
-       unsigned long flags;
        unsigned char *hna_ptr;
 
        while ((hna_buff_count + 1) * ETH_ALEN <= hna_buff_len) {
-               spin_lock_irqsave(&bat_priv->hna_ghash_lock, flags);
+               spin_lock_bh(&bat_priv->hna_ghash_lock);
 
                hna_ptr = hna_buff + (hna_buff_count * ETH_ALEN);
                hna_global_entry = (struct hna_global_entry *)
-                       hash_find(bat_priv->hna_global_hash, hna_ptr);
+                       hash_find(bat_priv->hna_global_hash, compare_orig,
+                                 choose_orig, hna_ptr);
 
                if (!hna_global_entry) {
-                       spin_unlock_irqrestore(&bat_priv->hna_ghash_lock,
-                                              flags);
+                       spin_unlock_bh(&bat_priv->hna_ghash_lock);
 
                        hna_global_entry =
                                kmalloc(sizeof(struct hna_global_entry),
@@ -339,26 +356,28 @@ void hna_global_add_orig(struct bat_priv *bat_priv,
                                "%pM (via %pM)\n",
                                hna_global_entry->addr, orig_node->orig);
 
-                       spin_lock_irqsave(&bat_priv->hna_ghash_lock, flags);
-                       hash_add(bat_priv->hna_global_hash, hna_global_entry);
+                       spin_lock_bh(&bat_priv->hna_ghash_lock);
+                       hash_add(bat_priv->hna_global_hash, compare_orig,
+                                choose_orig, hna_global_entry);
 
                }
 
                hna_global_entry->orig_node = orig_node;
-               spin_unlock_irqrestore(&bat_priv->hna_ghash_lock, flags);
+               spin_unlock_bh(&bat_priv->hna_ghash_lock);
 
                /* remove address from local hash if present */
-               spin_lock_irqsave(&bat_priv->hna_lhash_lock, flags);
+               spin_lock_bh(&bat_priv->hna_lhash_lock);
 
                hna_ptr = hna_buff + (hna_buff_count * ETH_ALEN);
                hna_local_entry = (struct hna_local_entry *)
-                       hash_find(bat_priv->hna_local_hash, hna_ptr);
+                       hash_find(bat_priv->hna_local_hash, compare_orig,
+                                 choose_orig, hna_ptr);
 
                if (hna_local_entry)
                        hna_local_del(bat_priv, hna_local_entry,
                                      "global hna received");
 
-               spin_unlock_irqrestore(&bat_priv->hna_lhash_lock, flags);
+               spin_unlock_bh(&bat_priv->hna_lhash_lock);
 
                hna_buff_count++;
        }
@@ -374,31 +393,18 @@ void hna_global_add_orig(struct bat_priv *bat_priv,
                        orig_node->hna_buff_len = hna_buff_len;
                }
        }
-
-       spin_lock_irqsave(&bat_priv->hna_ghash_lock, flags);
-
-       if (bat_priv->hna_global_hash->elements * 4 >
-                                       bat_priv->hna_global_hash->size) {
-               swaphash = hash_resize(bat_priv->hna_global_hash,
-                                      bat_priv->hna_global_hash->size * 2);
-
-               if (!swaphash)
-                       pr_err("Couldn't resize global hna hash table\n");
-               else
-                       bat_priv->hna_global_hash = swaphash;
-       }
-
-       spin_unlock_irqrestore(&bat_priv->hna_ghash_lock, flags);
 }
 
 int hna_global_seq_print_text(struct seq_file *seq, void *offset)
 {
        struct net_device *net_dev = (struct net_device *)seq->private;
        struct bat_priv *bat_priv = netdev_priv(net_dev);
+       struct hashtable_t *hash = bat_priv->hna_global_hash;
        struct hna_global_entry *hna_global_entry;
-       HASHIT(hashit);
-       HASHIT(hashit_count);
-       unsigned long flags;
+       int i;
+       struct hlist_node *walk;
+       struct hlist_head *head;
+       struct element_t *bucket;
        size_t buf_size, pos;
        char *buff;
 
@@ -411,30 +417,39 @@ int hna_global_seq_print_text(struct seq_file *seq, void *offset)
        seq_printf(seq, "Globally announced HNAs received via the mesh %s\n",
                   net_dev->name);
 
-       spin_lock_irqsave(&bat_priv->hna_ghash_lock, flags);
+       spin_lock_bh(&bat_priv->hna_ghash_lock);
 
        buf_size = 1;
        /* Estimate length for: " * xx:xx:xx:xx:xx:xx via xx:xx:xx:xx:xx:xx\n"*/
-       while (hash_iterate(bat_priv->hna_global_hash, &hashit_count))
-               buf_size += 43;
+       for (i = 0; i < hash->size; i++) {
+               head = &hash->table[i];
+
+               hlist_for_each(walk, head)
+                       buf_size += 43;
+       }
 
        buff = kmalloc(buf_size, GFP_ATOMIC);
        if (!buff) {
-               spin_unlock_irqrestore(&bat_priv->hna_ghash_lock, flags);
+               spin_unlock_bh(&bat_priv->hna_ghash_lock);
                return -ENOMEM;
        }
        buff[0] = '\0';
        pos = 0;
 
-       while (hash_iterate(bat_priv->hna_global_hash, &hashit)) {
-               hna_global_entry = hashit.bucket->data;
+       for (i = 0; i < hash->size; i++) {
+               head = &hash->table[i];
 
-               pos += snprintf(buff + pos, 44,
-                               " * %pM via %pM\n", hna_global_entry->addr,
-                               hna_global_entry->orig_node->orig);
+               hlist_for_each_entry(bucket, walk, head, hlist) {
+                       hna_global_entry = bucket->data;
+
+                       pos += snprintf(buff + pos, 44,
+                                       " * %pM via %pM\n",
+                                       hna_global_entry->addr,
+                                       hna_global_entry->orig_node->orig);
+               }
        }
 
-       spin_unlock_irqrestore(&bat_priv->hna_ghash_lock, flags);
+       spin_unlock_bh(&bat_priv->hna_ghash_lock);
 
        seq_printf(seq, "%s", buff);
        kfree(buff);
@@ -450,7 +465,8 @@ static void _hna_global_del_orig(struct bat_priv *bat_priv,
                hna_global_entry->addr, hna_global_entry->orig_node->orig,
                message);
 
-       hash_remove(bat_priv->hna_global_hash, hna_global_entry->addr);
+       hash_remove(bat_priv->hna_global_hash, compare_orig, choose_orig,
+                   hna_global_entry->addr);
        kfree(hna_global_entry);
 }
 
@@ -459,18 +475,18 @@ void hna_global_del_orig(struct bat_priv *bat_priv,
 {
        struct hna_global_entry *hna_global_entry;
        int hna_buff_count = 0;
-       unsigned long flags;
        unsigned char *hna_ptr;
 
        if (orig_node->hna_buff_len == 0)
                return;
 
-       spin_lock_irqsave(&bat_priv->hna_ghash_lock, flags);
+       spin_lock_bh(&bat_priv->hna_ghash_lock);
 
        while ((hna_buff_count + 1) * ETH_ALEN <= orig_node->hna_buff_len) {
                hna_ptr = orig_node->hna_buff + (hna_buff_count * ETH_ALEN);
                hna_global_entry = (struct hna_global_entry *)
-                       hash_find(bat_priv->hna_global_hash, hna_ptr);
+                       hash_find(bat_priv->hna_global_hash, compare_orig,
+                                 choose_orig, hna_ptr);
 
                if ((hna_global_entry) &&
                    (hna_global_entry->orig_node == orig_node))
@@ -480,7 +496,7 @@ void hna_global_del_orig(struct bat_priv *bat_priv,
                hna_buff_count++;
        }
 
-       spin_unlock_irqrestore(&bat_priv->hna_ghash_lock, flags);
+       spin_unlock_bh(&bat_priv->hna_ghash_lock);
 
        orig_node->hna_buff_len = 0;
        kfree(orig_node->hna_buff);
@@ -504,12 +520,12 @@ void hna_global_free(struct bat_priv *bat_priv)
 struct orig_node *transtable_search(struct bat_priv *bat_priv, uint8_t *addr)
 {
        struct hna_global_entry *hna_global_entry;
-       unsigned long flags;
 
-       spin_lock_irqsave(&bat_priv->hna_ghash_lock, flags);
+       spin_lock_bh(&bat_priv->hna_ghash_lock);
        hna_global_entry = (struct hna_global_entry *)
-                               hash_find(bat_priv->hna_global_hash, addr);
-       spin_unlock_irqrestore(&bat_priv->hna_ghash_lock, flags);
+                               hash_find(bat_priv->hna_global_hash,
+                                         compare_orig, choose_orig, addr);
+       spin_unlock_bh(&bat_priv->hna_ghash_lock);
 
        if (!hna_global_entry)
                return NULL;