diff options
author | Karsten Keil <isdn@linux-pingi.de> | 2012-05-04 04:15:32 (GMT) |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-05-04 15:54:27 (GMT) |
commit | 8423e6b212a19d5f02232855dec73196297b5ee9 (patch) | |
tree | bb244d8d7743d2c078fe817d25a3ae4a37ca3d39 /drivers/isdn/mISDN/tei.c | |
parent | 7ed80fe45d42678fb234bf9d18de6a98cfa9830d (diff) | |
download | linux-8423e6b212a19d5f02232855dec73196297b5ee9.tar.xz |
mISDN: L2 timeouts need to be queued as L2 event
To be full preemptiv safe, we cannot handle a L2 timeout in the timer
context itself, we should do all actions via the D-channel thread.
Signed-off-by: Karsten Keil <kkeil@linux-pingi.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/isdn/mISDN/tei.c')
-rw-r--r-- | drivers/isdn/mISDN/tei.c | 13 |
1 files changed, 10 insertions, 3 deletions
diff --git a/drivers/isdn/mISDN/tei.c b/drivers/isdn/mISDN/tei.c index 109276a..be88728 100644 --- a/drivers/isdn/mISDN/tei.c +++ b/drivers/isdn/mISDN/tei.c @@ -1294,7 +1294,7 @@ static int mgr_bcast(struct mISDNchannel *ch, struct sk_buff *skb) { struct manager *mgr = container_of(ch, struct manager, bcast); - struct mISDNhead *hh = mISDN_HEAD_P(skb); + struct mISDNhead *hhc, *hh = mISDN_HEAD_P(skb); struct sk_buff *cskb = NULL; struct layer2 *l2; u_long flags; @@ -1309,10 +1309,17 @@ mgr_bcast(struct mISDNchannel *ch, struct sk_buff *skb) skb = NULL; } else { if (!cskb) - cskb = skb_copy(skb, GFP_KERNEL); + cskb = skb_copy(skb, GFP_ATOMIC); } if (cskb) { - ret = l2->ch.send(&l2->ch, cskb); + hhc = mISDN_HEAD_P(cskb); + /* save original header behind normal header */ + hhc++; + *hhc = *hh; + hhc--; + hhc->prim = DL_INTERN_MSG; + hhc->id = l2->ch.nr; + ret = ch->st->own.recv(&ch->st->own, cskb); if (ret) { if (*debug & DEBUG_SEND_ERR) printk(KERN_DEBUG |