Commit fc6a7f6d authored by Chas Williams's avatar Chas Williams Committed by David S. Miller

[ATM]: [lec] rewrite to eliminate lec_arp_users in favor of lec_arp_lock

Signed-off-by: default avatarChas Williams <chas@cmf.nrl.navy.mil>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 51763947
...@@ -422,6 +422,7 @@ lec_get_stats(struct net_device *dev) ...@@ -422,6 +422,7 @@ lec_get_stats(struct net_device *dev)
static int static int
lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb) lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb)
{ {
unsigned long flags;
struct net_device *dev = (struct net_device*)vcc->proto_data; struct net_device *dev = (struct net_device*)vcc->proto_data;
struct lec_priv *priv = (struct lec_priv*)dev->priv; struct lec_priv *priv = (struct lec_priv*)dev->priv;
struct atmlec_msg *mesg; struct atmlec_msg *mesg;
...@@ -456,8 +457,10 @@ lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb) ...@@ -456,8 +457,10 @@ lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb)
lec_flush_complete(priv, mesg->content.normal.flag); lec_flush_complete(priv, mesg->content.normal.flag);
break; break;
case l_narp_req: /* LANE2: see 7.1.35 in the lane2 spec */ case l_narp_req: /* LANE2: see 7.1.35 in the lane2 spec */
spin_lock_irqsave(&priv->lec_arp_lock, flags);
entry = lec_arp_find(priv, mesg->content.normal.mac_addr); entry = lec_arp_find(priv, mesg->content.normal.mac_addr);
lec_arp_remove(priv, entry); lec_arp_remove(priv, entry);
spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
if (mesg->content.normal.no_source_le_narp) if (mesg->content.normal.no_source_le_narp)
break; break;
...@@ -1222,17 +1225,20 @@ module_exit(lane_module_cleanup); ...@@ -1222,17 +1225,20 @@ module_exit(lane_module_cleanup);
static int lane2_resolve(struct net_device *dev, u8 *dst_mac, int force, static int lane2_resolve(struct net_device *dev, u8 *dst_mac, int force,
u8 **tlvs, u32 *sizeoftlvs) u8 **tlvs, u32 *sizeoftlvs)
{ {
unsigned long flags;
struct lec_priv *priv = (struct lec_priv *)dev->priv; struct lec_priv *priv = (struct lec_priv *)dev->priv;
struct lec_arp_table *table; struct lec_arp_table *table;
struct sk_buff *skb; struct sk_buff *skb;
int retval; int retval;
if (force == 0) { if (force == 0) {
spin_lock_irqsave(&priv->lec_arp_lock, flags);
table = lec_arp_find(priv, dst_mac); table = lec_arp_find(priv, dst_mac);
spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
if(table == NULL) if(table == NULL)
return -1; return -1;
*tlvs = kmalloc(table->sizeoftlvs, GFP_KERNEL); *tlvs = kmalloc(table->sizeoftlvs, GFP_ATOMIC);
if (*tlvs == NULL) if (*tlvs == NULL)
return -1; return -1;
...@@ -1377,18 +1383,6 @@ void dump_arp_table(struct lec_priv *priv); ...@@ -1377,18 +1383,6 @@ void dump_arp_table(struct lec_priv *priv);
#define HASH(ch) (ch & (LEC_ARP_TABLE_SIZE -1)) #define HASH(ch) (ch & (LEC_ARP_TABLE_SIZE -1))
static __inline__ void
lec_arp_get(struct lec_priv *priv)
{
atomic_inc(&priv->lec_arp_users);
}
static __inline__ void
lec_arp_put(struct lec_priv *priv)
{
atomic_dec(&priv->lec_arp_users);
}
/* /*
* Initialization of arp-cache * Initialization of arp-cache
*/ */
...@@ -1397,12 +1391,12 @@ lec_arp_init(struct lec_priv *priv) ...@@ -1397,12 +1391,12 @@ lec_arp_init(struct lec_priv *priv)
{ {
unsigned short i; unsigned short i;
for (i=0;i<LEC_ARP_TABLE_SIZE;i++) { for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
priv->lec_arp_tables[i] = NULL; priv->lec_arp_tables[i] = NULL;
} }
spin_lock_init(&priv->lec_arp_lock); spin_lock_init(&priv->lec_arp_lock);
init_timer(&priv->lec_arp_timer); init_timer(&priv->lec_arp_timer);
priv->lec_arp_timer.expires = jiffies+LEC_ARP_REFRESH_INTERVAL; priv->lec_arp_timer.expires = jiffies + LEC_ARP_REFRESH_INTERVAL;
priv->lec_arp_timer.data = (unsigned long)priv; priv->lec_arp_timer.data = (unsigned long)priv;
priv->lec_arp_timer.function = lec_arp_check_expire; priv->lec_arp_timer.function = lec_arp_check_expire;
add_timer(&priv->lec_arp_timer); add_timer(&priv->lec_arp_timer);
...@@ -1439,12 +1433,9 @@ lec_arp_clear_vccs(struct lec_arp_table *entry) ...@@ -1439,12 +1433,9 @@ lec_arp_clear_vccs(struct lec_arp_table *entry)
static inline void 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 *to_add)
{ {
unsigned long flags;
unsigned short place; unsigned short place;
struct lec_arp_table *tmp; struct lec_arp_table *tmp;
spin_lock_irqsave(&priv->lec_arp_lock, flags);
place = HASH(to_add->mac_addr[ETH_ALEN-1]); place = HASH(to_add->mac_addr[ETH_ALEN-1]);
tmp = priv->lec_arp_tables[place]; tmp = priv->lec_arp_tables[place];
to_add->next = NULL; to_add->next = NULL;
...@@ -1457,8 +1448,6 @@ lec_arp_add(struct lec_priv *priv, struct lec_arp_table *to_add) ...@@ -1457,8 +1448,6 @@ lec_arp_add(struct lec_priv *priv, struct lec_arp_table *to_add)
tmp->next = to_add; tmp->next = to_add;
} }
spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
DPRINTK("LEC_ARP: Added entry:%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n", 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[0], 0xff&to_add->mac_addr[1],
0xff&to_add->mac_addr[2], 0xff&to_add->mac_addr[3], 0xff&to_add->mac_addr[2], 0xff&to_add->mac_addr[3],
...@@ -1472,15 +1461,11 @@ static int ...@@ -1472,15 +1461,11 @@ static int
lec_arp_remove(struct lec_priv *priv, lec_arp_remove(struct lec_priv *priv,
struct lec_arp_table *to_remove) struct lec_arp_table *to_remove)
{ {
unsigned long flags;
unsigned short place; unsigned short place;
struct lec_arp_table *tmp; struct lec_arp_table *tmp;
int remove_vcc=1; int remove_vcc=1;
spin_lock_irqsave(&priv->lec_arp_lock, flags);
if (!to_remove) { if (!to_remove) {
spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
return -1; return -1;
} }
place = HASH(to_remove->mac_addr[ETH_ALEN-1]); place = HASH(to_remove->mac_addr[ETH_ALEN-1]);
...@@ -1492,7 +1477,6 @@ lec_arp_remove(struct lec_priv *priv, ...@@ -1492,7 +1477,6 @@ lec_arp_remove(struct lec_priv *priv,
tmp = tmp->next; tmp = tmp->next;
} }
if (!tmp) {/* Entry was not found */ if (!tmp) {/* Entry was not found */
spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
return -1; return -1;
} }
} }
...@@ -1505,7 +1489,7 @@ lec_arp_remove(struct lec_priv *priv, ...@@ -1505,7 +1489,7 @@ lec_arp_remove(struct lec_priv *priv,
/* /*
* ESI_FLUSH_PENDING, ESI_FORWARD_DIRECT * ESI_FLUSH_PENDING, ESI_FORWARD_DIRECT
*/ */
for(place=0;place<LEC_ARP_TABLE_SIZE;place++) { for(place = 0; place < LEC_ARP_TABLE_SIZE; place++) {
for(tmp = priv->lec_arp_tables[place]; tmp != NULL; tmp = tmp->next) { for(tmp = priv->lec_arp_tables[place]; tmp != NULL; tmp = tmp->next) {
if (memcmp(tmp->atm_addr, to_remove->atm_addr, if (memcmp(tmp->atm_addr, to_remove->atm_addr,
ATM_ESA_LEN)==0) { ATM_ESA_LEN)==0) {
...@@ -1519,8 +1503,6 @@ lec_arp_remove(struct lec_priv *priv, ...@@ -1519,8 +1503,6 @@ lec_arp_remove(struct lec_priv *priv,
} }
skb_queue_purge(&to_remove->tx_wait); /* FIXME: good place for this? */ skb_queue_purge(&to_remove->tx_wait); /* FIXME: good place for this? */
spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
DPRINTK("LEC_ARP: Removed entry:%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n", DPRINTK("LEC_ARP: Removed entry:%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n",
0xff&to_remove->mac_addr[0], 0xff&to_remove->mac_addr[1], 0xff&to_remove->mac_addr[0], 0xff&to_remove->mac_addr[1],
0xff&to_remove->mac_addr[2], 0xff&to_remove->mac_addr[3], 0xff&to_remove->mac_addr[2], 0xff&to_remove->mac_addr[3],
...@@ -1704,6 +1686,7 @@ dump_arp_table(struct lec_priv *priv) ...@@ -1704,6 +1686,7 @@ dump_arp_table(struct lec_priv *priv)
void void
lec_arp_destroy(struct lec_priv *priv) lec_arp_destroy(struct lec_priv *priv)
{ {
unsigned long flags;
struct lec_arp_table *entry, *next; struct lec_arp_table *entry, *next;
int i; int i;
...@@ -1712,8 +1695,10 @@ lec_arp_destroy(struct lec_priv *priv) ...@@ -1712,8 +1695,10 @@ lec_arp_destroy(struct lec_priv *priv)
/* /*
* Remove all entries * Remove all entries
*/ */
for (i=0;i<LEC_ARP_TABLE_SIZE;i++) {
for(entry =priv->lec_arp_tables[i];entry != NULL; entry=next) { 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; next = entry->next;
lec_arp_remove(priv, entry); lec_arp_remove(priv, entry);
kfree(entry); kfree(entry);
...@@ -1748,7 +1733,8 @@ lec_arp_destroy(struct lec_priv *priv) ...@@ -1748,7 +1733,8 @@ lec_arp_destroy(struct lec_priv *priv)
priv->mcast_fwds = NULL; priv->mcast_fwds = NULL;
priv->mcast_vcc = NULL; priv->mcast_vcc = NULL;
memset(priv->lec_arp_tables, 0, memset(priv->lec_arp_tables, 0,
sizeof(struct lec_arp_table*)*LEC_ARP_TABLE_SIZE); sizeof(struct lec_arp_table *) * LEC_ARP_TABLE_SIZE);
spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
} }
...@@ -1765,18 +1751,15 @@ lec_arp_find(struct lec_priv *priv, ...@@ -1765,18 +1751,15 @@ lec_arp_find(struct lec_priv *priv,
DPRINTK("LEC_ARP: lec_arp_find :%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n", 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[0]&0xff, mac_addr[1]&0xff, mac_addr[2]&0xff,
mac_addr[3]&0xff, mac_addr[4]&0xff, mac_addr[5]&0xff); mac_addr[3]&0xff, mac_addr[4]&0xff, mac_addr[5]&0xff);
lec_arp_get(priv);
place = HASH(mac_addr[ETH_ALEN-1]); place = HASH(mac_addr[ETH_ALEN-1]);
to_return = priv->lec_arp_tables[place]; to_return = priv->lec_arp_tables[place];
while(to_return) { while(to_return) {
if (memcmp(mac_addr, to_return->mac_addr, ETH_ALEN) == 0) { if (memcmp(mac_addr, to_return->mac_addr, ETH_ALEN) == 0) {
lec_arp_put(priv);
return to_return; return to_return;
} }
to_return = to_return->next; to_return = to_return->next;
} }
lec_arp_put(priv);
return NULL; return NULL;
} }
...@@ -1785,17 +1768,17 @@ make_entry(struct lec_priv *priv, unsigned char *mac_addr) ...@@ -1785,17 +1768,17 @@ make_entry(struct lec_priv *priv, unsigned char *mac_addr)
{ {
struct lec_arp_table *to_return; struct lec_arp_table *to_return;
to_return=(struct lec_arp_table *)kmalloc(sizeof(struct lec_arp_table), to_return = (struct lec_arp_table *) kmalloc(sizeof(struct lec_arp_table),
GFP_ATOMIC); GFP_ATOMIC);
if (!to_return) { if (!to_return) {
printk("LEC: Arp entry kmalloc failed\n"); printk("LEC: Arp entry kmalloc failed\n");
return NULL; return NULL;
} }
memset(to_return,0,sizeof(struct lec_arp_table)); memset(to_return, 0, sizeof(struct lec_arp_table));
memcpy(to_return->mac_addr, mac_addr, ETH_ALEN); memcpy(to_return->mac_addr, mac_addr, ETH_ALEN);
init_timer(&to_return->timer); init_timer(&to_return->timer);
to_return->timer.function = lec_arp_expire_arp; to_return->timer.function = lec_arp_expire_arp;
to_return->timer.data = (unsigned long)to_return; to_return->timer.data = (unsigned long) to_return;
to_return->last_used = jiffies; to_return->last_used = jiffies;
to_return->priv = priv; to_return->priv = priv;
skb_queue_head_init(&to_return->tx_wait); skb_queue_head_init(&to_return->tx_wait);
...@@ -1835,6 +1818,7 @@ lec_arp_expire_arp(unsigned long data) ...@@ -1835,6 +1818,7 @@ lec_arp_expire_arp(unsigned long data)
static void static void
lec_arp_expire_vcc(unsigned long data) lec_arp_expire_vcc(unsigned long data)
{ {
unsigned flags;
struct lec_arp_table *to_remove = (struct lec_arp_table*)data; struct lec_arp_table *to_remove = (struct lec_arp_table*)data;
struct lec_priv *priv = (struct lec_priv *)to_remove->priv; struct lec_priv *priv = (struct lec_priv *)to_remove->priv;
struct lec_arp_table *entry = NULL; struct lec_arp_table *entry = NULL;
...@@ -1846,6 +1830,8 @@ lec_arp_expire_vcc(unsigned long data) ...@@ -1846,6 +1830,8 @@ lec_arp_expire_vcc(unsigned long data)
to_remove->vcc?to_remove->recv_vcc->vpi:0, to_remove->vcc?to_remove->recv_vcc->vpi:0,
to_remove->vcc?to_remove->recv_vcc->vci: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); 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) if (to_remove == priv->lec_arp_empty_ones)
priv->lec_arp_empty_ones = to_remove->next; priv->lec_arp_empty_ones = to_remove->next;
else { else {
...@@ -1866,6 +1852,8 @@ lec_arp_expire_vcc(unsigned long data) ...@@ -1866,6 +1852,8 @@ lec_arp_expire_vcc(unsigned long data)
entry->next = to_remove->next; entry->next = to_remove->next;
} }
} }
spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
lec_arp_clear_vccs(to_remove); lec_arp_clear_vccs(to_remove);
kfree(to_remove); kfree(to_remove);
} }
...@@ -1889,24 +1877,23 @@ lec_arp_expire_vcc(unsigned long data) ...@@ -1889,24 +1877,23 @@ lec_arp_expire_vcc(unsigned long data)
static void static void
lec_arp_check_expire(unsigned long data) lec_arp_check_expire(unsigned long data)
{ {
unsigned long flags;
struct lec_priv *priv = (struct lec_priv *)data; struct lec_priv *priv = (struct lec_priv *)data;
struct lec_arp_table *entry, *next; struct lec_arp_table *entry, *next;
unsigned long now; unsigned long now;
unsigned long time_to_check; unsigned long time_to_check;
int i; int i;
DPRINTK("lec_arp_check_expire %p,%d\n",priv, DPRINTK("lec_arp_check_expire %p\n",priv);
atomic_read(&priv->lec_arp_users));
DPRINTK("expire: eo:%p nf:%p\n",priv->lec_arp_empty_ones, DPRINTK("expire: eo:%p nf:%p\n",priv->lec_arp_empty_ones,
priv->lec_no_forward); priv->lec_no_forward);
if (!atomic_read(&priv->lec_arp_users)) {
lec_arp_get(priv);
now = jiffies; now = jiffies;
for(i=0;i<LEC_ARP_TABLE_SIZE;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 != NULL; ) { for(entry = priv->lec_arp_tables[i]; entry != NULL; ) {
if ((entry->flags) & LEC_REMOTE_FLAG && if ((entry->flags) & LEC_REMOTE_FLAG &&
priv->topology_change) priv->topology_change)
time_to_check=priv->forward_delay_time; time_to_check = priv->forward_delay_time;
else else
time_to_check = priv->aging_time; time_to_check = priv->aging_time;
...@@ -1950,8 +1937,7 @@ lec_arp_check_expire(unsigned long data) ...@@ -1950,8 +1937,7 @@ lec_arp_check_expire(unsigned long data)
} }
} }
} }
lec_arp_put(priv); spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
}
mod_timer(&priv->lec_arp_timer, jiffies + LEC_ARP_REFRESH_INTERVAL); mod_timer(&priv->lec_arp_timer, jiffies + LEC_ARP_REFRESH_INTERVAL);
} }
...@@ -1963,9 +1949,11 @@ struct atm_vcc* ...@@ -1963,9 +1949,11 @@ struct atm_vcc*
lec_arp_resolve(struct lec_priv *priv, unsigned char *mac_to_find, int is_rdesc, lec_arp_resolve(struct lec_priv *priv, unsigned char *mac_to_find, int is_rdesc,
struct lec_arp_table **ret_entry) struct lec_arp_table **ret_entry)
{ {
unsigned long flags;
struct lec_arp_table *entry; struct lec_arp_table *entry;
struct atm_vcc *found;
if (mac_to_find[0]&0x01) { if (mac_to_find[0] & 0x01) {
switch (priv->lane_version) { switch (priv->lane_version) {
case 1: case 1:
return priv->mcast_vcc; return priv->mcast_vcc;
...@@ -1979,6 +1967,7 @@ lec_arp_resolve(struct lec_priv *priv, unsigned char *mac_to_find, int is_rdesc, ...@@ -1979,6 +1967,7 @@ lec_arp_resolve(struct lec_priv *priv, unsigned char *mac_to_find, int is_rdesc,
} }
} }
spin_lock_irqsave(&priv->lec_arp_lock, flags);
entry = lec_arp_find(priv, mac_to_find); entry = lec_arp_find(priv, mac_to_find);
if (entry) { if (entry) {
...@@ -1986,7 +1975,8 @@ lec_arp_resolve(struct lec_priv *priv, unsigned char *mac_to_find, int is_rdesc, ...@@ -1986,7 +1975,8 @@ lec_arp_resolve(struct lec_priv *priv, unsigned char *mac_to_find, int is_rdesc,
/* Connection Ok */ /* Connection Ok */
entry->last_used = jiffies; entry->last_used = jiffies;
*ret_entry = entry; *ret_entry = entry;
return entry->vcc; found = entry->vcc;
goto out;
} }
/* Data direct VC not yet set up, check to see if the unknown /* Data direct VC not yet set up, check to see if the unknown
frame count is greater than the limit. If the limit has frame count is greater than the limit. If the limit has
...@@ -1996,7 +1986,8 @@ lec_arp_resolve(struct lec_priv *priv, unsigned char *mac_to_find, int is_rdesc, ...@@ -1996,7 +1986,8 @@ lec_arp_resolve(struct lec_priv *priv, unsigned char *mac_to_find, int is_rdesc,
entry->packets_flooded<priv->maximum_unknown_frame_count) { entry->packets_flooded<priv->maximum_unknown_frame_count) {
entry->packets_flooded++; entry->packets_flooded++;
DPRINTK("LEC_ARP: Flooding..\n"); DPRINTK("LEC_ARP: Flooding..\n");
return priv->mcast_vcc; found = priv->mcast_vcc;
goto out;
} }
/* We got here because entry->status == ESI_FLUSH_PENDING /* We got here because entry->status == ESI_FLUSH_PENDING
* or BUS flood limit was reached for an entry which is * or BUS flood limit was reached for an entry which is
...@@ -2004,13 +1995,14 @@ lec_arp_resolve(struct lec_priv *priv, unsigned char *mac_to_find, int is_rdesc, ...@@ -2004,13 +1995,14 @@ lec_arp_resolve(struct lec_priv *priv, unsigned char *mac_to_find, int is_rdesc,
*/ */
*ret_entry = entry; *ret_entry = entry;
DPRINTK("lec: entry->status %d entry->vcc %p\n", entry->status, entry->vcc); DPRINTK("lec: entry->status %d entry->vcc %p\n", entry->status, entry->vcc);
return NULL; found = NULL;
} else { } else {
/* No matching entry was found */ /* No matching entry was found */
entry = make_entry(priv, mac_to_find); entry = make_entry(priv, mac_to_find);
DPRINTK("LEC_ARP: Making entry\n"); DPRINTK("LEC_ARP: Making entry\n");
if (!entry) { if (!entry) {
return priv->mcast_vcc; found = priv->mcast_vcc;
goto out;
} }
lec_arp_add(priv, entry); lec_arp_add(priv, entry);
/* We want arp-request(s) to be sent */ /* We want arp-request(s) to be sent */
...@@ -2026,21 +2018,26 @@ lec_arp_resolve(struct lec_priv *priv, unsigned char *mac_to_find, int is_rdesc, ...@@ -2026,21 +2018,26 @@ lec_arp_resolve(struct lec_priv *priv, unsigned char *mac_to_find, int is_rdesc,
entry->timer.expires = jiffies + (1*HZ); entry->timer.expires = jiffies + (1*HZ);
entry->timer.function = lec_arp_expire_arp; entry->timer.function = lec_arp_expire_arp;
add_timer(&entry->timer); add_timer(&entry->timer);
return priv->mcast_vcc; found = priv->mcast_vcc;
} }
out:
spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
return found;
} }
int int
lec_addr_delete(struct lec_priv *priv, unsigned char *atm_addr, lec_addr_delete(struct lec_priv *priv, unsigned char *atm_addr,
unsigned long permanent) unsigned long permanent)
{ {
unsigned long flags;
struct lec_arp_table *entry, *next; struct lec_arp_table *entry, *next;
int i; int i;
lec_arp_get(priv);
DPRINTK("lec_addr_delete\n"); DPRINTK("lec_addr_delete\n");
for(i=0;i<LEC_ARP_TABLE_SIZE;i++) { spin_lock_irqsave(&priv->lec_arp_lock, flags);
for(entry=priv->lec_arp_tables[i];entry != NULL; entry=next) { for(i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
for(entry = priv->lec_arp_tables[i]; entry != NULL; entry = next) {
next = entry->next; next = entry->next;
if (!memcmp(atm_addr, entry->atm_addr, ATM_ESA_LEN) if (!memcmp(atm_addr, entry->atm_addr, ATM_ESA_LEN)
&& (permanent || && (permanent ||
...@@ -2048,11 +2045,11 @@ lec_addr_delete(struct lec_priv *priv, unsigned char *atm_addr, ...@@ -2048,11 +2045,11 @@ lec_addr_delete(struct lec_priv *priv, unsigned char *atm_addr,
lec_arp_remove(priv, entry); lec_arp_remove(priv, entry);
kfree(entry); kfree(entry);
} }
lec_arp_put(priv); spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
return 0; return 0;
} }
} }
lec_arp_put(priv); spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
return -1; return -1;
} }
...@@ -2064,6 +2061,7 @@ lec_arp_update(struct lec_priv *priv, unsigned char *mac_addr, ...@@ -2064,6 +2061,7 @@ lec_arp_update(struct lec_priv *priv, unsigned char *mac_addr,
unsigned char *atm_addr, unsigned long remoteflag, unsigned char *atm_addr, unsigned long remoteflag,
unsigned int targetless_le_arp) unsigned int targetless_le_arp)
{ {
unsigned long flags;
struct lec_arp_table *entry, *tmp; struct lec_arp_table *entry, *tmp;
int i; int i;
...@@ -2072,12 +2070,12 @@ lec_arp_update(struct lec_priv *priv, unsigned char *mac_addr, ...@@ -2072,12 +2070,12 @@ lec_arp_update(struct lec_priv *priv, unsigned char *mac_addr,
mac_addr[0],mac_addr[1],mac_addr[2],mac_addr[3], mac_addr[0],mac_addr[1],mac_addr[2],mac_addr[3],
mac_addr[4],mac_addr[5]); mac_addr[4],mac_addr[5]);
spin_lock_irqsave(&priv->lec_arp_lock, flags);
entry = lec_arp_find(priv, mac_addr); entry = lec_arp_find(priv, mac_addr);
if (entry == NULL && targetless_le_arp) if (entry == NULL && targetless_le_arp)
return; /* LANE2: ignore targetless LE_ARPs for which goto out; /* LANE2: ignore targetless LE_ARPs for which
* we have no entry in the cache. 7.1.30 * we have no entry in the cache. 7.1.30
*/ */
lec_arp_get(priv);
if (priv->lec_arp_empty_ones) { if (priv->lec_arp_empty_ones) {
entry = priv->lec_arp_empty_ones; entry = priv->lec_arp_empty_ones;
if (!memcmp(entry->atm_addr, atm_addr, ATM_ESA_LEN)) { if (!memcmp(entry->atm_addr, atm_addr, ATM_ESA_LEN)) {
...@@ -2117,27 +2115,24 @@ lec_arp_update(struct lec_priv *priv, unsigned char *mac_addr, ...@@ -2117,27 +2115,24 @@ lec_arp_update(struct lec_priv *priv, unsigned char *mac_addr,
entry->flags|=LEC_REMOTE_FLAG; entry->flags|=LEC_REMOTE_FLAG;
else else
entry->flags&=~LEC_REMOTE_FLAG; entry->flags&=~LEC_REMOTE_FLAG;
lec_arp_put(priv);
DPRINTK("After update\n"); DPRINTK("After update\n");
dump_arp_table(priv); dump_arp_table(priv);
return; goto out;
} }
} }
entry = lec_arp_find(priv, mac_addr); entry = lec_arp_find(priv, mac_addr);
if (!entry) { if (!entry) {
entry = make_entry(priv, mac_addr); entry = make_entry(priv, mac_addr);
if (!entry) { if (!entry)
lec_arp_put(priv); goto out;
return;
}
entry->status = ESI_UNKNOWN; entry->status = ESI_UNKNOWN;
lec_arp_add(priv, entry); lec_arp_add(priv, entry);
/* Temporary, changes before end of function */ /* Temporary, changes before end of function */
} }
memcpy(entry->atm_addr, atm_addr, ATM_ESA_LEN); memcpy(entry->atm_addr, atm_addr, ATM_ESA_LEN);
del_timer(&entry->timer); del_timer(&entry->timer);
for(i=0;i<LEC_ARP_TABLE_SIZE;i++) { for(i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
for(tmp=priv->lec_arp_tables[i];tmp;tmp=tmp->next) { for(tmp = priv->lec_arp_tables[i]; tmp; tmp=tmp->next) {
if (entry != tmp && if (entry != tmp &&
!memcmp(tmp->atm_addr, atm_addr, !memcmp(tmp->atm_addr, atm_addr,
ATM_ESA_LEN)) { ATM_ESA_LEN)) {
...@@ -2166,7 +2161,8 @@ lec_arp_update(struct lec_priv *priv, unsigned char *mac_addr, ...@@ -2166,7 +2161,8 @@ lec_arp_update(struct lec_priv *priv, unsigned char *mac_addr,
} }
DPRINTK("After update2\n"); DPRINTK("After update2\n");
dump_arp_table(priv); dump_arp_table(priv);
lec_arp_put(priv); out:
spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
} }
/* /*
...@@ -2177,10 +2173,11 @@ lec_vcc_added(struct lec_priv *priv, struct atmlec_ioc *ioc_data, ...@@ -2177,10 +2173,11 @@ lec_vcc_added(struct lec_priv *priv, struct atmlec_ioc *ioc_data,
struct atm_vcc *vcc, struct atm_vcc *vcc,
void (*old_push)(struct atm_vcc *vcc, struct sk_buff *skb)) void (*old_push)(struct atm_vcc *vcc, struct sk_buff *skb))
{ {
unsigned long flags;
struct lec_arp_table *entry; struct lec_arp_table *entry;
int i, found_entry=0; int i, found_entry=0;
lec_arp_get(priv); spin_lock_irqsave(&priv->lec_arp_lock, flags);
if (ioc_data->receive == 2) { if (ioc_data->receive == 2) {
/* Vcc for Multicast Forward. No timer, LANEv2 7.1.20 and 2.3.5.3 */ /* Vcc for Multicast Forward. No timer, LANEv2 7.1.20 and 2.3.5.3 */
...@@ -2189,26 +2186,22 @@ lec_vcc_added(struct lec_priv *priv, struct atmlec_ioc *ioc_data, ...@@ -2189,26 +2186,22 @@ lec_vcc_added(struct lec_priv *priv, struct atmlec_ioc *ioc_data,
entry = lec_arp_find(priv, bus_mac); entry = lec_arp_find(priv, bus_mac);
if (!entry) { if (!entry) {
printk("LEC_ARP: Multicast entry not found!\n"); printk("LEC_ARP: Multicast entry not found!\n");
lec_arp_put(priv); goto out;
return;
} }
memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN); memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN);
entry->recv_vcc = vcc; entry->recv_vcc = vcc;
entry->old_recv_push = old_push; entry->old_recv_push = old_push;
#endif #endif
entry = make_entry(priv, bus_mac); entry = make_entry(priv, bus_mac);
if (entry == NULL) { if (entry == NULL)
lec_arp_put(priv); goto out;
return;
}
del_timer(&entry->timer); del_timer(&entry->timer);
memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN); memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN);
entry->recv_vcc = vcc; entry->recv_vcc = vcc;
entry->old_recv_push = old_push; entry->old_recv_push = old_push;
entry->next = priv->mcast_fwds; entry->next = priv->mcast_fwds;
priv->mcast_fwds = entry; priv->mcast_fwds = entry;
lec_arp_put(priv); goto out;
return;
} else if (ioc_data->receive == 1) { } else if (ioc_data->receive == 1) {
/* Vcc which we don't want to make default vcc, attach it /* Vcc which we don't want to make default vcc, attach it
anyway. */ anyway. */
...@@ -2224,10 +2217,8 @@ lec_vcc_added(struct lec_priv *priv, struct atmlec_ioc *ioc_data, ...@@ -2224,10 +2217,8 @@ 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[16],ioc_data->atm_addr[17],
ioc_data->atm_addr[18],ioc_data->atm_addr[19]); ioc_data->atm_addr[18],ioc_data->atm_addr[19]);
entry = make_entry(priv, bus_mac); entry = make_entry(priv, bus_mac);
if (entry == NULL) { if (entry == NULL)
lec_arp_put(priv); goto out;
return;
}
memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN); memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN);
memset(entry->mac_addr, 0, ETH_ALEN); memset(entry->mac_addr, 0, ETH_ALEN);
entry->recv_vcc = vcc; entry->recv_vcc = vcc;
...@@ -2238,9 +2229,8 @@ lec_vcc_added(struct lec_priv *priv, struct atmlec_ioc *ioc_data, ...@@ -2238,9 +2229,8 @@ lec_vcc_added(struct lec_priv *priv, struct atmlec_ioc *ioc_data,
add_timer(&entry->timer); add_timer(&entry->timer);
entry->next = priv->lec_no_forward; entry->next = priv->lec_no_forward;
priv->lec_no_forward = entry; priv->lec_no_forward = entry;
lec_arp_put(priv);
dump_arp_table(priv); dump_arp_table(priv);
return; goto out;
} }
DPRINTK("LEC_ARP:Attaching data direct, default:%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n", DPRINTK("LEC_ARP:Attaching data direct, default:%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n",
ioc_data->atm_addr[0],ioc_data->atm_addr[1], ioc_data->atm_addr[0],ioc_data->atm_addr[1],
...@@ -2253,8 +2243,8 @@ lec_vcc_added(struct lec_priv *priv, struct atmlec_ioc *ioc_data, ...@@ -2253,8 +2243,8 @@ lec_vcc_added(struct lec_priv *priv, struct atmlec_ioc *ioc_data,
ioc_data->atm_addr[14],ioc_data->atm_addr[15], ioc_data->atm_addr[14],ioc_data->atm_addr[15],
ioc_data->atm_addr[16],ioc_data->atm_addr[17], ioc_data->atm_addr[16],ioc_data->atm_addr[17],
ioc_data->atm_addr[18],ioc_data->atm_addr[19]); ioc_data->atm_addr[18],ioc_data->atm_addr[19]);
for (i=0;i<LEC_ARP_TABLE_SIZE;i++) { for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
for (entry = priv->lec_arp_tables[i];entry;entry=entry->next) { for (entry = priv->lec_arp_tables[i]; entry; entry=entry->next) {
if (memcmp(ioc_data->atm_addr, entry->atm_addr, if (memcmp(ioc_data->atm_addr, entry->atm_addr,
ATM_ESA_LEN)==0) { ATM_ESA_LEN)==0) {
DPRINTK("LEC_ARP: Attaching data direct\n"); DPRINTK("LEC_ARP: Attaching data direct\n");
...@@ -2297,18 +2287,15 @@ lec_vcc_added(struct lec_priv *priv, struct atmlec_ioc *ioc_data, ...@@ -2297,18 +2287,15 @@ lec_vcc_added(struct lec_priv *priv, struct atmlec_ioc *ioc_data,
} }
} }
if (found_entry) { if (found_entry) {
lec_arp_put(priv);
DPRINTK("After vcc was added\n"); DPRINTK("After vcc was added\n");
dump_arp_table(priv); dump_arp_table(priv);
return; goto out;
} }
/* Not found, snatch address from first data packet that arrives from /* Not found, snatch address from first data packet that arrives from
this vcc */ this vcc */
entry = make_entry(priv, bus_mac); entry = make_entry(priv, bus_mac);
if (!entry) { if (!entry)
lec_arp_put(priv); goto out;
return;
}
entry->vcc = vcc; entry->vcc = vcc;
entry->old_push = old_push; entry->old_push = old_push;
memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN); memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN);
...@@ -2319,20 +2306,23 @@ lec_vcc_added(struct lec_priv *priv, struct atmlec_ioc *ioc_data, ...@@ -2319,20 +2306,23 @@ lec_vcc_added(struct lec_priv *priv, struct atmlec_ioc *ioc_data,
entry->timer.expires = jiffies + priv->vcc_timeout_period; entry->timer.expires = jiffies + priv->vcc_timeout_period;
entry->timer.function = lec_arp_expire_vcc; entry->timer.function = lec_arp_expire_vcc;
add_timer(&entry->timer); add_timer(&entry->timer);
lec_arp_put(priv);
DPRINTK("After vcc was added\n"); DPRINTK("After vcc was added\n");
dump_arp_table(priv); dump_arp_table(priv);
out:
spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
} }
void void
lec_flush_complete(struct lec_priv *priv, unsigned long tran_id) lec_flush_complete(struct lec_priv *priv, unsigned long tran_id)
{ {
unsigned long flags;
struct lec_arp_table *entry; struct lec_arp_table *entry;
int i; int i;
DPRINTK("LEC:lec_flush_complete %lx\n",tran_id); DPRINTK("LEC:lec_flush_complete %lx\n",tran_id);
for (i=0;i<LEC_ARP_TABLE_SIZE;i++) { spin_lock_irqsave(&priv->lec_arp_lock, flags);
for (entry=priv->lec_arp_tables[i];entry;entry=entry->next) { for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
for (entry = priv->lec_arp_tables[i]; entry; entry=entry->next) {
if (entry->flush_tran_id == tran_id && if (entry->flush_tran_id == tran_id &&
entry->status == ESI_FLUSH_PENDING) { entry->status == ESI_FLUSH_PENDING) {
struct sk_buff *skb; struct sk_buff *skb;
...@@ -2344,6 +2334,7 @@ lec_flush_complete(struct lec_priv *priv, unsigned long tran_id) ...@@ -2344,6 +2334,7 @@ lec_flush_complete(struct lec_priv *priv, unsigned long tran_id)
} }
} }
} }
spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
dump_arp_table(priv); dump_arp_table(priv);
} }
...@@ -2351,24 +2342,29 @@ void ...@@ -2351,24 +2342,29 @@ void
lec_set_flush_tran_id(struct lec_priv *priv, lec_set_flush_tran_id(struct lec_priv *priv,
unsigned char *atm_addr, unsigned long tran_id) unsigned char *atm_addr, unsigned long tran_id)
{ {
unsigned long flags;
struct lec_arp_table *entry; struct lec_arp_table *entry;
int i; int i;
for (i=0;i<LEC_ARP_TABLE_SIZE;i++) spin_lock_irqsave(&priv->lec_arp_lock, flags);
for(entry=priv->lec_arp_tables[i];entry;entry=entry->next) for (i = 0; i < LEC_ARP_TABLE_SIZE; i++)
for(entry = priv->lec_arp_tables[i]; entry; entry=entry->next)
if (!memcmp(atm_addr, entry->atm_addr, ATM_ESA_LEN)) { if (!memcmp(atm_addr, entry->atm_addr, ATM_ESA_LEN)) {
entry->flush_tran_id = tran_id; 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);
} }
int int
lec_mcast_make(struct lec_priv *priv, struct atm_vcc *vcc) lec_mcast_make(struct lec_priv *priv, struct atm_vcc *vcc)
{ {
unsigned long flags;
unsigned char mac_addr[] = { unsigned char mac_addr[] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
struct lec_arp_table *to_add; struct lec_arp_table *to_add;
struct lec_vcc_priv *vpriv; struct lec_vcc_priv *vpriv;
int err = 0;
if (!(vpriv = kmalloc(sizeof(struct lec_vcc_priv), GFP_KERNEL))) if (!(vpriv = kmalloc(sizeof(struct lec_vcc_priv), GFP_KERNEL)))
return -ENOMEM; return -ENOMEM;
...@@ -2376,13 +2372,13 @@ lec_mcast_make(struct lec_priv *priv, struct atm_vcc *vcc) ...@@ -2376,13 +2372,13 @@ lec_mcast_make(struct lec_priv *priv, struct atm_vcc *vcc)
vpriv->old_pop = vcc->pop; vpriv->old_pop = vcc->pop;
vcc->user_back = vpriv; vcc->user_back = vpriv;
vcc->pop = lec_pop; vcc->pop = lec_pop;
lec_arp_get(priv); spin_lock_irqsave(&priv->lec_arp_lock, flags);
to_add = make_entry(priv, mac_addr); to_add = make_entry(priv, mac_addr);
if (!to_add) { if (!to_add) {
lec_arp_put(priv);
vcc->pop = vpriv->old_pop; vcc->pop = vpriv->old_pop;
kfree(vpriv); kfree(vpriv);
return -ENOMEM; err = -ENOMEM;
goto out;
} }
memcpy(to_add->atm_addr, vcc->remote.sas_addr.prv, ATM_ESA_LEN); memcpy(to_add->atm_addr, vcc->remote.sas_addr.prv, ATM_ESA_LEN);
to_add->status = ESI_FORWARD_DIRECT; to_add->status = ESI_FORWARD_DIRECT;
...@@ -2392,19 +2388,21 @@ lec_mcast_make(struct lec_priv *priv, struct atm_vcc *vcc) ...@@ -2392,19 +2388,21 @@ lec_mcast_make(struct lec_priv *priv, struct atm_vcc *vcc)
vcc->push = lec_push; vcc->push = lec_push;
priv->mcast_vcc = vcc; priv->mcast_vcc = vcc;
lec_arp_add(priv, to_add); lec_arp_add(priv, to_add);
lec_arp_put(priv); out:
return 0; spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
return err;
} }
void void
lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc) lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc)
{ {
unsigned long flags;
struct lec_arp_table *entry, *next; struct lec_arp_table *entry, *next;
int i; int i;
DPRINTK("LEC_ARP: lec_vcc_close vpi:%d vci:%d\n",vcc->vpi,vcc->vci); DPRINTK("LEC_ARP: lec_vcc_close vpi:%d vci:%d\n",vcc->vpi,vcc->vci);
dump_arp_table(priv); dump_arp_table(priv);
lec_arp_get(priv); spin_lock_irqsave(&priv->lec_arp_lock, flags);
for(i=0;i<LEC_ARP_TABLE_SIZE;i++) { for(i=0;i<LEC_ARP_TABLE_SIZE;i++) {
for(entry = priv->lec_arp_tables[i];entry; entry=next) { for(entry = priv->lec_arp_tables[i];entry; entry=next) {
next = entry->next; next = entry->next;
...@@ -2466,7 +2464,7 @@ lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc) ...@@ -2466,7 +2464,7 @@ lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc)
entry = next; entry = next;
} }
lec_arp_put(priv); spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
dump_arp_table(priv); dump_arp_table(priv);
} }
...@@ -2486,26 +2484,22 @@ lec_arp_check_empties(struct lec_priv *priv, ...@@ -2486,26 +2484,22 @@ lec_arp_check_empties(struct lec_priv *priv,
#endif #endif
src = hdr->h_source; src = hdr->h_source;
lec_arp_get(priv); spin_lock_irqsave(&priv->lec_arp_lock, flags);
entry = priv->lec_arp_empty_ones; entry = priv->lec_arp_empty_ones;
if (vcc == entry->vcc) { if (vcc == entry->vcc) {
spin_lock_irqsave(&priv->lec_arp_lock, flags);
del_timer(&entry->timer); del_timer(&entry->timer);
memcpy(entry->mac_addr, src, ETH_ALEN); memcpy(entry->mac_addr, src, ETH_ALEN);
entry->status = ESI_FORWARD_DIRECT; entry->status = ESI_FORWARD_DIRECT;
entry->last_used = jiffies; entry->last_used = jiffies;
priv->lec_arp_empty_ones = entry->next; priv->lec_arp_empty_ones = entry->next;
spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
/* We might have got an entry */ /* We might have got an entry */
if ((prev=lec_arp_find(priv,src))) { if ((prev = lec_arp_find(priv,src))) {
lec_arp_remove(priv, prev); lec_arp_remove(priv, prev);
kfree(prev); kfree(prev);
} }
lec_arp_add(priv, entry); lec_arp_add(priv, entry);
lec_arp_put(priv); goto out;
return;
} }
spin_lock_irqsave(&priv->lec_arp_lock, flags);
prev = entry; prev = entry;
entry = entry->next; entry = entry->next;
while (entry && entry->vcc != vcc) { while (entry && entry->vcc != vcc) {
...@@ -2514,21 +2508,19 @@ lec_arp_check_empties(struct lec_priv *priv, ...@@ -2514,21 +2508,19 @@ lec_arp_check_empties(struct lec_priv *priv,
} }
if (!entry) { if (!entry) {
DPRINTK("LEC_ARP: Arp_check_empties: entry not found!\n"); DPRINTK("LEC_ARP: Arp_check_empties: entry not found!\n");
lec_arp_put(priv); goto out;
spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
return;
} }
del_timer(&entry->timer); del_timer(&entry->timer);
memcpy(entry->mac_addr, src, ETH_ALEN); memcpy(entry->mac_addr, src, ETH_ALEN);
entry->status = ESI_FORWARD_DIRECT; entry->status = ESI_FORWARD_DIRECT;
entry->last_used = jiffies; entry->last_used = jiffies;
prev->next = entry->next; prev->next = entry->next;
spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
if ((prev = lec_arp_find(priv, src))) { if ((prev = lec_arp_find(priv, src))) {
lec_arp_remove(priv, prev); lec_arp_remove(priv, prev);
kfree(prev); kfree(prev);
} }
lec_arp_add(priv, entry); lec_arp_add(priv, entry);
lec_arp_put(priv); out:
spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
} }
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -95,7 +95,6 @@ struct lec_priv { ...@@ -95,7 +95,6 @@ struct lec_priv {
establishes multiple Multicast Forward VCCs to us. This list establishes multiple Multicast Forward VCCs to us. This list
collects all those VCCs. LANEv1 client has only one item in this collects all those VCCs. LANEv1 client has only one item in this
list. These entries are not aged out. */ list. These entries are not aged out. */
atomic_t lec_arp_users;
spinlock_t lec_arp_lock; spinlock_t lec_arp_lock;
struct atm_vcc *mcast_vcc; /* Default Multicast Send VCC */ struct atm_vcc *mcast_vcc; /* Default Multicast Send VCC */
struct atm_vcc *lecd; struct atm_vcc *lecd;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment