Date: Thu, 27 Mar 2014 13:07:03 -0600 From: Ian Lepore <ian@FreeBSD.org> To: freebsd-arch <freebsd-arch@FreeBSD.org> Subject: Supporting variable-frequency event timers Message-ID: <1395947223.81853.121.camel@revolution.hippie.lan>
next in thread | raw e-mail | index | archive | help
--=-6fkTI/i94V3xVMnPriRG Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Increasingly, ARM systems are using techniques such as dynamic voltage and frequency scaling (DVFS) to save power. Sometimes the frequency changes affect the clocks being used as event timers. I'd like to commit the attached patch which allows an event timer driver to call et_change_frequency() to reconfigure the timer (if it's the active one) on all CPUs when the frequency changes. -- Ian --=-6fkTI/i94V3xVMnPriRG Content-Disposition: inline; filename="eventtimer_varfreq.diff" Content-Type: text/x-patch; name="eventtimer_varfreq.diff"; charset="us-ascii" Content-Transfer-Encoding: 7bit Index: sys/sys/timeet.h =================================================================== --- sys/sys/timeet.h (revision 263112) +++ sys/sys/timeet.h (working copy) @@ -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, Index: sys/sys/systm.h =================================================================== --- sys/sys/systm.h (revision 263112) +++ sys/sys/systm.h (working copy) @@ -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; Index: sys/kern/kern_et.c =================================================================== --- sys/kern/kern_et.c (revision 263112) +++ sys/kern/kern_et.c (working copy) @@ -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 * Index: sys/kern/kern_clocksource.c =================================================================== --- sys/kern/kern_clocksource.c (revision 263112) +++ sys/kern/kern_clocksource.c (working copy) @@ -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) --=-6fkTI/i94V3xVMnPriRG--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?1395947223.81853.121.camel>