wctc4xxp: Check for shutdown after acquiring the mutex lock.

In case we missed an alert, this will allow for rapid shutdown of Asterisk.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
This commit is contained in:
Shaun Ruffell 2014-05-02 11:07:56 -05:00 committed by Russ Meyerriecks
parent 7168b87cb5
commit ec9d162344

View File

@ -1658,7 +1658,6 @@ static int wctc4xxp_create_channel_pair(struct wcdte *wc,
struct channel_pvt *cpvt, u8 simple, u8 complicated); struct channel_pvt *cpvt, u8 simple, u8 complicated);
static int wctc4xxp_destroy_channel_pair(struct wcdte *wc, static int wctc4xxp_destroy_channel_pair(struct wcdte *wc,
struct channel_pvt *cpvt); struct channel_pvt *cpvt);
static int __wctc4xxp_setup_channels(struct wcdte *wc);
static void static void
wctc4xxp_init_state(struct channel_pvt *cpvt, int encoder, wctc4xxp_init_state(struct channel_pvt *cpvt, int encoder,
@ -1750,18 +1749,13 @@ do_channel_allocate(struct dahdi_transcoder_channel *dtc)
u8 wctc4xxp_dstfmt; /* Digium Transcoder Engine Dest Format */ u8 wctc4xxp_dstfmt; /* Digium Transcoder Engine Dest Format */
int res; int res;
#ifndef DEBUG_WCTC4XXP
mutex_lock(&wc->chanlock);
#else
if (mutex_lock_interruptible(&wc->chanlock)) if (mutex_lock_interruptible(&wc->chanlock))
return -EINTR; return -EINTR;
#endif
/* Check again to see if the channel was built after grabbing the /* Check again to see if the channel was built after grabbing the
* channel lock, in case the previous holder of the lock * channel lock, in case the previous holder of the lock
* built this channel as a complement to itself. */ * built this channel as a complement to itself. */
if (dahdi_tc_is_built(dtc)) { if (dahdi_tc_is_built(dtc)) {
mutex_unlock(&wc->chanlock);
DTE_DEBUG(DTE_DEBUG_CHANNEL_SETUP, DTE_DEBUG(DTE_DEBUG_CHANNEL_SETUP,
"Allocating channel %p which is already built.\n", dtc); "Allocating channel %p which is already built.\n", dtc);
return 0; return 0;
@ -1779,7 +1773,6 @@ do_channel_allocate(struct dahdi_transcoder_channel *dtc)
wctc4xxp_dstfmt); wctc4xxp_dstfmt);
if (res) { if (res) {
/* There was a problem creating the channel.... */ /* There was a problem creating the channel.... */
mutex_unlock(&wc->chanlock);
dev_err(&wc->pdev->dev, "Failed to create channel pair.\n"); dev_err(&wc->pdev->dev, "Failed to create channel pair.\n");
return res; return res;
} }
@ -1792,7 +1785,6 @@ do_channel_allocate(struct dahdi_transcoder_channel *dtc)
/* Mark the channel complement (other half of encoder/decoder pair) as /* Mark the channel complement (other half of encoder/decoder pair) as
* built */ * built */
wctc4xxp_mark_channel_complement_built(wc, dtc); wctc4xxp_mark_channel_complement_built(wc, dtc);
mutex_unlock(&wc->chanlock);
dahdi_transcoder_alert(dtc); dahdi_transcoder_alert(dtc);
return 0; return 0;
} }
@ -1829,12 +1821,22 @@ wctc4xxp_enable_polling(struct wcdte *wc)
static int static int
wctc4xxp_operation_allocate(struct dahdi_transcoder_channel *dtc) wctc4xxp_operation_allocate(struct dahdi_transcoder_channel *dtc)
{ {
int res;
struct wcdte *wc = ((struct channel_pvt *)(dtc->pvt))->wc; struct wcdte *wc = ((struct channel_pvt *)(dtc->pvt))->wc;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
mutex_lock(&wc->chanlock);
#else
res = mutex_lock_killable(&wc->chanlock);
if (res)
return res;
#endif
if (unlikely(test_bit(DTE_SHUTDOWN, &wc->flags))) { if (unlikely(test_bit(DTE_SHUTDOWN, &wc->flags))) {
/* The shudown flags can also be set if there is a /* The shudown flags can also be set if there is a
* catastrophic failure. */ * catastrophic failure. */
return -EIO; res = -EIO;
goto error_exit;
} }
atomic_inc(&wc->open_channels); atomic_inc(&wc->open_channels);
@ -1848,7 +1850,11 @@ wctc4xxp_operation_allocate(struct dahdi_transcoder_channel *dtc)
"Allocating channel %p which is already built.\n", dtc); "Allocating channel %p which is already built.\n", dtc);
return 0; return 0;
} }
return do_channel_allocate(dtc); res = do_channel_allocate(dtc);
error_exit:
mutex_unlock(&wc->chanlock);
return res;
} }
static void static void
@ -1874,19 +1880,21 @@ wctc4xxp_operation_release(struct dahdi_transcoder_channel *dtc)
BUG_ON(!cpvt); BUG_ON(!cpvt);
BUG_ON(!wc); BUG_ON(!wc);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
mutex_lock(&wc->chanlock);
#else
res = mutex_lock_killable(&wc->chanlock);
if (res)
return res;
#endif
if (unlikely(test_bit(DTE_SHUTDOWN, &wc->flags))) { if (unlikely(test_bit(DTE_SHUTDOWN, &wc->flags))) {
/* The shudown flags can also be set if there is a /* The shudown flags can also be set if there is a
* catastrophic failure. */ * catastrophic failure. */
return -EIO; res = -EIO;
goto error_exit;
} }
#ifndef DEBUG_WCTC4XXP
mutex_lock(&wc->chanlock);
#else
if (mutex_lock_interruptible(&wc->chanlock))
return -EINTR;
#endif
atomic_dec(&wc->open_channels); atomic_dec(&wc->open_channels);
#if !defined(CONFIG_WCTC4XXP_POLLING) #if !defined(CONFIG_WCTC4XXP_POLLING)
@ -3141,7 +3149,7 @@ error_exit:
static int static int
__wctc4xxp_setup_channels(struct wcdte *wc) wctc4xxp_setup_channels(struct wcdte *wc)
{ {
struct tcb *cmd; struct tcb *cmd;
int tdm_bus; int tdm_bus;
@ -3198,22 +3206,6 @@ error_exit:
return -1; return -1;
} }
static int
wctc4xxp_setup_channels(struct wcdte *wc)
{
int ret;
#ifndef DEBUG_WCTC4XXP
mutex_lock(&wc->chanlock);
#else
if (mutex_lock_interruptible(&wc->chanlock))
return -EINTR;
#endif
ret = __wctc4xxp_setup_channels(wc);
mutex_unlock(&wc->chanlock);
return ret;
}
static void wctc4xxp_setup_file_operations(struct file_operations *fops) static void wctc4xxp_setup_file_operations(struct file_operations *fops)
{ {
fops->owner = THIS_MODULE; fops->owner = THIS_MODULE;