From 428b54b9e46c555338dfe36e196ae01a2138b12e Mon Sep 17 00:00:00 2001 From: Shaun Ruffell Date: Wed, 18 Apr 2012 10:58:36 -0500 Subject: [PATCH 1/2] dahdi_dynamic: Use a tasklet for flushing dynamic drivers. Signed-off-by: Shaun Ruffell --- drivers/dahdi/dahdi_dynamic.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/drivers/dahdi/dahdi_dynamic.c b/drivers/dahdi/dahdi_dynamic.c index b9f400f..72fbf5e 100644 --- a/drivers/dahdi/dahdi_dynamic.c +++ b/drivers/dahdi/dahdi_dynamic.c @@ -88,6 +88,8 @@ static int txerrors; static struct tasklet_struct dahdi_dynamic_tlet; static void dahdi_dynamic_tasklet(unsigned long data); +#else +static struct tasklet_struct dahdi_dynamic_flush_tlet; #endif static DEFINE_MUTEX(dspan_mutex); @@ -208,12 +210,25 @@ static void __dahdi_dynamic_run(void) dahdi_dynamic_sendmessage(d); } +#ifdef ENABLE_TASKLETS + /* If tasklets are not enabled, the above section will be called in + * interrupt context and the flushing of each driver will be called in a + * separate tasklet that only handles that. This is necessary since some + * of the dynamic spans need to call functions that require interrupts + * to be enabled but dahdi_transmit / ...sendmessage needs to be called + * each time the masterspan is processed which happens with interrupts + * disabled. + * + */ + tasklet_hi_schedule(&dahdi_dynamic_flush_tlet); +#else list_for_each_entry_rcu(drv, &driver_list, list) { /* Flush any traffic still pending in the driver */ if (drv->flush) { drv->flush(); } } +#endif rcu_read_unlock(); } @@ -708,6 +723,20 @@ static void dahdi_dynamic_tasklet(unsigned long data) } taskletpending = 0; } +#else +static void dahdi_dynamic_flush_tasklet(unsigned long data) +{ + struct dahdi_dynamic_driver *drv; + + rcu_read_lock(); + list_for_each_entry_rcu(drv, &driver_list, list) { + /* Flush any traffic still pending in the driver */ + if (drv->flush) { + drv->flush(); + } + } + rcu_read_unlock(); +} #endif static int dahdi_dynamic_ioctl(unsigned int cmd, unsigned long data) @@ -840,6 +869,8 @@ static int dahdi_dynamic_init(void) mod_timer(&alarmcheck, jiffies + 1 * HZ); #ifdef ENABLE_TASKLETS tasklet_init(&dahdi_dynamic_tlet, dahdi_dynamic_tasklet, 0); +#else + tasklet_init(&dahdi_dynamic_flush_tlet, dahdi_dynamic_flush_tasklet, 0); #endif dahdi_set_dynamic_ops(&dahdi_dynamic_ops); @@ -856,6 +887,9 @@ static void dahdi_dynamic_cleanup(void) tasklet_disable(&dahdi_dynamic_tlet); tasklet_kill(&dahdi_dynamic_tlet); } +#else + tasklet_disable(&dahdi_dynamic_flush_tlet); + tasklet_kill(&dahdi_dynamic_flush_tlet); #endif del_timer_sync(&alarmcheck); /* Must call again in case it was running before and rescheduled -- 1.7.10