Index: ztd-loc.c
===================================================================
--- ztd-loc.c	(revision 1105)
+++ ztd-loc.c	(working copy)
@@ -255,7 +255,8 @@
 	"Local",
 	ztdlocal_create,
 	ztdlocal_destroy,
-	ztdlocal_transmit
+	ztdlocal_transmit,
+	NULL	/* flush */
 };
 
 /*static*/ int __init ztdlocal_init(void)
Index: ztd-eth.c
===================================================================
--- ztd-eth.c	(revision 1105)
+++ ztd-eth.c	(working copy)
@@ -56,6 +56,8 @@
 static spinlock_t zlock = SPIN_LOCK_UNLOCKED;
 #endif
 
+static struct sk_buff_head skbs;
+
 static struct ztdeth {
 	unsigned char addr[ETH_ALEN];
 	unsigned short subaddr; /* Network byte order */
@@ -171,7 +173,7 @@
 			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);
+			skb_queue_tail(&skbs, skb);
 		}
 	}
 	else
@@ -179,6 +181,18 @@
 	return 0;
 }
 
+
+static int ztdeth_flush(void)
+{
+	struct sk_buff *skb;
+
+	/* Handle all transmissions now */
+	while ((skb = skb_dequeue(&skbs))) {
+		dev_queue_xmit(skb);
+	}
+	return 0;
+}
+
 static struct packet_type ztdeth_ptype = {
 	type: __constant_htons(ETH_P_ZTDETH),		/* Protocol */
 	dev: NULL,					/* Device (NULL = wildcard) */
@@ -376,7 +390,8 @@
 	"Ethernet",
 	ztdeth_create,
 	ztdeth_destroy,
-	ztdeth_transmit
+	ztdeth_transmit,
+	ztdeth_flush
 };
 
 static struct notifier_block ztdeth_nblock = {
@@ -388,6 +403,9 @@
 	dev_add_pack(&ztdeth_ptype);
 	register_netdevice_notifier(&ztdeth_nblock);
 	zt_dynamic_register(&ztd_eth);
+
+	skb_queue_head_init(&skbs);
+
 	return 0;
 }
 
Index: ztdynamic.c
===================================================================
--- ztdynamic.c	(revision 1105)
+++ ztdynamic.c	(working copy)
@@ -132,6 +132,12 @@
 static spinlock_t dlock = SPIN_LOCK_UNLOCKED;
 #endif
 
+#ifdef DEFINE_RWLOCK
+static DEFINE_RWLOCK(drvlock);
+#else
+static rwlock_t drvlock = RW_LOCK_UNLOCKED;
+#endif
+
 static void checkmaster(void)
 {
 	unsigned long flags;
@@ -142,15 +148,13 @@
 	z = dspans;
 	while(z) {
 		if (z->timing) {
-			if (z->timing) {
-				z->master = 0;
-				newhasmaster = 1;
-				if (!z->alarm && (z->timing < best) && !z->dead) {
-					/* If not in alarm and they're
-					   a better timing source, use them */
-					master = z;
-					best = z->timing;
-				}
+			z->master = 0;
+			newhasmaster = 1;
+			if (!z->alarm && (z->timing < best) && !z->dead) {
+				/* If not in alarm and they're
+				   a better timing source, use them */
+				master = z;
+				best = z->timing;
 			}
 		}
 		z = z->next;
@@ -230,6 +234,7 @@
 {
 	unsigned long flags;
 	struct zt_dynamic *z;
+	struct zt_dynamic_driver *drv;
 	int y;
 	spin_lock_irqsave(&dlock, flags);
 	z = dspans;
@@ -248,6 +253,17 @@
 		z = z->next;
 	}
 	spin_unlock_irqrestore(&dlock, flags);
+
+	read_lock(&drvlock);
+	drv = drivers;
+	while(drv) {
+		/* Flush any traffic still pending in the driver */
+		if (drv->flush) {
+			drv->flush();
+		}
+		drv = drv->next;
+	}
+	read_unlock(&drvlock);
 }
 
 #ifdef ENABLE_TASKLETS
@@ -275,7 +291,7 @@
 	int x, bits, sig;
 	int nchans, master;
 	int newalarm;
-	unsigned short rxpos;
+	unsigned short rxpos, rxcnt;
 	
 	
 	spin_lock_irqsave(&dlock, flags);
@@ -373,6 +389,9 @@
 
 	master = ztd->master;
 	
+	rxcnt = ztd->rxcnt;
+	ztd->rxcnt = rxpos+1;
+
 	spin_unlock_irqrestore(&dlock, flags);
 	
 	/* Check for Yellow alarm */
@@ -388,6 +407,10 @@
 	/* Keep track of last received packet */
 	ztd->rxjif = jiffies;
 
+	/* note if we had a missing packet */
+	// if (rxpos != rxcnt)
+	//	printk("Span %s: Expected seq no %d, but received %d instead\n", span->name, rxcnt, rxpos);
+
 	/* If this is our master span, then run everything */
 	if (master)
 		ztdynamic_run();
@@ -710,14 +733,14 @@
 {
 	unsigned long flags;
 	int res = 0;
-	spin_lock_irqsave(&dlock, flags);
+	write_lock_irqsave(&drvlock, flags);
 	if (find_driver(dri->name))
 		res = -1;
 	else {
 		dri->next = drivers;
 		drivers = dri;
 	}
-	spin_unlock_irqrestore(&dlock, flags);
+	write_unlock_irqrestore(&drvlock, flags);
 	return res;
 }
 
@@ -726,7 +749,7 @@
 	struct zt_dynamic_driver *cur, *prev=NULL;
 	struct zt_dynamic *z, *zp, *zn;
 	unsigned long flags;
-	spin_lock_irqsave(&dlock, flags);
+	write_lock_irqsave(&drvlock, flags);
 	cur = drivers;
 	while(cur) {
 		if (cur == dri) {
@@ -739,6 +762,8 @@
 		prev = cur;
 		cur = cur->next;
 	}
+	write_unlock_irqrestore(&drvlock, flags);
+	spin_lock_irqsave(&dlock, flags);
 	z = dspans;
 	zp = NULL;
 	while(z) {
@@ -773,8 +798,8 @@
 	z = dspans;
 	while(z) {
 		newalarm = z->span.alarms & ~ZT_ALARM_RED;
-		/* If nothing received for a minute, consider that RED ALARM */
-		if ((jiffies - z->rxjif) > 1000 / HZ) {
+		/* If nothing received for a second, consider that RED ALARM */
+		if ((jiffies - z->rxjif) > 1 * HZ) {
 			newalarm |= ZT_ALARM_RED;
 			if (z->span.alarms != newalarm) {
 				z->span.alarms = newalarm;
Index: zaptel.h
===================================================================
--- zaptel.h	(revision 1105)
+++ zaptel.h	(working copy)
@@ -1347,6 +1347,9 @@
 	/* Transmit a given message */
 	int (*transmit)(void *tpipe, unsigned char *msg, int msglen);
 
+	/* Flush any pending messages */
+	int (*flush)(void);
+
 	struct zt_dynamic_driver *next;
 };
 


