summaryrefslogtreecommitdiff
path: root/ztdynamic.c
diff options
context:
space:
mode:
authormarkster <markster@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2004-08-16 17:27:12 +0000
committermarkster <markster@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2004-08-16 17:27:12 +0000
commit8239ad02390c0feec4c726160b7519f04caf25b9 (patch)
tree3566504c9c9f3ba77127c954d4f6d46bd565d02e /ztdynamic.c
parente4dfecf0f034a72e26d3cc0fc96b245e191fc553 (diff)
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
Diffstat (limited to 'ztdynamic.c')
-rwxr-xr-xztdynamic.c73
1 files changed, 69 insertions, 4 deletions
diff --git a/ztdynamic.c b/ztdynamic.c
index 90aa4fa..3515e16 100755
--- a/ztdynamic.c
+++ b/ztdynamic.c
@@ -31,6 +31,7 @@
#include <linux/slab.h>
#include <linux/kmod.h>
#include <linux/sched.h>
+#include <linux/interrupt.h>
#ifdef CONFIG_DEVFS_FS
#include <linux/devfs_fs_kernel.h>
#endif
@@ -41,6 +42,16 @@
#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;x<z->span.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");