[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