summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKai Germaschewski <kai@tp1.ruhr-uni-bochum.de>2002-10-29 08:37:35 -0600
committerKai Germaschewski <kai@tp1.ruhr-uni-bochum.de>2002-10-29 08:37:35 -0600
commit98659955cb525e3aa12de9604ea57667446a0461 (patch)
tree73eb5312452cababc0eaf25d5c9e1670d0411b29
parent96d1d0390e22e154f54336f8a9ac17c135cec619 (diff)
ISDN: Use a spinlock to protect the list of drivers
... and move up the function register_isdn().
-rw-r--r--drivers/isdn/i4l/isdn_common.c132
1 files changed, 74 insertions, 58 deletions
diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c
index f42497d38fbc..72f54e837ef3 100644
--- a/drivers/isdn/i4l/isdn_common.c
+++ b/drivers/isdn/i4l/isdn_common.c
@@ -75,7 +75,8 @@ struct isdn_driver {
struct fsm_inst fi;
} driver;
-struct isdn_driver *drivers[ISDN_MAX_DRIVERS];
+static spinlock_t drivers_lock = SPIN_LOCK_UNLOCKED;
+static struct isdn_driver *drivers[ISDN_MAX_DRIVERS];
int
isdn_drv_queue_empty(int di, int ch)
@@ -108,7 +109,78 @@ isdn_drv_hdrlen(int di)
return drivers[di]->interface->hl_hdrlen;
}
-static int isdn_add_channels(struct isdn_driver *, int, int, int);
+static int isdn_add_channels(struct isdn_driver *, int, int, int);
+static void isdn_receive_skb_callback(int di, int ch, struct sk_buff *skb);
+static int isdn_status_callback(isdn_ctrl * c);
+static void set_global_features(void);
+
+/*
+ * Register a new ISDN interface
+ */
+
+int
+register_isdn(isdn_if *iif)
+{
+ struct isdn_driver *drv;
+ unsigned long flags;
+ int drvidx;
+
+ if (dev->drivers >= ISDN_MAX_DRIVERS) {
+ printk(KERN_WARNING "register_isdn: Max. %d drivers supported\n",
+ ISDN_MAX_DRIVERS);
+ goto fail;
+ }
+
+ drv = kmalloc(sizeof(*drv), GFP_KERNEL);
+ if (!drv) {
+ printk(KERN_WARNING "register_isdn: out of mem\n");
+ goto fail;
+ }
+ memset(drv, 0, sizeof(*drv));
+
+ drv->maxbufsize = iif->maxbufsize;
+ drv->stavail = 0;
+ drv->flags = DRV_FLAG_LOADED;
+ drv->online = 0;
+ drv->interface = iif;
+ drv->channels = 0;
+
+ spin_lock_irqsave(&drivers_lock, flags);
+ for (drvidx = 0; drvidx < ISDN_MAX_DRIVERS; drvidx++)
+ if (!drivers[drvidx])
+ break;
+
+ if (!strlen(iif->id))
+ sprintf(iif->id, "line%d", drvidx);
+
+ strcpy(dev->drvid[drvidx], iif->id);
+
+ for (drvidx = 0; drvidx < ISDN_MAX_DRIVERS; drvidx++)
+ if (strcmp(iif->id, dev->drvid[drvidx]) == 0)
+ goto fail_unlock;
+
+ if (isdn_add_channels(drv, drvidx, iif->channels, 0))
+ goto fail_unlock;
+
+ drivers[drvidx] = drv;
+ spin_unlock_irqrestore(&drivers_lock, flags);
+
+ iif->channels = drvidx;
+ iif->rcvcallb_skb = isdn_receive_skb_callback;
+ iif->statcallb = isdn_status_callback;
+
+ isdn_info_update();
+ dev->drivers++;
+ set_global_features();
+
+ return 1;
+
+ fail_unlock:
+ spin_unlock_irqrestore(&drivers_lock, flags);
+ kfree(drv);
+ fail:
+ return 0;
+}
/* ====================================================================== */
@@ -120,7 +192,6 @@ static isdn_divert_if *divert_if; /* = NULL */
spinlock_t stat_lock = SPIN_LOCK_UNLOCKED;
-static void set_global_features(void);
static void isdn_register_devfs(int);
static void isdn_unregister_devfs(int);
static int isdn_wildmat(char *s, char *p);
@@ -1871,61 +1942,6 @@ EXPORT_SYMBOL(isdn_ppp_unregister_compressor);
#endif
int
-register_isdn(isdn_if * i)
-{
- struct isdn_driver *d;
- int j;
- ulong flags;
- int drvidx;
-
- if (dev->drivers >= ISDN_MAX_DRIVERS) {
- printk(KERN_WARNING "register_isdn: Max. %d drivers supported\n",
- ISDN_MAX_DRIVERS);
- return 0;
- }
- if (!i->writebuf_skb) {
- printk(KERN_WARNING "register_isdn: No write routine given.\n");
- return 0;
- }
- if (!(d = kmalloc(sizeof(driver), GFP_KERNEL))) {
- printk(KERN_WARNING "register_isdn: Could not alloc driver-struct\n");
- return 0;
- }
- memset((char *) d, 0, sizeof(driver));
-
- d->maxbufsize = i->maxbufsize;
- d->stavail = 0;
- d->flags = DRV_FLAG_LOADED;
- d->online = 0;
- d->interface = i;
- d->channels = 0;
- for (drvidx = 0; drvidx < ISDN_MAX_DRIVERS; drvidx++)
- if (!drivers[drvidx])
- break;
- if (isdn_add_channels(d, drvidx, i->channels, 0)) {
- kfree(d);
- return 0;
- }
- i->channels = drvidx;
- i->rcvcallb_skb = isdn_receive_skb_callback;
- i->statcallb = isdn_status_callback;
- if (!strlen(i->id))
- sprintf(i->id, "line%d", drvidx);
- save_flags(flags);
- cli();
- for (j = 0; j < drvidx; j++)
- if (!strcmp(i->id, dev->drvid[j]))
- sprintf(i->id, "line%d", drvidx);
- drivers[drvidx] = d;
- strcpy(dev->drvid[drvidx], i->id);
- isdn_info_update();
- dev->drivers++;
- set_global_features();
- restore_flags(flags);
- return 1;
-}
-
-int
isdn_slot_driver(int sl)
{
BUG_ON(sl < 0);