From b4b11683141ceb7fb21faa7a75111fc2488f2b64 Mon Sep 17 00:00:00 2001 From: Shaun Ruffell Date: Mon, 10 Nov 2008 19:48:22 +0000 Subject: - Do not hold any locks while calling close_channel, which can result in calls to the echocan modules which do not necesarrily assume they are being called in atomic context. - Remove the bigzaplock around calls to psuedo_alloc and pseudo_free. The structures protected by this lock are already protected by the chan_lock in these two cases. - Remove calls to in_atomic() that were previously added to work around this, but did not cover all the cases. Issue: DAHDI-195, DAHDI-170 git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@5275 a0bf4364-ded3-4de4-8d8a-66a801d63aff --- drivers/dahdi/dahdi-base.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) (limited to 'drivers/dahdi/dahdi-base.c') diff --git a/drivers/dahdi/dahdi-base.c b/drivers/dahdi/dahdi-base.c index 644ca0e..7d2b9c3 100644 --- a/drivers/dahdi/dahdi-base.c +++ b/drivers/dahdi/dahdi-base.c @@ -48,7 +48,6 @@ #include #include #include -#include #ifdef CONFIG_DAHDI_NET #include @@ -868,7 +867,7 @@ static int dahdi_reallocbufs(struct dahdi_chan *ss, int j, int numbufs) /* We need to allocate our buffers now */ if (j) { - if(!(newbuf = kcalloc(j * 2, numbufs, (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL))) + if (!(newbuf = kcalloc(j * 2, numbufs, GFP_KERNEL))) return -ENOMEM; } else newbuf = NULL; @@ -1149,6 +1148,8 @@ static void close_channel(struct dahdi_chan *chan) struct ppp_channel *ppp; #endif + might_sleep(); + /* XXX Buffers should be send out before reallocation!!! XXX */ if (!(chan->flags & DAHDI_FLAG_NOSTDTXRX)) dahdi_reallocbufs(chan, 0, 0); @@ -1455,6 +1456,8 @@ static int dahdi_chan_reg(struct dahdi_chan *chan) int res = 0; unsigned long flags; + might_sleep(); + write_lock_irqsave(&chan_lock, flags); for (x = 1; x < DAHDI_MAX_CHANNELS; x++) { if (chans[x]) @@ -1471,6 +1474,7 @@ static int dahdi_chan_reg(struct dahdi_chan *chan) chan->readchunk = chan->sreadchunk; if (!chan->writechunk) chan->writechunk = chan->swritechunk; + write_unlock_irqrestore(&chan_lock, flags); dahdi_set_law(chan, 0); close_channel(chan); /* set this AFTER running close_channel() so that @@ -1479,10 +1483,11 @@ static int dahdi_chan_reg(struct dahdi_chan *chan) res = 0; break; } - write_unlock_irqrestore(&chan_lock, flags); - if (x == DAHDI_MAX_CHANNELS) + if (DAHDI_MAX_CHANNELS == x) { + write_unlock_irqrestore(&chan_lock, flags); module_printk(KERN_ERR, "No more channels available\n"); + } return res; } @@ -1835,6 +1840,9 @@ static void dahdi_chan_unreg(struct dahdi_chan *chan) { int x; unsigned long flags; + + might_sleep(); + #ifdef CONFIG_DAHDI_NET if (chan->flags & DAHDI_FLAG_NETDEV) { unregister_hdlc_device(chan->hdlcnetdev->netdev); @@ -2600,7 +2608,6 @@ static int dahdi_specchan_release(struct inode *node, struct file *file, int uni static struct dahdi_chan *dahdi_alloc_pseudo(void) { struct dahdi_chan *pseudo; - unsigned long flags; /* Don't allow /dev/dahdi/pseudo to open if there are no spans */ if (maxspans < 1) @@ -2613,24 +2620,20 @@ static struct dahdi_chan *dahdi_alloc_pseudo(void) pseudo->sigcap = DAHDI_SIG_CLEAR; pseudo->flags = DAHDI_FLAG_PSEUDO | DAHDI_FLAG_AUDIO; - spin_lock_irqsave(&bigzaplock, flags); if (dahdi_chan_reg(pseudo)) { kfree(pseudo); pseudo = NULL; - } else - sprintf(pseudo->name, "Pseudo/%d", pseudo->channo); - spin_unlock_irqrestore(&bigzaplock, flags); + } else { + sprintf(pseudo->name, "Pseudo/%d", pseudo->channo); + } return pseudo; } static void dahdi_free_pseudo(struct dahdi_chan *pseudo) { - unsigned long flags; if (pseudo) { - spin_lock_irqsave(&bigzaplock, flags); dahdi_chan_unreg(pseudo); - spin_unlock_irqrestore(&bigzaplock, flags); kfree(pseudo); } } -- cgit v1.2.3