struct sk_buff *skb));
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 = {
lane2_resolve, /* resolve, spec 3.1.3 */
lane2_associate_req, /* associate_req, spec 3.1.4 */
entry = lec_arp_find(priv, src);
if (entry && entry->vcc != vcc) {
lec_arp_remove(priv, entry);
- kfree(entry);
+ lec_arp_put(entry);
}
}
spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_tables[i], next) {
lec_arp_remove(priv, entry);
- kfree(entry);
+ lec_arp_put(entry);
}
INIT_HLIST_HEAD(&priv->lec_arp_tables[i]);
}
del_timer_sync(&entry->timer);
lec_arp_clear_vccs(entry);
hlist_del(&entry->next);
- kfree(entry);
+ lec_arp_put(entry);
}
INIT_HLIST_HEAD(&priv->lec_arp_empty_ones);
del_timer_sync(&entry->timer);
lec_arp_clear_vccs(entry);
hlist_del(&entry->next);
- kfree(entry);
+ lec_arp_put(entry);
}
INIT_HLIST_HEAD(&priv->lec_no_forward);
/* No timer, LANEv2 7.1.20 and 2.3.5.3 */
lec_arp_clear_vccs(entry);
hlist_del(&entry->next);
- kfree(entry);
+ lec_arp_put(entry);
}
INIT_HLIST_HEAD(&priv->mcast_fwds);
priv->mcast_vcc = NULL;
to_return->last_used = jiffies;
to_return->priv = priv;
skb_queue_head_init(&to_return->tx_wait);
+ atomic_set(&to_return->usage, 1);
return to_return;
}
spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
lec_arp_clear_vccs(to_remove);
- kfree(to_remove);
+ lec_arp_put(to_remove);
}
/*
/* Remove entry */
DPRINTK("LEC:Entry timed out\n");
lec_arp_remove(priv, entry);
- kfree(entry);
+ lec_arp_put(entry);
} else {
/* Something else */
if ((entry->status == ESI_VC_PENDING ||
&& (permanent ||
!(entry->flags & LEC_PERMANENT_FLAG))) {
lec_arp_remove(priv, entry);
- kfree(entry);
+ lec_arp_put(entry);
}
spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
return 0;
tmp->old_push = entry->old_push;
tmp->last_used = jiffies;
del_timer(&entry->timer);
- kfree(entry);
+ lec_arp_put(entry);
entry = tmp;
} else {
entry->status = ESI_FORWARD_DIRECT;
hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_tables[i], next) {
if (vcc == entry->vcc) {
lec_arp_remove(priv, entry);
- kfree(entry);
+ lec_arp_put(entry);
if (priv->mcast_vcc == vcc) {
priv->mcast_vcc = NULL;
}
lec_arp_clear_vccs(entry);
del_timer(&entry->timer);
hlist_del(&entry->next);
- kfree(entry);
+ lec_arp_put(entry);
}
}
lec_arp_clear_vccs(entry);
del_timer(&entry->timer);
hlist_del(&entry->next);
- kfree(entry);
+ lec_arp_put(entry);
}
}
lec_arp_clear_vccs(entry);
/* No timer, LANEv2 7.1.20 and 2.3.5.3 */
hlist_del(&entry->next);
- kfree(entry);
+ lec_arp_put(entry);
}
}
/* We might have got an entry */
if ((tmp = lec_arp_find(priv, src))) {
lec_arp_remove(priv, tmp);
- kfree(tmp);
+ lec_arp_put(tmp);
}
hlist_del(&entry->next);
lec_arp_add(priv, entry);