add support for cloned stacks

messages queues can be temporary stopped now
some cleanups
This commit is contained in:
Karsten Keil 2005-05-30 16:42:28 +00:00
parent 9aa4b41d68
commit 865dfe93b2
15 changed files with 354 additions and 121 deletions

View File

@ -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);

View File

@ -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));

View File

@ -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 *);

View File

@ -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

View File

@ -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:

View File

@ -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);

View File

@ -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)) {

View File

@ -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;

View File

@ -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;

View File

@ -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:

View File

@ -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);
}

View File

@ -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);

View File

@ -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);

View File

@ -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:

View File

@ -9,16 +9,6 @@
#include <linux/types.h>
#include <linux/errno.h>
/* 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;
};