summaryrefslogtreecommitdiff
path: root/zaptel-base.c
diff options
context:
space:
mode:
authorsruffell <sruffell@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2008-01-23 23:02:05 +0000
committersruffell <sruffell@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2008-01-23 23:02:05 +0000
commitd8e4f2d9d55628bdc758ffcdcf4321883770a721 (patch)
treeab921e9bb6ef6dddc899e889e33cbd076d55ffc9 /zaptel-base.c
parent0a35ebf3e85a47802f2c49bfc932e53d1c17518f (diff)
Ensure that the zone lock is always acquired before the channel lock.
(issue #7620) git-svn-id: http://svn.digium.com/svn/zaptel/branches/1.2@3733 5390a7c7-147a-4af0-8ec9-7488f05a26cb
Diffstat (limited to 'zaptel-base.c')
-rw-r--r--zaptel-base.c9
1 files changed, 5 insertions, 4 deletions
diff --git a/zaptel-base.c b/zaptel-base.c
index 86cddbf..90d27da 100644
--- a/zaptel-base.c
+++ b/zaptel-base.c
@@ -1131,8 +1131,9 @@ static int start_tone(struct zt_chan *chan, int tone)
static int set_tone_zone(struct zt_chan *chan, int zone)
{
+ unsigned long flags;
int res=0;
- /* Assumes channel is already locked */
+ /* Do not call with the channel locked. */
if ((zone >= ZT_TONE_ZONE_MAX) || (zone < -1))
return -EINVAL;
@@ -1142,9 +1143,11 @@ static int set_tone_zone(struct zt_chan *chan, int zone)
zone = default_zone;
}
if (tone_zones[zone]) {
+ spin_lock_irqsave(&chan->lock, flags);
chan->curzone = tone_zones[zone];
chan->tonezone = zone;
memcpy(chan->ringcadence, chan->curzone->ringcadence, sizeof(chan->ringcadence));
+ spin_unlock_irqrestore(&chan->lock, flags);
} else {
res = -ENODATA;
}
@@ -2157,7 +2160,6 @@ static int initialize_channel(struct zt_chan *chan)
chan->curtone = NULL;
chan->tonep = 0;
chan->pdialcount = 0;
- set_tone_zone(chan, -1);
if (chan->gainalloc && chan->rxgain)
rxgain = chan->rxgain;
chan->rxgain = defgain;
@@ -2186,6 +2188,7 @@ static int initialize_channel(struct zt_chan *chan)
}
spin_unlock_irqrestore(&chan->lock, flags);
+ set_tone_zone(chan, -1);
if (chan->span && chan->span->echocan)
chan->span->echocan(chan, 0);
@@ -3762,9 +3765,7 @@ static int zt_chanandpseudo_ioctl(struct inode *inode, struct file *file, unsign
break;
case ZT_SETTONEZONE:
get_user(j,(int *)data);
- spin_lock_irqsave(&chan->lock, flags);
rv = set_tone_zone(chan, j);
- spin_unlock_irqrestore(&chan->lock, flags);
return rv;
case ZT_GETTONEZONE:
spin_lock_irqsave(&chan->lock, flags);