summaryrefslogtreecommitdiffstats
path: root/drivers/isdn/mISDN/tei.c
diff options
context:
space:
mode:
authorKarsten Keil <isdn@linux-pingi.de>2012-05-04 04:15:32 +0000
committerDavid S. Miller <davem@davemloft.net>2012-05-04 11:54:27 -0400
commit8423e6b212a19d5f02232855dec73196297b5ee9 (patch)
treebb244d8d7743d2c078fe817d25a3ae4a37ca3d39 /drivers/isdn/mISDN/tei.c
parent7ed80fe45d42678fb234bf9d18de6a98cfa9830d (diff)
downloadlinux-8423e6b212a19d5f02232855dec73196297b5ee9.tar.bz2
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.c13
1 files changed, 10 insertions, 3 deletions
diff --git a/drivers/isdn/mISDN/tei.c b/drivers/isdn/mISDN/tei.c
index 109276a0d1a0..be88728f1106 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