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

[ATM]: [lec] use refcnt to protect lec_arp_entries outside lock

Signed-off-by: default avatarChas Williams <chas@cmf.nrl.navy.mil>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 33a9c2d4
...@@ -396,7 +396,7 @@ static int lec_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -396,7 +396,7 @@ static int lec_start_xmit(struct sk_buff *skb, struct net_device *dev)
priv->stats.tx_dropped++; priv->stats.tx_dropped++;
dev_kfree_skb(skb); dev_kfree_skb(skb);
} }
return 0; goto out;
} }
#if DUMP_PACKETS > 0 #if DUMP_PACKETS > 0
printk("%s:sending to vpi:%d vci:%d\n", dev->name, vcc->vpi, vcc->vci); printk("%s:sending to vpi:%d vci:%d\n", dev->name, vcc->vpi, vcc->vci);
...@@ -428,6 +428,9 @@ static int lec_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -428,6 +428,9 @@ static int lec_start_xmit(struct sk_buff *skb, struct net_device *dev)
netif_wake_queue(dev); netif_wake_queue(dev);
} }
out:
if (entry)
lec_arp_put(entry);
dev->trans_start = jiffies; dev->trans_start = jiffies;
return 0; return 0;
} }
...@@ -1888,6 +1891,7 @@ static void lec_arp_check_expire(void *data) ...@@ -1888,6 +1891,7 @@ static void lec_arp_check_expire(void *data)
DPRINTK("lec_arp_check_expire %p\n", priv); DPRINTK("lec_arp_check_expire %p\n", priv);
now = jiffies; now = jiffies;
restart:
spin_lock_irqsave(&priv->lec_arp_lock, flags); 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++) {
hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_tables[i], next) { hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_tables[i], next) {
...@@ -1927,14 +1931,16 @@ static void lec_arp_check_expire(void *data) ...@@ -1927,14 +1931,16 @@ static void lec_arp_check_expire(void *data)
time_after_eq(now, entry->timestamp + time_after_eq(now, entry->timestamp +
priv->path_switching_delay)) { priv->path_switching_delay)) {
struct sk_buff *skb; struct sk_buff *skb;
struct atm_vcc *vcc = entry->vcc;
while ((skb = lec_arp_hold(entry);
skb_dequeue(&entry->tx_wait)) != spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
NULL) while ((skb = skb_dequeue(&entry->tx_wait)) != NULL)
lec_send(entry->vcc, skb, lec_send(vcc, skb, entry->priv);
entry->priv);
entry->last_used = jiffies; entry->last_used = jiffies;
entry->status = ESI_FORWARD_DIRECT; entry->status = ESI_FORWARD_DIRECT;
lec_arp_put(entry);
goto restart;
} }
} }
} }
...@@ -1977,6 +1983,7 @@ static struct atm_vcc *lec_arp_resolve(struct lec_priv *priv, ...@@ -1977,6 +1983,7 @@ static struct atm_vcc *lec_arp_resolve(struct lec_priv *priv,
if (entry->status == ESI_FORWARD_DIRECT) { if (entry->status == ESI_FORWARD_DIRECT) {
/* Connection Ok */ /* Connection Ok */
entry->last_used = jiffies; entry->last_used = jiffies;
lec_arp_hold(entry);
*ret_entry = entry; *ret_entry = entry;
found = entry->vcc; found = entry->vcc;
goto out; goto out;
...@@ -2007,6 +2014,7 @@ static struct atm_vcc *lec_arp_resolve(struct lec_priv *priv, ...@@ -2007,6 +2014,7 @@ static struct atm_vcc *lec_arp_resolve(struct lec_priv *priv,
* or BUS flood limit was reached for an entry which is * or BUS flood limit was reached for an entry which is
* in ESI_ARP_PENDING or ESI_VC_PENDING state. * in ESI_ARP_PENDING or ESI_VC_PENDING state.
*/ */
lec_arp_hold(entry);
*ret_entry = entry; *ret_entry = entry;
DPRINTK("lec: entry->status %d entry->vcc %p\n", entry->status, DPRINTK("lec: entry->status %d entry->vcc %p\n", entry->status,
entry->vcc); entry->vcc);
...@@ -2335,18 +2343,24 @@ static void lec_flush_complete(struct lec_priv *priv, unsigned long tran_id) ...@@ -2335,18 +2343,24 @@ static void lec_flush_complete(struct lec_priv *priv, unsigned long tran_id)
int i; int i;
DPRINTK("LEC:lec_flush_complete %lx\n", tran_id); DPRINTK("LEC:lec_flush_complete %lx\n", tran_id);
restart:
spin_lock_irqsave(&priv->lec_arp_lock, flags); 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++) {
hlist_for_each_entry(entry, node, &priv->lec_arp_tables[i], next) { hlist_for_each_entry(entry, node, &priv->lec_arp_tables[i], 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;
struct atm_vcc *vcc = entry->vcc;
while ((skb = lec_arp_hold(entry);
skb_dequeue(&entry->tx_wait)) != NULL) spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
lec_send(entry->vcc, skb, entry->priv); while ((skb = skb_dequeue(&entry->tx_wait)) != NULL)
lec_send(vcc, skb, entry->priv);
entry->last_used = jiffies;
entry->status = ESI_FORWARD_DIRECT; entry->status = ESI_FORWARD_DIRECT;
lec_arp_put(entry);
DPRINTK("LEC_ARP: Flushed\n"); DPRINTK("LEC_ARP: Flushed\n");
goto restart;
} }
} }
} }
......
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