[zaptel-commits] tzafrir: branch 1.4 r3038 - /branches/1.4/ztdummy.c

SVN commits to the Zaptel project zaptel-commits at lists.digium.com
Sat Sep 15 15:21:03 CDT 2007


Author: tzafrir
Date: Sat Sep 15 15:21:02 2007
New Revision: 3038

URL: http://svn.digium.com/view/zaptel?view=rev&rev=3038
Log:
Include support for high-resolution timers for linux >= 2.6.22 (#10314).

Changes from the patch:
* Only support kernels >= 2.6.22, as hrtimer_forward is only exported as
  of that version.
* Adapted to my recent changes in ztdummy.c .
* Use ZAPTEL_TIME_NS instead of ZAPTEL_RATE
* Simplified ticks debug statement. Will only be used if debug=2 or
  debug=3 .

Modified:
    branches/1.4/ztdummy.c

Modified: branches/1.4/ztdummy.c
URL: http://svn.digium.com/view/zaptel/branches/1.4/ztdummy.c?view=diff&rev=3038&r1=3037&r2=3038
==============================================================================
--- branches/1.4/ztdummy.c (original)
+++ branches/1.4/ztdummy.c Sat Sep 15 15:21:02 2007
@@ -8,6 +8,8 @@
  * Unified by Mark Spencer <markster at digium.com>
  * Converted to use RTC on i386 by Tony Mountifield <tony at softins.co.uk>
  *
+ * Converted to use HighResTimers on i386 by Jeffery Palmer <jeff at triggerinc.com>
+ *
  * Copyright (C) 2002, Hermes Softlab
  * Copyright (C) 2004, Digium, Inc.
  *
@@ -28,6 +30,14 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  */
+
+/*
+ * To use the high resolution timers, in your kernel CONFIG_HIGH_RES_TIMERS 
+ * needs to be enabled (Processor type and features -> High Resolution 
+ * Timer Support), and optionally HPET (Processor type and features -> 
+ * HPET Timer Support) provides a better clock source.
+ */
+
 #include <linux/version.h>
 
 #ifndef VERSION_CODE
@@ -46,7 +56,12 @@
  */
 #if defined(__i386__) || defined(__x86_64__)
 #if LINUX_VERSION_CODE >= VERSION_CODE(2,6,13)
+/* The symbol hrtimer_forward is only exported as of 2.6.22: */
+#if defined(CONFIG_HIGH_RES_TIMERS) && LINUX_VERSION_CODE >= VERSION_CODE(2,6,22)
+#define USE_HIGHRESTIMER
+#else
 #define USE_RTC
+#endif
 #else
 #if 0
 #define USE_RTC
@@ -70,6 +85,9 @@
 #include <asm/io.h>
 #endif
 #ifdef LINUX26
+#ifdef USE_HIGHRESTIMER
+#include <linux/hrtimer.h>
+#endif
 #ifdef USE_RTC
 #include <linux/rtc.h>
 #endif
@@ -83,16 +101,19 @@
 static int debug = 0;
 
 #ifdef LINUX26
-#ifdef USE_RTC
+#ifdef USE_HIGHRESTIMER
+#define ZTDUMMY_TYPE "HRtimer"
+struct hrtimer zaptimer;
+#elif defined(USE_RTC)
 #define ZTDUMMY_TYPE "RTC"
 static int rtc_rate = 0;
 static int current_rate = 0;
 static int taskletpending = 0;
 static struct tasklet_struct ztd_tlet;
 static void ztd_tasklet(unsigned long data);
-#else /* ifndef USE_RTC */
+#else /* Linux 2.6, but no RTC or HRTIMER used */
 #define ZTDUMMY_TYPE "Linux26"
-/* New 2.6 kernel timer stuff */
+/* 2.6 kernel timer stuff */
 static struct timer_list timer;
 #endif
 #else
@@ -121,6 +142,12 @@
 
 #define ZAPTEL_RATE 1000                     /* zaptel ticks per second */
 #define ZAPTEL_TIME (1000000 / ZAPTEL_RATE)  /* zaptel tick time in us */
+#define ZAPTEL_TIME_NS (ZAPTEL_TIME * 1000)  /* zaptel tick time in ns */
+
+/* Different bits of the debug variable: */
+#define DEBUG_GENERAL (1 << 0)
+#define DEBUG_TICKS   (1 << 1)
+
 
 #ifdef LINUX26
 #ifdef USE_RTC
@@ -164,6 +191,38 @@
 		zt_transmit(&ztd->span);
 	}
 	spin_unlock_irqrestore(&ztd->rtclock, flags);
+}
+#elif defined(USE_HIGHRESTIMER)
+static enum hrtimer_restart ztdummy_hr_int(struct hrtimer *htmr)
+{
+	unsigned long overrun;
+	
+	/* Trigger Zaptel */
+	zt_receive(&ztd->span);
+	zt_transmit(&ztd->span);
+
+	/* Overrun should always return 1, since we are in the timer that 
+	 * expired.
+	 * We should worry if overrun is 2 or more; then we really missed 
+	 * a tick */
+	overrun = hrtimer_forward(&zaptimer, htmr->expires, 
+			ktime_set(0, ZAPTEL_TIME_NS));
+	if(overrun > 1) {
+		if(printk_ratelimit())
+			printk(KERN_NOTICE "ztdummy: HRTimer missed %lu ticks\n", 
+					overrun - 1);
+	}
+
+	if(debug && DEBUG_TICKS) {
+		static int count = 0;
+		/* Printk every 5 seconds, good test to see if timer is 
+		 * running properly */
+		if (count++ % 5000 == 0)
+			printk(KERN_DEBUG "ztdummy: 5000 ticks from hrtimer\n");
+	}
+
+	/* Always restart the timer */
+	return HRTIMER_RESTART;
 }
 #else
 /* use kernel system tick timer if PC architecture RTC is not available */
@@ -276,6 +335,17 @@
 	update_rtc_rate(ztd);
 	rtc_control(&ztd->rtc_task, RTC_PIE_ON, 0);
 	tasklet_init(&ztd_tlet, ztd_tasklet, 0);
+#elif defined(USE_HIGHRESTIMER)
+	printk("ztdummy: Trying to load High Resolution Timer\n");
+	hrtimer_init(&zaptimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+	printk("ztdummy: Initialized High Resolution Timer\n");
+
+	/* Set timer callback function */
+	zaptimer.function = ztdummy_hr_int;
+
+	printk("ztdummy: Starting High Resolution Timer\n");
+	hrtimer_start(&zaptimer, ktime_set(0, ZAPTEL_TIME_NS), HRTIMER_MODE_REL);
+	printk("ztdummy: High Resolution Timer started, good to go\n");
 #else
 	init_timer(&timer);
 	timer.function = ztdummy_timer;
@@ -320,6 +390,9 @@
 	}
 	rtc_control(&ztd->rtc_task, RTC_PIE_OFF, 0);
 	rtc_unregister(&ztd->rtc_task);
+#elif defined(USE_HIGHRESTIMER)
+	/* Stop high resolution timer */
+	hrtimer_cancel(&zaptimer);
 #else
 	del_timer(&timer);
 #endif




More information about the zaptel-commits mailing list