[Asterisk-cvs] zaptel ztd-eth.c,1.7,1.8 ztdynamic.c,1.6,1.7

markster at lists.digium.com markster at lists.digium.com
Mon Aug 16 13:41:06 CDT 2004


Update of /usr/cvsroot/zaptel
In directory localhost.localdomain:/tmp/cvs-serv5495

Modified Files:
	ztd-eth.c ztdynamic.c 
Log Message:
Merge Paul Cadach's TDMoE fixes for using tasklet (Thanks!)


Index: ztd-eth.c
===================================================================
RCS file: /usr/cvsroot/zaptel/ztd-eth.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- ztd-eth.c	16 Aug 2004 04:08:29 -0000	1.7
+++ ztd-eth.c	16 Aug 2004 17:27:12 -0000	1.8
@@ -134,32 +134,41 @@
 	struct sk_buff *skb;
 	struct ztdeth_header *zh;
 	unsigned long flags;
+	struct net_device *dev;
+	unsigned char addr[ETH_ALEN];
+	unsigned short subaddr; /* Network byte order */
 
 	spin_lock_irqsave(&zlock, flags);
 	z = pvt;
 	if (z->dev) {
-		skb = dev_alloc_skb(msglen + z->dev->hard_header_len + sizeof(struct ztdeth_header) + 32);
+		/* Copy fields to local variables to remove spinlock ASAP */
+		dev = z->dev;
+		memcpy(addr, z->addr, sizeof(z->addr));
+		subaddr = z->subaddr;
+		spin_unlock_irqrestore(&zlock, flags);
+		skb = dev_alloc_skb(msglen + dev->hard_header_len + sizeof(struct ztdeth_header) + 32);
 		if (skb) {
 			/* Reserve header space */
-			skb_reserve(skb, z->dev->hard_header_len + sizeof(struct ztdeth_header));
+			skb_reserve(skb, dev->hard_header_len + sizeof(struct ztdeth_header));
 
 			/* Copy message body */
 			memcpy(skb_put(skb, msglen), msg, msglen);
 
 			/* Throw on header */
 			zh = (struct ztdeth_header *)skb_push(skb, sizeof(struct ztdeth_header));
-			zh->subaddr = z->subaddr;
+			zh->subaddr = subaddr;
 
 			/* Setup protocol and such */
 			skb->protocol = __constant_htons(ETH_P_ZTDETH);
 			skb->nh.raw = skb->data;
-			skb->dev = z->dev;
-			if (z->dev->hard_header)
-				z->dev->hard_header(skb, z->dev, ETH_P_ZTDETH, z->addr, z->dev->dev_addr, skb->len);
+			skb->dev = dev;
+			if (dev->hard_header)
+				dev->hard_header(skb, dev, ETH_P_ZTDETH, addr, dev->dev_addr, skb->len);
 			dev_queue_xmit(skb);
 		}
 	}
-	spin_unlock_irqrestore(&zlock, flags);
+	else
+		spin_unlock_irqrestore(&zlock, flags);
 	return 0;
 }
 
@@ -245,6 +254,13 @@
 		cur = cur->next;
 	}
 	spin_unlock_irqrestore(&zlock, flags);
+	if (cur == z) {	/* Successfully removed */
+		printk("TDMoE: Removed interface for %s\n", z->span->name);
+		kfree(z);
+#ifndef LINUX26
+		MOD_DEC_USE_COUNT;
+#endif
+	}
 }
 
 static void *ztdeth_create(struct zt_span *span, char *addr)
@@ -341,6 +357,9 @@
 		z->next = zdevs;
 		zdevs = z;
 		spin_unlock_irqrestore(&zlock, flags);
+#ifndef LINUX26
+		MOD_INC_USE_COUNT;
+#endif
 	}
 	return z;
 }
@@ -372,5 +391,11 @@
 	zt_dynamic_unregister(&ztd_eth);
 }
 
+MODULE_DESCRIPTION("Zaptel Dynamic TDMoE Support");
+MODULE_AUTHOR("Mark Spencer <markster at linux-support.net>");
+#ifdef MODULE_LICENSE
+MODULE_LICENSE("GPL");
+#endif
+
 module_init(ztdeth_init);
 module_exit(ztdeth_exit);

Index: ztdynamic.c
===================================================================
RCS file: /usr/cvsroot/zaptel/ztdynamic.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- ztdynamic.c	6 Jan 2004 13:26:44 -0000	1.6
+++ ztdynamic.c	16 Aug 2004 17:27:12 -0000	1.7
@@ -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_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 @@
 	
 	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 @@
 	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 @@
 		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 @@
 		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 @@
 
 }
 
+#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 @@
 	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");




More information about the svn-commits mailing list