svn commit: r212812 - head/sys/x86/isa
Alexander Motin
mav at FreeBSD.org
Sat Sep 18 07:36:43 UTC 2010
Author: mav
Date: Sat Sep 18 07:36:43 2010
New Revision: 212812
URL: http://svn.freebsd.org/changeset/base/212812
Log:
Restore pre-r212778 optimization, skipping timer reprogramming when it is
not neccessary. It allows to avoid time counter jump of up to 1/18s, when
base frequency slightly tuned via machdep.i8254_freq sysctl.
Fix few style things.
Suggested by: bde
Modified:
head/sys/x86/isa/clock.c
Modified: head/sys/x86/isa/clock.c
==============================================================================
--- head/sys/x86/isa/clock.c Sat Sep 18 07:18:30 2010 (r212811)
+++ head/sys/x86/isa/clock.c Sat Sep 18 07:36:43 2010 (r212812)
@@ -124,6 +124,8 @@ struct attimer_softc {
};
static struct attimer_softc *attimer_sc = NULL;
+static int timer0_period = -2;
+
/* Values for timerX_state: */
#define RELEASED 0
#define RELEASE_PENDING 1
@@ -367,36 +369,41 @@ DELAY(int n)
static void
set_i8254_freq(int mode, uint32_t period)
{
- int val;
+ int new_count;
mtx_lock_spin(&clock_lock);
- if (period == 0)
- val = 0x10000;
- else
- val = min(((uint64_t)i8254_freq * period) >> 32, 0x10000);
- if (val == 0x10000)
- i8254_max_count = 0xffff;
- else
- i8254_max_count = val;
- if (mode == MODE_STOP && i8254_timecounter)
- mode = MODE_PERIODIC;
+ if (mode == MODE_STOP) {
+ if (i8254_timecounter) {
+ mode = MODE_PERIODIC;
+ new_count = 0x10000;
+ } else
+ new_count = -1;
+ } else {
+ new_count = min(((uint64_t)i8254_freq * period +
+ 0x80000000LLU) >> 32, 0x10000);
+ }
+ if (new_count == timer0_period)
+ goto out;
+ i8254_max_count = ((new_count & ~0xffff) != 0) ? 0xffff : new_count;
+ timer0_period = (mode == MODE_PERIODIC) ? new_count : -1;
switch (mode) {
case MODE_STOP:
outb(TIMER_MODE, TIMER_SEL0 | TIMER_INTTC | TIMER_16BIT);
- outb(TIMER_CNTR0, 0xff);
- outb(TIMER_CNTR0, 0xff);
+ outb(TIMER_CNTR0, 0);
+ outb(TIMER_CNTR0, 0);
break;
case MODE_PERIODIC:
outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT);
- outb(TIMER_CNTR0, val & 0xff);
- outb(TIMER_CNTR0, val >> 8);
+ outb(TIMER_CNTR0, new_count & 0xff);
+ outb(TIMER_CNTR0, new_count >> 8);
break;
case MODE_ONESHOT:
outb(TIMER_MODE, TIMER_SEL0 | TIMER_INTTC | TIMER_16BIT);
- outb(TIMER_CNTR0, val & 0xff);
- outb(TIMER_CNTR0, val >> 8);
+ outb(TIMER_CNTR0, new_count & 0xff);
+ outb(TIMER_CNTR0, new_count >> 8);
break;
}
+out:
mtx_unlock_spin(&clock_lock);
}
@@ -404,7 +411,8 @@ static void
i8254_restore(void)
{
- if (attimer_sc)
+ timer0_period = -2;
+ if (attimer_sc != NULL)
set_i8254_freq(attimer_sc->mode, attimer_sc->period);
else
set_i8254_freq(0, 0);
@@ -473,7 +481,7 @@ sysctl_machdep_i8254_freq(SYSCTL_HANDLER
error = sysctl_handle_int(oidp, &freq, 0, req);
if (error == 0 && req->newptr != NULL) {
i8254_freq = freq;
- if (attimer_sc) {
+ if (attimer_sc != NULL) {
set_i8254_freq(attimer_sc->mode, attimer_sc->period);
attimer_sc->tc.tc_frequency = freq;
} else {
More information about the svn-src-head
mailing list