From 8239ad02390c0feec4c726160b7519f04caf25b9 Mon Sep 17 00:00:00 2001 From: markster Date: Mon, 16 Aug 2004 17:27:12 +0000 Subject: Merge Paul Cadach's TDMoE fixes for using tasklet (Thanks!) git-svn-id: http://svn.digium.com/svn/zaptel/trunk@450 5390a7c7-147a-4af0-8ec9-7488f05a26cb --- ztdynamic.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 69 insertions(+), 4 deletions(-) (limited to 'ztdynamic.c') diff --git a/ztdynamic.c b/ztdynamic.c index 90aa4fa..3515e16 100755 --- a/ztdynamic.c +++ b/ztdynamic.c @@ -31,6 +31,7 @@ #include #include #include +#include #ifdef CONFIG_DEVFS_FS #include #endif @@ -40,6 +41,16 @@ #include #endif +/* + * Tasklets provide better system interactive response at the cost of the + * possibility of losing a frame of data at very infrequent intervals. If + * you are more concerned with the performance of your machine, enable the + * tasklets. If you are strict about absolutely no drops, then do not enable + * tasklets. + */ + +#define ENABLE_TASKLETS + /* * Dynamic spans implemented using TDM over X with standard message * types. Message format is as follows: @@ -74,6 +85,18 @@ EXPORT_SYMBOL(zt_dynamic_register); EXPORT_SYMBOL(zt_dynamic_unregister); EXPORT_SYMBOL(zt_dynamic_receive); +#ifdef ENABLE_TASKLETS +static int taskletrun; +static int taskletsched; +static int taskletpending; +static int taskletexec; +static int txerrors; +static struct tasklet_struct ztd_tlet; + +static void ztd_tasklet(unsigned long data); +#endif + + static struct zt_dynamic { char addr[40]; char dname[20]; @@ -189,15 +212,15 @@ static void ztd_sendmessage(struct zt_dynamic *z) for (x=0;xspan.channels;x++) { memcpy(buf, z->chans[x].writechunk, ZT_CHUNKSIZE); - buf += 8; - msglen += 8; + buf += ZT_CHUNKSIZE; + msglen += ZT_CHUNKSIZE; } z->driver->transmit(z->pvt, z->msgbuf, msglen); } -static void ztdynamic_run(void) +static void __ztdynamic_run(void) { unsigned long flags; struct zt_dynamic *z; @@ -221,6 +244,21 @@ static void ztdynamic_run(void) spin_unlock_irqrestore(&dlock, flags); } +#ifdef ENABLE_TASKLETS +static void ztdynamic_run(void) +{ + if (!taskletpending) { + taskletpending = 1; + taskletsched++; + tasklet_hi_schedule(&ztd_tlet); + } else { + txerrors++; + } +} +#else +#define ztdynamic_run __ztdynamic_run +#endif + void zt_dynamic_receive(struct zt_span *span, unsigned char *msg, int msglen) { struct zt_dynamic *ztd = span->pvt; @@ -409,6 +447,12 @@ static int destroy_dynamic(ZT_DYNAMIC_SPAN *zds) spin_unlock_irqrestore(&dlock, flags); return -EINVAL; } + /* Don't destroy span until it is in use */ + if (z->usecount) { + spin_unlock_irqrestore(&dlock, flags); + printk("Attempt to destroy dynamic span while it is in use\n"); + return -EBUSY; + } /* Unlink it */ cur = dspans; while(cur) { @@ -563,7 +607,7 @@ static int create_dynamic(ZT_DYNAMIC_SPAN *zds) spin_unlock_irqrestore(&dlock, flags); sprintf(fn, "ztd-%s", zds->driver); request_module(fn); - spin_unlock_irqrestore(&dlock, flags); + spin_lock_irqsave(&dlock, flags); ztd = find_driver(zds->driver); } spin_unlock_irqrestore(&dlock, flags); @@ -608,6 +652,18 @@ static int create_dynamic(ZT_DYNAMIC_SPAN *zds) } +#ifdef ENABLE_TASKLETS +static void ztd_tasklet(unsigned long data) +{ + taskletrun++; + if (taskletpending) { + taskletexec++; + __ztdynamic_run(); + } + taskletpending = 0; +} +#endif + static int ztdynamic_ioctl(unsigned int cmd, unsigned long data) { ZT_DYNAMIC_SPAN zds; @@ -741,12 +797,21 @@ int ztdynamic_init(void) alarmcheck.function = check_for_red_alarm; /* Check once per second */ mod_timer(&alarmcheck, jiffies + 1 * HZ); +#ifdef ENABLE_TASKLETS + tasklet_init(&ztd_tlet, ztd_tasklet, 0); +#endif printk("Zaptel Dynamic Span support LOADED\n"); return 0; } void ztdynamic_cleanup(void) { +#ifdef ENABLE_TASKLETS + if (taskletpending) { + tasklet_disable(&ztd_tlet); + tasklet_kill(&ztd_tlet); + } +#endif zt_set_dynamic_ioctl(NULL); del_timer(&alarmcheck); printk("Zaptel Dynamic Span support unloaded\n"); -- cgit v1.2.3