diff options
author | Chas Williams <chas@cmf.nrl.navy.mil> | 2006-09-29 20:14:27 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2006-09-29 20:14:27 -0400 |
commit | d0732f649f090b31f976a9ce59a38e1191077909 (patch) | |
tree | 31309d2d342e0eac8ce4cd28e67fd56a6fd01ed1 /net/atm/lec.c | |
parent | 1c9d3e72a7164c590437f2ab6c2c4f6da91f1703 (diff) |
[ATM]: [lec] convert lec_arp_table to hlist
Signed-off-by: Chas Williams <chas@cmf.nrl.navy.mil>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/atm/lec.c')
-rw-r--r-- | net/atm/lec.c | 442 |
1 files changed, 165 insertions, 277 deletions
diff --git a/net/atm/lec.c b/net/atm/lec.c index d2b44e91badf..eb94e94bffa9 100644 --- a/net/atm/lec.c +++ b/net/atm/lec.c | |||
@@ -806,7 +806,7 @@ static void lec_push(struct atm_vcc *vcc, struct sk_buff *skb) | |||
806 | dev_kfree_skb(skb); | 806 | dev_kfree_skb(skb); |
807 | return; | 807 | return; |
808 | } | 808 | } |
809 | if (priv->lec_arp_empty_ones) { | 809 | if (!hlist_empty(&priv->lec_arp_empty_ones)) { |
810 | lec_arp_check_empties(priv, vcc, skb); | 810 | lec_arp_check_empties(priv, vcc, skb); |
811 | } | 811 | } |
812 | skb->dev = dev; | 812 | skb->dev = dev; |
@@ -998,29 +998,32 @@ static void lec_info(struct seq_file *seq, struct lec_arp_table *entry) | |||
998 | struct lec_state { | 998 | struct lec_state { |
999 | unsigned long flags; | 999 | unsigned long flags; |
1000 | struct lec_priv *locked; | 1000 | struct lec_priv *locked; |
1001 | struct lec_arp_table *entry; | 1001 | struct hlist_node *node; |
1002 | struct net_device *dev; | 1002 | struct net_device *dev; |
1003 | int itf; | 1003 | int itf; |
1004 | int arp_table; | 1004 | int arp_table; |
1005 | int misc_table; | 1005 | int misc_table; |
1006 | }; | 1006 | }; |
1007 | 1007 | ||
1008 | static void *lec_tbl_walk(struct lec_state *state, struct lec_arp_table *tbl, | 1008 | static void *lec_tbl_walk(struct lec_state *state, struct hlist_head *tbl, |
1009 | loff_t *l) | 1009 | loff_t *l) |
1010 | { | 1010 | { |
1011 | struct lec_arp_table *e = state->entry; | 1011 | struct hlist_node *e = state->node; |
1012 | struct lec_arp_table *tmp; | ||
1012 | 1013 | ||
1013 | if (!e) | 1014 | if (!e) |
1014 | e = tbl; | 1015 | e = tbl->first; |
1015 | if (e == (void *)1) { | 1016 | if (e == (void *)1) { |
1016 | e = tbl; | 1017 | e = tbl->first; |
1017 | --*l; | 1018 | --*l; |
1018 | } | 1019 | } |
1019 | for (; e; e = e->next) { | 1020 | |
1021 | hlist_for_each_entry_from(tmp, e, next) { | ||
1020 | if (--*l < 0) | 1022 | if (--*l < 0) |
1021 | break; | 1023 | break; |
1022 | } | 1024 | } |
1023 | state->entry = e; | 1025 | state->node = e; |
1026 | |||
1024 | return (*l < 0) ? state : NULL; | 1027 | return (*l < 0) ? state : NULL; |
1025 | } | 1028 | } |
1026 | 1029 | ||
@@ -1031,7 +1034,7 @@ static void *lec_arp_walk(struct lec_state *state, loff_t *l, | |||
1031 | int p; | 1034 | int p; |
1032 | 1035 | ||
1033 | for (p = state->arp_table; p < LEC_ARP_TABLE_SIZE; p++) { | 1036 | for (p = state->arp_table; p < LEC_ARP_TABLE_SIZE; p++) { |
1034 | v = lec_tbl_walk(state, priv->lec_arp_tables[p], l); | 1037 | v = lec_tbl_walk(state, &priv->lec_arp_tables[p], l); |
1035 | if (v) | 1038 | if (v) |
1036 | break; | 1039 | break; |
1037 | } | 1040 | } |
@@ -1042,10 +1045,10 @@ static void *lec_arp_walk(struct lec_state *state, loff_t *l, | |||
1042 | static void *lec_misc_walk(struct lec_state *state, loff_t *l, | 1045 | static void *lec_misc_walk(struct lec_state *state, loff_t *l, |
1043 | struct lec_priv *priv) | 1046 | struct lec_priv *priv) |
1044 | { | 1047 | { |
1045 | struct lec_arp_table *lec_misc_tables[] = { | 1048 | struct hlist_head *lec_misc_tables[] = { |
1046 | priv->lec_arp_empty_ones, | 1049 | &priv->lec_arp_empty_ones, |
1047 | priv->lec_no_forward, | 1050 | &priv->lec_no_forward, |
1048 | priv->mcast_fwds | 1051 | &priv->mcast_fwds |
1049 | }; | 1052 | }; |
1050 | void *v = NULL; | 1053 | void *v = NULL; |
1051 | int q; | 1054 | int q; |
@@ -1112,7 +1115,7 @@ static void *lec_seq_start(struct seq_file *seq, loff_t *pos) | |||
1112 | state->locked = NULL; | 1115 | state->locked = NULL; |
1113 | state->arp_table = 0; | 1116 | state->arp_table = 0; |
1114 | state->misc_table = 0; | 1117 | state->misc_table = 0; |
1115 | state->entry = (void *)1; | 1118 | state->node = (void *)1; |
1116 | 1119 | ||
1117 | return *pos ? lec_get_idx(state, *pos) : (void *)1; | 1120 | return *pos ? lec_get_idx(state, *pos) : (void *)1; |
1118 | } | 1121 | } |
@@ -1148,9 +1151,10 @@ static int lec_seq_show(struct seq_file *seq, void *v) | |||
1148 | else { | 1151 | else { |
1149 | struct lec_state *state = seq->private; | 1152 | struct lec_state *state = seq->private; |
1150 | struct net_device *dev = state->dev; | 1153 | struct net_device *dev = state->dev; |
1154 | struct lec_arp_table *entry = hlist_entry(state->node, struct lec_arp_table, next); | ||
1151 | 1155 | ||
1152 | seq_printf(seq, "%s ", dev->name); | 1156 | seq_printf(seq, "%s ", dev->name); |
1153 | lec_info(seq, state->entry); | 1157 | lec_info(seq, entry); |
1154 | } | 1158 | } |
1155 | return 0; | 1159 | return 0; |
1156 | } | 1160 | } |
@@ -1455,8 +1459,11 @@ static void lec_arp_init(struct lec_priv *priv) | |||
1455 | unsigned short i; | 1459 | unsigned short i; |
1456 | 1460 | ||
1457 | for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { | 1461 | for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { |
1458 | priv->lec_arp_tables[i] = NULL; | 1462 | INIT_HLIST_HEAD(&priv->lec_arp_tables[i]); |
1459 | } | 1463 | } |
1464 | INIT_HLIST_HEAD(&priv->lec_arp_empty_ones); | ||
1465 | INIT_HLIST_HEAD(&priv->lec_no_forward); | ||
1466 | INIT_HLIST_HEAD(&priv->mcast_fwds); | ||
1460 | spin_lock_init(&priv->lec_arp_lock); | 1467 | spin_lock_init(&priv->lec_arp_lock); |
1461 | init_timer(&priv->lec_arp_timer); | 1468 | init_timer(&priv->lec_arp_timer); |
1462 | priv->lec_arp_timer.expires = jiffies + LEC_ARP_REFRESH_INTERVAL; | 1469 | 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) | |||
1479 | vcc->user_back = NULL; | 1486 | vcc->user_back = NULL; |
1480 | vcc->push = entry->old_push; | 1487 | vcc->push = entry->old_push; |
1481 | vcc_release_async(vcc, -EPIPE); | 1488 | vcc_release_async(vcc, -EPIPE); |
1482 | vcc = NULL; | 1489 | entry->vcc = NULL; |
1483 | } | 1490 | } |
1484 | if (entry->recv_vcc) { | 1491 | if (entry->recv_vcc) { |
1485 | entry->recv_vcc->push = entry->old_recv_push; | 1492 | entry->recv_vcc->push = entry->old_recv_push; |
@@ -1493,27 +1500,17 @@ static void lec_arp_clear_vccs(struct lec_arp_table *entry) | |||
1493 | * LANE2: Add to the end of the list to satisfy 8.1.13 | 1500 | * LANE2: Add to the end of the list to satisfy 8.1.13 |
1494 | */ | 1501 | */ |
1495 | static inline void | 1502 | static inline void |
1496 | lec_arp_add(struct lec_priv *priv, struct lec_arp_table *to_add) | 1503 | lec_arp_add(struct lec_priv *priv, struct lec_arp_table *entry) |
1497 | { | 1504 | { |
1498 | unsigned short place; | 1505 | struct hlist_head *tmp; |
1499 | struct lec_arp_table *tmp; | ||
1500 | 1506 | ||
1501 | place = HASH(to_add->mac_addr[ETH_ALEN - 1]); | 1507 | tmp = &priv->lec_arp_tables[HASH(entry->mac_addr[ETH_ALEN - 1])]; |
1502 | tmp = priv->lec_arp_tables[place]; | 1508 | hlist_add_head(&entry->next, tmp); |
1503 | to_add->next = NULL; | ||
1504 | if (tmp == NULL) | ||
1505 | priv->lec_arp_tables[place] = to_add; | ||
1506 | |||
1507 | else { /* add to the end */ | ||
1508 | while (tmp->next) | ||
1509 | tmp = tmp->next; | ||
1510 | tmp->next = to_add; | ||
1511 | } | ||
1512 | 1509 | ||
1513 | DPRINTK("LEC_ARP: Added entry:%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n", | 1510 | DPRINTK("LEC_ARP: Added entry:%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n", |
1514 | 0xff & to_add->mac_addr[0], 0xff & to_add->mac_addr[1], | 1511 | 0xff & entry->mac_addr[0], 0xff & entry->mac_addr[1], |
1515 | 0xff & to_add->mac_addr[2], 0xff & to_add->mac_addr[3], | 1512 | 0xff & entry->mac_addr[2], 0xff & entry->mac_addr[3], |
1516 | 0xff & to_add->mac_addr[4], 0xff & to_add->mac_addr[5]); | 1513 | 0xff & entry->mac_addr[4], 0xff & entry->mac_addr[5]); |
1517 | } | 1514 | } |
1518 | 1515 | ||
1519 | /* | 1516 | /* |
@@ -1522,40 +1519,26 @@ lec_arp_add(struct lec_priv *priv, struct lec_arp_table *to_add) | |||
1522 | static int | 1519 | static int |
1523 | lec_arp_remove(struct lec_priv *priv, struct lec_arp_table *to_remove) | 1520 | lec_arp_remove(struct lec_priv *priv, struct lec_arp_table *to_remove) |
1524 | { | 1521 | { |
1525 | unsigned short place; | 1522 | struct hlist_node *node; |
1526 | struct lec_arp_table *tmp; | 1523 | struct lec_arp_table *entry; |
1527 | int remove_vcc = 1; | 1524 | int i, remove_vcc = 1; |
1528 | 1525 | ||
1529 | if (!to_remove) { | 1526 | if (!to_remove) { |
1530 | return -1; | 1527 | return -1; |
1531 | } | 1528 | } |
1532 | place = HASH(to_remove->mac_addr[ETH_ALEN - 1]); | 1529 | |
1533 | tmp = priv->lec_arp_tables[place]; | 1530 | hlist_del(&to_remove->next); |
1534 | if (tmp == to_remove) { | ||
1535 | priv->lec_arp_tables[place] = tmp->next; | ||
1536 | } else { | ||
1537 | while (tmp && tmp->next != to_remove) { | ||
1538 | tmp = tmp->next; | ||
1539 | } | ||
1540 | if (!tmp) { /* Entry was not found */ | ||
1541 | return -1; | ||
1542 | } | ||
1543 | } | ||
1544 | tmp->next = to_remove->next; | ||
1545 | del_timer(&to_remove->timer); | 1531 | del_timer(&to_remove->timer); |
1546 | 1532 | ||
1547 | /* If this is the only MAC connected to this VCC, also tear down | 1533 | /* If this is the only MAC connected to this VCC, also tear down the VCC */ |
1548 | the VCC */ | ||
1549 | if (to_remove->status >= ESI_FLUSH_PENDING) { | 1534 | if (to_remove->status >= ESI_FLUSH_PENDING) { |
1550 | /* | 1535 | /* |
1551 | * ESI_FLUSH_PENDING, ESI_FORWARD_DIRECT | 1536 | * ESI_FLUSH_PENDING, ESI_FORWARD_DIRECT |
1552 | */ | 1537 | */ |
1553 | for (place = 0; place < LEC_ARP_TABLE_SIZE; place++) { | 1538 | for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { |
1554 | for (tmp = priv->lec_arp_tables[place]; tmp != NULL; | 1539 | hlist_for_each_entry(entry, node, &priv->lec_arp_tables[i], next) { |
1555 | tmp = tmp->next) { | 1540 | if (memcmp(to_remove->atm_addr, |
1556 | if (memcmp | 1541 | entry->atm_addr, ATM_ESA_LEN) == 0) { |
1557 | (tmp->atm_addr, to_remove->atm_addr, | ||
1558 | ATM_ESA_LEN) == 0) { | ||
1559 | remove_vcc = 0; | 1542 | remove_vcc = 0; |
1560 | break; | 1543 | break; |
1561 | } | 1544 | } |
@@ -1591,28 +1574,19 @@ static char *get_status_string(unsigned char st) | |||
1591 | return "<UNKNOWN>"; | 1574 | return "<UNKNOWN>"; |
1592 | } | 1575 | } |
1593 | } | 1576 | } |
1594 | #endif | ||
1595 | 1577 | ||
1596 | static void dump_arp_table(struct lec_priv *priv) | 1578 | static void dump_arp_table(struct lec_priv *priv) |
1597 | { | 1579 | { |
1598 | #if DEBUG_ARP_TABLE | 1580 | struct hlist_node *node; |
1599 | int i, j, offset; | ||
1600 | struct lec_arp_table *rulla; | 1581 | struct lec_arp_table *rulla; |
1601 | char buf[1024]; | 1582 | char buf[256]; |
1602 | struct lec_arp_table **lec_arp_tables = | 1583 | int i, j, offset; |
1603 | (struct lec_arp_table **)priv->lec_arp_tables; | ||
1604 | struct lec_arp_table *lec_arp_empty_ones = | ||
1605 | (struct lec_arp_table *)priv->lec_arp_empty_ones; | ||
1606 | struct lec_arp_table *lec_no_forward = | ||
1607 | (struct lec_arp_table *)priv->lec_no_forward; | ||
1608 | struct lec_arp_table *mcast_fwds = priv->mcast_fwds; | ||
1609 | 1584 | ||
1610 | printk("Dump %p:\n", priv); | 1585 | printk("Dump %p:\n", priv); |
1611 | for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { | 1586 | for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { |
1612 | rulla = lec_arp_tables[i]; | 1587 | hlist_for_each_entry(rulla, node, &priv->lec_arp_tables[i], next) { |
1613 | offset = 0; | 1588 | offset = 0; |
1614 | offset += sprintf(buf, "%d: %p\n", i, rulla); | 1589 | offset += sprintf(buf, "%d: %p\n", i, rulla); |
1615 | while (rulla) { | ||
1616 | offset += sprintf(buf + offset, "Mac:"); | 1590 | offset += sprintf(buf + offset, "Mac:"); |
1617 | for (j = 0; j < ETH_ALEN; j++) { | 1591 | for (j = 0; j < ETH_ALEN; j++) { |
1618 | offset += sprintf(buf + offset, | 1592 | offset += sprintf(buf + offset, |
@@ -1639,15 +1613,13 @@ static void dump_arp_table(struct lec_priv *priv) | |||
1639 | "Flags:%x, Packets_flooded:%x, Status: %s ", | 1613 | "Flags:%x, Packets_flooded:%x, Status: %s ", |
1640 | rulla->flags, rulla->packets_flooded, | 1614 | rulla->flags, rulla->packets_flooded, |
1641 | get_status_string(rulla->status)); | 1615 | get_status_string(rulla->status)); |
1642 | offset += sprintf(buf + offset, "->%p\n", rulla->next); | 1616 | printk("%s\n", buf); |
1643 | rulla = rulla->next; | ||
1644 | } | 1617 | } |
1645 | printk("%s", buf); | ||
1646 | } | 1618 | } |
1647 | rulla = lec_no_forward; | 1619 | |
1648 | if (rulla) | 1620 | if (!hlist_empty(&priv->lec_no_forward)) |
1649 | printk("No forward\n"); | 1621 | printk("No forward\n"); |
1650 | while (rulla) { | 1622 | hlist_for_each_entry(rulla, node, &priv->lec_no_forward, next) { |
1651 | offset = 0; | 1623 | offset = 0; |
1652 | offset += sprintf(buf + offset, "Mac:"); | 1624 | offset += sprintf(buf + offset, "Mac:"); |
1653 | for (j = 0; j < ETH_ALEN; j++) { | 1625 | for (j = 0; j < ETH_ALEN; j++) { |
@@ -1671,14 +1643,12 @@ static void dump_arp_table(struct lec_priv *priv) | |||
1671 | "Flags:%x, Packets_flooded:%x, Status: %s ", | 1643 | "Flags:%x, Packets_flooded:%x, Status: %s ", |
1672 | rulla->flags, rulla->packets_flooded, | 1644 | rulla->flags, rulla->packets_flooded, |
1673 | get_status_string(rulla->status)); | 1645 | get_status_string(rulla->status)); |
1674 | offset += sprintf(buf + offset, "->%lx\n", (long)rulla->next); | 1646 | printk("%s\n", buf); |
1675 | rulla = rulla->next; | ||
1676 | printk("%s", buf); | ||
1677 | } | 1647 | } |
1678 | rulla = lec_arp_empty_ones; | 1648 | |
1679 | if (rulla) | 1649 | if (!hlist_empty(&priv->lec_arp_empty_ones)) |
1680 | printk("Empty ones\n"); | 1650 | printk("Empty ones\n"); |
1681 | while (rulla) { | 1651 | hlist_for_each_entry(rulla, node, &priv->lec_arp_empty_ones, next) { |
1682 | offset = 0; | 1652 | offset = 0; |
1683 | offset += sprintf(buf + offset, "Mac:"); | 1653 | offset += sprintf(buf + offset, "Mac:"); |
1684 | for (j = 0; j < ETH_ALEN; j++) { | 1654 | for (j = 0; j < ETH_ALEN; j++) { |
@@ -1702,15 +1672,12 @@ static void dump_arp_table(struct lec_priv *priv) | |||
1702 | "Flags:%x, Packets_flooded:%x, Status: %s ", | 1672 | "Flags:%x, Packets_flooded:%x, Status: %s ", |
1703 | rulla->flags, rulla->packets_flooded, | 1673 | rulla->flags, rulla->packets_flooded, |
1704 | get_status_string(rulla->status)); | 1674 | get_status_string(rulla->status)); |
1705 | offset += sprintf(buf + offset, "->%lx\n", (long)rulla->next); | ||
1706 | rulla = rulla->next; | ||
1707 | printk("%s", buf); | 1675 | printk("%s", buf); |
1708 | } | 1676 | } |
1709 | 1677 | ||
1710 | rulla = mcast_fwds; | 1678 | if (!hlist_empty(&priv->mcast_fwds)) |
1711 | if (rulla) | ||
1712 | printk("Multicast Forward VCCs\n"); | 1679 | printk("Multicast Forward VCCs\n"); |
1713 | while (rulla) { | 1680 | hlist_for_each_entry(rulla, node, &priv->mcast_fwds, next) { |
1714 | offset = 0; | 1681 | offset = 0; |
1715 | offset += sprintf(buf + offset, "Mac:"); | 1682 | offset += sprintf(buf + offset, "Mac:"); |
1716 | for (j = 0; j < ETH_ALEN; j++) { | 1683 | for (j = 0; j < ETH_ALEN; j++) { |
@@ -1734,13 +1701,13 @@ static void dump_arp_table(struct lec_priv *priv) | |||
1734 | "Flags:%x, Packets_flooded:%x, Status: %s ", | 1701 | "Flags:%x, Packets_flooded:%x, Status: %s ", |
1735 | rulla->flags, rulla->packets_flooded, | 1702 | rulla->flags, rulla->packets_flooded, |
1736 | get_status_string(rulla->status)); | 1703 | get_status_string(rulla->status)); |
1737 | offset += sprintf(buf + offset, "->%lx\n", (long)rulla->next); | 1704 | printk("%s\n", buf); |
1738 | rulla = rulla->next; | ||
1739 | printk("%s", buf); | ||
1740 | } | 1705 | } |
1741 | 1706 | ||
1742 | #endif | ||
1743 | } | 1707 | } |
1708 | #else | ||
1709 | #define dump_arp_table(priv) do { } while (0) | ||
1710 | #endif | ||
1744 | 1711 | ||
1745 | /* | 1712 | /* |
1746 | * Destruction of arp-cache | 1713 | * Destruction of arp-cache |
@@ -1748,7 +1715,8 @@ static void dump_arp_table(struct lec_priv *priv) | |||
1748 | static void lec_arp_destroy(struct lec_priv *priv) | 1715 | static void lec_arp_destroy(struct lec_priv *priv) |
1749 | { | 1716 | { |
1750 | unsigned long flags; | 1717 | unsigned long flags; |
1751 | struct lec_arp_table *entry, *next; | 1718 | struct hlist_node *node, *next; |
1719 | struct lec_arp_table *entry; | ||
1752 | int i; | 1720 | int i; |
1753 | 1721 | ||
1754 | del_timer_sync(&priv->lec_arp_timer); | 1722 | del_timer_sync(&priv->lec_arp_timer); |
@@ -1759,43 +1727,37 @@ static void lec_arp_destroy(struct lec_priv *priv) | |||
1759 | 1727 | ||
1760 | spin_lock_irqsave(&priv->lec_arp_lock, flags); | 1728 | spin_lock_irqsave(&priv->lec_arp_lock, flags); |
1761 | for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { | 1729 | for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { |
1762 | for (entry = priv->lec_arp_tables[i]; entry != NULL; | 1730 | hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_tables[i], next) { |
1763 | entry = next) { | ||
1764 | next = entry->next; | ||
1765 | lec_arp_remove(priv, entry); | 1731 | lec_arp_remove(priv, entry); |
1766 | kfree(entry); | 1732 | kfree(entry); |
1767 | } | 1733 | } |
1734 | INIT_HLIST_HEAD(&priv->lec_arp_tables[i]); | ||
1768 | } | 1735 | } |
1769 | entry = priv->lec_arp_empty_ones; | 1736 | |
1770 | while (entry) { | 1737 | hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_empty_ones, next) { |
1771 | next = entry->next; | ||
1772 | del_timer_sync(&entry->timer); | 1738 | del_timer_sync(&entry->timer); |
1773 | lec_arp_clear_vccs(entry); | 1739 | lec_arp_clear_vccs(entry); |
1740 | hlist_del(&entry->next); | ||
1774 | kfree(entry); | 1741 | kfree(entry); |
1775 | entry = next; | ||
1776 | } | 1742 | } |
1777 | priv->lec_arp_empty_ones = NULL; | 1743 | INIT_HLIST_HEAD(&priv->lec_arp_empty_ones); |
1778 | entry = priv->lec_no_forward; | 1744 | |
1779 | while (entry) { | 1745 | hlist_for_each_entry_safe(entry, node, next, &priv->lec_no_forward, next) { |
1780 | next = entry->next; | ||
1781 | del_timer_sync(&entry->timer); | 1746 | del_timer_sync(&entry->timer); |
1782 | lec_arp_clear_vccs(entry); | 1747 | lec_arp_clear_vccs(entry); |
1748 | hlist_del(&entry->next); | ||
1783 | kfree(entry); | 1749 | kfree(entry); |
1784 | entry = next; | ||
1785 | } | 1750 | } |
1786 | priv->lec_no_forward = NULL; | 1751 | INIT_HLIST_HEAD(&priv->lec_no_forward); |
1787 | entry = priv->mcast_fwds; | 1752 | |
1788 | while (entry) { | 1753 | hlist_for_each_entry_safe(entry, node, next, &priv->mcast_fwds, next) { |
1789 | next = entry->next; | ||
1790 | /* No timer, LANEv2 7.1.20 and 2.3.5.3 */ | 1754 | /* No timer, LANEv2 7.1.20 and 2.3.5.3 */ |
1791 | lec_arp_clear_vccs(entry); | 1755 | lec_arp_clear_vccs(entry); |
1756 | hlist_del(&entry->next); | ||
1792 | kfree(entry); | 1757 | kfree(entry); |
1793 | entry = next; | ||
1794 | } | 1758 | } |
1795 | priv->mcast_fwds = NULL; | 1759 | INIT_HLIST_HEAD(&priv->mcast_fwds); |
1796 | priv->mcast_vcc = NULL; | 1760 | priv->mcast_vcc = NULL; |
1797 | memset(priv->lec_arp_tables, 0, | ||
1798 | sizeof(struct lec_arp_table *) * LEC_ARP_TABLE_SIZE); | ||
1799 | spin_unlock_irqrestore(&priv->lec_arp_lock, flags); | 1761 | spin_unlock_irqrestore(&priv->lec_arp_lock, flags); |
1800 | } | 1762 | } |
1801 | 1763 | ||
@@ -1805,20 +1767,19 @@ static void lec_arp_destroy(struct lec_priv *priv) | |||
1805 | static struct lec_arp_table *lec_arp_find(struct lec_priv *priv, | 1767 | static struct lec_arp_table *lec_arp_find(struct lec_priv *priv, |
1806 | unsigned char *mac_addr) | 1768 | unsigned char *mac_addr) |
1807 | { | 1769 | { |
1808 | unsigned short place; | 1770 | struct hlist_node *node; |
1809 | struct lec_arp_table *to_return; | 1771 | struct hlist_head *head; |
1772 | struct lec_arp_table *entry; | ||
1810 | 1773 | ||
1811 | DPRINTK("LEC_ARP: lec_arp_find :%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n", | 1774 | DPRINTK("LEC_ARP: lec_arp_find :%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n", |
1812 | mac_addr[0] & 0xff, mac_addr[1] & 0xff, mac_addr[2] & 0xff, | 1775 | mac_addr[0] & 0xff, mac_addr[1] & 0xff, mac_addr[2] & 0xff, |
1813 | mac_addr[3] & 0xff, mac_addr[4] & 0xff, mac_addr[5] & 0xff); | 1776 | mac_addr[3] & 0xff, mac_addr[4] & 0xff, mac_addr[5] & 0xff); |
1814 | place = HASH(mac_addr[ETH_ALEN - 1]); | ||
1815 | 1777 | ||
1816 | to_return = priv->lec_arp_tables[place]; | 1778 | head = &priv->lec_arp_tables[HASH(mac_addr[ETH_ALEN - 1])]; |
1817 | while (to_return) { | 1779 | hlist_for_each_entry(entry, node, head, next) { |
1818 | if (!compare_ether_addr(mac_addr, to_return->mac_addr)) { | 1780 | if (!compare_ether_addr(mac_addr, entry->mac_addr)) { |
1819 | return to_return; | 1781 | return entry; |
1820 | } | 1782 | } |
1821 | to_return = to_return->next; | ||
1822 | } | 1783 | } |
1823 | return NULL; | 1784 | return NULL; |
1824 | } | 1785 | } |
@@ -1834,6 +1795,7 @@ static struct lec_arp_table *make_entry(struct lec_priv *priv, | |||
1834 | return NULL; | 1795 | return NULL; |
1835 | } | 1796 | } |
1836 | memcpy(to_return->mac_addr, mac_addr, ETH_ALEN); | 1797 | memcpy(to_return->mac_addr, mac_addr, ETH_ALEN); |
1798 | INIT_HLIST_NODE(&to_return->next); | ||
1837 | init_timer(&to_return->timer); | 1799 | init_timer(&to_return->timer); |
1838 | to_return->timer.function = lec_arp_expire_arp; | 1800 | to_return->timer.function = lec_arp_expire_arp; |
1839 | to_return->timer.data = (unsigned long)to_return; | 1801 | to_return->timer.data = (unsigned long)to_return; |
@@ -1871,7 +1833,6 @@ static void lec_arp_expire_vcc(unsigned long data) | |||
1871 | unsigned long flags; | 1833 | unsigned long flags; |
1872 | struct lec_arp_table *to_remove = (struct lec_arp_table *)data; | 1834 | struct lec_arp_table *to_remove = (struct lec_arp_table *)data; |
1873 | struct lec_priv *priv = (struct lec_priv *)to_remove->priv; | 1835 | struct lec_priv *priv = (struct lec_priv *)to_remove->priv; |
1874 | struct lec_arp_table *entry = NULL; | ||
1875 | 1836 | ||
1876 | del_timer(&to_remove->timer); | 1837 | del_timer(&to_remove->timer); |
1877 | 1838 | ||
@@ -1879,30 +1840,9 @@ static void lec_arp_expire_vcc(unsigned long data) | |||
1879 | to_remove, priv, | 1840 | to_remove, priv, |
1880 | to_remove->vcc ? to_remove->recv_vcc->vpi : 0, | 1841 | to_remove->vcc ? to_remove->recv_vcc->vpi : 0, |
1881 | to_remove->vcc ? to_remove->recv_vcc->vci : 0); | 1842 | to_remove->vcc ? to_remove->recv_vcc->vci : 0); |
1882 | DPRINTK("eo:%p nf:%p\n", priv->lec_arp_empty_ones, | ||
1883 | priv->lec_no_forward); | ||
1884 | 1843 | ||
1885 | spin_lock_irqsave(&priv->lec_arp_lock, flags); | 1844 | spin_lock_irqsave(&priv->lec_arp_lock, flags); |
1886 | if (to_remove == priv->lec_arp_empty_ones) | 1845 | hlist_del(&to_remove->next); |
1887 | priv->lec_arp_empty_ones = to_remove->next; | ||
1888 | else { | ||
1889 | entry = priv->lec_arp_empty_ones; | ||
1890 | while (entry && entry->next != to_remove) | ||
1891 | entry = entry->next; | ||
1892 | if (entry) | ||
1893 | entry->next = to_remove->next; | ||
1894 | } | ||
1895 | if (!entry) { | ||
1896 | if (to_remove == priv->lec_no_forward) { | ||
1897 | priv->lec_no_forward = to_remove->next; | ||
1898 | } else { | ||
1899 | entry = priv->lec_no_forward; | ||
1900 | while (entry && entry->next != to_remove) | ||
1901 | entry = entry->next; | ||
1902 | if (entry) | ||
1903 | entry->next = to_remove->next; | ||
1904 | } | ||
1905 | } | ||
1906 | spin_unlock_irqrestore(&priv->lec_arp_lock, flags); | 1846 | spin_unlock_irqrestore(&priv->lec_arp_lock, flags); |
1907 | 1847 | ||
1908 | lec_arp_clear_vccs(to_remove); | 1848 | lec_arp_clear_vccs(to_remove); |
@@ -1929,18 +1869,17 @@ static void lec_arp_check_expire(unsigned long data) | |||
1929 | { | 1869 | { |
1930 | unsigned long flags; | 1870 | unsigned long flags; |
1931 | struct lec_priv *priv = (struct lec_priv *)data; | 1871 | struct lec_priv *priv = (struct lec_priv *)data; |
1932 | struct lec_arp_table *entry, *next; | 1872 | struct hlist_node *node, *next; |
1873 | struct lec_arp_table *entry; | ||
1933 | unsigned long now; | 1874 | unsigned long now; |
1934 | unsigned long time_to_check; | 1875 | unsigned long time_to_check; |
1935 | int i; | 1876 | int i; |
1936 | 1877 | ||
1937 | DPRINTK("lec_arp_check_expire %p\n", priv); | 1878 | DPRINTK("lec_arp_check_expire %p\n", priv); |
1938 | DPRINTK("expire: eo:%p nf:%p\n", priv->lec_arp_empty_ones, | ||
1939 | priv->lec_no_forward); | ||
1940 | now = jiffies; | 1879 | now = jiffies; |
1941 | spin_lock_irqsave(&priv->lec_arp_lock, flags); | 1880 | spin_lock_irqsave(&priv->lec_arp_lock, flags); |
1942 | for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { | 1881 | for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { |
1943 | for (entry = priv->lec_arp_tables[i]; entry != NULL;) { | 1882 | hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_tables[i], next) { |
1944 | if ((entry->flags) & LEC_REMOTE_FLAG && | 1883 | if ((entry->flags) & LEC_REMOTE_FLAG && |
1945 | priv->topology_change) | 1884 | priv->topology_change) |
1946 | time_to_check = priv->forward_delay_time; | 1885 | time_to_check = priv->forward_delay_time; |
@@ -1954,10 +1893,8 @@ static void lec_arp_check_expire(unsigned long data) | |||
1954 | && !(entry->mac_addr[0] & 0x01)) { /* LANE2: 7.1.20 */ | 1893 | && !(entry->mac_addr[0] & 0x01)) { /* LANE2: 7.1.20 */ |
1955 | /* Remove entry */ | 1894 | /* Remove entry */ |
1956 | DPRINTK("LEC:Entry timed out\n"); | 1895 | DPRINTK("LEC:Entry timed out\n"); |
1957 | next = entry->next; | ||
1958 | lec_arp_remove(priv, entry); | 1896 | lec_arp_remove(priv, entry); |
1959 | kfree(entry); | 1897 | kfree(entry); |
1960 | entry = next; | ||
1961 | } else { | 1898 | } else { |
1962 | /* Something else */ | 1899 | /* Something else */ |
1963 | if ((entry->status == ESI_VC_PENDING || | 1900 | if ((entry->status == ESI_VC_PENDING || |
@@ -1988,7 +1925,6 @@ static void lec_arp_check_expire(unsigned long data) | |||
1988 | entry->last_used = jiffies; | 1925 | entry->last_used = jiffies; |
1989 | entry->status = ESI_FORWARD_DIRECT; | 1926 | entry->status = ESI_FORWARD_DIRECT; |
1990 | } | 1927 | } |
1991 | entry = entry->next; | ||
1992 | } | 1928 | } |
1993 | } | 1929 | } |
1994 | } | 1930 | } |
@@ -2100,15 +2036,14 @@ lec_addr_delete(struct lec_priv *priv, unsigned char *atm_addr, | |||
2100 | unsigned long permanent) | 2036 | unsigned long permanent) |
2101 | { | 2037 | { |
2102 | unsigned long flags; | 2038 | unsigned long flags; |
2103 | struct lec_arp_table *entry, *next; | 2039 | struct hlist_node *node, *next; |
2040 | struct lec_arp_table *entry; | ||
2104 | int i; | 2041 | int i; |
2105 | 2042 | ||
2106 | DPRINTK("lec_addr_delete\n"); | 2043 | DPRINTK("lec_addr_delete\n"); |
2107 | spin_lock_irqsave(&priv->lec_arp_lock, flags); | 2044 | spin_lock_irqsave(&priv->lec_arp_lock, flags); |
2108 | for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { | 2045 | for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { |
2109 | for (entry = priv->lec_arp_tables[i]; entry != NULL; | 2046 | hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_tables[i], next) { |
2110 | entry = next) { | ||
2111 | next = entry->next; | ||
2112 | if (!memcmp(atm_addr, entry->atm_addr, ATM_ESA_LEN) | 2047 | if (!memcmp(atm_addr, entry->atm_addr, ATM_ESA_LEN) |
2113 | && (permanent || | 2048 | && (permanent || |
2114 | !(entry->flags & LEC_PERMANENT_FLAG))) { | 2049 | !(entry->flags & LEC_PERMANENT_FLAG))) { |
@@ -2132,6 +2067,7 @@ lec_arp_update(struct lec_priv *priv, unsigned char *mac_addr, | |||
2132 | unsigned int targetless_le_arp) | 2067 | unsigned int targetless_le_arp) |
2133 | { | 2068 | { |
2134 | unsigned long flags; | 2069 | unsigned long flags; |
2070 | struct hlist_node *node, *next; | ||
2135 | struct lec_arp_table *entry, *tmp; | 2071 | struct lec_arp_table *entry, *tmp; |
2136 | int i; | 2072 | int i; |
2137 | 2073 | ||
@@ -2147,50 +2083,39 @@ lec_arp_update(struct lec_priv *priv, unsigned char *mac_addr, | |||
2147 | * LANE2: ignore targetless LE_ARPs for which | 2083 | * LANE2: ignore targetless LE_ARPs for which |
2148 | * we have no entry in the cache. 7.1.30 | 2084 | * we have no entry in the cache. 7.1.30 |
2149 | */ | 2085 | */ |
2150 | if (priv->lec_arp_empty_ones) { | 2086 | if (!hlist_empty(&priv->lec_arp_empty_ones)) { |
2151 | entry = priv->lec_arp_empty_ones; | 2087 | hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_empty_ones, next) { |
2152 | if (!memcmp(entry->atm_addr, atm_addr, ATM_ESA_LEN)) { | 2088 | if (memcmp(entry->atm_addr, atm_addr, ATM_ESA_LEN) == 0) { |
2153 | priv->lec_arp_empty_ones = entry->next; | 2089 | hlist_del(&entry->next); |
2154 | } else { | ||
2155 | while (entry->next && memcmp(entry->next->atm_addr, | ||
2156 | atm_addr, ATM_ESA_LEN)) | ||
2157 | entry = entry->next; | ||
2158 | if (entry->next) { | ||
2159 | tmp = entry; | ||
2160 | entry = entry->next; | ||
2161 | tmp->next = entry->next; | ||
2162 | } else | ||
2163 | entry = NULL; | ||
2164 | |||
2165 | } | ||
2166 | if (entry) { | ||
2167 | del_timer(&entry->timer); | ||
2168 | tmp = lec_arp_find(priv, mac_addr); | ||
2169 | if (tmp) { | ||
2170 | del_timer(&tmp->timer); | ||
2171 | tmp->status = ESI_FORWARD_DIRECT; | ||
2172 | memcpy(tmp->atm_addr, atm_addr, ATM_ESA_LEN); | ||
2173 | tmp->vcc = entry->vcc; | ||
2174 | tmp->old_push = entry->old_push; | ||
2175 | tmp->last_used = jiffies; | ||
2176 | del_timer(&entry->timer); | 2090 | del_timer(&entry->timer); |
2177 | kfree(entry); | 2091 | tmp = lec_arp_find(priv, mac_addr); |
2178 | entry = tmp; | 2092 | if (tmp) { |
2179 | } else { | 2093 | del_timer(&tmp->timer); |
2180 | entry->status = ESI_FORWARD_DIRECT; | 2094 | tmp->status = ESI_FORWARD_DIRECT; |
2181 | memcpy(entry->mac_addr, mac_addr, ETH_ALEN); | 2095 | memcpy(tmp->atm_addr, atm_addr, ATM_ESA_LEN); |
2182 | entry->last_used = jiffies; | 2096 | tmp->vcc = entry->vcc; |
2183 | lec_arp_add(priv, entry); | 2097 | tmp->old_push = entry->old_push; |
2098 | tmp->last_used = jiffies; | ||
2099 | del_timer(&entry->timer); | ||
2100 | kfree(entry); | ||
2101 | entry = tmp; | ||
2102 | } else { | ||
2103 | entry->status = ESI_FORWARD_DIRECT; | ||
2104 | memcpy(entry->mac_addr, mac_addr, ETH_ALEN); | ||
2105 | entry->last_used = jiffies; | ||
2106 | lec_arp_add(priv, entry); | ||
2107 | } | ||
2108 | if (remoteflag) | ||
2109 | entry->flags |= LEC_REMOTE_FLAG; | ||
2110 | else | ||
2111 | entry->flags &= ~LEC_REMOTE_FLAG; | ||
2112 | DPRINTK("After update\n"); | ||
2113 | dump_arp_table(priv); | ||
2114 | goto out; | ||
2184 | } | 2115 | } |
2185 | if (remoteflag) | ||
2186 | entry->flags |= LEC_REMOTE_FLAG; | ||
2187 | else | ||
2188 | entry->flags &= ~LEC_REMOTE_FLAG; | ||
2189 | DPRINTK("After update\n"); | ||
2190 | dump_arp_table(priv); | ||
2191 | goto out; | ||
2192 | } | 2116 | } |
2193 | } | 2117 | } |
2118 | |||
2194 | entry = lec_arp_find(priv, mac_addr); | 2119 | entry = lec_arp_find(priv, mac_addr); |
2195 | if (!entry) { | 2120 | if (!entry) { |
2196 | entry = make_entry(priv, mac_addr); | 2121 | entry = make_entry(priv, mac_addr); |
@@ -2203,7 +2128,7 @@ lec_arp_update(struct lec_priv *priv, unsigned char *mac_addr, | |||
2203 | memcpy(entry->atm_addr, atm_addr, ATM_ESA_LEN); | 2128 | memcpy(entry->atm_addr, atm_addr, ATM_ESA_LEN); |
2204 | del_timer(&entry->timer); | 2129 | del_timer(&entry->timer); |
2205 | for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { | 2130 | for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { |
2206 | for (tmp = priv->lec_arp_tables[i]; tmp; tmp = tmp->next) { | 2131 | hlist_for_each_entry(tmp, node, &priv->lec_arp_tables[i], next) { |
2207 | if (entry != tmp && | 2132 | if (entry != tmp && |
2208 | !memcmp(tmp->atm_addr, atm_addr, ATM_ESA_LEN)) { | 2133 | !memcmp(tmp->atm_addr, atm_addr, ATM_ESA_LEN)) { |
2209 | /* Vcc to this host exists */ | 2134 | /* Vcc to this host exists */ |
@@ -2226,8 +2151,7 @@ lec_arp_update(struct lec_priv *priv, unsigned char *mac_addr, | |||
2226 | entry->flags &= ~LEC_REMOTE_FLAG; | 2151 | entry->flags &= ~LEC_REMOTE_FLAG; |
2227 | if (entry->status == ESI_ARP_PENDING || entry->status == ESI_UNKNOWN) { | 2152 | if (entry->status == ESI_ARP_PENDING || entry->status == ESI_UNKNOWN) { |
2228 | entry->status = ESI_VC_PENDING; | 2153 | entry->status = ESI_VC_PENDING; |
2229 | send_to_lecd(priv, l_svc_setup, entry->mac_addr, atm_addr, | 2154 | send_to_lecd(priv, l_svc_setup, entry->mac_addr, atm_addr, NULL); |
2230 | NULL); | ||
2231 | } | 2155 | } |
2232 | DPRINTK("After update2\n"); | 2156 | DPRINTK("After update2\n"); |
2233 | dump_arp_table(priv); | 2157 | dump_arp_table(priv); |
@@ -2244,6 +2168,7 @@ lec_vcc_added(struct lec_priv *priv, struct atmlec_ioc *ioc_data, | |||
2244 | void (*old_push) (struct atm_vcc *vcc, struct sk_buff *skb)) | 2168 | void (*old_push) (struct atm_vcc *vcc, struct sk_buff *skb)) |
2245 | { | 2169 | { |
2246 | unsigned long flags; | 2170 | unsigned long flags; |
2171 | struct hlist_node *node; | ||
2247 | struct lec_arp_table *entry; | 2172 | struct lec_arp_table *entry; |
2248 | int i, found_entry = 0; | 2173 | int i, found_entry = 0; |
2249 | 2174 | ||
@@ -2269,8 +2194,7 @@ lec_vcc_added(struct lec_priv *priv, struct atmlec_ioc *ioc_data, | |||
2269 | memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN); | 2194 | memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN); |
2270 | entry->recv_vcc = vcc; | 2195 | entry->recv_vcc = vcc; |
2271 | entry->old_recv_push = old_push; | 2196 | entry->old_recv_push = old_push; |
2272 | entry->next = priv->mcast_fwds; | 2197 | hlist_add_head(&entry->next, &priv->mcast_fwds); |
2273 | priv->mcast_fwds = entry; | ||
2274 | goto out; | 2198 | goto out; |
2275 | } else if (ioc_data->receive == 1) { | 2199 | } else if (ioc_data->receive == 1) { |
2276 | /* | 2200 | /* |
@@ -2300,9 +2224,8 @@ lec_vcc_added(struct lec_priv *priv, struct atmlec_ioc *ioc_data, | |||
2300 | entry->status = ESI_UNKNOWN; | 2224 | entry->status = ESI_UNKNOWN; |
2301 | entry->timer.expires = jiffies + priv->vcc_timeout_period; | 2225 | entry->timer.expires = jiffies + priv->vcc_timeout_period; |
2302 | entry->timer.function = lec_arp_expire_vcc; | 2226 | entry->timer.function = lec_arp_expire_vcc; |
2227 | hlist_add_head(&entry->next, &priv->lec_no_forward); | ||
2303 | add_timer(&entry->timer); | 2228 | add_timer(&entry->timer); |
2304 | entry->next = priv->lec_no_forward; | ||
2305 | priv->lec_no_forward = entry; | ||
2306 | dump_arp_table(priv); | 2229 | dump_arp_table(priv); |
2307 | goto out; | 2230 | goto out; |
2308 | } | 2231 | } |
@@ -2320,8 +2243,7 @@ lec_vcc_added(struct lec_priv *priv, struct atmlec_ioc *ioc_data, | |||
2320 | ioc_data->atm_addr[16], ioc_data->atm_addr[17], | 2243 | ioc_data->atm_addr[16], ioc_data->atm_addr[17], |
2321 | ioc_data->atm_addr[18], ioc_data->atm_addr[19]); | 2244 | ioc_data->atm_addr[18], ioc_data->atm_addr[19]); |
2322 | for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { | 2245 | for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { |
2323 | for (entry = priv->lec_arp_tables[i]; entry; | 2246 | hlist_for_each_entry(entry, node, &priv->lec_arp_tables[i], next) { |
2324 | entry = entry->next) { | ||
2325 | if (memcmp | 2247 | if (memcmp |
2326 | (ioc_data->atm_addr, entry->atm_addr, | 2248 | (ioc_data->atm_addr, entry->atm_addr, |
2327 | ATM_ESA_LEN) == 0) { | 2249 | ATM_ESA_LEN) == 0) { |
@@ -2384,8 +2306,7 @@ lec_vcc_added(struct lec_priv *priv, struct atmlec_ioc *ioc_data, | |||
2384 | memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN); | 2306 | memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN); |
2385 | memset(entry->mac_addr, 0, ETH_ALEN); | 2307 | memset(entry->mac_addr, 0, ETH_ALEN); |
2386 | entry->status = ESI_UNKNOWN; | 2308 | entry->status = ESI_UNKNOWN; |
2387 | entry->next = priv->lec_arp_empty_ones; | 2309 | hlist_add_head(&entry->next, &priv->lec_arp_empty_ones); |
2388 | priv->lec_arp_empty_ones = entry; | ||
2389 | entry->timer.expires = jiffies + priv->vcc_timeout_period; | 2310 | entry->timer.expires = jiffies + priv->vcc_timeout_period; |
2390 | entry->timer.function = lec_arp_expire_vcc; | 2311 | entry->timer.function = lec_arp_expire_vcc; |
2391 | add_timer(&entry->timer); | 2312 | add_timer(&entry->timer); |
@@ -2398,14 +2319,14 @@ out: | |||
2398 | static void lec_flush_complete(struct lec_priv *priv, unsigned long tran_id) | 2319 | static void lec_flush_complete(struct lec_priv *priv, unsigned long tran_id) |
2399 | { | 2320 | { |
2400 | unsigned long flags; | 2321 | unsigned long flags; |
2322 | struct hlist_node *node; | ||
2401 | struct lec_arp_table *entry; | 2323 | struct lec_arp_table *entry; |
2402 | int i; | 2324 | int i; |
2403 | 2325 | ||
2404 | DPRINTK("LEC:lec_flush_complete %lx\n", tran_id); | 2326 | DPRINTK("LEC:lec_flush_complete %lx\n", tran_id); |
2405 | spin_lock_irqsave(&priv->lec_arp_lock, flags); | 2327 | spin_lock_irqsave(&priv->lec_arp_lock, flags); |
2406 | for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { | 2328 | for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { |
2407 | for (entry = priv->lec_arp_tables[i]; entry; | 2329 | hlist_for_each_entry(entry, node, &priv->lec_arp_tables[i], next) { |
2408 | entry = entry->next) { | ||
2409 | if (entry->flush_tran_id == tran_id | 2330 | if (entry->flush_tran_id == tran_id |
2410 | && entry->status == ESI_FLUSH_PENDING) { | 2331 | && entry->status == ESI_FLUSH_PENDING) { |
2411 | struct sk_buff *skb; | 2332 | struct sk_buff *skb; |
@@ -2427,19 +2348,19 @@ lec_set_flush_tran_id(struct lec_priv *priv, | |||
2427 | unsigned char *atm_addr, unsigned long tran_id) | 2348 | unsigned char *atm_addr, unsigned long tran_id) |
2428 | { | 2349 | { |
2429 | unsigned long flags; | 2350 | unsigned long flags; |
2351 | struct hlist_node *node; | ||
2430 | struct lec_arp_table *entry; | 2352 | struct lec_arp_table *entry; |
2431 | int i; | 2353 | int i; |
2432 | 2354 | ||
2433 | spin_lock_irqsave(&priv->lec_arp_lock, flags); | 2355 | spin_lock_irqsave(&priv->lec_arp_lock, flags); |
2434 | for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) | 2356 | for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) |
2435 | for (entry = priv->lec_arp_tables[i]; entry; | 2357 | hlist_for_each_entry(entry, node, &priv->lec_arp_tables[i], next) { |
2436 | entry = entry->next) | ||
2437 | if (!memcmp(atm_addr, entry->atm_addr, ATM_ESA_LEN)) { | 2358 | if (!memcmp(atm_addr, entry->atm_addr, ATM_ESA_LEN)) { |
2438 | entry->flush_tran_id = tran_id; | 2359 | entry->flush_tran_id = tran_id; |
2439 | DPRINTK | 2360 | DPRINTK("Set flush transaction id to %lx for %p\n", |
2440 | ("Set flush transaction id to %lx for %p\n", | 2361 | tran_id, entry); |
2441 | tran_id, entry); | ||
2442 | } | 2362 | } |
2363 | } | ||
2443 | spin_unlock_irqrestore(&priv->lec_arp_lock, flags); | 2364 | spin_unlock_irqrestore(&priv->lec_arp_lock, flags); |
2444 | } | 2365 | } |
2445 | 2366 | ||
@@ -2483,15 +2404,17 @@ out: | |||
2483 | static void lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc) | 2404 | static void lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc) |
2484 | { | 2405 | { |
2485 | unsigned long flags; | 2406 | unsigned long flags; |
2486 | struct lec_arp_table *entry, *next; | 2407 | struct hlist_node *node, *next; |
2408 | struct lec_arp_table *entry; | ||
2487 | int i; | 2409 | int i; |
2488 | 2410 | ||
2489 | DPRINTK("LEC_ARP: lec_vcc_close vpi:%d vci:%d\n", vcc->vpi, vcc->vci); | 2411 | DPRINTK("LEC_ARP: lec_vcc_close vpi:%d vci:%d\n", vcc->vpi, vcc->vci); |
2490 | dump_arp_table(priv); | 2412 | dump_arp_table(priv); |
2413 | |||
2491 | spin_lock_irqsave(&priv->lec_arp_lock, flags); | 2414 | spin_lock_irqsave(&priv->lec_arp_lock, flags); |
2415 | |||
2492 | for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { | 2416 | for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { |
2493 | for (entry = priv->lec_arp_tables[i]; entry; entry = next) { | 2417 | hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_tables[i], next) { |
2494 | next = entry->next; | ||
2495 | if (vcc == entry->vcc) { | 2418 | if (vcc == entry->vcc) { |
2496 | lec_arp_remove(priv, entry); | 2419 | lec_arp_remove(priv, entry); |
2497 | kfree(entry); | 2420 | kfree(entry); |
@@ -2502,49 +2425,31 @@ static void lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc) | |||
2502 | } | 2425 | } |
2503 | } | 2426 | } |
2504 | 2427 | ||
2505 | entry = priv->lec_arp_empty_ones; | 2428 | hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_empty_ones, next) { |
2506 | priv->lec_arp_empty_ones = NULL; | 2429 | if (entry->vcc == vcc) { |
2507 | while (entry != NULL) { | ||
2508 | next = entry->next; | ||
2509 | if (entry->vcc == vcc) { /* leave it out from the list */ | ||
2510 | lec_arp_clear_vccs(entry); | 2430 | lec_arp_clear_vccs(entry); |
2511 | del_timer(&entry->timer); | 2431 | del_timer(&entry->timer); |
2432 | hlist_del(&entry->next); | ||
2512 | kfree(entry); | 2433 | kfree(entry); |
2513 | } else { /* put it back to the list */ | ||
2514 | entry->next = priv->lec_arp_empty_ones; | ||
2515 | priv->lec_arp_empty_ones = entry; | ||
2516 | } | 2434 | } |
2517 | entry = next; | ||
2518 | } | 2435 | } |
2519 | 2436 | ||
2520 | entry = priv->lec_no_forward; | 2437 | hlist_for_each_entry_safe(entry, node, next, &priv->lec_no_forward, next) { |
2521 | priv->lec_no_forward = NULL; | ||
2522 | while (entry != NULL) { | ||
2523 | next = entry->next; | ||
2524 | if (entry->recv_vcc == vcc) { | 2438 | if (entry->recv_vcc == vcc) { |
2525 | lec_arp_clear_vccs(entry); | 2439 | lec_arp_clear_vccs(entry); |
2526 | del_timer(&entry->timer); | 2440 | del_timer(&entry->timer); |
2441 | hlist_del(&entry->next); | ||
2527 | kfree(entry); | 2442 | kfree(entry); |
2528 | } else { | ||
2529 | entry->next = priv->lec_no_forward; | ||
2530 | priv->lec_no_forward = entry; | ||
2531 | } | 2443 | } |
2532 | entry = next; | ||
2533 | } | 2444 | } |
2534 | 2445 | ||
2535 | entry = priv->mcast_fwds; | 2446 | hlist_for_each_entry_safe(entry, node, next, &priv->mcast_fwds, next) { |
2536 | priv->mcast_fwds = NULL; | ||
2537 | while (entry != NULL) { | ||
2538 | next = entry->next; | ||
2539 | if (entry->recv_vcc == vcc) { | 2447 | if (entry->recv_vcc == vcc) { |
2540 | lec_arp_clear_vccs(entry); | 2448 | lec_arp_clear_vccs(entry); |
2541 | /* No timer, LANEv2 7.1.20 and 2.3.5.3 */ | 2449 | /* No timer, LANEv2 7.1.20 and 2.3.5.3 */ |
2450 | hlist_del(&entry->next); | ||
2542 | kfree(entry); | 2451 | kfree(entry); |
2543 | } else { | ||
2544 | entry->next = priv->mcast_fwds; | ||
2545 | priv->mcast_fwds = entry; | ||
2546 | } | 2452 | } |
2547 | entry = next; | ||
2548 | } | 2453 | } |
2549 | 2454 | ||
2550 | spin_unlock_irqrestore(&priv->lec_arp_lock, flags); | 2455 | spin_unlock_irqrestore(&priv->lec_arp_lock, flags); |
@@ -2556,7 +2461,8 @@ lec_arp_check_empties(struct lec_priv *priv, | |||
2556 | struct atm_vcc *vcc, struct sk_buff *skb) | 2461 | struct atm_vcc *vcc, struct sk_buff *skb) |
2557 | { | 2462 | { |
2558 | unsigned long flags; | 2463 | unsigned long flags; |
2559 | struct lec_arp_table *entry, *prev; | 2464 | struct hlist_node *node, *next; |
2465 | struct lec_arp_table *entry, *tmp; | ||
2560 | struct lecdatahdr_8023 *hdr = (struct lecdatahdr_8023 *)skb->data; | 2466 | struct lecdatahdr_8023 *hdr = (struct lecdatahdr_8023 *)skb->data; |
2561 | unsigned char *src; | 2467 | unsigned char *src; |
2562 | #ifdef CONFIG_TR | 2468 | #ifdef CONFIG_TR |
@@ -2569,41 +2475,23 @@ lec_arp_check_empties(struct lec_priv *priv, | |||
2569 | src = hdr->h_source; | 2475 | src = hdr->h_source; |
2570 | 2476 | ||
2571 | spin_lock_irqsave(&priv->lec_arp_lock, flags); | 2477 | spin_lock_irqsave(&priv->lec_arp_lock, flags); |
2572 | entry = priv->lec_arp_empty_ones; | 2478 | hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_empty_ones, next) { |
2573 | if (vcc == entry->vcc) { | 2479 | if (vcc == entry->vcc) { |
2574 | del_timer(&entry->timer); | 2480 | del_timer(&entry->timer); |
2575 | memcpy(entry->mac_addr, src, ETH_ALEN); | 2481 | memcpy(entry->mac_addr, src, ETH_ALEN); |
2576 | entry->status = ESI_FORWARD_DIRECT; | 2482 | entry->status = ESI_FORWARD_DIRECT; |
2577 | entry->last_used = jiffies; | 2483 | entry->last_used = jiffies; |
2578 | priv->lec_arp_empty_ones = entry->next; | 2484 | /* We might have got an entry */ |
2579 | /* We might have got an entry */ | 2485 | if ((tmp = lec_arp_find(priv, src))) { |
2580 | if ((prev = lec_arp_find(priv, src))) { | 2486 | lec_arp_remove(priv, tmp); |
2581 | lec_arp_remove(priv, prev); | 2487 | kfree(tmp); |
2582 | kfree(prev); | 2488 | } |
2489 | hlist_del(&entry->next); | ||
2490 | lec_arp_add(priv, entry); | ||
2491 | goto out; | ||
2583 | } | 2492 | } |
2584 | lec_arp_add(priv, entry); | ||
2585 | goto out; | ||
2586 | } | ||
2587 | prev = entry; | ||
2588 | entry = entry->next; | ||
2589 | while (entry && entry->vcc != vcc) { | ||
2590 | prev = entry; | ||
2591 | entry = entry->next; | ||
2592 | } | 2493 | } |
2593 | if (!entry) { | 2494 | DPRINTK("LEC_ARP: Arp_check_empties: entry not found!\n"); |
2594 | DPRINTK("LEC_ARP: Arp_check_empties: entry not found!\n"); | ||
2595 | goto out; | ||
2596 | } | ||
2597 | del_timer(&entry->timer); | ||
2598 | memcpy(entry->mac_addr, src, ETH_ALEN); | ||
2599 | entry->status = ESI_FORWARD_DIRECT; | ||
2600 | entry->last_used = jiffies; | ||
2601 | prev->next = entry->next; | ||
2602 | if ((prev = lec_arp_find(priv, src))) { | ||
2603 | lec_arp_remove(priv, prev); | ||
2604 | kfree(prev); | ||
2605 | } | ||
2606 | lec_arp_add(priv, entry); | ||
2607 | out: | 2495 | out: |
2608 | spin_unlock_irqrestore(&priv->lec_arp_lock, flags); | 2496 | spin_unlock_irqrestore(&priv->lec_arp_lock, flags); |
2609 | } | 2497 | } |