[zaptel-commits] tzafrir: branch tzafrir/syncing r1480 - /team/tzafrir/syncing/xpp/xpp_zap.c

zaptel-commits at lists.digium.com zaptel-commits at lists.digium.com
Sun Sep 24 17:24:14 MST 2006


Author: tzafrir
Date: Sun Sep 24 19:24:13 2006
New Revision: 1480

URL: http://svn.digium.com/view/zaptel?rev=1480&view=rev
Log:
Use the do_sync operation to sync the xpp driver.
* Create a separate dummy XPP_SYNCER span.
* Add "zaptel sync mode" in addition to host sync mode and device sync mode.
* Device will not register as sync master. Added a new kernel parameter to 
  allow setting that (be_zap_master).
* Small cleanup in the init code.
* Still buggy when zaptel sync master is an Astribank.

Modified:
    team/tzafrir/syncing/xpp/xpp_zap.c

Modified: team/tzafrir/syncing/xpp/xpp_zap.c
URL: http://svn.digium.com/view/zaptel/team/tzafrir/syncing/xpp/xpp_zap.c?rev=1480&r1=1479&r2=1480&view=diff
==============================================================================
--- team/tzafrir/syncing/xpp/xpp_zap.c (original)
+++ team/tzafrir/syncing/xpp/xpp_zap.c Sun Sep 24 19:24:13 2006
@@ -67,6 +67,7 @@
 
 DEF_PARM(int, print_dbg, 0, "Print DBG statements");
 DEF_PARM(int, max_queue_len, MAX_QUEUE_LEN, "Maximum Queue Length.");
+DEF_PARM(int, be_zap_master, 1, "Should spans ask to be zaptel sync. source? (0) no, (1) yes, (2) only the first in each span.");
 DEF_PARM(bool, have_sync_bus, 0, "True if all Astribank(TM) devices are connected via a sync-cable");
 DEF_PARM(bool, zap_autoreg, 1, "Register spans automatically (1) or not (0)");
 
@@ -84,6 +85,30 @@
 static int proc_xpd_ztregister_read(char *page, char **start, off_t off, int count, int *eof, void *data);
 static int proc_xpd_ztregister_write(struct file *file, const char __user *buffer, unsigned long count, void *data);
 static void xpd_free(xpd_t *xpd);
+
+
+struct zt_span	xpp_sync_span;
+struct zt_chan	xpp_sync_chan;
+
+/* dummy xpd structure for our span, to allow us being a sync source. */
+struct xpd sync_xpd = {
+	.xpdname = "XPPSYNCER",
+	.channels = 0
+};
+
+/* called by the zaptel sync master span from zt_recieve. */
+int syncer_do_sync(struct zt_span *span)
+{
+	static int counter = 1;
+
+	xpp_tick( (unsigned long)&sync_xpd); /* actually do something */
+	
+	/* print stats visible in the /proc/zaptel file */
+	if ((counter++ %1000) == 0) {
+		snprintf(xpp_sync_span.desc, MAX_SPANDESC, "ticks: %d", counter);
+	}
+	return 0;
+}
 
 static void external_sync(xpd_t *the_xpd)
 {
@@ -134,7 +159,8 @@
 	xpd_t	*the_xpd = (xpd_t *)param;
 	int	i;
 	int	j;
-
+	/* if the_xpd is zaptel sync_master and local sync master is sync_xpd */
+	int	sync_master_only_mode = 0; 
 	if(!the_xpd) {		/* Called from timer */
 #if 0
 		static int rate_limit = 0;
@@ -143,13 +169,18 @@
 #endif
 		mod_timer(&xpp_timer, jiffies + 1);	/* Must be 1KHz rate */
 	}
+	else if ( (sync_master == &sync_xpd) && zt_is_sync_master(&the_xpd->span)) {
+		sync_master_only_mode = 1; /* continue, but only copy your span */
+	}
 	else if(the_xpd != sync_master)
 		return;
+	
 	/* Statistics */
 	if((xpp_timer_count % SAMPLE_TICKS) == 0) {
 		xpp_last_jiffies = jiffies;
 	}
-	xpp_timer_count++;
+	if (!sync_master_only_mode)
+		xpp_timer_count++;
 
 	for(i = 0; i < MAX_BUSES; i++) {
 		xbus = xbus_of(i);
@@ -168,11 +199,33 @@
 		for(j = 0; j < MAX_XPDS; j++) {
 			xpd_t	*xpd = xpd_of(xbus, j);
 
+			/* sanity checks: no point in syncing if we don't have a hardware
+			 * and talk to zaptel
+			 */
 			if(!xpd)
 				continue;
 			if(!xpd->card_present)
 				continue;
+			/* prevent recusrsive calls to sync master. The following two conditions 
+			 * handle the case where one of our spans is the zaptel sync master, 
+			 * whereas the syncer span is the xpp sync master.
+			 * 
+			 * The zaptel sync master will run through xpp_tick but only set 
+			 * zt_recieve for its span. This, in turn, will trigger a call to 
+			 * the sync functions of spans and specifically cause our syncer span 
+			 * to call xpp_tick.
+			 *
+			 * If our syncer span is the zaptel sync source, it will then trigger 
+			 * a full xpp_tick . But we need to make sure it will not trigger the 
+			 * tick of itself again.
+			 */
+			if(sync_master_only_mode && !zt_is_sync_master(&xpd->span))
+				continue;
+			if((the_xpd == &sync_xpd) && (sync_master == &sync_xpd) && 
+					zt_is_sync_master(&xpd->span))
+				continue;
 			xpd->timer_count++;
+			/* actions that need doing before actual data copying */
 			CALL_XMETHOD(card_tick, xbus, xpd);
 			if(!SPAN_REGISTERED(xpd))
 				continue;
@@ -690,6 +743,7 @@
 
 	len += sprintf(page + len, "# To modify sync source write into this file:\n");
 	len += sprintf(page + len, "#     HOST        - For host based sync\n");
+	len += sprintf(page + len, "#     ZAPTEL      - Sync from zaptel sync master\n");
 	len += sprintf(page + len, "#     0 0         - XBUS-0/XPD-0 provide sync\n");
 	len += sprintf(page + len, "#     m n         - XBUS-m/XPD-n provide sync\n");
 	if(!sync_master)
@@ -732,6 +786,10 @@
 	buf[count] = '\0';
 	if(strncmp("HOST", buf, 4) == 0) {
 		sync_master_is(NULL);
+		goto out;
+	} else if (strncmp("ZAPTEL", buf, 6) == 0) {
+		//external_sync(&sync_xpd); /* TODO: rename that function? */
+		sync_master_is(&sync_xpd); 
 		goto out;
 	}
 	ret = sscanf(buf, "%d %d %d", &xbus_num, &xpd_num, &setit);
@@ -1311,6 +1369,7 @@
 	xbus_t		*xbus;
 	int		cn;
 	const xops_t	*xops;
+	int		become_master;
 
 	BUG_ON(!xpd);
 	xops = xpd->xops;
@@ -1353,7 +1412,13 @@
 
 	DBG("Registering span of %s.\n", xpd->xpdname);
 	xpd->xops->card_zaptel_preregistration(xpd, 1);
-	if(zt_register(&xpd->span, 1)) {
+	if ( be_zap_master == 0 )
+		become_master = 0;
+	else if (be_zap_master == 1 )
+		become_master = 1;
+	else /* only first XPD in bus will ask to be zaptel master */
+		become_master = (xpd->id == 0); 
+	if(zt_register(&xpd->span, become_master )) {
 		xbus_t	*xbus = xpd->xbus;
 		ERR("%s/%s: Failed to zt_register span\n", xbus->busname, xpd->xpdname);
 		return -ENODEV;
@@ -1377,8 +1442,17 @@
 
 /*------------------------- Initialization -------------------------*/
 
+static void __exit xpp_syncer_cleanup(void)
+{
+	if (xpp_sync_span.flags & ZT_FLAG_REGISTERED) {
+		zt_unregister(&xpp_sync_span);
+	}
+}
+
 static void do_cleanup(void)
 {
+	xbus_core_shutdown();
+	xpp_syncer_cleanup();
 	if(timer_pending(&xpp_timer))
 		del_timer_sync(&xpp_timer);
 #ifdef CONFIG_PROC_FS
@@ -1392,6 +1466,27 @@
 #endif
 }
 
+static int __init xpp_syncer_init(void)
+{
+	int	ret;
+
+	/* Modified from ztdummy.c */
+	sprintf(xpp_sync_span.name, "XPP_SYNCER/1");
+	snprintf(xpp_sync_span.desc, MAX_SPANDESC, "ticks: nothing.");
+	sprintf(xpp_sync_chan.name, "XPP_SYNCER/%d/%d", 1, 0);
+	xpp_sync_chan.chanpos = 1;
+	xpp_sync_span.chans = &xpp_sync_chan;
+	xpp_sync_span.channels = 0;		/* no channels on our span */
+	xpp_sync_span.deflaw = ZT_LAW_MULAW;
+	init_waitqueue_head(&xpp_sync_span.maintq);
+	xpp_sync_span.do_sync = syncer_do_sync;
+	if ((ret = zt_register(&xpp_sync_span, 0)) < 0) {
+		xpp_syncer_cleanup();
+		return ret;
+	}
+	return 0;
+}
+
 int __init xpp_zap_init(void)
 {
 	int	ret;
@@ -1426,6 +1521,12 @@
 	ent->write_proc = proc_sync_write;
 	ent->data = NULL;
 #endif
+	ret = xpp_syncer_init();
+	if(ret) {
+		ERR("xbus_syncer_init failed (%d)\n", ret);
+		do_cleanup();
+		return ret;
+	}
 	ret = xbus_core_init();
 	if(ret) {
 		ERR("xbus_core_init failed (%d)\n", ret);
@@ -1441,7 +1542,6 @@
 
 void __exit xpp_zap_cleanup(void)
 {
-	xbus_core_shutdown();
 	do_cleanup();
 }
 



More information about the zaptel-commits mailing list