dahdi: dahdi_chan.ec_factory can be protected with the mutex.

This is never accessed or modified in interrupt context. This closes a potential
race if the echocan is being changed on a channel while enabling disabling is
hapening on another thread.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
This commit is contained in:
Shaun Ruffell 2014-06-19 16:45:41 -05:00 committed by Russ Meyerriecks
parent 761e02da52
commit a3578ca156

View File

@ -991,10 +991,13 @@ static int dahdi_seq_show(struct seq_file *sfile, void *data)
seq_fill_alarm_string(sfile, chan->chan_alarms); seq_fill_alarm_string(sfile, chan->chan_alarms);
if (chan->ec_factory) mutex_lock(&chan->mutex);
if (chan->ec_factory) {
seq_printf(sfile, "(EC: %s - %s) ", seq_printf(sfile, "(EC: %s - %s) ",
chan->ec_factory->get_name(chan), chan->ec_factory->get_name(chan),
chan->ec_state ? "ACTIVE" : "INACTIVE"); chan->ec_state ? "ACTIVE" : "INACTIVE");
}
mutex_unlock(&chan->mutex);
seq_printf(sfile, "\n"); seq_printf(sfile, "\n");
} }
@ -1489,14 +1492,13 @@ static const struct dahdi_echocan_factory hwec_factory = {
static int dahdi_enable_hw_preechocan(struct dahdi_chan *chan) static int dahdi_enable_hw_preechocan(struct dahdi_chan *chan)
{ {
int res; int res;
unsigned long flags;
spin_lock_irqsave(&chan->lock, flags); mutex_lock(&chan->mutex);
if (chan->ec_factory != &hwec_factory) if (chan->ec_factory != &hwec_factory)
res = -ENODEV; res = -ENODEV;
else else
res = 0; res = 0;
spin_unlock_irqrestore(&chan->lock, flags); mutex_unlock(&chan->mutex);
if (-ENODEV == res) if (-ENODEV == res)
return 0; return 0;
@ -2303,10 +2305,10 @@ static void dahdi_chan_unreg(struct dahdi_chan *chan)
*/ */
} }
spin_lock_irqsave(&chan->lock, flags); mutex_lock(&chan->mutex);
release_echocan(chan->ec_factory); release_echocan(chan->ec_factory);
chan->ec_factory = NULL; chan->ec_factory = NULL;
spin_unlock_irqrestore(&chan->lock, flags); mutex_unlock(&chan->mutex);
#ifdef CONFIG_DAHDI_NET #ifdef CONFIG_DAHDI_NET
if (dahdi_have_netdev(chan)) { if (dahdi_have_netdev(chan)) {
@ -5227,7 +5229,6 @@ static bool dahdi_is_hwec_available(const struct dahdi_chan *chan)
static int dahdi_ioctl_attach_echocan(unsigned long data) static int dahdi_ioctl_attach_echocan(unsigned long data)
{ {
unsigned long flags;
struct dahdi_chan *chan; struct dahdi_chan *chan;
struct dahdi_attach_echocan ae; struct dahdi_attach_echocan ae;
const struct dahdi_echocan_factory *new = NULL, *old; const struct dahdi_echocan_factory *new = NULL, *old;
@ -5269,10 +5270,10 @@ static int dahdi_ioctl_attach_echocan(unsigned long data)
} }
} }
spin_lock_irqsave(&chan->lock, flags); mutex_lock(&chan->mutex);
old = chan->ec_factory; old = chan->ec_factory;
chan->ec_factory = new; chan->ec_factory = new;
spin_unlock_irqrestore(&chan->lock, flags); mutex_unlock(&chan->mutex);
if (old) if (old)
release_echocan(old); release_echocan(old);