2005-04-16 15:20:36 -07:00
/* net/atm/ipcommon.c - Common items for all ways of doing IP over ATM */
/* Written 1996-2000 by Werner Almesberger, EPFL LRC/ICA */
# include <linux/module.h>
# include <linux/string.h>
# include <linux/skbuff.h>
# include <linux/netdevice.h>
# include <linux/in.h>
# include <linux/atmdev.h>
# include <linux/atmclip.h>
# include "common.h"
# include "ipcommon.h"
#if 0
# define DPRINTK(format,args...) printk(KERN_DEBUG format,##args)
# else
# define DPRINTK(format,args...)
# endif
/*
* skb_migrate appends the list at " from " to " to " , emptying " from " in the
* process . skb_migrate is atomic with respect to all other skb operations on
2006-07-08 13:30:52 -07:00
* " from " and " to " . Note that it locks both lists at the same time , so to deal
* with the lock ordering , the locks are taken in address order .
2005-04-16 15:20:36 -07:00
*
* This function should live in skbuff . c or skbuff . h .
*/
2006-07-08 13:30:52 -07:00
void skb_migrate ( struct sk_buff_head * from , struct sk_buff_head * to )
2005-04-16 15:20:36 -07:00
{
unsigned long flags ;
struct sk_buff * skb_from = ( struct sk_buff * ) from ;
struct sk_buff * skb_to = ( struct sk_buff * ) to ;
struct sk_buff * prev ;
2006-07-08 13:30:52 -07:00
if ( ( unsigned long ) from < ( unsigned long ) to ) {
spin_lock_irqsave ( & from - > lock , flags ) ;
spin_lock_nested ( & to - > lock , SINGLE_DEPTH_NESTING ) ;
} else {
spin_lock_irqsave ( & to - > lock , flags ) ;
spin_lock_nested ( & from - > lock , SINGLE_DEPTH_NESTING ) ;
}
2005-04-16 15:20:36 -07:00
prev = from - > prev ;
from - > next - > prev = to - > prev ;
prev - > next = skb_to ;
to - > prev - > next = from - > next ;
to - > prev = from - > prev ;
to - > qlen + = from - > qlen ;
spin_unlock ( & to - > lock ) ;
from - > prev = skb_from ;
from - > next = skb_from ;
from - > qlen = 0 ;
2006-07-08 13:30:52 -07:00
spin_unlock_irqrestore ( & from - > lock , flags ) ;
2005-04-16 15:20:36 -07:00
}
EXPORT_SYMBOL ( skb_migrate ) ;