diff --git a/drivers/isdn/hardware/mISDN/l3_udss1.c b/drivers/isdn/hardware/mISDN/l3_udss1.c index 5838018..0b1f110 100644 --- a/drivers/isdn/hardware/mISDN/l3_udss1.c +++ b/drivers/isdn/hardware/mISDN/l3_udss1.c @@ -33,8 +33,12 @@ static int dss1man(l3_process_t *, u_int, void *); static void MsgStart(l3_process_t *pc, u_char mt) { pc->op = &pc->obuf[0]; *pc->op++ = 8; - *pc->op++ = 1; - *pc->op++ = pc->callref ^ 0x80; + if (pc->callref == -1) { /* dummy cr */ + *pc->op++ = 0; + } else { + *pc->op++ = 1; + *pc->op++ = pc->callref ^ 0x80; + } *pc->op++ = mt; } @@ -1748,12 +1752,6 @@ static struct stateentry downstatelist[] = CC_CONNECT | REQUEST, l3dss1_connect_req}, {SBIT(10), CC_SUSPEND | REQUEST, l3dss1_suspend_req}, -#if 0 - {SBIT(7) | SBIT(9) | SBIT(25), - CC_REDIR | REQUEST, l3dss1_redir_req}, - {SBIT(6), - CC_REDIR | REQUEST, l3dss1_redir_req_early}, -#endif }; #define DOWNSLLEN \ @@ -1957,17 +1955,9 @@ dss1_fromdown(hisaxif_t *hif, u_int prim, u_int nr, int dtyp, void *arg) { dev_kfree_skb(skb); return(0); } else if (cr == -1) { /* Dummy Callref */ -#if 0 - u_char *p; if (mt == MT_FACILITY) - if ((p = findie(skb->data, skb->len, IE_FACILITY, 0))) { - l3dss1_parse_facility(st, NULL, - (pr == (DL_DATA | INDICATION)) ? -1 : -2, p); - dev_kfree_skb(skb); - return(0); - } -#endif - if (l3->debug & L3_DEB_WARN) + l3dss1_facility(l3->dummy, prim, skb); + else if (l3->debug & L3_DEB_WARN) l3_debug(l3, "dss1up dummy Callref (no facility msg or ie)"); dev_kfree_skb(skb); return(0); @@ -2098,12 +2088,6 @@ dss1_fromup(hisaxif_t *hif, u_int prim, u_int nr, int dtyp, void *arg) { printk(KERN_ERR "HiSax dss1 fromup without proc pr=%04x\n", prim); return(-EINVAL); } -#if 0 - if ( pr == (CC_TDSS1_IO | REQUEST)) { - l3dss1_io_timer(proc); /* timer expires */ - return; - } -#endif for (i = 0; i < DOWNSLLEN; i++) if ((prim == downstatelist[i].primitive) && ((1 << proc->state) & downstatelist[i].state)) @@ -2213,6 +2197,19 @@ create_udss1(hisaxstack_t *st, hisaxif_t *hif) { nl3->global->l3 = nl3; L3InitTimer(nl3->global, &nl3->global->timer); } + if (!(nl3->dummy = kmalloc(sizeof(l3_process_t), GFP_ATOMIC))) { + printk(KERN_ERR "HiSax can't get memory for dss1 dummy CR\n"); + kfree(nl3->global); + kfree(nl3); + return(NULL); + } else { + nl3->dummy->state = 0; + nl3->dummy->callref = -1; + nl3->dummy->next = NULL; + nl3->dummy->n303 = N303; + nl3->dummy->l3 = nl3; + L3InitTimer(nl3->dummy, &nl3->dummy->timer); + } nl3->inst.protocol = hif->protocol; nl3->inst.obj = &u_dss1; nl3->inst.layer = hif->layer; diff --git a/drivers/isdn/hardware/mISDN/layer3.c b/drivers/isdn/hardware/mISDN/layer3.c index a39623a..f8b44e8 100644 --- a/drivers/isdn/hardware/mISDN/layer3.c +++ b/drivers/isdn/hardware/mISDN/layer3.c @@ -285,8 +285,18 @@ release_l3_process(l3_process_t *p) REMOVE_FROM_LISTBASE(p, l3->proc); StopAllL3Timer(p); kfree(p); - if (!l3->proc) - RELEASE(); + if (!l3->proc && !test_bit(FLG_PTP, &l3->Flag)) { + if (l3->debug) + l3_debug(l3, "release_l3_process: last process"); + if (!skb_queue_len(&l3->squeue)) { + if (l3->debug) + l3_debug(l3, "release_l3_process: release link"); + FsmEvent(&l3->l3m, EV_RELEASE_REQ, NULL); + } else { + if (l3->debug) + l3_debug(l3, "release_l3_process: not release link"); + } + } }; static void @@ -307,14 +317,17 @@ int hisax_l3up(l3_process_t *l3p, u_int prim, void *arg) { layer3_t *l3; hisaxif_t *up; + l3msg_t l3msg; int err = -EINVAL; if (!l3p) return(-EINVAL); l3 = l3p->l3; up = &l3->inst.up; + l3msg.id = l3p->id; + l3msg.arg = arg; if (up->func) - err = up->func(up, prim, l3->msgnr++, 0, arg); + err = up->func(up, prim, l3->msgnr++, DTYPE_L3MSGP, &l3msg); return(err); } @@ -491,6 +504,7 @@ init_l3(layer3_t *l3) { l3->proc = NULL; l3->global = NULL; + l3->dummy = NULL; skb_queue_head_init(&l3->squeue); l3->l3m.fsm = &l3fsm; l3->l3m.state = ST_L3_LC_REL; @@ -513,6 +527,11 @@ release_l3(layer3_t *l3) kfree(l3->global); l3->global = NULL; } + if (l3->dummy) { + StopAllL3Timer(l3->dummy); + kfree(l3->dummy); + l3->dummy = NULL; + } FsmDelTimer(&l3->l3m_timer, 54); discard_queue(&l3->squeue); } diff --git a/drivers/isdn/hardware/mISDN/layer3.h b/drivers/isdn/hardware/mISDN/layer3.h index c65a525..230317e 100644 --- a/drivers/isdn/hardware/mISDN/layer3.h +++ b/drivers/isdn/hardware/mISDN/layer3.h @@ -20,7 +20,8 @@ #define L3_DEB_CHECK 0x10 #define L3_DEB_SI 0x20 -#define FLG_L2BLOCK 1 +#define FLG_L2BLOCK 1 +#define FLG_PTP 2 typedef struct _cause { u_char len __attribute__ ((packed)); @@ -268,6 +269,7 @@ typedef struct _layer3 { struct FsmTimer l3m_timer; l3_process_t *proc; l3_process_t *global; + l3_process_t *dummy; int (*p_mgr)(l3_process_t *, u_int, void *); u_int id; int debug; diff --git a/include/linux/mISDNif.h b/include/linux/mISDNif.h index 857f335..c29a90e 100644 --- a/include/linux/mISDNif.h +++ b/include/linux/mISDNif.h @@ -206,6 +206,7 @@ #define IF_TYPE(i) ((i)->stat & IF_TYPEMASK) #define DTYPE_SKB -1 +#define DTYPE_L3MSGP -2 /* special packet type */ #define PACKET_NOACK 250 @@ -250,6 +251,11 @@ typedef struct _bsetup { u_int protocol[MAX_LAYER+1]; } bsetup_t; +typedef struct _l3msg_t { + int id; + void *arg; +} l3msg_t; + #ifdef __KERNEL__ typedef struct _hisaxobject {