diff options
author | Chas Williams <chas@cmf.nrl.navy.mil> | 2006-09-29 20:17:17 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2006-09-29 20:17:17 -0400 |
commit | 6656e3c4c8e0c80f2d2bfece574876d269f64861 (patch) | |
tree | b4470a2f0ffd372eb3886a6e344cd336ec430d03 /net/atm | |
parent | 33a9c2d4b758279c5077fc15d221b385a574ae0b (diff) |
[ATM]: [lec] use refcnt to protect lec_arp_entries outside lock
Signed-off-by: Chas Williams <chas@cmf.nrl.navy.mil>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/atm')
-rw-r--r-- | net/atm/lec.c | 32 |
1 files changed, 23 insertions, 9 deletions
diff --git a/net/atm/lec.c b/net/atm/lec.c index c5d1f9e9a647..66c57c1091a8 100644 --- a/net/atm/lec.c +++ b/net/atm/lec.c | |||
@@ -396,7 +396,7 @@ static int lec_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
396 | priv->stats.tx_dropped++; | 396 | priv->stats.tx_dropped++; |
397 | dev_kfree_skb(skb); | 397 | dev_kfree_skb(skb); |
398 | } | 398 | } |
399 | return 0; | 399 | goto out; |
400 | } | 400 | } |
401 | #if DUMP_PACKETS > 0 | 401 | #if DUMP_PACKETS > 0 |
402 | printk("%s:sending to vpi:%d vci:%d\n", dev->name, vcc->vpi, vcc->vci); | 402 | 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 | netif_wake_queue(dev); | 428 | netif_wake_queue(dev); |
429 | } | 429 | } |
430 | 430 | ||
431 | out: | ||
432 | if (entry) | ||
433 | lec_arp_put(entry); | ||
431 | dev->trans_start = jiffies; | 434 | dev->trans_start = jiffies; |
432 | return 0; | 435 | return 0; |
433 | } | 436 | } |
@@ -1888,6 +1891,7 @@ static void lec_arp_check_expire(void *data) | |||
1888 | 1891 | ||
1889 | DPRINTK("lec_arp_check_expire %p\n", priv); | 1892 | DPRINTK("lec_arp_check_expire %p\n", priv); |
1890 | now = jiffies; | 1893 | now = jiffies; |
1894 | restart: | ||
1891 | spin_lock_irqsave(&priv->lec_arp_lock, flags); | 1895 | spin_lock_irqsave(&priv->lec_arp_lock, flags); |
1892 | for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { | 1896 | for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { |
1893 | hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_tables[i], next) { | 1897 | 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 | time_after_eq(now, entry->timestamp + | 1931 | time_after_eq(now, entry->timestamp + |
1928 | priv->path_switching_delay)) { | 1932 | priv->path_switching_delay)) { |
1929 | struct sk_buff *skb; | 1933 | struct sk_buff *skb; |
1934 | struct atm_vcc *vcc = entry->vcc; | ||
1930 | 1935 | ||
1931 | while ((skb = | 1936 | lec_arp_hold(entry); |
1932 | skb_dequeue(&entry->tx_wait)) != | 1937 | spin_unlock_irqrestore(&priv->lec_arp_lock, flags); |
1933 | NULL) | 1938 | while ((skb = skb_dequeue(&entry->tx_wait)) != NULL) |
1934 | lec_send(entry->vcc, skb, | 1939 | lec_send(vcc, skb, entry->priv); |
1935 | entry->priv); | ||
1936 | entry->last_used = jiffies; | 1940 | entry->last_used = jiffies; |
1937 | entry->status = ESI_FORWARD_DIRECT; | 1941 | entry->status = ESI_FORWARD_DIRECT; |
1942 | lec_arp_put(entry); | ||
1943 | goto restart; | ||
1938 | } | 1944 | } |
1939 | } | 1945 | } |
1940 | } | 1946 | } |
@@ -1977,6 +1983,7 @@ static struct atm_vcc *lec_arp_resolve(struct lec_priv *priv, | |||
1977 | if (entry->status == ESI_FORWARD_DIRECT) { | 1983 | if (entry->status == ESI_FORWARD_DIRECT) { |
1978 | /* Connection Ok */ | 1984 | /* Connection Ok */ |
1979 | entry->last_used = jiffies; | 1985 | entry->last_used = jiffies; |
1986 | lec_arp_hold(entry); | ||
1980 | *ret_entry = entry; | 1987 | *ret_entry = entry; |
1981 | found = entry->vcc; | 1988 | found = entry->vcc; |
1982 | goto out; | 1989 | goto out; |
@@ -2007,6 +2014,7 @@ static struct atm_vcc *lec_arp_resolve(struct lec_priv *priv, | |||
2007 | * or BUS flood limit was reached for an entry which is | 2014 | * or BUS flood limit was reached for an entry which is |
2008 | * in ESI_ARP_PENDING or ESI_VC_PENDING state. | 2015 | * in ESI_ARP_PENDING or ESI_VC_PENDING state. |
2009 | */ | 2016 | */ |
2017 | lec_arp_hold(entry); | ||
2010 | *ret_entry = entry; | 2018 | *ret_entry = entry; |
2011 | DPRINTK("lec: entry->status %d entry->vcc %p\n", entry->status, | 2019 | DPRINTK("lec: entry->status %d entry->vcc %p\n", entry->status, |
2012 | entry->vcc); | 2020 | entry->vcc); |
@@ -2335,18 +2343,24 @@ static void lec_flush_complete(struct lec_priv *priv, unsigned long tran_id) | |||
2335 | int i; | 2343 | int i; |
2336 | 2344 | ||
2337 | DPRINTK("LEC:lec_flush_complete %lx\n", tran_id); | 2345 | DPRINTK("LEC:lec_flush_complete %lx\n", tran_id); |
2346 | restart: | ||
2338 | spin_lock_irqsave(&priv->lec_arp_lock, flags); | 2347 | spin_lock_irqsave(&priv->lec_arp_lock, flags); |
2339 | for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { | 2348 | for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { |
2340 | hlist_for_each_entry(entry, node, &priv->lec_arp_tables[i], next) { | 2349 | hlist_for_each_entry(entry, node, &priv->lec_arp_tables[i], next) { |
2341 | if (entry->flush_tran_id == tran_id | 2350 | if (entry->flush_tran_id == tran_id |
2342 | && entry->status == ESI_FLUSH_PENDING) { | 2351 | && entry->status == ESI_FLUSH_PENDING) { |
2343 | struct sk_buff *skb; | 2352 | struct sk_buff *skb; |
2353 | struct atm_vcc *vcc = entry->vcc; | ||
2344 | 2354 | ||
2345 | while ((skb = | 2355 | lec_arp_hold(entry); |
2346 | skb_dequeue(&entry->tx_wait)) != NULL) | 2356 | spin_unlock_irqrestore(&priv->lec_arp_lock, flags); |
2347 | lec_send(entry->vcc, skb, entry->priv); | 2357 | while ((skb = skb_dequeue(&entry->tx_wait)) != NULL) |
2358 | lec_send(vcc, skb, entry->priv); | ||
2359 | entry->last_used = jiffies; | ||
2348 | entry->status = ESI_FORWARD_DIRECT; | 2360 | entry->status = ESI_FORWARD_DIRECT; |
2361 | lec_arp_put(entry); | ||
2349 | DPRINTK("LEC_ARP: Flushed\n"); | 2362 | DPRINTK("LEC_ARP: Flushed\n"); |
2363 | goto restart; | ||
2350 | } | 2364 | } |
2351 | } | 2365 | } |
2352 | } | 2366 | } |