From a688430c41f37c3e451da5a4c5c5ce1037820936 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:36 +0000 Subject: [PATCH] --- yaml --- r: 184239 b: refs/heads/master c: a11ef7be8e982426e9fbbfc84fa0c01d23ce05c3 h: refs/heads/master i: 184237: a926b3fd7b5117083624c561f1df4f7efd308ffc 184235: b26bca6a5a53d056116d411a4b9d7b80f89bdb4f 184231: e75506f89f974a4b692ce3d86d7bb056fe44d47a 184223: 39e5e77a1a4a18c559f8b10d848e6e4185c33c44 v: v3 --- [refs] | 2 +- trunk/drivers/isdn/capi/capi.c | 60 +++++++++++++++++++++------------- 2 files changed, 39 insertions(+), 23 deletions(-) diff --git a/[refs] b/[refs] index e46064c6743e..474552a9ddf6 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: b75b2eedcbf6458c68713c772c2ade83ab7a55f0 +refs/heads/master: a11ef7be8e982426e9fbbfc84fa0c01d23ce05c3 diff --git a/trunk/drivers/isdn/capi/capi.c b/trunk/drivers/isdn/capi/capi.c index 554fa1b36d13..c5c54fab50eb 100644 --- a/trunk/drivers/isdn/capi/capi.c +++ b/trunk/drivers/isdn/capi/capi.c @@ -436,15 +436,13 @@ gen_data_b3_resp_for(struct capiminor *mp, struct sk_buff *skb) static int handle_recv_skb(struct capiminor *mp, struct sk_buff *skb) { + unsigned int datalen = skb->len - CAPIMSG_LEN(skb->data); struct tty_struct *tty; struct sk_buff *nskb; - int datalen; u16 errcode, datahandle; struct tty_ldisc *ld; int ret = -1; - datalen = skb->len - CAPIMSG_LEN(skb->data); - tty = tty_port_tty_get(&mp->port); if (!tty) { #ifdef _DEBUG_DATAFLOW @@ -454,50 +452,68 @@ static int handle_recv_skb(struct capiminor *mp, struct sk_buff *skb) } ld = tty_ldisc_ref(tty); - if (!ld) - goto out1; + if (!ld) { + /* fatal error, do not requeue */ + ret = 0; + kfree_skb(skb); + goto deref_tty; + } if (ld->ops->receive_buf == NULL) { #if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS) printk(KERN_DEBUG "capi: ldisc has no receive_buf function\n"); #endif - goto out2; + /* fatal error, do not requeue */ + goto free_skb; } if (mp->ttyinstop) { #if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS) printk(KERN_DEBUG "capi: recv tty throttled\n"); #endif - goto out2; + goto deref_ldisc; } + if (tty->receive_room < datalen) { #if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS) printk(KERN_DEBUG "capi: no room in tty\n"); #endif - goto out2; + goto deref_ldisc; } - if ((nskb = gen_data_b3_resp_for(mp, skb)) == NULL) { + + nskb = gen_data_b3_resp_for(mp, skb); + if (!nskb) { printk(KERN_ERR "capi: gen_data_b3_resp failed\n"); - goto out2; + goto deref_ldisc; } - datahandle = CAPIMSG_U16(skb->data,CAPIMSG_BASELEN+4); + + datahandle = CAPIMSG_U16(skb->data, CAPIMSG_BASELEN + 4); + errcode = capi20_put_message(mp->ap, nskb); - if (errcode != CAPI_NOERROR) { + + if (errcode == CAPI_NOERROR) { + skb_pull(skb, CAPIMSG_LEN(skb->data)); +#ifdef _DEBUG_DATAFLOW + printk(KERN_DEBUG "capi: DATA_B3_RESP %u len=%d => ldisc\n", + datahandle, skb->len); +#endif + ld->ops->receive_buf(tty, skb->data, NULL, skb->len); + } else { printk(KERN_ERR "capi: send DATA_B3_RESP failed=%x\n", errcode); kfree_skb(nskb); - goto out2; + + if (errcode == CAPI_SENDQUEUEFULL) + goto deref_ldisc; } - (void)skb_pull(skb, CAPIMSG_LEN(skb->data)); -#ifdef _DEBUG_DATAFLOW - printk(KERN_DEBUG "capi: DATA_B3_RESP %u len=%d => ldisc\n", - datahandle, skb->len); -#endif - ld->ops->receive_buf(tty, skb->data, NULL, skb->len); - kfree_skb(skb); + +free_skb: ret = 0; -out2: + kfree_skb(skb); + +deref_ldisc: tty_ldisc_deref(ld); -out1: + +deref_tty: tty_kref_put(tty); return ret; }