diff options
Diffstat (limited to 'net/atm/clip.c')
| -rw-r--r-- | net/atm/clip.c | 27 | 
1 files changed, 19 insertions, 8 deletions
| diff --git a/net/atm/clip.c b/net/atm/clip.c index c12c2582457c..5de42ea309bc 100644 --- a/net/atm/clip.c +++ b/net/atm/clip.c @@ -46,8 +46,8 @@  static struct net_device *clip_devs;  static struct atm_vcc *atmarpd; -static struct neigh_table clip_tbl;  static struct timer_list idle_timer; +static const struct neigh_ops clip_neigh_ops;  static int to_atmarpd(enum atmarp_ctrl_type type, int itf, __be32 ip)  { @@ -123,6 +123,8 @@ static int neigh_check_cb(struct neighbour *n)  	struct atmarp_entry *entry = neighbour_priv(n);  	struct clip_vcc *cv; +	if (n->ops != &clip_neigh_ops) +		return 0;  	for (cv = entry->vccs; cv; cv = cv->next) {  		unsigned long exp = cv->last_use + cv->idle_timeout; @@ -154,10 +156,10 @@ static int neigh_check_cb(struct neighbour *n)  static void idle_timer_check(unsigned long dummy)  { -	write_lock(&clip_tbl.lock); -	__neigh_for_each_release(&clip_tbl, neigh_check_cb); +	write_lock(&arp_tbl.lock); +	__neigh_for_each_release(&arp_tbl, neigh_check_cb);  	mod_timer(&idle_timer, jiffies + CLIP_CHECK_INTERVAL * HZ); -	write_unlock(&clip_tbl.lock); +	write_unlock(&arp_tbl.lock);  }  static int clip_arp_rcv(struct sk_buff *skb) @@ -328,6 +330,8 @@ static netdev_tx_t clip_start_xmit(struct sk_buff *skb,  	struct atmarp_entry *entry;  	struct neighbour *n;  	struct atm_vcc *vcc; +	struct rtable *rt; +	__be32 *daddr;  	int old;  	unsigned long flags; @@ -338,7 +342,12 @@ static netdev_tx_t clip_start_xmit(struct sk_buff *skb,  		dev->stats.tx_dropped++;  		return NETDEV_TX_OK;  	} -	n = dst_get_neighbour_noref(dst); +	rt = (struct rtable *) dst; +	if (rt->rt_gateway) +		daddr = &rt->rt_gateway; +	else +		daddr = &ip_hdr(skb)->daddr; +	n = dst_neigh_lookup(dst, daddr);  	if (!n) {  		pr_err("NO NEIGHBOUR !\n");  		dev_kfree_skb(skb); @@ -358,7 +367,7 @@ static netdev_tx_t clip_start_xmit(struct sk_buff *skb,  			dev_kfree_skb(skb);  			dev->stats.tx_dropped++;  		} -		return NETDEV_TX_OK; +		goto out_release_neigh;  	}  	pr_debug("neigh %p, vccs %p\n", entry, entry->vccs);  	ATM_SKB(skb)->vcc = vcc = entry->vccs->vcc; @@ -377,14 +386,14 @@ static netdev_tx_t clip_start_xmit(struct sk_buff *skb,  	old = xchg(&entry->vccs->xoff, 1);	/* assume XOFF ... */  	if (old) {  		pr_warning("XOFF->XOFF transition\n"); -		return NETDEV_TX_OK; +		goto out_release_neigh;  	}  	dev->stats.tx_packets++;  	dev->stats.tx_bytes += skb->len;  	vcc->send(vcc, skb);  	if (atm_may_send(vcc, 0)) {  		entry->vccs->xoff = 0; -		return NETDEV_TX_OK; +		goto out_release_neigh;  	}  	spin_lock_irqsave(&clip_priv->xoff_lock, flags);  	netif_stop_queue(dev);	/* XOFF -> throttle immediately */ @@ -396,6 +405,8 @@ static netdev_tx_t clip_start_xmit(struct sk_buff *skb,  	   of the brief netif_stop_queue. If this isn't true or if it  	   changes, use netif_wake_queue instead. */  	spin_unlock_irqrestore(&clip_priv->xoff_lock, flags); +out_release_neigh: +	neigh_release(n);  	return NETDEV_TX_OK;  } | 
