From patchwork Mon Feb 8 20:12:36 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Kiszka X-Patchwork-Id: 44828 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id B52FDB7CF1 for ; Tue, 9 Feb 2010 07:16:30 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754708Ab0BHUQH (ORCPT ); Mon, 8 Feb 2010 15:16:07 -0500 Received: from fmmailgate02.web.de ([217.72.192.227]:43397 "EHLO fmmailgate02.web.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754333Ab0BHUNO (ORCPT ); Mon, 8 Feb 2010 15:13:14 -0500 Received: from smtp05.web.de (fmsmtp05.dlan.cinetic.de [172.20.4.166]) by fmmailgate02.web.de (Postfix) with ESMTP id 8F34414D52AE5; Mon, 8 Feb 2010 21:13:13 +0100 (CET) Received: from [88.65.45.120] (helo=localhost.localdomain) by smtp05.web.de with asmtp (TLSv1:AES256-SHA:256) (WEB.DE 4.110 #314) id 1NeZyr-0006fo-01; Mon, 08 Feb 2010 21:13:13 +0100 From: Jan Kiszka To: David Miller , Karsten Keil Cc: linux-kernel@vger.kernel.org, i4ldeveloper@listserv.isdn4linux.de, isdn4linux@listserv.isdn4linux.de, netdev@vger.kernel.org, Alan Cox , Marcel Holtmann Subject: [PATCH v2 32/41] CAPI: Rework capiminor RX handler Date: Mon, 8 Feb 2010 21:12:36 +0100 Message-Id: <986a5c803a1c55bd0d7d721024a471fbe43953c9.1265659936.git.jan.kiszka@web.de> X-Mailer: git-send-email 1.6.0.2 In-Reply-To: References: In-Reply-To: References: X-Sender: jan.kiszka@web.de X-Provags-ID: V01U2FsdGVkX19jxrWTEiQfV+TDbhG9R58Oa+PsAwVLoZdjaWkg QCnEY9zy8semq93cYE2Nnhw5UUmTKCXl83hPBLuLoZ0SaGPzJj XbdB6IpSc= Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Avoid re-queuing skbs unless the error detected in handle_recv_skb is expected to be recoverable such as lacking memory, a full CAPI queue, a full TTY input buffer, or a not yet existing TTY. Signed-off-by: Jan Kiszka --- drivers/isdn/capi/capi.c | 60 +++++++++++++++++++++++++++++----------------- 1 files changed, 38 insertions(+), 22 deletions(-) diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 554fa1b..c5c54fa 100644 --- a/drivers/isdn/capi/capi.c +++ b/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; }