summaryrefslogtreecommitdiff
path: root/zaptel.c
diff options
context:
space:
mode:
authormarkster <markster@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2004-02-08 17:22:20 +0000
committermarkster <markster@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2004-02-08 17:22:20 +0000
commit13c3ab4e0f3d5b022ed9598bcf7320b75c3f7a02 (patch)
tree64b002b221be66c840eca2b648a12bdd5aa767fa /zaptel.c
parent130d038b151d1f72885d72fc73118f1d0daa9223 (diff)
Remove "zapfreelock" and replace with "bigzaplock" and make sure we're not performing interrupt routines that effect multiple channels at the same time that other things can be going on.
git-svn-id: http://svn.digium.com/svn/zaptel/trunk@311 5390a7c7-147a-4af0-8ec9-7488f05a26cb
Diffstat (limited to 'zaptel.c')
-rwxr-xr-xzaptel.c77
1 files changed, 41 insertions, 36 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;