mirror of
https://github.com/adulau/aha.git
synced 2024-12-28 03:36:19 +00:00
[ATM]: [lec] add reference counting to lec_arp entries
Signed-off-by: Chas Williams <chas@cmf.nrl.navy.mil> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
987e46bdf3
commit
33a9c2d4b7
2 changed files with 29 additions and 14 deletions
|
@ -107,6 +107,19 @@ static void lec_vcc_added(struct lec_priv *priv, struct atmlec_ioc *ioc_data,
|
||||||
struct sk_buff *skb));
|
struct sk_buff *skb));
|
||||||
static void lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc);
|
static void lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc);
|
||||||
|
|
||||||
|
/* must be done under lec_arp_lock */
|
||||||
|
static inline void lec_arp_hold(struct lec_arp_table *entry)
|
||||||
|
{
|
||||||
|
atomic_inc(&entry->usage);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void lec_arp_put(struct lec_arp_table *entry)
|
||||||
|
{
|
||||||
|
if (atomic_dec_and_test(&entry->usage))
|
||||||
|
kfree(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static struct lane2_ops lane2_ops = {
|
static struct lane2_ops lane2_ops = {
|
||||||
lane2_resolve, /* resolve, spec 3.1.3 */
|
lane2_resolve, /* resolve, spec 3.1.3 */
|
||||||
lane2_associate_req, /* associate_req, spec 3.1.4 */
|
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)
|
||||||
entry = lec_arp_find(priv, src);
|
entry = lec_arp_find(priv, src);
|
||||||
if (entry && entry->vcc != vcc) {
|
if (entry && entry->vcc != vcc) {
|
||||||
lec_arp_remove(priv, entry);
|
lec_arp_remove(priv, entry);
|
||||||
kfree(entry);
|
lec_arp_put(entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
|
spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
|
||||||
|
@ -1726,7 +1739,7 @@ static void lec_arp_destroy(struct lec_priv *priv)
|
||||||
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) {
|
||||||
lec_arp_remove(priv, entry);
|
lec_arp_remove(priv, entry);
|
||||||
kfree(entry);
|
lec_arp_put(entry);
|
||||||
}
|
}
|
||||||
INIT_HLIST_HEAD(&priv->lec_arp_tables[i]);
|
INIT_HLIST_HEAD(&priv->lec_arp_tables[i]);
|
||||||
}
|
}
|
||||||
|
@ -1735,7 +1748,7 @@ static void lec_arp_destroy(struct lec_priv *priv)
|
||||||
del_timer_sync(&entry->timer);
|
del_timer_sync(&entry->timer);
|
||||||
lec_arp_clear_vccs(entry);
|
lec_arp_clear_vccs(entry);
|
||||||
hlist_del(&entry->next);
|
hlist_del(&entry->next);
|
||||||
kfree(entry);
|
lec_arp_put(entry);
|
||||||
}
|
}
|
||||||
INIT_HLIST_HEAD(&priv->lec_arp_empty_ones);
|
INIT_HLIST_HEAD(&priv->lec_arp_empty_ones);
|
||||||
|
|
||||||
|
@ -1743,7 +1756,7 @@ static void lec_arp_destroy(struct lec_priv *priv)
|
||||||
del_timer_sync(&entry->timer);
|
del_timer_sync(&entry->timer);
|
||||||
lec_arp_clear_vccs(entry);
|
lec_arp_clear_vccs(entry);
|
||||||
hlist_del(&entry->next);
|
hlist_del(&entry->next);
|
||||||
kfree(entry);
|
lec_arp_put(entry);
|
||||||
}
|
}
|
||||||
INIT_HLIST_HEAD(&priv->lec_no_forward);
|
INIT_HLIST_HEAD(&priv->lec_no_forward);
|
||||||
|
|
||||||
|
@ -1751,7 +1764,7 @@ static void lec_arp_destroy(struct lec_priv *priv)
|
||||||
/* No timer, LANEv2 7.1.20 and 2.3.5.3 */
|
/* No timer, LANEv2 7.1.20 and 2.3.5.3 */
|
||||||
lec_arp_clear_vccs(entry);
|
lec_arp_clear_vccs(entry);
|
||||||
hlist_del(&entry->next);
|
hlist_del(&entry->next);
|
||||||
kfree(entry);
|
lec_arp_put(entry);
|
||||||
}
|
}
|
||||||
INIT_HLIST_HEAD(&priv->mcast_fwds);
|
INIT_HLIST_HEAD(&priv->mcast_fwds);
|
||||||
priv->mcast_vcc = NULL;
|
priv->mcast_vcc = NULL;
|
||||||
|
@ -1799,6 +1812,7 @@ static struct lec_arp_table *make_entry(struct lec_priv *priv,
|
||||||
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);
|
||||||
|
atomic_set(&to_return->usage, 1);
|
||||||
return to_return;
|
return to_return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1843,7 +1857,7 @@ static void lec_arp_expire_vcc(unsigned long data)
|
||||||
spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
|
spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
|
||||||
|
|
||||||
lec_arp_clear_vccs(to_remove);
|
lec_arp_clear_vccs(to_remove);
|
||||||
kfree(to_remove);
|
lec_arp_put(to_remove);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1891,7 +1905,7 @@ static void lec_arp_check_expire(void *data)
|
||||||
/* Remove entry */
|
/* Remove entry */
|
||||||
DPRINTK("LEC:Entry timed out\n");
|
DPRINTK("LEC:Entry timed out\n");
|
||||||
lec_arp_remove(priv, entry);
|
lec_arp_remove(priv, entry);
|
||||||
kfree(entry);
|
lec_arp_put(entry);
|
||||||
} else {
|
} else {
|
||||||
/* Something else */
|
/* Something else */
|
||||||
if ((entry->status == ESI_VC_PENDING ||
|
if ((entry->status == ESI_VC_PENDING ||
|
||||||
|
@ -2045,7 +2059,7 @@ lec_addr_delete(struct lec_priv *priv, unsigned char *atm_addr,
|
||||||
&& (permanent ||
|
&& (permanent ||
|
||||||
!(entry->flags & LEC_PERMANENT_FLAG))) {
|
!(entry->flags & LEC_PERMANENT_FLAG))) {
|
||||||
lec_arp_remove(priv, entry);
|
lec_arp_remove(priv, entry);
|
||||||
kfree(entry);
|
lec_arp_put(entry);
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
|
spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2094,7 +2108,7 @@ lec_arp_update(struct lec_priv *priv, unsigned char *mac_addr,
|
||||||
tmp->old_push = entry->old_push;
|
tmp->old_push = entry->old_push;
|
||||||
tmp->last_used = jiffies;
|
tmp->last_used = jiffies;
|
||||||
del_timer(&entry->timer);
|
del_timer(&entry->timer);
|
||||||
kfree(entry);
|
lec_arp_put(entry);
|
||||||
entry = tmp;
|
entry = tmp;
|
||||||
} else {
|
} else {
|
||||||
entry->status = ESI_FORWARD_DIRECT;
|
entry->status = ESI_FORWARD_DIRECT;
|
||||||
|
@ -2414,7 +2428,7 @@ static void lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc)
|
||||||
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) {
|
||||||
if (vcc == entry->vcc) {
|
if (vcc == entry->vcc) {
|
||||||
lec_arp_remove(priv, entry);
|
lec_arp_remove(priv, entry);
|
||||||
kfree(entry);
|
lec_arp_put(entry);
|
||||||
if (priv->mcast_vcc == vcc) {
|
if (priv->mcast_vcc == vcc) {
|
||||||
priv->mcast_vcc = NULL;
|
priv->mcast_vcc = NULL;
|
||||||
}
|
}
|
||||||
|
@ -2427,7 +2441,7 @@ static void lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc)
|
||||||
lec_arp_clear_vccs(entry);
|
lec_arp_clear_vccs(entry);
|
||||||
del_timer(&entry->timer);
|
del_timer(&entry->timer);
|
||||||
hlist_del(&entry->next);
|
hlist_del(&entry->next);
|
||||||
kfree(entry);
|
lec_arp_put(entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2436,7 +2450,7 @@ static void lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc)
|
||||||
lec_arp_clear_vccs(entry);
|
lec_arp_clear_vccs(entry);
|
||||||
del_timer(&entry->timer);
|
del_timer(&entry->timer);
|
||||||
hlist_del(&entry->next);
|
hlist_del(&entry->next);
|
||||||
kfree(entry);
|
lec_arp_put(entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2445,7 +2459,7 @@ static void lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc)
|
||||||
lec_arp_clear_vccs(entry);
|
lec_arp_clear_vccs(entry);
|
||||||
/* No timer, LANEv2 7.1.20 and 2.3.5.3 */
|
/* No timer, LANEv2 7.1.20 and 2.3.5.3 */
|
||||||
hlist_del(&entry->next);
|
hlist_del(&entry->next);
|
||||||
kfree(entry);
|
lec_arp_put(entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2481,7 +2495,7 @@ lec_arp_check_empties(struct lec_priv *priv,
|
||||||
/* We might have got an entry */
|
/* We might have got an entry */
|
||||||
if ((tmp = lec_arp_find(priv, src))) {
|
if ((tmp = lec_arp_find(priv, src))) {
|
||||||
lec_arp_remove(priv, tmp);
|
lec_arp_remove(priv, tmp);
|
||||||
kfree(tmp);
|
lec_arp_put(tmp);
|
||||||
}
|
}
|
||||||
hlist_del(&entry->next);
|
hlist_del(&entry->next);
|
||||||
lec_arp_add(priv, entry);
|
lec_arp_add(priv, entry);
|
||||||
|
|
|
@ -47,6 +47,7 @@ struct lec_arp_table {
|
||||||
* the length of the tlvs array
|
* the length of the tlvs array
|
||||||
*/
|
*/
|
||||||
struct sk_buff_head tx_wait; /* wait queue for outgoing packets */
|
struct sk_buff_head tx_wait; /* wait queue for outgoing packets */
|
||||||
|
atomic_t usage; /* usage count */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in a new issue