summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShaun Ruffell <sruffell@digium.com>2011-01-06 21:34:10 +0000
committerShaun Ruffell <sruffell@digium.com>2011-01-06 21:34:10 +0000
commitebd396872801f4998d413872716d743dee9cd9fe (patch)
tree7a8580dc8df0013536dd37da2e27c7aef9d1b292
parenta8c1e348c5544d1ca1e3d8019b94774cf0a9b29b (diff)
dahdi: Do not call dahdi_check_conf under lock.
dahdi_check_conf() acqurires the locks as needed when scanning the channels and should not be called under any spinlocks. Fixes a regression that Tzafrir reported in #asterisk-dev that he could trigger via "asterisk -rx 'channel originate Local/600@demo Application Meetme 3000,d'" Signed-off-by: Shaun Ruffell <sruffell@digium.com> Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com> git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@9621 a0bf4364-ded3-4de4-8d8a-66a801d63aff
-rw-r--r--drivers/dahdi/dahdi-base.c14
1 files changed, 8 insertions, 6 deletions
diff --git a/drivers/dahdi/dahdi-base.c b/drivers/dahdi/dahdi-base.c
index 8c32f7c..0564fd8 100644
--- a/drivers/dahdi/dahdi-base.c
+++ b/drivers/dahdi/dahdi-base.c
@@ -1493,8 +1493,6 @@ static void close_channel(struct dahdi_chan *chan)
chan->dacs_chan = NULL;
chan->confmute = 0;
- /* release conference resource, if any to release */
- if (oldconf) dahdi_check_conf(oldconf);
chan->gotgs = 0;
reset_conf(chan);
chan->dacs_chan = NULL;
@@ -1523,6 +1521,10 @@ static void close_channel(struct dahdi_chan *chan)
spin_unlock_irqrestore(&chan->lock, flags);
+ /* release conference resource, if any to release */
+ if (oldconf)
+ dahdi_check_conf(oldconf);
+
if (rxgain)
kfree(rxgain);
if (readchunkpreec)
@@ -5141,7 +5143,7 @@ static int dahdi_ioctl_setconf(struct file *file, unsigned long data)
struct dahdi_chan *conf_chan = NULL;
unsigned long flags;
unsigned int confmode;
- int j;
+ int oldconf;
if (copy_from_user(&conf, (void __user *)data, sizeof(conf)))
return -EFAULT;
@@ -5173,6 +5175,7 @@ static int dahdi_ioctl_setconf(struct file *file, unsigned long data)
/* likewise if 0 mode must have no conf */
if ((!conf.confmode) && conf.confno)
return -EINVAL;
+ dahdi_check_conf(conf.confno);
conf.chan = chan->channo; /* return with real channel # */
spin_lock_irqsave(&chan_lock, flags);
spin_lock(&chan->lock);
@@ -5190,13 +5193,11 @@ static int dahdi_ioctl_setconf(struct file *file, unsigned long data)
memset(chan->conflast1, 0, DAHDI_MAX_CHUNKSIZE);
memset(chan->conflast2, 0, DAHDI_MAX_CHUNKSIZE);
}
- j = chan->confna; /* save old conference number */
+ oldconf = chan->confna; /* save old conference number */
chan->confna = conf.confno; /* set conference number */
chan->conf_chan = conf_chan;
chan->confmode = conf.confmode; /* set conference mode */
chan->_confn = 0; /* Clear confn */
- dahdi_check_conf(j);
- dahdi_check_conf(conf.confno);
if (chan->span && chan->span->ops->dacs) {
if ((confmode == DAHDI_CONF_DIGITALMON) &&
(chan->txgain == defgain) &&
@@ -5234,6 +5235,7 @@ static int dahdi_ioctl_setconf(struct file *file, unsigned long data)
spin_unlock(&chan->lock);
spin_unlock_irqrestore(&chan_lock, flags);
+ dahdi_check_conf(oldconf);
if (copy_to_user((void __user *)data, &conf, sizeof(conf)))
return -EFAULT;
return 0;