aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorChas Williams <chas@cmf.nrl.navy.mil>2006-09-29 20:17:17 -0400
committerDavid S. Miller <davem@davemloft.net>2006-09-29 20:17:17 -0400
commit6656e3c4c8e0c80f2d2bfece574876d269f64861 (patch)
treeb4470a2f0ffd372eb3886a6e344cd336ec430d03 /net
parent33a9c2d4b758279c5077fc15d221b385a574ae0b (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')
-rw-r--r--net/atm/lec.c32
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
431out:
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;
1894restart:
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);
2346restart:
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 }