Commit b0deac08 authored by Karsten Keil's avatar Karsten Keil Committed by Linus Torvalds

[PATCH] next fixes

here are the next fixes, sorry for the delay, but one of bugs was a really
odd one.

Note:
- here are lot of bugs left, so ISDN is not stable yet but
  I think it's really time to fix it, even if it need some cycles
  to get it right (normally I'm only send patches if it works 100% for
  me).
- I add some additional #warnings to address places which need fixing
  (I hope that some of the other ISDN developer jump in)
parent e0cce02e
...@@ -58,12 +58,16 @@ MODULE_LICENSE("GPL"); ...@@ -58,12 +58,16 @@ MODULE_LICENSE("GPL");
int capi_major = 68; /* allocated */ int capi_major = 68; /* allocated */
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
#define CAPINC_NR_PORTS 32
#define CAPINC_MAX_PORTS 256
int capi_ttymajor = 191; int capi_ttymajor = 191;
int capi_ttyminors = CAPINC_NR_PORTS;
#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
MODULE_PARM(capi_major, "i"); MODULE_PARM(capi_major, "i");
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
MODULE_PARM(capi_ttymajor, "i"); MODULE_PARM(capi_ttymajor, "i");
MODULE_PARM(capi_ttyminors, "i");
#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
/* -------- defines ------------------------------------------------- */ /* -------- defines ------------------------------------------------- */
...@@ -1262,7 +1266,6 @@ static int capinc_tty_read_proc(char *page, char **start, off_t off, ...@@ -1262,7 +1266,6 @@ static int capinc_tty_read_proc(char *page, char **start, off_t off,
return 0; return 0;
} }
#define CAPINC_NR_PORTS 256
static struct tty_driver *capinc_tty_driver; static struct tty_driver *capinc_tty_driver;
static struct tty_operations capinc_ops = { static struct tty_operations capinc_ops = {
...@@ -1289,8 +1292,14 @@ static struct tty_operations capinc_ops = { ...@@ -1289,8 +1292,14 @@ static struct tty_operations capinc_ops = {
static int capinc_tty_init(void) static int capinc_tty_init(void)
{ {
struct tty_driver *drv = alloc_tty_driver(CAPINC_NR_PORTS); struct tty_driver *drv;
if (capi_ttyminors > CAPINC_MAX_PORTS)
capi_ttyminors = CAPINC_MAX_PORTS;
if (capi_ttyminors <= 0)
capi_ttyminors = CAPINC_NR_PORTS;
drv = alloc_tty_driver(capi_ttyminors);
if (!drv) if (!drv)
return -ENOMEM; return -ENOMEM;
...@@ -1454,7 +1463,6 @@ static int __init capi_init(void) ...@@ -1454,7 +1463,6 @@ static int __init capi_init(void)
char *p; char *p;
char *compileinfo; char *compileinfo;
if ((p = strchr(revision, ':')) != 0 && p[1]) { if ((p = strchr(revision, ':')) != 0 && p[1]) {
strlcpy(rev, p + 2, sizeof(rev)); strlcpy(rev, p + 2, sizeof(rev));
if ((p = strchr(rev, '$')) != 0 && p > rev) if ((p = strchr(rev, '$')) != 0 && p > rev)
...@@ -1470,8 +1478,6 @@ static int __init capi_init(void) ...@@ -1470,8 +1478,6 @@ static int __init capi_init(void)
devfs_mk_cdev(MKDEV(capi_major, 0), S_IFCHR | S_IRUSR | S_IWUSR, devfs_mk_cdev(MKDEV(capi_major, 0), S_IFCHR | S_IRUSR | S_IWUSR,
"isdn/capi20"); "isdn/capi20");
printk(KERN_NOTICE "capi20: started up with major %d\n", capi_major);
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
if (capinc_tty_init() < 0) { if (capinc_tty_init() < 0) {
unregister_chrdev(capi_major, "capi20"); unregister_chrdev(capi_major, "capi20");
......
...@@ -1991,6 +1991,10 @@ static int capidrv_addcontr(u16 contr, struct capi_profile *profp) ...@@ -1991,6 +1991,10 @@ static int capidrv_addcontr(u16 contr, struct capi_profile *profp)
int i; int i;
sprintf(id, "capidrv-%d", contr); sprintf(id, "capidrv-%d", contr);
if (!try_module_get(THIS_MODULE)) {
printk(KERN_WARNING "capidrv: (%s) Could not reserve module\n", id);
return -1;
}
if (!(card = (capidrv_contr *) kmalloc(sizeof(capidrv_contr), GFP_ATOMIC))) { if (!(card = (capidrv_contr *) kmalloc(sizeof(capidrv_contr), GFP_ATOMIC))) {
printk(KERN_WARNING printk(KERN_WARNING
"capidrv: (%s) Could not allocate contr-struct.\n", id); "capidrv: (%s) Could not allocate contr-struct.\n", id);
...@@ -1998,11 +2002,6 @@ static int capidrv_addcontr(u16 contr, struct capi_profile *profp) ...@@ -1998,11 +2002,6 @@ static int capidrv_addcontr(u16 contr, struct capi_profile *profp)
} }
memset(card, 0, sizeof(capidrv_contr)); memset(card, 0, sizeof(capidrv_contr));
card->owner = THIS_MODULE; card->owner = THIS_MODULE;
if (!try_module_get(card->owner)) {
printk(KERN_WARNING "capidrv: (%s) Could not reserve module\n", id);
kfree(card);
return -1;
}
init_timer(&card->listentimer); init_timer(&card->listentimer);
strcpy(card->name, id); strcpy(card->name, id);
card->contrnr = contr; card->contrnr = contr;
...@@ -2099,6 +2098,7 @@ static int capidrv_delcontr(u16 contr) ...@@ -2099,6 +2098,7 @@ static int capidrv_delcontr(u16 contr)
printk(KERN_ERR "capidrv: delcontr: no contr %u\n", contr); printk(KERN_ERR "capidrv: delcontr: no contr %u\n", contr);
return -1; return -1;
} }
#warning FIXME: maybe a race condition the card should be removed here from global list /kkeil
spin_unlock_irqrestore(&global_lock, flags); spin_unlock_irqrestore(&global_lock, flags);
del_timer(&card->listentimer); del_timer(&card->listentimer);
......
...@@ -77,31 +77,17 @@ static struct work_struct tq_recv_notify; ...@@ -77,31 +77,17 @@ static struct work_struct tq_recv_notify;
static inline struct capi_ctr * static inline struct capi_ctr *
capi_ctr_get(struct capi_ctr *card) capi_ctr_get(struct capi_ctr *card)
{ {
if (try_module_get(card->owner)) if (!try_module_get(card->owner))
return card; return NULL;
return NULL; DBG("Reserve module: %s", card->owner->name);
return card;
} }
static inline void static inline void
capi_ctr_put(struct capi_ctr *card) capi_ctr_put(struct capi_ctr *card)
{ {
module_put(card->owner); module_put(card->owner);
DBG("MOD_COUNT DEC"); DBG("Release module: %s", card->owner->name);
}
/* -------- own ref counting -------------------------------------- */
static inline void
kcapi_get_ref(void)
{
if (!try_module_get(THIS_MODULE))
printk(KERN_WARNING "%s: cannot reserve module\n", __FUNCTION__);
}
static inline void
kcapi_put_ref(void)
{
module_put(THIS_MODULE);
} }
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
...@@ -224,10 +210,13 @@ static int notify_push(unsigned int cmd, u32 controller, ...@@ -224,10 +210,13 @@ static int notify_push(unsigned int cmd, u32 controller,
{ {
struct capi_notifier *np; struct capi_notifier *np;
kcapi_get_ref(); if (!try_module_get(THIS_MODULE)) {
printk(KERN_WARNING "%s: cannot reserve module\n", __FUNCTION__);
return -1;
}
np = (struct capi_notifier *)kmalloc(sizeof(struct capi_notifier), GFP_ATOMIC); np = (struct capi_notifier *)kmalloc(sizeof(struct capi_notifier), GFP_ATOMIC);
if (!np) { if (!np) {
kcapi_put_ref(); module_put(THIS_MODULE);
return -1; return -1;
} }
memset(np, 0, sizeof(struct capi_notifier)); memset(np, 0, sizeof(struct capi_notifier));
...@@ -241,9 +230,9 @@ static int notify_push(unsigned int cmd, u32 controller, ...@@ -241,9 +230,9 @@ static int notify_push(unsigned int cmd, u32 controller,
* of devices. Devices can only removed in * of devices. Devices can only removed in
* user process, not in bh. * user process, not in bh.
*/ */
kcapi_get_ref(); __module_get(THIS_MODULE);
if (schedule_work(&tq_state_notify) == 0) if (schedule_work(&tq_state_notify) == 0)
kcapi_put_ref(); module_put(THIS_MODULE);
return 0; return 0;
} }
...@@ -301,9 +290,9 @@ static void notify_handler(void *dummy) ...@@ -301,9 +290,9 @@ static void notify_handler(void *dummy)
while ((np = notify_dequeue()) != 0) { while ((np = notify_dequeue()) != 0) {
notify_doit(np); notify_doit(np);
kfree(np); kfree(np);
kcapi_put_ref(); module_put(THIS_MODULE);
} }
kcapi_put_ref(); module_put(THIS_MODULE);
} }
/* -------- Receiver ------------------------------------------ */ /* -------- Receiver ------------------------------------------ */
......
...@@ -37,8 +37,8 @@ ...@@ -37,8 +37,8 @@
static int suppress_pollack; static int suppress_pollack;
static struct pci_device_id c4_pci_tbl[] = { static struct pci_device_id c4_pci_tbl[] = {
{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21285, PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_C4, 4 }, { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21285, PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_C4, 0, 0, (unsigned long)4 },
{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21285, PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_C2, 2 }, { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21285, PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_C2, 0, 0, (unsigned long)2 },
{ } /* Terminating entry */ { } /* Terminating entry */
}; };
...@@ -145,6 +145,7 @@ static inline int wait_for_doorbell(avmcard *card, unsigned long t) ...@@ -145,6 +145,7 @@ static inline int wait_for_doorbell(avmcard *card, unsigned long t)
while (c4inmeml(card->mbase+DOORBELL) != 0xffffffff) { while (c4inmeml(card->mbase+DOORBELL) != 0xffffffff) {
if (!time_before(jiffies, stop)) if (!time_before(jiffies, stop))
return -1; return -1;
mb();
} }
return 0; return 0;
} }
...@@ -297,6 +298,7 @@ static void c4_reset(avmcard *card) ...@@ -297,6 +298,7 @@ static void c4_reset(avmcard *card)
if (!time_before(jiffies, stop)) if (!time_before(jiffies, stop))
return; return;
c4outmeml(card->mbase+DOORBELL, DBELL_ADDR); c4outmeml(card->mbase+DOORBELL, DBELL_ADDR);
mb();
} }
c4_poke(card, DC21285_ARMCSR_BASE + CHAN_1_CONTROL, 0); c4_poke(card, DC21285_ARMCSR_BASE + CHAN_1_CONTROL, 0);
...@@ -320,6 +322,7 @@ static int c4_detect(avmcard *card) ...@@ -320,6 +322,7 @@ static int c4_detect(avmcard *card)
if (!time_before(jiffies, stop)) if (!time_before(jiffies, stop))
return 2; return 2;
c4outmeml(card->mbase+DOORBELL, DBELL_ADDR); c4outmeml(card->mbase+DOORBELL, DBELL_ADDR);
mb();
} }
c4_poke(card, DC21285_ARMCSR_BASE + CHAN_1_CONTROL, 0); c4_poke(card, DC21285_ARMCSR_BASE + CHAN_1_CONTROL, 0);
...@@ -899,6 +902,9 @@ static void c4_remove(struct pci_dev *pdev) ...@@ -899,6 +902,9 @@ static void c4_remove(struct pci_dev *pdev)
avmctrl_info *cinfo; avmctrl_info *cinfo;
u_int i; u_int i;
if (!card)
return;
c4_reset(card); c4_reset(card);
for (i=0; i < card->nr_controllers; i++) { for (i=0; i < card->nr_controllers; i++) {
...@@ -910,6 +916,7 @@ static void c4_remove(struct pci_dev *pdev) ...@@ -910,6 +916,7 @@ static void c4_remove(struct pci_dev *pdev)
iounmap(card->mbase); iounmap(card->mbase);
release_region(card->port, AVMB1_PORTLEN); release_region(card->port, AVMB1_PORTLEN);
avmcard_dma_free(card->dma); avmcard_dma_free(card->dma);
pci_set_drvdata(pdev, NULL);
b1_free_card(card); b1_free_card(card);
} }
...@@ -1141,7 +1148,7 @@ static int c4_add_card(struct capicardparams *p, struct pci_dev *dev, ...@@ -1141,7 +1148,7 @@ static int c4_add_card(struct capicardparams *p, struct pci_dev *dev,
retval = c4_detect(card); retval = c4_detect(card);
if (retval != 0) { if (retval != 0) {
printk(KERN_NOTICE "c4: NO card at 0x%x (%d)\n", printk(KERN_NOTICE "c4: NO card at 0x%x error(%d)\n",
card->port, retval); card->port, retval);
retval = -EIO; retval = -EIO;
goto err_unmap; goto err_unmap;
...@@ -1185,7 +1192,7 @@ static int c4_add_card(struct capicardparams *p, struct pci_dev *dev, ...@@ -1185,7 +1192,7 @@ static int c4_add_card(struct capicardparams *p, struct pci_dev *dev,
printk(KERN_INFO "c4: AVM C%d at i/o %#x, irq %d, mem %#lx\n", printk(KERN_INFO "c4: AVM C%d at i/o %#x, irq %d, mem %#lx\n",
nr_controllers, card->port, card->irq, nr_controllers, card->port, card->irq,
card->membase); card->membase);
pci_set_drvdata(dev, card);
return 0; return 0;
err_free_irq: err_free_irq:
......
...@@ -559,7 +559,7 @@ isdn_audio_eval_dtmf(modem_info * info) ...@@ -559,7 +559,7 @@ isdn_audio_eval_dtmf(modem_info * info)
ISDN_AUDIO_SKB_DLECOUNT(skb) = 0; ISDN_AUDIO_SKB_DLECOUNT(skb) = 0;
ISDN_AUDIO_SKB_LOCK(skb) = 0; ISDN_AUDIO_SKB_LOCK(skb) = 0;
isdn_tty_queue_tail(info, skb, 2); isdn_tty_queue_tail(info, skb, 2);
if ((dev->modempoll) && (info->rcvsched)) if (((get_isdn_dev())->modempoll) && (info->rcvsched))
mod_timer(&info->read_timer, jiffies + 4); mod_timer(&info->read_timer, jiffies + 4);
} else } else
kfree_skb(skb); kfree_skb(skb);
...@@ -670,7 +670,7 @@ isdn_audio_put_dle_code(modem_info * info, u_char code) ...@@ -670,7 +670,7 @@ isdn_audio_put_dle_code(modem_info * info, u_char code)
ISDN_AUDIO_SKB_LOCK(skb) = 0; ISDN_AUDIO_SKB_LOCK(skb) = 0;
isdn_tty_queue_tail(info, skb, 2); isdn_tty_queue_tail(info, skb, 2);
/* Schedule dequeuing */ /* Schedule dequeuing */
if ((dev->modempoll) && (info->rcvsched)) if (((get_isdn_dev())->modempoll) && (info->rcvsched))
mod_timer(&info->read_timer, jiffies + 4); mod_timer(&info->read_timer, jiffies + 4);
} }
......
...@@ -32,15 +32,15 @@ MODULE_DESCRIPTION("ISDN4Linux: link layer"); ...@@ -32,15 +32,15 @@ MODULE_DESCRIPTION("ISDN4Linux: link layer");
MODULE_AUTHOR("Fritz Elfert"); MODULE_AUTHOR("Fritz Elfert");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
isdn_dev *dev; static isdn_dev_t *isdndev;
static void isdn_lock_driver(struct isdn_driver *drv); isdn_dev_t *
static void isdn_unlock_driver(struct isdn_driver *drv); get_isdn_dev(void) {
return(isdndev);
/* ====================================================================== */ }
/* Description of hardware-level-driver */ /* Description of hardware-level-driver */
struct isdn_driver { typedef struct isdn_driver {
int di; int di;
char id[20]; char id[20];
atomic_t refcnt; atomic_t refcnt;
...@@ -55,7 +55,15 @@ struct isdn_driver { ...@@ -55,7 +55,15 @@ struct isdn_driver {
spinlock_t lock; spinlock_t lock;
struct isdn_slot *slots; struct isdn_slot *slots;
struct fsm_inst fi; struct fsm_inst fi;
} driver; } isdn_driver_t;
static spinlock_t drivers_lock = SPIN_LOCK_UNLOCKED;
static isdn_driver_t *drivers[ISDN_MAX_DRIVERS];
static void isdn_lock_driver(struct isdn_driver *drv);
static void isdn_unlock_driver(struct isdn_driver *drv);
/* ====================================================================== */
static void drv_destroy(struct isdn_driver *drv); static void drv_destroy(struct isdn_driver *drv);
...@@ -332,7 +340,7 @@ slot_icall(struct fsm_inst *fi, int pr, void *arg) ...@@ -332,7 +340,7 @@ slot_icall(struct fsm_inst *fi, int pr, void *arg)
isdn_lock_driver(slot->drv); isdn_lock_driver(slot->drv);
fsm_change_state(fi, ST_SLOT_IN); fsm_change_state(fi, ST_SLOT_IN);
slot_debug(fi, "ICALL: %s\n", ctrl->parm.num); slot_debug(fi, "ICALL: %s\n", ctrl->parm.num);
if (dev->global_flags & ISDN_GLOBAL_STOPPED) if (isdndev->global_flags & ISDN_GLOBAL_STOPPED)
return 0; return 0;
strcpy(slot->num, ctrl->parm.setup.phone); strcpy(slot->num, ctrl->parm.setup.phone);
...@@ -461,9 +469,6 @@ static char *drv_st_str[] = { ...@@ -461,9 +469,6 @@ static char *drv_st_str[] = {
static int __drv_command(struct isdn_driver *drv, isdn_ctrl *cmd); static int __drv_command(struct isdn_driver *drv, isdn_ctrl *cmd);
static spinlock_t drivers_lock = SPIN_LOCK_UNLOCKED;
static struct isdn_driver *drivers[ISDN_MAX_DRIVERS];
static int static int
isdn_writebuf_skb(struct isdn_slot *slot, struct sk_buff *skb) isdn_writebuf_skb(struct isdn_slot *slot, struct sk_buff *skb)
{ {
...@@ -563,14 +568,14 @@ set_global_features(void) ...@@ -563,14 +568,14 @@ set_global_features(void)
unsigned long flags; unsigned long flags;
int drvidx; int drvidx;
dev->global_features = 0; isdndev->global_features = 0;
spin_lock_irqsave(&drivers_lock, flags); spin_lock_irqsave(&drivers_lock, flags);
for (drvidx = 0; drvidx < ISDN_MAX_DRIVERS; drvidx++) { for (drvidx = 0; drvidx < ISDN_MAX_DRIVERS; drvidx++) {
if (!drivers[drvidx]) if (!drivers[drvidx])
continue; continue;
if (drivers[drvidx]->fi.state != ST_DRV_RUNNING) if (drivers[drvidx]->fi.state != ST_DRV_RUNNING)
continue; continue;
dev->global_features |= drivers[drvidx]->features; isdndev->global_features |= drivers[drvidx]->features;
} }
spin_unlock_irqrestore(&drivers_lock, flags); spin_unlock_irqrestore(&drivers_lock, flags);
} }
...@@ -632,7 +637,7 @@ drv_stat_unload(struct fsm_inst *fi, int pr, void *arg) ...@@ -632,7 +637,7 @@ drv_stat_unload(struct fsm_inst *fi, int pr, void *arg)
spin_unlock_irqrestore(&drivers_lock, flags); spin_unlock_irqrestore(&drivers_lock, flags);
put_drv(drv); put_drv(drv);
dev->channels -= drv->channels; isdndev->channels -= drv->channels;
isdn_info_update(); isdn_info_update();
return 0; return 0;
...@@ -798,6 +803,7 @@ isdn_status_callback(isdn_ctrl *c) ...@@ -798,6 +803,7 @@ isdn_status_callback(isdn_ctrl *c)
case ISDN_STAT_AUDIO: case ISDN_STAT_AUDIO:
rc = fsm_event(&drv->fi, EV_STAT_AUDIO, c); rc = fsm_event(&drv->fi, EV_STAT_AUDIO, c);
break; break;
#warning FIXME divert interface
#if 0 #if 0
case ISDN_STAT_ICALL: case ISDN_STAT_ICALL:
/* Find any ttyI, waiting for D-channel setup */ /* Find any ttyI, waiting for D-channel setup */
...@@ -851,12 +857,6 @@ isdn_status_callback(isdn_ctrl *c) ...@@ -851,12 +857,6 @@ isdn_status_callback(isdn_ctrl *c)
if (divert_if) if (divert_if)
divert_if->stat_callback(c); divert_if->stat_callback(c);
break; break;
case ISDN_STAT_BCONN:
break;
case ISDN_STAT_BHUP:
break;
#endif
#if 0 // FIXME
case ISDN_STAT_DISCH: case ISDN_STAT_DISCH:
save_flags(flags); save_flags(flags);
cli(); cli();
...@@ -899,7 +899,7 @@ register_isdn(isdn_if *iif) ...@@ -899,7 +899,7 @@ register_isdn(isdn_if *iif)
unsigned long flags; unsigned long flags;
int drvidx; int drvidx;
drv = kmalloc(sizeof(*drv), GFP_KERNEL); drv = kmalloc(sizeof(*drv), GFP_ATOMIC);
if (!drv) { if (!drv) {
printk(KERN_WARNING "register_isdn: out of mem\n"); printk(KERN_WARNING "register_isdn: out of mem\n");
goto fail; goto fail;
...@@ -1264,13 +1264,13 @@ isdn_statstr(void) ...@@ -1264,13 +1264,13 @@ isdn_statstr(void)
void void
isdn_info_update(void) isdn_info_update(void)
{ {
infostruct *p = dev->infochain; infostruct *p = isdndev->infochain;
while (p) { while (p) {
*(p->private) = 1; *(p->private) = 1;
p = (infostruct *) p->next; p = (infostruct *) p->next;
} }
wake_up_interruptible(&(dev->info_waitq)); wake_up_interruptible(&(isdndev->info_waitq));
} }
static int static int
...@@ -1282,9 +1282,9 @@ isdn_status_open(struct inode *ino, struct file *filep) ...@@ -1282,9 +1282,9 @@ isdn_status_open(struct inode *ino, struct file *filep)
if (!p) if (!p)
return -ENOMEM; return -ENOMEM;
p->next = (char *) dev->infochain; p->next = (char *) isdndev->infochain;
p->private = (char *) &(filep->private_data); p->private = (char *) &(filep->private_data);
dev->infochain = p; isdndev->infochain = p;
/* At opening we allow a single update */ /* At opening we allow a single update */
filep->private_data = (char *) 1; filep->private_data = (char *) 1;
...@@ -1294,7 +1294,7 @@ isdn_status_open(struct inode *ino, struct file *filep) ...@@ -1294,7 +1294,7 @@ isdn_status_open(struct inode *ino, struct file *filep)
static int static int
isdn_status_release(struct inode *ino, struct file *filep) isdn_status_release(struct inode *ino, struct file *filep)
{ {
infostruct *p = dev->infochain; infostruct *p = isdndev->infochain;
infostruct *q = NULL; infostruct *q = NULL;
lock_kernel(); lock_kernel();
...@@ -1304,7 +1304,7 @@ isdn_status_release(struct inode *ino, struct file *filep) ...@@ -1304,7 +1304,7 @@ isdn_status_release(struct inode *ino, struct file *filep)
if (q) if (q)
q->next = p->next; q->next = p->next;
else else
dev->infochain = (infostruct *) (p->next); isdndev->infochain = (infostruct *) (p->next);
kfree(p); kfree(p);
goto out; goto out;
} }
...@@ -1331,7 +1331,7 @@ isdn_status_read(struct file *file, char *buf, size_t count, loff_t * off) ...@@ -1331,7 +1331,7 @@ isdn_status_read(struct file *file, char *buf, size_t count, loff_t * off)
if (!file->private_data) { if (!file->private_data) {
if (file->f_flags & O_NONBLOCK) if (file->f_flags & O_NONBLOCK)
return -EAGAIN; return -EAGAIN;
interruptible_sleep_on(&(dev->info_waitq)); interruptible_sleep_on(&(isdndev->info_waitq));
} }
lock_kernel(); lock_kernel();
p = isdn_statstr(); p = isdn_statstr();
...@@ -1364,7 +1364,7 @@ isdn_status_poll(struct file *file, poll_table *wait) ...@@ -1364,7 +1364,7 @@ isdn_status_poll(struct file *file, poll_table *wait)
{ {
unsigned int mask = 0; unsigned int mask = 0;
poll_wait(file, &(dev->info_waitq), wait); poll_wait(file, &(isdndev->info_waitq), wait);
lock_kernel(); lock_kernel();
if (file->private_data) if (file->private_data)
mask |= POLLIN | POLLRDNORM; mask |= POLLIN | POLLRDNORM;
...@@ -1449,8 +1449,8 @@ isdn_ctrl_release(struct inode *ino, struct file *file) ...@@ -1449,8 +1449,8 @@ isdn_ctrl_release(struct inode *ino, struct file *file)
{ {
struct isdn_slot *slot = file->private_data; struct isdn_slot *slot = file->private_data;
if (dev->profd == current) if (isdndev->profd == current)
dev->profd = NULL; isdndev->profd = NULL;
isdn_unlock_driver(slot->drv); isdn_unlock_driver(slot->drv);
put_slot(slot); put_slot(slot);
...@@ -1590,15 +1590,15 @@ isdn_ctrl_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) ...@@ -1590,15 +1590,15 @@ isdn_ctrl_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
case IIOCNETHUP: case IIOCNETHUP:
return isdn_net_ioctl(inode, file, cmd, arg); return isdn_net_ioctl(inode, file, cmd, arg);
case IIOCSETVER: case IIOCSETVER:
dev->net_verbose = arg; isdndev->net_verbose = arg;
printk(KERN_INFO "isdn: Verbose-Level is %d\n", dev->net_verbose); printk(KERN_INFO "isdn: Verbose-Level is %d\n", isdndev->net_verbose);
return 0; return 0;
case IIOCSETGST: case IIOCSETGST:
if (arg) { if (arg) {
dev->global_flags |= ISDN_GLOBAL_STOPPED; isdndev->global_flags |= ISDN_GLOBAL_STOPPED;
isdn_net_hangup_all(); isdn_net_hangup_all();
} else { } else {
dev->global_flags &= ~ISDN_GLOBAL_STOPPED; isdndev->global_flags &= ~ISDN_GLOBAL_STOPPED;
} }
return 0; return 0;
case IIOCSETBRJ: case IIOCSETBRJ:
...@@ -1622,7 +1622,7 @@ isdn_ctrl_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) ...@@ -1622,7 +1622,7 @@ isdn_ctrl_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
drivers[drvidx]->flags &= ~DRV_FLAG_REJBUS; drivers[drvidx]->flags &= ~DRV_FLAG_REJBUS;
return 0; return 0;
case IIOCSIGPRF: case IIOCSIGPRF:
dev->profd = current; isdndev->profd = current;
return 0; return 0;
break; break;
case IIOCGETPRF: case IIOCGETPRF:
...@@ -1738,7 +1738,7 @@ isdn_ctrl_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) ...@@ -1738,7 +1738,7 @@ isdn_ctrl_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
return -EINVAL; return -EINVAL;
case IIOCDBGVAR: case IIOCDBGVAR:
if (arg) { if (arg) {
if (copy_to_user((char *) arg, (char *) &dev, sizeof(ulong))) if (copy_to_user((char *) arg, (char *) &isdndev, sizeof(ulong)))
return -EFAULT; return -EFAULT;
return 0; return 0;
} else } else
...@@ -1940,16 +1940,16 @@ isdn_add_channels(struct isdn_driver *drv, int n) ...@@ -1940,16 +1940,16 @@ isdn_add_channels(struct isdn_driver *drv, int n)
if (n < 1) if (n < 1)
return 0; return 0;
if (dev->channels + n > ISDN_MAX_CHANNELS) { if (isdndev->channels + n > ISDN_MAX_CHANNELS) {
printk(KERN_WARNING "register_isdn: Max. %d channels supported\n", printk(KERN_WARNING "register_isdn: Max. %d channels supported\n",
ISDN_MAX_CHANNELS); ISDN_MAX_CHANNELS);
return -EBUSY; return -EBUSY;
} }
dev->channels += n; isdndev->channels += n;
drv->slots = kmalloc(sizeof(struct isdn_slot) * n, GFP_KERNEL); drv->slots = kmalloc(sizeof(struct isdn_slot) * n, GFP_ATOMIC);
if (!drv->slots) if (!drv->slots)
return -ENOMEM; return -ENOMEM;
memset(drv->slots, 0, sizeof(struct isdn_slot) * n);
for (ch = 0; ch < n; ch++) { for (ch = 0; ch < n; ch++) {
slot = drv->slots + ch; slot = drv->slots + ch;
...@@ -1973,50 +1973,57 @@ isdn_add_channels(struct isdn_driver *drv, int n) ...@@ -1973,50 +1973,57 @@ isdn_add_channels(struct isdn_driver *drv, int n)
#if defined(CONFIG_ISDN_DIVERSION) || defined(CONFIG_ISDN_DIVERSION_MODULE) #if defined(CONFIG_ISDN_DIVERSION) || defined(CONFIG_ISDN_DIVERSION_MODULE)
/*
* map_drvname
*/
static char *map_drvname(int di) static char *map_drvname(int di)
{ {
if ((di < 0) || (di >= ISDN_MAX_DRIVERS)) if ((di < 0) || (di >= ISDN_MAX_DRIVERS))
return(NULL); return(NULL);
return(dev->drvid[di]); /* driver name */ return(isdndev->drvid[di]); /* driver name */
} /* map_drvname */ }
/*
* map_namedrv
*/
static int map_namedrv(char *id) static int map_namedrv(char *id)
{ int i; {
int i;
for (i = 0; i < ISDN_MAX_DRIVERS; i++) for (i = 0; i < ISDN_MAX_DRIVERS; i++) {
{ if (!strcmp(dev->drvid[i],id)) if (!strcmp(dev->drvid[i],id))
return(i); return(i);
} }
return(-1); return(-1);
} /* map_namedrv */ }
/*
* DIVERT_REG_NAME
*/
int DIVERT_REG_NAME(isdn_divert_if *i_div) int DIVERT_REG_NAME(isdn_divert_if *i_div)
{ {
if (i_div->if_magic != DIVERT_IF_MAGIC) if (i_div->if_magic != DIVERT_IF_MAGIC)
return(DIVERT_VER_ERR); return(DIVERT_VER_ERR);
switch (i_div->cmd) switch (i_div->cmd) {
{ case DIVERT_CMD_REL:
case DIVERT_CMD_REL: if (divert_if != i_div)
if (divert_if != i_div) return(DIVERT_REL_ERR);
return(DIVERT_REL_ERR); divert_if = NULL; /* free interface */
divert_if = NULL; /* free interface */ MOD_DEC_USE_COUNT;
MOD_DEC_USE_COUNT; return(DIVERT_NO_ERR);
return(DIVERT_NO_ERR); case DIVERT_CMD_REG:
if (divert_if)
case DIVERT_CMD_REG: return(DIVERT_REG_ERR);
if (divert_if) i_div->ll_cmd = isdn_command; /* set command function */
return(DIVERT_REG_ERR); i_div->drv_to_name = map_drvname;
i_div->ll_cmd = isdn_command; /* set command function */ i_div->name_to_drv = map_namedrv;
i_div->drv_to_name = map_drvname; MOD_INC_USE_COUNT;
i_div->name_to_drv = map_namedrv; divert_if = i_div; /* remember interface */
MOD_INC_USE_COUNT; return(DIVERT_NO_ERR);
divert_if = i_div; /* remember interface */ default:
return(DIVERT_NO_ERR); return(DIVERT_CMD_ERR);
}
default: }
return(DIVERT_CMD_ERR);
}
} /* DIVERT_REG_NAME */
EXPORT_SYMBOL(DIVERT_REG_NAME); EXPORT_SYMBOL(DIVERT_REG_NAME);
...@@ -2060,7 +2067,7 @@ isdn_slot_command(struct isdn_slot *slot, int cmd, isdn_ctrl *ctrl) ...@@ -2060,7 +2067,7 @@ isdn_slot_command(struct isdn_slot *slot, int cmd, isdn_ctrl *ctrl)
ctrl->arg &= ~0xff; ctrl->arg |= slot->ch; ctrl->arg &= ~0xff; ctrl->arg |= slot->ch;
break; break;
case ISDN_CMD_DIAL: case ISDN_CMD_DIAL:
if (dev->global_flags & ISDN_GLOBAL_STOPPED) if (isdndev->global_flags & ISDN_GLOBAL_STOPPED)
return -EBUSY; return -EBUSY;
/* fall through */ /* fall through */
...@@ -2200,14 +2207,14 @@ static int __init isdn_init(void) ...@@ -2200,14 +2207,14 @@ static int __init isdn_init(void)
if (retval) if (retval)
goto err_slot_fsm; goto err_slot_fsm;
dev = vmalloc(sizeof(*dev)); isdndev = vmalloc(sizeof(*isdndev));
if (!dev) { if (!isdndev) {
retval = -ENOMEM; retval = -ENOMEM;
goto err_drv_fsm; goto err_drv_fsm;
} }
memset(dev, 0, sizeof(*dev)); memset(isdndev, 0, sizeof(*isdndev));
init_MUTEX(&dev->sem); init_MUTEX(&isdndev->sem);
init_waitqueue_head(&dev->info_waitq); init_waitqueue_head(&isdndev->info_waitq);
retval = register_chrdev(ISDN_MAJOR, "isdn", &isdn_fops); retval = register_chrdev(ISDN_MAJOR, "isdn", &isdn_fops);
if (retval) { if (retval) {
...@@ -2239,7 +2246,7 @@ static int __init isdn_init(void) ...@@ -2239,7 +2246,7 @@ static int __init isdn_init(void)
isdn_cleanup_devfs(); isdn_cleanup_devfs();
unregister_chrdev(ISDN_MAJOR, "isdn"); unregister_chrdev(ISDN_MAJOR, "isdn");
err_vfree: err_vfree:
vfree(dev); vfree(isdndev);
err_drv_fsm: err_drv_fsm:
fsm_free(&drv_fsm); fsm_free(&drv_fsm);
err_slot_fsm: err_slot_fsm:
...@@ -2261,7 +2268,7 @@ static void __exit isdn_exit(void) ...@@ -2261,7 +2268,7 @@ static void __exit isdn_exit(void)
isdn_tty_exit(); isdn_tty_exit();
unregister_chrdev(ISDN_MAJOR, "isdn"); unregister_chrdev(ISDN_MAJOR, "isdn");
isdn_cleanup_devfs(); isdn_cleanup_devfs();
vfree(dev); vfree(isdndev);
fsm_free(&drv_fsm); fsm_free(&drv_fsm);
fsm_free(&slot_fsm); fsm_free(&slot_fsm);
} }
......
...@@ -837,7 +837,7 @@ isdn_net_force_hangup(char *name) // FIXME rename? ...@@ -837,7 +837,7 @@ isdn_net_force_hangup(char *name) // FIXME rename?
if (!idev) if (!idev)
return -ENODEV; return -ENODEV;
if (idev->isdn_slot < 0) if (idev->isdn_slot == NULL)
return -ENOTCONN; return -ENOTCONN;
isdn_net_hangup(idev); isdn_net_hangup(idev);
...@@ -1186,7 +1186,7 @@ isdn_net_unbind_channel(isdn_net_dev *idev) ...@@ -1186,7 +1186,7 @@ isdn_net_unbind_channel(isdn_net_dev *idev)
{ {
isdn_net_local *mlp = idev->mlp; isdn_net_local *mlp = idev->mlp;
if (idev->isdn_slot < 0) { if (idev->isdn_slot == NULL) {
isdn_BUG(); isdn_BUG();
return; return;
} }
...@@ -1344,7 +1344,7 @@ isdn_net_autodial(struct sk_buff *skb, struct net_device *ndev) ...@@ -1344,7 +1344,7 @@ isdn_net_autodial(struct sk_buff *skb, struct net_device *ndev)
goto discard; goto discard;
/* Log packet, which triggered dialing */ /* Log packet, which triggered dialing */
if (dev->net_verbose) if ((get_isdn_dev())->net_verbose)
isdn_net_log_skb(skb, idev); isdn_net_log_skb(skb, idev);
stop_queue: stop_queue:
...@@ -1497,12 +1497,13 @@ isdn_net_dev_icall(isdn_net_dev *idev, struct isdn_slot *slot, ...@@ -1497,12 +1497,13 @@ isdn_net_dev_icall(isdn_net_dev *idev, struct isdn_slot *slot,
int int
isdn_net_find_icall(struct isdn_slot *slot, setup_parm *setup) isdn_net_find_icall(struct isdn_slot *slot, setup_parm *setup)
{ {
isdn_net_local *lp; isdn_net_local *lp;
isdn_net_dev *idev; isdn_net_dev *idev;
char *nr, *eaz; char *nr, *eaz;
unsigned char si1, si2; unsigned char si1, si2;
int retval; int retval;
unsigned long flags; int verbose = (get_isdn_dev())->net_verbose;
unsigned long flags;
/* fix up calling number */ /* fix up calling number */
if (!setup->phone[0]) { if (!setup->phone[0]) {
...@@ -1522,14 +1523,14 @@ isdn_net_find_icall(struct isdn_slot *slot, setup_parm *setup) ...@@ -1522,14 +1523,14 @@ isdn_net_find_icall(struct isdn_slot *slot, setup_parm *setup)
} }
si1 = setup->si1; si1 = setup->si1;
si2 = setup->si2; si2 = setup->si2;
if (dev->net_verbose > 1) if (verbose > 1)
printk(KERN_INFO "isdn_net: call from %s,%d,%d -> %s\n", printk(KERN_INFO "isdn_net: call from %s,%d,%d -> %s\n",
nr, si1, si2, eaz); nr, si1, si2, eaz);
/* check service indicator */ /* check service indicator */
/* Accept DATA and VOICE calls at this stage /* Accept DATA and VOICE calls at this stage
local eaz is checked later for allowed call types */ local eaz is checked later for allowed call types */
if ((si1 != 7) && (si1 != 1)) { if ((si1 != 7) && (si1 != 1)) {
if (dev->net_verbose > 1) if (verbose > 1)
printk(KERN_INFO "isdn_net: " printk(KERN_INFO "isdn_net: "
"Service-Indicator not 1 or 7, ignored\n"); "Service-Indicator not 1 or 7, ignored\n");
return 0; return 0;
...@@ -1558,7 +1559,7 @@ isdn_net_find_icall(struct isdn_slot *slot, setup_parm *setup) ...@@ -1558,7 +1559,7 @@ isdn_net_find_icall(struct isdn_slot *slot, setup_parm *setup)
} }
spin_unlock_irqrestore(&running_devs_lock, flags); spin_unlock_irqrestore(&running_devs_lock, flags);
if (!retval) { if (!retval) {
if (dev->net_verbose) if (verbose)
printk(KERN_INFO "isdn_net: call " printk(KERN_INFO "isdn_net: call "
"from %s -> %s ignored\n", nr, eaz); "from %s -> %s ignored\n", nr, eaz);
} }
...@@ -2174,10 +2175,10 @@ isdn_net_bsent(isdn_net_dev *idev, isdn_ctrl *c) ...@@ -2174,10 +2175,10 @@ isdn_net_bsent(isdn_net_dev *idev, isdn_ctrl *c)
int int
isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev) isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
{ {
isdn_net_dev *idev; isdn_net_dev *idev;
isdn_net_local *mlp = ndev->priv; isdn_net_local *mlp = ndev->priv;
unsigned long flags; unsigned long flags;
int retval; int retval;
ndev->trans_start = jiffies; ndev->trans_start = jiffies;
...@@ -2208,7 +2209,7 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev) ...@@ -2208,7 +2209,7 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
idev->last_jiffies = jiffies; idev->last_jiffies = jiffies;
idev->transcount = 0; idev->transcount = 0;
} }
if (dev->net_verbose > 3) if ((get_isdn_dev())->net_verbose > 3)
printk(KERN_DEBUG "%s: %d bogocps\n", idev->name, idev->cps); printk(KERN_DEBUG "%s: %d bogocps\n", idev->name, idev->cps);
if (idev->cps > mlp->triggercps) { if (idev->cps > mlp->triggercps) {
......
...@@ -381,7 +381,7 @@ isdn_tty_rcv_skb(struct isdn_slot *slot, struct sk_buff *skb) ...@@ -381,7 +381,7 @@ isdn_tty_rcv_skb(struct isdn_slot *slot, struct sk_buff *skb)
); );
restore_flags(flags); restore_flags(flags);
/* Schedule dequeuing */ /* Schedule dequeuing */
if (dev->modempoll && info->rcvsched) if ((get_isdn_dev())->modempoll && info->rcvsched)
mod_timer(&info->read_timer, jiffies + 4); mod_timer(&info->read_timer, jiffies + 4);
return 1; return 1;
} }
...@@ -1735,8 +1735,10 @@ isdn_tty_open(struct tty_struct *tty, struct file *filp) ...@@ -1735,8 +1735,10 @@ isdn_tty_open(struct tty_struct *tty, struct file *filp)
info = &isdn_mdm.info[line]; info = &isdn_mdm.info[line];
if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_open")) if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_open"))
return -ENODEV; return -ENODEV;
if (!try_module_get(info->owner)) if (!try_module_get(info->owner)) {
printk(KERN_WARNING "%s: cannot reserve module\n", __FUNCTION__); printk(KERN_WARNING "%s: cannot reserve module\n", __FUNCTION__);
return -ENODEV;
}
#ifdef ISDN_DEBUG_MODEM_OPEN #ifdef ISDN_DEBUG_MODEM_OPEN
printk(KERN_DEBUG "isdn_tty_open %s, count = %d\n", tty->name, printk(KERN_DEBUG "isdn_tty_open %s, count = %d\n", tty->name,
info->count); info->count);
...@@ -1766,7 +1768,7 @@ isdn_tty_open(struct tty_struct *tty, struct file *filp) ...@@ -1766,7 +1768,7 @@ isdn_tty_open(struct tty_struct *tty, struct file *filp)
#ifdef ISDN_DEBUG_MODEM_OPEN #ifdef ISDN_DEBUG_MODEM_OPEN
printk(KERN_DEBUG "isdn_tty_open ttyi%d successful...\n", info->line); printk(KERN_DEBUG "isdn_tty_open ttyi%d successful...\n", info->line);
#endif #endif
dev->modempoll++; (get_isdn_dev())->modempoll++;
#ifdef ISDN_DEBUG_MODEM_OPEN #ifdef ISDN_DEBUG_MODEM_OPEN
printk(KERN_DEBUG "isdn_tty_open normal exit\n"); printk(KERN_DEBUG "isdn_tty_open normal exit\n");
#endif #endif
...@@ -1785,6 +1787,7 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp) ...@@ -1785,6 +1787,7 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp)
if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_close")) if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_close"))
goto out; goto out;
#warning need fixing /kkeil
save_flags(flags); save_flags(flags);
cli(); cli();
if (tty_hung_up_p(filp)) { if (tty_hung_up_p(filp)) {
...@@ -1841,7 +1844,7 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp) ...@@ -1841,7 +1844,7 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp)
break; break;
} }
} }
dev->modempoll--; (get_isdn_dev())->modempoll--;
isdn_tty_shutdown(info); isdn_tty_shutdown(info);
if (tty->driver->flush_buffer) if (tty->driver->flush_buffer)
tty->driver->flush_buffer(tty); tty->driver->flush_buffer(tty);
...@@ -1985,8 +1988,8 @@ modem_write_profile(atemu * m) ...@@ -1985,8 +1988,8 @@ modem_write_profile(atemu * m)
memcpy(m->profile, m->mdmreg, ISDN_MODEM_NUMREG); memcpy(m->profile, m->mdmreg, ISDN_MODEM_NUMREG);
memcpy(m->pmsn, m->msn, ISDN_MSNLEN); memcpy(m->pmsn, m->msn, ISDN_MSNLEN);
memcpy(m->plmsn, m->lmsn, ISDN_LMSNLEN); memcpy(m->plmsn, m->lmsn, ISDN_LMSNLEN);
if (dev->profd) if ((get_isdn_dev())->profd)
kill_pg_info(SIGIO, SEND_SIG_PRIV, dev->profd->pgrp); kill_pg_info(SIGIO, SEND_SIG_PRIV, (get_isdn_dev())->profd->pgrp);
} }
static struct tty_operations modem_ops = { static struct tty_operations modem_ops = {
...@@ -2228,7 +2231,7 @@ isdn_tty_find_icall(struct isdn_slot *slot, setup_parm *setup) ...@@ -2228,7 +2231,7 @@ isdn_tty_find_icall(struct isdn_slot *slot, setup_parm *setup)
printk(KERN_DEBUG "m_fi: match1 wret=%d\n", wret); printk(KERN_DEBUG "m_fi: match1 wret=%d\n", wret);
printk(KERN_DEBUG "m_fi: sl=%d flags=%08lx drv=%d ch=%d usg=%d\n", sl, printk(KERN_DEBUG "m_fi: sl=%d flags=%08lx drv=%d ch=%d usg=%d\n", sl,
info->flags, info->isdn_driver, info->isdn_channel, info->flags, info->isdn_driver, info->isdn_channel,
dev->usage[idx]); slot->usage);
#endif #endif
if ( if (
#ifndef FIX_FILE_TRANSFER #ifndef FIX_FILE_TRANSFER
...@@ -2504,7 +2507,7 @@ isdn_tty_at_cout(char *msg, modem_info * info) ...@@ -2504,7 +2507,7 @@ isdn_tty_at_cout(char *msg, modem_info * info)
isdn_tty_queue_tail(info, skb, skb->len); isdn_tty_queue_tail(info, skb, skb->len);
restore_flags(flags); restore_flags(flags);
/* Schedule dequeuing */ /* Schedule dequeuing */
if (dev->modempoll && info->rcvsched) if ((get_isdn_dev())->modempoll && info->rcvsched)
mod_timer(&info->read_timer, jiffies + 4); mod_timer(&info->read_timer, jiffies + 4);
} else { } else {
restore_flags(flags); restore_flags(flags);
...@@ -3289,7 +3292,7 @@ isdn_tty_cmd_PLUSF(char **p, modem_info * info) ...@@ -3289,7 +3292,7 @@ isdn_tty_cmd_PLUSF(char **p, modem_info * info)
#ifdef CONFIG_ISDN_TTY_FAX #ifdef CONFIG_ISDN_TTY_FAX
case '1': case '1':
p[0]++; p[0]++;
if (!(dev->global_features & if (!((get_isdn_dev())->global_features &
ISDN_FEATURE_L3_FCLASS1)) ISDN_FEATURE_L3_FCLASS1))
PARSE_ERROR1; PARSE_ERROR1;
m->mdmreg[REG_SI1] = 1; m->mdmreg[REG_SI1] = 1;
...@@ -3300,7 +3303,7 @@ isdn_tty_cmd_PLUSF(char **p, modem_info * info) ...@@ -3300,7 +3303,7 @@ isdn_tty_cmd_PLUSF(char **p, modem_info * info)
break; break;
case '2': case '2':
p[0]++; p[0]++;
if (!(dev->global_features & if (!((get_isdn_dev())->global_features &
ISDN_FEATURE_L3_FCLASS2)) ISDN_FEATURE_L3_FCLASS2))
PARSE_ERROR1; PARSE_ERROR1;
m->mdmreg[REG_SI1] = 1; m->mdmreg[REG_SI1] = 1;
...@@ -3322,10 +3325,10 @@ isdn_tty_cmd_PLUSF(char **p, modem_info * info) ...@@ -3322,10 +3325,10 @@ isdn_tty_cmd_PLUSF(char **p, modem_info * info)
p[0]++; p[0]++;
strcpy(rs, "\r\n0,"); strcpy(rs, "\r\n0,");
#ifdef CONFIG_ISDN_TTY_FAX #ifdef CONFIG_ISDN_TTY_FAX
if (dev->global_features & if ((get_isdn_dev())->global_features &
ISDN_FEATURE_L3_FCLASS1) ISDN_FEATURE_L3_FCLASS1)
strcat(rs, "1,"); strcat(rs, "1,");
if (dev->global_features & if ((get_isdn_dev())->global_features &
ISDN_FEATURE_L3_FCLASS2) ISDN_FEATURE_L3_FCLASS2)
strcat(rs, "2,"); strcat(rs, "2,");
#endif #endif
......
...@@ -43,8 +43,6 @@ MODULE_PARM_DESC(icn_id2, "ID-String of first card, second S0 (4B only)"); ...@@ -43,8 +43,6 @@ MODULE_PARM_DESC(icn_id2, "ID-String of first card, second S0 (4B only)");
static char static char
*revision = "$Revision: 1.65.6.8 $"; *revision = "$Revision: 1.65.6.8 $";
static spinlock_t icn_lock = SPIN_LOCK_UNLOCKED;
static int icn_addcard(int, char *, char *); static int icn_addcard(int, char *, char *);
/* /*
...@@ -58,18 +56,14 @@ icn_free_queue(icn_card * card, int channel) ...@@ -58,18 +56,14 @@ icn_free_queue(icn_card * card, int channel)
{ {
struct sk_buff_head *queue = &card->spqueue[channel]; struct sk_buff_head *queue = &card->spqueue[channel];
struct sk_buff *skb; struct sk_buff *skb;
unsigned long flags;
skb_queue_purge(queue); skb_queue_purge(queue);
spin_lock_irqsave(&icn_lock, flags);
card->xlen[channel] = 0; card->xlen[channel] = 0;
card->sndcount[channel] = 0; card->sndcount[channel] = 0;
if ((skb = card->xskb[channel])) { if ((skb = card->xskb[channel])) {
card->xskb[channel] = NULL; card->xskb[channel] = NULL;
spin_unlock_irqrestore(&icn_lock, flags);
dev_kfree_skb(skb); dev_kfree_skb(skb);
} else }
spin_unlock_irqrestore(&icn_lock, flags);
} }
/* Put a value into a shift-register, highest bit first. /* Put a value into a shift-register, highest bit first.
...@@ -113,6 +107,8 @@ icn_enable_ram(icn_card * card) ...@@ -113,6 +107,8 @@ icn_enable_ram(icn_card * card)
/* /*
* Map a cards channel0 (Bank0/Bank8) or channel1 (Bank4/Bank12) * Map a cards channel0 (Bank0/Bank8) or channel1 (Bank4/Bank12)
*
* must called with holding the devlock
*/ */
static inline void static inline void
icn_map_channel(icn_card * card, int channel) icn_map_channel(icn_card * card, int channel)
...@@ -137,17 +133,17 @@ icn_map_channel(icn_card * card, int channel) ...@@ -137,17 +133,17 @@ icn_map_channel(icn_card * card, int channel)
* Lock a cards channel. * Lock a cards channel.
* Return 0 if requested card/channel is unmapped (failure). * Return 0 if requested card/channel is unmapped (failure).
* Return 1 on success. * Return 1 on success.
*
* must called with holding the devlock
*/ */
static inline int static inline int
icn_lock_channel(icn_card * card, int channel) icn_lock_channel(icn_card * card, int channel)
{ {
register int retval; register int retval;
ulong flags;
#ifdef MAP_DEBUG #ifdef MAP_DEBUG
printk(KERN_DEBUG "icn_lock_channel %d\n", channel); printk(KERN_DEBUG "icn_lock_channel %d\n", channel);
#endif #endif
spin_lock_irqsave(&icn_lock, flags);
if ((dev.channel == channel) && (card == dev.mcard)) { if ((dev.channel == channel) && (card == dev.mcard)) {
dev.chanlock++; dev.chanlock++;
retval = 1; retval = 1;
...@@ -160,25 +156,35 @@ icn_lock_channel(icn_card * card, int channel) ...@@ -160,25 +156,35 @@ icn_lock_channel(icn_card * card, int channel)
printk(KERN_DEBUG "icn_lock_channel %d FAILED, dc=%d\n", channel, dev.channel); printk(KERN_DEBUG "icn_lock_channel %d FAILED, dc=%d\n", channel, dev.channel);
#endif #endif
} }
spin_unlock_irqrestore(&icn_lock, flags);
return retval; return retval;
} }
/* /*
* Release current card/channel lock * Release current card/channel lock
*
* must called with holding the devlock
*/ */
static inline void static inline void
icn_release_channel(void) __icn_release_channel(void)
{ {
ulong flags;
#ifdef MAP_DEBUG #ifdef MAP_DEBUG
printk(KERN_DEBUG "icn_release_channel l=%d\n", dev.chanlock); printk(KERN_DEBUG "icn_release_channel l=%d\n", dev.chanlock);
#endif #endif
spin_lock_irqsave(&icn_lock, flags);
if (dev.chanlock > 0) if (dev.chanlock > 0)
dev.chanlock--; dev.chanlock--;
spin_unlock_irqrestore(&icn_lock, flags); }
/*
* Release current card/channel lock
*/
static inline void
icn_release_channel(void)
{
ulong flags;
spin_lock_irqsave(&dev.devlock, flags);
__icn_release_channel();
spin_unlock_irqrestore(&dev.devlock, flags);
} }
/* /*
...@@ -194,18 +200,18 @@ icn_trymaplock_channel(icn_card * card, int channel) ...@@ -194,18 +200,18 @@ icn_trymaplock_channel(icn_card * card, int channel)
printk(KERN_DEBUG "trymaplock c=%d dc=%d l=%d\n", channel, dev.channel, printk(KERN_DEBUG "trymaplock c=%d dc=%d l=%d\n", channel, dev.channel,
dev.chanlock); dev.chanlock);
#endif #endif
spin_lock_irqsave(&icn_lock, flags); spin_lock_irqsave(&dev.devlock, flags);
if ((!dev.chanlock) || if ((!dev.chanlock) ||
((dev.channel == channel) && (dev.mcard == card))) { ((dev.channel == channel) && (dev.mcard == card))) {
dev.chanlock++; dev.chanlock++;
icn_map_channel(card, channel); icn_map_channel(card, channel);
spin_unlock_irqrestore(&icn_lock, flags); spin_unlock_irqrestore(&dev.devlock, flags);
#ifdef MAP_DEBUG #ifdef MAP_DEBUG
printk(KERN_DEBUG "trymaplock %d OK\n", channel); printk(KERN_DEBUG "trymaplock %d OK\n", channel);
#endif #endif
return 1; return 1;
} }
spin_unlock_irqrestore(&icn_lock, flags); spin_unlock_irqrestore(&dev.devlock, flags);
#ifdef MAP_DEBUG #ifdef MAP_DEBUG
printk(KERN_DEBUG "trymaplock %d FAILED\n", channel); printk(KERN_DEBUG "trymaplock %d FAILED\n", channel);
#endif #endif
...@@ -224,12 +230,12 @@ icn_maprelease_channel(icn_card * card, int channel) ...@@ -224,12 +230,12 @@ icn_maprelease_channel(icn_card * card, int channel)
#ifdef MAP_DEBUG #ifdef MAP_DEBUG
printk(KERN_DEBUG "map_release c=%d l=%d\n", channel, dev.chanlock); printk(KERN_DEBUG "map_release c=%d l=%d\n", channel, dev.chanlock);
#endif #endif
spin_lock_irqsave(&icn_lock, flags); spin_lock_irqsave(&dev.devlock, flags);
if (dev.chanlock > 0) if (dev.chanlock > 0)
dev.chanlock--; dev.chanlock--;
if (!dev.chanlock) if (!dev.chanlock)
icn_map_channel(card, channel); icn_map_channel(card, channel);
spin_unlock_irqrestore(&icn_lock, flags); spin_unlock_irqrestore(&dev.devlock, flags);
} }
/* Get Data from the B-Channel, assemble fragmented packets and put them /* Get Data from the B-Channel, assemble fragmented packets and put them
...@@ -305,13 +311,13 @@ icn_pollbchan_send(int channel, icn_card * card) ...@@ -305,13 +311,13 @@ icn_pollbchan_send(int channel, icn_card * card)
(card->sndcount[channel] || (card->sndcount[channel] ||
skb_queue_len(&card->spqueue[channel]) || skb_queue_len(&card->spqueue[channel]) ||
card->xskb[channel])) { card->xskb[channel])) {
spin_lock_irqsave(&icn_lock, flags); spin_lock_irqsave(&card->lock, flags);
if (card->xmit_lock[channel]) { if (card->xmit_lock[channel]) {
spin_unlock_irqrestore(&icn_lock, flags); spin_unlock_irqrestore(&card->lock, flags);
break; break;
} }
card->xmit_lock[channel]++; card->xmit_lock[channel]++;
spin_unlock_irqrestore(&icn_lock, flags); spin_unlock_irqrestore(&card->lock, flags);
skb = card->xskb[channel]; skb = card->xskb[channel];
if (!skb) { if (!skb) {
skb = skb_dequeue(&card->spqueue[channel]); skb = skb_dequeue(&card->spqueue[channel]);
...@@ -337,14 +343,15 @@ icn_pollbchan_send(int channel, icn_card * card) ...@@ -337,14 +343,15 @@ icn_pollbchan_send(int channel, icn_card * card)
writeb(cnt, &sbuf_l); writeb(cnt, &sbuf_l);
memcpy_toio(&sbuf_d, skb->data, cnt); memcpy_toio(&sbuf_d, skb->data, cnt);
skb_pull(skb, cnt); skb_pull(skb, cnt);
card->sndcount[channel] -= cnt;
sbnext; /* switch to next buffer */ sbnext; /* switch to next buffer */
icn_maprelease_channel(card, mch & 2); icn_maprelease_channel(card, mch & 2);
spin_lock_irqsave(&card->lock, flags);
card->sndcount[channel] -= cnt;
if (!skb->len) { if (!skb->len) {
spin_lock_irqsave(&icn_lock, flags);
if (card->xskb[channel]) if (card->xskb[channel])
card->xskb[channel] = NULL; card->xskb[channel] = NULL;
spin_unlock_irqrestore(&icn_lock, flags); card->xmit_lock[channel] = 0;
spin_unlock_irqrestore(&card->lock, flags);
dev_kfree_skb(skb); dev_kfree_skb(skb);
if (card->xlen[channel]) { if (card->xlen[channel]) {
cmd.command = ISDN_STAT_BSENT; cmd.command = ISDN_STAT_BSENT;
...@@ -354,11 +361,10 @@ icn_pollbchan_send(int channel, icn_card * card) ...@@ -354,11 +361,10 @@ icn_pollbchan_send(int channel, icn_card * card)
card->interface.statcallb(&cmd); card->interface.statcallb(&cmd);
} }
} else { } else {
spin_lock_irqsave(&icn_lock, flags);
card->xskb[channel] = skb; card->xskb[channel] = skb;
spin_unlock_irqrestore(&icn_lock, flags); card->xmit_lock[channel] = 0;
spin_unlock_irqrestore(&card->lock, flags);
} }
card->xmit_lock[channel] = 0;
if (!icn_trymaplock_channel(card, mch)) if (!icn_trymaplock_channel(card, mch))
break; break;
} }
...@@ -387,10 +393,10 @@ icn_pollbchan(unsigned long data) ...@@ -387,10 +393,10 @@ icn_pollbchan(unsigned long data)
} }
if (card->flags & (ICN_FLAGS_B1ACTIVE | ICN_FLAGS_B2ACTIVE)) { if (card->flags & (ICN_FLAGS_B1ACTIVE | ICN_FLAGS_B2ACTIVE)) {
/* schedule b-channel polling again */ /* schedule b-channel polling again */
spin_lock_irqsave(&icn_lock, flags); spin_lock_irqsave(&card->lock, flags);
mod_timer(&card->rb_timer, jiffies+ICN_TIMER_BCREAD); mod_timer(&card->rb_timer, jiffies+ICN_TIMER_BCREAD);
card->flags |= ICN_FLAGS_RBTIMER; card->flags |= ICN_FLAGS_RBTIMER;
spin_unlock_irqrestore(&icn_lock, flags); spin_unlock_irqrestore(&card->lock, flags);
} else } else
card->flags &= ~ICN_FLAGS_RBTIMER; card->flags &= ~ICN_FLAGS_RBTIMER;
} }
...@@ -458,7 +464,7 @@ icn_parse_status(u_char * status, int channel, icn_card * card) ...@@ -458,7 +464,7 @@ icn_parse_status(u_char * status, int channel, icn_card * card)
cmd.arg = channel; cmd.arg = channel;
switch (action) { switch (action) {
case 11: case 11:
spin_lock_irqsave(&icn_lock, flags); spin_lock_irqsave(&card->lock, flags);
icn_free_queue(card,channel); icn_free_queue(card,channel);
card->rcvidx[channel] = 0; card->rcvidx[channel] = 0;
...@@ -475,23 +481,25 @@ icn_parse_status(u_char * status, int channel, icn_card * card) ...@@ -475,23 +481,25 @@ icn_parse_status(u_char * status, int channel, icn_card * card)
ncmd.driver = card->myid; ncmd.driver = card->myid;
ncmd.arg = channel; ncmd.arg = channel;
ncmd.command = ISDN_STAT_BHUP; ncmd.command = ISDN_STAT_BHUP;
spin_unlock_irqrestore(&icn_lock, flags); spin_unlock_irqrestore(&card->lock, flags);
card->interface.statcallb(&cmd); card->interface.statcallb(&cmd);
} else } else
spin_unlock_irqrestore(&icn_lock, flags); spin_unlock_irqrestore(&card->lock, flags);
break; break;
case 1: case 1:
spin_lock_irqsave(&card->lock, flags);
icn_free_queue(card,channel); icn_free_queue(card,channel);
card->flags |= (channel) ? card->flags |= (channel) ?
ICN_FLAGS_B2ACTIVE : ICN_FLAGS_B1ACTIVE; ICN_FLAGS_B2ACTIVE : ICN_FLAGS_B1ACTIVE;
spin_unlock_irqrestore(&card->lock, flags);
break; break;
case 2: case 2:
spin_lock_irqsave(&card->lock, flags);
card->flags &= ~((channel) ? card->flags &= ~((channel) ?
ICN_FLAGS_B2ACTIVE : ICN_FLAGS_B1ACTIVE); ICN_FLAGS_B2ACTIVE : ICN_FLAGS_B1ACTIVE);
icn_free_queue(card, channel); icn_free_queue(card, channel);
spin_lock_irqsave(&icn_lock, flags);
card->rcvidx[channel] = 0; card->rcvidx[channel] = 0;
spin_unlock_irqrestore(&icn_lock, flags); spin_unlock_irqrestore(&card->lock, flags);
break; break;
case 3: case 3:
{ {
...@@ -545,11 +553,11 @@ icn_parse_status(u_char * status, int channel, icn_card * card) ...@@ -545,11 +553,11 @@ icn_parse_status(u_char * status, int channel, icn_card * card)
strlcpy(cmd.parm.num, status + 1, sizeof(cmd.parm.num)); strlcpy(cmd.parm.num, status + 1, sizeof(cmd.parm.num));
break; break;
case 8: case 8:
spin_lock_irqsave(&card->lock, flags);
card->flags &= ~ICN_FLAGS_B1ACTIVE; card->flags &= ~ICN_FLAGS_B1ACTIVE;
icn_free_queue(card, 0); icn_free_queue(card, 0);
spin_lock_irqsave(&icn_lock, flags);
card->rcvidx[0] = 0; card->rcvidx[0] = 0;
spin_unlock_irqrestore(&icn_lock, flags); spin_unlock_irqrestore(&card->lock, flags);
cmd.arg = 0; cmd.arg = 0;
cmd.driver = card->myid; cmd.driver = card->myid;
card->interface.statcallb(&cmd); card->interface.statcallb(&cmd);
...@@ -558,11 +566,11 @@ icn_parse_status(u_char * status, int channel, icn_card * card) ...@@ -558,11 +566,11 @@ icn_parse_status(u_char * status, int channel, icn_card * card)
cmd.driver = card->myid; cmd.driver = card->myid;
card->interface.statcallb(&cmd); card->interface.statcallb(&cmd);
cmd.command = ISDN_STAT_BHUP; cmd.command = ISDN_STAT_BHUP;
spin_lock_irqsave(&card->lock, flags);
card->flags &= ~ICN_FLAGS_B2ACTIVE; card->flags &= ~ICN_FLAGS_B2ACTIVE;
icn_free_queue(card, 1); icn_free_queue(card, 1);
spin_lock_irqsave(&icn_lock, flags);
card->rcvidx[1] = 0; card->rcvidx[1] = 0;
spin_unlock_irqrestore(&icn_lock, flags); spin_unlock_irqrestore(&card->lock, flags);
cmd.arg = 1; cmd.arg = 1;
cmd.driver = card->myid; cmd.driver = card->myid;
card->interface.statcallb(&cmd); card->interface.statcallb(&cmd);
...@@ -580,7 +588,7 @@ icn_putmsg(icn_card * card, unsigned char c) ...@@ -580,7 +588,7 @@ icn_putmsg(icn_card * card, unsigned char c)
{ {
ulong flags; ulong flags;
spin_lock_irqsave(&icn_lock, flags); spin_lock_irqsave(&card->lock, flags);
*card->msg_buf_write++ = (c == 0xff) ? '\n' : c; *card->msg_buf_write++ = (c == 0xff) ? '\n' : c;
if (card->msg_buf_write == card->msg_buf_read) { if (card->msg_buf_write == card->msg_buf_read) {
if (++card->msg_buf_read > card->msg_buf_end) if (++card->msg_buf_read > card->msg_buf_end)
...@@ -588,7 +596,7 @@ icn_putmsg(icn_card * card, unsigned char c) ...@@ -588,7 +596,7 @@ icn_putmsg(icn_card * card, unsigned char c)
} }
if (card->msg_buf_write > card->msg_buf_end) if (card->msg_buf_write > card->msg_buf_end)
card->msg_buf_write = card->msg_buf; card->msg_buf_write = card->msg_buf;
spin_unlock_irqrestore(&icn_lock, flags); spin_unlock_irqrestore(&card->lock, flags);
} }
static void static void
...@@ -666,22 +674,20 @@ icn_polldchan(unsigned long data) ...@@ -666,22 +674,20 @@ icn_polldchan(unsigned long data)
cmd.arg = avail; cmd.arg = avail;
card->interface.statcallb(&cmd); card->interface.statcallb(&cmd);
} }
spin_lock_irqsave(&card->lock, flags);
if (card->flags & (ICN_FLAGS_B1ACTIVE | ICN_FLAGS_B2ACTIVE)) if (card->flags & (ICN_FLAGS_B1ACTIVE | ICN_FLAGS_B2ACTIVE))
if (!(card->flags & ICN_FLAGS_RBTIMER)) { if (!(card->flags & ICN_FLAGS_RBTIMER)) {
/* schedule b-channel polling */ /* schedule b-channel polling */
card->flags |= ICN_FLAGS_RBTIMER; card->flags |= ICN_FLAGS_RBTIMER;
spin_lock_irqsave(&icn_lock, flags);
del_timer(&card->rb_timer); del_timer(&card->rb_timer);
card->rb_timer.function = icn_pollbchan; card->rb_timer.function = icn_pollbchan;
card->rb_timer.data = (unsigned long) card; card->rb_timer.data = (unsigned long) card;
card->rb_timer.expires = jiffies + ICN_TIMER_BCREAD; card->rb_timer.expires = jiffies + ICN_TIMER_BCREAD;
add_timer(&card->rb_timer); add_timer(&card->rb_timer);
spin_unlock_irqrestore(&icn_lock, flags);
} }
/* schedule again */ /* schedule again */
spin_lock_irqsave(&icn_lock, flags);
mod_timer(&card->st_timer, jiffies+ICN_TIMER_DCREAD); mod_timer(&card->st_timer, jiffies+ICN_TIMER_DCREAD);
spin_unlock_irqrestore(&icn_lock, flags); spin_unlock_irqrestore(&card->lock, flags);
} }
/* Append a packet to the transmit buffer-queue. /* Append a packet to the transmit buffer-queue.
...@@ -710,7 +716,7 @@ icn_sendbuf(int channel, int ack, struct sk_buff *skb, icn_card * card) ...@@ -710,7 +716,7 @@ icn_sendbuf(int channel, int ack, struct sk_buff *skb, icn_card * card)
return 0; return 0;
if (card->sndcount[channel] > ICN_MAX_SQUEUE) if (card->sndcount[channel] > ICN_MAX_SQUEUE)
return 0; return 0;
spin_lock_irqsave(&icn_lock, flags); #warning TODO test headroom or use skb->nb to flag ACK
nskb = skb_clone(skb, GFP_ATOMIC); nskb = skb_clone(skb, GFP_ATOMIC);
if (nskb) { if (nskb) {
/* Push ACK flag as one /* Push ACK flag as one
...@@ -721,8 +727,9 @@ icn_sendbuf(int channel, int ack, struct sk_buff *skb, icn_card * card) ...@@ -721,8 +727,9 @@ icn_sendbuf(int channel, int ack, struct sk_buff *skb, icn_card * card)
dev_kfree_skb(skb); dev_kfree_skb(skb);
} else } else
len = 0; len = 0;
spin_lock_irqsave(&card->lock, flags);
card->sndcount[channel] += len; card->sndcount[channel] += len;
spin_unlock_irqrestore(&icn_lock, flags); spin_unlock_irqrestore(&card->lock, flags);
} }
return len; return len;
} }
...@@ -844,10 +851,10 @@ icn_loadboot(u_char * buffer, icn_card * card) ...@@ -844,10 +851,10 @@ icn_loadboot(u_char * buffer, icn_card * card)
#ifdef BOOT_DEBUG #ifdef BOOT_DEBUG
printk(KERN_DEBUG "Map Bank 0\n"); printk(KERN_DEBUG "Map Bank 0\n");
#endif #endif
spin_lock_irqsave(&icn_lock, flags); spin_lock_irqsave(&dev.devlock, flags);
icn_map_channel(card, 0); /* Select Bank 0 */ icn_map_channel(card, 0); /* Select Bank 0 */
icn_lock_channel(card, 0); /* Lock Bank 0 */ icn_lock_channel(card, 0); /* Lock Bank 0 */
spin_unlock_irqrestore(&icn_lock, flags); spin_unlock_irqrestore(&dev.devlock, flags);
SLEEP(1); SLEEP(1);
memcpy_toio(dev.shmem, codebuf, ICN_CODE_STAGE1); /* Copy code */ memcpy_toio(dev.shmem, codebuf, ICN_CODE_STAGE1); /* Copy code */
#ifdef BOOT_DEBUG #ifdef BOOT_DEBUG
...@@ -858,11 +865,11 @@ icn_loadboot(u_char * buffer, icn_card * card) ...@@ -858,11 +865,11 @@ icn_loadboot(u_char * buffer, icn_card * card)
#ifdef BOOT_DEBUG #ifdef BOOT_DEBUG
printk(KERN_DEBUG "Map Bank 8\n"); printk(KERN_DEBUG "Map Bank 8\n");
#endif #endif
spin_lock_irqsave(&icn_lock, flags); spin_lock_irqsave(&dev.devlock, flags);
icn_release_channel(); __icn_release_channel();
icn_map_channel(card, 2); /* Select Bank 8 */ icn_map_channel(card, 2); /* Select Bank 8 */
icn_lock_channel(card, 2); /* Lock Bank 8 */ icn_lock_channel(card, 2); /* Lock Bank 8 */
spin_unlock_irqrestore(&icn_lock, flags); spin_unlock_irqrestore(&dev.devlock, flags);
SLEEP(1); SLEEP(1);
memcpy_toio(dev.shmem, codebuf, ICN_CODE_STAGE1); /* Copy code */ memcpy_toio(dev.shmem, codebuf, ICN_CODE_STAGE1); /* Copy code */
#ifdef BOOT_DEBUG #ifdef BOOT_DEBUG
...@@ -882,10 +889,10 @@ icn_loadboot(u_char * buffer, icn_card * card) ...@@ -882,10 +889,10 @@ icn_loadboot(u_char * buffer, icn_card * card)
#ifdef BOOT_DEBUG #ifdef BOOT_DEBUG
printk(KERN_DEBUG "Map Bank 0\n"); printk(KERN_DEBUG "Map Bank 0\n");
#endif #endif
spin_lock_irqsave(&icn_lock, flags); spin_lock_irqsave(&dev.devlock, flags);
icn_map_channel(card, 0); /* Select Bank 0 */ icn_map_channel(card, 0); /* Select Bank 0 */
icn_lock_channel(card, 0); /* Lock Bank 0 */ icn_lock_channel(card, 0); /* Lock Bank 0 */
spin_unlock_irqrestore(&icn_lock, flags); spin_unlock_irqrestore(&dev.devlock, flags);
SLEEP(1); SLEEP(1);
ret = (icn_check_loader(1)); ret = (icn_check_loader(1));
...@@ -912,7 +919,7 @@ icn_loadproto(u_char * buffer, icn_card * card) ...@@ -912,7 +919,7 @@ icn_loadproto(u_char * buffer, icn_card * card)
if ((ret = verify_area(VERIFY_READ, (void *) buffer, ICN_CODE_STAGE2))) if ((ret = verify_area(VERIFY_READ, (void *) buffer, ICN_CODE_STAGE2)))
return ret; return ret;
timer = 0; timer = 0;
spin_lock_irqsave(&icn_lock, flags); spin_lock_irqsave(&dev.devlock, flags);
if (card->secondhalf) { if (card->secondhalf) {
icn_map_channel(card, 2); icn_map_channel(card, 2);
icn_lock_channel(card, 2); icn_lock_channel(card, 2);
...@@ -920,7 +927,7 @@ icn_loadproto(u_char * buffer, icn_card * card) ...@@ -920,7 +927,7 @@ icn_loadproto(u_char * buffer, icn_card * card)
icn_map_channel(card, 0); icn_map_channel(card, 0);
icn_lock_channel(card, 0); icn_lock_channel(card, 0);
} }
spin_unlock_irqrestore(&icn_lock, flags); spin_unlock_irqrestore(&dev.devlock, flags);
while (left) { while (left) {
if (sbfree) { /* If there is a free buffer... */ if (sbfree) { /* If there is a free buffer... */
cnt = left; cnt = left;
...@@ -975,7 +982,7 @@ icn_loadproto(u_char * buffer, icn_card * card) ...@@ -975,7 +982,7 @@ icn_loadproto(u_char * buffer, icn_card * card)
printk(KERN_DEBUG "Proto loaded, install poll-timer %d\n", printk(KERN_DEBUG "Proto loaded, install poll-timer %d\n",
card->secondhalf); card->secondhalf);
#endif #endif
spin_lock_irqsave(&icn_lock, flags); spin_lock_irqsave(&card->lock, flags);
init_timer(&card->st_timer); init_timer(&card->st_timer);
card->st_timer.expires = jiffies + ICN_TIMER_DCREAD; card->st_timer.expires = jiffies + ICN_TIMER_DCREAD;
card->st_timer.function = icn_polldchan; card->st_timer.function = icn_polldchan;
...@@ -990,7 +997,7 @@ icn_loadproto(u_char * buffer, icn_card * card) ...@@ -990,7 +997,7 @@ icn_loadproto(u_char * buffer, icn_card * card)
add_timer(&card->other->st_timer); add_timer(&card->other->st_timer);
card->other->flags |= ICN_FLAGS_RUNNING; card->other->flags |= ICN_FLAGS_RUNNING;
} }
spin_unlock_irqrestore(&icn_lock, flags); spin_unlock_irqrestore(&card->lock, flags);
} }
icn_maprelease_channel(card, 0); icn_maprelease_channel(card, 0);
return 0; return 0;
...@@ -1048,7 +1055,7 @@ icn_writecmd(const u_char * buf, int len, int user, icn_card * card) ...@@ -1048,7 +1055,7 @@ icn_writecmd(const u_char * buf, int len, int user, icn_card * card)
} else } else
memcpy(msg, buf, count); memcpy(msg, buf, count);
spin_lock_irqsave(&icn_lock, flags); spin_lock_irqsave(&dev.devlock, flags);
lastmap_card = dev.mcard; lastmap_card = dev.mcard;
lastmap_channel = dev.channel; lastmap_channel = dev.channel;
icn_map_channel(card, mch); icn_map_channel(card, mch);
...@@ -1070,7 +1077,7 @@ icn_writecmd(const u_char * buf, int len, int user, icn_card * card) ...@@ -1070,7 +1077,7 @@ icn_writecmd(const u_char * buf, int len, int user, icn_card * card)
writeb((readb(&cmd_i) + count) & 0xff, &cmd_i); writeb((readb(&cmd_i) + count) & 0xff, &cmd_i);
if (lastmap_card) if (lastmap_card)
icn_map_channel(lastmap_card, lastmap_channel); icn_map_channel(lastmap_card, lastmap_channel);
spin_unlock_irqrestore(&icn_lock, flags); spin_unlock_irqrestore(&dev.devlock, flags);
if (len) { if (len) {
mdelay(1); mdelay(1);
if (loop++ > 20) if (loop++ > 20)
...@@ -1096,18 +1103,19 @@ icn_stopcard(icn_card * card) ...@@ -1096,18 +1103,19 @@ icn_stopcard(icn_card * card)
unsigned long flags; unsigned long flags;
isdn_ctrl cmd; isdn_ctrl cmd;
spin_lock_irqsave(&icn_lock, flags); spin_lock_irqsave(&card->lock, flags);
if (card->flags & ICN_FLAGS_RUNNING) { if (card->flags & ICN_FLAGS_RUNNING) {
card->flags &= ~ICN_FLAGS_RUNNING; card->flags &= ~ICN_FLAGS_RUNNING;
del_timer(&card->st_timer); del_timer(&card->st_timer);
del_timer(&card->rb_timer); del_timer(&card->rb_timer);
spin_unlock_irqrestore(&card->lock, flags);
cmd.command = ISDN_STAT_STOP; cmd.command = ISDN_STAT_STOP;
cmd.driver = card->myid; cmd.driver = card->myid;
card->interface.statcallb(&cmd); card->interface.statcallb(&cmd);
if (card->doubleS0) if (card->doubleS0)
icn_stopcard(card->other); icn_stopcard(card->other);
} } else
spin_unlock_irqrestore(&icn_lock, flags); spin_unlock_irqrestore(&card->lock, flags);
} }
static void static void
...@@ -1170,14 +1178,14 @@ icn_command(isdn_ctrl * c, icn_card * card) ...@@ -1170,14 +1178,14 @@ icn_command(isdn_ctrl * c, icn_card * card)
} }
release_mem_region(a & 0x0ffc000, 0x4000); release_mem_region(a & 0x0ffc000, 0x4000);
icn_stopallcards(); icn_stopallcards();
spin_lock_irqsave(&icn_lock, flags); spin_lock_irqsave(&card->lock, flags);
if (dev.mvalid) { if (dev.mvalid) {
iounmap(dev.shmem); iounmap(dev.shmem);
release_mem_region(dev.memaddr, 0x4000); release_mem_region(dev.memaddr, 0x4000);
} }
dev.mvalid = 0; dev.mvalid = 0;
dev.memaddr = a & 0x0ffc000; dev.memaddr = a & 0x0ffc000;
spin_unlock_irqrestore(&icn_lock, flags); spin_unlock_irqrestore(&card->lock, flags);
printk(KERN_INFO printk(KERN_INFO
"icn: (%s) mmio set to 0x%08lx\n", "icn: (%s) mmio set to 0x%08lx\n",
CID, CID,
...@@ -1200,7 +1208,7 @@ icn_command(isdn_ctrl * c, icn_card * card) ...@@ -1200,7 +1208,7 @@ icn_command(isdn_ctrl * c, icn_card * card)
} }
release_region((unsigned short) a, ICN_PORTLEN); release_region((unsigned short) a, ICN_PORTLEN);
icn_stopcard(card); icn_stopcard(card);
spin_lock_irqsave(&icn_lock, flags); spin_lock_irqsave(&card->lock, flags);
if (card->rvalid) if (card->rvalid)
release_region(card->port, ICN_PORTLEN); release_region(card->port, ICN_PORTLEN);
card->port = (unsigned short) a; card->port = (unsigned short) a;
...@@ -1209,7 +1217,7 @@ icn_command(isdn_ctrl * c, icn_card * card) ...@@ -1209,7 +1217,7 @@ icn_command(isdn_ctrl * c, icn_card * card)
card->other->port = (unsigned short) a; card->other->port = (unsigned short) a;
card->other->rvalid = 0; card->other->rvalid = 0;
} }
spin_unlock_irqrestore(&icn_lock, flags); spin_unlock_irqrestore(&card->lock, flags);
printk(KERN_INFO printk(KERN_INFO
"icn: (%s) port set to 0x%03x\n", "icn: (%s) port set to 0x%03x\n",
CID, card->port); CID, card->port);
...@@ -1522,6 +1530,7 @@ icn_initcard(int port, char *id) ...@@ -1522,6 +1530,7 @@ icn_initcard(int port, char *id)
return (icn_card *) 0; return (icn_card *) 0;
} }
memset((char *) card, 0, sizeof(icn_card)); memset((char *) card, 0, sizeof(icn_card));
spin_lock_init(&card->lock);
card->port = port; card->port = port;
card->interface.owner = THIS_MODULE; card->interface.owner = THIS_MODULE;
card->interface.hl_hdrlen = 1; card->interface.hl_hdrlen = 1;
...@@ -1629,6 +1638,7 @@ static int __init icn_init(void) ...@@ -1629,6 +1638,7 @@ static int __init icn_init(void)
dev.channel = -1; dev.channel = -1;
dev.mcard = NULL; dev.mcard = NULL;
dev.firstload = 1; dev.firstload = 1;
spin_lock_init(&dev.devlock);
if ((p = strchr(revision, ':'))) { if ((p = strchr(revision, ':'))) {
strcpy(rev, p + 1); strcpy(rev, p + 1);
...@@ -1647,12 +1657,14 @@ static void __exit icn_exit(void) ...@@ -1647,12 +1657,14 @@ static void __exit icn_exit(void)
icn_card *card = cards; icn_card *card = cards;
icn_card *last; icn_card *last;
int i; int i;
unsigned long flags;
icn_stopallcards(); icn_stopallcards();
while (card) { while (card) {
cmd.command = ISDN_STAT_UNLOAD; cmd.command = ISDN_STAT_UNLOAD;
cmd.driver = card->myid; cmd.driver = card->myid;
card->interface.statcallb(&cmd); card->interface.statcallb(&cmd);
spin_lock_irqsave(&card->lock, flags);
if (card->rvalid) { if (card->rvalid) {
OUTB_P(0, ICN_RUN); /* Reset Controller */ OUTB_P(0, ICN_RUN); /* Reset Controller */
OUTB_P(0, ICN_MAPRAM); /* Disable RAM */ OUTB_P(0, ICN_MAPRAM); /* Disable RAM */
...@@ -1664,8 +1676,10 @@ static void __exit icn_exit(void) ...@@ -1664,8 +1676,10 @@ static void __exit icn_exit(void)
icn_free_queue(card, i); icn_free_queue(card, i);
} }
card = card->next; card = card->next;
spin_unlock_irqrestore(&card->lock, flags);
} }
card = cards; card = cards;
cards = NULL;
while (card) { while (card) {
last = card; last = card;
card = card->next; card = card->next;
......
...@@ -142,15 +142,15 @@ typedef struct icn_card { ...@@ -142,15 +142,15 @@ typedef struct icn_card {
int myid; /* Driver-Nr. assigned by linklevel */ int myid; /* Driver-Nr. assigned by linklevel */
int rvalid; /* IO-portregion has been requested */ int rvalid; /* IO-portregion has been requested */
int leased; /* Flag: This Adapter is connected */ int leased; /* Flag: This Adapter is connected */
/* to a leased line */ /* to a leased line */
unsigned short flags; /* Statusflags */ unsigned short flags; /* Statusflags */
int doubleS0; /* Flag: ICN4B */ int doubleS0; /* Flag: ICN4B */
int secondhalf; /* Flag: Second half of a doubleS0 */ int secondhalf; /* Flag: Second half of a doubleS0 */
int fw_rev; /* Firmware revision loaded */ int fw_rev; /* Firmware revision loaded */
int ptype; /* Protocol type (1TR6 or Euro) */ int ptype; /* Protocol type (1TR6 or Euro) */
struct timer_list st_timer; /* Timer for Status-Polls */ struct timer_list st_timer; /* Timer for Status-Polls */
struct timer_list rb_timer; /* Timer for B-Channel-Polls */ struct timer_list rb_timer; /* Timer for B-Channel-Polls */
u_char rcvbuf[ICN_BCH][4096]; /* B-Channel-Receive-Buffers */ u_char rcvbuf[ICN_BCH][4096]; /* B-Channel-Receive-Buffers */
int rcvidx[ICN_BCH]; /* Index for above buffers */ int rcvidx[ICN_BCH]; /* Index for above buffers */
int l2_proto[ICN_BCH]; /* Current layer-2-protocol */ int l2_proto[ICN_BCH]; /* Current layer-2-protocol */
isdn_if interface; /* Interface to upper layer */ isdn_if interface; /* Interface to upper layer */
...@@ -162,18 +162,18 @@ typedef struct icn_card { ...@@ -162,18 +162,18 @@ typedef struct icn_card {
char *msg_buf_end; /* Pointer to end of statusbuffer */ char *msg_buf_end; /* Pointer to end of statusbuffer */
int sndcount[ICN_BCH]; /* Byte-counters for B-Ch.-send */ int sndcount[ICN_BCH]; /* Byte-counters for B-Ch.-send */
int xlen[ICN_BCH]; /* Byte-counters/Flags for sent-ACK */ int xlen[ICN_BCH]; /* Byte-counters/Flags for sent-ACK */
struct sk_buff *xskb[ICN_BCH]; struct sk_buff *xskb[ICN_BCH]; /* Current transmitted skb */
/* Current transmitted skb */ struct sk_buff_head spqueue[ICN_BCH]; /* Sendqueue */
struct sk_buff_head
spqueue[ICN_BCH]; /* Sendqueue */
char regname[35]; /* Name used for request_region */ char regname[35]; /* Name used for request_region */
u_char xmit_lock[ICN_BCH]; /* Semaphore for pollbchan_send() */ u_char xmit_lock[ICN_BCH]; /* Semaphore for pollbchan_send()*/
spinlock_t lock; /* protect critical operations */
} icn_card; } icn_card;
/* /*
* Main driver data * Main driver data
*/ */
typedef struct icn_dev { typedef struct icn_dev {
spinlock_t devlock; /* spinlock to protect this struct */
unsigned long memaddr; /* Address of memory mapped buffers */ unsigned long memaddr; /* Address of memory mapped buffers */
icn_shmem *shmem; /* Pointer to memory-mapped-buffers */ icn_shmem *shmem; /* Pointer to memory-mapped-buffers */
int mvalid; /* IO-shmem has been requested */ int mvalid; /* IO-shmem has been requested */
......
...@@ -94,48 +94,48 @@ ...@@ -94,48 +94,48 @@
#define ISDN_CMSGLEN 50 /* Length of CONNECT-Message to add for Modem */ #define ISDN_CMSGLEN 50 /* Length of CONNECT-Message to add for Modem */
#define ISDN_MSNLEN 32 #define ISDN_MSNLEN 32
#define NET_DV 0x06 /* Data version for isdn_net_ioctl_cfg */ #define NET_DV 0x06 /* Data version for isdn_net_ioctl_cfg */
#define TTY_DV 0x06 /* Data version for iprofd etc. */ #define TTY_DV 0x06 /* Data version for iprofd etc. */
#define INF_DV 0x01 /* Data version for /dev/isdninfo */ #define INF_DV 0x01 /* Data version for /dev/isdninfo */
typedef struct { typedef struct {
char drvid[25]; char drvid[25];
unsigned long arg; unsigned long arg;
} isdn_ioctl_struct; } isdn_ioctl_struct;
typedef struct { typedef struct {
char name[10]; char name[10];
char phone[ISDN_MSNLEN]; char phone[ISDN_MSNLEN];
int outgoing; int outgoing;
} isdn_net_ioctl_phone; } isdn_net_ioctl_phone;
typedef struct { typedef struct {
char name[10]; /* Name of interface */ char name[10]; /* Name of interface */
char master[10]; /* Name of Master for Bundling */ char master[10]; /* Name of Master for Bundling */
char slave[10]; /* Name of Slave for Bundling */ char slave[10]; /* Name of Slave for Bundling */
char eaz[256]; /* EAZ/MSN */ char eaz[256]; /* EAZ/MSN */
char drvid[25]; /* DriverId for Bindings */ char drvid[25]; /* DriverId for Bindings */
int onhtime; /* Hangup-Timeout */ int onhtime; /* Hangup-Timeout */
int charge; /* Charge-Units */ int charge; /* Charge-Units */
int l2_proto; /* Layer-2 protocol */ int l2_proto; /* Layer-2 protocol */
int l3_proto; /* Layer-3 protocol */ int l3_proto; /* Layer-3 protocol */
int p_encap; /* Encapsulation */ int p_encap; /* Encapsulation */
int exclusive; /* Channel, if bound exclusive */ int exclusive; /* Channel, if bound exclusive */
int dialmax; /* Dial Retry-Counter */ int dialmax; /* Dial Retry-Counter */
int slavedelay; /* Delay until slave starts up */ int slavedelay; /* Delay until slave starts up */
int cbdelay; /* Delay before Callback */ int cbdelay; /* Delay before Callback */
int chargehup; /* Flag: Charge-Hangup */ int chargehup; /* Flag: Charge-Hangup */
int ihup; /* Flag: Hangup-Timeout on incoming line */ int ihup; /* Flag: Hangup-Timeout on incoming line */
int secure; /* Flag: Secure */ int secure; /* Flag: Secure */
int callback; /* Flag: Callback */ int callback; /* Flag: Callback */
int cbhup; /* Flag: Reject Call before Callback */ int cbhup; /* Flag: Reject Call before Callback */
int pppbind; /* ippp device for bindings */ int pppbind; /* ippp device for bindings */
int chargeint; /* Use fixed charge interval length */ int chargeint; /* Use fixed charge interval length */
int triggercps; /* BogoCPS needed for triggering slave */ int triggercps; /* BogoCPS needed for triggering slave */
int dialtimeout; /* Dial-Timeout */ int dialtimeout; /* Dial-Timeout */
int dialwait; /* Time to wait after failed dial */ int dialwait; /* Time to wait after failed dial */
int dialmode; /* Flag: off / on / auto */ int dialmode; /* Flag: off / on / auto */
} isdn_net_ioctl_cfg; } isdn_net_ioctl_cfg;
#define ISDN_NET_DIALMODE_MASK 0xC0 /* bits for status */ #define ISDN_NET_DIALMODE_MASK 0xC0 /* bits for status */
...@@ -385,24 +385,22 @@ typedef struct { ...@@ -385,24 +385,22 @@ typedef struct {
} infostruct; } infostruct;
/* Main driver-data */ /* Main driver-data */
typedef struct isdn_devt { typedef struct _isdn_dev_t {
unsigned short flags; /* Bitmapped Flags: */ unsigned short flags; /* Bitmapped Flags: */
/* */ int channels; /* Current number of channels */
int channels; /* Current number of channels */ int net_verbose; /* Verbose-Flag */
int net_verbose; /* Verbose-Flag */ int modempoll; /* Flag: tty-read active */
int modempoll; /* Flag: tty-read active */ int tflags; /* Timer-Flags: */
int tflags; /* Timer-Flags: */ /* see ISDN_TIMER_..defines */
/* see ISDN_TIMER_..defines */ int global_flags;
int global_flags; infostruct *infochain; /* List of open info-devs. */
infostruct *infochain; /* List of open info-devs. */ wait_queue_head_t info_waitq; /* Wait-Queue for isdninfo */
wait_queue_head_t info_waitq; /* Wait-Queue for isdninfo */ struct task_struct *profd; /* For iprofd */
struct task_struct *profd; /* For iprofd */ struct semaphore sem; /* serialize list access*/
struct semaphore sem; /* serialize list access*/ unsigned long global_features;
unsigned long global_features; } isdn_dev_t;
} isdn_dev;
extern isdn_dev_t *get_isdn_dev(void);
extern isdn_dev *dev;
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment