|  | /* 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 | 
|  | * "from" and "to". Note that it locks both lists at the same time, so beware | 
|  | * of potential deadlocks. | 
|  | * | 
|  | * This function should live in skbuff.c or skbuff.h. | 
|  | */ | 
|  |  | 
|  |  | 
|  | void skb_migrate(struct sk_buff_head *from,struct sk_buff_head *to) | 
|  | { | 
|  | struct sk_buff *skb; | 
|  | 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; | 
|  |  | 
|  | spin_lock_irqsave(&from->lock,flags); | 
|  | spin_lock(&to->lock); | 
|  | prev = from->prev; | 
|  | from->next->prev = to->prev; | 
|  | prev->next = skb_to; | 
|  | to->prev->next = from->next; | 
|  | to->prev = from->prev; | 
|  | for (skb = from->next; skb != skb_to; skb = skb->next) | 
|  | skb->list = to; | 
|  | to->qlen += from->qlen; | 
|  | spin_unlock(&to->lock); | 
|  | from->prev = skb_from; | 
|  | from->next = skb_from; | 
|  | from->qlen = 0; | 
|  | spin_unlock_irqrestore(&from->lock,flags); | 
|  | } | 
|  |  | 
|  |  | 
|  | EXPORT_SYMBOL(skb_migrate); |