diff options
| -rw-r--r-- | net/atm/lec.c | 42 | ||||
| -rw-r--r-- | net/atm/lec_arpc.h | 1 |
2 files changed, 29 insertions, 14 deletions
diff --git a/net/atm/lec.c b/net/atm/lec.c index 29acfb0e6d04..c5d1f9e9a647 100644 --- a/net/atm/lec.c +++ b/net/atm/lec.c | |||
| @@ -107,6 +107,19 @@ static void lec_vcc_added(struct lec_priv *priv, struct atmlec_ioc *ioc_data, | |||
| 107 | struct sk_buff *skb)); | 107 | struct sk_buff *skb)); |
| 108 | static void lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc); | 108 | static void lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc); |
| 109 | 109 | ||
| 110 | /* must be done under lec_arp_lock */ | ||
| 111 | static inline void lec_arp_hold(struct lec_arp_table *entry) | ||
| 112 | { | ||
| 113 | atomic_inc(&entry->usage); | ||
| 114 | } | ||
| 115 | |||
| 116 | static inline void lec_arp_put(struct lec_arp_table *entry) | ||
| 117 | { | ||
| 118 | if (atomic_dec_and_test(&entry->usage)) | ||
| 119 | kfree(entry); | ||
| 120 | } | ||
| 121 | |||
| 122 | |||
| 110 | static struct lane2_ops lane2_ops = { | 123 | static struct lane2_ops lane2_ops = { |
| 111 | lane2_resolve, /* resolve, spec 3.1.3 */ | 124 | lane2_resolve, /* resolve, spec 3.1.3 */ |
| 112 | lane2_associate_req, /* associate_req, spec 3.1.4 */ | 125 | lane2_associate_req, /* associate_req, spec 3.1.4 */ |
| @@ -795,7 +808,7 @@ static void lec_push(struct atm_vcc *vcc, struct sk_buff *skb) | |||
| 795 | entry = lec_arp_find(priv, src); | 808 | entry = lec_arp_find(priv, src); |
| 796 | if (entry && entry->vcc != vcc) { | 809 | if (entry && entry->vcc != vcc) { |
| 797 | lec_arp_remove(priv, entry); | 810 | lec_arp_remove(priv, entry); |
| 798 | kfree(entry); | 811 | lec_arp_put(entry); |
| 799 | } | 812 | } |
| 800 | } | 813 | } |
| 801 | spin_unlock_irqrestore(&priv->lec_arp_lock, flags); | 814 | spin_unlock_irqrestore(&priv->lec_arp_lock, flags); |
| @@ -1726,7 +1739,7 @@ static void lec_arp_destroy(struct lec_priv *priv) | |||
| 1726 | for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { | 1739 | for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { |
| 1727 | hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_tables[i], next) { | 1740 | hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_tables[i], next) { |
| 1728 | lec_arp_remove(priv, entry); | 1741 | lec_arp_remove(priv, entry); |
| 1729 | kfree(entry); | 1742 | lec_arp_put(entry); |
| 1730 | } | 1743 | } |
| 1731 | INIT_HLIST_HEAD(&priv->lec_arp_tables[i]); | 1744 | INIT_HLIST_HEAD(&priv->lec_arp_tables[i]); |
| 1732 | } | 1745 | } |
| @@ -1735,7 +1748,7 @@ static void lec_arp_destroy(struct lec_priv *priv) | |||
| 1735 | del_timer_sync(&entry->timer); | 1748 | del_timer_sync(&entry->timer); |
| 1736 | lec_arp_clear_vccs(entry); | 1749 | lec_arp_clear_vccs(entry); |
| 1737 | hlist_del(&entry->next); | 1750 | hlist_del(&entry->next); |
| 1738 | kfree(entry); | 1751 | lec_arp_put(entry); |
| 1739 | } | 1752 | } |
| 1740 | INIT_HLIST_HEAD(&priv->lec_arp_empty_ones); | 1753 | INIT_HLIST_HEAD(&priv->lec_arp_empty_ones); |
| 1741 | 1754 | ||
| @@ -1743,7 +1756,7 @@ static void lec_arp_destroy(struct lec_priv *priv) | |||
| 1743 | del_timer_sync(&entry->timer); | 1756 | del_timer_sync(&entry->timer); |
| 1744 | lec_arp_clear_vccs(entry); | 1757 | lec_arp_clear_vccs(entry); |
| 1745 | hlist_del(&entry->next); | 1758 | hlist_del(&entry->next); |
| 1746 | kfree(entry); | 1759 | lec_arp_put(entry); |
| 1747 | } | 1760 | } |
| 1748 | INIT_HLIST_HEAD(&priv->lec_no_forward); | 1761 | INIT_HLIST_HEAD(&priv->lec_no_forward); |
| 1749 | 1762 | ||
| @@ -1751,7 +1764,7 @@ static void lec_arp_destroy(struct lec_priv *priv) | |||
| 1751 | /* No timer, LANEv2 7.1.20 and 2.3.5.3 */ | 1764 | /* No timer, LANEv2 7.1.20 and 2.3.5.3 */ |
| 1752 | lec_arp_clear_vccs(entry); | 1765 | lec_arp_clear_vccs(entry); |
| 1753 | hlist_del(&entry->next); | 1766 | hlist_del(&entry->next); |
| 1754 | kfree(entry); | 1767 | lec_arp_put(entry); |
| 1755 | } | 1768 | } |
| 1756 | INIT_HLIST_HEAD(&priv->mcast_fwds); | 1769 | INIT_HLIST_HEAD(&priv->mcast_fwds); |
| 1757 | priv->mcast_vcc = NULL; | 1770 | priv->mcast_vcc = NULL; |
| @@ -1799,6 +1812,7 @@ static struct lec_arp_table *make_entry(struct lec_priv *priv, | |||
| 1799 | to_return->last_used = jiffies; | 1812 | to_return->last_used = jiffies; |
| 1800 | to_return->priv = priv; | 1813 | to_return->priv = priv; |
| 1801 | skb_queue_head_init(&to_return->tx_wait); | 1814 | skb_queue_head_init(&to_return->tx_wait); |
| 1815 | atomic_set(&to_return->usage, 1); | ||
| 1802 | return to_return; | 1816 | return to_return; |
| 1803 | } | 1817 | } |
| 1804 | 1818 | ||
| @@ -1843,7 +1857,7 @@ static void lec_arp_expire_vcc(unsigned long data) | |||
| 1843 | spin_unlock_irqrestore(&priv->lec_arp_lock, flags); | 1857 | spin_unlock_irqrestore(&priv->lec_arp_lock, flags); |
| 1844 | 1858 | ||
| 1845 | lec_arp_clear_vccs(to_remove); | 1859 | lec_arp_clear_vccs(to_remove); |
| 1846 | kfree(to_remove); | 1860 | lec_arp_put(to_remove); |
| 1847 | } | 1861 | } |
| 1848 | 1862 | ||
| 1849 | /* | 1863 | /* |
| @@ -1891,7 +1905,7 @@ static void lec_arp_check_expire(void *data) | |||
| 1891 | /* Remove entry */ | 1905 | /* Remove entry */ |
| 1892 | DPRINTK("LEC:Entry timed out\n"); | 1906 | DPRINTK("LEC:Entry timed out\n"); |
| 1893 | lec_arp_remove(priv, entry); | 1907 | lec_arp_remove(priv, entry); |
| 1894 | kfree(entry); | 1908 | lec_arp_put(entry); |
| 1895 | } else { | 1909 | } else { |
| 1896 | /* Something else */ | 1910 | /* Something else */ |
| 1897 | if ((entry->status == ESI_VC_PENDING || | 1911 | if ((entry->status == ESI_VC_PENDING || |
| @@ -2045,7 +2059,7 @@ lec_addr_delete(struct lec_priv *priv, unsigned char *atm_addr, | |||
| 2045 | && (permanent || | 2059 | && (permanent || |
| 2046 | !(entry->flags & LEC_PERMANENT_FLAG))) { | 2060 | !(entry->flags & LEC_PERMANENT_FLAG))) { |
| 2047 | lec_arp_remove(priv, entry); | 2061 | lec_arp_remove(priv, entry); |
| 2048 | kfree(entry); | 2062 | lec_arp_put(entry); |
| 2049 | } | 2063 | } |
| 2050 | spin_unlock_irqrestore(&priv->lec_arp_lock, flags); | 2064 | spin_unlock_irqrestore(&priv->lec_arp_lock, flags); |
| 2051 | return 0; | 2065 | return 0; |
| @@ -2094,7 +2108,7 @@ lec_arp_update(struct lec_priv *priv, unsigned char *mac_addr, | |||
| 2094 | tmp->old_push = entry->old_push; | 2108 | tmp->old_push = entry->old_push; |
| 2095 | tmp->last_used = jiffies; | 2109 | tmp->last_used = jiffies; |
| 2096 | del_timer(&entry->timer); | 2110 | del_timer(&entry->timer); |
| 2097 | kfree(entry); | 2111 | lec_arp_put(entry); |
| 2098 | entry = tmp; | 2112 | entry = tmp; |
| 2099 | } else { | 2113 | } else { |
| 2100 | entry->status = ESI_FORWARD_DIRECT; | 2114 | entry->status = ESI_FORWARD_DIRECT; |
| @@ -2414,7 +2428,7 @@ static void lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc) | |||
| 2414 | hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_tables[i], next) { | 2428 | hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_tables[i], next) { |
| 2415 | if (vcc == entry->vcc) { | 2429 | if (vcc == entry->vcc) { |
| 2416 | lec_arp_remove(priv, entry); | 2430 | lec_arp_remove(priv, entry); |
| 2417 | kfree(entry); | 2431 | lec_arp_put(entry); |
| 2418 | if (priv->mcast_vcc == vcc) { | 2432 | if (priv->mcast_vcc == vcc) { |
| 2419 | priv->mcast_vcc = NULL; | 2433 | priv->mcast_vcc = NULL; |
| 2420 | } | 2434 | } |
| @@ -2427,7 +2441,7 @@ static void lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc) | |||
| 2427 | lec_arp_clear_vccs(entry); | 2441 | lec_arp_clear_vccs(entry); |
| 2428 | del_timer(&entry->timer); | 2442 | del_timer(&entry->timer); |
| 2429 | hlist_del(&entry->next); | 2443 | hlist_del(&entry->next); |
| 2430 | kfree(entry); | 2444 | lec_arp_put(entry); |
| 2431 | } | 2445 | } |
| 2432 | } | 2446 | } |
| 2433 | 2447 | ||
| @@ -2436,7 +2450,7 @@ static void lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc) | |||
| 2436 | lec_arp_clear_vccs(entry); | 2450 | lec_arp_clear_vccs(entry); |
| 2437 | del_timer(&entry->timer); | 2451 | del_timer(&entry->timer); |
| 2438 | hlist_del(&entry->next); | 2452 | hlist_del(&entry->next); |
| 2439 | kfree(entry); | 2453 | lec_arp_put(entry); |
| 2440 | } | 2454 | } |
| 2441 | } | 2455 | } |
| 2442 | 2456 | ||
| @@ -2445,7 +2459,7 @@ static void lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc) | |||
| 2445 | lec_arp_clear_vccs(entry); | 2459 | lec_arp_clear_vccs(entry); |
| 2446 | /* No timer, LANEv2 7.1.20 and 2.3.5.3 */ | 2460 | /* No timer, LANEv2 7.1.20 and 2.3.5.3 */ |
| 2447 | hlist_del(&entry->next); | 2461 | hlist_del(&entry->next); |
| 2448 | kfree(entry); | 2462 | lec_arp_put(entry); |
| 2449 | } | 2463 | } |
| 2450 | } | 2464 | } |
| 2451 | 2465 | ||
| @@ -2481,7 +2495,7 @@ lec_arp_check_empties(struct lec_priv *priv, | |||
| 2481 | /* We might have got an entry */ | 2495 | /* We might have got an entry */ |
| 2482 | if ((tmp = lec_arp_find(priv, src))) { | 2496 | if ((tmp = lec_arp_find(priv, src))) { |
| 2483 | lec_arp_remove(priv, tmp); | 2497 | lec_arp_remove(priv, tmp); |
| 2484 | kfree(tmp); | 2498 | lec_arp_put(tmp); |
| 2485 | } | 2499 | } |
| 2486 | hlist_del(&entry->next); | 2500 | hlist_del(&entry->next); |
| 2487 | lec_arp_add(priv, entry); | 2501 | lec_arp_add(priv, entry); |
diff --git a/net/atm/lec_arpc.h b/net/atm/lec_arpc.h index 125df36d33b8..ec67435a40a6 100644 --- a/net/atm/lec_arpc.h +++ b/net/atm/lec_arpc.h | |||
| @@ -47,6 +47,7 @@ struct lec_arp_table { | |||
| 47 | * the length of the tlvs array | 47 | * the length of the tlvs array |
| 48 | */ | 48 | */ |
| 49 | struct sk_buff_head tx_wait; /* wait queue for outgoing packets */ | 49 | struct sk_buff_head tx_wait; /* wait queue for outgoing packets */ |
| 50 | atomic_t usage; /* usage count */ | ||
| 50 | }; | 51 | }; |
| 51 | 52 | ||
| 52 | /* | 53 | /* |
