Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 2 Apr 2014 15:56:11 +0000 (UTC)
From:      Ian Lepore <ian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r264041 - in head: share/man/man9 sys/kern sys/sys
Message-ID:  <201404021556.s32FuB88046873@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ian
Date: Wed Apr  2 15:56:11 2014
New Revision: 264041
URL: http://svnweb.freebsd.org/changeset/base/264041

Log:
  Add support for event timers whose clock frequency can change while running.

Modified:
  head/share/man/man9/eventtimers.9
  head/sys/kern/kern_clocksource.c
  head/sys/kern/kern_et.c
  head/sys/sys/systm.h
  head/sys/sys/timeet.h

Modified: head/share/man/man9/eventtimers.9
==============================================================================
--- head/share/man/man9/eventtimers.9	Wed Apr  2 15:32:44 2014	(r264040)
+++ head/share/man/man9/eventtimers.9	Wed Apr  2 15:56:11 2014	(r264041)
@@ -24,7 +24,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd February 25, 2013
+.Dd April 2, 2014
 .Dt EVENTTIMERS 9
 .Os
 .Sh NAME
@@ -68,6 +68,8 @@ struct eventtimer {
 .Fn et_register "struct eventtimer *et"
 .Ft int
 .Fn et_deregister "struct eventtimer *et"
+.Ft void
+.Fn et_change_frequency "struct eventtimer *et" "uint64_t newfreq"
 .Fn ET_LOCK
 .Fn ET_UNLOCK
 .Ft struct eventtimer *
@@ -176,6 +178,21 @@ methods control timers associated with t
 .Pp
 Driver may deregister its functionality by calling
 .Fn et_deregister .
+.Pp
+If the frequency of the clock hardware can change while it is 
+running (for example, during power-saving modes), the driver must call
+.Fn et_change_frequency
+on each change.
+If the given event timer is the active timer,
+.Fn et_change_frequency
+stops the timer on all CPUs, updates 
+.Va et->frequency ,
+then restarts the timer on all CPUs so that all
+current events are rescheduled using the new frequency.
+If the given timer is not currently active,
+.Fn et_change_frequency
+simply updates
+.Va et->frequency .
 .Sh CONSUMER API
 .Fn et_find
 allows consumer to find available event timer, optionally matching specific

Modified: head/sys/kern/kern_clocksource.c
==============================================================================
--- head/sys/kern/kern_clocksource.c	Wed Apr  2 15:32:44 2014	(r264040)
+++ head/sys/kern/kern_clocksource.c	Wed Apr  2 15:56:11 2014	(r264041)
@@ -799,6 +799,25 @@ cpu_activeclock(void)
 	spinlock_exit();
 }
 
+/*
+ * Change the frequency of the given timer.  This changes et->et_frequency and
+ * if et is the active timer it reconfigures the timer on all CPUs.  This is
+ * intended to be a private interface for the use of et_change_frequency() only.
+ */
+void
+cpu_et_frequency(struct eventtimer *et, uint64_t newfreq)
+{
+
+	ET_LOCK();
+	if (et == timer) {
+		configtimer(0);
+		et->et_frequency = newfreq;
+		configtimer(1);
+	} else
+		et->et_frequency = newfreq;
+	ET_UNLOCK();
+}
+
 #ifdef KDTRACE_HOOKS
 void
 clocksource_cyc_set(const struct bintime *bt)

Modified: head/sys/kern/kern_et.c
==============================================================================
--- head/sys/kern/kern_et.c	Wed Apr  2 15:32:44 2014	(r264040)
+++ head/sys/kern/kern_et.c	Wed Apr  2 15:56:11 2014	(r264041)
@@ -113,6 +113,18 @@ et_deregister(struct eventtimer *et)
 }
 
 /*
+ * Change the frequency of the given timer.  If it is the active timer,
+ * reconfigure it on all CPUs (reschedules all current events based on the new
+ * timer frequency).
+ */
+void
+et_change_frequency(struct eventtimer *et, uint64_t newfreq)
+{
+
+	cpu_et_frequency(et, newfreq);
+}
+
+/*
  * Find free event timer hardware with specified parameters.
  */
 struct eventtimer *

Modified: head/sys/sys/systm.h
==============================================================================
--- head/sys/sys/systm.h	Wed Apr  2 15:32:44 2014	(r264040)
+++ head/sys/sys/systm.h	Wed Apr  2 15:56:11 2014	(r264041)
@@ -168,6 +168,7 @@ struct ucred;
 struct uio;
 struct _jmp_buf;
 struct trapframe;
+struct eventtimer;
 
 int	setjmp(struct _jmp_buf *) __returns_twice;
 void	longjmp(struct _jmp_buf *, int) __dead2;
@@ -286,6 +287,7 @@ void	cpu_stopprofclock(void);
 sbintime_t 	cpu_idleclock(void);
 void	cpu_activeclock(void);
 void	cpu_new_callout(int cpu, sbintime_t bt, sbintime_t bt_opt);
+void	cpu_et_frequency(struct eventtimer *et, uint64_t newfreq);
 extern int	cpu_can_deep_sleep;
 extern int	cpu_disable_deep_sleep;
 

Modified: head/sys/sys/timeet.h
==============================================================================
--- head/sys/sys/timeet.h	Wed Apr  2 15:32:44 2014	(r264040)
+++ head/sys/sys/timeet.h	Wed Apr  2 15:56:11 2014	(r264041)
@@ -89,6 +89,7 @@ extern struct mtx	et_eventtimers_mtx;
 /* Driver API */
 int	et_register(struct eventtimer *et);
 int	et_deregister(struct eventtimer *et);
+void	et_change_frequency(struct eventtimer *et, uint64_t newfreq);
 /* Consumer API  */
 struct eventtimer *et_find(const char *name, int check, int want);
 int	et_init(struct eventtimer *et, et_event_cb_t *event,



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201404021556.s32FuB88046873>