[dahdi-commits] sruffell: branch linux/sruffell/dahdi-linux-chainedvb r7104 - /linux/team/sru...

SVN commits to the DAHDI project dahdi-commits at lists.digium.com
Wed Sep 9 01:13:13 CDT 2009


Author: sruffell
Date: Wed Sep  9 01:13:10 2009
New Revision: 7104

URL: http://svn.asterisk.org/svn-view/dahdi?view=rev&rev=7104
Log:
wip:  In the middle of restructuring in order to support the idle list.

Doesn't work yet, but the idle list (or something like it...not sure what is
going to be best yet) will be a set of chained descriptors that contain an
idle SFRAME.  The intent is to allow the cards to have a low default latency
(and not add significant delay to any conversations) yet still have plenty of
descriptors chained up so that the card never sees a condition where there
isn't another transmit descriptor to send.  You will still have blips and
breaks in the audio when the card moves onto the idle list, but I believe this
may work around what appear to be bad register writes to the modules when the
descriptor list goes empty.

Now...all this would be unnecessary if the host system is designed in such a
way that it never holds off interrupts for the dahdi cards for longer than the
latency value after reset.....but there appear to be some systems where this
is impractical.

Modified:
    linux/team/sruffell/dahdi-linux-chainedvb/drivers/dahdi/voicebus/voicebus.c

Modified: linux/team/sruffell/dahdi-linux-chainedvb/drivers/dahdi/voicebus/voicebus.c
URL: http://svn.asterisk.org/svn-view/dahdi/linux/team/sruffell/dahdi-linux-chainedvb/drivers/dahdi/voicebus/voicebus.c?view=diff&rev=7104&r1=7103&r2=7104
==============================================================================
--- linux/team/sruffell/dahdi-linux-chainedvb/drivers/dahdi/voicebus/voicebus.c (original)
+++ linux/team/sruffell/dahdi-linux-chainedvb/drivers/dahdi/voicebus/voicebus.c Wed Sep  9 01:13:10 2009
@@ -138,28 +138,37 @@
  * @desc:	Kernel virtual address of the descriptor.
  * @desc_dma:	Bus address of the desc to give to the hardware.
  * @pending:	Kernel virtual address desc->buffer1.
+ * @idle_desc:	Either NULL or the first entry on the idle list.	
+ * @node:	Used to chain the descriptors in host memory.
  *
  */
 struct voicebus_chained_descriptor {
 	struct voicebus_descriptor *desc;
 	dma_addr_t	dma_addr;
+	void 		*pending;
+	struct voicebus_chained_descriptor *idle_desc;
 	struct list_head node;
-	void 		*pending;
 };
 
 /**
  * struct voicebus_descriptor_list -
- * @desc_list:	Allocated buffer list.
- * @head:	Next buffer to complete.
- * @tail:	Next free buffer to use.
- * @direction:	DMA_FROM_DEVICE or DMA_TO_DEVICE
- * @padding:	Number of bytes to pad descriptors for cache alignment.
+ * @active_list:   Allocated buffer list.
+ * @head:	   Next buffer to complete.
+ * @tail:	   Next free buffer to use.
+ * @direction:	   DMA_FROM_DEVICE or DMA_TO_DEVICE
+ * @padding:	   Number of bytes to pad descriptors for cache alignment.
+ * @idle_buffer:   Kernel virtual addres of common overflow buffer.
+ * @idle_dma_addr: Bus address of the overflow buffer.
+ * @count:	   The number of descriptors given to hardware.
  *
  */
 struct voicebus_descriptor_list {
-	struct list_head	desc_list;
+	struct list_head	active_list;
 	struct voicebus_chained_descriptor *head;
 	struct voicebus_chained_descriptor *tail;
+	struct list_head 	idle_list;
+	void 			*idle_buffer;
+	dma_addr_t		idle_dma_addr;
 	enum dma_data_direction	direction;
 	unsigned int		padding;
 	atomic_t		count;
@@ -273,7 +282,7 @@
 
 /* Bit definitions for struct voicebus.flags */
 #define TX_UNDERRUN			1
-#define RX_UNDERRUN			2
+#define ON_IDLE_LIST			2
 #define IN_DEFERRED_PROCESSING		3
 #define STOP				4
 #define STOPPED				5
@@ -348,16 +357,25 @@
 		    struct voicebus_chained_descriptor *d)
 {
 	/* Skip the head of the list if necessary. */
-	return (d->node.next == &dl->desc_list) ? 
-		list_entry(dl->desc_list.next, typeof(*d), node) :
+	return (d->node.next == &dl->active_list) ? 
+		list_entry(dl->active_list.next, typeof(*d), node) :
 		list_entry(d->node.next, typeof(*d), node);
 }
 
+static struct voicebus_chained_descriptor *
+get_prev_descriptor(struct voicebus_descriptor_list *dl,
+		    struct voicebus_chained_descriptor *d)
+{
+	/* Skip the head of the list if necessary. */
+	return (d->node.prev == &dl->active_list) ? 
+		list_entry(dl->active_list.prev, typeof(*d), node) :
+		list_entry(d->node.prev, typeof(*d), node);
+}
 static void vb_cleanup_descriptors(struct voicebus *vb,
 				   struct voicebus_descriptor_list *dl)
 {
 	struct voicebus_chained_descriptor *d;
-	struct list_head *const list = &dl->desc_list;
+	struct list_head *const list = &dl->active_list;
 
 	list_for_each_entry(d, list, node) {
 		if (d->desc->buffer1) {
@@ -402,7 +420,7 @@
 vb_free_descriptors(struct voicebus *vb, struct voicebus_descriptor_list *dl)
 {
 	struct voicebus_chained_descriptor *d;
-	struct list_head *const list = &dl->desc_list;
+	struct list_head *const list = &dl->active_list;
 
 	vb_cleanup_descriptors(vb, dl);
 	while (!list_empty(list)) {
@@ -412,6 +430,10 @@
 				  d->desc, d->dma_addr);
 		kfree(d);
 	}
+	dma_free_coherent(&vb->pdev->dev, vb->framesize,
+			  dl->idle_buffer, dl->idle_dma_addr);
+	dl->idle_buffer = NULL;
+	dl->idle_dma_addr = 0;
 }
 #else
 static void
@@ -429,20 +451,29 @@
 #endif
 
 #if defined(USE_CHAINED_DESCRIPTORS)
+#define vb_initialize_descriptors vb_initialize_chained_descriptors
 static int
-vb_initialize_descriptors(struct voicebus *vb, struct voicebus_descriptor_list *dl,
-	u32 des1, unsigned int direction)
+vb_initialize_chained_descriptors(struct voicebus *vb, struct voicebus_descriptor_list *dl,
+				  u32 des1, unsigned int direction)
 {
 	int i;
 	const u32 CHAINED = 0x01000000;
 	struct voicebus_chained_descriptor *d;
 	struct voicebus_chained_descriptor *prev;
+	struct list_head *const list = &dl->idle_list;
 
 	/* Since we're passing each descriptor address explicitly, we don't
 	 * need any padding for the chained descriptor. */
 	dl->padding = 0;
 
-	INIT_LIST_HEAD(&dl->desc_list);
+	INIT_LIST_HEAD(&dl->active_list);
+	INIT_LIST_HEAD(&dl->idle_list);
+	dl->idle_buffer = dma_alloc_coherent(&vb->pdev->dev, vb->framesize,
+				       &dl->idle_dma_addr, GFP_KERNEL);
+
+	if (!dl->idle_buffer)
+		return -ENOMEM;
+
 
 	for (i = 0; i < DLIST_SIZE; ++i) {
 		d = kzalloc(sizeof(*d), GFP_KERNEL);
@@ -456,14 +487,18 @@
 			goto error_nomem;
 		}
 		
-		list_add_tail(&d->node, &dl->desc_list);
-	}
-
-	dl->head = list_entry(dl->desc_list.next, typeof(*d), node);
+		list_add_tail(&d->node, list);
+	}
+
+	dl->head = list_entry(list->next, typeof(*d), node);
 	dl->tail = dl->head;
 
+	/* By default, chain all the descriptors together, and point them all
+	 * at the idle buffer. */
 	prev = dl->head;
-	list_for_each_entry_reverse(d, &dl->desc_list, node) {
+	list_for_each_entry_reverse(d, list, node) {
+		d->pending = dl->idle_buffer;
+		d->desc->buffer1 = dl->idle_dma_addr;
 		d->desc->buffer2 = prev->dma_addr;
 		d->desc->des1 |= cpu_to_le32(des1 | CHAINED);
 		prev = d;
@@ -477,8 +512,9 @@
 	return -ENOMEM;
 }
 #else
+#define vb_initialize_descriptors vb_initialize_ring_descriptors
 static int
-vb_initialize_descriptors(struct voicebus *vb, struct voicebus_descriptor_list *dl,
+vb_initialize_ring_descriptors(struct voicebus *vb, struct voicebus_descriptor_list *dl,
 	u32 des1, unsigned int direction)
 {
 	int i;
@@ -884,6 +920,7 @@
 		     struct voicebus_descriptor_list *dl, void *vbb)
 {
 	struct voicebus_chained_descriptor *d;
+	struct voicebus_chained_descriptor *p;
 
 	d = dl->tail;
 
@@ -891,12 +928,23 @@
 	if (unlikely(d->desc->buffer1)) {
 		WARN_ON(1);
 		voicebus_free(vb, vbb);
+		return -EBUSY;
 	}
 
 	dl->tail = get_next_descriptor(dl, d);
 	d->pending = vbb;
 	d->desc->buffer1 = dma_map_single(&vb->pdev->dev, vbb,
 					  vb->framesize, dl->direction);
+	
+	d->idle_desc = list_entry(dl->idle_list.next, typeof(*d), node);
+	d->desc->buffer2 = d->idle_desc->dma_addr;
+
+	p = get_prev_descriptor(dl, d);
+	p->desc->buffer2 = d->dma_addr;
+	p->idle_desc = NULL;
+
+	wmb();
+	WARN_ON(!OWNED(p->desc));
 
 	/* That's it until the hardware is done with it. */
 	SET_OWNED(d->desc);
@@ -904,7 +952,7 @@
 	return -EFAULT;
 }
 
-static void* vb_retrieve(struct voicebus *vb,
+static void *vb_retrieve(struct voicebus *vb,
 			 struct voicebus_descriptor_list *dl)
 {
 	struct voicebus_chained_descriptor *d;
@@ -919,6 +967,10 @@
 		dl->head = get_next_descriptor(dl, d);
 		d->desc->buffer1 = 0;
 		atomic_dec(&dl->count);
+
+		if (unlikely(d->idle_desc))
+			set_bit(ON_IDLE_LIST, &vb->flags);
+
 		return vbb;
 	} else {
 		return NULL;
@@ -1393,8 +1445,11 @@
 	}
 
 	/* Always handle the transmit buffers first. */
-	while ((vbb = vb_get_completed_txb(vb)))
+	while ((vbb = vb_get_completed_txb(vb))) {
 		vb->handle_transmit(vbb, vb->context);
+		if (unlikely(test_bit(ON_IDLE_LIST, &vb->flags))) {
+		}
+	}
 
 	if (unlikely(underrun)) {
 		vb_rx_demand_poll(vb);




More information about the dahdi-commits mailing list