diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/dahdi/voicebus/voicebus.c | 73 | ||||
-rw-r--r-- | drivers/dahdi/voicebus/voicebus.h | 8 |
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 |