From 7f384a52e3951076d4b4370fb0462cc3a93f68f9 Mon Sep 17 00:00:00 2001 From: Russ Meyerriecks Date: Wed, 15 Aug 2012 14:10:34 -0500 Subject: [PATCH] wctc4xxp: Fail gracefully on "Failed to create channel" scenario. Sometimes the DTE device api returns a failure to create timeslot. When this happens, subsequent channel allocations will also continue to fail. This patch attempts to mark the channel as wedged, so that further channel allocates might succeed and the device continue to operate. Internal-Issue-ID: DAHLIN-298 Internal-Issue-ID: DAHDI-990 Signed-off-by: Russ Meyerriecks --- drivers/dahdi/dahdi_transcode.c | 2 +- drivers/dahdi/wctc4xxp/base.c | 26 ++++++++++++++++++-------- include/dahdi/kernel.h | 9 +++++++++ 3 files changed, 28 insertions(+), 9 deletions(-) diff --git a/drivers/dahdi/dahdi_transcode.c b/drivers/dahdi/dahdi_transcode.c index 075391c..7340ca2 100644 --- a/drivers/dahdi/dahdi_transcode.c +++ b/drivers/dahdi/dahdi_transcode.c @@ -198,7 +198,7 @@ get_free_channel(struct dahdi_transcoder *tc, for (i = 0; i < tc->numchannels; i++) { chan = &tc->channels[i]; - if (!dahdi_tc_is_busy(chan)) { + if (!dahdi_tc_is_busy(chan) && !dahdi_tc_is_wedged(chan)) { if (!dahdi_tc_is_built(chan)) { dahdi_tc_set_busy(chan); return chan; diff --git a/drivers/dahdi/wctc4xxp/base.c b/drivers/dahdi/wctc4xxp/base.c index c88f7d7..09150ec 100644 --- a/drivers/dahdi/wctc4xxp/base.c +++ b/drivers/dahdi/wctc4xxp/base.c @@ -1782,6 +1782,15 @@ do_channel_allocate(struct dahdi_transcoder_channel *dtc) wctc4xxp_dstfmt); if (res) { /* There was a problem creating the channel.... */ + /* Sometimes the DTC device fails to setup a channel. + As a workaround, we mark that channel as perma-busy + so that subsequent allocates don't get stuck */ + if (-EBUSY == res) { + dahdi_tc_set_wedged(dtc); + dev_err(&wc->pdev->dev, "Channel %p seems to be wedged"\ + " Permanently disabling channel"\ + " until driver is reloaded\n", dtc); + } up(&wc->chansem); return res; } @@ -1901,12 +1910,8 @@ wctc4xxp_operation_release(struct dahdi_transcoder_channel *dtc) packets_received = atomic_read(&cpvt->stats.packets_received); packets_sent = atomic_read(&cpvt->stats.packets_sent); - if ((packets_sent - packets_received) > 5) { - DTE_DEBUG(DTE_DEBUG_GENERAL, "%s channel %d sent %d packets " - "and received %d packets.\n", (cpvt->encoder) ? - "encoder" : "decoder", cpvt->chan_out_num, - packets_sent, packets_received); - } + if ((packets_sent - packets_received) > 5) + DTE_DEBUG(DTE_DEBUG_GENERAL, "%s channel %d sent %d packets " "and received %d packets.\n", (cpvt->encoder) ? "encoder" : "decoder", cpvt->chan_out_num, packets_sent, packets_received); /* Remove any packets that are waiting on the outbound queue. */ wctc4xxp_cleanup_channel_private(wc, dtc); @@ -3022,11 +3027,11 @@ wctc4xxp_create_channel_pair(struct wcdte *wc, struct channel_pvt *cpvt, * encoder and another for the complex->simple decoder. */ if (send_create_channel_cmd(wc, cmd, encoder_timeslot, &encoder_channel)) - goto error_exit; + goto ebusy_exit; if (send_create_channel_cmd(wc, cmd, decoder_timeslot, &decoder_channel)) - goto error_exit; + goto ebusy_exit; DTE_DEBUG(DTE_DEBUG_CHANNEL_SETUP, "DTE is using the following channels encoder_channel: " \ @@ -3062,9 +3067,14 @@ wctc4xxp_create_channel_pair(struct wcdte *wc, struct channel_pvt *cpvt, free_cmd(cmd); return 0; + error_exit: free_cmd(cmd); return -EIO; + +ebusy_exit: + free_cmd(cmd); + return -EBUSY; } static int diff --git a/include/dahdi/kernel.h b/include/dahdi/kernel.h index 65dfd89..8ee9bbf 100644 --- a/include/dahdi/kernel.h +++ b/include/dahdi/kernel.h @@ -987,6 +987,7 @@ struct dahdi_transcoder_channel { #define DAHDI_TC_FLAG_CHAN_BUILT 2 #define DAHDI_TC_FLAG_NONBLOCK 3 #define DAHDI_TC_FLAG_DATA_WAITING 4 +#define DAHDI_TC_FLAG_WEDGED 5 unsigned long flags; u32 dstfmt; u32 srcfmt; @@ -1026,11 +1027,19 @@ static inline int dahdi_tc_is_busy(struct dahdi_transcoder_channel *dtc) { return test_bit(DAHDI_TC_FLAG_BUSY, &dtc->flags); } +static inline int +dahdi_tc_is_wedged(struct dahdi_transcoder_channel *dtc) { + return test_bit(DAHDI_TC_FLAG_WEDGED, &dtc->flags); +} static inline void dahdi_tc_set_busy(struct dahdi_transcoder_channel *dtc) { set_bit(DAHDI_TC_FLAG_BUSY, &dtc->flags); } static inline void +dahdi_tc_set_wedged(struct dahdi_transcoder_channel *dtc) { + set_bit(DAHDI_TC_FLAG_WEDGED, &dtc->flags); +} +static inline void dahdi_tc_clear_busy(struct dahdi_transcoder_channel *dtc) { clear_bit(DAHDI_TC_FLAG_BUSY, &dtc->flags); } -- 1.8.0.1