aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKarsten Keil <isdn@linux-pingi.de>2012-05-04 00:15:32 -0400
committerDavid S. Miller <davem@davemloft.net>2012-05-04 11:54:27 -0400
commit8423e6b212a19d5f02232855dec73196297b5ee9 (patch)
treebb244d8d7743d2c078fe817d25a3ae4a37ca3d39
parent7ed80fe45d42678fb234bf9d18de6a98cfa9830d (diff)
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>
-rw-r--r--drivers/isdn/mISDN/layer2.c58
-rw-r--r--drivers/isdn/mISDN/tei.c13
-rw-r--r--include/linux/mISDNif.h7
3 files changed, 69 insertions, 9 deletions
diff --git a/drivers/isdn/mISDN/layer2.c b/drivers/isdn/mISDN/layer2.c
index 39d7375fa551..b6fbaec1d612 100644
--- a/drivers/isdn/mISDN/layer2.c
+++ b/drivers/isdn/mISDN/layer2.c
@@ -58,6 +58,8 @@ enum {
58 EV_L1_DEACTIVATE, 58 EV_L1_DEACTIVATE,
59 EV_L2_T200, 59 EV_L2_T200,
60 EV_L2_T203, 60 EV_L2_T203,
61 EV_L2_T200I,
62 EV_L2_T203I,
61 EV_L2_SET_OWN_BUSY, 63 EV_L2_SET_OWN_BUSY,
62 EV_L2_CLEAR_OWN_BUSY, 64 EV_L2_CLEAR_OWN_BUSY,
63 EV_L2_FRAME_ERROR, 65 EV_L2_FRAME_ERROR,
@@ -86,6 +88,8 @@ static char *strL2Event[] =
86 "EV_L1_DEACTIVATE", 88 "EV_L1_DEACTIVATE",
87 "EV_L2_T200", 89 "EV_L2_T200",
88 "EV_L2_T203", 90 "EV_L2_T203",
91 "EV_L2_T200I",
92 "EV_L2_T203I",
89 "EV_L2_SET_OWN_BUSY", 93 "EV_L2_SET_OWN_BUSY",
90 "EV_L2_CLEAR_OWN_BUSY", 94 "EV_L2_CLEAR_OWN_BUSY",
91 "EV_L2_FRAME_ERROR", 95 "EV_L2_FRAME_ERROR",
@@ -276,6 +280,31 @@ ph_data_confirm(struct layer2 *l2, struct mISDNhead *hh, struct sk_buff *skb) {
276 return ret; 280 return ret;
277} 281}
278 282
283static void
284l2_timeout(struct FsmInst *fi, int event, void *arg)
285{
286 struct layer2 *l2 = fi->userdata;
287 struct sk_buff *skb;
288 struct mISDNhead *hh;
289
290 skb = mI_alloc_skb(0, GFP_ATOMIC);
291 if (!skb) {
292 printk(KERN_WARNING "L2(%d,%d) nr:%x timer %s lost - no skb\n",
293 l2->sapi, l2->tei, l2->ch.nr, event == EV_L2_T200 ?
294 "T200" : "T203");
295 return;
296 }
297 hh = mISDN_HEAD_P(skb);
298 hh->prim = event == EV_L2_T200 ? DL_TIMER200_IND : DL_TIMER203_IND;
299 hh->id = l2->ch.nr;
300 if (*debug & DEBUG_TIMER)
301 printk(KERN_DEBUG "L2(%d,%d) nr:%x timer %s expired\n",
302 l2->sapi, l2->tei, l2->ch.nr, event == EV_L2_T200 ?
303 "T200" : "T203");
304 if (l2->ch.st)
305 l2->ch.st->own.recv(&l2->ch.st->own, skb);
306}
307
279static int 308static int
280l2mgr(struct layer2 *l2, u_int prim, void *arg) { 309l2mgr(struct layer2 *l2, u_int prim, void *arg) {
281 long c = (long)arg; 310 long c = (long)arg;
@@ -1814,11 +1843,16 @@ static struct FsmNode L2FnList[] =
1814 {ST_L2_8, EV_L2_SUPER, l2_st8_got_super}, 1843 {ST_L2_8, EV_L2_SUPER, l2_st8_got_super},
1815 {ST_L2_7, EV_L2_I, l2_got_iframe}, 1844 {ST_L2_7, EV_L2_I, l2_got_iframe},
1816 {ST_L2_8, EV_L2_I, l2_got_iframe}, 1845 {ST_L2_8, EV_L2_I, l2_got_iframe},
1817 {ST_L2_5, EV_L2_T200, l2_st5_tout_200}, 1846 {ST_L2_5, EV_L2_T200, l2_timeout},
1818 {ST_L2_6, EV_L2_T200, l2_st6_tout_200}, 1847 {ST_L2_6, EV_L2_T200, l2_timeout},
1819 {ST_L2_7, EV_L2_T200, l2_st7_tout_200}, 1848 {ST_L2_7, EV_L2_T200, l2_timeout},
1820 {ST_L2_8, EV_L2_T200, l2_st8_tout_200}, 1849 {ST_L2_8, EV_L2_T200, l2_timeout},
1821 {ST_L2_7, EV_L2_T203, l2_st7_tout_203}, 1850 {ST_L2_7, EV_L2_T203, l2_timeout},
1851 {ST_L2_5, EV_L2_T200I, l2_st5_tout_200},
1852 {ST_L2_6, EV_L2_T200I, l2_st6_tout_200},
1853 {ST_L2_7, EV_L2_T200I, l2_st7_tout_200},
1854 {ST_L2_8, EV_L2_T200I, l2_st8_tout_200},
1855 {ST_L2_7, EV_L2_T203I, l2_st7_tout_203},
1822 {ST_L2_7, EV_L2_ACK_PULL, l2_pull_iqueue}, 1856 {ST_L2_7, EV_L2_ACK_PULL, l2_pull_iqueue},
1823 {ST_L2_7, EV_L2_SET_OWN_BUSY, l2_set_own_busy}, 1857 {ST_L2_7, EV_L2_SET_OWN_BUSY, l2_set_own_busy},
1824 {ST_L2_8, EV_L2_SET_OWN_BUSY, l2_set_own_busy}, 1858 {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)
1932 if (*debug & DEBUG_L2_RECV) 1966 if (*debug & DEBUG_L2_RECV)
1933 printk(KERN_DEBUG "%s: prim(%x) id(%x) sapi(%d) tei(%d)\n", 1967 printk(KERN_DEBUG "%s: prim(%x) id(%x) sapi(%d) tei(%d)\n",
1934 __func__, hh->prim, hh->id, l2->sapi, l2->tei); 1968 __func__, hh->prim, hh->id, l2->sapi, l2->tei);
1969 if (hh->prim == DL_INTERN_MSG) {
1970 struct mISDNhead *chh = hh + 1; /* saved copy */
1971
1972 *hh = *chh;
1973 if (*debug & DEBUG_L2_RECV)
1974 printk(KERN_DEBUG "%s: prim(%x) id(%x) internal msg\n",
1975 __func__, hh->prim, hh->id);
1976 }
1935 switch (hh->prim) { 1977 switch (hh->prim) {
1936 case PH_DATA_IND: 1978 case PH_DATA_IND:
1937 ret = ph_data_indication(l2, hh, skb); 1979 ret = ph_data_indication(l2, hh, skb);
@@ -1987,6 +2029,12 @@ l2_send(struct mISDNchannel *ch, struct sk_buff *skb)
1987 ret = mISDN_FsmEvent(&l2->l2m, EV_L2_DL_RELEASE_REQ, 2029 ret = mISDN_FsmEvent(&l2->l2m, EV_L2_DL_RELEASE_REQ,
1988 skb); 2030 skb);
1989 break; 2031 break;
2032 case DL_TIMER200_IND:
2033 mISDN_FsmEvent(&l2->l2m, EV_L2_T200I, NULL);
2034 break;
2035 case DL_TIMER203_IND:
2036 mISDN_FsmEvent(&l2->l2m, EV_L2_T203I, NULL);
2037 break;
1990 default: 2038 default:
1991 if (*debug & DEBUG_L2) 2039 if (*debug & DEBUG_L2)
1992 l2m_debug(&l2->l2m, "l2 unknown pr %04x", 2040 l2m_debug(&l2->l2m, "l2 unknown pr %04x",
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
1294mgr_bcast(struct mISDNchannel *ch, struct sk_buff *skb) 1294mgr_bcast(struct mISDNchannel *ch, struct sk_buff *skb)
1295{ 1295{
1296 struct manager *mgr = container_of(ch, struct manager, bcast); 1296 struct manager *mgr = container_of(ch, struct manager, bcast);
1297 struct mISDNhead *hh = mISDN_HEAD_P(skb); 1297 struct mISDNhead *hhc, *hh = mISDN_HEAD_P(skb);
1298 struct sk_buff *cskb = NULL; 1298 struct sk_buff *cskb = NULL;
1299 struct layer2 *l2; 1299 struct layer2 *l2;
1300 u_long flags; 1300 u_long flags;
@@ -1309,10 +1309,17 @@ mgr_bcast(struct mISDNchannel *ch, struct sk_buff *skb)
1309 skb = NULL; 1309 skb = NULL;
1310 } else { 1310 } else {
1311 if (!cskb) 1311 if (!cskb)
1312 cskb = skb_copy(skb, GFP_KERNEL); 1312 cskb = skb_copy(skb, GFP_ATOMIC);
1313 } 1313 }
1314 if (cskb) { 1314 if (cskb) {
1315 ret = l2->ch.send(&l2->ch, cskb); 1315 hhc = mISDN_HEAD_P(cskb);
1316 /* save original header behind normal header */
1317 hhc++;
1318 *hhc = *hh;
1319 hhc--;
1320 hhc->prim = DL_INTERN_MSG;
1321 hhc->id = l2->ch.nr;
1322 ret = ch->st->own.recv(&ch->st->own, cskb);
1316 if (ret) { 1323 if (ret) {
1317 if (*debug & DEBUG_SEND_ERR) 1324 if (*debug & DEBUG_SEND_ERR)
1318 printk(KERN_DEBUG 1325 printk(KERN_DEBUG
diff --git a/include/linux/mISDNif.h b/include/linux/mISDNif.h
index b5e7f2202484..b80f7648562a 100644
--- a/include/linux/mISDNif.h
+++ b/include/linux/mISDNif.h
@@ -37,7 +37,7 @@
37 */ 37 */
38#define MISDN_MAJOR_VERSION 1 38#define MISDN_MAJOR_VERSION 1
39#define MISDN_MINOR_VERSION 1 39#define MISDN_MINOR_VERSION 1
40#define MISDN_RELEASE 21 40#define MISDN_RELEASE 26
41 41
42/* primitives for information exchange 42/* primitives for information exchange
43 * generell format 43 * generell format
@@ -115,6 +115,11 @@
115#define MDL_ERROR_IND 0x1F04 115#define MDL_ERROR_IND 0x1F04
116#define MDL_ERROR_RSP 0x5F04 116#define MDL_ERROR_RSP 0x5F04
117 117
118/* intern layer 2 */
119#define DL_TIMER200_IND 0x7004
120#define DL_TIMER203_IND 0x7304
121#define DL_INTERN_MSG 0x7804
122
118/* DL_INFORMATION_IND types */ 123/* DL_INFORMATION_IND types */
119#define DL_INFO_L2_CONNECT 0x0001 124#define DL_INFO_L2_CONNECT 0x0001
120#define DL_INFO_L2_REMOVED 0x0002 125#define DL_INFO_L2_REMOVED 0x0002