From owner-svn-src-all@FreeBSD.ORG Wed Apr 2 15:56:12 2014 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id E9F18B17; Wed, 2 Apr 2014 15:56:12 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id D5F72235; Wed, 2 Apr 2014 15:56:12 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.8/8.14.8) with ESMTP id s32FuCfc046880; Wed, 2 Apr 2014 15:56:12 GMT (envelope-from ian@svn.freebsd.org) Received: (from ian@localhost) by svn.freebsd.org (8.14.8/8.14.8/Submit) id s32FuB88046873; Wed, 2 Apr 2014 15:56:11 GMT (envelope-from ian@svn.freebsd.org) Message-Id: <201404021556.s32FuB88046873@svn.freebsd.org> From: Ian Lepore Date: Wed, 2 Apr 2014 15:56:11 +0000 (UTC) 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 X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.17 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 02 Apr 2014 15:56:13 -0000 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,