[dahdi-commits] dahdi/linux.git branch "master" updated.

SVN commits to the DAHDI project dahdi-commits at lists.digium.com
Fri May 30 15:07:39 CDT 2014


branch "master" has been updated
       via  d7c0b0aba14caaced017bc5520d48f5ddb5ac488 (commit)
       via  e10f740476b19afc302c3322201a750db1e872f4 (commit)
       via  dc92bf05cdf181125e597247a8de19df9ad471e8 (commit)
       via  8557bb6786e695fed7abbbba533fe827143b4c51 (commit)
       via  5981b152de1bfac22c650b1f63d793eab46fa40c (commit)
      from  cbe92363ea76571e0d0df8a96c2715817efc3159 (commit)

Summary of changes:
 drivers/dahdi/wctc4xxp/base.c |  128 ++++++++++++++++++++++++++---------------
 1 file changed, 82 insertions(+), 46 deletions(-)


- Log -----------------------------------------------------------------
commit d7c0b0aba14caaced017bc5520d48f5ddb5ac488
Author: Shaun Ruffell <sruffell at digium.com>
Date:   Thu May 29 15:53:45 2014 -0500

    wctc4xxp: Prevent exhausting memory in firmware.
    
    If the host system sends to many packets to the DTE to process, the on-card
    memory can be exhausted which will result in an out of memory alert. In commit
    2ac233824705e2f5f1cf67b6b22459fa20e9aa4c, the driver will halt all communication
    with the card and request a reload if any alert is received.
    
    Now the driver will silently drop any "burst" traffic that was sent to the
    transcoder as opposed to expecting the firmware to do it. There is currently a
    limit of 640 samples (80ms of audio) in flight to the firmware at any one time
    allowed.
    
    Signed-off-by: Shaun Ruffell <sruffell at digium.com>
    Signed-off-by: Russ Meyerriecks <rmeyerriecks at digium.com>

diff --git a/drivers/dahdi/wctc4xxp/base.c b/drivers/dahdi/wctc4xxp/base.c
index b178ffb..68d1f4a 100644
--- a/drivers/dahdi/wctc4xxp/base.c
+++ b/drivers/dahdi/wctc4xxp/base.c
@@ -306,6 +306,11 @@ struct channel_pvt {
 	};
 	struct channel_stats stats;
 	struct list_head rx_queue; /* Transcoded packets for this channel. */
+
+	/* Used to prevent user space from flooding the firmware. */
+	struct list_head node;
+	long samples_in_flight;
+	unsigned long send_time;
 };
 
 struct wcdte {
@@ -1812,6 +1817,7 @@ wctc4xxp_cleanup_channel_private(struct wcdte *wc,
 	spin_lock_irqsave(&cpvt->lock, flags);
 	list_splice_init(&cpvt->rx_queue, &local_list);
 	dahdi_tc_clear_data_waiting(dtc);
+	cpvt->samples_in_flight = 0;
 	spin_unlock_irqrestore(&cpvt->lock, flags);
 
 	memset(&cpvt->stats, 0, sizeof(cpvt->stats));
@@ -2035,12 +2041,10 @@ 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);
-	}
+	DTE_DEBUG(DTE_DEBUG_ETH_STATS,
+		"%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. */
@@ -2243,6 +2247,9 @@ wctc4xxp_write(struct file *file, const char __user *frame,
 	struct channel_pvt *cpvt = dtc->pvt;
 	struct wcdte *wc = cpvt->wc;
 	struct tcb *cmd;
+	u32 samples;
+	unsigned long flags;
+	const unsigned long MAX_SAMPLES_IN_FLIGHT = 640;
 
 	BUG_ON(!cpvt);
 	BUG_ON(!wc);
@@ -2280,6 +2287,24 @@ wctc4xxp_write(struct file *file, const char __user *frame,
 		}
 	}
 
+	/* Do not flood the firmware with packets. This can result in out of
+	 * memory conditions in the firmware. */
+	spin_lock_irqsave(&cpvt->lock, flags);
+	if (time_after(jiffies, cpvt->send_time)) {
+		cpvt->samples_in_flight = max(0L,
+					      cpvt->samples_in_flight - 160L);
+	}
+	samples = wctc4xxp_bytes_to_samples(dtc->srcfmt, count);
+	if ((cpvt->samples_in_flight + samples) > MAX_SAMPLES_IN_FLIGHT) {
+		spin_unlock_irqrestore(&cpvt->lock, flags);
+		/* This should most likely be an error, but it results in
+		 * codec_dahdi spamming when it's not set to wait for new
+		 * packets. Instead we will silently drop the bytes. */
+		return count;
+	}
+	cpvt->send_time = jiffies + msecs_to_jiffies(20);
+	spin_unlock_irqrestore(&cpvt->lock, flags);
+
 	cmd = wctc4xxp_create_rtp_cmd(wc, dtc, count);
 	if (!cmd)
 		return -ENOMEM;
@@ -2548,6 +2573,7 @@ queue_rtp_packet(struct wcdte *wc, struct tcb *cmd)
 	struct channel_pvt *cpvt;
 	struct rtp_packet *packet = cmd->data;
 	unsigned long flags;
+	long samples;
 
 	if (unlikely(ip_fast_csum((void *)(&packet->iphdr),
 		packet->iphdr.ihl))) {
@@ -2584,15 +2610,20 @@ queue_rtp_packet(struct wcdte *wc, struct tcb *cmd)
 	}
 
 	cpvt = dtc->pvt;
-	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 {
+	if (!dahdi_tc_is_busy(dtc)) {
 		free_cmd(cmd);
+		return;
 	}
+
+	spin_lock_irqsave(&cpvt->lock, flags);
+	samples = wctc4xxp_bytes_to_samples(dtc->dstfmt,
+			be16_to_cpu(packet->udphdr.len) -
+			sizeof(struct rtphdr) - sizeof(struct udphdr));
+	cpvt->samples_in_flight = max(cpvt->samples_in_flight - samples, 0L);
+	list_add_tail(&cmd->node, &cpvt->rx_queue);
+	dahdi_tc_set_data_waiting(dtc);
+	spin_unlock_irqrestore(&cpvt->lock, flags);
+	dahdi_transcoder_alert(dtc);
 	return;
 }
 

commit e10f740476b19afc302c3322201a750db1e872f4
Author: Shaun Ruffell <sruffell at digium.com>
Date:   Thu May 29 14:43:24 2014 -0500

    wctc4xxp: Service tx ring in interrupt handler.
    
    This helps to keep the tx descriptor ring at max capacity when the system is
    otherwise loaded. Now ready packets are moved from cmd_list to the transmit
    descriptor ring directly in the interrupt handler and not when the deferred
    function runs.
    
    Signed-off-by: Shaun Ruffell <sruffell at digium.com>
    Signed-off-by: Russ Meyerriecks <rmeyerriecks at digium.com>

diff --git a/drivers/dahdi/wctc4xxp/base.c b/drivers/dahdi/wctc4xxp/base.c
index d8c89ae..b178ffb 100644
--- a/drivers/dahdi/wctc4xxp/base.c
+++ b/drivers/dahdi/wctc4xxp/base.c
@@ -2600,8 +2600,8 @@ static void service_tx_ring(struct wcdte *wc)
 {
 	struct tcb *cmd;
 	unsigned long flags;
+	spin_lock_irqsave(&wc->cmd_list_lock, flags);
 	while ((cmd = wctc4xxp_retrieve(wc->txd))) {
-		spin_lock_irqsave(&wc->cmd_list_lock, flags);
 		cmd->flags |= TX_COMPLETE;
 		if (!(cmd->flags & (WAIT_FOR_ACK | WAIT_FOR_RESPONSE))) {
 			/* If we're not waiting for an ACK or Response from
@@ -2628,8 +2628,8 @@ static void service_tx_ring(struct wcdte *wc)
 			}
 			wctc4xxp_submit(wc->txd, cmd);
 		}
-		spin_unlock_irqrestore(&wc->cmd_list_lock, flags);
 	}
+	spin_unlock_irqrestore(&wc->cmd_list_lock, flags);
 }
 
 static void service_rx_ring(struct wcdte *wc)
@@ -2675,13 +2675,13 @@ static void deferred_work_func(struct work_struct *work)
 {
 	struct wcdte *wc = container_of(work, struct wcdte, deferred_work);
 #endif
-	service_tx_ring(wc);
 	service_rx_ring(wc);
 }
 
 DAHDI_IRQ_HANDLER(wctc4xxp_interrupt)
 {
 	struct wcdte *wc = dev_id;
+	bool packets_to_process = false;
 	u32 ints;
 #define NORMAL_INTERRUPT_SUMMARY (1<<16)
 #define ABNORMAL_INTERRUPT_SUMMARY (1<<15)
@@ -2703,11 +2703,14 @@ DAHDI_IRQ_HANDLER(wctc4xxp_interrupt)
 
 	if (likely(ints & NORMAL_INTERRUPTS)) {
 
-		if (ints & (RX_COMPLETE_INTERRUPT | TIMER_INTERRUPT))
-			wctc4xxp_handle_receive_ring(wc);
+		if (ints & (RX_COMPLETE_INTERRUPT | TIMER_INTERRUPT)) {
+			packets_to_process = !wctc4xxp_handle_receive_ring(wc);
+			service_tx_ring(wc);
+		}
 
 #if DEFERRED_PROCESSING == WORKQUEUE
-		schedule_work(&wc->deferred_work);
+		if (packets_to_process)
+			schedule_work(&wc->deferred_work);
 #elif DEFERRED_PROCESSING == INTERRUPT
 #error "You will need to change the locks if you want to run the processing " \
 		"in the interrupt handler."

commit dc92bf05cdf181125e597247a8de19df9ad471e8
Author: Shaun Ruffell <sruffell at digium.com>
Date:   Thu May 29 13:02:25 2014 -0500

    wctc4xxp: Fix the timestamp calculation for the RTP stream.
    
    I do not have any evidence that this made a difference, but hopefully it will
    clear things up for people in the future who might be wondering why the
    timestamp does not increase with the number of samples actually sent.
    
    Signed-off-by: Shaun Ruffell <sruffell at digium.com>
    Signed-off-by: Russ Meyerriecks <rmeyerriecks at digium.com>

diff --git a/drivers/dahdi/wctc4xxp/base.c b/drivers/dahdi/wctc4xxp/base.c
index 60f1b77..d8c89ae 100644
--- a/drivers/dahdi/wctc4xxp/base.c
+++ b/drivers/dahdi/wctc4xxp/base.c
@@ -300,7 +300,7 @@ struct channel_pvt {
 	u16 timeslot_out_num;	/* DTE timeslot to send data to */
 	u16 chan_in_num;	/* DTE channel to receive from */
 	u16 chan_out_num;	/* DTE channel to send data to */
-	u32 timestamp;
+	u32 last_timestamp;
 	struct {
 		u8 encoder:1;	/* If we're an encoder */
 	};
@@ -1511,6 +1511,22 @@ static void wctc4xxp_match_packet_counts(struct wcdte *wc)
 	free_cmd(cmd);
 }
 
+static inline u32 wctc4xxp_bytes_to_samples(u32 fmt, size_t count)
+{
+	switch (fmt) {
+	case DAHDI_FORMAT_G723_1:
+		return count * (G723_SAMPLES/G723_5K_BYTES);
+	case DAHDI_FORMAT_ULAW:
+	case DAHDI_FORMAT_ALAW:
+		return count;
+	case DAHDI_FORMAT_G729A:
+		return count * (G729_SAMPLES/G729_BYTES);
+	default:
+		WARN_ON(1);
+		return 0;
+	}
+}
+
 static struct tcb *
 wctc4xxp_create_rtp_cmd(struct wcdte *wc, struct dahdi_transcoder_channel *dtc,
 	size_t inbytes)
@@ -1564,9 +1580,12 @@ wctc4xxp_create_rtp_cmd(struct wcdte *wc, struct dahdi_transcoder_channel *dtc,
 	packet->rtphdr.marker =	    0;
 	packet->rtphdr.type =	    wctc4xxp_dahdifmt_to_dtefmt(dtc->srcfmt);
 	packet->rtphdr.seqno =	    cpu_to_be16(cpvt->seqno);
-	packet->rtphdr.timestamp =  cpu_to_be32(cpvt->timestamp);
+	packet->rtphdr.timestamp =  cpu_to_be32(cpvt->last_timestamp);
 	packet->rtphdr.ssrc =	    cpu_to_be32(cpvt->ssrc);
 
+	cpvt->last_timestamp +=     wctc4xxp_bytes_to_samples(dtc->srcfmt,
+							      inbytes);
+
 	WARN_ON(cmd->data_len > SFRAME_SIZE);
 	return cmd;
 }
@@ -2259,12 +2278,6 @@ wctc4xxp_write(struct file *file, const char __user *frame,
 			   G723_6K_BYTES, G723_SID_BYTES);
 			return -EINVAL;
 		}
-		cpvt->timestamp += G723_SAMPLES;
-	} else if (DAHDI_FORMAT_G723_1 == dtc->dstfmt) {
-		cpvt->timestamp = G723_SAMPLES;
-	} else {
-		/* Same for ulaw and alaw */
-		cpvt->timestamp += G729_SAMPLES;
 	}
 
 	cmd = wctc4xxp_create_rtp_cmd(wc, dtc, count);

commit 8557bb6786e695fed7abbbba533fe827143b4c51
Author: Shaun Ruffell <sruffell at digium.com>
Date:   Thu May 29 07:40:48 2014 -0500

    wctc4xxp: Speed up the rate of polling.
    
    The polling interval was not fast enough to keep the tx ring full on a loaded
    card. This fixes a regression introduced in commits
    ba05e31c8a786d7524fd1aed47feda27331606dd and
    354d88cd418627285e86e77cceb9318e33f0348c.
    
    Signed-off-by: Shaun Ruffell <sruffell at digium.com>
    Signed-off-by: Russ Meyerriecks <rmeyerriecks at digium.com>

diff --git a/drivers/dahdi/wctc4xxp/base.c b/drivers/dahdi/wctc4xxp/base.c
index 006ab49..60f1b77 100644
--- a/drivers/dahdi/wctc4xxp/base.c
+++ b/drivers/dahdi/wctc4xxp/base.c
@@ -78,7 +78,7 @@
 
 /* The total number of active channels over which the driver will start polling
  * the card every 10 ms. */
-#define POLLING_CALL_THRESHOLD 8
+#define POLLING_CALL_THRESHOLD 40
 
 #define INVALID 999 /* Used to mark invalid channels, commands, etc.. */
 #define MAX_CHANNEL_PACKETS  5
@@ -1904,7 +1904,7 @@ static void
 wctc4xxp_enable_polling(struct wcdte *wc)
 {
 	set_bit(DTE_POLLING, &wc->flags);
-	wctc4xxp_setctl(wc, 0x0058, 0x1000a);
+	wctc4xxp_setctl(wc, 0x0058, 0x10003);
 	/* Enable the general purpose timer interrupt. */
 	wctc4xxp_setintmask(wc, (DEFAULT_INTERRUPTS | (1 << 11)) & ~0x41);
 }

commit 5981b152de1bfac22c650b1f63d793eab46fa40c
Author: Shaun Ruffell <sruffell at digium.com>
Date:   Fri May 16 01:47:13 2014 -0500

    wctc4xxp: Handle all known interrupts regardless of mask.
    
    When switching to polling mode it was possible that we would mask off the
    receive complete interrupt until the next timer fired. Now go ahead and handle
    anything we know how to handle regardless of the current mask.
    
    Also, no need to update the reg local anymore since it isn't used to ack any
    interrupts. We now always ack all the interrupts first and inspect them all.
    
    Signed-off-by: Shaun Ruffell <sruffell at digium.com>
    Signed-off-by: Russ Meyerriecks <rmeyerriecks at digium.com>

diff --git a/drivers/dahdi/wctc4xxp/base.c b/drivers/dahdi/wctc4xxp/base.c
index 6959d91..006ab49 100644
--- a/drivers/dahdi/wctc4xxp/base.c
+++ b/drivers/dahdi/wctc4xxp/base.c
@@ -2670,7 +2670,9 @@ DAHDI_IRQ_HANDLER(wctc4xxp_interrupt)
 {
 	struct wcdte *wc = dev_id;
 	u32 ints;
-	u32 reg;
+#define NORMAL_INTERRUPT_SUMMARY (1<<16)
+#define ABNORMAL_INTERRUPT_SUMMARY (1<<15)
+
 #define TX_COMPLETE_INTERRUPT 0x00000001
 #define RX_COMPLETE_INTERRUPT 0x00000040
 #define TIMER_INTERRUPT	      (1<<11)
@@ -2680,25 +2682,16 @@ DAHDI_IRQ_HANDLER(wctc4xxp_interrupt)
 	/* Read and clear interrupts */
 	ints = __wctc4xxp_getctl(wc, 0x0028);
 
-	ints &= wc->intmask;
-
-	if (!ints)
+	if (!(ints & (NORMAL_INTERRUPT_SUMMARY|ABNORMAL_INTERRUPT_SUMMARY)))
 		return IRQ_NONE;
 
-	if (likely(ints & NORMAL_INTERRUPTS)) {
-		reg = 0;
-		if (ints & TX_COMPLETE_INTERRUPT)
-			reg |= TX_COMPLETE_INTERRUPT;
+	/* Clear all the pending interrupts. */
+	__wctc4xxp_setctl(wc, 0x0028, ints);
 
-		if (ints & RX_COMPLETE_INTERRUPT) {
-			wctc4xxp_handle_receive_ring(wc);
-			reg |= RX_COMPLETE_INTERRUPT;
-		}
+	if (likely(ints & NORMAL_INTERRUPTS)) {
 
-		if (ints & TIMER_INTERRUPT) {
+		if (ints & (RX_COMPLETE_INTERRUPT | TIMER_INTERRUPT))
 			wctc4xxp_handle_receive_ring(wc);
-			reg |= TIMER_INTERRUPT;
-		}
 
 #if DEFERRED_PROCESSING == WORKQUEUE
 		schedule_work(&wc->deferred_work);
@@ -2709,7 +2702,6 @@ DAHDI_IRQ_HANDLER(wctc4xxp_interrupt)
 #error "Define a deferred processing function in kernel/wctc4xxp/wctc4xxp.h"
 #endif
 
-		__wctc4xxp_setctl(wc, 0x0028, reg);
 	} else {
 		if ((ints & 0x00008000) && debug)
 			dev_info(&wc->pdev->dev, "Abnormal Interrupt.\n");
@@ -2736,9 +2728,6 @@ DAHDI_IRQ_HANDLER(wctc4xxp_interrupt)
 			dev_info(&wc->pdev->dev,
 				 "Transmit Processor Stopped INT\n");
 		}
-
-		/* Clear all the pending interrupts. */
-		__wctc4xxp_setctl(wc, 0x0028, ints);
 	}
 	return IRQ_HANDLED;
 }

-----------------------------------------------------------------------


-- 
dahdi/linux.git



More information about the dahdi-commits mailing list