]> git.hungrycats.org Git - linux/commitdiff
[PATCH] next fixes
authorKarsten Keil <kkeil@suse.de>
Sun, 7 Sep 2003 06:54:07 +0000 (23:54 -0700)
committerLinus Torvalds <torvalds@home.osdl.org>
Sun, 7 Sep 2003 06:54:07 +0000 (23:54 -0700)
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
drivers/isdn/capi/capidrv.c
drivers/isdn/capi/kcapi.c
drivers/isdn/hardware/avm/c4.c
drivers/isdn/i4l/isdn_audio.c
drivers/isdn/i4l/isdn_common.c
drivers/isdn/i4l/isdn_net_lib.c
drivers/isdn/i4l/isdn_tty.c
drivers/isdn/icn/icn.c
drivers/isdn/icn/icn.h
include/linux/isdn.h

index 8404fefda237c884423e30a8abf7d39a3846c9c0..95ab10c2900afa5f2380ea10bc66ff44440690e1 100644 (file)
@@ -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");
index cdd1b90334cecc79116afb578cc34b8ef0bec3ff..97f04687bcd4e3fae97c584a21c3fc1dcc8ea566 100644 (file)
@@ -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);
index b78f7b1dc0215149d82be989b6b18fa99ece9d9d..b8c94f374f6dee1def656953fc6d0afdf59a9d4d 100644 (file)
@@ -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 ------------------------------------------ */
index c4817536e324c7c1625c24342c2a2c0d98ec256d..4abccbdcea069e0a50f8aa20f223f754b9b8a585 100644 (file)
@@ -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:
index 5c9fc1ad38fb95d09ddf670ba3470ff33f887a09..f23d82560d78e713961e2f710bd529a086666bdd 100644 (file)
@@ -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);
 }
 
index 3de5bef85bdd0c8f9771f93effde4ba7a8cd2f58..a31e2aa769530c2f134a3593329a61dcb5bd9153 100644 (file)
@@ -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);
 }
index 6acdd8ca0dc18ba25899c7bc7e6e2b314a8ed52e..c18e6f93fb3c98db6aa7b83dd49e71e2f21cbade 100644 (file)
@@ -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) {
index 389fbffc32895f9a67e4ed0676224c2f914a80e3..996e8c5a9612de15899820aff6c460b2df93c7e8 100644 (file)
@@ -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
index 925db4617f64ce7d905f81889385da850f527e88..b715a91f3dbfc46a95bad69c275558f8f1be5441 100644 (file)
@@ -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;
index a8bbc45867d869dbdf07447de3907ab734aa74e0..4ab15c917ed487020ee93a069af885d9047dbe69 100644 (file)
@@ -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      */
index 35a2ef6e2452123a40adfd08c6ff01d35d36f016..a704d7b489b040dd9554ccb17bb77d3b709cb011 100644 (file)
 #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__ */