summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xzaptel.c77
-rwxr-xr-xzaptel.h1
2 files changed, 41 insertions, 37 deletions
diff --git a/zaptel.c b/zaptel.c
index f1497c5..9f2f359 100755
--- a/zaptel.c
+++ b/zaptel.c
@@ -296,9 +296,7 @@ static struct zt_timer {
static spinlock_t zaptimerlock = SPIN_LOCK_UNLOCKED;
-static spinlock_t zapfreelock = SPIN_LOCK_UNLOCKED;
-
-static int zapneedfree = 0;
+static spinlock_t bigzaplock = SPIN_LOCK_UNLOCKED;
struct zt_zone {
char name[40]; /* Informational, only */
@@ -2069,8 +2067,6 @@ static int zt_specchan_open(struct inode *inode, struct file *file, int unit, in
/* Make sure we're not already open, a net device, or a slave device */
if (chans[unit]->flags & ZT_FLAG_OPEN)
res = -EBUSY;
- else if (chans[unit]->flags & ZT_FLAG_DEAD)
- res = -EBUSY;
else if (chans[unit]->flags & ZT_FLAG_NETDEV)
res = -EBUSY;
else if (chans[unit]->master != chans[unit])
@@ -2138,7 +2134,7 @@ static struct zt_chan *zt_alloc_pseudo(void)
return pseudo;
}
-static void __zt_free_pseudo(struct zt_chan *pseudo)
+static void zt_free_pseudo(struct zt_chan *pseudo)
{
if (pseudo) {
zt_chan_unreg(pseudo);
@@ -2146,19 +2142,7 @@ static void __zt_free_pseudo(struct zt_chan *pseudo)
}
}
-static void zt_free_pseudo(struct zt_chan *pseudo)
-{
- long flags;
- if (pseudo) {
- /* Mark as dead for later reaping */
- pseudo->flags |= ZT_FLAG_DEAD;
- spin_lock_irqsave(&zapfreelock, flags);
- zapneedfree = 1;
- spin_unlock_irqrestore(&zapfreelock, flags);
- }
-}
-
-static int zt_open(struct inode *inode, struct file *file)
+static int __zt_open(struct inode *inode, struct file *file)
{
int unit = UNIT(file);
struct zt_chan *chan;
@@ -2189,6 +2173,16 @@ static int zt_open(struct inode *inode, struct file *file)
return zt_specchan_open(inode, file, unit, 1);
}
+static int zt_open(struct inode *inode, struct file *file)
+{
+ int res;
+ unsigned long flags;
+ spin_lock_irqsave(&bigzaplock, flags);
+ res = __zt_open(inode, file);
+ spin_unlock_irqrestore(&bigzaplock, flags);
+ return res;
+}
+
static ssize_t zt_read(struct file *file, char *usrbuf, size_t count, loff_t *ppos)
{
int unit = UNIT(file);
@@ -2443,7 +2437,7 @@ static void __do_dtmf(struct zt_chan *chan)
__qevent(chan, ZT_EVENT_DIALCOMPLETE);
}
-static int zt_release(struct inode *inode, struct file *file)
+static int __zt_release(struct inode *inode, struct file *file)
{
int unit = UNIT(file);
int res;
@@ -2475,6 +2469,17 @@ static int zt_release(struct inode *inode, struct file *file)
return zt_specchan_release(inode, file, unit);
}
+static int zt_release(struct inode *inode, struct file *file)
+{
+ /* Lock the big zap lock when handling a release */
+ unsigned long flags;
+ int res;
+ spin_lock_irqsave(&bigzaplock, flags);
+ res = __zt_release(inode, file);
+ spin_unlock_irqrestore(&bigzaplock, flags);
+ return res;
+}
+
void zt_alarm_notify(struct zt_span *span)
{
int j;
@@ -3157,7 +3162,7 @@ static int zt_chanandpseudo_ioctl(struct inode *inode, struct file *file, unsign
struct zt_bufferinfo bi;
struct zt_confinfo conf;
struct zt_ring_cadence cad;
- unsigned long flags;
+ unsigned long flags, flagso;
int i, j, k, rv;
int ret, c;
@@ -3363,8 +3368,10 @@ static int zt_chanandpseudo_ioctl(struct inode *inode, struct file *file, unsign
break;
case ZT_CONFMUTE: /* set confmute flag */
if (!(chan->flags & ZT_FLAG_AUDIO)) return (-EINVAL);
+ spin_lock_irqsave(&bigzaplock, flags);
get_user(j,(int *)data); /* get conf # */
chan->confmute = j;
+ spin_unlock_irqrestore(&bigzaplock, flags);
break;
case ZT_GETCONFMUTE: /* get confmute flag */
if (!(chan->flags & ZT_FLAG_AUDIO)) return (-EINVAL);
@@ -3427,12 +3434,14 @@ static int zt_chanandpseudo_ioctl(struct inode *inode, struct file *file, unsign
/* likewise if 0 mode must have no conf */
if ((!conf.confmode) && conf.confno) return (-EINVAL);
conf.chan = i; /* return with real channel # */
+ spin_lock_irqsave(&bigzaplock, flagso);
spin_lock_irqsave(&chan->lock, flags);
if (conf.confno == -1)
conf.confno = zt_first_empty_conference();
if ((conf.confno < 1) && (conf.confmode)) {
/* No more empty conferences */
spin_unlock_irqrestore(&chan->lock, flags);
+ spin_unlock_irqrestore(&bigzaplock, flagso);
return -EBUSY;
}
/* if changing confs, clear last added info */
@@ -3454,8 +3463,9 @@ static int zt_chanandpseudo_ioctl(struct inode *inode, struct file *file, unsign
/* Get alias */
chans[i]->_confn = zt_get_conf_alias(conf.confno);
}
- copy_to_user((struct zt_confinfo *) data,&conf,sizeof(conf));
spin_unlock_irqrestore(&chan->lock, flags);
+ spin_unlock_irqrestore(&bigzaplock, flagso);
+ copy_to_user((struct zt_confinfo *) data,&conf,sizeof(conf));
break;
case ZT_CONFLINK: /* do conf link stuff */
if (!(chan->flags & ZT_FLAG_AUDIO)) return (-EINVAL);
@@ -3465,6 +3475,7 @@ static int zt_chanandpseudo_ioctl(struct inode *inode, struct file *file, unsign
if ((conf.confno < 0) || (conf.confno > ZT_MAX_CONF)) return(-EINVAL);
/* cant listen to self!! */
if (conf.chan && (conf.chan == conf.confno)) return(-EINVAL);
+ spin_lock_irqsave(&bigzaplock, flagso);
spin_lock_irqsave(&chan->lock, flags);
/* if to clear all links */
if ((!conf.chan) && (!conf.confno))
@@ -3473,6 +3484,7 @@ static int zt_chanandpseudo_ioctl(struct inode *inode, struct file *file, unsign
memset(conf_links,0,sizeof(conf_links));
recalc_maxlinks();
spin_unlock_irqrestore(&chan->lock, flags);
+ spin_unlock_irqrestore(&bigzaplock, flagso);
break;
}
rv = 0; /* clear return value */
@@ -3523,6 +3535,7 @@ static int zt_chanandpseudo_ioctl(struct inode *inode, struct file *file, unsign
}
recalc_maxlinks();
spin_unlock_irqrestore(&chan->lock, flags);
+ spin_unlock_irqrestore(&bigzaplock, flagso);
return(rv);
case ZT_CONFDIAG: /* output diagnostic info to console */
if (!(chan->flags & ZT_FLAG_AUDIO)) return (-EINVAL);
@@ -5722,7 +5735,7 @@ int zt_transmit(struct zt_span *span)
int zt_receive(struct zt_span *span)
{
int x,y,z;
- unsigned long flags;
+ unsigned long flags, flagso;
#if 1
#ifdef CONFIG_ZAPTEL_WATCHDOG
@@ -5800,6 +5813,9 @@ int zt_receive(struct zt_span *span)
}
if (span == master) {
+ /* Hold the big zap lock for the duration of major
+ activities which touch all sorts of channels */
+ spin_lock_irqsave(&bigzaplock, flagso);
/* Process any timers */
process_timers();
/* If we have dynamic stuff, call the ioctl with 0,0 parameters to
@@ -5842,7 +5858,7 @@ int zt_receive(struct zt_span *span)
#ifdef CONFIG_ZAPTEL_MMX
kernel_fpu_end();
#endif
- }
+ }
/* do all the pseudo/conferenced channel transmits (putbuf's) */
for (x=1;x<maxchans;x++) {
if (chans[x] && (chans[x]->flags & ZT_FLAG_PSEUDO)) {
@@ -5864,18 +5880,7 @@ int zt_receive(struct zt_span *span)
spin_unlock_irqrestore(&chans[x]->lock, flags);
}
}
- spin_lock_irqsave(&zapfreelock, flags);
- if (zapneedfree) {
- /* Free any pseudos that might need it */
- for (x=0;x<maxchans;x++) {
- if (chans[x] && (chans[x]->flags & ZT_FLAG_DEAD)) {
- __zt_free_pseudo(chans[x]);
- }
- }
- zapneedfree = 0;
- }
- spin_unlock_irqrestore(&zapfreelock, flags);
-
+ spin_unlock_irqrestore(&bigzaplock, flagso);
}
#endif
return 0;
diff --git a/zaptel.h b/zaptel.h
index 04ef153..a45b561 100755
--- a/zaptel.h
+++ b/zaptel.h
@@ -1111,7 +1111,6 @@ typedef enum {
#define ZT_FLAG_LINEAR (1 << 13) /* Talk to user space in linear */
#define ZT_FLAG_PPP (1 << 14) /* PPP is available */
#define ZT_FLAG_T1PPP (1 << 15)
-#define ZT_FLAG_DEAD (1 << 16) /* Dead, needs to be removed */
struct zt_span {
spinlock_t lock;