From patchwork Sat Mar 17 15:01:12 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Karsten Keil X-Patchwork-Id: 154491 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 E2A09B6FC3 for ; Tue, 24 Apr 2012 03:08:38 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754524Ab2DWRI2 (ORCPT ); Mon, 23 Apr 2012 13:08:28 -0400 Received: from moutng.kundenserver.de ([212.227.17.8]:62432 "EHLO moutng.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754199Ab2DWRIW (ORCPT ); Mon, 23 Apr 2012 13:08:22 -0400 Received: from mailone.linux-pingi.de (p5497CD69.dip.t-dialin.net [84.151.205.105]) by mrelayeu.kundenserver.de (node=mrbap2) with ESMTP (Nemesis) id 0MHaGK-1SNS9941wS-003j6e; Mon, 23 Apr 2012 19:08:20 +0200 Received: from pingi6.linux-pingi.de (pingi6.linux-pingi.de [10.23.200.6]) by mailone.linux-pingi.de (Postfix) with ESMTP id 028064FD9; Mon, 23 Apr 2012 19:08:17 +0200 (CEST) Received: by pingi6.linux-pingi.de (Postfix, from userid 1000) id 331249FBA7; Mon, 23 Apr 2012 19:05:50 +0200 (CEST) Date: Sat, 17 Mar 2012 16:01:12 +0100 Subject: [PATCH 12/28] mISDN: L2 timeouts need to be queued as L2 event From: Karsten Keil To: David Miller Cc: netdev@vger.kernel.org, isdn4linux@listserv.isdn4linux.de Message-Id: <20120423170550.331249FBA7@pingi6.linux-pingi.de> X-Provags-ID: V02:K0:lytPJ8fYM95S8Uwf6HjI3qZ7vMPDcajCwC3PrBiowZ9 jATcelId4j/DNnioW+1jxt/yMdbLdkBcNNAFAifDnOeGxWoJk8 ciOlmHVHJQcSuJYwOOScYMVVU916wvdzQ+nk+HTMLbsxFYaa7g PKJeBZNHaegHSk+j9Sywc9PEWc5tjYrFE45ZbZJIuH5hMw9oDX fjM7r1nbv8kWRXXVaLYLo779QYW4YvRWZRNL5x0CSI5F9P4SkP S/yJf4x/S1aOjcDM68Kr77J9czTpUPKk17PJV50ysy9aokDnsV hprQDK2cgyZqjS1Ud8i7jRV/wxqiT+LlSPuk6tWrZzWExOW4AM Q71TkUiXEYgIbG+ZJfN654tEV46iiTBTUBjSB1wh+GLDRwRooK I4BKRExXdhj5TXFmpjzPl3hF5uOxSuBZJo= Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org 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 --- drivers/isdn/mISDN/layer2.c | 58 +++++++++++++++++++++++++++++++++++++++--- drivers/isdn/mISDN/tei.c | 13 +++++++-- include/linux/mISDNif.h | 9 ++++++- 3 files changed, 71 insertions(+), 9 deletions(-) diff --git a/drivers/isdn/mISDN/layer2.c b/drivers/isdn/mISDN/layer2.c index 39d7375..d421495 100644 --- a/drivers/isdn/mISDN/layer2.c +++ b/drivers/isdn/mISDN/layer2.c @@ -58,6 +58,8 @@ enum { EV_L1_DEACTIVATE, EV_L2_T200, EV_L2_T203, + EV_L2_T200I, + EV_L2_T203I, EV_L2_SET_OWN_BUSY, EV_L2_CLEAR_OWN_BUSY, EV_L2_FRAME_ERROR, @@ -86,6 +88,8 @@ static char *strL2Event[] = "EV_L1_DEACTIVATE", "EV_L2_T200", "EV_L2_T203", + "EV_L2_T200I", + "EV_L2_T203I", "EV_L2_SET_OWN_BUSY", "EV_L2_CLEAR_OWN_BUSY", "EV_L2_FRAME_ERROR", @@ -276,6 +280,31 @@ ph_data_confirm(struct layer2 *l2, struct mISDNhead *hh, struct sk_buff *skb) { return ret; } +static void +l2_timeout(struct FsmInst *fi, int event, void *arg) +{ + struct layer2 *l2 = fi->userdata; + struct sk_buff *skb; + struct mISDNhead *hh; + + skb = mI_alloc_skb(0, GFP_ATOMIC); + if (!skb) { + printk(KERN_WARNING "L2(%d,%d) nr:%x timer %s lost - no skb\n", + l2->sapi, l2->tei, l2->ch.nr, event == EV_L2_T200 ? + "T200" : "T203"); + return; + } + hh = mISDN_HEAD_P(skb); + hh->prim = event == EV_L2_T200 ? DL_TIMER200_IND : DL_TIMER203_IND; + hh->id = l2->ch.nr; + if (*debug & DEBUG_TIMER) + printk(KERN_DEBUG "L2(%d,%d) nr:%x timer %s expired\n", + l2->sapi, l2->tei, l2->ch.nr, event == EV_L2_T200 ? + "T200" : "T203"); + if (l2->ch.st) + l2->ch.st->own.recv(&l2->ch.st->own, skb); +} + static int l2mgr(struct layer2 *l2, u_int prim, void *arg) { long c = (long)arg; @@ -1814,11 +1843,16 @@ static struct FsmNode L2FnList[] = {ST_L2_8, EV_L2_SUPER, l2_st8_got_super}, {ST_L2_7, EV_L2_I, l2_got_iframe}, {ST_L2_8, EV_L2_I, l2_got_iframe}, - {ST_L2_5, EV_L2_T200, l2_st5_tout_200}, - {ST_L2_6, EV_L2_T200, l2_st6_tout_200}, - {ST_L2_7, EV_L2_T200, l2_st7_tout_200}, - {ST_L2_8, EV_L2_T200, l2_st8_tout_200}, - {ST_L2_7, EV_L2_T203, l2_st7_tout_203}, + {ST_L2_5, EV_L2_T200, l2_timeout}, + {ST_L2_6, EV_L2_T200, l2_timeout}, + {ST_L2_7, EV_L2_T200, l2_timeout}, + {ST_L2_8, EV_L2_T200, l2_timeout}, + {ST_L2_7, EV_L2_T203, l2_timeout}, + {ST_L2_5, EV_L2_T200I, l2_st5_tout_200}, + {ST_L2_6, EV_L2_T200I, l2_st6_tout_200}, + {ST_L2_7, EV_L2_T200I, l2_st7_tout_200}, + {ST_L2_8, EV_L2_T200I, l2_st8_tout_200}, + {ST_L2_7, EV_L2_T203I, l2_st7_tout_203}, {ST_L2_7, EV_L2_ACK_PULL, l2_pull_iqueue}, {ST_L2_7, EV_L2_SET_OWN_BUSY, l2_set_own_busy}, {ST_L2_8, EV_L2_SET_OWN_BUSY, l2_set_own_busy}, @@ -1932,6 +1966,14 @@ l2_send(struct mISDNchannel *ch, struct sk_buff *skb) if (*debug & DEBUG_L2_RECV) printk(KERN_DEBUG "%s: prim(%x) id(%x) sapi(%d) tei(%d)\n", __func__, hh->prim, hh->id, l2->sapi, l2->tei); + if (hh->prim == DL_INTERN_MSG) { + struct mISDNhead *chh = hh + 1; /* saved copy */ + + *hh = *chh; + if (*debug & DEBUG_L2_RECV) + printk(KERN_DEBUG "%s: prim(%x) id(%x) internal msg\n", + __func__, hh->prim, hh->id); + } switch (hh->prim) { case PH_DATA_IND: ret = ph_data_indication(l2, hh, skb); @@ -1987,6 +2029,12 @@ l2_send(struct mISDNchannel *ch, struct sk_buff *skb) ret = mISDN_FsmEvent(&l2->l2m, EV_L2_DL_RELEASE_REQ, skb); break; + case DL_TIMER200_IND: + mISDN_FsmEvent(&l2->l2m, EV_L2_T200I, NULL); + break; + case DL_TIMER203_IND: + mISDN_FsmEvent(&l2->l2m, EV_L2_T203I, NULL); + break; default: if (*debug & DEBUG_L2) l2m_debug(&l2->l2m, "l2 unknown pr %04x", diff --git a/drivers/isdn/mISDN/tei.c b/drivers/isdn/mISDN/tei.c index 25ed826..c7f6bea 100644 --- a/drivers/isdn/mISDN/tei.c +++ b/drivers/isdn/mISDN/tei.c @@ -1293,7 +1293,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; @@ -1308,10 +1308,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 diff --git a/include/linux/mISDNif.h b/include/linux/mISDNif.h index bdda647..b7457e8 100644 --- a/include/linux/mISDNif.h +++ b/include/linux/mISDNif.h @@ -37,7 +37,7 @@ */ #define MISDN_MAJOR_VERSION 1 #define MISDN_MINOR_VERSION 1 -#define MISDN_RELEASE 24 +#define MISDN_RELEASE 26 /* primitives for information exchange * generell format @@ -115,6 +115,11 @@ #define MDL_ERROR_IND 0x1F04 #define MDL_ERROR_RSP 0x5F04 +/* intern layer 2 */ +#define DL_TIMER200_IND 0x7004 +#define DL_TIMER203_IND 0x7304 +#define DL_INTERN_MSG 0x7804 + /* DL_INFORMATION_IND types */ #define DL_INFO_L2_CONNECT 0x0001 #define DL_INFO_L2_REMOVED 0x0002 @@ -289,6 +294,8 @@ struct mISDNversion { unsigned short release; }; +#define MAX_DEVICE_ID 63 + struct mISDN_devinfo { u_int id; u_int Dprotocols;