From 865dfe93b2b7faca36d7d30e59af4f5554638f41 Mon Sep 17 00:00:00 2001 From: Karsten Keil Date: Mon, 30 May 2005 16:42:28 +0000 Subject: [PATCH] add support for cloned stacks messages queues can be temporary stopped now some cleanups --- drivers/isdn/hardware/mISDN/contr.c | 11 +- drivers/isdn/hardware/mISDN/core.c | 4 + drivers/isdn/hardware/mISDN/core.h | 6 +- drivers/isdn/hardware/mISDN/debug.h | 4 + drivers/isdn/hardware/mISDN/dtmf.c | 3 +- drivers/isdn/hardware/mISDN/hfc_pci.c | 10 +- drivers/isdn/hardware/mISDN/isar.c | 4 +- drivers/isdn/hardware/mISDN/l3_udss1.c | 6 +- drivers/isdn/hardware/mISDN/layer1.c | 2 +- drivers/isdn/hardware/mISDN/layer2.c | 37 +++-- drivers/isdn/hardware/mISDN/sedl_fax.c | 28 ++-- drivers/isdn/hardware/mISDN/stack.c | 181 +++++++++++++++++++++---- drivers/isdn/hardware/mISDN/udevice.c | 125 +++++++++++++---- drivers/isdn/hardware/mISDN/x25_dte.c | 2 +- include/linux/mISDNif.h | 52 ++++--- 15 files changed, 354 insertions(+), 121 deletions(-) diff --git a/drivers/isdn/hardware/mISDN/contr.c b/drivers/isdn/hardware/mISDN/contr.c index 57fccd4..665203f 100644 --- a/drivers/isdn/hardware/mISDN/contr.c +++ b/drivers/isdn/hardware/mISDN/contr.c @@ -577,9 +577,8 @@ ControllerConstr(Controller_t **contr_p, mISDNstack_t *st, mISDN_pid_t *pid, mIS ControllerDestr(contr); return -ENOMEM; } - // FIXME ??? - contr->addr = st->id; - sprintf(contr->inst.name, "CAPI %d", st->id); + contr->addr = (st->id >> 8) & 0xff; + sprintf(contr->inst.name, "CAPI %d", contr->addr); mISDN_init_instance(&contr->inst, ocapi, contr, ControllerL3L4); if (!mISDN_SetHandledPID(ocapi, &contr->inst.pid)) { int_error(); @@ -613,14 +612,14 @@ ControllerConstr(Controller_t **contr_p, mISDNstack_t *st, mISDN_pid_t *pid, mIS { char tmp[10]; - sprintf(tmp, "mISDN%d", st->id); + sprintf(tmp, "mISDN%d", (st->id >> 8) & 0xff); contr->ctrl = cdrv_if->attach_ctr(&mISDN_driver, tmp, contr); if (!contr->ctrl) retval = -ENODEV; } #else contr->ctrl->owner = THIS_MODULE; - sprintf(contr->ctrl->name, "mISDN%d", st->id); + sprintf(contr->ctrl->name, "mISDN%d", contr->addr); contr->ctrl->driver_name = "mISDN"; contr->ctrl->driverdata = contr; contr->ctrl->register_appl = RegisterApplication; @@ -633,6 +632,8 @@ ControllerConstr(Controller_t **contr_p, mISDNstack_t *st, mISDN_pid_t *pid, mIS retval = attach_capi_ctr(contr->ctrl); #endif if (!retval) { + printk(KERN_DEBUG "contr->addr(%02x) cnr(%02x) st(%08x)\n", + contr->addr, contr->ctrl->cnr, st->id); contr->addr = contr->ctrl->cnr; plciInit(contr); ocapi->ctrl(st, MGR_REGLAYER | INDICATION, &contr->inst); diff --git a/drivers/isdn/hardware/mISDN/core.c b/drivers/isdn/hardware/mISDN/core.c index 662a531..e88949f 100644 --- a/drivers/isdn/hardware/mISDN/core.c +++ b/drivers/isdn/hardware/mISDN/core.c @@ -578,6 +578,10 @@ static int central_manager(void *data, u_int prim, void *arg) { return(release_stack(st)); case MGR_SELCHANNEL | REQUEST: return(sel_channel(st, arg)); + case MGR_STOPSTACK | REQUEST: + return(mISDN_start_stop(st, 0)); + case MGR_STARTSTACK | REQUEST: + return(mISDN_start_stop(st, 1)); #ifdef FIXME case MGR_ADDIF | REQUEST: return(add_if(data, prim, arg)); diff --git a/drivers/isdn/hardware/mISDN/core.h b/drivers/isdn/hardware/mISDN/core.h index c21e7e4..f472bf0 100644 --- a/drivers/isdn/hardware/mISDN/core.h +++ b/drivers/isdn/hardware/mISDN/core.h @@ -19,7 +19,10 @@ /* debugging */ #define DEBUG_CORE_FUNC 0x0001 -#define DEBUG_DUMMY_FUNC 0x0002 +//#define DEBUG_DUMMY_FUNC 0x0002 +#define DEBUG_MSG_THREAD_ERR 0x0010 +#define DEBUG_MSG_THREAD_INFO 0x0020 +#define DEBUG_QUEUE_FUNC 0x0040 #define DEBUG_DEV_OP 0x0100 #define DEBUG_MGR_FUNC 0x0200 #define DEBUG_DEV_TIMER 0x0400 @@ -42,6 +45,7 @@ extern void get_stack_info(struct sk_buff *); extern int get_stack_cnt(void); extern mISDNstack_t *get_stack4id(u_int); extern mISDNstack_t *new_stack(mISDNstack_t *, mISDNinstance_t *); +extern int mISDN_start_stop(mISDNstack_t *, int); extern int release_stack(mISDNstack_t *); extern int do_for_all_layers(void *, u_int, void *); extern int change_stack_para(mISDNstack_t *, u_int, mISDN_stPara_t *); diff --git a/drivers/isdn/hardware/mISDN/debug.h b/drivers/isdn/hardware/mISDN/debug.h index 4bc155e..59342b2 100644 --- a/drivers/isdn/hardware/mISDN/debug.h +++ b/drivers/isdn/hardware/mISDN/debug.h @@ -5,9 +5,13 @@ * This file is (c) under GNU PUBLIC LICENSE * */ +#ifndef MISDN_DEBUG_H + +#define MISDN_DEBUG_MANAGER 0x10000 extern void vmISDN_debug(int id, char *head, char *fmt, va_list args); extern void mISDN_debug(int id, char *head, char *fmt, ...); extern char * mISDN_getrev(const char *revision); extern void mISDN_debugprint(mISDNinstance_t *inst, char *fmt, ...); extern int mISDN_QuickHex(char *, u_char *, int); +#endif diff --git a/drivers/isdn/hardware/mISDN/dtmf.c b/drivers/isdn/hardware/mISDN/dtmf.c index 1340d42..d61048d 100644 --- a/drivers/isdn/hardware/mISDN/dtmf.c +++ b/drivers/isdn/hardware/mISDN/dtmf.c @@ -583,9 +583,10 @@ dtmf_manager(void *data, u_int prim, void *arg) { } switch(prim) { case MGR_CLRSTPARA | INDICATION: - case MGR_CLONELAYER | REQUEST: break; #ifdef OBSOLATE + case MGR_CLONELAYER | REQUEST: + break; case MGR_CONNECT | REQUEST: return(mISDN_ConnectIF(inst, arg)); case MGR_SETIF | REQUEST: diff --git a/drivers/isdn/hardware/mISDN/hfc_pci.c b/drivers/isdn/hardware/mISDN/hfc_pci.c index e56d06d..df9a8d2 100644 --- a/drivers/isdn/hardware/mISDN/hfc_pci.c +++ b/drivers/isdn/hardware/mISDN/hfc_pci.c @@ -1929,7 +1929,7 @@ hfcpci_l2l1(mISDNinstance_t *inst, struct sk_buff *skb) return(mISDN_queueup_newhead(inst, 0, hh->prim | CONFIRM, ret, skb)); } else if ((hh->prim == (PH_DEACTIVATE | REQUEST)) || (hh->prim == (DL_RELEASE | REQUEST)) || - (hh->prim == (MGR_DISCONNECT | REQUEST))) { + ((hh->prim == (PH_CONTROL | REQUEST) && (hh->dinfo == HW_DEACTIVATE)))) { bch->inst.lock(hc, 0); if (test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag)) { dev_kfree_skb(bch->next_skb); @@ -1940,7 +1940,7 @@ hfcpci_l2l1(mISDNinstance_t *inst, struct sk_buff *skb) test_and_clear_bit(BC_FLG_ACTIV, &bch->Flag); bch->inst.unlock(hc); skb_trim(skb, 0); - if (hh->prim != (MGR_DISCONNECT | REQUEST)) { + if (hh->prim != (PH_CONTROL | REQUEST)) { #ifdef FIXME if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_RAWDEV) if (bch->dev) @@ -2360,8 +2360,8 @@ HFC_manager(void *data, u_int prim, void *arg) { dev_kfree_skb(skb); } } else { - if ((skb = create_link_skb(MGR_DISCONNECT | REQUEST, - 0, 0, NULL, 0))) { + if ((skb = create_link_skb(PH_CONTROL | REQUEST, + HW_DEACTIVATE, 0, NULL, 0))) { if (hfcpci_l2l1(inst, skb)) dev_kfree_skb(skb); } @@ -2574,6 +2574,7 @@ static int __init HFC_init(void) } dst = card->dch.inst.st; } + HFC_obj.ctrl(dst, MGR_STOPSTACK | REQUEST, NULL); for (i = 0; i < 2; i++) { if ((err = HFC_obj.ctrl(dst, MGR_NEWSTACK | REQUEST, &card->bch[i].inst))) { @@ -2609,6 +2610,7 @@ static int __init HFC_init(void) err = 0; return(err); } + HFC_obj.ctrl(dst, MGR_STARTSTACK | REQUEST, NULL); HFC_obj.ctrl(dst, MGR_CTRLREADY | INDICATION, NULL); } printk(KERN_INFO "HFC %d cards installed\n", HFC_cnt); diff --git a/drivers/isdn/hardware/mISDN/isar.c b/drivers/isdn/hardware/mISDN/isar.c index 560ab2a..f6375f6 100644 --- a/drivers/isdn/hardware/mISDN/isar.c +++ b/drivers/isdn/hardware/mISDN/isar.c @@ -1645,7 +1645,7 @@ isar_down(mISDNinstance_t *inst, struct sk_buff *skb) return(mISDN_queueup_newhead(inst, 0, hh->prim | CONFIRM, ret, skb)); } else if ((hh->prim == (PH_DEACTIVATE | REQUEST)) || (hh->prim == (DL_RELEASE | REQUEST)) || - (hh->prim == (MGR_DISCONNECT | REQUEST))) { + ((hh->prim == (PH_CONTROL | REQUEST) && (hh->dinfo == HW_DEACTIVATE)))) { bch->inst.lock(bch->inst.privat, 0); if (test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag)) { dev_kfree_skb(bch->next_skb); @@ -1656,7 +1656,7 @@ isar_down(mISDNinstance_t *inst, struct sk_buff *skb) test_and_clear_bit(BC_FLG_ACTIV, &bch->Flag); bch->inst.unlock(bch->inst.privat); skb_trim(skb, 0); - if (hh->prim != (MGR_DISCONNECT | REQUEST)) + if (hh->prim != (PH_CONTROL | REQUEST)) if (!mISDN_queueup_newhead(inst, 0, hh->prim | CONFIRM, 0, skb)) return(0); } else if (hh->prim == (PH_CONTROL | REQUEST)) { diff --git a/drivers/isdn/hardware/mISDN/l3_udss1.c b/drivers/isdn/hardware/mISDN/l3_udss1.c index e82db2e..77857e1 100644 --- a/drivers/isdn/hardware/mISDN/l3_udss1.c +++ b/drivers/isdn/hardware/mISDN/l3_udss1.c @@ -2313,7 +2313,7 @@ new_udss1(mISDNstack_t *st, mISDN_pid_t *pid) nl3->dummy->l3 = nl3; nl3->dummy->t303skb = NULL; L3InitTimer(nl3->dummy, &nl3->dummy->timer); - sprintf(nl3->inst.name, "DSS1 %d", st->id); + sprintf(nl3->inst.name, "DSS1 %x", st->id >> 8); nl3->p_mgr = dss1man; list_add_tail(&nl3->list, &u_dss1.ilist); err = u_dss1.ctrl(&nl3->inst, MGR_NEWENTITY | REQUEST, NULL); @@ -2354,7 +2354,7 @@ udss1_manager(void *data, u_int prim, void *arg) { mISDNinstance_t *inst = data; layer3_t *l3l; - if (debug & 0x1000) + if (debug & MISDN_DEBUG_MANAGER) printk(KERN_DEBUG "udss1_manager data:%p prim:%x arg:%p\n", data, prim, arg); if (!data) return(-EINVAL); @@ -2391,7 +2391,7 @@ udss1_manager(void *data, u_int prim, void *arg) { #endif case MGR_RELEASE | INDICATION: case MGR_UNREGLAYER | REQUEST: - if (debug & 0x1000) + if (debug & MISDN_DEBUG_MANAGER) printk(KERN_DEBUG "release_udss1 id %x\n", l3l->inst.st->id); release_udss1(l3l); break; diff --git a/drivers/isdn/hardware/mISDN/layer1.c b/drivers/isdn/hardware/mISDN/layer1.c index 32774dd..44e73bf 100644 --- a/drivers/isdn/hardware/mISDN/layer1.c +++ b/drivers/isdn/hardware/mISDN/layer1.c @@ -648,7 +648,7 @@ new_l1(mISDNstack_t *st, mISDN_pid_t *pid) { } switch(pid->protocol[1]) { case ISDN_PID_L1_TE_S0: - sprintf(nl1->inst.name, "l1TES0 %d", st->id); + sprintf(nl1->inst.name, "l1TES0 %x", st->id >> 8); nl1->l1m.fsm = &l1fsm_s; nl1->l1m.state = ST_L1_F3; nl1->Flags = 0; diff --git a/drivers/isdn/hardware/mISDN/layer2.c b/drivers/isdn/hardware/mISDN/layer2.c index 3106efe..3dd55b4 100644 --- a/drivers/isdn/hardware/mISDN/layer2.c +++ b/drivers/isdn/hardware/mISDN/layer2.c @@ -187,10 +187,12 @@ l2down_create(layer2_t *l2, u_int prim, int dinfo, int len, void *arg) return(err); } +#ifdef OBSOLATE static int l2_chain_down(mISDNinstance_t *inst, struct sk_buff *skb) { return(l2down_raw(inst->privat, skb)); } +#endif static int ph_data_confirm(mISDNinstance_t *inst, mISDN_head_t *hh, struct sk_buff *skb) { @@ -1833,15 +1835,24 @@ ph_data_indication(layer2_t *l2, mISDN_head_t *hh, struct sk_buff *skb) { } psapi >>= 2; ptei >>= 1; - if ((psapi != l2->sapi) && (psapi != TEI_SAPI)) - return(ret); + if ((psapi != l2->sapi) && (psapi != TEI_SAPI)) { + /* not our bussiness */ + printk(KERN_DEBUG "%s: sapi %d/%d sapi mismatch\n", __FUNCTION__, + psapi, l2->sapi); + dev_kfree_skb(skb); + return(0); + } if (ptei == GROUP_TEI) { if (psapi == TEI_SAPI) { hh->prim = MDL_UNITDATA | INDICATION; return(l2_tei(l2->tm, skb)); } } else if ((ptei != l2->tei) || (psapi == TEI_SAPI)) { - return(ret); + /* not our bussiness */ + printk(KERN_DEBUG "%s: tei %d/%d sapi %d mismatch\n", __FUNCTION__, + ptei, l2->tei, psapi); + dev_kfree_skb(skb); + return(0); } } else datap += l; @@ -1966,6 +1977,8 @@ static int l2from_up(layer2_t *l2, struct sk_buff *skb, mISDN_head_t *hh) { int ret = -EINVAL; + if (hh->addr & FLG_MSG_CLONED) + return(l2down_raw(l2, skb)); switch (hh->prim) { case (DL_DATA | REQUEST): ret = mISDN_FsmEvent(&l2->l2m, EV_L2_DL_DATA, skb); @@ -2135,7 +2148,7 @@ release_l2(layer2_t *l2) } static int -new_l2(mISDNstack_t *st, mISDN_pid_t *pid, layer2_t **newl2) { +new_l2(mISDNstack_t *st, mISDN_pid_t *pid) { layer2_t *nl2; int err; u_char *p; @@ -2160,7 +2173,7 @@ new_l2(mISDNstack_t *st, mISDN_pid_t *pid, layer2_t **newl2) { } switch(pid->protocol[2] & ~ISDN_PID_FEATURE_MASK) { case ISDN_PID_L2_LAPD_NET: - sprintf(nl2->inst.name, "lapdn %x", st->id); + sprintf(nl2->inst.name, "lapdn %x", st->id>>8); test_and_set_bit(FLG_LAPD, &nl2->flag); test_and_set_bit(FLG_LAPD_NET, &nl2->flag); test_and_set_bit(FLG_FIXED_TEI, &nl2->flag); @@ -2178,7 +2191,7 @@ new_l2(mISDNstack_t *st, mISDN_pid_t *pid, layer2_t **newl2) { } break; case ISDN_PID_L2_LAPD: - sprintf(nl2->inst.name, "lapd %x", st->id); + sprintf(nl2->inst.name, "lapd %x", st->id>>8); test_and_set_bit(FLG_LAPD, &nl2->flag); test_and_set_bit(FLG_MOD128, &nl2->flag); test_and_set_bit(FLG_ORIG, &nl2->flag); @@ -2201,7 +2214,7 @@ new_l2(mISDNstack_t *st, mISDN_pid_t *pid, layer2_t **newl2) { break; case ISDN_PID_L2_B_X75SLP: test_and_set_bit(FLG_LAPB, &nl2->flag); - sprintf(nl2->inst.name, "lapb %x", st->id); + sprintf(nl2->inst.name, "lapb %x", st->id >> 8); nl2->window = 7; nl2->maxlen = MAX_DATA_SIZE; nl2->T200 = 1000; @@ -2272,11 +2285,10 @@ new_l2(mISDNstack_t *st, mISDN_pid_t *pid, layer2_t **newl2) { stp.down_headerlen = l2headersize(nl2, 0); isdnl2.ctrl(st, MGR_ADDSTPARA | REQUEST, &stp); } - if (newl2) - *newl2 = nl2; return(err); } +#ifdef OBSOLATE static int clone_l2(layer2_t *l2, mISDNinstance_t **new_ip) { int err; @@ -2295,7 +2307,6 @@ clone_l2(layer2_t *l2, mISDNinstance_t **new_ip) { printk(KERN_ERR "clone l2 failed err(%d)\n", err); return(err); } -#ifdef FIXME nl2->cloneif = nif; nif->func = l2from_down; nif->fdata = nl2; @@ -2311,10 +2322,10 @@ clone_l2(layer2_t *l2, mISDNinstance_t **new_ip) { nl2->inst.down.func = l2_chain_down; nl2->inst.down.fdata = l2; nl2->inst.down.stat = IF_UP; -#endif *new_ip = &nl2->inst; return(err); } +#endif static int l2_status(layer2_t *l2, status_info_l2_t *si) @@ -2383,7 +2394,7 @@ l2_manager(void *data, u_int prim, void *arg) { } } if (prim == (MGR_NEWLAYER | REQUEST)) - return(new_l2(data, arg, NULL)); + return(new_l2(data, arg)); if (err) { if (debug & 0x1) printk(KERN_WARNING "l2_manager prim(%x) l2 no instance\n", prim); @@ -2398,9 +2409,9 @@ l2_manager(void *data, u_int prim, void *arg) { l2l->maxlen = ((mISDN_stPara_t *)arg)->maxdatalen; case MGR_CLRSTPARA | INDICATION: break; +#ifdef OBSOLATE case MGR_CLONELAYER | REQUEST: return(clone_l2(l2l, arg)); -#ifdef OBSOLATE case MGR_CONNECT | REQUEST: return(mISDN_ConnectIF(inst, arg)); case MGR_SETIF | REQUEST: diff --git a/drivers/isdn/hardware/mISDN/sedl_fax.c b/drivers/isdn/hardware/mISDN/sedl_fax.c index 0df98f1..ab8cf5d 100644 --- a/drivers/isdn/hardware/mISDN/sedl_fax.c +++ b/drivers/isdn/hardware/mISDN/sedl_fax.c @@ -543,8 +543,8 @@ setup_speedfax(sedl_fax *sf) sf->bch[1].Write_Reg = &WriteISAR; lock_dev(sf, 0); #ifdef SPIN_DEBUG - printk(KERN_ERR "spin_lock_adr=%p now(%p)\n", &sf->lock.spin_adr, sf->lock.spin_adr); - printk(KERN_ERR "busy_lock_adr=%p now(%p)\n", &sf->lock.busy_adr, sf->lock.busy_adr); + printk(KERN_DEBUG "spin_lock_adr=%p now(%p)\n", &sf->lock.spin_adr, sf->lock.spin_adr); + printk(KERN_DEBUG "busy_lock_adr=%p now(%p)\n", &sf->lock.busy_adr, sf->lock.busy_adr); #endif writereg(sf->addr, sf->isar, ISAR_IRQBIT, 0); writereg(sf->addr, sf->isac, ISAC_MASK, 0xFF); @@ -606,8 +606,9 @@ speedfax_manager(void *data, u_int prim, void *arg) { int channel = -1; struct sk_buff *skb; - printk(KERN_DEBUG "%s: data:%p prim:%x arg:%p\n", - __FUNCTION__, data, prim, arg); + if (debug & MISDN_DEBUG_MANAGER) + printk(KERN_DEBUG "%s: data:%p prim:%x arg:%p\n", + __FUNCTION__, data, prim, arg); if (!data) { MGR_HASPROTOCOL_HANDLER(prim,arg,&speedfax) printk(KERN_ERR "speedfax_manager no data prim %x arg %p\n", @@ -641,22 +642,17 @@ speedfax_manager(void *data, u_int prim, void *arg) { bch_set_para(&card->bch[channel], &inst->st->para); break; case MGR_UNREGLAYER | REQUEST: - if (channel == 2) { -// inst->down.fdata = &card->dch; - if ((skb = create_link_skb(PH_CONTROL | REQUEST, - HW_DEACTIVATE, 0, NULL, 0))) { + if ((skb = create_link_skb(PH_CONTROL | REQUEST, + HW_DEACTIVATE, 0, NULL, 0))) { + if (channel == 2) { if (mISDN_ISAC_l1hw(inst, skb)) dev_kfree_skb(skb); - } - } else { -// inst->down.fdata = &card->bch[channel]; - if ((skb = create_link_skb(MGR_DISCONNECT | REQUEST, - 0, 0, NULL, 0))) { + } else { if (isar_down(inst, skb)) dev_kfree_skb(skb); } - } -// speedfax.ctrl(inst->up.peer, MGR_DISCONNECT | REQUEST, &inst->up); + } else + printk(KERN_WARNING "no SKB in %s MGR_UNREGLAYER | REQUEST\n", __FUNCTION__); speedfax.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL); break; case MGR_CLRSTPARA | INDICATION: @@ -774,6 +770,7 @@ static int __devinit setup_instance(sedl_fax *card) release_card(card); return(err); } + speedfax.ctrl(card->dch.inst.st, MGR_STOPSTACK | REQUEST, NULL); for (i=0; i<2; i++) { err = speedfax.ctrl(card->dch.inst.st, MGR_NEWSTACK | REQUEST, &card->bch[i].inst); if (err) { @@ -793,6 +790,7 @@ static int __devinit setup_instance(sedl_fax *card) speedfax.ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL); return(err); } + speedfax.ctrl(card->dch.inst.st, MGR_STARTSTACK | REQUEST, NULL); printk(KERN_INFO "SpeedFax %d cards installed\n", sedl_cnt); return(0); } diff --git a/drivers/isdn/hardware/mISDN/stack.c b/drivers/isdn/hardware/mISDN/stack.c index d560815..5f78075 100644 --- a/drivers/isdn/hardware/mISDN/stack.c +++ b/drivers/isdn/hardware/mISDN/stack.c @@ -45,7 +45,9 @@ get_stack_info(struct sk_buff *skb) } } else st = get_stack4id(hp->addr); - printk(KERN_DEBUG "%s: addr(%08x) st(%p)\n", __FUNCTION__, hp->addr, st); + if (core_debug & DEBUG_CORE_FUNC) + printk(KERN_DEBUG "%s: addr(%08x) st(%p) id(%08x)\n", __FUNCTION__, hp->addr, st, + st ? st->id : 0); if (!st) { hp->len = -ENODEV; return; @@ -60,6 +62,14 @@ get_stack_info(struct sk_buff *skb) si->mgr = 0; memcpy(&si->pid, &st->pid, sizeof(mISDN_pid_t)); memcpy(&si->para, &st->para, sizeof(mISDN_stPara_t)); + if (st->clone) + si->clone = st->clone->id; + else + si->clone = 0; + if (st->master) + si->master = st->master->id; + else + si->master = 0; si->instcnt = 0; for (i = 0; i <= MAX_LAYER_NR; i++) { if (st->i_array[i]) { @@ -103,11 +113,13 @@ get_free_stackid(mISDNstack_t *mst, int flag) while(id < CLONE_ID_MAX) { found = 0; id += CLONE_ID_INC; - list_for_each_entry(st, &mISDN_stacklist, list) { + st = mst->clone; + while (st) { if (st->id == id) { found++; break; } + st = st->clone; } if (!found) return(id); @@ -142,9 +154,19 @@ get_stack4id(u_int id) list_for_each_entry(st, &mISDN_stacklist, list) { if (id == st->id) return(st); - list_for_each_entry(cst, &st->childlist, list) { - if (cst->id == id) - return(cst); + if ((id & FLG_CHILD_STACK) && ((id & MASTER_ID_MASK) == st->id)) { + list_for_each_entry(cst, &st->childlist, list) { + if (cst->id == id) + return(cst); + } + } + if ((id & FLG_CLONE_STACK) && ((id & MASTER_ID_MASK) == st->id)) { + cst = st->clone; + while (cst) { + if (cst->id == id) + return(cst); + cst = cst->clone; + } } } return(NULL); @@ -172,19 +194,19 @@ get_nextlayer(mISDNstack_t *st, u_int addr) mISDNinstance_t *inst=NULL; int layer = addr & LAYER_ID_MASK; - if (core_debug & DEBUG_CORE_FUNC) - printk(KERN_DEBUG "%s: st(%08x) addr(%08x)\n", __FUNCTION__, st->id, addr); - if (!(addr & FLG_MSG_TARGET)) { switch(addr & MSG_DIR_MASK) { case FLG_MSG_DOWN: if (addr & FLG_MSG_CLONED) { - + /* OK */ } else layer -= LAYER_ID_INC; break; case FLG_MSG_UP: - layer += LAYER_ID_INC; + if (addr & FLG_MSG_CLONED) { + /* OK */ + } else + layer += LAYER_ID_INC; break; case MSG_TO_OWNER: break; @@ -198,7 +220,9 @@ get_nextlayer(mISDNstack_t *st, u_int addr) return(NULL); } inst = st->i_array[layer]; - /* maybe more checks */ + if (core_debug & DEBUG_QUEUE_FUNC) + printk(KERN_DEBUG "%s: st(%08x) addr(%08x) -> inst(%08x)\n", + __FUNCTION__, st->id, addr, inst ? inst->id : 0); return(inst); } @@ -304,7 +328,7 @@ mISDN_queue_message(mISDNinstance_t *inst, u_int aflag, struct sk_buff *skb) mISDNstack_t *st = inst->st; u_int id; - if (core_debug & DEBUG_CORE_FUNC) + if (core_debug & DEBUG_QUEUE_FUNC) printk(KERN_DEBUG "%s(%08x, %x, prim(%x))\n", __FUNCTION__, inst->id, aflag, hh->prim); if (aflag & FLG_MSG_TARGET) { @@ -314,24 +338,31 @@ mISDN_queue_message(mISDNinstance_t *inst, u_int aflag, struct sk_buff *skb) } if ((aflag & MSG_DIR_MASK) == FLG_MSG_DOWN) { if (inst->parent) { - st = inst->parent->st; - id = id | FLG_MSG_CLONED; + inst = inst->parent; + st = inst->st; + id = (inst->id & INST_ID_MASK) | FLG_MSG_TARGET | FLG_MSG_CLONED | FLG_MSG_DOWN; } } if (!st) return(-EINVAL); if (st->id == 0 || test_bit(mISDN_STACK_ABORT, &st->status)) return(-EBUSY); + if (inst->id == 0) { /* instance is not initialised */ + if (!(aflag & FLG_MSG_TARGET)) { + id &= INST_ID_MASK; + id |= (st->id & INST_ID_MASK) | aflag | FLG_INSTANCE; + } + } if (test_bit(mISDN_STACK_KILLED, &st->status)) return(-EBUSY); - if (test_bit(mISDN_STACK_STOPPED, &st->status)) - return(-EBUSY); if ((st->id & STACK_ID_MASK) != (id & STACK_ID_MASK)) { - int_errtxt("stack id not match st(%08x) id(%08x)", st->id, id); + int_errtxt("stack id not match st(%08x) id(%08x) inst(%08x) aflag(%08x) prim(%x)", + st->id, id, inst->id, aflag, hh->prim); } hh->addr = id; skb_queue_tail(&st->msgq, skb); - wake_up_interruptible(&st->workq); + if (!test_bit(mISDN_STACK_STOPPED, &st->status)) + wake_up_interruptible(&st->workq); return(0); } @@ -363,12 +394,16 @@ mISDNStackd(void *data) printk(KERN_DEBUG "mISDNStackd started for id(%08x)\n", st->id); test_and_clear_bit(mISDN_STACK_INIT, &st->status); for (;;) { - struct sk_buff *skb; + struct sk_buff *skb, *c_skb; mISDN_head_t *hh; - while ((skb = skb_dequeue(&st->msgq))) { + while ((!test_bit(mISDN_STACK_STOPPED, &st->status)) && + ((skb = skb_dequeue(&st->msgq)))) { mISDNinstance_t *inst; +#ifdef MISDN_MSG_STATS + st->msg_cnt++; +#endif hh = mISDN_HEAD_P(skb); if ((hh->addr & MSG_DIR_MASK) == MSG_BROADCAST) { do_broadcast(st, skb); @@ -376,19 +411,50 @@ mISDNStackd(void *data) } inst = get_nextlayer(st, hh->addr); if (!inst) { - int_errtxt("%s: st(%08x) no instance for addr(%08x) prim(%x) dinfo(%x)", __FUNCTION__, - st->id, hh->addr, hh->prim, hh->dinfo); + if (core_debug & DEBUG_MSG_THREAD_ERR) + printk(KERN_DEBUG "%s: st(%08x) no instance for addr(%08x) prim(%x) dinfo(%x)\n", + __FUNCTION__, st->id, hh->addr, hh->prim, hh->dinfo); dev_kfree_skb(skb); continue; } + if (inst->clone && ((hh->addr & MSG_DIR_MASK) == FLG_MSG_UP)) { + u_int id = (inst->clone->id & INST_ID_MASK) | FLG_MSG_TARGET | FLG_MSG_CLONED | FLG_MSG_UP; + +#ifdef MISDN_MSG_STATS + st->clone_cnt++; +#endif + c_skb = skb_copy(skb, GFP_KERNEL); + if (c_skb) { + if (core_debug & DEBUG_MSG_THREAD_INFO) + printk(KERN_DEBUG "%s: inst(%08x) msg clone msg to(%08x) caddr(%08x) prim(%x)\n", + __FUNCTION__, inst->id, inst->clone->id, id, hh->prim); + err = mISDN_queue_message(inst->clone, id, c_skb); + if (err) { + if (core_debug & DEBUG_MSG_THREAD_ERR) + printk(KERN_DEBUG "%s: clone instance(%08x) cannot queue msg(%08x) err(%d)\n", + __FUNCTION__, inst->clone->id, id, err); + dev_kfree_skb(c_skb); + } + } else { + printk(KERN_WARNING "%s OOM on msg cloning inst(%08x) caddr(%08x) prim(%x) len(%d)\n", + __FUNCTION__, inst->id, id, hh->prim, skb->len); + } + } + if (core_debug & DEBUG_MSG_THREAD_INFO) + printk(KERN_DEBUG "%s: inst(%08x) msg call addr(%08x) prim(%x)\n", + __FUNCTION__, inst->id, hh->addr, hh->prim); if (!inst->function) { - int_errtxt("%s: instance(%08x) no function", __FUNCTION__, inst->id); + if (core_debug & DEBUG_MSG_THREAD_ERR) + printk(KERN_DEBUG "%s: instance(%08x) no function\n", + __FUNCTION__, inst->id); dev_kfree_skb(skb); continue; } err = inst->function(inst, skb); if (err) { - int_errtxt("%s: instance(%08x)->function return(%d)", __FUNCTION__, inst->id, err); + if (core_debug & DEBUG_MSG_THREAD_ERR) + printk(KERN_DEBUG "%s: instance(%08x)->function return(%d)\n", + __FUNCTION__, inst->id, err); dev_kfree_skb(skb); continue; } @@ -397,8 +463,22 @@ mISDNStackd(void *data) break; if (st->notify != NULL) up(st->notify); - interruptible_sleep_on(&st->workq); +#ifdef MISDN_MSG_STATS + st->sleep_cnt++; +#endif + wait_event_interruptible(st->workq, ((!skb_queue_empty(&st->msgq)) || + test_bit(mISDN_STACK_ABORT, &st->status))); + if (test_bit(mISDN_STACK_STOPPED, &st->status)) { + wait_event_interruptible(st->workq, (!test_bit(mISDN_STACK_STOPPED, &st->status))); +#ifdef MISDN_MSG_STATS + st->stopped_cnt++; +#endif + } } +#ifdef MISDN_MSG_STATS + printk(KERN_DEBUG "mISDNStackd daemon for id(%08x) proceed %d msg %d clone %d sleep %d stopped\n", + st->id, st->msg_cnt, st->clone_cnt, st->sleep_cnt, st->stopped_cnt); +#endif printk(KERN_DEBUG "mISDNStackd daemon for id(%08x) killed now\n", st->id); test_and_set_bit(mISDN_STACK_KILLED, &st->status); discard_queue(&st->msgq); @@ -421,6 +501,7 @@ new_stack(mISDNstack_t *master, mISDNinstance_t *inst) return(NULL); } memset(newst, 0, sizeof(mISDNstack_t)); + INIT_LIST_HEAD(&newst->list); INIT_LIST_HEAD(&newst->childlist); INIT_LIST_HEAD(&newst->prereg); init_waitqueue_head(&newst->workq); @@ -428,7 +509,13 @@ new_stack(mISDNstack_t *master, mISDNinstance_t *inst) test_and_set_bit(mISDN_STACK_INIT, &newst->status); if (!master) { if (inst && inst->st) { + master = inst->st; + while(master->clone) + master = master->clone; newst->id = get_free_stackid(inst->st, FLG_CLONE_STACK); + newst->master = master; + master->clone = newst; + master = NULL; } else { newst->id = get_free_stackid(NULL, 0); } @@ -438,17 +525,30 @@ new_stack(mISDNstack_t *master, mISDNinstance_t *inst) newst->mgr = inst; if (master) { list_add_tail(&newst->list, &master->childlist); - } else { + } else if (!(newst->id & FLG_CLONE_STACK)) { list_add_tail(&newst->list, &mISDN_stacklist); } if (core_debug & DEBUG_CORE_FUNC) printk(KERN_DEBUG "Stack id %x added\n", newst->id); - if (inst) + if (inst) { inst->st = newst; + } kernel_thread(mISDNStackd, (void *)newst, 0); return(newst); } +int +mISDN_start_stop(mISDNstack_t *st, int start) +{ + int ret; + + if (start) { + ret = test_and_clear_bit(mISDN_STACK_STOPPED, &st->status); + wake_up_interruptible(&st->workq); + } else + ret = test_and_set_bit(mISDN_STACK_STOPPED, &st->status); + return(ret); +} static int release_layers(mISDNstack_t *st, u_int prim) @@ -546,7 +646,7 @@ delete_stack(mISDNstack_t *st) if (st->thread) { st->notify = &sem; test_and_set_bit(mISDN_STACK_ABORT, &st->status); - wake_up_interruptible(&st->workq); + mISDN_start_stop(st, 1); down(&sem); st->notify = NULL; } @@ -572,7 +672,15 @@ release_stack(mISDNstack_t *st) { return(err); } } - + if (st->clone) { + st->clone->master = st->master; + } + if (st->master) { + st->master->clone = st->clone; + } else if (st->clone) { /* no master left -> delete clone too */ + delete_stack(st->clone); + st->clone = NULL; + } if ((err = delete_stack(st))) return(err); @@ -745,6 +853,19 @@ unregister_instance(mISDNinstance_t *inst) { if (inst->st && (inst->st->mgr != inst)) inst->st = NULL; } + if (inst->parent) { /*we are cloned */ + inst->parent->clone = inst->clone; + if (inst->clone) + inst->clone->parent = inst->parent; + inst->clone = NULL; + inst->parent = NULL; + } else if (inst->clone) { + /* deleting the top level master of a clone */ + /* FIXME: should be handled somehow, maybe unregister the clone */ + int_errtxt("removed master(%08x) of clone(%08x)", inst->id, inst->clone->id); + inst->clone->parent = NULL; + inst->clone = NULL; + } if (inst->list.prev && inst->list.next) list_del_init(&inst->list); else @@ -762,7 +883,7 @@ copy_pid(mISDN_pid_t *dpid, mISDN_pid_t *spid, u_char *pbuf) u_int i, off; memcpy(dpid, spid, sizeof(mISDN_pid_t)); - if (spid->pbuf) { + if (spid->pbuf && spid->maxplen) { if (!pbuf) { int_error(); return(-ENOMEM); diff --git a/drivers/isdn/hardware/mISDN/udevice.c b/drivers/isdn/hardware/mISDN/udevice.c index 7a07000..51ede39 100644 --- a/drivers/isdn/hardware/mISDN/udevice.c +++ b/drivers/isdn/hardware/mISDN/udevice.c @@ -375,13 +375,13 @@ create_layer(mISDNdevice_t *dev, struct sk_buff *skb) devicelayer_t *nl; mISDNobject_t *obj; mISDNinstance_t *inst = NULL; - mISDN_head_t *hp; + mISDN_head_t *hp; hp = mISDN_HEAD_P(skb); linfo = (layer_info_t *)skb->data; if (!(st = get_stack4id(linfo->st))) { /* should be changed */ - int_error(); + printk(KERN_WARNING "%s: no stack found for id(%08x)\n", __FUNCTION__, linfo->st); return(-ENODEV); } if (linfo->object_id != -1) { @@ -402,7 +402,64 @@ create_layer(mISDNdevice_t *dev, struct sk_buff *skb) printk(KERN_WARNING "%s: no inst found\n", __FUNCTION__); return(-EINVAL); } - } else if ((inst = getlayer4lay(st, linfo->pid.layermask))) { + } else if (linfo->extentions & EXT_INST_CLONE) { + mISDN_pid_t *pid; + + inst = get_instance4id(linfo->parent); + if (!inst) { + printk(KERN_WARNING "%s: no parent inst found\n", __FUNCTION__); + return(-EINVAL); + } + if (!(inst->extentions & EXT_INST_CLONE)) { + printk(KERN_WARNING "%s: inst(%08x) ext(%x) is not cloneable\n", + __FUNCTION__, inst->id, inst->extentions); + return(-ENOSYS); + } + for(i=0; i<=MAX_LAYER_NR; i++) + if (!st->i_array[i]) + break; + if (i > MAX_LAYER_NR) { + printk(KERN_WARNING "%s: no free instance slot in stack id(%08x)\n", + __FUNCTION__, st->id); + return(-EBUSY); + } + pid = kmalloc(sizeof(mISDN_pid_t), GFP_ATOMIC); + if (!pid) { + printk(KERN_ERR "kmalloc pid failed\n"); + return(-ENOMEM); + } + memset(pid, 0, sizeof(mISDN_pid_t)); + if (inst->pid.pbuf && inst->pid.maxplen) { + pid->pbuf = kmalloc(inst->pid.maxplen, GFP_ATOMIC); + if (!pid->pbuf) { + kfree(pid); + printk(KERN_ERR "kmalloc pid->pbuf failed\n"); + return(-ENOMEM); + } + memset(pid->pbuf, 0, inst->pid.maxplen); + } + copy_pid(pid, &inst->pid, pid->pbuf); + ret = inst->obj->own_ctrl(st, MGR_NEWLAYER | REQUEST, pid); + if (pid->pbuf) + kfree(pid->pbuf); + kfree(pid); + if (ret) { + printk(KERN_WARNING "%s: MGR_NEWLAYER | REQUEST for clone returns %d\n", __FUNCTION__, ret); + return(ret); + } + if (!st->i_array[i]) { + int_error(); + return(-EINVAL); + } else { + while (inst->clone) + inst = inst->clone; + inst->clone = st->i_array[i]; + st->i_array[i]->parent = inst; + inst = st->i_array[i]; + } + } +#if 0 + else if ((inst = getlayer4lay(st, linfo->pid.layermask))) { if (!(linfo->extentions & EXT_INST_MIDDLE)) { printk(KERN_WARNING "mISDN create_layer st(%x) LM(%x) inst not empty(%08x)\n", @@ -410,12 +467,15 @@ create_layer(mISDNdevice_t *dev, struct sk_buff *skb) return(-EBUSY); } } +#endif if (!(nl = kmalloc(sizeof(devicelayer_t), GFP_ATOMIC))) { printk(KERN_ERR "kmalloc devicelayer failed\n"); return(-ENOMEM); } memset(nl, 0, sizeof(devicelayer_t)); - if (st) + if (inst) + nl->id = get_new_devicelayer_id(dev, inst->id); + else if (st) nl->id = get_new_devicelayer_id(dev, st->id); else nl->id = get_new_devicelayer_id(dev, 0); @@ -426,36 +486,39 @@ create_layer(mISDNdevice_t *dev, struct sk_buff *skb) } if (device_debug & DEBUG_MGR_FUNC) printk(KERN_DEBUG - "mISDN create_layer LM(%x) nl(%p:%08x) nl inst(%p)\n", - linfo->pid.layermask, nl, nl->id, &nl->inst); + "mISDN create_layer LM(%x) nl(%p:%08x) nl->inst(%p) inst(%p)\n", + linfo->pid.layermask, nl, nl->id, &nl->inst, inst); nl->dev = dev; - mISDN_init_instance(&nl->inst, &udev_obj, nl, from_up_down); - memcpy(&nl->inst.pid, &linfo->pid, sizeof(mISDN_pid_t)); - strcpy(nl->inst.name, linfo->name); - nl->inst.extentions = linfo->extentions; - for (i=0; i<= MAX_LAYER_NR; i++) { - if (linfo->pid.layermask & ISDN_LAYER(i)) { - if (st && (st->pid.protocol[i] == ISDN_PID_NONE)) { - st->pid.protocol[i] = linfo->pid.protocol[i]; - nl->lm_st |= ISDN_LAYER(i); + list_add_tail(&nl->list, &dev->layerlist); + if (!inst) { + mISDN_init_instance(&nl->inst, &udev_obj, nl, from_up_down); + memcpy(&nl->inst.pid, &linfo->pid, sizeof(mISDN_pid_t)); + strcpy(nl->inst.name, linfo->name); + nl->inst.extentions = linfo->extentions; + for (i=0; i<= MAX_LAYER_NR; i++) { + if (linfo->pid.layermask & ISDN_LAYER(i)) { + if (st && (st->pid.protocol[i] == ISDN_PID_NONE)) { + st->pid.protocol[i] = linfo->pid.protocol[i]; + nl->lm_st |= ISDN_LAYER(i); + } } } + if (st && (linfo->extentions & EXT_INST_MGR)) { + st->mgr = &nl->inst; + test_and_set_bit(FLG_MGR_OWNSTACK, &nl->Flags); + } + if (st) + nl->inst.obj->ctrl(st, MGR_ADDLAYER | REQUEST, &nl->inst); + } else { + nl->slave = inst; + nl->inst.extentions |= EXT_INST_UNUSED; } - if (st && (linfo->extentions & EXT_INST_MGR)) { - st->mgr = &nl->inst; - test_and_set_bit(FLG_MGR_OWNSTACK, &nl->Flags); - } - list_add_tail(&nl->list, &dev->layerlist); - if (st) - nl->inst.obj->ctrl(st, MGR_ADDLAYER | REQUEST, &nl->inst); skb_trim(skb, 0); memcpy(skb_put(skb, sizeof(nl->id)), &nl->id, sizeof(nl->id)); - if (inst) { - nl->slave = inst; + if (inst) memcpy(skb_put(skb, sizeof(inst->id)), &inst->id, sizeof(inst->id)); - } else { + else memset(skb_put(skb, sizeof(nl->id)), 0, sizeof(nl->id)); - } return(8); } @@ -521,7 +584,9 @@ del_layer(devicelayer_t *dl) } dl->id = 0; list_del(&dl->list); - udev_obj.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL); + if (!(inst->extentions & EXT_INST_UNUSED)) { + udev_obj.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL); + } if (test_and_clear_bit(FLG_MGR_OWNSTACK, &dl->Flags)) { if (dl->inst.st) { del_stack(get_devstack(dev, dl->inst.st->id)); @@ -531,6 +596,7 @@ del_layer(devicelayer_t *dl) return(0); } +#ifdef OBSOLATE static mISDNinstance_t * clone_instance(devicelayer_t *dl, mISDNstack_t *st, mISDNinstance_t *peer) { @@ -556,7 +622,6 @@ clone_instance(devicelayer_t *dl, mISDNstack_t *st, mISDNinstance_t *peer) return(dl->slave); } -#ifdef OBSOLATE static int remove_if(devicelayer_t *dl, int stat) { mISDNif_t *hif,*phif,*shif; @@ -1046,6 +1111,10 @@ get_layer_info(struct sk_buff *skb) li->id = inst->id; if (inst->st) li->st = inst->st->id; + if (inst->parent) + li->parent = inst->parent->id; + if (inst->clone) + li->clone = inst->clone->id; memcpy(&li->pid, &inst->pid, sizeof(mISDN_pid_t)); hp->len = sizeof(layer_info_t); skb_put(skb, hp->len); diff --git a/drivers/isdn/hardware/mISDN/x25_dte.c b/drivers/isdn/hardware/mISDN/x25_dte.c index 37d432b..e3bc5cd 100644 --- a/drivers/isdn/hardware/mISDN/x25_dte.c +++ b/drivers/isdn/hardware/mISDN/x25_dte.c @@ -1300,9 +1300,9 @@ dte_manager(void *data, u_int prim, void *arg) { } break; case MGR_CLRSTPARA | INDICATION: +#ifdef OBSOLATE case MGR_CLONELAYER | REQUEST: break; -#ifdef OBSOLATE case MGR_CONNECT | REQUEST: return(mISDN_ConnectIF(inst, arg)); case MGR_SETIF | REQUEST: diff --git a/include/linux/mISDNif.h b/include/linux/mISDNif.h index bce732f..862b3ea 100644 --- a/include/linux/mISDNif.h +++ b/include/linux/mISDNif.h @@ -9,16 +9,6 @@ #include #include -/* primitives for information exchange - * generell format - * <8 bit reserved> - * <4 bit flags> - * <4 bit layer> - * <8 bit command> - * <8 bit subcommand> - * - */ - /* * ABI Version 32 bit * @@ -36,6 +26,19 @@ #define MISDN_REVISION "$Revision$" #define MISDN_DATE "$Date$" +/* collect some statistics about the message queues */ +#define MISDN_MSG_STATS + +/* primitives for information exchange + * generell format + * <8 bit reserved> + * <4 bit flags> + * <4 bit layer> + * <8 bit command> + * <8 bit subcommand> + * + */ + /* SUBCOMMANDS */ #define REQUEST 0x80 #define CONFIRM 0x81 @@ -66,15 +69,17 @@ #define MGR_GETLAYERID 0x0f2200 #define MGR_NEWLAYER 0x0f2300 #define MGR_DELLAYER 0x0f2400 -#define MGR_CLONELAYER 0x0f2500 +//#define MGR_CLONELAYER 0x0f2500 //#define MGR_GETIF 0x0f3100 //#define MGR_CONNECT 0x0f3200 -#define MGR_DISCONNECT 0x0f3300 +//#define MGR_DISCONNECT 0x0f3300 //#define MGR_SETIF 0x0f3400 //#define MGR_ADDIF 0x0f3500 //#define MGR_QUEUEIF 0x0f3600 #define MGR_CTRLREADY 0x0f4100 #define MGR_STACKREADY 0x0f4200 +#define MGR_STOPSTACK 0x0f4300 +#define MGR_STARTSTACK 0x0f4400 #define MGR_RELEASE 0x0f4500 #define MGR_GETDEVICE 0x0f5100 #define MGR_DELDEVICE 0x0f5200 @@ -498,15 +503,16 @@ #define CHANNEL_EXT_PCM 0x01000000 #define CHANNEL_EXT_REV 0x02000000 -/* interface extentions */ +/* instance/stack extentions */ #define EXT_STACK_CLONE 0x00000001 #define EXT_INST_CLONE 0x00000100 #define EXT_INST_MGR 0x00000200 #define EXT_INST_MIDDLE 0x00000400 -#define EXT_IF_CHAIN 0x00010000 -#define EXT_IF_EXCLUSIV 0x00020000 -#define EXT_IF_CREATE 0x00040000 -#define EXT_IF_SPLIT 0x00080000 +#define EXT_INST_UNUSED 0x00000800 +//#define EXT_IF_CHAIN 0x00010000 +//#define EXT_IF_EXCLUSIV 0x00020000 +//#define EXT_IF_CREATE 0x00040000 +//#define EXT_IF_SPLIT 0x00080000 /* stack status flag (bit position) */ #define mISDN_STACK_INIT 0 @@ -580,6 +586,8 @@ typedef struct _stack_info { mISDN_stPara_t para; u_int extentions; u_int mgr; + u_int master; + u_int clone; int instcnt; int inst[MAX_LAYER_NR +1]; int childcnt; @@ -592,6 +600,8 @@ typedef struct _layer_info { int extentions; u_int id; u_int st; + u_int clone; + u_int parent; mISDN_pid_t pid; } layer_info_t; @@ -765,9 +775,17 @@ struct _mISDNstack { struct semaphore *notify; wait_queue_head_t workq; struct sk_buff_head msgq; +#ifdef MISDN_MSG_STATS + u_int msg_cnt; + u_int sleep_cnt; + u_int clone_cnt; + u_int stopped_cnt; +#endif mISDNinstance_t *i_array[MAX_LAYER_NR + 1]; struct list_head prereg; mISDNinstance_t *mgr; + mISDNstack_t *master; + mISDNstack_t *clone; struct list_head childlist; };