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:
parent
7168b87cb5
commit
ec9d162344
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user