From f1172c58e5c06164cfdb29bbf36e40b532e4d554 Mon Sep 17 00:00:00 2001
From: Nate Lawson <njl@FreeBSD.org>
Date: Thu, 12 Jul 2007 17:00:51 +0000
Subject: [PATCH] Fix a bug where the callout might not be initialized before
 being used. Rev 1.9 introduced another path where machclk_freq would be
 initialized before the rest of setup was done (i.e. initializing the
 callout).  Make the one-time initialization a separate function and make
 init_machclk() able to be called multiple times, any time.  We depend on
 tsc_freq first being updated from the highest priority eventhandler, thus we
 run last and call init_machclk() to set machclk_freq.  Also, don't initialize
 static variables to 0.

Tested by:	Eygene Ryabinkin
Approved by:	re
---
 sys/contrib/altq/altq/altq_subr.c | 24 ++++++++++++++++++------
 1 file changed, 18 insertions(+), 6 deletions(-)

diff --git a/sys/contrib/altq/altq/altq_subr.c b/sys/contrib/altq/altq/altq_subr.c
index fb6b91c398d9..c7c2f4a9e765 100644
--- a/sys/contrib/altq/altq/altq_subr.c
+++ b/sys/contrib/altq/altq/altq_subr.c
@@ -887,8 +887,8 @@ write_dsfield(m, pktattr, dsfield)
 #define	MACHCLK_SHIFT	8
 
 int machclk_usepcc;
-u_int32_t machclk_freq = 0;
-u_int32_t machclk_per_tick = 0;
+u_int32_t machclk_freq;
+u_int32_t machclk_per_tick;
 
 #ifdef __alpha__
 #ifdef __FreeBSD__
@@ -911,14 +911,14 @@ tsc_freq_changed(void *arg, const struct cf_level *level, int status)
 		return;
 
 	/* Total setting for this level gives the new frequency in MHz. */
-	machclk_freq = level->total_set.freq * 1000000;
+	init_machclk();
 }
 EVENTHANDLER_DEFINE(cpufreq_post_change, tsc_freq_changed, NULL,
-    EVENTHANDLER_PRI_ANY);
+    EVENTHANDLER_PRI_LAST);
 #endif /* __FreeBSD_version >= 700035 */
 
-void
-init_machclk(void)
+static void
+init_machclk_setup(void)
 {
 #if (__FreeBSD_version >= 600000)
 	callout_init(&tbr_callout, 0);
@@ -941,6 +941,18 @@ init_machclk(void)
 	    tsc_is_broken))
 		machclk_usepcc = 0;
 #endif
+}
+
+void
+init_machclk(void)
+{
+	static int called;
+
+	/* Call one-time initialization function. */
+	if (!called) {
+		init_machclk_setup();
+		called = 1;
+	}
 
 	if (machclk_usepcc == 0) {
 		/* emulate 256MHz using microtime() */