diff options
author | Karsten Keil <isdn@linux-pingi.de> | 2012-05-04 00:15:32 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-05-04 11:54:27 -0400 |
commit | 8423e6b212a19d5f02232855dec73196297b5ee9 (patch) | |
tree | bb244d8d7743d2c078fe817d25a3ae4a37ca3d39 | |
parent | 7ed80fe45d42678fb234bf9d18de6a98cfa9830d (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.c | 58 | ||||
-rw-r--r-- | drivers/isdn/mISDN/tei.c | 13 | ||||
-rw-r--r-- | include/linux/mISDNif.h | 7 |
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 | ||
283 | static void | ||
284 | l2_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 | |||
279 | static int | 308 | static int |
280 | l2mgr(struct layer2 *l2, u_int prim, void *arg) { | 309 | l2mgr(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 | |||
1294 | mgr_bcast(struct mISDNchannel *ch, struct sk_buff *skb) | 1294 | mgr_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 |