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