summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorian <ian@FreeBSD.org>2014-04-02 15:56:11 +0000
committerian <ian@FreeBSD.org>2014-04-02 15:56:11 +0000
commit2b2f1d5e5ca561f2d22a5740eb522aba203a4bd9 (patch)
treeb1adbca49b6597be5e6a864372592ed31819c399
parent3c7cca5de7a2a252aa6ffad5160d5b0d3def5ae4 (diff)
downloadFreeBSD-src-2b2f1d5e5ca561f2d22a5740eb522aba203a4bd9.zip
FreeBSD-src-2b2f1d5e5ca561f2d22a5740eb522aba203a4bd9.tar.gz
Add support for event timers whose clock frequency can change while running.
-rw-r--r--share/man/man9/eventtimers.919
-rw-r--r--sys/kern/kern_clocksource.c19
-rw-r--r--sys/kern/kern_et.c12
-rw-r--r--sys/sys/systm.h2
-rw-r--r--sys/sys/timeet.h1
5 files changed, 52 insertions, 1 deletions
diff --git a/share/man/man9/eventtimers.9 b/share/man/man9/eventtimers.9
index b43bc49..0c28d76 100644
--- a/share/man/man9/eventtimers.9
+++ b/share/man/man9/eventtimers.9
@@ -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 the current CPU.
.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
diff --git a/sys/kern/kern_clocksource.c b/sys/kern/kern_clocksource.c
index 8855293..fab3119 100644
--- a/sys/kern/kern_clocksource.c
+++ b/sys/kern/kern_clocksource.c
@@ -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)
diff --git a/sys/kern/kern_et.c b/sys/kern/kern_et.c
index d07316c..f64bef5 100644
--- a/sys/kern/kern_et.c
+++ b/sys/kern/kern_et.c
@@ -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 *
diff --git a/sys/sys/systm.h b/sys/sys/systm.h
index ac15568..0f2732c 100644
--- a/sys/sys/systm.h
+++ b/sys/sys/systm.h
@@ -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;
diff --git a/sys/sys/timeet.h b/sys/sys/timeet.h
index 23a170c..728578b 100644
--- a/sys/sys/timeet.h
+++ b/sys/sys/timeet.h
@@ -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,
OpenPOWER on IntegriCloud