summaryrefslogtreecommitdiff
path: root/drivers/dahdi/voicebus
diff options
context:
space:
mode:
authorShaun Ruffell <sruffell@digium.com>2010-07-26 00:30:37 +0000
committerShaun Ruffell <sruffell@digium.com>2010-07-26 00:30:37 +0000
commitc3a505d8eae4e5da94e8c5ac671a1815f7770859 (patch)
tree4dadd3fcb1b4bfddcddbd77e4cccedef9f0e4ee7 /drivers/dahdi/voicebus
parent4b380bbcbb33017a3c343d4ded0e5eff2fe497a7 (diff)
wcte12xp, wctdm24xxp: Return buffer processing to interrupt handler.
In revision 8095, I had moved most of the buffer processing out of the interrupt handler and into a tasklet. The intended result was to enable multiple cards to interleave with one another. But once again I was bitten by the fact that there are some systems that for one reason or another do not process their tasklets in a timely enough manner for the real-time nature of TDM processing. This commit moves this processing back into the interrupt handler by default. It also limits the number of frames that the interrupt handler will process at any given time which appears to achieve the same intended result. (closes issue #17289) Tested by: alecdavis git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@8982 a0bf4364-ded3-4de4-8d8a-66a801d63aff
Diffstat (limited to 'drivers/dahdi/voicebus')
-rw-r--r--drivers/dahdi/voicebus/voicebus.c73
-rw-r--r--drivers/dahdi/voicebus/voicebus.h8
2 files changed, 66 insertions, 15 deletions
diff --git a/drivers/dahdi/voicebus/voicebus.c b/drivers/dahdi/voicebus/voicebus.c
index 3874fbb..9bc7386 100644
--- a/drivers/dahdi/voicebus/voicebus.c
+++ b/drivers/dahdi/voicebus/voicebus.c
@@ -332,6 +332,34 @@ vb_is_stopped(struct voicebus *vb)
return ret;
}
+#if defined(CONFIG_VOICEBUS_INTERRUPT)
+
+static inline void vb_disable_deferred(struct voicebus *vb)
+{
+ if (atomic_inc_return(&vb->deferred_disabled_count) == 1)
+ disable_irq(vb->pdev->irq);
+}
+
+static inline void vb_enable_deferred(struct voicebus *vb)
+{
+ if (atomic_dec_return(&vb->deferred_disabled_count) == 0)
+ enable_irq(vb->pdev->irq);
+}
+
+#else
+
+static inline void vb_disable_deferred(struct voicebus *vb)
+{
+ tasklet_disable(&vb->tasklet);
+}
+
+static inline void vb_enable_deferred(struct voicebus *vb)
+{
+ tasklet_enable(&vb-tasklet);
+}
+
+#endif
+
static void
vb_cleanup_tx_descriptors(struct voicebus *vb)
{
@@ -340,7 +368,7 @@ vb_cleanup_tx_descriptors(struct voicebus *vb)
struct voicebus_descriptor *d;
struct vbb *vbb;
- tasklet_disable(&vb->tasklet);
+ vb_disable_deferred(vb);
while (!list_empty(&vb->tx_complete)) {
vbb = list_entry(vb->tx_complete.next, struct vbb, entry);
@@ -370,7 +398,7 @@ vb_cleanup_tx_descriptors(struct voicebus *vb)
dl->head = dl->tail = 0;
atomic_set(&dl->count, 0);
- tasklet_enable(&vb->tasklet);
+ vb_enable_deferred(vb);
}
static void vb_cleanup_rx_descriptors(struct voicebus *vb)
@@ -380,7 +408,7 @@ static void vb_cleanup_rx_descriptors(struct voicebus *vb)
struct voicebus_descriptor *d;
struct vbb *vbb;
- tasklet_disable(&vb->tasklet);
+ vb_disable_deferred(vb);
for (i = 0; i < DRING_SIZE; ++i) {
d = vb_descriptor(dl, i);
if (d->buffer1) {
@@ -397,7 +425,7 @@ static void vb_cleanup_rx_descriptors(struct voicebus *vb)
dl->head = 0;
dl->tail = 0;
atomic_set(&dl->count, 0);
- tasklet_enable(&vb->tasklet);
+ vb_enable_deferred(vb);
}
static void vb_cleanup_descriptors(struct voicebus *vb,
@@ -667,13 +695,13 @@ static void setup_descriptors(struct voicebus *vb)
list_add_tail(&vbb->entry, &buffers);
}
- tasklet_disable(&vb->tasklet);
+ vb_disable_deferred(vb);
while (!list_empty(&buffers)) {
vbb = list_entry(buffers.next, struct vbb, entry);
list_del(&vbb->entry);
vb_submit_rxb(vb, vbb);
}
- tasklet_enable(&vb->tasklet);
+ vb_enable_deferred(vb);
if (BOOT != vb->mode) {
for (i = 0; i < vb->min_tx_buffer_count; ++i) {
@@ -686,13 +714,13 @@ static void setup_descriptors(struct voicebus *vb)
handle_transmit(vb, &buffers);
- tasklet_disable(&vb->tasklet);
+ vb_disable_deferred(vb);
while (!list_empty(&buffers)) {
vbb = list_entry(buffers.next, struct vbb, entry);
list_del_init(&vbb->entry);
voicebus_transmit(vb, vbb);
}
- tasklet_enable(&vb->tasklet);
+ vb_enable_deferred(vb);
}
}
@@ -1113,6 +1141,15 @@ vb_increase_latency(struct voicebus *vb, unsigned int increase,
vb->min_tx_buffer_count += increase;
}
+static void vb_schedule_deferred(struct voicebus *vb)
+{
+#if !defined(CONFIG_VOICEBUS_INTERRUPT)
+ tasklet_hi_schedule(&vb->tasklet);
+#else
+ vb->tasklet.func(vb->tasklet.data);
+#endif
+}
+
/**
* vb_tasklet_boot() - When vb->mode == BOOT
*
@@ -1157,8 +1194,10 @@ static void vb_tasklet_boot(unsigned long data)
/* If there may still be buffers in the descriptor rings, reschedule
* ourself to run again. We essentially yield here to allow any other
* cards a chance to run. */
+#if !defined(CONFIG_VOICEBUS_INTERRUPT)
if (unlikely(!count && !test_bit(VOICEBUS_STOP, &vb->flags)))
- tasklet_hi_schedule(&vb->tasklet);
+ vb_schedule_deferred(vb);
+#endif
/* And finally, pass up any receive buffers. */
count = DEFAULT_COUNT;
@@ -1250,11 +1289,13 @@ static void vb_tasklet_hx8(unsigned long data)
#endif
}
+#if !defined(CONFIG_VOICEBUS_INTERRUPT)
/* If there may still be buffers in the descriptor rings, reschedule
* ourself to run again. We essentially yield here to allow any other
* cards a chance to run. */
if (unlikely(!count && !test_bit(VOICEBUS_STOP, &vb->flags)))
- tasklet_hi_schedule(&vb->tasklet);
+ vb_schedule_deferred(vb);
+#endif
/* And finally, pass up any receive buffers. */
count = DEFAULT_COUNT;
@@ -1393,11 +1434,13 @@ static void vb_tasklet_normal(unsigned long data)
#endif
}
+#if !defined(CONFIG_VOICEBUS_INTERRUPT)
/* If there may still be buffers in the descriptor rings, reschedule
* ourself to run again. We essentially yield here to allow any other
* cards a chance to run. */
if (unlikely(!count && !test_bit(VOICEBUS_STOP, &vb->flags)))
- tasklet_hi_schedule(&vb->tasklet);
+ vb_schedule_deferred(vb);
+#endif
/* And finally, pass up any receive buffers. */
count = DEFAULT_COUNT;
@@ -1460,10 +1503,10 @@ static void handle_hardunderrun(struct work_struct *work)
if (vb->ops->handle_error)
vb->ops->handle_error(vb);
- tasklet_disable(&vb->tasklet);
+ vb_disable_deferred(vb);
setup_descriptors(vb);
start_packet_processing(vb);
- tasklet_enable(&vb->tasklet);
+ vb_enable_deferred(vb);
}
}
@@ -1504,7 +1547,7 @@ vb_isr(int irq, void *dev_id)
schedule_work(&vb->underrun_work);
} else if (HX8 == vb->mode) {
set_bit(VOICEBUS_HARD_UNDERRUN, &vb->flags);
- tasklet_hi_schedule(&vb->tasklet);
+ vb_schedule_deferred(vb);
__vb_setctl(vb, SR_CSR5, int_status);
}
} else if (likely(int_status &
@@ -1512,7 +1555,7 @@ vb_isr(int irq, void *dev_id)
/* ******************************************************** */
/* NORMAL INTERRUPT CASE */
/* ******************************************************** */
- tasklet_hi_schedule(&vb->tasklet);
+ vb_schedule_deferred(vb);
__vb_setctl(vb, SR_CSR5, TX_COMPLETE_INTERRUPT|RX_COMPLETE_INTERRUPT);
} else {
if (int_status & FATAL_BUS_ERROR_INTERRUPT)
diff --git a/drivers/dahdi/voicebus/voicebus.h b/drivers/dahdi/voicebus/voicebus.h
index 37b9271..6c67f15 100644
--- a/drivers/dahdi/voicebus/voicebus.h
+++ b/drivers/dahdi/voicebus/voicebus.h
@@ -58,6 +58,10 @@
/* Define this in order to create a debugging network interface. */
#undef VOICEBUS_NET_DEBUG
+/* Define this to only run the processing in an interrupt handler
+ * (and not tasklet). */
+#define CONFIG_VOICEBUS_INTERRUPT
+
struct voicebus;
struct vbb {
@@ -123,6 +127,10 @@ struct voicebus {
struct tasklet_struct tasklet;
enum voicebus_mode mode;
+#if defined(CONFIG_VOICEBUS_INTERRUPT)
+ atomic_t deferred_disabled_count;
+#endif
+
#if defined(CONFIG_VOICEBUS_TIMER)
struct timer_list timer;
#endif