[ATM]: [lec] convert lec_arp_table to hlist
authorChas Williams <chas@cmf.nrl.navy.mil>
Sat, 30 Sep 2006 00:14:27 +0000 (17:14 -0700)
committerDavid S. Miller <davem@davemloft.net>
Sat, 30 Sep 2006 00:14:27 +0000 (17:14 -0700)
Signed-off-by: Chas Williams <chas@cmf.nrl.navy.mil>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/atm/lec.c
net/atm/lec.h
net/atm/lec_arpc.h

index d2b44e9..eb94e94 100644 (file)
@@ -806,7 +806,7 @@ static void lec_push(struct atm_vcc *vcc, struct sk_buff *skb)
                        dev_kfree_skb(skb);
                        return;
                }
-               if (priv->lec_arp_empty_ones) {
+               if (!hlist_empty(&priv->lec_arp_empty_ones)) {
                        lec_arp_check_empties(priv, vcc, skb);
                }
                skb->dev = dev;
@@ -998,29 +998,32 @@ static void lec_info(struct seq_file *seq, struct lec_arp_table *entry)
 struct lec_state {
        unsigned long flags;
        struct lec_priv *locked;
-       struct lec_arp_table *entry;
+       struct hlist_node *node;
        struct net_device *dev;
        int itf;
        int arp_table;
        int misc_table;
 };
 
-static void *lec_tbl_walk(struct lec_state *state, struct lec_arp_table *tbl,
+static void *lec_tbl_walk(struct lec_state *state, struct hlist_head *tbl,
                          loff_t *l)
 {
-       struct lec_arp_table *e = state->entry;
+       struct hlist_node *e = state->node;
+       struct lec_arp_table *tmp;
 
        if (!e)
-               e = tbl;
+               e = tbl->first;
        if (e == (void *)1) {
-               e = tbl;
+               e = tbl->first;
                --*l;
        }
-       for (; e; e = e->next) {
+
+       hlist_for_each_entry_from(tmp, e, next) {
                if (--*l < 0)
                        break;
        }
-       state->entry = e;
+       state->node = e;
+
        return (*l < 0) ? state : NULL;
 }
 
@@ -1031,7 +1034,7 @@ static void *lec_arp_walk(struct lec_state *state, loff_t *l,
        int p;
 
        for (p = state->arp_table; p < LEC_ARP_TABLE_SIZE; p++) {
-               v = lec_tbl_walk(state, priv->lec_arp_tables[p], l);
+               v = lec_tbl_walk(state, &priv->lec_arp_tables[p], l);
                if (v)
                        break;
        }
@@ -1042,10 +1045,10 @@ static void *lec_arp_walk(struct lec_state *state, loff_t *l,
 static void *lec_misc_walk(struct lec_state *state, loff_t *l,
                           struct lec_priv *priv)
 {
-       struct lec_arp_table *lec_misc_tables[] = {
-               priv->lec_arp_empty_ones,
-               priv->lec_no_forward,
-               priv->mcast_fwds
+       struct hlist_head *lec_misc_tables[] = {
+               &priv->lec_arp_empty_ones,
+               &priv->lec_no_forward,
+               &priv->mcast_fwds
        };
        void *v = NULL;
        int q;
@@ -1112,7 +1115,7 @@ static void *lec_seq_start(struct seq_file *seq, loff_t *pos)
        state->locked = NULL;
        state->arp_table = 0;
        state->misc_table = 0;
-       state->entry = (void *)1;
+       state->node = (void *)1;
 
        return *pos ? lec_get_idx(state, *pos) : (void *)1;
 }
@@ -1148,9 +1151,10 @@ static int lec_seq_show(struct seq_file *seq, void *v)
        else {
                struct lec_state *state = seq->private;
                struct net_device *dev = state->dev;
+               struct lec_arp_table *entry = hlist_entry(state->node, struct lec_arp_table, next);
 
                seq_printf(seq, "%s ", dev->name);
-               lec_info(seq, state->entry);
+               lec_info(seq, entry);
        }
        return 0;
 }
@@ -1455,8 +1459,11 @@ static void lec_arp_init(struct lec_priv *priv)
        unsigned short i;
 
        for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
-               priv->lec_arp_tables[i] = NULL;
+               INIT_HLIST_HEAD(&priv->lec_arp_tables[i]);
        }
+        INIT_HLIST_HEAD(&priv->lec_arp_empty_ones);
+        INIT_HLIST_HEAD(&priv->lec_no_forward);
+        INIT_HLIST_HEAD(&priv->mcast_fwds);
        spin_lock_init(&priv->lec_arp_lock);
        init_timer(&priv->lec_arp_timer);
        priv->lec_arp_timer.expires = jiffies + LEC_ARP_REFRESH_INTERVAL;
@@ -1479,7 +1486,7 @@ static void lec_arp_clear_vccs(struct lec_arp_table *entry)
                vcc->user_back = NULL;
                vcc->push = entry->old_push;
                vcc_release_async(vcc, -EPIPE);
-               vcc = NULL;
+               entry->vcc = NULL;
        }
        if (entry->recv_vcc) {
                entry->recv_vcc->push = entry->old_recv_push;
@@ -1493,27 +1500,17 @@ static void lec_arp_clear_vccs(struct lec_arp_table *entry)
  * LANE2: Add to the end of the list to satisfy 8.1.13
  */
 static inline void
-lec_arp_add(struct lec_priv *priv, struct lec_arp_table *to_add)
+lec_arp_add(struct lec_priv *priv, struct lec_arp_table *entry)
 {
-       unsigned short place;
-       struct lec_arp_table *tmp;
+       struct hlist_head *tmp;
 
-       place = HASH(to_add->mac_addr[ETH_ALEN - 1]);
-       tmp = priv->lec_arp_tables[place];
-       to_add->next = NULL;
-       if (tmp == NULL)
-               priv->lec_arp_tables[place] = to_add;
-
-       else {                  /* add to the end */
-               while (tmp->next)
-                       tmp = tmp->next;
-               tmp->next = to_add;
-       }
+       tmp = &priv->lec_arp_tables[HASH(entry->mac_addr[ETH_ALEN - 1])];
+       hlist_add_head(&entry->next, tmp);
 
        DPRINTK("LEC_ARP: Added entry:%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n",
-               0xff & to_add->mac_addr[0], 0xff & to_add->mac_addr[1],
-               0xff & to_add->mac_addr[2], 0xff & to_add->mac_addr[3],
-               0xff & to_add->mac_addr[4], 0xff & to_add->mac_addr[5]);
+               0xff & entry->mac_addr[0], 0xff & entry->mac_addr[1],
+               0xff & entry->mac_addr[2], 0xff & entry->mac_addr[3],
+               0xff & entry->mac_addr[4], 0xff & entry->mac_addr[5]);
 }
 
 /*
@@ -1522,40 +1519,26 @@ lec_arp_add(struct lec_priv *priv, struct lec_arp_table *to_add)
 static int
 lec_arp_remove(struct lec_priv *priv, struct lec_arp_table *to_remove)
 {
-       unsigned short place;
-       struct lec_arp_table *tmp;
-       int remove_vcc = 1;
+       struct hlist_node *node;
+       struct lec_arp_table *entry;
+       int i, remove_vcc = 1;
 
        if (!to_remove) {
                return -1;
        }
-       place = HASH(to_remove->mac_addr[ETH_ALEN - 1]);
-       tmp = priv->lec_arp_tables[place];
-       if (tmp == to_remove) {
-               priv->lec_arp_tables[place] = tmp->next;
-       } else {
-               while (tmp && tmp->next != to_remove) {
-                       tmp = tmp->next;
-               }
-               if (!tmp) {     /* Entry was not found */
-                       return -1;
-               }
-       }
-       tmp->next = to_remove->next;
+
+       hlist_del(&to_remove->next);
        del_timer(&to_remove->timer);
 
-       /* If this is the only MAC connected to this VCC, also tear down
-          the VCC */
+       /* If this is the only MAC connected to this VCC, also tear down the VCC */
        if (to_remove->status >= ESI_FLUSH_PENDING) {
                /*
                 * ESI_FLUSH_PENDING, ESI_FORWARD_DIRECT
                 */
-               for (place = 0; place < LEC_ARP_TABLE_SIZE; place++) {
-                       for (tmp = priv->lec_arp_tables[place]; tmp != NULL;
-                            tmp = tmp->next) {
-                               if (memcmp
-                                   (tmp->atm_addr, to_remove->atm_addr,
-                                    ATM_ESA_LEN) == 0) {
+               for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
+                       hlist_for_each_entry(entry, node, &priv->lec_arp_tables[i], next) {
+                               if (memcmp(to_remove->atm_addr,
+                                          entry->atm_addr, ATM_ESA_LEN) == 0) {
                                        remove_vcc = 0;
                                        break;
                                }
@@ -1591,28 +1574,19 @@ static char *get_status_string(unsigned char st)
                return "<UNKNOWN>";
        }
 }
-#endif
 
 static void dump_arp_table(struct lec_priv *priv)
 {
-#if DEBUG_ARP_TABLE
-       int i, j, offset;
+       struct hlist_node *node;
        struct lec_arp_table *rulla;
-       char buf[1024];
-       struct lec_arp_table **lec_arp_tables =
-           (struct lec_arp_table **)priv->lec_arp_tables;
-       struct lec_arp_table *lec_arp_empty_ones =
-           (struct lec_arp_table *)priv->lec_arp_empty_ones;
-       struct lec_arp_table *lec_no_forward =
-           (struct lec_arp_table *)priv->lec_no_forward;
-       struct lec_arp_table *mcast_fwds = priv->mcast_fwds;
+       char buf[256];
+       int i, j, offset;
 
        printk("Dump %p:\n", priv);
        for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
-               rulla = lec_arp_tables[i];
-               offset = 0;
-               offset += sprintf(buf, "%d: %p\n", i, rulla);
-               while (rulla) {
+               hlist_for_each_entry(rulla, node, &priv->lec_arp_tables[i], next) {
+                       offset = 0;
+                       offset += sprintf(buf, "%d: %p\n", i, rulla);
                        offset += sprintf(buf + offset, "Mac:");
                        for (j = 0; j < ETH_ALEN; j++) {
                                offset += sprintf(buf + offset,
@@ -1639,15 +1613,13 @@ static void dump_arp_table(struct lec_priv *priv)
                                    "Flags:%x, Packets_flooded:%x, Status: %s ",
                                    rulla->flags, rulla->packets_flooded,
                                    get_status_string(rulla->status));
-                       offset += sprintf(buf + offset, "->%p\n", rulla->next);
-                       rulla = rulla->next;
+                       printk("%s\n", buf);
                }
-               printk("%s", buf);
        }
-       rulla = lec_no_forward;
-       if (rulla)
+
+       if (!hlist_empty(&priv->lec_no_forward))
                printk("No forward\n");
-       while (rulla) {
+       hlist_for_each_entry(rulla, node, &priv->lec_no_forward, next) {
                offset = 0;
                offset += sprintf(buf + offset, "Mac:");
                for (j = 0; j < ETH_ALEN; j++) {
@@ -1671,14 +1643,12 @@ static void dump_arp_table(struct lec_priv *priv)
                                  "Flags:%x, Packets_flooded:%x, Status: %s ",
                                  rulla->flags, rulla->packets_flooded,
                                  get_status_string(rulla->status));
-               offset += sprintf(buf + offset, "->%lx\n", (long)rulla->next);
-               rulla = rulla->next;
-               printk("%s", buf);
+               printk("%s\n", buf);
        }
-       rulla = lec_arp_empty_ones;
-       if (rulla)
+
+       if (!hlist_empty(&priv->lec_arp_empty_ones))
                printk("Empty ones\n");
-       while (rulla) {
+       hlist_for_each_entry(rulla, node, &priv->lec_arp_empty_ones, next) {
                offset = 0;
                offset += sprintf(buf + offset, "Mac:");
                for (j = 0; j < ETH_ALEN; j++) {
@@ -1702,15 +1672,12 @@ static void dump_arp_table(struct lec_priv *priv)
                                  "Flags:%x, Packets_flooded:%x, Status: %s ",
                                  rulla->flags, rulla->packets_flooded,
                                  get_status_string(rulla->status));
-               offset += sprintf(buf + offset, "->%lx\n", (long)rulla->next);
-               rulla = rulla->next;
                printk("%s", buf);
        }
 
-       rulla = mcast_fwds;
-       if (rulla)
+       if (!hlist_empty(&priv->mcast_fwds))
                printk("Multicast Forward VCCs\n");
-       while (rulla) {
+       hlist_for_each_entry(rulla, node, &priv->mcast_fwds, next) {
                offset = 0;
                offset += sprintf(buf + offset, "Mac:");
                for (j = 0; j < ETH_ALEN; j++) {
@@ -1734,13 +1701,13 @@ static void dump_arp_table(struct lec_priv *priv)
                                  "Flags:%x, Packets_flooded:%x, Status: %s ",
                                  rulla->flags, rulla->packets_flooded,
                                  get_status_string(rulla->status));
-               offset += sprintf(buf + offset, "->%lx\n", (long)rulla->next);
-               rulla = rulla->next;
-               printk("%s", buf);
+               printk("%s\n", buf);
        }
 
-#endif
 }
+#else
+#define dump_arp_table(priv) do { } while (0)
+#endif
 
 /*
  * Destruction of arp-cache
@@ -1748,7 +1715,8 @@ static void dump_arp_table(struct lec_priv *priv)
 static void lec_arp_destroy(struct lec_priv *priv)
 {
        unsigned long flags;
-       struct lec_arp_table *entry, *next;
+       struct hlist_node *node, *next;
+       struct lec_arp_table *entry;
        int i;
 
        del_timer_sync(&priv->lec_arp_timer);
@@ -1759,43 +1727,37 @@ static void lec_arp_destroy(struct lec_priv *priv)
 
        spin_lock_irqsave(&priv->lec_arp_lock, flags);
        for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
-               for (entry = priv->lec_arp_tables[i]; entry != NULL;
-                    entry = next) {
-                       next = entry->next;
+               hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_tables[i], next) {
                        lec_arp_remove(priv, entry);
                        kfree(entry);
                }
+               INIT_HLIST_HEAD(&priv->lec_arp_tables[i]);
        }
-       entry = priv->lec_arp_empty_ones;
-       while (entry) {
-               next = entry->next;
+
+       hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_empty_ones, next) {
                del_timer_sync(&entry->timer);
                lec_arp_clear_vccs(entry);
+               hlist_del(&entry->next);
                kfree(entry);
-               entry = next;
        }
-       priv->lec_arp_empty_ones = NULL;
-       entry = priv->lec_no_forward;
-       while (entry) {
-               next = entry->next;
+       INIT_HLIST_HEAD(&priv->lec_arp_empty_ones);
+
+       hlist_for_each_entry_safe(entry, node, next, &priv->lec_no_forward, next) {
                del_timer_sync(&entry->timer);
                lec_arp_clear_vccs(entry);
+               hlist_del(&entry->next);
                kfree(entry);
-               entry = next;
        }
-       priv->lec_no_forward = NULL;
-       entry = priv->mcast_fwds;
-       while (entry) {
-               next = entry->next;
+       INIT_HLIST_HEAD(&priv->lec_no_forward);
+
+       hlist_for_each_entry_safe(entry, node, next, &priv->mcast_fwds, next) {
                /* No timer, LANEv2 7.1.20 and 2.3.5.3 */
                lec_arp_clear_vccs(entry);
+               hlist_del(&entry->next);
                kfree(entry);
-               entry = next;
        }
-       priv->mcast_fwds = NULL;
+       INIT_HLIST_HEAD(&priv->mcast_fwds);
        priv->mcast_vcc = NULL;
-       memset(priv->lec_arp_tables, 0,
-              sizeof(struct lec_arp_table *) * LEC_ARP_TABLE_SIZE);
        spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
 }
 
@@ -1805,20 +1767,19 @@ static void lec_arp_destroy(struct lec_priv *priv)
 static struct lec_arp_table *lec_arp_find(struct lec_priv *priv,
                                          unsigned char *mac_addr)
 {
-       unsigned short place;
-       struct lec_arp_table *to_return;
+       struct hlist_node *node;
+       struct hlist_head *head;
+       struct lec_arp_table *entry;
 
        DPRINTK("LEC_ARP: lec_arp_find :%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n",
                mac_addr[0] & 0xff, mac_addr[1] & 0xff, mac_addr[2] & 0xff,
                mac_addr[3] & 0xff, mac_addr[4] & 0xff, mac_addr[5] & 0xff);
-       place = HASH(mac_addr[ETH_ALEN - 1]);
 
-       to_return = priv->lec_arp_tables[place];
-       while (to_return) {
-               if (!compare_ether_addr(mac_addr, to_return->mac_addr)) {
-                       return to_return;
+       head = &priv->lec_arp_tables[HASH(mac_addr[ETH_ALEN - 1])];
+       hlist_for_each_entry(entry, node, head, next) {
+               if (!compare_ether_addr(mac_addr, entry->mac_addr)) {
+                       return entry;
                }
-               to_return = to_return->next;
        }
        return NULL;
 }
@@ -1834,6 +1795,7 @@ static struct lec_arp_table *make_entry(struct lec_priv *priv,
                return NULL;
        }
        memcpy(to_return->mac_addr, mac_addr, ETH_ALEN);
+       INIT_HLIST_NODE(&to_return->next);
        init_timer(&to_return->timer);
        to_return->timer.function = lec_arp_expire_arp;
        to_return->timer.data = (unsigned long)to_return;
@@ -1871,7 +1833,6 @@ static void lec_arp_expire_vcc(unsigned long data)
        unsigned long flags;
        struct lec_arp_table *to_remove = (struct lec_arp_table *)data;
        struct lec_priv *priv = (struct lec_priv *)to_remove->priv;
-       struct lec_arp_table *entry = NULL;
 
        del_timer(&to_remove->timer);
 
@@ -1879,30 +1840,9 @@ static void lec_arp_expire_vcc(unsigned long data)
                to_remove, priv,
                to_remove->vcc ? to_remove->recv_vcc->vpi : 0,
                to_remove->vcc ? to_remove->recv_vcc->vci : 0);
-       DPRINTK("eo:%p nf:%p\n", priv->lec_arp_empty_ones,
-               priv->lec_no_forward);
 
        spin_lock_irqsave(&priv->lec_arp_lock, flags);
-       if (to_remove == priv->lec_arp_empty_ones)
-               priv->lec_arp_empty_ones = to_remove->next;
-       else {
-               entry = priv->lec_arp_empty_ones;
-               while (entry && entry->next != to_remove)
-                       entry = entry->next;
-               if (entry)
-                       entry->next = to_remove->next;
-       }
-       if (!entry) {
-               if (to_remove == priv->lec_no_forward) {
-                       priv->lec_no_forward = to_remove->next;
-               } else {
-                       entry = priv->lec_no_forward;
-                       while (entry && entry->next != to_remove)
-                               entry = entry->next;
-                       if (entry)
-                               entry->next = to_remove->next;
-               }
-       }
+       hlist_del(&to_remove->next);
        spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
 
        lec_arp_clear_vccs(to_remove);
@@ -1929,18 +1869,17 @@ static void lec_arp_check_expire(unsigned long data)
 {
        unsigned long flags;
        struct lec_priv *priv = (struct lec_priv *)data;
-       struct lec_arp_table *entry, *next;
+       struct hlist_node *node, *next;
+       struct lec_arp_table *entry;
        unsigned long now;
        unsigned long time_to_check;
        int i;
 
        DPRINTK("lec_arp_check_expire %p\n", priv);
-       DPRINTK("expire: eo:%p nf:%p\n", priv->lec_arp_empty_ones,
-               priv->lec_no_forward);
        now = jiffies;
        spin_lock_irqsave(&priv->lec_arp_lock, flags);
        for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
-               for (entry = priv->lec_arp_tables[i]; entry != NULL;) {
+               hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_tables[i], next) {
                        if ((entry->flags) & LEC_REMOTE_FLAG &&
                            priv->topology_change)
                                time_to_check = priv->forward_delay_time;
@@ -1954,10 +1893,8 @@ static void lec_arp_check_expire(unsigned long data)
                            && !(entry->mac_addr[0] & 0x01)) {  /* LANE2: 7.1.20 */
                                /* Remove entry */
                                DPRINTK("LEC:Entry timed out\n");
-                               next = entry->next;
                                lec_arp_remove(priv, entry);
                                kfree(entry);
-                               entry = next;
                        } else {
                                /* Something else */
                                if ((entry->status == ESI_VC_PENDING ||
@@ -1988,7 +1925,6 @@ static void lec_arp_check_expire(unsigned long data)
                                        entry->last_used = jiffies;
                                        entry->status = ESI_FORWARD_DIRECT;
                                }
-                               entry = entry->next;
                        }
                }
        }
@@ -2100,15 +2036,14 @@ lec_addr_delete(struct lec_priv *priv, unsigned char *atm_addr,
                unsigned long permanent)
 {
        unsigned long flags;
-       struct lec_arp_table *entry, *next;
+       struct hlist_node *node, *next;
+       struct lec_arp_table *entry;
        int i;
 
        DPRINTK("lec_addr_delete\n");
        spin_lock_irqsave(&priv->lec_arp_lock, flags);
        for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
-               for (entry = priv->lec_arp_tables[i]; entry != NULL;
-                    entry = next) {
-                       next = entry->next;
+               hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_tables[i], next) {
                        if (!memcmp(atm_addr, entry->atm_addr, ATM_ESA_LEN)
                            && (permanent ||
                                !(entry->flags & LEC_PERMANENT_FLAG))) {
@@ -2132,6 +2067,7 @@ lec_arp_update(struct lec_priv *priv, unsigned char *mac_addr,
               unsigned int targetless_le_arp)
 {
        unsigned long flags;
+       struct hlist_node *node, *next;
        struct lec_arp_table *entry, *tmp;
        int i;
 
@@ -2147,50 +2083,39 @@ lec_arp_update(struct lec_priv *priv, unsigned char *mac_addr,
                                 * LANE2: ignore targetless LE_ARPs for which
                                 * we have no entry in the cache. 7.1.30
                                 */
-       if (priv->lec_arp_empty_ones) {
-               entry = priv->lec_arp_empty_ones;
-               if (!memcmp(entry->atm_addr, atm_addr, ATM_ESA_LEN)) {
-                       priv->lec_arp_empty_ones = entry->next;
-               } else {
-                       while (entry->next && memcmp(entry->next->atm_addr,
-                                                    atm_addr, ATM_ESA_LEN))
-                               entry = entry->next;
-                       if (entry->next) {
-                               tmp = entry;
-                               entry = entry->next;
-                               tmp->next = entry->next;
-                       } else
-                               entry = NULL;
-
-               }
-               if (entry) {
-                       del_timer(&entry->timer);
-                       tmp = lec_arp_find(priv, mac_addr);
-                       if (tmp) {
-                               del_timer(&tmp->timer);
-                               tmp->status = ESI_FORWARD_DIRECT;
-                               memcpy(tmp->atm_addr, atm_addr, ATM_ESA_LEN);
-                               tmp->vcc = entry->vcc;
-                               tmp->old_push = entry->old_push;
-                               tmp->last_used = jiffies;
+       if (!hlist_empty(&priv->lec_arp_empty_ones)) {
+               hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_empty_ones, next) {
+                       if (memcmp(entry->atm_addr, atm_addr, ATM_ESA_LEN) == 0) {
+                               hlist_del(&entry->next);
                                del_timer(&entry->timer);
-                               kfree(entry);
-                               entry = tmp;
-                       } else {
-                               entry->status = ESI_FORWARD_DIRECT;
-                               memcpy(entry->mac_addr, mac_addr, ETH_ALEN);
-                               entry->last_used = jiffies;
-                               lec_arp_add(priv, entry);
+                               tmp = lec_arp_find(priv, mac_addr);
+                               if (tmp) {
+                                       del_timer(&tmp->timer);
+                                       tmp->status = ESI_FORWARD_DIRECT;
+                                       memcpy(tmp->atm_addr, atm_addr, ATM_ESA_LEN);
+                                       tmp->vcc = entry->vcc;
+                                       tmp->old_push = entry->old_push;
+                                       tmp->last_used = jiffies;
+                                       del_timer(&entry->timer);
+                                       kfree(entry);
+                                       entry = tmp;
+                               } else {
+                                       entry->status = ESI_FORWARD_DIRECT;
+                                       memcpy(entry->mac_addr, mac_addr, ETH_ALEN);
+                                       entry->last_used = jiffies;
+                                       lec_arp_add(priv, entry);
+                               }
+                               if (remoteflag)
+                                       entry->flags |= LEC_REMOTE_FLAG;
+                               else
+                                       entry->flags &= ~LEC_REMOTE_FLAG;
+                               DPRINTK("After update\n");
+                               dump_arp_table(priv);
+                               goto out;
                        }
-                       if (remoteflag)
-                               entry->flags |= LEC_REMOTE_FLAG;
-                       else
-                               entry->flags &= ~LEC_REMOTE_FLAG;
-                       DPRINTK("After update\n");
-                       dump_arp_table(priv);
-                       goto out;
                }
        }
+
        entry = lec_arp_find(priv, mac_addr);
        if (!entry) {
                entry = make_entry(priv, mac_addr);
@@ -2203,7 +2128,7 @@ lec_arp_update(struct lec_priv *priv, unsigned char *mac_addr,
        memcpy(entry->atm_addr, atm_addr, ATM_ESA_LEN);
        del_timer(&entry->timer);
        for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
-               for (tmp = priv->lec_arp_tables[i]; tmp; tmp = tmp->next) {
+               hlist_for_each_entry(tmp, node, &priv->lec_arp_tables[i], next) {
                        if (entry != tmp &&
                            !memcmp(tmp->atm_addr, atm_addr, ATM_ESA_LEN)) {
                                /* Vcc to this host exists */
@@ -2226,8 +2151,7 @@ lec_arp_update(struct lec_priv *priv, unsigned char *mac_addr,
                entry->flags &= ~LEC_REMOTE_FLAG;
        if (entry->status == ESI_ARP_PENDING || entry->status == ESI_UNKNOWN) {
                entry->status = ESI_VC_PENDING;
-               send_to_lecd(priv, l_svc_setup, entry->mac_addr, atm_addr,
-                            NULL);
+               send_to_lecd(priv, l_svc_setup, entry->mac_addr, atm_addr, NULL);
        }
        DPRINTK("After update2\n");
        dump_arp_table(priv);
@@ -2244,6 +2168,7 @@ lec_vcc_added(struct lec_priv *priv, struct atmlec_ioc *ioc_data,
              void (*old_push) (struct atm_vcc *vcc, struct sk_buff *skb))
 {
        unsigned long flags;
+       struct hlist_node *node;
        struct lec_arp_table *entry;
        int i, found_entry = 0;
 
@@ -2269,8 +2194,7 @@ lec_vcc_added(struct lec_priv *priv, struct atmlec_ioc *ioc_data,
                memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN);
                entry->recv_vcc = vcc;
                entry->old_recv_push = old_push;
-               entry->next = priv->mcast_fwds;
-               priv->mcast_fwds = entry;
+               hlist_add_head(&entry->next, &priv->mcast_fwds);
                goto out;
        } else if (ioc_data->receive == 1) {
                /*
@@ -2300,9 +2224,8 @@ lec_vcc_added(struct lec_priv *priv, struct atmlec_ioc *ioc_data,
                entry->status = ESI_UNKNOWN;
                entry->timer.expires = jiffies + priv->vcc_timeout_period;
                entry->timer.function = lec_arp_expire_vcc;
+               hlist_add_head(&entry->next, &priv->lec_no_forward);
                add_timer(&entry->timer);
-               entry->next = priv->lec_no_forward;
-               priv->lec_no_forward = entry;
                dump_arp_table(priv);
                goto out;
        }
@@ -2320,8 +2243,7 @@ lec_vcc_added(struct lec_priv *priv, struct atmlec_ioc *ioc_data,
             ioc_data->atm_addr[16], ioc_data->atm_addr[17],
             ioc_data->atm_addr[18], ioc_data->atm_addr[19]);
        for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
-               for (entry = priv->lec_arp_tables[i]; entry;
-                    entry = entry->next) {
+               hlist_for_each_entry(entry, node, &priv->lec_arp_tables[i], next) {
                        if (memcmp
                            (ioc_data->atm_addr, entry->atm_addr,
                             ATM_ESA_LEN) == 0) {
@@ -2384,8 +2306,7 @@ lec_vcc_added(struct lec_priv *priv, struct atmlec_ioc *ioc_data,
        memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN);
        memset(entry->mac_addr, 0, ETH_ALEN);
        entry->status = ESI_UNKNOWN;
-       entry->next = priv->lec_arp_empty_ones;
-       priv->lec_arp_empty_ones = entry;
+       hlist_add_head(&entry->next, &priv->lec_arp_empty_ones);
        entry->timer.expires = jiffies + priv->vcc_timeout_period;
        entry->timer.function = lec_arp_expire_vcc;
        add_timer(&entry->timer);
@@ -2398,14 +2319,14 @@ out:
 static void lec_flush_complete(struct lec_priv *priv, unsigned long tran_id)
 {
        unsigned long flags;
+       struct hlist_node *node;
        struct lec_arp_table *entry;
        int i;
 
        DPRINTK("LEC:lec_flush_complete %lx\n", tran_id);
        spin_lock_irqsave(&priv->lec_arp_lock, flags);
        for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
-               for (entry = priv->lec_arp_tables[i]; entry;
-                    entry = entry->next) {
+               hlist_for_each_entry(entry, node, &priv->lec_arp_tables[i], next) {
                        if (entry->flush_tran_id == tran_id
                            && entry->status == ESI_FLUSH_PENDING) {
                                struct sk_buff *skb;
@@ -2427,19 +2348,19 @@ lec_set_flush_tran_id(struct lec_priv *priv,
                      unsigned char *atm_addr, unsigned long tran_id)
 {
        unsigned long flags;
+       struct hlist_node *node;
        struct lec_arp_table *entry;
        int i;
 
        spin_lock_irqsave(&priv->lec_arp_lock, flags);
        for (i = 0; i < LEC_ARP_TABLE_SIZE; i++)
-               for (entry = priv->lec_arp_tables[i]; entry;
-                    entry = entry->next)
+               hlist_for_each_entry(entry, node, &priv->lec_arp_tables[i], next) {
                        if (!memcmp(atm_addr, entry->atm_addr, ATM_ESA_LEN)) {
                                entry->flush_tran_id = tran_id;
-                               DPRINTK
-                                   ("Set flush transaction id to %lx for %p\n",
-                                    tran_id, entry);
+                               DPRINTK("Set flush transaction id to %lx for %p\n",
+                                       tran_id, entry);
                        }
+               }
        spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
 }
 
@@ -2483,15 +2404,17 @@ out:
 static void lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc)
 {
        unsigned long flags;
-       struct lec_arp_table *entry, *next;
+       struct hlist_node *node, *next;
+       struct lec_arp_table *entry;
        int i;
 
        DPRINTK("LEC_ARP: lec_vcc_close vpi:%d vci:%d\n", vcc->vpi, vcc->vci);
        dump_arp_table(priv);
+
        spin_lock_irqsave(&priv->lec_arp_lock, flags);
+
        for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
-               for (entry = priv->lec_arp_tables[i]; entry; entry = next) {
-                       next = entry->next;
+               hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_tables[i], next) {
                        if (vcc == entry->vcc) {
                                lec_arp_remove(priv, entry);
                                kfree(entry);
@@ -2502,49 +2425,31 @@ static void lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc)
                }
        }
 
-       entry = priv->lec_arp_empty_ones;
-       priv->lec_arp_empty_ones = NULL;
-       while (entry != NULL) {
-               next = entry->next;
-               if (entry->vcc == vcc) {        /* leave it out from the list */
+       hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_empty_ones, next) {
+               if (entry->vcc == vcc) {
                        lec_arp_clear_vccs(entry);
                        del_timer(&entry->timer);
+                       hlist_del(&entry->next);
                        kfree(entry);
-               } else {                        /* put it back to the list */
-                       entry->next = priv->lec_arp_empty_ones;
-                       priv->lec_arp_empty_ones = entry;
                }
-               entry = next;
        }
 
-       entry = priv->lec_no_forward;
-       priv->lec_no_forward = NULL;
-       while (entry != NULL) {
-               next = entry->next;
+       hlist_for_each_entry_safe(entry, node, next, &priv->lec_no_forward, next) {
                if (entry->recv_vcc == vcc) {
                        lec_arp_clear_vccs(entry);
                        del_timer(&entry->timer);
+                       hlist_del(&entry->next);
                        kfree(entry);
-               } else {
-                       entry->next = priv->lec_no_forward;
-                       priv->lec_no_forward = entry;
                }
-               entry = next;
        }
 
-       entry = priv->mcast_fwds;
-       priv->mcast_fwds = NULL;
-       while (entry != NULL) {
-               next = entry->next;
+       hlist_for_each_entry_safe(entry, node, next, &priv->mcast_fwds, next) {
                if (entry->recv_vcc == vcc) {
                        lec_arp_clear_vccs(entry);
                        /* No timer, LANEv2 7.1.20 and 2.3.5.3 */
+                       hlist_del(&entry->next);
                        kfree(entry);
-               } else {
-                       entry->next = priv->mcast_fwds;
-                       priv->mcast_fwds = entry;
                }
-               entry = next;
        }
 
        spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
@@ -2556,7 +2461,8 @@ lec_arp_check_empties(struct lec_priv *priv,
                      struct atm_vcc *vcc, struct sk_buff *skb)
 {
        unsigned long flags;
-       struct lec_arp_table *entry, *prev;
+       struct hlist_node *node, *next;
+       struct lec_arp_table *entry, *tmp;
        struct lecdatahdr_8023 *hdr = (struct lecdatahdr_8023 *)skb->data;
        unsigned char *src;
 #ifdef CONFIG_TR
@@ -2569,41 +2475,23 @@ lec_arp_check_empties(struct lec_priv *priv,
                src = hdr->h_source;
 
        spin_lock_irqsave(&priv->lec_arp_lock, flags);
-       entry = priv->lec_arp_empty_ones;
-       if (vcc == entry->vcc) {
-               del_timer(&entry->timer);
-               memcpy(entry->mac_addr, src, ETH_ALEN);
-               entry->status = ESI_FORWARD_DIRECT;
-               entry->last_used = jiffies;
-               priv->lec_arp_empty_ones = entry->next;
-               /* We might have got an entry */
-               if ((prev = lec_arp_find(priv, src))) {
-                       lec_arp_remove(priv, prev);
-                       kfree(prev);
+       hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_empty_ones, next) {
+               if (vcc == entry->vcc) {
+                       del_timer(&entry->timer);
+                       memcpy(entry->mac_addr, src, ETH_ALEN);
+                       entry->status = ESI_FORWARD_DIRECT;
+                       entry->last_used = jiffies;
+                       /* We might have got an entry */
+                       if ((tmp = lec_arp_find(priv, src))) {
+                               lec_arp_remove(priv, tmp);
+                               kfree(tmp);
+                       }
+                       hlist_del(&entry->next);
+                       lec_arp_add(priv, entry);
+                       goto out;
                }
-               lec_arp_add(priv, entry);
-               goto out;
-       }
-       prev = entry;
-       entry = entry->next;
-       while (entry && entry->vcc != vcc) {
-               prev = entry;
-               entry = entry->next;
        }
-       if (!entry) {
-               DPRINTK("LEC_ARP: Arp_check_empties: entry not found!\n");
-               goto out;
-       }
-       del_timer(&entry->timer);
-       memcpy(entry->mac_addr, src, ETH_ALEN);
-       entry->status = ESI_FORWARD_DIRECT;
-       entry->last_used = jiffies;
-       prev->next = entry->next;
-       if ((prev = lec_arp_find(priv, src))) {
-               lec_arp_remove(priv, prev);
-               kfree(prev);
-       }
-       lec_arp_add(priv, entry);
+       DPRINTK("LEC_ARP: Arp_check_empties: entry not found!\n");
 out:
        spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
 }
index c700472..8052641 100644 (file)
@@ -72,18 +72,18 @@ struct lane2_ops {
 struct lec_priv {
        struct net_device_stats stats;
        unsigned short lecid;                   /* Lecid of this client */
-       struct lec_arp_table *lec_arp_empty_ones;
+       struct hlist_head lec_arp_empty_ones;
                                                /* Used for storing VCC's that don't have a MAC address attached yet */
-       struct lec_arp_table *lec_arp_tables[LEC_ARP_TABLE_SIZE];
+       struct hlist_head lec_arp_tables[LEC_ARP_TABLE_SIZE];
                                                /* Actual LE ARP table */
-       struct lec_arp_table *lec_no_forward;
+       struct hlist_head lec_no_forward;
                                                /*
                                                 * Used for storing VCC's (and forward packets from) which are to
                                                 * age out by not using them to forward packets.
                                                 * This is because to some LE clients there will be 2 VCCs. Only
                                                 * one of them gets used.
                                                 */
-       struct lec_arp_table *mcast_fwds;
+       struct hlist_head mcast_fwds;
                                                /*
                                                 * With LANEv2 it is possible that BUS (or a special multicast server)
                                                 * establishes multiple Multicast Forward VCCs to us. This list
index 0230ca1..885f1fb 100644 (file)
@@ -11,7 +11,7 @@
 #include <linux/atmlec.h>
 
 struct lec_arp_table {
-       struct lec_arp_table *next;     /* Linked entry list */
+       struct hlist_node next;         /* Linked entry list */
        unsigned char atm_addr[ATM_ESA_LEN];    /* Atm address */
        unsigned char mac_addr[ETH_ALEN];       /* Mac address */
        int is_rdesc;                   /* Mac address is a route descriptor */