On Wed, Feb 20, 2008 at 12:06:40AM +0100, Jarek Poplawski wrote: ... > (testing patch #1)
SORRY!!! ----> take 2 (unlocking fixed) --- drivers/net/ppp_generic.c | 39 +++++++++++++++++++++++++++++---------- 1 files changed, 29 insertions(+), 10 deletions(-) diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index 4dc5b4b..c4e3808 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c @@ -1473,7 +1473,7 @@ void ppp_input(struct ppp_channel *chan, struct sk_buff *skb) { struct channel *pch = chan->ppp; - int proto; + int proto, locked; if (!pch || skb->len == 0) { kfree_skb(skb); @@ -1481,8 +1481,13 @@ ppp_input(struct ppp_channel *chan, struct sk_buff *skb) } proto = PPP_PROTO(skb); - read_lock_bh(&pch->upl); - if (!pch->ppp || proto >= 0xc000 || proto == PPP_CCPFRAG) { + /* + * We use trylock to avoid dependency between soft-irq-safe upl lock + * and soft-irq-unsafe sk_dst_lock. + */ + local_bh_disable(); + locked = read_trylock(&pch->upl); + if (!locked || !pch->ppp || proto >= 0xc000 || proto == PPP_CCPFRAG) { /* put it on the channel queue */ skb_queue_tail(&pch->file.rq, skb); /* drop old frames if queue too long */ @@ -1493,7 +1498,10 @@ ppp_input(struct ppp_channel *chan, struct sk_buff *skb) } else { ppp_do_recv(pch->ppp, skb, pch); } - read_unlock_bh(&pch->upl); + + if (locked) + read_unlock(&pch->upl); + local_bh_enable(); } /* Put a 0-length skb in the receive queue as an error indication */ @@ -1502,12 +1510,14 @@ ppp_input_error(struct ppp_channel *chan, int code) { struct channel *pch = chan->ppp; struct sk_buff *skb; + int locked; if (!pch) return; - read_lock_bh(&pch->upl); - if (pch->ppp) { + /* a trylock comment in ppp_input() */ + local_bh_disable(); + if ((locked = read_trylock(&pch->upl)) && pch->ppp) { skb = alloc_skb(0, GFP_ATOMIC); if (skb) { skb->len = 0; /* probably unnecessary */ @@ -1515,7 +1525,10 @@ ppp_input_error(struct ppp_channel *chan, int code) ppp_do_recv(pch->ppp, skb, pch); } } - read_unlock_bh(&pch->upl); + + if (locked) + read_unlock(&pch->upl); + local_bh_enable(); } /* @@ -2044,10 +2057,16 @@ int ppp_unit_number(struct ppp_channel *chan) int unit = -1; if (pch) { - read_lock_bh(&pch->upl); - if (pch->ppp) + int locked; + + /* a trylock comment in ppp_input() */ + local_bh_disable(); + if ((locked = read_trylock(&pch->upl)) && pch->ppp) unit = pch->ppp->file.index; - read_unlock_bh(&pch->upl); + + if (locked) + read_unlock(&pch->upl); + local_bh_enable(); } return unit; } -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html