diff --git a/[refs] b/[refs] index d724e0d88b61..60047d299a54 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: cf3752e2d203bbbfc88d29e362e6938cef4339b3 +refs/heads/master: e653181dd6b3ad38ce14904351b03a5388f4b0f7 diff --git a/trunk/drivers/net/pppol2tp.c b/trunk/drivers/net/pppol2tp.c index 9a90cede0ecc..3d10ca050b79 100644 --- a/trunk/drivers/net/pppol2tp.c +++ b/trunk/drivers/net/pppol2tp.c @@ -342,10 +342,11 @@ static struct pppol2tp_tunnel *pppol2tp_tunnel_find(u16 tunnel_id) static void pppol2tp_recv_queue_skb(struct pppol2tp_session *session, struct sk_buff *skb) { struct sk_buff *skbp; + struct sk_buff *tmp; u16 ns = PPPOL2TP_SKB_CB(skb)->ns; spin_lock_bh(&session->reorder_q.lock); - skb_queue_walk(&session->reorder_q, skbp) { + skb_queue_walk_safe(&session->reorder_q, skbp, tmp) { if (PPPOL2TP_SKB_CB(skbp)->ns > ns) { __skb_insert(skb, skbp->prev, skbp, &session->reorder_q); PRINTK(session->debug, PPPOL2TP_MSG_SEQ, KERN_DEBUG, @@ -371,10 +372,9 @@ static void pppol2tp_recv_dequeue_skb(struct pppol2tp_session *session, struct s int length = PPPOL2TP_SKB_CB(skb)->length; struct sock *session_sock = NULL; - /* We're about to requeue the skb, so unlink it and return resources + /* We're about to requeue the skb, so return resources * to its current owner (a socket receive buffer). */ - skb_unlink(skb, &session->reorder_q); skb_orphan(skb); tunnel->stats.rx_packets++; @@ -470,6 +470,11 @@ static void pppol2tp_recv_dequeue(struct pppol2tp_session *session) goto out; } } + __skb_unlink(skb, &session->reorder_q); + + /* Process the skb. We release the queue lock while we + * do so to let other contexts process the queue. + */ spin_unlock_bh(&session->reorder_q.lock); pppol2tp_recv_dequeue_skb(session, skb); spin_lock_bh(&session->reorder_q.lock);