aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/atm/lec.c442
-rw-r--r--net/atm/lec.h8
-rw-r--r--net/atm/lec_arpc.h2
3 files changed, 170 insertions, 282 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)
998struct lec_state { 998struct 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
1008static void *lec_tbl_walk(struct lec_state *state, struct lec_arp_table *tbl, 1008static 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,
1042static void *lec_misc_walk(struct lec_state *state, loff_t *l, 1045static 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 */
1495static inline void 1502static inline void
1496lec_arp_add(struct lec_priv *priv, struct lec_arp_table *to_add) 1503lec_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)
1522static int 1519static int
1523lec_arp_remove(struct lec_priv *priv, struct lec_arp_table *to_remove) 1520lec_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