From b5ac763f29c88b09682d1f50096b21745e9ae8a1 Mon Sep 17 00:00:00 2001 From: Shaun Ruffell Date: Thu, 8 May 2014 13:46:18 -0500 Subject: [PATCH] wctc4xxp: Cleanup RTP for unopened channels. When we start the shutdown sequence for a channel, there is no need to submit any RTP packets that are queued on the command list. Under extreme load with many backed up RTP packets it was possible to have RTP packets submitted after the channel shutdown process started. Signed-off-by: Shaun Ruffell Signed-off-by: Russ Meyerriecks --- drivers/dahdi/dahdi_transcode.c | 3 ++- drivers/dahdi/wctc4xxp/base.c | 29 +++++++++++++++++++++++------ 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/drivers/dahdi/dahdi_transcode.c b/drivers/dahdi/dahdi_transcode.c index 075391c..a495dcf 100644 --- a/drivers/dahdi/dahdi_transcode.c +++ b/drivers/dahdi/dahdi_transcode.c @@ -168,8 +168,9 @@ static void dtc_release(struct dahdi_transcoder_channel *chan) BUG_ON(!chan); if (chan->parent && chan->parent->release) { chan->parent->release(chan); + } else { + dahdi_tc_clear_busy(chan); } - dahdi_tc_clear_busy(chan); } static int dahdi_tc_release(struct inode *inode, struct file *file) diff --git a/drivers/dahdi/wctc4xxp/base.c b/drivers/dahdi/wctc4xxp/base.c index 7323535..75e67df 100644 --- a/drivers/dahdi/wctc4xxp/base.c +++ b/drivers/dahdi/wctc4xxp/base.c @@ -1421,7 +1421,7 @@ static struct tcb * wctc4xxp_create_rtp_cmd(struct wcdte *wc, struct dahdi_transcoder_channel *dtc, size_t inbytes) { - const struct channel_pvt *cpvt = dtc->pvt; + struct channel_pvt *cpvt = dtc->pvt; struct rtp_packet *packet; struct tcb *cmd; @@ -1429,6 +1429,7 @@ wctc4xxp_create_rtp_cmd(struct wcdte *wc, struct dahdi_transcoder_channel *dtc, if (!cmd) return NULL; + cmd->cpvt = cpvt; packet = cmd->data; BUG_ON(cmd->data_len < sizeof(*packet)); @@ -1698,6 +1699,16 @@ wctc4xxp_cleanup_channel_private(struct wcdte *wc, unsigned long flags; LIST_HEAD(local_list); + /* Once we cleanup this channel, we do not want any queued packets + * waiting to be transmitted. Anything on the hardware descriptor ring + * will be flushed by the csm_encaps command to shutdown the channel. */ + spin_lock_irqsave(&wc->cmd_list_lock, flags); + list_for_each_entry_safe(cmd, temp, &wc->cmd_list, node) { + if (cmd->cpvt == cpvt) + list_move(&cmd->node, &local_list); + } + spin_unlock_irqrestore(&wc->cmd_list_lock, flags); + spin_lock_irqsave(&cpvt->lock, flags); list_splice_init(&cpvt->rx_queue, &local_list); dahdi_tc_clear_data_waiting(dtc); @@ -1913,7 +1924,9 @@ wctc4xxp_operation_release(struct dahdi_transcoder_channel *dtc) packets_sent, packets_received); } + /* Remove any packets that are waiting on the outbound queue. */ + dahdi_tc_clear_busy(dtc); wctc4xxp_cleanup_channel_private(wc, dtc); index = cpvt->timeslot_in_num/2; BUG_ON(index >= wc->numchannels); @@ -2480,11 +2493,15 @@ queue_rtp_packet(struct wcdte *wc, struct tcb *cmd) } cpvt = dtc->pvt; - spin_lock_irqsave(&cpvt->lock, flags); - list_add_tail(&cmd->node, &cpvt->rx_queue); - dahdi_tc_set_data_waiting(dtc); - spin_unlock_irqrestore(&cpvt->lock, flags); - dahdi_transcoder_alert(dtc); + if (dahdi_tc_is_busy(dtc)) { + spin_lock_irqsave(&cpvt->lock, flags); + list_add_tail(&cmd->node, &cpvt->rx_queue); + dahdi_tc_set_data_waiting(dtc); + spin_unlock_irqrestore(&cpvt->lock, flags); + dahdi_transcoder_alert(dtc); + } else { + free_cmd(cmd); + } return; }