From ec9d162344a8e84a6e0e3f563a800cbfb5bc75ac Mon Sep 17 00:00:00 2001 From: Shaun Ruffell Date: Fri, 2 May 2014 11:07:56 -0500 Subject: [PATCH] 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 Signed-off-by: Russ Meyerriecks --- drivers/dahdi/wctc4xxp/base.c | 62 +++++++++++++++-------------------- 1 file changed, 27 insertions(+), 35 deletions(-) diff --git a/drivers/dahdi/wctc4xxp/base.c b/drivers/dahdi/wctc4xxp/base.c index 0b38a37..f6f3d43 100644 --- a/drivers/dahdi/wctc4xxp/base.c +++ b/drivers/dahdi/wctc4xxp/base.c @@ -1658,7 +1658,6 @@ static int wctc4xxp_create_channel_pair(struct wcdte *wc, struct channel_pvt *cpvt, u8 simple, u8 complicated); static int wctc4xxp_destroy_channel_pair(struct wcdte *wc, struct channel_pvt *cpvt); -static int __wctc4xxp_setup_channels(struct wcdte *wc); static void 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 */ int res; -#ifndef DEBUG_WCTC4XXP - mutex_lock(&wc->chanlock); -#else if (mutex_lock_interruptible(&wc->chanlock)) return -EINTR; -#endif /* Check again to see if the channel was built after grabbing the * channel lock, in case the previous holder of the lock * built this channel as a complement to itself. */ if (dahdi_tc_is_built(dtc)) { - mutex_unlock(&wc->chanlock); DTE_DEBUG(DTE_DEBUG_CHANNEL_SETUP, "Allocating channel %p which is already built.\n", dtc); return 0; @@ -1779,7 +1773,6 @@ do_channel_allocate(struct dahdi_transcoder_channel *dtc) wctc4xxp_dstfmt); if (res) { /* There was a problem creating the channel.... */ - mutex_unlock(&wc->chanlock); dev_err(&wc->pdev->dev, "Failed to create channel pair.\n"); 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 * built */ wctc4xxp_mark_channel_complement_built(wc, dtc); - mutex_unlock(&wc->chanlock); dahdi_transcoder_alert(dtc); return 0; } @@ -1829,12 +1821,22 @@ wctc4xxp_enable_polling(struct wcdte *wc) static int wctc4xxp_operation_allocate(struct dahdi_transcoder_channel *dtc) { + int res; 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))) { /* The shudown flags can also be set if there is a * catastrophic failure. */ - return -EIO; + res = -EIO; + goto error_exit; } 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); return 0; } - return do_channel_allocate(dtc); + res = do_channel_allocate(dtc); + +error_exit: + mutex_unlock(&wc->chanlock); + return res; } static void @@ -1874,19 +1880,21 @@ wctc4xxp_operation_release(struct dahdi_transcoder_channel *dtc) BUG_ON(!cpvt); 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))) { /* The shudown flags can also be set if there is a * 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); #if !defined(CONFIG_WCTC4XXP_POLLING) @@ -3141,7 +3149,7 @@ error_exit: static int -__wctc4xxp_setup_channels(struct wcdte *wc) +wctc4xxp_setup_channels(struct wcdte *wc) { struct tcb *cmd; int tdm_bus; @@ -3198,22 +3206,6 @@ error_exit: 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) { fops->owner = THIS_MODULE;