use the common kernel list.h implementation for the lists in mISDN

This commit is contained in:
Karsten Keil 2004-06-17 12:31:14 +00:00
parent 818a365de2
commit 918caa4018
31 changed files with 797 additions and 858 deletions

View File

@ -130,8 +130,7 @@ typedef struct hdlc_hw {
typedef struct _fritzpnppci {
struct _fritzpnppci *prev;
struct _fritzpnppci *next;
struct list_head list;
void *pdev;
u_int type;
u_int irq;
@ -410,7 +409,8 @@ hdlc_empty_fifo(bchannel_t *bch, int count)
mISDN_debugprint(&bch->inst, "hdlc_empty_fifo: incoming packet too large");
return;
}
ptr = (u_int *) p = bch->rx_buf + bch->rx_idx;
p = bch->rx_buf + bch->rx_idx;
ptr = (u_int *)p;
bch->rx_idx += count;
if (fc->type == AVM_FRITZ_PCIV2) {
while (cnt < count) {
@ -1110,7 +1110,7 @@ release_card(fritzpnppci *card)
mISDN_free_dch(&card->dch);
fritz.ctrl(card->dch.inst.up.peer, MGR_DISCONNECT | REQUEST, &card->dch.inst.up);
fritz.ctrl(&card->dch.inst, MGR_UNREGLAYER | REQUEST, NULL);
REMOVE_FROM_LISTBASE(card, ((fritzpnppci *)fritz.ilist));
list_del(&card->list);
unlock_dev(card);
if (card->type == AVM_FRITZ_PNP) {
pnp_disable_dev(card->pdev);
@ -1124,7 +1124,7 @@ release_card(fritzpnppci *card)
static int
fritz_manager(void *data, u_int prim, void *arg) {
fritzpnppci *card = fritz.ilist;
fritzpnppci *card;
mISDNinstance_t *inst = data;
struct sk_buff *skb;
int channel = -1;
@ -1138,7 +1138,7 @@ fritz_manager(void *data, u_int prim, void *arg) {
__FUNCTION__, prim, arg);
return(-EINVAL);
}
while(card) {
list_for_each_entry(card, &fritz.ilist, list) {
if (&card->dch.inst == inst) {
channel = 2;
break;
@ -1151,7 +1151,6 @@ fritz_manager(void *data, u_int prim, void *arg) {
channel = 1;
break;
}
card = card->next;
}
if (channel<0) {
printk(KERN_WARNING "%s: no channel data %p prim %x arg %p\n",
@ -1245,7 +1244,7 @@ static int __devinit setup_instance(fritzpnppci *card)
int i, err;
mISDN_pid_t pid;
APPEND_TO_LIST(card, ((fritzpnppci *)fritz.ilist));
list_add_tail(&card->list, &fritz.ilist);
card->dch.debug = debug;
lock_HW_init(&card->lock);
card->dch.inst.lock = lock_dev;
@ -1274,7 +1273,7 @@ static int __devinit setup_instance(fritzpnppci *card)
mISDN_free_dch(&card->dch);
mISDN_free_bch(&card->bch[1]);
mISDN_free_bch(&card->bch[0]);
REMOVE_FROM_LISTBASE(card, ((fritzpnppci *)fritz.ilist));
list_del(&card->list);
kfree(card);
return(err);
}
@ -1460,18 +1459,16 @@ static int __init Fritz_init(void)
int err, pci_nr_found;
printk(KERN_INFO "AVM Fritz PCI/PnP driver Rev. %s\n", mISDN_getrev(avm_fritz_rev));
#ifdef MODULE
fritz.owner = THIS_MODULE;
#endif
INIT_LIST_HEAD(&fritz.ilist);
fritz.name = FritzName;
fritz.own_ctrl = fritz_manager;
fritz.DPROTO.protocol[0] = ISDN_PID_L0_TE_S0;
fritz.BPROTO.protocol[1] = ISDN_PID_L1_B_64TRANS |
ISDN_PID_L1_B_64HDLC;
fritz.BPROTO.protocol[2] = ISDN_PID_L2_B_TRANS;
fritz.prev = NULL;
fritz.next = NULL;
if ((err = mISDN_register(&fritz))) {
printk(KERN_ERR "Can't register Fritz PCI error(%d)\n", err);
return(err);
@ -1507,14 +1504,16 @@ static int __init Fritz_init(void)
static void __exit Fritz_cleanup(void)
{
fritzpnppci *card, *next;
int err;
if ((err = mISDN_unregister(&fritz))) {
printk(KERN_ERR "Can't unregister Fritz PCI error(%d)\n", err);
}
while(fritz.ilist) {
list_for_each_entry_safe(card, next, &fritz.ilist, list) {
printk(KERN_ERR "Fritz PCI card struct not empty refs %d\n",
fritz.refcnt);
release_card(fritz.ilist);
release_card(card);
}
#if defined(CONFIG_PNP)
pnp_unregister_driver(&fcpnp_driver);

View File

@ -193,7 +193,7 @@ free_garbage(void)
kmem_cache_free(mISDN_AppPlci_cp, item);
break;
case KM_DBG_TYP_NI:
printk(KERN_DEBUG "Ncci: NCCI(%x) state(%x) m.state(%x) aplci(%p)\n",
printk(KERN_DEBUG "Ncci: NCCI(%x) state(%lx) m.state(%x) aplci(%p)\n",
kda->a.ni.addr,
kda->a.ni.state,
kda->a.ni.ncci_m.state,
@ -310,30 +310,29 @@ capi20_manager(void *data, u_int prim, void *arg) {
mISDNinstance_t *inst = data;
int found=0;
PLInst_t *plink = NULL;
Controller_t *ctrl = (Controller_t *)capi_obj.ilist;
Controller_t *ctrl;
if (CAPI_DBG_INFO & debug)
printk(KERN_DEBUG "capi20_manager data:%p prim:%x arg:%p\n", data, prim, arg);
if (!data)
return(-EINVAL);
while(ctrl) {
list_for_each_entry(ctrl, &capi_obj.ilist, list) {
if (&ctrl->inst == inst) {
found++;
break;
}
plink = ctrl->linklist;
while(plink) {
list_for_each_entry(plink, &ctrl->linklist, list) {
if (&plink->inst == inst) {
found++;
break;
}
plink = plink->next;
}
if (found)
break;
plink = NULL;
ctrl = ctrl->next;
}
if (&ctrl->list == &capi_obj.ilist)
ctrl = NULL;
if (prim == (MGR_NEWLAYER | REQUEST)) {
int ret = ControllerConstr(&ctrl, data, arg, &capi_obj);
if (!ret)
@ -398,9 +397,7 @@ int Capi20Init(void)
capi_obj.BPROTO.protocol[4] = ISDN_PID_L4_B_CAPI20;
capi_obj.BPROTO.protocol[3] = ISDN_PID_L3_B_TRANS;
capi_obj.own_ctrl = capi20_manager;
capi_obj.prev = NULL;
capi_obj.next = NULL;
capi_obj.ilist = NULL;
INIT_LIST_HEAD(&capi_obj.ilist);
if ((err = CapiNew()))
return(err);
if ((err = mISDN_register(&capi_obj))) {
@ -421,14 +418,14 @@ int Capi20Init(void)
static void Capi20cleanup(void)
{
int err;
Controller_t *contr;
Controller_t *contr, *next;
if ((err = mISDN_unregister(&capi_obj))) {
printk(KERN_ERR "Can't unregister CAPI20 error(%d)\n", err);
}
if (capi_obj.ilist) {
if (!list_empty(&capi_obj.ilist)) {
printk(KERN_WARNING "mISDN controller list not empty\n");
while((contr = capi_obj.ilist))
list_for_each_entry_safe(contr, next, &capi_obj.ilist, list)
ControllerDestr(contr);
}
#ifdef OLDCAPI_DRIVER_INTERFACE

View File

@ -20,7 +20,7 @@ ControllerDestr(Controller_t *contr)
spin_lock_irqsave(&contr->list_lock, flags);
list_for_each_safe(item, next, &contr->Applications) {
ApplicationDestr((Application_t *)item, 3);
ApplicationDestr(list_entry(item, Application_t, head), 3);
}
if (contr->plcis) {
Plci_t *plci = contr->plcis;
@ -46,7 +46,7 @@ ControllerDestr(Controller_t *contr)
contr->plcis = NULL;
}
list_for_each_safe(item, next, &contr->SSProcesse) {
SSProcessDestr((SSProcess_t *)item);
SSProcessDestr(list_entry(item, SSProcess_t, head));
}
#ifdef OLDCAPI_DRIVER_INTERFACE
if (contr->ctrl)
@ -66,15 +66,15 @@ ControllerDestr(Controller_t *contr)
inst->down.peer->obj->ctrl(inst->down.peer,
MGR_DISCONNECT | REQUEST, &inst->down);
}
while (contr->linklist) {
PLInst_t *plink = contr->linklist;
REMOVE_FROM_LISTBASE(plink, contr->linklist);
list_for_each_safe(item, next, &contr->linklist) {
PLInst_t *plink = list_entry(item, PLInst_t, list);
list_del(&plink->list);
kfree(plink);
}
if (contr->entity != MISDN_ENTITY_NONE)
inst->obj->ctrl(inst, MGR_DELENTITY | REQUEST, (void *)contr->entity);
inst->obj->ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
REMOVE_FROM_LISTBASE(contr, ((Controller_t *)inst->obj->ilist));
list_del(&contr->list);
spin_unlock_irqrestore(&contr->list_lock, flags);
kfree(contr);
}
@ -116,8 +116,13 @@ ControllerRun(Controller_t *contr)
pidmask.protocol[1] = 0x03ff;
pidmask.protocol[2] = 0x1fff;
pidmask.protocol[3] = 0x00ff;
plink = contr->linklist;
ret = plink->inst.obj->ctrl(plink->st, MGR_EVALSTACK | REQUEST, &pidmask);
if (list_empty(&contr->linklist)) {
int_error();
ret = -EINVAL;
} else {
plink = list_entry(contr->linklist.next, PLInst_t, list);
ret = plink->inst.obj->ctrl(plink->st, MGR_EVALSTACK | REQUEST, &pidmask);
}
if (ret) {
/* Fallback on error, minimum set */
int_error();
@ -510,13 +515,25 @@ ControllerPutStatus(Controller_t *contr, char *msg)
int
ControllerConstr(Controller_t **contr_p, mISDNstack_t *st, mISDN_pid_t *pid, mISDNobject_t *ocapi)
{
Controller_t *contr;
int retval;
mISDNstack_t *cst;
PLInst_t *plink;
struct list_head *head;
Controller_t *contr;
int retval;
mISDNstack_t *cst;
PLInst_t *plink;
if (!st)
return(-EINVAL);
if (list_empty(&st->childlist)) {
if ((st->id & FLG_CLONE_STACK) &&
(st->childlist.prev != &st->childlist)) {
head = st->childlist.prev;
} else {
printk(KERN_ERR "%s: invalid empty childlist (no clone) stid(%x) childlist(%p<-%p->%p)\n",
__FUNCTION__, st->id, st->childlist.prev, &st->childlist, st->childlist.next);
return(-EINVAL);
}
} else
head = &st->childlist;
if (!pid)
return(-EINVAL);
contr = kmalloc(sizeof(Controller_t), GFP_KERNEL);
@ -525,6 +542,7 @@ ControllerConstr(Controller_t **contr_p, mISDNstack_t *st, mISDN_pid_t *pid, mIS
memset(contr, 0, sizeof(Controller_t));
INIT_LIST_HEAD(&contr->Applications);
INIT_LIST_HEAD(&contr->SSProcesse);
INIT_LIST_HEAD(&contr->linklist);
spin_lock_init(&contr->list_lock);
spin_lock_init(&contr->id_lock);
contr->next_id = 1;
@ -538,11 +556,8 @@ ControllerConstr(Controller_t **contr_p, mISDNstack_t *st, mISDN_pid_t *pid, mIS
}
memset(contr->ctrl, 0, sizeof(struct capi_ctr));
#endif
cst = st->child;
while(cst) {
list_for_each_entry(cst, head, list)
contr->nr_bc++;
cst = cst->next;
}
if (!contr->nr_bc) {
printk(KERN_ERR "no bchannels\n");
ControllerDestr(contr);
@ -571,8 +586,7 @@ ControllerConstr(Controller_t **contr_p, mISDNstack_t *st, mISDN_pid_t *pid, mIS
ControllerDestr(contr);
return(-ENOPROTOOPT);
}
cst = st->child;
while(cst) {
list_for_each_entry(cst, head, list) {
if (!(plink = kmalloc(sizeof(PLInst_t), GFP_KERNEL))) {
printk(KERN_ERR "no mem for PLinst\n");
int_error();
@ -585,10 +599,9 @@ ControllerConstr(Controller_t **contr_p, mISDNstack_t *st, mISDN_pid_t *pid, mIS
mISDN_init_instance(&plink->inst, ocapi, plink);
plink->inst.pid.layermask |= ISDN_LAYER(4);
plink->inst.down.stat = IF_NOACTIV;
APPEND_TO_LIST(plink, contr->linklist);
cst = cst->next;
list_add_tail(&plink->list, &contr->linklist);
}
APPEND_TO_LIST(contr, ocapi->ilist);
list_add_tail(&contr->list, &ocapi->ilist);
contr->entity = MISDN_ENTITY_NONE;
retval = ocapi->ctrl(&contr->inst, MGR_NEWENTITY | REQUEST, NULL);
if (retval) {
@ -639,26 +652,23 @@ ControllerSelChannel(Controller_t *contr, u_int channel)
channel_info_t ci;
int ret;
if (!contr->linklist) {
if (list_empty(&contr->linklist)) {
int_errtxt("no linklist for controller(%x)", contr->addr);
return(NULL);
}
ci.channel = channel;
ci.st.p = NULL;
ret = contr->inst.obj->ctrl(contr->inst.st, MGR_SELCHANNEL | REQUEST,
&ci);
ret = contr->inst.obj->ctrl(contr->inst.st, MGR_SELCHANNEL | REQUEST, &ci);
if (ret) {
int_errtxt("MGR_SELCHANNEL ret(%d)", ret);
return(NULL);
}
cst = ci.st.p;
plink = contr->linklist;
while(plink) {
list_for_each_entry(plink, &contr->linklist, list) {
if (cst == plink->st)
break;
plink = plink->next;
return(plink);
}
return(plink);
return(NULL);
}
int

View File

@ -19,10 +19,11 @@
#include <linux/smp_lock.h>
#endif
static char *mISDN_core_revision = "$Revision$";
static char *mISDN_core_revision = "$Revision$";
LIST_HEAD(mISDN_objectlist);
rwlock_t mISDN_objects_lock = RW_LOCK_UNLOCKED;
mISDNobject_t *mISDN_objects = NULL;
rwlock_t mISDN_objects_lock = RW_LOCK_UNLOCKED;
int core_debug;
static u_char entityarray[MISDN_MAX_ENTITY/8];
@ -153,14 +154,13 @@ get_object(int id) {
mISDNobject_t *obj;
read_lock(&mISDN_objects_lock);
obj = mISDN_objects;
while(obj) {
if (obj->id == id)
break;
obj = obj->next;
}
list_for_each_entry(obj, &mISDN_objectlist, list)
if (obj->id == id) {
read_unlock(&mISDN_objects_lock);
return(obj);
}
read_unlock(&mISDN_objects_lock);
return(obj);
return(NULL);
}
static mISDNobject_t *
@ -169,17 +169,17 @@ find_object(int protocol) {
int err;
read_lock(&mISDN_objects_lock);
obj = mISDN_objects;
while (obj) {
list_for_each_entry(obj, &mISDN_objectlist, list) {
err = obj->own_ctrl(NULL, MGR_HASPROTOCOL | REQUEST, &protocol);
if (!err)
break;
goto unlock;
if (err != -ENOPROTOOPT) {
if (0 == mISDN_HasProtocol(obj, protocol))
break;
goto unlock;
}
obj = obj->next;
}
obj = NULL;
unlock:
read_unlock(&mISDN_objects_lock);
return(obj);
}
@ -220,26 +220,16 @@ find_object_module(int protocol) {
static void
remove_object(mISDNobject_t *obj) {
mISDNstack_t *st = mISDN_stacklist;
mISDNlayer_t *layer;
mISDNinstance_t *inst, *tmp;
mISDNstack_t *st, *nst;
mISDNlayer_t *layer, *nl;
mISDNinstance_t *inst;
while (st) {
layer = st->lstack;
while(layer) {
list_for_each_entry_safe(st, nst, &mISDN_stacklist, list) {
list_for_each_entry_safe(layer, nl, &st->layerlist, list) {
inst = layer->inst;
while (inst) {
if (inst->obj == obj) {
tmp = inst->next;
inst->obj->own_ctrl(st, MGR_RELEASE
| INDICATION, inst);
inst = tmp;
} else
inst = inst->next;
}
layer = layer->next;
if (inst && inst->obj == obj)
inst->obj->own_ctrl(st, MGR_RELEASE | INDICATION, inst);
}
st = st->next;
}
}
@ -296,7 +286,7 @@ get_next_instance(mISDNstack_t *st, mISDN_pid_t *pid)
static int
sel_channel(mISDNstack_t *st, channel_info_t *ci)
{
int err = -EINVAL;
int err = -EINVAL;
if (!ci)
return(err);
@ -314,20 +304,30 @@ sel_channel(mISDNstack_t *st, channel_info_t *ci)
printk(KERN_WARNING "%s: no mgr st(%p)\n", __FUNCTION__, st);
}
if (err) {
mISDNstack_t *cst = st->child;
mISDNstack_t *cst;
u_int nr = 0;
ci->st.p = NULL;
if (!(ci->channel & (~CHANNEL_NUMBER))) {
/* only number is set */
while(cst) {
struct list_head *head;
if (list_empty(&st->childlist)) {
if ((st->id & FLG_CLONE_STACK) &&
(st->childlist.prev != &st->childlist)) {
head = st->childlist.prev;
} else {
printk(KERN_WARNING "%s: invalid empty childlist (no clone) stid(%x) childlist(%p<-%p->%p)\n",
__FUNCTION__, st->id, st->childlist.prev, &st->childlist, st->childlist.next);
return(err);
}
} else
head = &st->childlist;
list_for_each_entry(cst, head, list) {
nr++;
if (nr == (ci->channel & 3)) {
ci->st.p = cst;
err = 0;
break;
return(0);
}
cst = cst->next;
}
}
}
@ -363,7 +363,10 @@ add_if(mISDNinstance_t *inst, u_int prim, mISDNif_t *hif) {
myif = &inst->up;
} else
return(-EINVAL);
APPEND_TO_LIST(hif, myif);
while(myif->clone)
myif = myif->clone;
myif->clone = hif;
hif->predecessor = myif;
inst->obj->own_ctrl(inst, prim, hif);
return(0);
}
@ -567,7 +570,7 @@ int mISDN_register(mISDNobject_t *obj) {
return(-EINVAL);
write_lock_irqsave(&mISDN_objects_lock, flags);
obj->id = obj_id++;
APPEND_TO_LIST(obj, mISDN_objects);
list_add_tail(&obj->list, &mISDN_objectlist);
write_unlock_irqrestore(&mISDN_objects_lock, flags);
obj->ctrl = central_manager;
// register_prop
@ -592,10 +595,11 @@ int mISDN_unregister(mISDNobject_t *obj) {
else
remove_object(obj);
write_lock_irqsave(&mISDN_objects_lock, flags);
REMOVE_FROM_LISTBASE(obj, mISDN_objects);
list_del(&obj->list);
write_unlock_irqrestore(&mISDN_objects_lock, flags);
if (core_debug & DEBUG_CORE_FUNC)
printk(KERN_DEBUG "mISDN_unregister: mISDN_objects(%p)\n", mISDN_objects);
printk(KERN_DEBUG "mISDN_unregister: mISDN_objectlist(%p<-%p->%p)\n",
mISDN_objectlist.prev, &mISDN_objectlist, mISDN_objectlist.next);
return(0);
}
@ -628,23 +632,21 @@ mISDNInit(void)
void mISDN_cleanup(void) {
DECLARE_MUTEX_LOCKED(sem);
mISDNstack_t *st;
mISDNstack_t *st, *nst;
free_mISDNdev();
if (mISDN_objects) {
if (!list_empty(&mISDN_objectlist)) {
printk(KERN_WARNING "mISDNcore mISDN_objects not empty\n");
}
if (mISDN_stacklist) {
if (!list_empty(&mISDN_stacklist)) {
printk(KERN_WARNING "mISDNcore mISDN_stacklist not empty\n");
st = mISDN_stacklist;
while (st) {
printk(KERN_WARNING "mISDNcore st %x in list\n",
list_for_each_entry_safe(st, nst, &mISDN_stacklist, list) {
printk(KERN_WARNING "mISDNcore st %x still in list\n",
st->id);
if (st == st->next) {
if (list_empty(&st->list)) {
printk(KERN_WARNING "mISDNcore st == next\n");
break;
}
st = st->next;
}
}
if (mISDN_thread.thread) {

View File

@ -37,8 +37,8 @@ extern int free_device(mISDNdevice_t *dev);
/* from mISDN_stack.c */
extern mISDNstack_t *mISDN_stacklist;
extern mISDNinstance_t *mISDN_instlist;
extern struct list_head mISDN_stacklist;
extern struct list_head mISDN_instlist;
extern void get_stack_info(iframe_t *);
extern int get_stack_cnt(void);
@ -57,7 +57,7 @@ extern mISDNinstance_t *get_instance(mISDNstack_t *, int, int);
/* from mISDN_core.c */
extern mISDNobject_t *mISDN_objects;
extern struct list_head mISDN_objectlist;
extern int core_debug;
extern int register_layer(mISDNstack_t *, mISDNinstance_t *);

View File

@ -78,24 +78,22 @@ extern u8 silence;
/* all members within a conference (this is linked 1:1 with the dsp) */
struct _dsp;
typedef struct _conf_member {
struct _conf_member *prev;
struct _conf_member *next;
struct _dsp *dsp;
struct list_head list;
struct _dsp *dsp;
} conf_member_t;
/* the list of all conferences */
typedef struct _conference {
struct _conference *prev;
struct _conference *next;
u32 id; /* all cmx stacks with the same ID are connected */
conf_member_t *mlist;
int software; /* conf is processed by software */
int hardware; /* conf is processed by hardware */
struct list_head list;
u32 id; /* all cmx stacks with the same ID are connected */
struct list_head mlist;
int software; /* conf is processed by software */
int hardware; /* conf is processed by hardware */
//#ifndef AUTOJITTER
int largest; /* largest frame received in conf's life. */
int largest; /* largest frame received in conf's life. */
//#endif
int W_min, W_max; /* min/maximum rx-write pointer of members */
s32 conf_buff[CMX_BUFF_SIZE];
int W_min, W_max; /* min/maximum rx-write pointer of members */
s32 conf_buff[CMX_BUFF_SIZE];
} conference_t;
extern mISDNobject_t dsp_obj;
@ -148,8 +146,7 @@ struct dsp_features {
};
typedef struct _dsp {
struct _dsp *prev;
struct _dsp *next;
struct list_head list;
mISDNinstance_t inst;
int b_active;
int echo; /* echo is done by software */
@ -205,7 +202,7 @@ typedef struct _dsp {
extern void dsp_change_volume(struct sk_buff *skb, int volume);
extern conference_t *Conf_list;
extern struct list_head Conf_list;
extern void dsp_cmx_debug(dsp_t *dsp);
extern void dsp_cmx_hardware(conference_t *conf, dsp_t *dsp);
extern int dsp_cmx_conf(dsp_t *dsp, u32 conf_id);

View File

@ -149,7 +149,7 @@
//#define CMX_DEBUG /* massive read/write pointer output */
extern mISDN_HWlock_t dsp_lock;
conference_t *Conf_list = NULL;
LIST_HEAD(Conf_list);
/*
* debug cmx memory structure
@ -162,8 +162,7 @@ dsp_cmx_debug(dsp_t *dsp)
dsp_t *odsp;
printk(KERN_DEBUG "-----Current DSP\n");
odsp = (dsp_t *)dsp_obj.ilist;
while(odsp)
list_for_each_entry(odsp, &dsp_obj.ilist, list)
{
printk(KERN_DEBUG "* %s echo=%d txmix=%d", odsp->inst.name, odsp->echo, odsp->tx_mix);
if (odsp->conf)
@ -171,21 +170,16 @@ dsp_cmx_debug(dsp_t *dsp)
if (dsp == odsp)
printk(" *this*");
printk("\n");
odsp = odsp->next;
}
printk(KERN_DEBUG "-----Current Conf:\n");
conf = Conf_list;
while(conf)
list_for_each_entry(conf, &Conf_list, list)
{
printk(KERN_DEBUG "* Conf %d (0x%x)\n", conf->id, (u32)conf);
member = conf->mlist;
while(member)
list_for_each_entry(member, &conf->mlist, list)
{
printk(KERN_DEBUG " - member = %s (slot_tx %d, bank_tx %d, slot_rx %d, bank_rx %d hfc_conf %d)%s\n", member->dsp->inst.name, member->dsp->pcm_slot_tx, member->dsp->pcm_bank_tx, member->dsp->pcm_slot_rx, member->dsp->pcm_bank_rx, member->dsp->hfc_conf, (member->dsp==dsp)?" *this*":"");
member = member->next;
}
conf = conf->next;
}
printk(KERN_DEBUG "-----end\n");
}
@ -205,12 +199,9 @@ static conference_t
}
/* search conference */
conf = Conf_list;
while(conf) {
list_for_each_entry(conf, &Conf_list, list)
if (conf->id == id)
return(conf);
conf = conf->next;
}
return(NULL);
}
@ -254,10 +245,10 @@ dsp_cmx_add_conf_member(dsp_t *dsp, conference_t *conf)
dsp->W_rx = conf->W_max;
dsp->R_rx = conf->W_max;
APPEND_TO_LIST(member, ((conf_member_t *)conf->mlist));
list_add_tail(&member->list, &conf->mlist);
/* zero conf-buffer if we change from 2 to 3 members */
if (conf->mlist->next) if (!conf->mlist->next->next)
if (3 == count_list_member(&conf->mlist))
memset(conf->conf_buff, 0, sizeof(conf->conf_buff));
dsp->conf = conf;
@ -287,33 +278,28 @@ dsp_cmx_del_conf_member(dsp_t *dsp)
return(-EINVAL);
}
member = dsp->conf->mlist;
if (!member) {
if (list_empty(&dsp->conf->mlist)) {
printk(KERN_WARNING "%s: dsp has linked an empty conf.\n",
__FUNCTION__);
return(-EINVAL);
}
/* find us in conf */
while(member) {
if (member->dsp == dsp)
break;
member = member->next;
}
if (!member) {
printk(KERN_WARNING "%s: dsp is not present in its own conf_meber list.\n",
__FUNCTION__);
return(-EINVAL);
list_for_each_entry(member, &dsp->conf->mlist, list) {
if (member->dsp == dsp) {
list_del(&member->list);
dsp->conf = NULL;
dsp->member = NULL;
unlock_HW(&dsp_lock);
vfree(member);
lock_HW(&dsp_lock, 0);
return(0);
}
}
printk(KERN_WARNING "%s: dsp is not present in its own conf_meber list.\n",
__FUNCTION__);
REMOVE_FROM_LISTBASE(member, ((conf_member_t *)dsp->conf->mlist));
dsp->conf = NULL;
dsp->member = NULL;
unlock_HW(&dsp_lock);
vfree(member);
lock_HW(&dsp_lock, 0);
return(0);
return(-EINVAL);
}
@ -339,9 +325,10 @@ static conference_t
}
lock_HW(&dsp_lock, 0);
memset(conf, 0, sizeof(conference_t));
INIT_LIST_HEAD(&conf->mlist);
conf->id = id;
APPEND_TO_LIST(conf, ((conference_t *)Conf_list));
list_add_tail(&conf->list, &Conf_list);
return(conf);
}
@ -359,13 +346,12 @@ dsp_cmx_del_conf(conference_t *conf)
return(-EINVAL);
}
if (conf->mlist) {
if (!list_empty(&conf->mlist)) {
printk(KERN_WARNING "%s: conf not empty.\n",
__FUNCTION__);
return(-EINVAL);
}
REMOVE_FROM_LISTBASE(conf, ((conference_t *)Conf_list));
list_del(&conf->list);
unlock_HW(&dsp_lock);
vfree(conf);
lock_HW(&dsp_lock, 0);
@ -409,11 +395,11 @@ dsp_cmx_hw_message(dsp_t *dsp, u32 message, u32 param1, u32 param2, u32 param3,
void
dsp_cmx_hardware(conference_t *conf, dsp_t *dsp)
{
conf_member_t *member;
conf_member_t *member, *nextm;
int memb = 0, i, ii, i1, i2;
int freeunits[8];
u_char freeslots[256];
int same_hfc = -1, current_conf = -1, all_conf = 1;
int same_hfc = -1, same_pcm = -1, current_conf = -1, all_conf = 1;
/* dsp gets updated (no conf) */
//printk("-----1\n");
@ -451,18 +437,22 @@ dsp_cmx_hardware(conference_t *conf, dsp_t *dsp)
if (dsp_debug & DEBUG_DSP_CMX)
printk(KERN_DEBUG "%s checking conference %d\n", __FUNCTION__, conf->id);
//printk("-----5\n");
member = conf->mlist;
if (list_empty(&conf->mlist)) {
printk(KERN_ERR "%s: conference whithout members\n", __FUNCTION__);
return;
}
member = list_entry(conf->mlist.next, conf_member_t, list);
same_hfc = member->dsp->features.hfc_id;
same_pcm = member->dsp->features.pcm_id;
/* check all members in our conference */
while (member) {
list_for_each_entry(member, &conf->mlist, list) {
/* check if member uses mixing */
if (member->dsp->tx_mix) {
if (dsp_debug & DEBUG_DSP_CMX)
printk(KERN_DEBUG "%s dsp %s cannot form a conf, because tx_mix is turned on\n", __FUNCTION__, member->dsp->inst.name);
conf_software:
member = conf->mlist;
while (member) {
list_for_each_entry(member, &conf->mlist, list) {
dsp = member->dsp;
/* remove HFC conference if enabled */
if (dsp->hfc_conf >= 0) {
@ -481,7 +471,6 @@ dsp_cmx_hardware(conference_t *conf, dsp_t *dsp)
dsp->pcm_slot_rx = -1;
dsp->pcm_bank_rx = -1;
}
member = member->next;
}
conf->hardware = 0;
conf->software = 1;
@ -517,9 +506,10 @@ dsp_cmx_hardware(conference_t *conf, dsp_t *dsp)
goto conf_software;
}
/* check if relations are on the same PCM bus */
if (member->dsp->features.pcm_id != conf->mlist->dsp->features.pcm_id) {
if (member->dsp->features.pcm_id != same_pcm) {
if (dsp_debug & DEBUG_DSP_CMX)
printk(KERN_DEBUG "%s dsp %s cannot form a conf, because dsp is on a different PCM bus than the first dsp\n", __FUNCTION__, member->dsp->inst.name);
printk(KERN_DEBUG "%s dsp %s cannot form a conf, because dsp is on a different PCM bus than the first dsp\n",
__FUNCTION__, member->dsp->inst.name);
goto conf_software;
}
/* determine if members are on the same hfc chip */
@ -532,7 +522,6 @@ dsp_cmx_hardware(conference_t *conf, dsp_t *dsp)
if (member->dsp->hfc_conf < 0)
all_conf = 0;
member = member->next;
memb++;
}
@ -546,7 +535,8 @@ dsp_cmx_hardware(conference_t *conf, dsp_t *dsp)
printk(KERN_DEBUG "%s conf %d cannot form a HW conference, because dsp is alone\n", __FUNCTION__, conf->id);
conf->hardware = 0;
conf->software = 1;
dsp = conf->mlist->dsp;
member = list_entry(conf->mlist.next, conf_member_t, list);
dsp = member->dsp;
goto one_member;
}
@ -557,7 +547,8 @@ dsp_cmx_hardware(conference_t *conf, dsp_t *dsp)
/* if we have only two members */
if (memb == 2) {
member = conf->mlist;
member = list_entry(conf->mlist.next, conf_member_t, list);
nextm = list_entry(member->list.next, conf_member_t, list);
/* remove HFC conference if enabled */
if (member->dsp->hfc_conf >= 0) {
if (dsp_debug & DEBUG_DSP_CMX)
@ -565,39 +556,40 @@ dsp_cmx_hardware(conference_t *conf, dsp_t *dsp)
dsp_cmx_hw_message(member->dsp, HW_CONF_SPLIT, 0, 0, 0, 0);
member->dsp->hfc_conf = -1;
}
if (member->next->dsp->hfc_conf >= 0) {
if (nextm->dsp->hfc_conf >= 0) {
if (dsp_debug & DEBUG_DSP_CMX)
printk(KERN_DEBUG "%s removing %s from HFC conf %d because two parties require only a PCM slot\n", __FUNCTION__, member->next->dsp->inst.name, member->next->dsp->hfc_conf);
dsp_cmx_hw_message(member->next->dsp, HW_CONF_SPLIT, 0, 0, 0, 0);
member->next->dsp->hfc_conf = -1;
printk(KERN_DEBUG "%s removing %s from HFC conf %d because two parties require only a PCM slot\n", __FUNCTION__, nextm->dsp->inst.name, nextm->dsp->hfc_conf);
dsp_cmx_hw_message(nextm->dsp, HW_CONF_SPLIT, 0, 0, 0, 0);
nextm->dsp->hfc_conf = -1;
}
/* if members have two banks (and not on the same chip) */
if (member->dsp->features.pcm_banks>1
&& member->next->dsp->features.pcm_banks>1
&& member->dsp->features.pcm_id!=member->next->dsp->features.pcm_id) {
&& nextm->dsp->features.pcm_banks>1
&& member->dsp->features.pcm_id!=nextm->dsp->features.pcm_id) {
/* if both members have same slots with crossed banks */
if (member->dsp->pcm_slot_tx>=0
&& member->dsp->pcm_slot_rx>=0
&& member->next->dsp->pcm_slot_tx>=0
&& member->next->dsp->pcm_slot_rx>=0
&& member->next->dsp->pcm_slot_tx==member->dsp->pcm_slot_rx
&& member->next->dsp->pcm_slot_rx==member->dsp->pcm_slot_tx
&& member->next->dsp->pcm_slot_tx==member->dsp->pcm_slot_tx
&& nextm->dsp->pcm_slot_tx>=0
&& nextm->dsp->pcm_slot_rx>=0
&& nextm->dsp->pcm_slot_tx==member->dsp->pcm_slot_rx
&& nextm->dsp->pcm_slot_rx==member->dsp->pcm_slot_tx
&& nextm->dsp->pcm_slot_tx==member->dsp->pcm_slot_tx
&& member->dsp->pcm_bank_tx!=member->dsp->pcm_bank_rx
&& member->next->dsp->pcm_bank_tx!=member->next->dsp->pcm_bank_rx) {
&& nextm->dsp->pcm_bank_tx!=nextm->dsp->pcm_bank_rx) {
/* all members have same slot */
if (dsp_debug & DEBUG_DSP_CMX)
printk(KERN_DEBUG "%s dsp %s & %s stay joined on PCM slot %d bank %d (TX) bank %d (RX) (on different chips)\n", __FUNCTION__, member->dsp->inst.name, member->next->dsp->inst.name, member->dsp->pcm_slot_tx, member->dsp->pcm_bank_tx, member->dsp->pcm_bank_rx);
printk(KERN_DEBUG "%s dsp %s & %s stay joined on PCM slot %d bank %d (TX) bank %d (RX) (on different chips)\n", __FUNCTION__,
member->dsp->inst.name, nextm->dsp->inst.name,
member->dsp->pcm_slot_tx, member->dsp->pcm_bank_tx, member->dsp->pcm_bank_rx);
conf->hardware = 0;
conf->software = 1;
return;
}
/* find a new slot */
memset(freeslots, 1, sizeof(freeslots));
dsp = (dsp_t *)dsp_obj.ilist;
while(dsp) {
list_for_each_entry(dsp, &dsp_obj.ilist, list) {
if (dsp!=member->dsp
&& dsp!=member->next->dsp
&& dsp!=nextm->dsp
&& member->dsp->features.pcm_id==dsp->features.pcm_id) {
if (dsp->pcm_slot_rx>=0
&& dsp->pcm_slot_rx<sizeof(freeslots))
@ -606,7 +598,6 @@ dsp_cmx_hardware(conference_t *conf, dsp_t *dsp)
&& dsp->pcm_slot_tx<sizeof(freeslots))
freeslots[dsp->pcm_slot_rx] = 0;
}
dsp = dsp->next;
}
i = 0;
ii = member->dsp->features.pcm_slots;
@ -617,23 +608,27 @@ dsp_cmx_hardware(conference_t *conf, dsp_t *dsp)
}
if (i == ii) {
if (dsp_debug & DEBUG_DSP_CMX)
printk(KERN_DEBUG "%s no slot available for %s & %s\n", __FUNCTION__, member->dsp->inst.name, member->next->dsp->inst.name);
printk(KERN_DEBUG "%s no slot available for %s & %s\n", __FUNCTION__,
member->dsp->inst.name, nextm->dsp->inst.name);
/* no more slots available */
goto conf_software;
}
/* assign free slot */
member->dsp->pcm_slot_tx = i;
member->dsp->pcm_slot_rx = i;
member->next->dsp->pcm_slot_tx = i;
member->next->dsp->pcm_slot_rx = i;
nextm->dsp->pcm_slot_tx = i;
nextm->dsp->pcm_slot_rx = i;
member->dsp->pcm_bank_rx = 0;
member->dsp->pcm_bank_tx = 1;
member->next->dsp->pcm_bank_rx = 1;
member->next->dsp->pcm_bank_tx = 0;
nextm->dsp->pcm_bank_rx = 1;
nextm->dsp->pcm_bank_tx = 0;
if (dsp_debug & DEBUG_DSP_CMX)
printk(KERN_DEBUG "%s adding %s & %s to new PCM slot %d (TX and RX on different chips) because both members have not same slots\n", __FUNCTION__, member->dsp->inst.name, member->next->dsp->inst.name, member->dsp->pcm_slot_tx);
dsp_cmx_hw_message(member->dsp, HW_PCM_CONN, member->dsp->pcm_slot_tx, member->dsp->pcm_bank_tx, member->dsp->pcm_slot_rx, member->dsp->pcm_bank_rx);
dsp_cmx_hw_message(member->next->dsp, HW_PCM_CONN, member->next->dsp->pcm_slot_tx, member->next->dsp->pcm_bank_tx, member->next->dsp->pcm_slot_rx, member->next->dsp->pcm_bank_rx);
printk(KERN_DEBUG "%s adding %s & %s to new PCM slot %d (TX and RX on different chips) because both members have not same slots\n", __FUNCTION__,
member->dsp->inst.name, nextm->dsp->inst.name, member->dsp->pcm_slot_tx);
dsp_cmx_hw_message(member->dsp, HW_PCM_CONN, member->dsp->pcm_slot_tx, member->dsp->pcm_bank_tx,
member->dsp->pcm_slot_rx, member->dsp->pcm_bank_rx);
dsp_cmx_hw_message(nextm->dsp, HW_PCM_CONN, nextm->dsp->pcm_slot_tx, nextm->dsp->pcm_bank_tx,
nextm->dsp->pcm_slot_rx, nextm->dsp->pcm_bank_rx);
conf->hardware = 1;
conf->software = 0;
return;
@ -642,28 +637,28 @@ dsp_cmx_hardware(conference_t *conf, dsp_t *dsp)
/* if both members have different crossed slots */
if (member->dsp->pcm_slot_tx>=0
&& member->dsp->pcm_slot_rx>=0
&& member->next->dsp->pcm_slot_tx>=0
&& member->next->dsp->pcm_slot_rx>=0
&& member->next->dsp->pcm_slot_tx==member->dsp->pcm_slot_rx
&& member->next->dsp->pcm_slot_rx==member->dsp->pcm_slot_tx
&& nextm->dsp->pcm_slot_tx>=0
&& nextm->dsp->pcm_slot_rx>=0
&& nextm->dsp->pcm_slot_tx==member->dsp->pcm_slot_rx
&& nextm->dsp->pcm_slot_rx==member->dsp->pcm_slot_tx
&& member->dsp->pcm_slot_tx!=member->dsp->pcm_slot_rx
&& member->dsp->pcm_bank_tx==0
&& member->dsp->pcm_bank_rx==0
&& member->next->dsp->pcm_bank_tx==0
&& member->next->dsp->pcm_bank_rx==0) {
&& nextm->dsp->pcm_bank_tx==0
&& nextm->dsp->pcm_bank_rx==0) {
/* all members have same slot */
if (dsp_debug & DEBUG_DSP_CMX)
printk(KERN_DEBUG "%s dsp %s & %s stay joined on PCM slot %d (TX) %d (RX) on same chip or one bank PCM)\n", __FUNCTION__, member->dsp->inst.name, member->next->dsp->inst.name, member->dsp->pcm_slot_tx, member->dsp->pcm_slot_rx);
printk(KERN_DEBUG "%s dsp %s & %s stay joined on PCM slot %d (TX) %d (RX) on same chip or one bank PCM)\n", __FUNCTION__,
member->dsp->inst.name, nextm->dsp->inst.name, member->dsp->pcm_slot_tx, member->dsp->pcm_slot_rx);
conf->hardware = 0;
conf->software = 1;
return;
}
/* find two new slot */
memset(freeslots, 1, sizeof(freeslots));
dsp = (dsp_t *)dsp_obj.ilist;
while(dsp) {
list_for_each_entry(dsp, &dsp_obj.ilist, list) {
if (dsp!=member->dsp
&& dsp!=member->next->dsp
&& dsp!=nextm->dsp
&& member->dsp->features.pcm_id==dsp->features.pcm_id) {
if (dsp->pcm_slot_rx>=0
&& dsp->pcm_slot_rx<sizeof(freeslots))
@ -672,7 +667,6 @@ dsp_cmx_hardware(conference_t *conf, dsp_t *dsp)
&& dsp->pcm_slot_tx<sizeof(freeslots))
freeslots[dsp->pcm_slot_rx] = 0;
}
dsp = dsp->next;
}
i1 = 0;
ii = member->dsp->features.pcm_slots;
@ -683,7 +677,8 @@ dsp_cmx_hardware(conference_t *conf, dsp_t *dsp)
}
if (i1 == ii) {
if (dsp_debug & DEBUG_DSP_CMX)
printk(KERN_DEBUG "%s no slot available for %s & %s\n", __FUNCTION__, member->dsp->inst.name, member->next->dsp->inst.name);
printk(KERN_DEBUG "%s no slot available for %s & %s\n", __FUNCTION__,
member->dsp->inst.name, nextm->dsp->inst.name);
/* no more slots available */
goto conf_software;
}
@ -695,23 +690,26 @@ dsp_cmx_hardware(conference_t *conf, dsp_t *dsp)
}
if (i2 == ii) {
if (dsp_debug & DEBUG_DSP_CMX)
printk(KERN_DEBUG "%s no slot available for %s & %s\n", __FUNCTION__, member->dsp->inst.name, member->next->dsp->inst.name);
printk(KERN_DEBUG "%s no slot available for %s & %s\n", __FUNCTION__,
member->dsp->inst.name, nextm->dsp->inst.name);
/* no more slots available */
goto conf_software;
}
/* assign free slots */
member->dsp->pcm_slot_tx = i1;
member->dsp->pcm_slot_rx = i2;
member->next->dsp->pcm_slot_tx = i2;
member->next->dsp->pcm_slot_rx = i1;
nextm->dsp->pcm_slot_tx = i2;
nextm->dsp->pcm_slot_rx = i1;
member->dsp->pcm_bank_rx = 0;
member->dsp->pcm_bank_tx = 0;
member->next->dsp->pcm_bank_rx = 0;
member->next->dsp->pcm_bank_tx = 0;
nextm->dsp->pcm_bank_rx = 0;
nextm->dsp->pcm_bank_tx = 0;
if (dsp_debug & DEBUG_DSP_CMX)
printk(KERN_DEBUG "%s adding %s & %s to new PCM slot %d (TX) %d (RX) on same chip or one bank PCM) because both members have not crossed slots\n", __FUNCTION__, member->dsp->inst.name, member->next->dsp->inst.name, member->dsp->pcm_slot_tx, member->dsp->pcm_slot_rx);
printk(KERN_DEBUG "%s adding %s & %s to new PCM slot %d (TX) %d (RX) on same chip or one bank PCM) because both members have not crossed slots\n", __FUNCTION__,
member->dsp->inst.name, nextm->dsp->inst.name, member->dsp->pcm_slot_tx,
member->dsp->pcm_slot_rx);
dsp_cmx_hw_message(member->dsp, HW_PCM_CONN, member->dsp->pcm_slot_tx, member->dsp->pcm_bank_tx, member->dsp->pcm_slot_rx, member->dsp->pcm_bank_rx);
dsp_cmx_hw_message(member->next->dsp, HW_PCM_CONN, member->next->dsp->pcm_slot_tx, member->next->dsp->pcm_bank_tx, member->next->dsp->pcm_slot_rx, member->next->dsp->pcm_bank_rx);
dsp_cmx_hw_message(nextm->dsp, HW_PCM_CONN, nextm->dsp->pcm_slot_tx, nextm->dsp->pcm_bank_tx, nextm->dsp->pcm_slot_rx, nextm->dsp->pcm_bank_rx);
conf->hardware = 1;
conf->software = 0;
return;
@ -725,7 +723,8 @@ dsp_cmx_hardware(conference_t *conf, dsp_t *dsp)
/* if not the same HFC chip */
if (same_hfc < 0) {
if (dsp_debug & DEBUG_DSP_CMX)
printk(KERN_DEBUG "%s conference %d cannot be formed, because members are on different chips or not on HFC chip\n", __FUNCTION__, conf->id);
printk(KERN_DEBUG "%s conference %d cannot be formed, because members are on different chips or not on HFC chip\n",
__FUNCTION__, conf->id);
goto conf_software;
}
@ -737,17 +736,14 @@ dsp_cmx_hardware(conference_t *conf, dsp_t *dsp)
*/
if (current_conf >= 0) {
join_members:
member = conf->mlist;
while (member) {
list_for_each_entry(member, &conf->mlist, list) {
/* join to current conference */
if (member->dsp->hfc_conf == current_conf) {
member = member->next;
continue;
}
/* get a free timeslot first */
memset(freeslots, 1, sizeof(freeslots));
dsp = (dsp_t *)dsp_obj.ilist;
while(dsp) {
list_for_each_entry(dsp, &dsp_obj.ilist, list) {
/* not checking current member, because
* slot will be overwritten.
*/
@ -762,7 +758,6 @@ dsp_cmx_hardware(conference_t *conf, dsp_t *dsp)
&& dsp->pcm_slot_rx<sizeof(freeslots))
freeslots[dsp->pcm_slot_rx] = 0;
}
dsp = dsp->next;
}
i = 0;
ii = member->dsp->features.pcm_slots;
@ -787,7 +782,6 @@ dsp_cmx_hardware(conference_t *conf, dsp_t *dsp)
member->dsp->hfc_conf = current_conf;
dsp_cmx_hw_message(member->dsp, HW_PCM_CONN, i, 2, i, 2);
dsp_cmx_hw_message(member->dsp, HW_CONF_JOIN, current_conf, 0, 0, 0);
member = member->next;
}
return;
}
@ -795,8 +789,7 @@ dsp_cmx_hardware(conference_t *conf, dsp_t *dsp)
/* no member is in a conference yet, so we find a free one
*/
memset(freeunits, 1, sizeof(freeunits));
dsp = (dsp_t *)dsp_obj.ilist;
while(dsp) {
list_for_each_entry(dsp, &dsp_obj.ilist, list) {
/* dsp must be on the same chip */
if (dsp->features.hfc_id==same_hfc
/* dsp must have joined a HW conference */
@ -804,7 +797,6 @@ dsp_cmx_hardware(conference_t *conf, dsp_t *dsp)
/* slot must be within range */
&& dsp->hfc_conf<8)
freeunits[dsp->hfc_conf] = 0;
dsp = dsp->next;
}
i = 0;
ii = 8;
@ -855,7 +847,7 @@ dsp_cmx_conf(dsp_t *dsp, u32 conf_id)
dsp_cmx_hardware(NULL, dsp);
/* conf now empty? */
if (!conf->mlist) {
if (list_empty(&conf->mlist)) {
if (dsp_debug & DEBUG_DSP_CMX)
printk(KERN_DEBUG "conference is empty, so we remove it.\n");
err = dsp_cmx_del_conf(conf);
@ -891,7 +883,7 @@ dsp_cmx_conf(dsp_t *dsp, u32 conf_id)
dsp->conf_id = conf_id;
/* if we are alone, we do nothing! */
if (!conf->mlist) {
if (list_empty(&conf->mlist)) {
if (dsp_debug & DEBUG_DSP_CMX)
printk(KERN_DEBUG "we are alone in this conference, so exit.\n");
/* update hardware */
@ -954,8 +946,7 @@ dsp_cmx_receive(dsp_t *dsp, struct sk_buff *skb)
else if (conf->largest > dsp->largest)
dsp->largest = conf->largest;
member = conf->mlist;
while(member) {
list_for_each_entry(member, &conf->mlist, list) {
if (member != dsp->member) {
/* if W_rx is lower */
if (((member->dsp->W_rx - W_min) & CMX_BUFF_MASK) >= CMX_BUFF_HALF)
@ -964,7 +955,6 @@ dsp_cmx_receive(dsp_t *dsp, struct sk_buff *skb)
if (((W_max - member->dsp->W_rx) & CMX_BUFF_MASK) >= CMX_BUFF_HALF)
W_max = member->dsp->W_rx;
}
member = member->next;
}
}
@ -990,9 +980,9 @@ dsp_cmx_receive(dsp_t *dsp, struct sk_buff *skb)
if (conf) {
#ifdef CMX_CONF_DEBUG
#warning CMX_CONF_DEBUG is enabled, it causes performance loss with normal 2-party crossconnects
if (conf->mlist) if (conf->mlist->next) {
if (2 <= count_list_member(&conf->mlist)) {
#else
if (conf->mlist) if (conf->mlist->next) if (conf->mlist->next->next) {
if (3 <= count_list_member(&conf->mlist)) {
#endif
//printk(KERN_DEBUG "cmxing dsp:%s dsp->W_rx=%04x conf->W_max=%04x\n", dsp->inst.name, dsp->W_rx, conf->W_max);
/* -> received data is added to conf-buffer
@ -1158,19 +1148,19 @@ struct sk_buff
dsp->R_tx = t;
return(nskb);
}
if (!conf->mlist->next) {
if (1 == count_list_member(&conf->mlist)) {
goto single;
}
/* STEP 2.2: PROCESS DATA (two members) */
#ifdef CMX_CONF_DEBUG
if (0) {
#else
if (!conf->mlist->next->next) {
if (2 == count_list_member(&conf->mlist)) {
#endif
/* "other" becomes other party */
other = conf->mlist->dsp;
other = (list_entry(conf->mlist.next, conf_member_t, list))->dsp;
if (other == member)
other = conf->mlist->next->dsp;
other = (list_entry(conf->mlist.prev, conf_member_t, list))->dsp;
o = other->rx_buff; /* received data */
/* -> if echo is NOT enabled */
if (!dsp->echo) {

View File

@ -677,7 +677,7 @@ release_dsp(dsp_t *dsp)
conf = dsp->conf;
if (conf) {
dsp_cmx_del_conf_member(dsp);
if (!conf->mlist) {
if (!list_empty(&conf->mlist)) {
dsp_cmx_del_conf(conf);
}
}
@ -695,7 +695,7 @@ release_dsp(dsp_t *dsp)
if (dsp_debug & DEBUG_DSP_MGR)
printk(KERN_DEBUG "%s: remove & destroy object %s\n", __FUNCTION__, dsp->inst.name);
REMOVE_FROM_LISTBASE(dsp, ((dsp_t *)dsp_obj.ilist));
list_del(&dsp->list);
dsp_obj.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
unlock_HW(&dsp_lock);
vfree(dsp);
@ -757,11 +757,11 @@ new_dsp(mISDNstack_t *st, mISDN_pid_t *pid)
INIT_WORK(&ndsp->sendwork, (void *)(void *)sendevent, ndsp);
lock_HW(&dsp_lock, 0);
/* append and register */
APPEND_TO_LIST(ndsp, ((dsp_t *)dsp_obj.ilist));
list_add_tail(&ndsp->list, &dsp_obj.ilist);
err = dsp_obj.ctrl(st, MGR_REGLAYER | INDICATION, &ndsp->inst);
if (err) {
printk(KERN_ERR "%s: failed to register layer %s\n", __FUNCTION__, ndsp->inst.name);
REMOVE_FROM_LISTBASE(ndsp, ((dsp_t *)dsp_obj.ilist));
list_del(&ndsp->list);
unlock_HW(&dsp_lock);
goto free_mem;
}
@ -811,17 +811,22 @@ dsp_feat(dsp_t *dsp)
static int
dsp_manager(void *data, u_int prim, void *arg) {
mISDNinstance_t *inst = data;
dsp_t *dspl = (dsp_t *)dsp_obj.ilist;
int ret = 0;
dsp_t *dspl;
int ret = -EINVAL;
if (dsp_debug & DEBUG_DSP_MGR)
printk(KERN_DEBUG "%s: data:%p prim:%x arg:%p\n", __FUNCTION__, data, prim, arg);
if (!data)
return(-EINVAL);
while(dspl) {
if (&dspl->inst == inst)
return(ret);
list_for_each_entry(dspl, &dsp_obj.ilist, list) {
if (&dspl->inst == inst) {
ret = 0;
break;
dspl = dspl->next;
}
}
if (ret && (prim != (MGR_NEWLAYER | REQUEST))) {
printk(KERN_WARNING "%s: given instance(%p) not in ilist.\n", __FUNCTION__, data);
return(ret);
}
switch(prim) {
@ -829,39 +834,19 @@ dsp_manager(void *data, u_int prim, void *arg) {
ret = new_dsp(data, arg);
break;
case MGR_CONNECT | REQUEST:
if (!dspl) {
printk(KERN_WARNING "%s: given instance(%p) not in ilist.\n", __FUNCTION__, data);
ret = -EINVAL;
break;
}
ret = mISDN_ConnectIF(inst, arg);
dsp_feat(dspl);
break;
case MGR_SETIF | REQUEST:
case MGR_SETIF | INDICATION:
if (!dspl) {
printk(KERN_WARNING "%s: given instance(%p) not in ilist.\n", __FUNCTION__, data);
ret = -EINVAL;
break;
}
ret = mISDN_SetIF(inst, arg, prim, dsp_from_up, dsp_from_down, dspl);
break;
case MGR_DISCONNECT | REQUEST:
case MGR_DISCONNECT | INDICATION:
if (!dspl) {
printk(KERN_WARNING "%s: given instance(%p) not in ilist.\n", __FUNCTION__, data);
ret = -EINVAL;
break;
}
ret = mISDN_DisConnectIF(inst, arg);
break;
case MGR_UNREGLAYER | REQUEST:
case MGR_RELEASE | INDICATION:
if (!dspl) {
printk(KERN_WARNING "%s: given instance(%p) not in ilist.\n", __FUNCTION__, data);
ret = -EINVAL;
break;
}
if (dsp_debug & DEBUG_DSP_MGR)
printk(KERN_DEBUG "%s: release_dsp id %x\n", __FUNCTION__, dspl->inst.st->id);
@ -922,9 +907,7 @@ static int dsp_init(void)
dsp_obj.name = DSPName;
dsp_obj.BPROTO.protocol[3] = ISDN_PID_L3_B_DSP;
dsp_obj.own_ctrl = dsp_manager;
dsp_obj.prev = NULL;
dsp_obj.next = NULL;
dsp_obj.ilist = NULL;
INIT_LIST_HEAD(&dsp_obj.ilist);
/* initialize audio tables */
silence = (dsp_options&DSP_OPT_ULAW)?0xff:0x2a;
@ -954,7 +937,8 @@ static int dsp_init(void)
*/
static void dsp_cleanup(void)
{
int err;
dsp_t *dspl, *nd;
int err;
if (dsp_debug & DEBUG_DSP_MGR)
printk(KERN_DEBUG "%s: removing module\n", __FUNCTION__);
@ -963,12 +947,12 @@ static void dsp_cleanup(void)
printk(KERN_ERR "mISDN_dsp: Can't unregister Audio DSP error(%d)\n",
err);
}
if(dsp_obj.ilist) {
if (!list_empty(&dsp_obj.ilist)) {
printk(KERN_WARNING "mISDN_dsp: Audio DSP object inst list not empty.\n");
while(dsp_obj.ilist)
release_dsp(dsp_obj.ilist);
list_for_each_entry_safe(dspl, nd, &dsp_obj.ilist, list)
release_dsp(dspl);
}
if (Conf_list) {
if (!list_empty(&Conf_list)) {
printk(KERN_ERR "mISDN_dsp: Conference list not empty. Not all memory freed.\n");
}
}

View File

@ -24,14 +24,13 @@
#define DTMF_NPOINTS 205 /* Number of samples for DTMF recognition */
typedef struct _dtmf {
struct _dtmf *prev;
struct _dtmf *next;
u_long Flags;
int debug;
char last;
int idx;
int buf[DTMF_NPOINTS];
mISDNinstance_t inst;
struct list_head list;
u_long Flags;
int debug;
char last;
int idx;
int buf[DTMF_NPOINTS];
mISDNinstance_t inst;
} dtmf_t;
#define FLG_DTMF_ULAW 1
@ -490,7 +489,7 @@ release_dtmf(dtmf_t *dtmf) {
inst->down.peer->obj->ctrl(inst->down.peer,
MGR_DISCONNECT | REQUEST, &inst->down);
}
REMOVE_FROM_LISTBASE(dtmf, ((dtmf_t *)dtmf_obj.ilist));
list_del(&dtmf->list);
dtmf_obj.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
kfree(dtmf);
}
@ -515,10 +514,10 @@ new_dtmf(mISDNstack_t *st, mISDN_pid_t *pid) {
return(-ENOPROTOOPT);
}
n_dtmf->debug = debug;
APPEND_TO_LIST(n_dtmf, ((dtmf_t *)dtmf_obj.ilist));
list_add_tail(&n_dtmf->list, &dtmf_obj.ilist);
err = dtmf_obj.ctrl(st, MGR_REGLAYER | INDICATION, &n_dtmf->inst);
if (err) {
REMOVE_FROM_LISTBASE(n_dtmf, ((dtmf_t *)dtmf_obj.ilist));
list_del(&n_dtmf->list);
kfree(n_dtmf);
}
return(err);
@ -559,23 +558,25 @@ MODULE_LICENSE("GPL");
static int
dtmf_manager(void *data, u_int prim, void *arg) {
mISDNinstance_t *inst = data;
dtmf_t *dtmf_l = dtmf_obj.ilist;
mISDNinstance_t *inst = data;
dtmf_t *dtmf_l;
int ret = -EINVAL;
if (debug & DEBUG_DTMF_MGR)
printk(KERN_DEBUG "dtmf_manager data:%p prim:%x arg:%p\n", data, prim, arg);
if (!data)
return(-EINVAL);
while(dtmf_l) {
if (&dtmf_l->inst == inst)
return(ret);
list_for_each_entry(dtmf_l, &dtmf_obj.ilist, list) {
if (&dtmf_l->inst == inst) {
ret = 0;
break;
dtmf_l = dtmf_l->next;
}
}
if (prim == (MGR_NEWLAYER | REQUEST))
return(new_dtmf(data, arg));
if (!dtmf_l) {
if (ret) {
printk(KERN_WARNING "dtmf_manager prim(%x) no instance\n", prim);
return(-EINVAL);
return(ret);
}
switch(prim) {
case MGR_CLRSTPARA | INDICATION:
@ -616,9 +617,7 @@ static int dtmf_init(void)
dtmf_obj.name = MName;
dtmf_obj.BPROTO.protocol[2] = ISDN_PID_L2_B_TRANSDTMF;
dtmf_obj.own_ctrl = dtmf_manager;
dtmf_obj.prev = NULL;
dtmf_obj.next = NULL;
dtmf_obj.ilist = NULL;
INIT_LIST_HEAD(&dtmf_obj.ilist);
if ((err = mISDN_register(&dtmf_obj))) {
printk(KERN_ERR "Can't register %s error(%d)\n", MName, err);
}
@ -627,15 +626,16 @@ static int dtmf_init(void)
static void dtmf_cleanup(void)
{
int err;
int err;
dtmf_t *dtmf, *nd;
if ((err = mISDN_unregister(&dtmf_obj))) {
printk(KERN_ERR "Can't unregister DTMF error(%d)\n", err);
}
if(dtmf_obj.ilist) {
if (!list_empty(&dtmf_obj.ilist)) {
printk(KERN_WARNING "dtmf inst list not empty\n");
while(dtmf_obj.ilist)
release_dtmf(dtmf_obj.ilist);
list_for_each_entry_safe(dtmf, nd, &dtmf_obj.ilist, list)
release_dtmf(dtmf);
}
}

View File

@ -21,8 +21,7 @@
static int ttt=180;
typedef struct _faxl3 {
struct _faxl3 *prev;
struct _faxl3 *next;
struct list_head list;
spinlock_t lock;
u_long state;
int debug;
@ -1953,7 +1952,7 @@ release_faxl3(faxl3_t *faxl3) {
inst->down.peer->obj->ctrl(inst->down.peer,
MGR_DISCONNECT | REQUEST, &inst->down);
}
REMOVE_FROM_LISTBASE(faxl3, ((faxl3_t *)faxl3_obj.ilist));
list_del(&faxl3->list);
discard_queue(&faxl3->downq);
discard_queue(&faxl3->dataq);
discard_queue(&faxl3->pageq);
@ -2048,7 +2047,7 @@ new_faxl3(mISDNstack_t *st, mISDN_pid_t *pid) {
skb_queue_head_init(&n_faxl3->pageq);
skb_queue_head_init(&n_faxl3->saveq);
APPEND_TO_LIST(n_faxl3, ((faxl3_t *)faxl3_obj.ilist));
list_add_tail(&n_faxl3->list, &faxl3_obj.ilist);
n_faxl3->entity = MISDN_ENTITY_NONE;
err = faxl3_obj.ctrl(&n_faxl3->inst, MGR_NEWENTITY | REQUEST, NULL);
if (err) {
@ -2057,7 +2056,7 @@ new_faxl3(mISDNstack_t *st, mISDN_pid_t *pid) {
}
err = faxl3_obj.ctrl(st, MGR_REGLAYER | INDICATION, &n_faxl3->inst);
if (err) {
REMOVE_FROM_LISTBASE(n_faxl3, ((faxl3_t *)faxl3_obj.ilist));
list_del(&n_faxl3->list);
kfree(n_faxl3);
} else {
if (st->para.maxdatalen)
@ -2075,23 +2074,25 @@ new_faxl3(mISDNstack_t *st, mISDN_pid_t *pid) {
static int
faxl3_manager(void *data, u_int prim, void *arg) {
mISDNinstance_t *inst = data;
faxl3_t *faxl3_l = faxl3_obj.ilist;
mISDNinstance_t *inst = data;
faxl3_t *faxl3_l;
int err = -EINVAL;
if (debug & DEBUG_FAXL3_MGR)
printk(KERN_DEBUG "faxl3_manager data:%p prim:%x arg:%p\n", data, prim, arg);
if (!data)
return(-EINVAL);
while(faxl3_l) {
if (&faxl3_l->inst == inst)
return(err);
list_for_each_entry(faxl3_l, &faxl3_obj.ilist, list) {
if (&faxl3_l->inst == inst) {
err = 0;
break;
faxl3_l = faxl3_l->next;
}
}
if (prim == (MGR_NEWLAYER | REQUEST))
return(new_faxl3(data, arg));
if (!faxl3_l) {
if (err) {
printk(KERN_WARNING "faxl3_manager prim(%x) no instance\n", prim);
return(-EINVAL);
return(err);
}
switch(prim) {
case MGR_CLRSTPARA | INDICATION:
@ -2145,9 +2146,7 @@ static int faxl3_init(void)
faxl3_obj.name = MName;
faxl3_obj.BPROTO.protocol[3] = ISDN_PID_L3_B_T30;
faxl3_obj.own_ctrl = faxl3_manager;
faxl3_obj.prev = NULL;
faxl3_obj.next = NULL;
faxl3_obj.ilist = NULL;
INIT_LIST_HEAD(&faxl3_obj.ilist);
if ((err = mISDN_register(&faxl3_obj))) {
printk(KERN_ERR "Can't register %s error(%d)\n", MName, err);
return(err);
@ -2167,15 +2166,16 @@ static int faxl3_init(void)
static void faxl3_cleanup(void)
{
int err;
faxl3_t *l3, *nl3;
int err;
if ((err = mISDN_unregister(&faxl3_obj))) {
printk(KERN_ERR "Can't unregister DTMF error(%d)\n", err);
}
if(faxl3_obj.ilist) {
if(!list_empty(&faxl3_obj.ilist)) {
printk(KERN_WARNING "faxl3 inst list not empty\n");
while(faxl3_obj.ilist)
release_faxl3(faxl3_obj.ilist);
list_for_each_entry_safe(l3, nl3, &faxl3_obj.ilist, list)
release_faxl3(l3);
}
mISDN_FsmFree(&faxl3fsm);
mISDN_FsmFree(&modfsm);

View File

@ -321,9 +321,10 @@ mISDN_ConnectIF(mISDNinstance_t *owner, mISDNinstance_t *peer)
int
mISDN_DisConnectIF(mISDNinstance_t *inst, mISDNif_t *hif) {
if (hif) {
if (hif->next && hif->next->owner) {
hif->next->owner->obj->ctrl(hif->next->owner,
MGR_DISCONNECT | REQUEST, hif->next);
if (hif->clone) {
if (hif->clone->owner)
hif->clone->owner->obj->ctrl(hif->clone->owner,
MGR_DISCONNECT | REQUEST, hif->clone);
}
if (inst->up.peer) {
if (inst->up.peer == hif->owner)
@ -354,6 +355,10 @@ mISDN_init_instance(mISDNinstance_t *inst, mISDNobject_t *obj, void *data)
inst->data = data;
inst->up.owner = inst;
inst->down.owner = inst;
inst->up.clone = NULL;
inst->up.predecessor = NULL;
inst->down.clone = NULL;
inst->down.predecessor = NULL;
obj->ctrl(NULL, MGR_DISCONNECT | REQUEST, &inst->down);
obj->ctrl(NULL, MGR_DISCONNECT | REQUEST, &inst->up);
}

View File

@ -20,42 +20,6 @@
printk(KERN_ERR "mISDN: INTERNAL ERROR in %s:%d " fmt "\n", \
__FILE__, __LINE__, ## arg)
#define APPEND_TO_LIST(item,base) \
if (item->prev || item->next) \
int_errtxt("APPEND not clean %p<-%p->%p", \
item->prev, item, item->next); \
item->next = NULL; \
item->prev = base; \
while (item->prev && item->prev->next) \
item->prev = item->prev->next; \
if (item->prev == item) { \
int_errtxt("APPEND DUP %p", item); \
} else \
if (base) { \
item->prev->next = item; \
} else \
base = item
#define INSERT_INTO_LIST(newi,nexti,base) \
newi->next = nexti; \
newi->prev = nexti->prev; \
if (newi->prev) \
newi->prev->next = newi; \
nexti->prev = newi; \
if (base == nexti) \
base = newi
#define REMOVE_FROM_LIST(item) \
if (item->prev) \
item->prev->next = item->next; \
if (item->next) \
item->next->prev = item->prev
#define REMOVE_FROM_LISTBASE(item,base) \
REMOVE_FROM_LIST(item); \
if (item == base) \
base = item->next
static inline int
discard_queue(struct sk_buff_head *q)
{
@ -103,6 +67,17 @@ extern int mISDN_SetHandledPID(mISDNobject_t *, mISDN_pid_t *);
extern void mISDN_RemoveUsedPID(mISDN_pid_t *, mISDN_pid_t *);
extern void mISDN_init_instance(mISDNinstance_t *, mISDNobject_t *, void *);
static inline int
count_list_member(struct list_head *head)
{
int cnt = 0;
struct list_head *m;
list_for_each(m, head)
cnt++;
return(cnt);
}
static inline int
mISDN_HasProtocolP(mISDNobject_t *obj, int *PP)
{

View File

@ -2191,7 +2191,7 @@ hfcmulti_dch_bh(dchannel_t *dch)
if (hc->created[hc->chan[ch].port]) {
while(upif) {
if_link(upif, prim, para, 0, NULL, 0);
upif = upif->next;
upif = upif->clone;
}
}
}
@ -2479,11 +2479,12 @@ init_card(hfc_multi_t *hc)
static int
SelFreeBChannel(hfc_multi_t *hc, int ch, channel_info_t *ci)
{
bchannel_t *bch;
hfc_multi_t *hfc;
mISDNstack_t *bst;
int cnr;
int port = hc->chan[ch].port;
bchannel_t *bch;
hfc_multi_t *hfc;
mISDNstack_t *bst;
struct list_head *head;
int cnr;
int port = hc->chan[ch].port;
if (port < 0 || port>=hc->type) {
printk(KERN_WARNING "%s: port(%d) out of range", __FUNCTION__, port);
@ -2493,9 +2494,20 @@ SelFreeBChannel(hfc_multi_t *hc, int ch, channel_info_t *ci)
if (!ci)
return(-EINVAL);
ci->st.p = NULL;
bst = hc->chan[ch].dch->inst.st->child;
cnr=0;
while(bst) {
bst = hc->chan[ch].dch->inst.st;
if (list_empty(&bst->childlist)) {
if ((bst->id & FLG_CLONE_STACK) &&
(bst->childlist.prev != &bst->childlist)) {
head = bst->childlist.prev;
} else {
printk(KERN_ERR "%s: invalid empty childlist (no clone) stid(%x) childlist(%p<-%p->%p)\n",
__FUNCTION__, bst->id, bst->childlist.prev, &bst->childlist, bst->childlist.next);
return(-EINVAL);
}
} else
head = &bst->childlist;
list_for_each_entry(bst, head, list) {
if (cnr == ((hc->type==1)?30:2)) /* 30 or 2 B-channels */ {
printk(KERN_WARNING "%s: fatal error: more b-stacks than ports", __FUNCTION__);
return(-EINVAL);
@ -2529,7 +2541,6 @@ SelFreeBChannel(hfc_multi_t *hc, int ch, channel_info_t *ci)
}
}
cnr++;
bst = bst->next;
}
return(-EBUSY);
}
@ -2783,7 +2794,7 @@ release_port(hfc_multi_t *hc, int port)
if (debug & DEBUG_HFCMULTI_INIT)
printk(KERN_DEBUG "%s: removing object from listbase\n", __FUNCTION__);
REMOVE_FROM_LISTBASE(hc, ((hfc_multi_t *)HFCM_obj.ilist));
list_del(&hc->list);
kfree(hc);
}
@ -2793,7 +2804,7 @@ release_port(hfc_multi_t *hc, int port)
static int
HFC_manager(void *data, u_int prim, void *arg)
{
hfc_multi_t *hc = HFCM_obj.ilist;
hfc_multi_t *hc;
mISDNinstance_t *inst = data;
struct sk_buff *skb;
dchannel_t *dch = NULL;
@ -2808,7 +2819,7 @@ HFC_manager(void *data, u_int prim, void *arg)
}
/* find channel and card */
while(hc) {
list_for_each_entry(hc, &HFCM_obj.ilist, list) {
i = 0;
while(i < 32) {
//printk(KERN_DEBUG "comparing (D-channel) card=%08x inst=%08x with inst=%08x\n", hc, &hc->dch[i].inst, inst);
@ -2828,8 +2839,6 @@ HFC_manager(void *data, u_int prim, void *arg)
}
if (ch >= 0)
break;
hc = hc->next;
}
if (ch < 0) {
printk(KERN_ERR "%s: no card/channel found data %p prim %x arg %p\n", __FUNCTION__, data, prim, arg);
@ -2955,7 +2964,7 @@ static int __init
HFCmulti_init(void)
{
int err, err2, i;
hfc_multi_t *hc;
hfc_multi_t *hc,*next;
mISDN_pid_t pid, pids[MAX_CARDS];
mISDNstack_t *dst = NULL; /* make gcc happy */
int port_cnt;
@ -3004,6 +3013,7 @@ HFCmulti_init(void)
#ifdef MODULE
HFCM_obj.owner = THIS_MODULE;
#endif
INIT_LIST_HEAD(&HFCM_obj.ilist);
HFCM_obj.name = HFCName;
HFCM_obj.own_ctrl = HFC_manager;
HFCM_obj.DPROTO.protocol[0] = ISDN_PID_L0_TE_S0 | ISDN_PID_L0_NT_S0
@ -3087,7 +3097,7 @@ HFCmulti_init(void)
if (debug & DEBUG_HFCMULTI_INIT)
printk(KERN_DEBUG "%s: (after APPEND_TO_LIST)\n", __FUNCTION__);
APPEND_TO_LIST(hc, ((hfc_multi_t *)HFCM_obj.ilist));
list_add_tail(&hc->list, &HFCM_obj.ilist);
if (debug & DEBUG_HFCMULTI_INIT)
printk(KERN_DEBUG "%s: (after APPEND_TO_LIST)\n", __FUNCTION__);
@ -3415,7 +3425,7 @@ HFCmulti_init(void)
}
if (debug & DEBUG_HFCMULTI_INIT)
printk(KERN_DEBUG "%s: before REMOVE_FROM_LIST (refcnt = %d)\n", __FUNCTION__, HFCM_obj.refcnt);
REMOVE_FROM_LISTBASE(hc, ((hfc_multi_t *)HFCM_obj.ilist));
list_del(&hc->list);
if (debug & DEBUG_HFCMULTI_INIT)
printk(KERN_DEBUG "%s: after REMOVE_FROM_LIST (refcnt = %d)\n", __FUNCTION__, HFCM_obj.refcnt);
kfree(hc);
@ -3426,9 +3436,9 @@ HFCmulti_init(void)
if ((err2 = mISDN_unregister(&HFCM_obj))) {
printk(KERN_ERR "Can't unregister HFC-Multi cards error(%d)\n", err);
}
while(HFCM_obj.ilist) {
list_for_each_entry_safe(hc, next, &HFCM_obj.ilist, list) {
printk(KERN_ERR "HFC PCI card struct not empty refs %d\n", HFCM_obj.refcnt);
release_port(HFCM_obj.ilist, -1); /* all ports */
release_port(hc, -1); /* all ports */
}
if (debug & DEBUG_HFCMULTI_INIT)
printk(KERN_DEBUG "%s: after mISDN_unregister (refcnt = %d)\n", __FUNCTION__, HFCM_obj.refcnt);
@ -3443,6 +3453,7 @@ HFCmulti_init(void)
static void __exit
HFCmulti_cleanup(void)
{
hfc_multi_t *hc,*next;
int err;
if (debug & DEBUG_HFCMULTI_INIT)
@ -3452,9 +3463,10 @@ HFCmulti_cleanup(void)
}
if (debug & DEBUG_HFCMULTI_INIT)
printk(KERN_DEBUG "%s: now checking ilist (refcnt = %d)\n", __FUNCTION__, HFCM_obj.refcnt);
while(HFCM_obj.ilist) {
list_for_each_entry_safe(hc, next, &HFCM_obj.ilist, list) {
printk(KERN_ERR "HFC PCI card struct not empty refs %d\n", HFCM_obj.refcnt);
release_port(HFCM_obj.ilist, -1); /* all ports */
release_port(hc, -1); /* all ports */
}
if (debug & DEBUG_HFCMULTI_INIT)
printk(KERN_DEBUG "%s: done (refcnt = %d)\n", __FUNCTION__, HFCM_obj.refcnt);

View File

@ -86,9 +86,7 @@ typedef struct hfcmulti_hw hfcmulti_hw_t;
#define HFC_CHIP_CLOCK2 6 /* double clock mode */
struct hfc_multi {
struct hfc_multi *prev;
struct hfc_multi *next;
struct list_head list;
char name[32];
int id; /* chip number starting with 1 */
int pcm; /* id of pcm bus */

View File

@ -158,17 +158,16 @@ typedef struct hfcPCI_hw hfcPCI_hw_t;
#define HFC_CFG_SW_DD_DU 7
typedef struct _hfc_pci {
struct _hfc_pci *prev;
struct _hfc_pci *next;
u_char subtyp;
u_char chanlimit;
u_long cfg;
u_int irq;
u_int irqcnt;
hfcPCI_hw_t hw;
mISDN_HWlock_t lock;
dchannel_t dch;
bchannel_t bch[2];
struct list_head list;
u_char subtyp;
u_char chanlimit;
u_long cfg;
u_int irq;
u_int irqcnt;
hfcPCI_hw_t hw;
mISDN_HWlock_t lock;
dchannel_t dch;
bchannel_t bch[2];
} hfc_pci_t;
@ -1915,7 +1914,7 @@ HW_hfcD_bh(dchannel_t *dch)
}
while(upif) {
if_link(upif, prim, para, 0, NULL, 0);
upif = upif->next;
upif = upif->clone;
}
}
}
@ -2034,17 +2033,29 @@ static int init_card(hfc_pci_t *hc)
static int
SelFreeBChannel(hfc_pci_t *hc, channel_info_t *ci)
{
bchannel_t *bch;
hfc_pci_t *hfc;
mISDNstack_t *bst;
u_int cnr;
bchannel_t *bch;
hfc_pci_t *hfc;
mISDNstack_t *bst;
u_int cnr;
struct list_head *head;
if (!ci)
return(-EINVAL);
ci->st.p = NULL;
bst = hc->dch.inst.st->child;
cnr=0;
while(bst) {
bst = hc->dch.inst.st;
if (list_empty(&bst->childlist)) {
if ((bst->id & FLG_CLONE_STACK) &&
(bst->childlist.prev != &bst->childlist)) {
head = bst->childlist.prev;
} else {
printk(KERN_ERR "%s: invalid empty childlist (no clone) stid(%x) childlist(%p<-%p->%p)\n",
__FUNCTION__, bst->id, bst->childlist.prev, &bst->childlist, bst->childlist.next);
return(-EINVAL);
}
} else
head = &bst->childlist;
list_for_each_entry(bst, head, list) {
if(!bst->mgr) {
int_errtxt("no mgr st(%p)", bst);
return(-EINVAL);
@ -2076,7 +2087,6 @@ SelFreeBChannel(hfc_pci_t *hc, channel_info_t *ci)
}
}
cnr++;
bst = bst->next;
}
return(-EBUSY);
}
@ -2178,12 +2188,12 @@ setup_hfcpci(hfc_pci_t *hc)
/* Allocate memory for FIFOS */
/* Because the HFC-PCI needs a 32K physical alignment, we */
/* need to allocate the double mem and align the address */
if (!((void *) hc->hw.share_start = kmalloc(65536, GFP_KERNEL))) {
if (!(hc->hw.share_start = kmalloc(65536, GFP_KERNEL))) {
printk(KERN_WARNING "HFC-PCI: Error allocating memory for FIFO!\n");
return 1;
}
(ulong) hc->hw.fifos =
(((ulong) hc->hw.share_start) & ~0x7FFF) + 0x8000;
hc->hw.fifos = (void *)
((((ulong) hc->hw.share_start) & ~0x7FFF) + 0x8000);
pci_write_config_dword(hc->hw.dev, 0x80, (u_int) virt_to_bus(hc->hw.fifos));
hc->hw.pci_io = ioremap((ulong) hc->hw.pci_io, 256);
printk(KERN_INFO
@ -2234,14 +2244,14 @@ release_card(hfc_pci_t *hc) {
mISDN_free_dch(&hc->dch);
HFC_obj.ctrl(hc->dch.inst.up.peer, MGR_DISCONNECT | REQUEST, &hc->dch.inst.up);
HFC_obj.ctrl(&hc->dch.inst, MGR_UNREGLAYER | REQUEST, NULL);
REMOVE_FROM_LISTBASE(hc, ((hfc_pci_t *)HFC_obj.ilist));
list_del(&hc->list);
unlock_dev(hc);
kfree(hc);
}
static int
HFC_manager(void *data, u_int prim, void *arg) {
hfc_pci_t *card = HFC_obj.ilist;
hfc_pci_t *card;
mISDNinstance_t *inst = data;
struct sk_buff *skb;
int channel = -1;
@ -2252,7 +2262,7 @@ HFC_manager(void *data, u_int prim, void *arg) {
__FUNCTION__, prim, arg);
return(-EINVAL);
}
while(card) {
list_for_each_entry(card, &HFC_obj.ilist, list) {
if (&card->dch.inst == inst) {
channel = 2;
break;
@ -2266,7 +2276,6 @@ HFC_manager(void *data, u_int prim, void *arg) {
channel = 1;
break;
}
card = card->next;
}
if (channel<0) {
printk(KERN_ERR "%s: no channel data %p prim %x arg %p\n",
@ -2371,6 +2380,7 @@ static int __init HFC_init(void)
#ifdef MODULE
HFC_obj.owner = THIS_MODULE;
#endif
INIT_LIST_HEAD(&HFC_obj.ilist);
HFC_obj.name = HFCName;
HFC_obj.own_ctrl = HFC_manager;
HFC_obj.DPROTO.protocol[0] = ISDN_PID_L0_TE_S0 |
@ -2380,8 +2390,6 @@ static int __init HFC_init(void)
ISDN_PID_L1_B_64HDLC;
HFC_obj.BPROTO.protocol[2] = ISDN_PID_L2_B_TRANS |
ISDN_PID_L2_B_RAWDEV;
HFC_obj.prev = NULL;
HFC_obj.next = NULL;
if ((err = mISDN_register(&HFC_obj))) {
printk(KERN_ERR "Can't register HFC PCI error(%d)\n", err);
return(err);
@ -2393,7 +2401,7 @@ static int __init HFC_init(void)
return(-ENOMEM);
}
memset(card, 0, sizeof(hfc_pci_t));
APPEND_TO_LIST(card, ((hfc_pci_t *)HFC_obj.ilist));
list_add_tail(&card->list, &HFC_obj.ilist);
card->dch.debug = debug;
lock_HW_init(&card->lock);
card->dch.inst.lock = lock_dev;
@ -2420,7 +2428,10 @@ static int __init HFC_init(void)
}
}
if (protocol[HFC_cnt] == 0x100) {
prev = card->prev;
if (card->list.prev == &HFC_obj.ilist)
prev = NULL;
else
prev = list_entry(card->list.prev, hfc_pci_t, list);
if (!prev) {
int_errtxt("card(%d) no previous HFC",
@ -2475,7 +2486,7 @@ static int __init HFC_init(void)
mISDN_free_dch(&card->dch);
mISDN_free_bch(&card->bch[1]);
mISDN_free_bch(&card->bch[0]);
REMOVE_FROM_LISTBASE(card, ((hfc_pci_t *)HFC_obj.ilist));
list_del(&card->list);
kfree(card);
if (!HFC_cnt) {
mISDN_unregister(&HFC_obj);
@ -2545,14 +2556,16 @@ static int __init HFC_init(void)
#ifdef MODULE
static void __exit HFC_cleanup(void)
{
int err;
hfc_pci_t *card, *next;
int err;
if ((err = mISDN_unregister(&HFC_obj))) {
printk(KERN_ERR "Can't unregister HFC PCI error(%d)\n", err);
}
while(HFC_obj.ilist) {
list_for_each_entry_safe(card, next, &HFC_obj.ilist, list) {
printk(KERN_ERR "HFC PCI card struct not empty refs %d\n",
HFC_obj.refcnt);
release_card(HFC_obj.ilist);
release_card(card);
}
return;
}

View File

@ -92,7 +92,7 @@ isac_new_ph(dchannel_t *dch)
}
while(upif) {
if_link(upif, prim, para, 0, NULL, 0);
upif = upif->next;
upif = upif->clone;
}
}

View File

@ -1516,7 +1516,7 @@ l3dss1_global_restart(l3_process_t *pc, u_char pr, void *arg)
u_char *p, ri, ch = 0, chan = 0;
struct sk_buff *skb = arg;
Q931_info_t *qi = (Q931_info_t *)skb->data;
l3_process_t *up;
l3_process_t *up, *n;
// newl3state(pc, 2);
L3DelTimer(&pc->timer);
@ -1539,13 +1539,11 @@ l3dss1_global_restart(l3_process_t *pc, u_char pr, void *arg)
if (pc->l3->debug)
l3_debug(pc->l3, "Restart for channel %d", chan);
}
up = pc->l3->proc;
while (up) {
list_for_each_entry_safe(up, n, &pc->l3->plist, list) {
if ((ri & 7) == 7)
dss1man(up, CC_RESTART | REQUEST, NULL);
else if (up->bc == chan)
mISDN_l3up(up, CC_RESTART | REQUEST, NULL);
up = up->next;
}
dev_kfree_skb(skb);
skb = MsgStart(pc, MT_RESTART_ACKNOWLEDGE, chan ? 6 : 3);
@ -2221,7 +2219,7 @@ release_udss1(layer3_t *l3)
inst->down.peer->obj->ctrl(inst->down.peer,
MGR_DISCONNECT | REQUEST, &inst->down);
}
REMOVE_FROM_LISTBASE(l3, ((layer3_t *)u_dss1.ilist));
list_del(&l3->list);
u_dss1.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
if (l3->entity != MISDN_ENTITY_NONE)
u_dss1.ctrl(inst, MGR_DELENTITY | REQUEST, (void *)l3->entity);
@ -2270,7 +2268,7 @@ new_udss1(mISDNstack_t *st, mISDN_pid_t *pid)
nl3->global->state = 0;
nl3->global->callref = 0;
nl3->global->id = MISDN_ID_GLOBAL;
nl3->global->next = NULL;
INIT_LIST_HEAD(&nl3->global->list);
nl3->global->n303 = N303;
nl3->global->l3 = nl3;
nl3->global->t303skb = NULL;
@ -2284,14 +2282,14 @@ new_udss1(mISDNstack_t *st, mISDN_pid_t *pid)
nl3->dummy->state = 0;
nl3->dummy->callref = -1;
nl3->dummy->id = MISDN_ID_DUMMY;
nl3->dummy->next = NULL;
INIT_LIST_HEAD(&nl3->dummy->list);
nl3->dummy->n303 = N303;
nl3->dummy->l3 = nl3;
nl3->dummy->t303skb = NULL;
L3InitTimer(nl3->dummy, &nl3->dummy->timer);
sprintf(nl3->inst.name, "DSS1 %d", st->id);
nl3->p_mgr = dss1man;
APPEND_TO_LIST(nl3, ((layer3_t *)u_dss1.ilist));
list_add_tail(&nl3->list, &u_dss1.ilist);
err = u_dss1.ctrl(&nl3->inst, MGR_NEWENTITY | REQUEST, NULL);
if (err) {
printk(KERN_WARNING "mISDN %s: MGR_NEWENTITY REQUEST failed err(%x)\n",
@ -2300,7 +2298,7 @@ new_udss1(mISDNstack_t *st, mISDN_pid_t *pid)
err = u_dss1.ctrl(st, MGR_REGLAYER | INDICATION, &nl3->inst);
if (err) {
release_l3(nl3);
REMOVE_FROM_LISTBASE(nl3, ((layer3_t *)u_dss1.ilist));
list_del(&nl3->list);
kfree(nl3);
} else {
mISDN_stPara_t stp;
@ -2328,17 +2326,18 @@ MODULE_PARM(debug, "1i");
static int
udss1_manager(void *data, u_int prim, void *arg) {
mISDNinstance_t *inst = data;
layer3_t *l3l = u_dss1.ilist;
layer3_t *l3l;
if (debug & 0x1000)
printk(KERN_DEBUG "udss1_manager data:%p prim:%x arg:%p\n", data, prim, arg);
if (!data)
return(-EINVAL);
while(l3l) {
list_for_each_entry(l3l, &u_dss1.ilist, list) {
if (&l3l->inst == inst)
break;
l3l = l3l->next;
}
if (&l3l->list == &u_dss1.ilist)
l3l = NULL;
if (prim == (MGR_NEWLAYER | REQUEST))
return(new_udss1(data, arg));
if (!l3l) {
@ -2387,14 +2386,13 @@ int UDSS1Init(void)
#ifdef MODULE
u_dss1.owner = THIS_MODULE;
#endif
INIT_LIST_HEAD(&u_dss1.ilist);
u_dss1.name = MName;
u_dss1.DPROTO.protocol[3] = ISDN_PID_L3_DSS1USER |
ISDN_PID_L3_DF_PTP |
ISDN_PID_L3_DF_EXTCID |
ISDN_PID_L3_DF_CRLEN2;
u_dss1.own_ctrl = udss1_manager;
u_dss1.prev = NULL;
u_dss1.next = NULL;
mISDNl3New();
if ((err = mISDN_register(&u_dss1))) {
printk(KERN_ERR "Can't register %s error(%d)\n", MName, err);
@ -2407,14 +2405,15 @@ int UDSS1Init(void)
void UDSS1_cleanup(void)
{
int err;
layer3_t *l3, *next;
if ((err = mISDN_unregister(&u_dss1))) {
printk(KERN_ERR "Can't unregister User DSS1 error(%d)\n", err);
}
if (u_dss1.ilist) {
if (!list_empty(&u_dss1.ilist)) {
printk(KERN_WARNING "mISDNl3 u_dss1 list not empty\n");
while(u_dss1.ilist)
release_udss1(u_dss1.ilist);
list_for_each_entry_safe(l3, next, &u_dss1.ilist, list)
release_udss1(l3);
}
mISDNl3Free();
}

View File

@ -19,14 +19,13 @@ static char *l1_revision = "$Revision$";
#include "debug.h"
typedef struct _layer1 {
struct _layer1 *prev;
struct _layer1 *next;
u_long Flags;
struct FsmInst l1m;
struct FsmTimer timer;
int debug;
int delay;
mISDNinstance_t inst;
struct list_head list;
u_long Flags;
struct FsmInst l1m;
struct FsmTimer timer;
int debug;
int delay;
mISDNinstance_t inst;
} layer1_t;
/* l1 status_info */
@ -614,7 +613,7 @@ release_l1(layer1_t *l1) {
inst->down.peer->obj->ctrl(inst->down.peer,
MGR_DISCONNECT | REQUEST, &inst->down);
}
REMOVE_FROM_LISTBASE(l1, ((layer1_t *)isdnl1.ilist));
list_del(&l1->list);
isdnl1.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
kfree(l1);
}
@ -656,11 +655,11 @@ new_l1(mISDNstack_t *st, mISDN_pid_t *pid) {
nl1->l1m.userint = 0;
nl1->l1m.printdebug = l1m_debug;
mISDN_FsmInitTimer(&nl1->l1m, &nl1->timer);
APPEND_TO_LIST(nl1, ((layer1_t *)isdnl1.ilist));
list_add_tail(&nl1->list, &isdnl1.ilist);
err = isdnl1.ctrl(st, MGR_REGLAYER | INDICATION, &nl1->inst);
if (err) {
mISDN_FsmDelTimer(&nl1->timer, 0);
REMOVE_FROM_LISTBASE(nl1, ((layer1_t *)isdnl1.ilist));
list_del(&nl1->list);
kfree(nl1);
}
return(err);
@ -699,66 +698,57 @@ MODULE_LICENSE("GPL");
static int
l1_manager(void *data, u_int prim, void *arg) {
mISDNinstance_t *inst = data;
layer1_t *l1l = isdnl1.ilist;
mISDNinstance_t *inst = data;
layer1_t *l1l;
int err = -EINVAL;
if (debug & 0x10000)
printk(KERN_DEBUG "%s: data(%p) prim(%x) arg(%p)\n",
__FUNCTION__, data, prim, arg);
if (!data)
return(-EINVAL);
while(l1l) {
if (&l1l->inst == inst)
return(err);
list_for_each_entry(l1l, &isdnl1.ilist, list) {
if (&l1l->inst == inst) {
err = 0;
break;
l1l = l1l->next;
}
}
if (err && (prim != (MGR_NEWLAYER | REQUEST))) {
printk(KERN_WARNING "l1_manager connect no instance\n");
return(err);
}
switch(prim) {
case MGR_NEWLAYER | REQUEST:
return(new_l1(data, arg));
err = new_l1(data, arg);
break;
case MGR_CONNECT | REQUEST:
if (!l1l) {
printk(KERN_WARNING "l1_manager connect no instance\n");
return(-EINVAL);
}
return(mISDN_ConnectIF(inst, arg));
err = mISDN_ConnectIF(inst, arg);
break;
case MGR_SETIF | REQUEST:
case MGR_SETIF | INDICATION:
if (!l1l) {
printk(KERN_WARNING "l1_manager setif no instance\n");
return(-EINVAL);
}
return(mISDN_SetIF(inst, arg, prim, l1from_up, l1from_down, l1l));
err = mISDN_SetIF(inst, arg, prim, l1from_up, l1from_down, l1l);
break;
case MGR_DISCONNECT | REQUEST:
case MGR_DISCONNECT | INDICATION:
if (!l1l) {
printk(KERN_WARNING "l1_manager disconnect no instance\n");
return(-EINVAL);
}
return(mISDN_DisConnectIF(inst, arg));
err = mISDN_DisConnectIF(inst, arg);
break;
case MGR_UNREGLAYER | REQUEST:
case MGR_RELEASE | INDICATION:
if (l1l) {
printk(KERN_DEBUG "release_l1 id %x\n", l1l->inst.st->id);
release_l1(l1l);
} else
printk(KERN_WARNING "l1_manager release no instance\n");
break;
printk(KERN_DEBUG "release_l1 id %x\n", l1l->inst.st->id);
release_l1(l1l);
break;
case MGR_STATUS | REQUEST:
if (!l1l) {
printk(KERN_WARNING "l1_manager status l1 no instance\n");
return(-EINVAL);
}
return(l1_status(l1l, arg));
err = l1_status(l1l, arg);
break;
PRIM_NOT_HANDLED(MGR_CTRLREADY|INDICATION);
PRIM_NOT_HANDLED(MGR_ADDSTPARA|INDICATION);
default:
printk(KERN_WARNING "l1_manager prim %x not handled\n", prim);
return(-EINVAL);
err = -EINVAL;
break;
}
return(0);
return(err);
}
int Isdnl1Init(void)
@ -772,9 +762,7 @@ int Isdnl1Init(void)
isdnl1.name = MName;
isdnl1.DPROTO.protocol[1] = ISDN_PID_L1_TE_S0;
isdnl1.own_ctrl = l1_manager;
isdnl1.prev = NULL;
isdnl1.next = NULL;
isdnl1.ilist = NULL;
INIT_LIST_HEAD(&isdnl1.ilist);
#ifdef mISDN_UINTERFACE
isdnl1.DPROTO.protocol[1] |= ISDN_PID_L1_TE_U;
l1fsm_u.state_count = L1U_STATE_COUNT;
@ -807,15 +795,16 @@ int Isdnl1Init(void)
#ifdef MODULE
void cleanup_module(void)
{
int err;
int err;
layer1_t *l1, *nl1;
if ((err = mISDN_unregister(&isdnl1))) {
printk(KERN_ERR "Can't unregister ISDN layer 1 error(%d)\n", err);
}
if(isdnl1.ilist) {
if(!list_empty(&isdnl1.ilist)) {
printk(KERN_WARNING "mISDNl1 inst list not empty\n");
while(isdnl1.ilist)
release_l1(isdnl1.ilist);
list_for_each_entry_safe(l1, nl1, &isdnl1.ilist, list)
release_l1(l1);
}
#ifdef mISDN_UINTERFACE
mISDN_FsmFree(&l1fsm_u);

View File

@ -200,7 +200,7 @@ static int
ph_data_confirm(mISDNif_t *up, mISDN_head_t *hh, struct sk_buff *skb) {
layer2_t *l2 = up->fdata;
struct sk_buff *nskb = skb;
mISDNif_t *next = up->next;
mISDNif_t *next = up->clone;
int ret = -EAGAIN;
if (test_bit(FLG_L1_BUSY, &l2->flag)) {
@ -1885,16 +1885,18 @@ l2from_down(mISDNif_t *hif, struct sk_buff *askb)
layer2_t *l2;
int ret = -EINVAL;
struct sk_buff *cskb = askb;
mISDNif_t *next;
mISDN_head_t *hh, sh;
if (!hif || !askb)
return(-EINVAL);
l2 = hif->fdata;
hh = mISDN_HEAD_P(askb);
next = hif->clone;
// printk(KERN_DEBUG "%s: prim(%x)\n", __FUNCTION__, hh->prim);
if (!l2) {
if (hif->next && hif->next->func)
ret = hif->next->func(hif->next, askb);
if (next && next->func)
ret = next->func(next, askb);
return(ret);
}
if (hh->prim == (PH_DATA | CONFIRM))
@ -1912,14 +1914,14 @@ l2from_down(mISDNif_t *hif, struct sk_buff *askb)
}
}
}
if (hif->next && hif->next->func)
ret = hif->next->func(hif->next, askb);
if (next && next->func)
ret = next->func(next, askb);
return(ret);
}
if (hif->next) {
if (hif->next->func) {
if (next) {
if (next->func) {
if (!(cskb = skb_clone(askb, GFP_ATOMIC)))
return(hif->next->func(hif->next, askb));
return(next->func(next, askb));
else
sh = *hh;
}
@ -1960,9 +1962,9 @@ l2from_down(mISDNif_t *hif, struct sk_buff *askb)
dev_kfree_skb(cskb);
ret = 0;
}
if (hif->next && hif->next->func) {
if (next && next->func) {
*hh = sh;
ret = hif->next->func(hif->next, askb);
ret = next->func(next, askb);
}
return(ret);
}
@ -2096,14 +2098,17 @@ release_l2(layer2_t *l2)
if (l2->cloneif) {
printk(KERN_DEBUG "%s: cloneif(%p) owner(%p) peer(%p)\n",
__FUNCTION__, l2->cloneif, l2->cloneif->owner, l2->cloneif->peer);
REMOVE_FROM_LIST(l2->cloneif);
if (l2->cloneif->predecessor)
l2->cloneif->predecessor->clone = l2->cloneif->clone;
if (l2->cloneif->clone)
l2->cloneif->clone->predecessor = l2->cloneif->predecessor;
if (l2->cloneif->owner &&
(l2->cloneif->owner->up.next == l2->cloneif))
l2->cloneif->owner->up.next = l2->cloneif->next;
(l2->cloneif->owner->up.clone == l2->cloneif))
l2->cloneif->owner->up.clone = l2->cloneif->clone;
kfree(l2->cloneif);
l2->cloneif = NULL;
}
REMOVE_FROM_LISTBASE(l2, ((layer2_t *)isdnl2.ilist));
list_del(&l2->list);
isdnl2.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
if (l2->entity != MISDN_ENTITY_NONE)
isdnl2.ctrl(inst, MGR_DELENTITY | REQUEST, (void *)l2->entity);
@ -2225,7 +2230,7 @@ new_l2(mISDNstack_t *st, mISDN_pid_t *pid, layer2_t **newl2) {
mISDN_FsmInitTimer(&nl2->l2m, &nl2->t200);
mISDN_FsmInitTimer(&nl2->l2m, &nl2->t203);
APPEND_TO_LIST(nl2, ((layer2_t *)isdnl2.ilist));
list_add_tail(&nl2->list, &isdnl2.ilist);
err = isdnl2.ctrl(&nl2->inst, MGR_NEWENTITY | REQUEST, NULL);
if (err) {
printk(KERN_WARNING "mISDN %s: MGR_NEWENTITY REQUEST failed err(%x)\n",
@ -2235,7 +2240,7 @@ new_l2(mISDNstack_t *st, mISDN_pid_t *pid, layer2_t **newl2) {
if (err) {
mISDN_FsmDelTimer(&nl2->t200, 0);
mISDN_FsmDelTimer(&nl2->t203, 0);
REMOVE_FROM_LISTBASE(nl2, ((layer2_t *)isdnl2.ilist));
list_del(&nl2->list);
kfree(nl2);
nl2 = NULL;
} else {
@ -2286,7 +2291,10 @@ clone_l2(layer2_t *l2, mISDNinstance_t **new_ip) {
nif->owner = l2->inst.down.peer;
nif->peer = &nl2->inst;
nif->stat = IF_DOWN;
APPEND_TO_LIST(nif, nif->owner->up.next);
nif->predecessor = &nif->owner->up;
while(nif->predecessor->clone)
nif->predecessor = nif->predecessor->clone;
nif->predecessor->clone = nif;
nl2->inst.down.owner = &nl2->inst;
nl2->inst.down.peer = &l2->inst;
nl2->inst.down.func = l2_chain_down;
@ -2347,25 +2355,27 @@ MODULE_PARM(debug, "1i");
static int
l2_manager(void *data, u_int prim, void *arg) {
mISDNinstance_t *inst = data;
layer2_t *l2l = isdnl2.ilist;;
mISDNinstance_t *inst = data;
layer2_t *l2l;
int err = -EINVAL;
if (debug & 0x1000)
printk(KERN_DEBUG "%s: data:%p prim:%x arg:%p\n", __FUNCTION__,
data, prim, arg);
if (!data)
return(-EINVAL);
while(l2l) {
if (&l2l->inst == inst)
return(err);
list_for_each_entry(l2l, &isdnl2.ilist, list) {
if (&l2l->inst == inst) {
err = 0;
break;
l2l = l2l->next;
}
}
if (prim == (MGR_NEWLAYER | REQUEST))
return(new_l2(data, arg, NULL));
if (!l2l) {
if (err) {
if (debug & 0x1)
printk(KERN_WARNING "l2_manager prim(%x) l2 no instance\n", prim);
return(-EINVAL);
return(err);
}
switch(prim) {
case MGR_NEWENTITY | CONFIRM:
@ -2423,8 +2433,7 @@ int Isdnl2_Init(void)
ISDN_PID_L2_DF_PTP;
isdnl2.BPROTO.protocol[2] = ISDN_PID_L2_B_X75SLP;
isdnl2.own_ctrl = l2_manager;
isdnl2.prev = NULL;
isdnl2.next = NULL;
INIT_LIST_HEAD(&isdnl2.ilist);
l2fsm.state_count = L2_STATE_COUNT;
l2fsm.event_count = L2_EVENT_COUNT;
l2fsm.strEvent = strL2Event;
@ -2440,15 +2449,16 @@ int Isdnl2_Init(void)
void Isdnl2_cleanup(void)
{
int err;
int err;
layer2_t *l2, *nl2;
if ((err = mISDN_unregister(&isdnl2))) {
printk(KERN_ERR "Can't unregister ISDN layer 2 error(%d)\n", err);
}
if(isdnl2.ilist) {
if(!list_empty(&isdnl2.ilist)) {
printk(KERN_WARNING "mISDNl2 l2 list not empty\n");
while(isdnl2.ilist)
release_l2(isdnl2.ilist);
list_for_each_entry_safe(l2, nl2, &isdnl2.ilist, list)
release_l2(l2);
}
TEIFree();
mISDN_FsmFree(&l2fsm);

View File

@ -30,8 +30,7 @@ typedef struct _laddr {
} laddr_t;
typedef struct _layer2 {
struct _layer2 *prev;
struct _layer2 *next;
struct list_head list;
int sapi;
int tei;
laddr_t addr;

View File

@ -254,26 +254,22 @@ no_l3_proto_spec(struct PStack *st, isdn_ctrl *ic)
l3_process_t
*getl3proc(layer3_t *l3, int cr)
{
l3_process_t *p = l3->proc;
while (p)
l3_process_t *p;
list_for_each_entry(p, &l3->plist, list)
if (p->callref == cr)
return (p);
else
p = p->next;
return (NULL);
}
l3_process_t
*getl3proc4id(layer3_t *l3, u_int id)
{
l3_process_t *p = l3->proc;
l3_process_t *p;
while (p)
list_for_each_entry(p, &l3->plist, list)
if (p->id == id)
return (p);
else
p = p->next;
return (NULL);
}
@ -324,7 +320,7 @@ l3_process_t
p->callref = cr;
p->n303 = n303;
L3InitTimer(p, &p->timer);
APPEND_TO_LIST(p, l3->proc);
list_add_tail(&p->list, &l3->plist);
return (p);
};
@ -337,10 +333,10 @@ release_l3_process(l3_process_t *p)
return;
l3 = p->l3;
mISDN_l3up(p, CC_RELEASE_CR | INDICATION, NULL);
REMOVE_FROM_LISTBASE(p, l3->proc);
list_del(&p->list);
StopAllL3Timer(p);
kfree(p);
if (!l3->proc && !test_bit(FLG_PTP, &l3->Flag)) {
if (list_empty(&l3->plist) && !test_bit(FLG_PTP, &l3->Flag)) {
if (l3->debug)
l3_debug(l3, "release_l3_process: last process");
if (!skb_queue_len(&l3->squeue)) {
@ -357,15 +353,10 @@ release_l3_process(l3_process_t *p)
static void
l3ml3p(layer3_t *l3, int pr)
{
l3_process_t *p = l3->proc;
l3_process_t *np;
l3_process_t *p, *np;
while (p) {
/* p might be kfreed under us, so we need to save where we want to go on */
np = p->next;
list_for_each_entry_safe(p, np, &l3->plist, list)
l3->p_mgr(p, pr, NULL);
p = np;
}
}
int
@ -419,7 +410,7 @@ lc_connect(struct FsmInst *fi, int event, void *arg)
dev_kfree_skb(skb);
dequeued++;
}
if ((!l3->proc) && dequeued) {
if (list_empty(&l3->plist) && dequeued) {
if (l3->debug)
l3m_debug(fi, "lc_connect: release link");
mISDN_FsmEvent(&l3->l3m, EV_RELEASE_REQ, NULL);
@ -441,7 +432,7 @@ lc_connected(struct FsmInst *fi, int event, void *arg)
dev_kfree_skb(skb);
dequeued++;
}
if ((!l3->proc) && dequeued) {
if (list_empty(&l3->plist) && dequeued) {
if (l3->debug)
l3m_debug(fi, "lc_connected: release link");
mISDN_FsmEvent(&l3->l3m, EV_RELEASE_REQ, NULL);
@ -558,7 +549,7 @@ l3_msg(layer3_t *l3, u_int pr, int dinfo, int len, void *arg)
void
init_l3(layer3_t *l3)
{
l3->proc = NULL;
INIT_LIST_HEAD(&l3->plist);
l3->global = NULL;
l3->dummy = NULL;
l3->entity = MISDN_ENTITY_NONE;
@ -578,11 +569,13 @@ init_l3(layer3_t *l3)
void
release_l3(layer3_t *l3)
{
l3_process_t *p, *np;
if (l3->l3m.debug)
printk(KERN_DEBUG "release_l3(%p) proc(%p) global(%p) dummy(%p)\n",
l3, l3->proc, l3->global, l3->dummy);
while (l3->proc)
release_l3_process(l3->proc);
printk(KERN_DEBUG "release_l3(%p) plist(%s) global(%p) dummy(%p)\n",
l3, list_empty(&l3->plist) ? "no" : "yes", l3->global, l3->dummy);
list_for_each_entry_safe(p, np, &l3->plist, list)
release_l3_process(p);
if (l3->global) {
StopAllL3Timer(l3->global);
kfree(l3->global);

View File

@ -35,8 +35,7 @@ typedef struct _L3Timer {
} L3Timer_t;
typedef struct _l3_process {
struct _l3_process *prev;
struct _l3_process *next;
struct list_head list;
struct _layer3 *l3;
int callref;
int state;
@ -49,14 +48,13 @@ typedef struct _l3_process {
} l3_process_t;
typedef struct _layer3 {
struct _layer3 *prev;
struct _layer3 *next;
struct list_head list;
struct FsmInst l3m;
struct FsmTimer l3m_timer;
int entity;
int pid_cnt;
int next_id;
l3_process_t *proc;
struct list_head plist;
l3_process_t *global;
l3_process_t *dummy;
int (*p_mgr)(l3_process_t *, u_int, void *);

View File

@ -148,11 +148,10 @@ typedef struct FacConfParm FacConfParm_t;
// ---------------------------------------------------------------------------
struct _PLInst {
PLInst_t *prev;
PLInst_t *next;
u_int state;
mISDNstack_t *st;
mISDNinstance_t inst;
struct list_head list;
u_int state;
mISDNstack_t *st;
mISDNinstance_t inst;
};
struct _ConfQueue {
@ -175,11 +174,10 @@ struct Bprotocol {
// ---------------------------------------------------------------------------
struct _Controller {
struct _Controller *prev;
struct _Controller *next;
struct list_head list;
mISDNinstance_t inst;
int nr_bc;
PLInst_t *linklist;
struct list_head linklist;
struct capi_ctr *ctrl;
__u32 addr;
int entity;

View File

@ -109,8 +109,7 @@ const char *Sedlbauer_Types[] =
/* data struct */
typedef struct _sedl_fax {
struct _sedl_fax *prev;
struct _sedl_fax *next;
struct list_head list;
void *pdev;
u_int subtyp;
u_int irq;
@ -582,7 +581,7 @@ release_card(sedl_fax *card) {
mISDN_free_dch(&card->dch);
speedfax.ctrl(card->dch.inst.up.peer, MGR_DISCONNECT | REQUEST, &card->dch.inst.up);
speedfax.ctrl(&card->dch.inst, MGR_UNREGLAYER | REQUEST, NULL);
REMOVE_FROM_LISTBASE(card, ((sedl_fax *)speedfax.ilist));
list_del(&card->list);
unlock_dev(card);
if (card->subtyp == SEDL_SPEEDFAX_ISA) {
pnp_disable_dev(card->pdev);
@ -597,7 +596,7 @@ release_card(sedl_fax *card) {
static int
speedfax_manager(void *data, u_int prim, void *arg) {
sedl_fax *card = speedfax.ilist;
sedl_fax *card;
mISDNinstance_t *inst=data;
int channel = -1;
struct sk_buff *skb;
@ -610,7 +609,7 @@ speedfax_manager(void *data, u_int prim, void *arg) {
prim, arg);
return(-EINVAL);
}
while(card) {
list_for_each_entry(card, &speedfax.ilist, list) {
if (&card->dch.inst == inst) {
channel = 2;
break;
@ -623,7 +622,6 @@ speedfax_manager(void *data, u_int prim, void *arg) {
channel = 1;
break;
}
card = card->next;
}
if (channel<0) {
printk(KERN_ERR "speedfax_manager no channel data %p prim %x arg %p\n",
@ -731,7 +729,7 @@ static int __devinit setup_instance(sedl_fax *card)
kfree(card);
return(-EINVAL);
}
APPEND_TO_LIST(card, ((sedl_fax *)speedfax.ilist));
list_add_tail(&card->list, &speedfax.ilist);
card->dch.debug = debug;
lock_HW_init(&card->lock);
card->dch.inst.lock = lock_dev;
@ -759,7 +757,7 @@ static int __devinit setup_instance(sedl_fax *card)
mISDN_free_dch(&card->dch);
mISDN_free_bch(&card->bch[1]);
mISDN_free_bch(&card->bch[0]);
REMOVE_FROM_LISTBASE(card, ((sedl_fax *)speedfax.ilist));
list_del(&card->list);
kfree(card);
return(err);
}
@ -825,6 +823,7 @@ static int __devinit sedlpci_probe(struct pci_dev *pdev, const struct pci_device
return(err);
}
#if defined(CONFIG_PNP)
#ifdef NEW_ISAPNP
static int __devinit sedlpnp_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id)
#else
@ -864,6 +863,7 @@ static int __devinit sedlpnp_probe(struct pci_dev *pdev, const struct isapnp_dev
pnp_set_drvdata(pdev, NULL);
return(err);
}
#endif /* CONFIG_PNP */
static void __devexit sedl_remove_pci(struct pci_dev *pdev)
{
@ -875,6 +875,7 @@ static void __devexit sedl_remove_pci(struct pci_dev *pdev)
printk(KERN_WARNING "%s: drvdata allready removed\n", __FUNCTION__);
}
#if defined(CONFIG_PNP)
#ifdef NEW_ISAPNP
static void __devexit sedl_remove_pnp(struct pnp_dev *pdev)
#else
@ -888,6 +889,7 @@ static void __devexit sedl_remove_pnp(struct pci_dev *pdev)
else
printk(KERN_WARNING "%s: drvdata allready removed\n", __FUNCTION__);
}
#endif
static struct pci_device_id sedlpci_ids[] __devinitdata = {
{ PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_100, PCI_SUBVENDOR_SPEEDFAX_PYRAMID, PCI_SUB_ID_SEDLBAUER,
@ -905,6 +907,7 @@ static struct pci_driver sedlpci_driver = {
id_table: sedlpci_ids,
};
#if defined(CONFIG_PNP)
#ifdef NEW_ISAPNP
static struct pnp_device_id sedlpnp_ids[] __devinitdata = {
{
@ -930,6 +933,7 @@ static struct isapnp_driver sedlpnp_driver = {
remove: __devexit_p(sedl_remove_pnp),
id_table: sedlpnp_ids,
};
#endif /* CONFIG_PNP */
static int __init Speedfax_init(void)
{
@ -938,6 +942,7 @@ static int __init Speedfax_init(void)
#ifdef MODULE
speedfax.owner = THIS_MODULE;
#endif
INIT_LIST_HEAD(&speedfax.ilist);
speedfax.name = SpeedfaxName;
speedfax.own_ctrl = speedfax_manager;
speedfax.DPROTO.protocol[0] = ISDN_PID_L0_TE_S0;
@ -948,9 +953,6 @@ static int __init Speedfax_init(void)
speedfax.BPROTO.protocol[2] = ISDN_PID_L2_B_TRANS |
ISDN_PID_L2_B_T30;
speedfax.prev = NULL;
speedfax.next = NULL;
if ((err = mISDN_register(&speedfax))) {
printk(KERN_ERR "Can't register Speedfax error(%d)\n", err);
return(err);
@ -959,11 +961,11 @@ static int __init Speedfax_init(void)
if (err < 0)
goto out;
pci_nr_found = err;
#if defined(CONFIG_PNP)
err = pnp_register_driver(&sedlpnp_driver);
if (err < 0)
goto out_unregister_pci;
#endif
#if !defined(CONFIG_HOTPLUG) || defined(MODULE)
if (pci_nr_found + err == 0) {
err = -ENODEV;
@ -974,7 +976,9 @@ static int __init Speedfax_init(void)
#if !defined(CONFIG_HOTPLUG) || defined(MODULE)
out_unregister_isapnp:
#if defined(CONFIG_PNP)
pnp_unregister_driver(&sedlpnp_driver);
#endif
#endif
out_unregister_pci:
pci_unregister_driver(&sedlpci_driver);
@ -984,16 +988,20 @@ static int __init Speedfax_init(void)
static void __exit Speedfax_cleanup(void)
{
int err;
int err;
sedl_fax *card, *next;
if ((err = mISDN_unregister(&speedfax))) {
printk(KERN_ERR "Can't unregister Speedfax PCI error(%d)\n", err);
}
while(speedfax.ilist) {
list_for_each_entry_safe(card, next, &speedfax.ilist, list) {
printk(KERN_ERR "Speedfax PCI card struct not empty refs %d\n",
speedfax.refcnt);
release_card(speedfax.ilist);
release_card(card);
}
#if defined(CONFIG_PNP)
pnp_unregister_driver(&sedlpnp_driver);
#endif
pci_unregister_driver(&sedlpci_driver);
}

View File

@ -8,18 +8,16 @@
#include "core.h"
mISDNstack_t *mISDN_stacklist = NULL;
mISDNinstance_t *mISDN_instlist = NULL;
LIST_HEAD(mISDN_stacklist);
LIST_HEAD(mISDN_instlist);
int
get_stack_cnt(void) {
int cnt = 0;
mISDNstack_t *st = mISDN_stacklist;
mISDNstack_t *st;
while(st) {
list_for_each_entry(st, &mISDN_stacklist, list)
cnt++;
st = st->next;
}
return(cnt);
}
@ -44,20 +42,16 @@ get_stack_info(iframe_t *frm) {
memcpy(&si->pid, &st->pid, sizeof(mISDN_pid_t));
memcpy(&si->para, &st->para, sizeof(mISDN_stPara_t));
si->instcnt = 0;
lay = st->lstack;
while(lay) {
list_for_each_entry(lay, &st->layerlist, list) {
if (lay->inst) {
si->inst[si->instcnt] = lay->inst->id;
si->instcnt++;
}
lay = lay->next;
}
si->childcnt = 0;
cst = st->child;
while(cst) {
list_for_each_entry(cst, &st->childlist, list) {
si->child[si->childcnt] = cst->id;
si->childcnt++;
cst = cst->next;
}
frm->len = sizeof(stack_info_t);
if (si->childcnt>2)
@ -67,18 +61,19 @@ get_stack_info(iframe_t *frm) {
static int
get_free_stackid(mISDNstack_t *mst, int flag) {
u_int id=1;
u_int id=1, found;
mISDNstack_t *st;
if (!mst) {
while(id<127) {
st = mISDN_stacklist;
while (st) {
if (st->id == id)
found = 0;
list_for_each_entry(st, &mISDN_stacklist, list) {
if (st->id == id) {
found++;
break;
st = st->next;
}
}
if (st)
if (found)
id++;
else
return(id);
@ -86,27 +81,29 @@ get_free_stackid(mISDNstack_t *mst, int flag) {
} else if (flag & FLG_CLONE_STACK) {
id = mst->id | FLG_CLONE_STACK;
while(id < CLONE_ID_MAX) {
found = 0;
id += CLONE_ID_INC;
st = mISDN_stacklist;
while (st) {
if (st->id == id)
list_for_each_entry(st, &mISDN_stacklist, list) {
if (st->id == id) {
found++;
break;
st = st->next;
}
}
if (!st)
if (!found)
return(id);
}
} else if (flag & FLG_CHILD_STACK) {
id = mst->id | FLG_CHILD_STACK;
while(id < CHILD_ID_MAX) {
id += CHILD_ID_INC;
st = mst->child;
while (st) {
if (st->id == id)
found = 0;
list_for_each_entry(st, &mst->childlist, list) {
if (st->id == id) {
found++;
break;
st = st->next;
}
}
if (!st)
if (!found)
return(id);
}
}
@ -116,22 +113,19 @@ get_free_stackid(mISDNstack_t *mst, int flag) {
mISDNstack_t *
get_stack4id(u_int id)
{
mISDNstack_t *cst, *st = mISDN_stacklist;
mISDNstack_t *cst, *st;
if (core_debug & DEBUG_CORE_FUNC)
printk(KERN_DEBUG "get_stack4id(%x)\n", id);
if (!id) /* 0 isn't a valid id */
return(NULL);
while(st) {
list_for_each_entry(st, &mISDN_stacklist, list) {
if (id == st->id)
return(st);
cst = st->child;
while (cst) {
list_for_each_entry(cst, &st->childlist, list) {
if (cst->id == id)
return(cst);
cst = cst->next;
}
st = st->next;
}
return(NULL);
}
@ -146,14 +140,12 @@ getlayer4lay(mISDNstack_t *st, int layermask)
int_error();
return(NULL);
}
layer = st->lstack;
while(layer) {
list_for_each_entry(layer, &st->layerlist, list) {
inst = layer->inst;
if(inst && (inst->pid.layermask & layermask))
break;
layer = layer->next;
return(layer);
}
return(layer);
return(NULL);
}
mISDNinstance_t *
@ -173,8 +165,7 @@ get_instance(mISDNstack_t *st, int layer_nr, int protocol)
int_errtxt("lnr %d", layer_nr);
return(NULL);
}
layer = st->lstack;
while(layer) {
list_for_each_entry(layer, &st->layerlist, list) {
inst = layer->inst;
if (inst) {
if (core_debug & DEBUG_CORE_FUNC)
@ -186,11 +177,10 @@ get_instance(mISDNstack_t *st, int layer_nr, int protocol)
goto out;
inst = NULL;
}
if (layer == layer->next) {
if (list_empty(&layer->list)) {
int_errtxt("deadloop layer %p", layer);
return(NULL);
}
layer = layer->next;
}
out:
return(inst);
@ -199,13 +189,11 @@ out:
mISDNinstance_t *
get_instance4id(u_int id)
{
mISDNinstance_t *inst = mISDN_instlist;
mISDNinstance_t *inst;
while(inst) {
list_for_each_entry(inst, &mISDN_instlist, list)
if (inst->id == id)
return(inst);
inst = inst->next;
}
return(NULL);
}
@ -231,22 +219,16 @@ insertlayer(mISDNstack_t *st, mISDNlayer_t *layer, int layermask)
int_error();
return(-EINVAL);
}
item = st->lstack;
if (!item) {
st->lstack = layer;
if (list_empty(&st->layerlist)) {
list_add(&layer->list, &st->layerlist);
} else {
while(item) {
list_for_each_entry(item, &st->layerlist, list) {
if (layermask < get_layermask(item)) {
INSERT_INTO_LIST(layer, item, st->lstack);
list_add_tail(&layer->list, &item->list);
return(0);
} else {
if (!item->next)
break;
}
item = item->next;
}
item->next = layer;
layer->prev = item;
list_add_tail(&layer->list, &st->layerlist);
}
return(0);
}
@ -264,6 +246,8 @@ new_stack(mISDNstack_t *master, mISDNinstance_t *inst)
return(NULL);
}
memset(newst, 0, sizeof(mISDNstack_t));
INIT_LIST_HEAD(&newst->layerlist);
INIT_LIST_HEAD(&newst->childlist);
if (!master) {
if (inst && inst->st) {
newst->id = get_free_stackid(inst->st, FLG_CLONE_STACK);
@ -275,9 +259,9 @@ new_stack(mISDNstack_t *master, mISDNinstance_t *inst)
}
newst->mgr = inst;
if (master) {
APPEND_TO_LIST(newst, master->child);
list_add_tail(&newst->list, &master->childlist);
} else {
APPEND_TO_LIST(newst, mISDN_stacklist);
list_add_tail(&newst->list, &mISDN_stacklist);
}
if (core_debug & DEBUG_CORE_FUNC)
printk(KERN_DEBUG "Stack id %x added\n", newst->id);
@ -291,10 +275,10 @@ static int
release_layers(mISDNstack_t *st, u_int prim)
{
mISDNinstance_t *inst;
mISDNlayer_t *layer;
mISDNlayer_t *layer, *nl;
int cnt = 0;
while((layer = st->lstack)) {
list_for_each_entry_safe(layer, nl, &st->layerlist, list) {
inst = layer->inst;
if (inst) {
if (core_debug & DEBUG_CORE_FUNC)
@ -303,10 +287,10 @@ release_layers(mISDNstack_t *st, u_int prim)
inst->name, inst->pid.layermask);
inst->obj->own_ctrl(inst, prim, NULL);
}
REMOVE_FROM_LISTBASE(layer, st->lstack);
list_del(&layer->list);
kfree(layer);
if (cnt++ > 1000) {
int_errtxt("release_layers st(%p)", st);
int_errtxt("release_layers endless loop st(%p)", st);
return(-EINVAL);
}
}
@ -317,17 +301,15 @@ int
do_for_all_layers(mISDNstack_t *st, u_int prim, void *arg)
{
mISDNinstance_t *inst;
mISDNlayer_t *layer;
mISDNlayer_t *layer, *nl;
int cnt = 0;
if (!st) {
int_error();
return(-EINVAL);
}
layer = st->lstack;
while(layer) {
list_for_each_entry_safe(layer, nl, &st->layerlist, list) {
inst = layer->inst;
layer = layer->next;
if (inst) {
if (core_debug & DEBUG_CORE_FUNC)
printk(KERN_DEBUG "%s: st(%p) inst(%p):%x %s prim(%x) arg(%p)\n",
@ -335,7 +317,7 @@ do_for_all_layers(mISDNstack_t *st, u_int prim, void *arg)
inst->obj->own_ctrl(inst, prim, arg);
}
if (cnt++ > 1000) {
int_errtxt("release_layers st(%p)", st);
int_errtxt("do_for_all_layers endless loop st(%p)", st);
return(-EINVAL);
}
}
@ -382,66 +364,55 @@ change_stack_para(mISDNstack_t *st, u_int prim, mISDN_stPara_t *stpara)
int
release_stack(mISDNstack_t *st) {
int err;
mISDNstack_t *cst;
mISDNstack_t *cst, *nst;
if (core_debug & DEBUG_CORE_FUNC)
printk(KERN_DEBUG "%s: st(%p)\n", __FUNCTION__, st);
while (st->child) {
cst = st->child;
list_for_each_entry_safe(cst, nst, &st->childlist, list) {
if (core_debug & DEBUG_CORE_FUNC)
printk(KERN_DEBUG "%s: cst(%p)\n", __FUNCTION__, cst);
if ((err = release_layers(cst, MGR_RELEASE | INDICATION))) {
printk(KERN_WARNING "release_stack child err(%d)\n", err);
return(err);
}
REMOVE_FROM_LISTBASE(cst, st->child);
list_del(&cst->list);
kfree(cst);
}
if ((err = release_layers(st, MGR_RELEASE | INDICATION))) {
printk(KERN_WARNING "release_stack err(%d)\n", err);
return(err);
}
REMOVE_FROM_LISTBASE(st, mISDN_stacklist);
list_del(&st->list);
kfree(st);
if (core_debug & DEBUG_CORE_FUNC)
printk(KERN_DEBUG "%s: mISDN_stacklist(%p)\n", __FUNCTION__, mISDN_stacklist);
printk(KERN_DEBUG "%s: mISDN_stacklist(%p<-%p->%p)\n", __FUNCTION__,
mISDN_stacklist.prev, &mISDN_stacklist, mISDN_stacklist.next);
return(0);
}
void
release_stacks(mISDNobject_t *obj) {
mISDNstack_t *st, *tmp;
mISDNlayer_t *layer;
mISDNinstance_t *inst;
mISDNlayer_t *layer, *ltmp;
int rel;
st = mISDN_stacklist;
if (core_debug & DEBUG_CORE_FUNC)
printk(KERN_DEBUG "%s: obj(%p) %s\n",
__FUNCTION__, obj, obj->name);
while (st) {
list_for_each_entry_safe(st, tmp, &mISDN_stacklist, list) {
rel = 0;
layer = st->lstack;
if (core_debug & DEBUG_CORE_FUNC)
printk(KERN_DEBUG "%s: st(%p) l(%p)\n",
__FUNCTION__, st, layer);
while(layer) {
inst = layer->inst;
if (inst) {
if (core_debug & DEBUG_CORE_FUNC)
printk(KERN_DEBUG "%s: inst(%p)\n",
__FUNCTION__, inst);
if (inst->obj == obj)
rel++;
}
layer = layer->next;
printk(KERN_DEBUG "%s: st(%p)\n",
__FUNCTION__, st);
list_for_each_entry_safe(layer, ltmp, &st->layerlist, list) {
if (core_debug & DEBUG_CORE_FUNC)
printk(KERN_DEBUG "%s: layer(%p) inst(%p)\n",
__FUNCTION__, layer, layer->inst);
if (layer->inst && layer->inst->obj == obj)
rel++;
}
if (rel) {
tmp = st->next;
if (rel)
release_stack(st);
st = tmp;
} else
st = st->next;
}
if (obj->refcnt)
printk(KERN_WARNING "release_stacks obj %s refcnt is %d\n",
@ -451,24 +422,22 @@ release_stacks(mISDNobject_t *obj) {
static void
get_free_instid(mISDNstack_t *st, mISDNinstance_t *inst) {
mISDNinstance_t *il = mISDN_instlist;
mISDNinstance_t *il;
inst->id = mISDN_get_lowlayer(inst->pid.layermask)<<20;
inst->id |= FLG_INSTANCE;
if (st) {
inst->id |= st->id;
} else {
while(il) {
list_for_each_entry(il, &mISDN_instlist, list) {
if (il->id == inst->id) {
if ((inst->id & IF_INSTMASK) >= INST_ID_MAX) {
inst->id = 0;
return;
}
inst->id += INST_ID_INC;
il = mISDN_instlist;
continue;
il = list_entry(mISDN_instlist.next, mISDNinstance_t, list);
}
il = il->next;
}
}
}
@ -515,7 +484,7 @@ register_layer(mISDNstack_t *st, mISDNinstance_t *inst) {
if (!inst->id) {
int_errtxt("no free inst->id for layer %x", inst->pid.layermask);
if (st && layer) {
REMOVE_FROM_LISTBASE(layer, st->lstack);
list_del(&layer->list);
kfree(layer);
}
return(-EINVAL);
@ -523,7 +492,7 @@ register_layer(mISDNstack_t *st, mISDNinstance_t *inst) {
inst->st = st;
if (refinc)
inst->obj->refcnt++;
APPEND_TO_LIST(inst, mISDN_instlist);
list_add_tail(&inst->list, &mISDN_instlist);
return(0);
}
@ -550,12 +519,12 @@ unregister_instance(mISDNinstance_t *inst) {
if (inst->st && (inst->st->mgr != inst))
inst->st = NULL;
}
REMOVE_FROM_LISTBASE(inst, mISDN_instlist);
inst->prev = inst->next = NULL;
list_del_init(&inst->list);
inst->id = 0;
inst->obj->refcnt--;
if (core_debug & DEBUG_CORE_FUNC)
printk(KERN_DEBUG "%s: mISDN_instlist(%p)\n", __FUNCTION__, mISDN_instlist);
printk(KERN_DEBUG "%s: mISDN_instlist(%p<-%p->%p)\n", __FUNCTION__,
mISDN_instlist.prev, &mISDN_instlist, mISDN_instlist.next);
return(0);
}
@ -588,7 +557,7 @@ set_stack(mISDNstack_t *st, mISDN_pid_t *pid)
int err;
u_char *pbuf = NULL;
mISDNinstance_t *inst;
mISDNlayer_t *hl;
mISDNlayer_t *hl, *hln;
if (!st || !pid) {
int_error();
@ -624,8 +593,10 @@ set_stack(mISDNstack_t *st, mISDN_pid_t *pid)
}
mISDN_RemoveUsedPID(pid, &inst->pid);
}
hl = st->lstack;
while(hl && hl->next) {
list_for_each_entry_safe(hl, hln, &st->layerlist, list) {
if (hl->list.next == &st->layerlist)
break;
if (!hl->inst) {
int_error();
return(-EINVAL);
@ -639,8 +610,7 @@ set_stack(mISDNstack_t *st, mISDN_pid_t *pid)
return(-EINVAL);
}
hl->inst->obj->own_ctrl(hl->inst, MGR_CONNECT | REQUEST,
hl->next->inst);
hl = hl->next;
hln->inst);
}
st->mgr->obj->own_ctrl(st->mgr, MGR_SETSTACK |CONFIRM, NULL);
return(0);

View File

@ -10,7 +10,6 @@
#include <linux/vmalloc.h>
#include <linux/config.h>
#include <linux/timer.h>
#include <linux/list.h>
#include "core.h"
#define MAX_HEADER_LEN 4
@ -23,8 +22,7 @@
typedef struct _devicelayer {
struct _devicelayer *prev;
struct _devicelayer *next;
struct list_head list;
mISDNdevice_t *dev;
mISDNinstance_t inst;
mISDNinstance_t *slave;
@ -36,16 +34,14 @@ typedef struct _devicelayer {
} devicelayer_t;
typedef struct _devicestack {
struct _devicestack *prev;
struct _devicestack *next;
struct list_head list;
mISDNdevice_t *dev;
mISDNstack_t *st;
int extentions;
} devicestack_t;
typedef struct _mISDNtimer {
struct _mISDNtimer *prev;
struct _mISDNtimer *next;
struct list_head list;
struct _mISDNdevice *dev;
struct timer_list tl;
int id;
@ -57,7 +53,7 @@ typedef struct entity_item {
int entity;
} entity_item_t;
static mISDNdevice_t *mISDN_devicelist = NULL;
static LIST_HEAD(mISDN_devicelist);
static rwlock_t mISDN_device_lock = RW_LOCK_UNLOCKED;
static mISDNobject_t udev_obj;
@ -76,14 +72,17 @@ static int mISDN_wdata(mISDNdevice_t *dev);
static mISDNdevice_t *
get_mISDNdevice4minor(int minor)
{
mISDNdevice_t *dev = mISDN_devicelist;
mISDNdevice_t *dev;
while(dev) {
if (dev->minor == minor)
break;
dev = dev->next;
read_lock(&mISDN_device_lock);
list_for_each_entry(dev, &mISDN_devicelist, list) {
if (dev->minor == minor) {
read_unlock(&mISDN_device_lock);
return(dev);
}
}
return(dev);
read_unlock(&mISDN_device_lock);
return(NULL);
}
static __inline__ void
@ -252,69 +251,65 @@ mISDN_rdata(mISDNdevice_t *dev, iframe_t *iff, int use_value) {
}
static devicelayer_t
*get_devlayer(mISDNdevice_t *dev, int addr) {
devicelayer_t *dl = dev->layer;
*get_devlayer(mISDNdevice_t *dev, int addr) {
devicelayer_t *dl;
if (device_debug & DEBUG_MGR_FUNC)
printk(KERN_DEBUG "%s: addr:%x\n", __FUNCTION__, addr);
while(dl) {
list_for_each_entry(dl, &dev->layerlist, list) {
// if (device_debug & DEBUG_MGR_FUNC)
// printk(KERN_DEBUG "%s: dl(%p) iaddr:%x\n",
// __FUNCTION__, dl, dl->iaddr);
if ((u_int)dl->iaddr == (IF_IADDRMASK & addr))
break;
dl = dl->next;
return(dl);
}
return(dl);
return(NULL);
}
static devicestack_t
*get_devstack(mISDNdevice_t *dev, int addr)
{
devicestack_t *ds = dev->stack;
devicestack_t *ds;
if (device_debug & DEBUG_MGR_FUNC)
printk(KERN_DEBUG "%s: addr:%x\n", __FUNCTION__, addr);
while(ds) {
list_for_each_entry(ds, &dev->stacklist, list) {
if (ds->st && (ds->st->id == (u_int)addr))
break;
ds = ds->next;
return(ds);
}
return(ds);
return(NULL);
}
static mISDNtimer_t
*get_devtimer(mISDNdevice_t *dev, int id)
*get_devtimer(mISDNdevice_t *dev, int id)
{
mISDNtimer_t *ht = dev->timer;
mISDNtimer_t *ht;
if (device_debug & DEBUG_DEV_TIMER)
printk(KERN_DEBUG "%s: dev:%p id:%x\n", __FUNCTION__, dev, id);
while(ht) {
list_for_each_entry(ht, &dev->timerlist, list) {
if (ht->id == id)
break;
ht = ht->next;
return(ht);
}
return(ht);
return(NULL);
}
static int
stack_inst_flg(mISDNdevice_t *dev, mISDNstack_t *st, int bit, int clear)
{
int ret = -1;
devicelayer_t *dl = dev->layer;
int ret;
devicelayer_t *dl;
while(dl) {
list_for_each_entry(dl, &dev->layerlist, list) {
if (dl->inst.st == st) {
if (clear)
ret = test_and_clear_bit(bit, &dl->Flags);
else
ret = test_and_set_bit(bit, &dl->Flags);
break;
return(ret);
}
dl = dl->next;
}
return(ret);
return(-1);
}
static int
@ -349,7 +344,8 @@ new_devstack(mISDNdevice_t *dev, stack_info_t *si)
nds->dev = dev;
if (si->extentions & EXT_STACK_CLONE) {
// memcpy(&inst.st->pid, &st->pid, sizeof(mISDN_pid_t));
inst.st->child = st->child;
// FIXME that is a ugly idea, but I don't have a better one
inst.st->childlist.prev = &st->childlist;
} else {
memcpy(&inst.st->pid, &si->pid, sizeof(mISDN_pid_t));
}
@ -357,7 +353,7 @@ new_devstack(mISDNdevice_t *dev, stack_info_t *si)
inst.st->extentions |= si->extentions;
inst.st->mgr = get_instance4id(si->mgr);
nds->st = inst.st;
APPEND_TO_LIST(nds, dev->stack);
list_add_tail(&nds->list, &dev->stacklist);
return(inst.st->id);
}
@ -453,7 +449,7 @@ create_layer(mISDNdevice_t *dev, layer_info_t *linfo, int *adr)
nl->inst.up.owner = &nl->inst;
nl->inst.obj = &udev_obj;
nl->inst.data = nl;
APPEND_TO_LIST(nl, dev->layer);
list_add_tail(&nl->list, &dev->layerlist);
nl->inst.obj->ctrl(st, MGR_REGLAYER | INDICATION, &nl->inst);
nl->iaddr = nl->inst.id;
*adr++ = nl->iaddr;
@ -492,7 +488,10 @@ remove_if(devicelayer_t *dl, int stat) {
memcpy(phif, shif, sizeof(mISDNif_t));
memset(shif, 0, sizeof(mISDNif_t));
}
REMOVE_FROM_LIST(hif);
if (hif->predecessor)
hif->predecessor->clone = hif->clone;
if (hif->clone)
hif->clone->predecessor = hif->predecessor;
return(err);
}
@ -514,10 +513,10 @@ del_stack(devicestack_t *ds)
return(-EINVAL);
if (ds->st) {
if (ds->extentions & EXT_STACK_CLONE)
ds->st->child = NULL;
INIT_LIST_HEAD(&ds->st->childlist);
udev_obj.ctrl(ds->st, MGR_DELSTACK | REQUEST, NULL);
}
REMOVE_FROM_LISTBASE(ds, dev->stack);
list_del(&ds->list);
kfree(ds);
return(0);
}
@ -529,8 +528,8 @@ del_layer(devicelayer_t *dl) {
int i;
if (device_debug & DEBUG_MGR_FUNC) {
printk(KERN_DEBUG "%s: dl(%p) inst(%p) LM(%x) dev(%p) nexti(%p)\n",
__FUNCTION__, dl, inst, inst->pid.layermask, dev, inst->next);
printk(KERN_DEBUG "%s: dl(%p) inst(%p) LM(%x) dev(%p)\n",
__FUNCTION__, dl, inst, inst->pid.layermask, dev);
printk(KERN_DEBUG "%s: iaddr %x inst %s slave %p\n",
__FUNCTION__, dl->iaddr, inst->name, dl->slave);
}
@ -566,7 +565,7 @@ del_layer(devicelayer_t *dl) {
MGR_DISCONNECT | REQUEST, &inst->down);
}
dl->iaddr = 0;
REMOVE_FROM_LISTBASE(dl, dev->layer);
list_del(&dl->list);
udev_obj.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
if (test_and_clear_bit(FLG_MGR_OWNSTACK, &dl->Flags)) {
if (dl->inst.st) {
@ -859,14 +858,12 @@ dev_init_timer(mISDNdevice_t *dev, iframe_t *iff)
ht = kmalloc(sizeof(mISDNtimer_t), GFP_ATOMIC);
if (!ht)
return(-ENOMEM);
ht->prev = NULL;
ht->next = NULL;
ht->dev = dev;
ht->id = iff->addr;
ht->tl.data = (long) ht;
ht->tl.function = (void *) dev_expire_timer;
init_timer(&ht->tl);
APPEND_TO_LIST(ht, dev->timer);
list_add_tail(&ht->list, &dev->timerlist);
if (device_debug & DEBUG_DEV_TIMER)
printk(KERN_DEBUG "%s: new(%x)\n", __FUNCTION__, ht->id);
} else if (device_debug & DEBUG_DEV_TIMER)
@ -933,6 +930,16 @@ dev_del_timer(mISDNdevice_t *dev, iframe_t *iff)
return(0);
}
static void
dev_free_timer(mISDNtimer_t *ht)
{
if (device_debug & DEBUG_DEV_TIMER)
printk(KERN_DEBUG "%s: timer(%x)\n", __FUNCTION__, ht->id);
del_timer(&ht->tl);
list_del(&ht->list);
kfree(ht);
}
static int
dev_remove_timer(mISDNdevice_t *dev, int id)
{
@ -943,11 +950,7 @@ dev_remove_timer(mISDNdevice_t *dev, int id)
printk(KERN_WARNING "%s: no timer(%x)\n", __FUNCTION__, id);
return(-ENODEV);
}
if (device_debug & DEBUG_DEV_TIMER)
printk(KERN_DEBUG "%s: timer(%x)\n", __FUNCTION__, ht->id);
del_timer(&ht->tl);
REMOVE_FROM_LISTBASE(ht, dev->timer);
kfree(ht);
dev_free_timer(ht);
return(0);
}
@ -1532,9 +1535,12 @@ init_device(u_int minor) {
init_waitqueue_head(&dev->rport.procq);
init_waitqueue_head(&dev->wport.procq);
init_MUTEX(&dev->io_sema);
INIT_LIST_HEAD(&dev->layerlist);
INIT_LIST_HEAD(&dev->stacklist);
INIT_LIST_HEAD(&dev->timerlist);
INIT_LIST_HEAD(&dev->entitylist);
write_lock_irqsave(&mISDN_device_lock, flags);
APPEND_TO_LIST(dev, mISDN_devicelist);
list_add_tail(&dev->list, &mISDN_devicelist);
write_unlock_irqrestore(&mISDN_device_lock, flags);
}
return(dev);
@ -1568,6 +1574,7 @@ get_free_rawdevice(void)
int
free_device(mISDNdevice_t *dev)
{
struct list_head *item, *ni;
u_long flags;
if (!dev)
@ -1575,25 +1582,24 @@ free_device(mISDNdevice_t *dev)
if (device_debug & DEBUG_MGR_FUNC)
printk(KERN_DEBUG "%s: dev(%d)\n", __FUNCTION__, dev->minor);
/* release related stuff */
while(dev->layer)
del_layer(dev->layer);
while(dev->stack)
del_stack(dev->stack);
while(dev->timer)
dev_remove_timer(dev, dev->timer->id);
list_for_each_safe(item, ni, &dev->layerlist)
del_layer(list_entry(item, devicelayer_t, list));
list_for_each_safe(item, ni, &dev->stacklist)
del_stack(list_entry(item, devicestack_t, list));
list_for_each_safe(item, ni, &dev->timerlist)
dev_free_timer(list_entry(item, mISDNtimer_t, list));
if (dev->rport.buf)
vfree(dev->rport.buf);
if (dev->wport.buf)
vfree(dev->wport.buf);
write_lock_irqsave(&mISDN_device_lock, flags);
REMOVE_FROM_LISTBASE(dev, mISDN_devicelist);
list_del(&dev->list);
write_unlock_irqrestore(&mISDN_device_lock, flags);
if (!list_empty(&dev->entitylist)) {
printk(KERN_WARNING "MISDN %s: entitylist not empty\n", __FUNCTION__);
while(!list_empty(&dev->entitylist)) {
struct entity_item *ei;
ei = (struct entity_item *)dev->entitylist.next;
list_del((struct list_head *)ei);
list_for_each_safe(item, ni, &dev->entitylist) {
struct entity_item *ei = list_entry(item, struct entity_item, head);
list_del(item);
mISDN_delete_entity(ei->entity);
kfree(ei);
}
@ -1631,7 +1637,7 @@ mISDN_open(struct inode *ino, struct file *filep)
if (!dev->rport.buf) {
if (isnew) {
write_lock_irqsave(&mISDN_device_lock, flags);
REMOVE_FROM_LISTBASE(dev, mISDN_devicelist);
list_del(&dev->list);
write_unlock_irqrestore(&mISDN_device_lock, flags);
kfree(dev);
}
@ -1652,7 +1658,7 @@ mISDN_open(struct inode *ino, struct file *filep)
if (dev->rport.buf)
vfree(dev->rport.buf);
write_lock_irqsave(&mISDN_device_lock, flags);
REMOVE_FROM_LISTBASE(dev, mISDN_devicelist);
list_del(&dev->list);
write_unlock_irqrestore(&mISDN_device_lock, flags);
kfree(dev);
}
@ -1674,12 +1680,12 @@ mISDN_open(struct inode *ino, struct file *filep)
static int
mISDN_close(struct inode *ino, struct file *filep)
{
mISDNdevice_t *dev = mISDN_devicelist;
mISDNdevice_t *dev, *nd;
if (device_debug & DEBUG_DEV_OP)
printk(KERN_DEBUG "mISDN: mISDN_close %p %p\n", filep, filep->private_data);
read_lock(&mISDN_device_lock);
while (dev) {
list_for_each_entry_safe(dev, nd, &mISDN_devicelist, list) {
if (dev == filep->private_data) {
if (device_debug & DEBUG_DEV_OP)
printk(KERN_DEBUG "mISDN: dev(%d) %p mode %x/%x\n",
@ -1699,7 +1705,6 @@ mISDN_close(struct inode *ino, struct file *filep)
free_device(dev);
return 0;
}
dev = dev->next;
}
read_unlock(&mISDN_device_lock);
printk(KERN_WARNING "mISDN: No private data while closing device\n");
@ -1941,9 +1946,9 @@ set_if(devicelayer_t *dl, u_int prim, mISDNif_t *hif)
static int
udev_manager(void *data, u_int prim, void *arg) {
mISDNinstance_t *inst = data;
mISDNdevice_t *dev = mISDN_devicelist;
devicelayer_t *dl = NULL;
int err = -EINVAL;
mISDNdevice_t *dev;
devicelayer_t *dl;
int err = -EINVAL;
if (device_debug & DEBUG_MGR_FUNC)
printk(KERN_DEBUG "udev_manager data:%p prim:%x arg:%p\n",
@ -1951,18 +1956,17 @@ udev_manager(void *data, u_int prim, void *arg) {
if (!data)
return(-EINVAL);
read_lock(&mISDN_device_lock);
while(dev) {
dl = dev->layer;
while(dl) {
if (&dl->inst == inst)
list_for_each_entry(dev, &mISDN_devicelist, list) {
list_for_each_entry(dl, &dev->layerlist, list) {
if (&dl->inst == inst) {
err = 0;
break;
dl = dl->next;
}
}
if (dl)
if (!err)
break;
dev = dev->next;
}
if (!dl) {
if (err) {
printk(KERN_WARNING "dev_manager prim %x without device layer\n", prim);
goto out;
}
@ -1987,6 +1991,7 @@ udev_manager(void *data, u_int prim, void *arg) {
break;
default:
printk(KERN_WARNING "dev_manager prim %x not handled\n", prim);
err = -EINVAL;
break;
}
out:
@ -2002,9 +2007,8 @@ int init_mISDNdev (int debug) {
udev_obj.DPROTO.protocol[i] = ISDN_PID_ANY;
udev_obj.BPROTO.protocol[i] = ISDN_PID_ANY;
}
INIT_LIST_HEAD(&udev_obj.ilist);
udev_obj.own_ctrl = udev_manager;
udev_obj.prev = NULL;
udev_obj.next = NULL;
device_debug = debug;
if (register_chrdev(mISDN_MAJOR, "mISDN", &mISDN_fops)) {
printk(KERN_WARNING "mISDN: Could not register devices\n");
@ -2018,13 +2022,12 @@ int init_mISDNdev (int debug) {
int free_mISDNdev(void) {
int err = 0;
mISDNdevice_t *dev = mISDN_devicelist;
mISDNdevice_t *dev, *nd;
if (mISDN_devicelist) {
if (!list_empty(&mISDN_devicelist)) {
printk(KERN_WARNING "mISDN: devices open on remove\n");
while (dev) {
list_for_each_entry_safe(dev, nd, &mISDN_devicelist, list) {
free_device(dev);
dev = mISDN_devicelist;
}
err = -EBUSY;
}

View File

@ -51,8 +51,7 @@ typedef struct _w6692_bc {
} w6692_bc;
typedef struct _w6692pci {
struct _w6692pci *prev;
struct _w6692pci *next;
struct list_head list;
void *pdev;
u_int irq;
u_int irqcnt;
@ -165,7 +164,7 @@ W6692_new_ph(dchannel_t *dch)
para = HW_RESET;
while(upif) {
if_link(upif, prim, para, 0, NULL, 0);
upif = upif->next;
upif = upif->clone;
}
upif = &dch->inst.up;
/* fall trough */
@ -198,7 +197,7 @@ W6692_new_ph(dchannel_t *dch)
}
while(upif) {
if_link(upif, prim, para, 0, NULL, 0);
upif = upif->next;
upif = upif->clone;
}
}
@ -1278,7 +1277,7 @@ release_card(w6692pci *card)
mISDN_free_dch(&card->dch);
w6692.ctrl(card->dch.inst.up.peer, MGR_DISCONNECT | REQUEST, &card->dch.inst.up);
w6692.ctrl(&card->dch.inst, MGR_UNREGLAYER | REQUEST, NULL);
REMOVE_FROM_LISTBASE(card, ((w6692pci *)w6692.ilist));
list_del(&card->list);
unlock_dev(card);
pci_disable_device(card->pdev);
pci_set_drvdata(card->pdev, NULL);
@ -1287,7 +1286,7 @@ release_card(w6692pci *card)
static int
w6692_manager(void *data, u_int prim, void *arg) {
w6692pci *card = w6692.ilist;
w6692pci *card;
mISDNinstance_t *inst = data;
struct sk_buff *skb;
int channel = -1;
@ -1301,7 +1300,7 @@ w6692_manager(void *data, u_int prim, void *arg) {
__FUNCTION__, prim, arg);
return(-EINVAL);
}
while(card) {
list_for_each_entry(card, &w6692.ilist, list) {
if (&card->dch.inst == inst) {
channel = 2;
break;
@ -1314,7 +1313,6 @@ w6692_manager(void *data, u_int prim, void *arg) {
channel = 1;
break;
}
card = card->next;
}
if (channel<0) {
printk(KERN_WARNING "%s: no channel data %p prim %x arg %p\n",
@ -1420,7 +1418,7 @@ static int __devinit setup_instance(w6692pci *card)
int i, err;
mISDN_pid_t pid;
APPEND_TO_LIST(card, ((w6692pci *)w6692.ilist));
list_add_tail(&card->list, &w6692.ilist);
card->dch.debug = debug;
lock_HW_init(&card->lock);
card->dch.inst.lock = lock_dev;
@ -1451,7 +1449,7 @@ static int __devinit setup_instance(w6692pci *card)
mISDN_free_dch(&card->dch);
mISDN_free_bch(&card->bch[1]);
mISDN_free_bch(&card->bch[0]);
REMOVE_FROM_LISTBASE(card, ((w6692pci *)w6692.ilist));
list_del(&card->list);
kfree(card);
return(err);
}
@ -1567,14 +1565,13 @@ static int __init w6692_init(void)
#ifdef MODULE
w6692.owner = THIS_MODULE;
#endif
INIT_LIST_HEAD(&w6692.ilist);
w6692.name = W6692Name;
w6692.own_ctrl = w6692_manager;
w6692.DPROTO.protocol[0] = ISDN_PID_L0_TE_S0;
w6692.BPROTO.protocol[1] = ISDN_PID_L1_B_64TRANS |
ISDN_PID_L1_B_64HDLC;
w6692.BPROTO.protocol[2] = ISDN_PID_L2_B_TRANS;
w6692.prev = NULL;
w6692.next = NULL;
if ((err = mISDN_register(&w6692))) {
printk(KERN_ERR "Can't register Winbond W6692 PCI error(%d)\n", err);
return(err);
@ -1597,15 +1594,16 @@ static int __init w6692_init(void)
static void __exit w6692_cleanup(void)
{
int err;
int err;
w6692pci *card, *next;
if ((err = mISDN_unregister(&w6692))) {
printk(KERN_ERR "Can't unregister Winbond W6692 PCI error(%d)\n", err);
}
while(w6692.ilist) {
list_for_each_entry_safe(card, next, &w6692.ilist, list) {
printk(KERN_ERR "Winbond W6692 PCI card struct not empty refs %d\n",
w6692.refcnt);
release_card(w6692.ilist);
release_card(card);
}
pci_unregister_driver(&w6692_driver);
}

View File

@ -1248,22 +1248,24 @@ MODULE_LICENSE("GPL");
static int
dte_manager(void *data, u_int prim, void *arg) {
mISDNinstance_t *inst = data;
x25_l3_t *l3_l = x25dte_obj.ilist;
x25_l3_t *l3_l;
int err = -EINVAL;
if (debug & DEBUG_L3X25_MGR)
printk(KERN_DEBUG "l3x25_manager data:%p prim:%x arg:%p\n", data, prim, arg);
if (!data)
return(-EINVAL);
while(l3_l) {
if (&l3_l->inst == inst)
return(err);
list_for_each_entry(l3_l, &x25dte_obj.ilist, list) {
if (&l3_l->inst == inst) {
err = 0;
break;
l3_l = l3_l->next;
}
}
if (prim == (MGR_NEWLAYER | REQUEST))
return(new_l3(data, arg));
if (!l3_l) {
if (err) {
printk(KERN_WARNING "l3x25_manager prim(%x) no instance\n", prim);
return(-EINVAL);
return(err);
}
switch(prim) {
case MGR_NEWENTITY | CONFIRM:
@ -1320,9 +1322,7 @@ x25_dte_init(void)
x25dte_obj.name = MName;
x25dte_obj.BPROTO.protocol[3] = ISDN_PID_L3_B_X25DTE;
x25dte_obj.own_ctrl = dte_manager;
x25dte_obj.prev = NULL;
x25dte_obj.next = NULL;
x25dte_obj.ilist = NULL;
INIT_LIST_HEAD(&x25dte_obj.ilist);
if ((err = mISDN_register(&x25dte_obj))) {
printk(KERN_ERR "Can't register %s error(%d)\n", MName, err);
} else {
@ -1349,15 +1349,16 @@ x25_dte_init(void)
static void
x25_dte_cleanup(void)
{
int err;
x25_l3_t *l3, *nl3;
int err;
if ((err = mISDN_unregister(&x25dte_obj))) {
printk(KERN_ERR "Can't unregister l3x25 error(%d)\n", err);
}
if(x25dte_obj.ilist) {
if(!list_empty(&x25dte_obj.ilist)) {
printk(KERN_WARNING "l3x25 inst list not empty\n");
while(x25dte_obj.ilist)
X25_release_l3(x25dte_obj.ilist);
list_for_each_entry_safe(l3, nl3, &x25dte_obj.ilist, list)
X25_release_l3(l3);
}
X25_l3_cleanup();
mISDN_FsmFree(&dte_rfsm);

View File

@ -273,13 +273,12 @@ X25_reset_channel(x25_channel_t *l3c, struct sk_buff *skb)
int
X25_restart(x25_l3_t *l3)
{
x25_channel_t *l3c = l3->channels;
x25_channel_t *l3c;
while(l3c) {
list_for_each_entry(l3c, &l3->channellist, list) {
memcpy(l3c->cause, l3->cause, 2);
X25_reset_channel(l3c, NULL);
mISDN_FsmEvent(&l3c->x25p, EV_L3_READY, NULL);
l3c = l3c->next;
}
return(0);
}
@ -539,9 +538,7 @@ X25_get_and_test_ps(x25_channel_t *chan, u_char ptype, struct sk_buff *skb)
void
X25_release_channel(x25_channel_t *l3c)
{
x25_l3_t *l3 = l3c->l3;
REMOVE_FROM_LISTBASE(l3c, l3->channels);
list_del(&l3c->list);
if (l3c->ncpi_data)
kfree(l3c->ncpi_data);
l3c->ncpi_data = NULL;
@ -561,6 +558,7 @@ X25_release_channel(x25_channel_t *l3c)
void
X25_release_l3(x25_l3_t *l3) {
mISDNinstance_t *inst = &l3->inst;
x25_channel_t *ch, *nch;
if (inst->up.peer) {
inst->up.peer->obj->ctrl(inst->up.peer,
@ -571,11 +569,11 @@ X25_release_l3(x25_l3_t *l3) {
MGR_DISCONNECT | REQUEST, &inst->down);
}
if (inst->obj) {
REMOVE_FROM_LISTBASE(l3, ((x25_l3_t *)inst->obj->ilist));
list_del_init(&l3->list);
}
discard_queue(&l3->downq);
while(l3->channels)
X25_release_channel(l3->channels);
list_for_each_entry_safe(ch, nch, &l3->channellist, list)
X25_release_channel(ch);
mISDN_FsmDelTimer(&l3->TR, 3);
if (inst->obj) {
if (l3->entity != MISDN_ENTITY_NONE)
@ -654,7 +652,7 @@ new_x25_channel(x25_l3_t *l3, x25_channel_t **ch_p, __u16 ch, int dlen, u_char *
mISDN_FsmInitTimer(&l3c->x25d, &l3c->TD);
skb_queue_head_init(&l3c->dataq);
APPEND_TO_LIST(l3c, l3->channels);
list_add_tail(&l3c->list, &l3->channellist);
*ch_p = l3c;
return(0);
}
@ -671,6 +669,7 @@ new_x25_l3(x25_l3_t **l3_p, mISDNstack_t *st, mISDN_pid_t *pid, mISDNobject_t *o
return(-ENOMEM);
}
memset(n_l3, 0, sizeof(x25_l3_t));
INIT_LIST_HEAD(&n_l3->channellist);
n_l3->entity = MISDN_ENTITY_NONE;
n_l3->next_id = 1;
spin_lock_init(&n_l3->lock);
@ -706,7 +705,7 @@ new_x25_l3(x25_l3_t **l3_p, mISDNstack_t *st, mISDN_pid_t *pid, mISDNobject_t *o
mISDN_FsmInitTimer(&n_l3->x25r, &n_l3->TR);
skb_queue_head_init(&n_l3->downq);
APPEND_TO_LIST(n_l3, ((x25_l3_t *)obj->ilist));
list_add_tail(&n_l3->list, &obj->ilist);
err = obj->ctrl(&n_l3->inst, MGR_NEWENTITY | REQUEST, NULL);
if (err) {
printk(KERN_WARNING "mISDN %s: MGR_NEWENTITY REQUEST failed err(%x)\n",
@ -714,7 +713,7 @@ new_x25_l3(x25_l3_t **l3_p, mISDNstack_t *st, mISDN_pid_t *pid, mISDNobject_t *o
}
err = obj->ctrl(st, MGR_REGLAYER | INDICATION, &n_l3->inst);
if (err) {
REMOVE_FROM_LISTBASE(n_l3, ((x25_l3_t *)obj->ilist));
list_del(&n_l3->list);
kfree(n_l3);
n_l3 = NULL;
} else {
@ -923,27 +922,25 @@ X25_send_diagnostic(x25_l3_t *l3, struct sk_buff *skb, int err, int channel)
x25_channel_t *
X25_get_channel(x25_l3_t *l3, __u16 ch)
{
x25_channel_t *l3c = l3->channels;
x25_channel_t *l3c;
while(l3c) {
list_for_each_entry(l3c, &l3->channellist, list) {
if (l3c->lchan == ch)
break;
l3c = l3c->next;
return(l3c);
}
return(l3c);
return(NULL);
}
x25_channel_t *
X25_get_channel4NCCI(x25_l3_t *l3, __u32 addr)
{
x25_channel_t *l3c = l3->channels;
x25_channel_t *l3c;
while(l3c) {
list_for_each_entry(l3c, &l3->channellist, list) {
if ((l3c->ncci & 0xffff0000) == (addr & 0xffff0000))
break;
l3c = l3c->next;
return(l3c);
}
return(l3c);
return(NULL);
}
int

View File

@ -47,10 +47,9 @@ struct _x25_ConfQueue {
};
struct _x25_l3 {
x25_l3_t *prev;
x25_l3_t *next;
struct list_head list;
mISDNinstance_t inst;
x25_channel_t *channels;
struct list_head channellist;
struct FsmInst l2l3m;
struct FsmInst x25r;
struct FsmTimer TR;
@ -70,8 +69,7 @@ struct _x25_l3 {
};
struct _x25_channel {
x25_channel_t *prev;
x25_channel_t *next;
struct list_head list;
x25_l3_t *l3;
struct FsmInst x25p;
struct FsmInst x25d;

View File

@ -596,6 +596,7 @@ typedef struct _Q931_info {
#ifdef __KERNEL__
#include <linux/isdn_compat.h>
#include <linux/list.h>
#include <linux/skbuff.h>
typedef struct _mISDNobject mISDNobject_t;
@ -635,8 +636,7 @@ typedef struct _mISDN_headext {
/* Basic struct of a mISDN component */
struct _mISDNobject {
mISDNobject_t *prev;
mISDNobject_t *next;
struct list_head list;
char *name;
int id;
int refcnt;
@ -644,27 +644,26 @@ struct _mISDNobject {
mISDN_pid_t BPROTO;
ctrl_func_t *own_ctrl;
ctrl_func_t *ctrl;
void *ilist;
struct list_head ilist;
struct module *owner;
};
/* the interface between two mISDNinstances */
struct _mISDNif {
mISDNif_t *prev;
mISDNif_t *next;
if_func_t *func;
void *fdata;
mISDNif_t *clone;
mISDNif_t *predecessor;
int extentions;
int stat;
mISDNstack_t *st;
mISDNinstance_t *owner;
mISDNinstance_t *peer;
if_func_t *func;
void *fdata;
};
/* a instance of a mISDNobject */
struct _mISDNinstance {
mISDNinstance_t *prev;
mISDNinstance_t *next;
struct list_head list;
char name[mISDN_MAX_IDLEN];
int extentions;
u_int id;
@ -682,23 +681,21 @@ struct _mISDNinstance {
* normally here is only one instance per layer only if the information
* will be splitted here are more instances */
struct _mISDNlayer {
mISDNlayer_t *prev;
mISDNlayer_t *next;
struct list_head list;
mISDNinstance_t *inst;
};
/* the STACK; a (vertical) chain of layers */
struct _mISDNstack {
mISDNstack_t *prev;
mISDNstack_t *next;
struct list_head list;
u_int id;
u_int extentions;
mISDN_pid_t pid;
mISDN_stPara_t para;
mISDNlayer_t *lstack;
struct list_head layerlist;
mISDNinstance_t *mgr;
mISDNstack_t *child;
struct list_head childlist;
};
/* lowlevel read/write struct for the mISDNdevice */
@ -716,16 +713,15 @@ struct _mISDNport {
/* the user interface to handle /dev/mISDN */
struct _mISDNdevice {
mISDNdevice_t *prev;
mISDNdevice_t *next;
struct list_head list;
int minor;
struct semaphore io_sema;
int open_mode;
mISDNport_t rport;
mISDNport_t wport;
struct _devicelayer *layer;
struct _devicestack *stack;
struct _mISDNtimer *timer;
struct list_head layerlist;
struct list_head stacklist;
struct list_head timerlist;
struct list_head entitylist;
};