[svn-commits] sruffell: linux/trunk r9034 - /linux/trunk/drivers/dahdi/wctc4xxp/base.c

SVN commits to the Digium repositories svn-commits at lists.digium.com
Wed Jul 28 10:30:58 CDT 2010


Author: sruffell
Date: Wed Jul 28 10:30:47 2010
New Revision: 9034

URL: http://svnview.digium.com/svn/dahdi?view=rev&rev=9034
Log:
wctc4xxp: Allow read to return more than one packet of data.

As of this writing codec_dahdi (Asterisk module) will not call 'read' on
a transcoder channel more often than it calls 'write'.  When a
translation path is setup that will transcode from g723 to g729, write
is called every 30ms and each 'read' returns only 20ms of data.  The end
result is audio that slowly becomes increasing delayed.

Since codec_dahdi calls the system read function with a buffer large
enough to hold more than one packet this can prevents packets from
backing up on the channel. DAHDI-582

Modified:
    linux/trunk/drivers/dahdi/wctc4xxp/base.c

Modified: linux/trunk/drivers/dahdi/wctc4xxp/base.c
URL: http://svnview.digium.com/svn/dahdi/linux/trunk/drivers/dahdi/wctc4xxp/base.c?view=diff&rev=9034&r1=9033&r2=9034
==============================================================================
--- linux/trunk/drivers/dahdi/wctc4xxp/base.c (original)
+++ linux/trunk/drivers/dahdi/wctc4xxp/base.c Wed Jul 28 10:30:47 2010
@@ -1,7 +1,7 @@
 /*
  * Wildcard TC400B Driver
  *
- * Copyright (C) 2006-2009, Digium, Inc.
+ * Copyright (C) 2006-2010, Digium, Inc.
  *
  * All rights reserved.
  *
@@ -2038,6 +2038,8 @@
 	struct tcb *cmd;
 	struct rtp_packet *packet;
 	ssize_t payload_bytes;
+	ssize_t returned_bytes = 0;
+	unsigned long flags;
 
 	BUG_ON(!dtc);
 	BUG_ON(!cpvt);
@@ -2050,48 +2052,64 @@
 
 	cmd = get_ready_cmd(dtc);
 	if (!cmd) {
-		if (file->f_flags & O_NONBLOCK) {
+		if (file->f_flags & O_NONBLOCK)
 			return -EAGAIN;
-		} else {
-			ret = wait_event_interruptible(dtc->ready,
+		ret = wait_event_interruptible(dtc->ready,
 				dahdi_tc_is_data_waiting(dtc));
-			if (-ERESTARTSYS == ret) {
-				/* Signal interrupted the wait */
-				return -EINTR;
-			} else {
-				/* List went not empty. */
-				cmd = get_ready_cmd(dtc);
+		if (-ERESTARTSYS == ret)
+			return -EINTR;
+		/* List went not empty. */
+		cmd = get_ready_cmd(dtc);
+	}
+
+	do {
+		BUG_ON(!cmd);
+		packet = cmd->data;
+
+		payload_bytes = be16_to_cpu(packet->udphdr.len) -
+					sizeof(struct rtphdr) -
+					sizeof(struct udphdr);
+
+		if (count < (payload_bytes + returned_bytes)) {
+			if (returned_bytes) {
+				/* If we have already returned at least one
+				 * packets worth of data, we'll add this next
+				 * packet to the head of the receive queue so
+				 * it will be picked up next time. */
+				spin_lock_irqsave(&cpvt->lock, flags);
+				list_add(&cmd->node, &cpvt->rx_queue);
+				dahdi_tc_set_data_waiting(dtc);
+				spin_unlock_irqrestore(&cpvt->lock, flags);
+				return returned_bytes;
 			}
+
+			if (printk_ratelimit()) {
+				DTE_PRINTK(ERR,
+				  "Cannot copy %zd bytes into %zd byte user " \
+				  "buffer.\n", payload_bytes, count);
+			}
+			free_cmd(cmd);
+			return -EFBIG;
 		}
-	}
-
-	BUG_ON(!cmd);
-	packet = cmd->data;
-
-	payload_bytes = be16_to_cpu(packet->udphdr.len) -
-		sizeof(struct rtphdr) - sizeof(struct udphdr);
-
-	if (count < payload_bytes) {
-		if (printk_ratelimit()) {
-			DTE_PRINTK(ERR,
-			  "Cannot copy %zd bytes into %zd byte user " \
-			  "buffer.\n", payload_bytes, count);
+
+		atomic_inc(&cpvt->stats.packets_received);
+
+		ret = copy_to_user(&frame[returned_bytes],
+				   &packet->payload[0], payload_bytes);
+		if (unlikely(ret)) {
+			DTE_PRINTK(ERR, "Failed to copy data in %s\n",
+				   __func__);
+			free_cmd(cmd);
+			return -EFAULT;
 		}
+
+		returned_bytes += payload_bytes;
+
 		free_cmd(cmd);
-		return -EFBIG;
-	}
-
-	atomic_inc(&cpvt->stats.packets_received);
-
-	if (unlikely(copy_to_user(frame, &packet->payload[0], payload_bytes))) {
-		DTE_PRINTK(ERR, "Failed to copy data in %s\n", __func__);
-		free_cmd(cmd);
-		return -EFAULT;
-	}
-
-	free_cmd(cmd);
-
-	return payload_bytes;
+
+	} while ((cmd = get_ready_cmd(dtc)));
+
+	return returned_bytes;
 }
 
 /* Called with a frame in the srcfmt to be transcoded into the dstfmt. */




More information about the svn-commits mailing list