MFcalloutng:

Switch eventtimers(9) from using struct bintime to sbintime_t.
Even before this not a single driver really supported full dynamic range of
struct bintime even in theory, not speaking about practical inexpediency.
This change legitimates the status quo and cleans up the code.
This commit is contained in:
mav 2013-02-28 13:46:03 +00:00
parent 240074414d
commit 6cf7cc6e4d
23 changed files with 207 additions and 370 deletions

View File

@ -1,5 +1,5 @@
.\"
.\" Copyright (c) 2011 Alexander Motin <mav@FreeBSD.org>
.\" Copyright (c) 2011-2013 Alexander Motin <mav@FreeBSD.org>
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd December 14, 2011
.Dd February 25, 2013
.Dt EVENTTIMERS 9
.Os
.Sh NAME
@ -36,7 +36,7 @@
struct eventtimer;
typedef int et_start_t(struct eventtimer *et,
struct bintime *first, struct bintime *period);
sbintime_t first, sbintime_t period);
typedef int et_stop_t(struct eventtimer *et);
typedef void et_event_cb_t(struct eventtimer *et, void *arg);
typedef int et_deregister_cb_t(struct eventtimer *et, void *arg);
@ -53,8 +53,8 @@ struct eventtimer {
int et_quality;
int et_active;
uint64_t et_frequency;
struct bintime et_min_period;
struct bintime et_max_period;
sbintime_t et_min_period;
sbintime_t et_max_period;
et_start_t *et_start;
et_stop_t *et_stop;
et_event_cb_t *et_event_cb;
@ -75,7 +75,7 @@ struct eventtimer {
.Ft int
.Fn et_init "struct eventtimer *et" "et_event_cb_t *event" "et_deregister_cb_t *deregister" "void *arg"
.Ft int
.Fn et_start "struct eventtimer *et" "struct bintime *first" "struct bintime *period"
.Fn et_start "struct eventtimer *et" "sbintime_t first" "sbintime_t period"
.Ft int
.Fn et_stop "struct eventtimer *et"
.Ft int

View File

@ -95,7 +95,7 @@ int a10_timer_get_timerfreq(struct a10_timer_softc *);
static u_int a10_timer_get_timecount(struct timecounter *);
static int a10_timer_timer_start(struct eventtimer *,
struct bintime *, struct bintime *);
sbintime_t first, sbintime_t period);
static int a10_timer_timer_stop(struct eventtimer *);
static uint64_t timer_read_counter64(void);
@ -193,12 +193,8 @@ a10_timer_attach(device_t dev)
sc->et.et_name = "a10_timer Eventtimer";
sc->et.et_flags = ET_FLAGS_ONESHOT | ET_FLAGS_PERIODIC;
sc->et.et_quality = 1000;
sc->et.et_min_period.sec = 0;
sc->et.et_min_period.frac =
((0x00000005LLU << 32) / sc->et.et_frequency) << 32;
sc->et.et_max_period.sec = 0xfffffff0U / sc->et.et_frequency;
sc->et.et_max_period.frac =
((0xfffffffeLLU << 32) / sc->et.et_frequency) << 32;
sc->et.et_min_period = (0x00000005LLU << 32) / sc->et.et_frequency;
sc->et.et_max_period = (0xfffffffeLLU << 32) / sc->et.et_frequency;
sc->et.et_start = a10_timer_timer_start;
sc->et.et_stop = a10_timer_timer_stop;
sc->et.et_priv = sc;
@ -225,8 +221,8 @@ a10_timer_attach(device_t dev)
}
static int
a10_timer_timer_start(struct eventtimer *et, struct bintime *first,
struct bintime *period)
a10_timer_timer_start(struct eventtimer *et, sbintime_t first,
sbintime_t period)
{
struct a10_timer_softc *sc;
uint32_t count;
@ -234,26 +230,21 @@ a10_timer_timer_start(struct eventtimer *et, struct bintime *first,
sc = (struct a10_timer_softc *)et->et_priv;
sc->sc_period = 0;
if (period != NULL) {
sc->sc_period = (sc->et.et_frequency * (period->frac >> 32)) >> 32;
sc->sc_period += sc->et.et_frequency * period->sec;
}
if (first == NULL)
if (period != 0)
sc->sc_period = ((uint32_t)et->et_frequency * period) >> 32;
else
sc->sc_period = 0;
if (first != 0)
count = ((uint32_t)et->et_frequency * first) >> 32;
else
count = sc->sc_period;
else {
count = (sc->et.et_frequency * (first->frac >> 32)) >> 32;
if (first->sec != 0)
count += sc->et.et_frequency * first->sec;
}
/* Update timer values */
timer_write_4(sc, SW_TIMER0_INT_VALUE_REG, sc->sc_period);
timer_write_4(sc, SW_TIMER0_CUR_VALUE_REG, count);
val = timer_read_4(sc, SW_TIMER0_CTRL_REG);
if (first == NULL) {
if (period != 0) {
/* periodic */
val |= TIMER_AUTORELOAD;
} else {

View File

@ -167,31 +167,23 @@ arm_tmr_get_timecount(struct timecounter *tc)
* Always returns 0
*/
static int
arm_tmr_start(struct eventtimer *et, struct bintime *first,
struct bintime *period)
arm_tmr_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
{
struct arm_tmr_softc *sc = (struct arm_tmr_softc *)et->et_priv;
uint32_t load, count;
uint32_t ctrl;
ctrl = PRV_TIMER_CTRL_IRQ_ENABLE | PRV_TIMER_CTRL_TIMER_ENABLE;
if (period != NULL) {
load = (et->et_frequency * (period->frac >> 32)) >> 32;
if (period->sec > 0)
load += et->et_frequency * period->sec;
if (period != 0) {
load = ((uint32_t)et->et_frequency * period) >> 32;
ctrl |= PRV_TIMER_CTRL_AUTO_RELOAD;
} else {
} else
load = 0;
}
if (first != NULL) {
count = (sc->et.et_frequency * (first->frac >> 32)) >> 32;
if (first->sec != 0)
count += sc->et.et_frequency * first->sec;
} else {
if (first != 0)
count = ((uint32_t)et->et_frequency * first) >> 32;
else
count = load;
}
tmr_prv_write_4(PRV_TIMER_LOAD, load);
tmr_prv_write_4(PRV_TIMER_COUNT, count);
@ -330,12 +322,8 @@ arm_tmr_attach(device_t dev)
sc->et.et_quality = 1000;
sc->et.et_frequency = sc->clkfreq;
sc->et.et_min_period.sec = 0;
sc->et.et_min_period.frac =
((0x00000002LLU << 32) / sc->et.et_frequency) << 32;
sc->et.et_max_period.sec = 0xfffffff0U / sc->et.et_frequency;
sc->et.et_max_period.frac =
((0xfffffffeLLU << 32) / sc->et.et_frequency) << 32;
sc->et.et_min_period = (0x00000002LLU << 32) / sc->et.et_frequency;
sc->et.et_max_period = (0xfffffffeLLU << 32) / sc->et.et_frequency;
sc->et.et_start = arm_tmr_start;
sc->et.et_stop = arm_tmr_stop;
sc->et.et_priv = sc;

View File

@ -118,19 +118,16 @@ bcm_systimer_tc_get_timecount(struct timecounter *tc)
}
static int
bcm_systimer_start(struct eventtimer *et, struct bintime *first,
struct bintime *period)
bcm_systimer_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
{
struct systimer *st = et->et_priv;
uint32_t clo;
uint32_t count;
register_t s;
if (first != NULL) {
if (first != 0) {
count = (st->et.et_frequency * (first->frac >> 32)) >> 32;
if (first->sec != 0)
count += st->et.et_frequency * first->sec;
count = ((uint32_t)et->et_frequency * first) >> 32;
s = intr_disable();
clo = bcm_systimer_tc_read_4(SYSTIMER_CLO);
@ -238,12 +235,10 @@ bcm_systimer_attach(device_t dev)
sc->st[DEFAULT_TIMER].et.et_flags = ET_FLAGS_ONESHOT;
sc->st[DEFAULT_TIMER].et.et_quality = 1000;
sc->st[DEFAULT_TIMER].et.et_frequency = sc->sysclk_freq;
sc->st[DEFAULT_TIMER].et.et_min_period.sec = 0;
sc->st[DEFAULT_TIMER].et.et_min_period.frac =
((MIN_PERIOD << 32) / sc->st[DEFAULT_TIMER].et.et_frequency) << 32;
sc->st[DEFAULT_TIMER].et.et_max_period.sec = 0xfffffff0U / sc->st[DEFAULT_TIMER].et.et_frequency;
sc->st[DEFAULT_TIMER].et.et_max_period.frac =
((0xfffffffeLLU << 32) / sc->st[DEFAULT_TIMER].et.et_frequency) << 32;
sc->st[DEFAULT_TIMER].et.et_min_period =
(MIN_PERIOD << 32) / sc->st[DEFAULT_TIMER].et.et_frequency;
sc->st[DEFAULT_TIMER].et.et_max_period =
(0xfffffffeLLU << 32) / sc->st[DEFAULT_TIMER].et.et_frequency;
sc->st[DEFAULT_TIMER].et.et_start = bcm_systimer_start;
sc->st[DEFAULT_TIMER].et.et_stop = bcm_systimer_stop;
sc->st[DEFAULT_TIMER].et.et_priv = &sc->st[DEFAULT_TIMER];

View File

@ -72,8 +72,8 @@ static struct lpc_timer_softc *timer_softc = NULL;
static int lpc_timer_initialized = 0;
static int lpc_timer_probe(device_t);
static int lpc_timer_attach(device_t);
static int lpc_timer_start(struct eventtimer *, struct bintime *first,
struct bintime *);
static int lpc_timer_start(struct eventtimer *,
sbintime_t first, sbintime_t period);
static int lpc_timer_stop(struct eventtimer *et);
static unsigned lpc_get_timecount(struct timecounter *);
static int lpc_hardclock(void *);
@ -173,12 +173,8 @@ lpc_timer_attach(device_t dev)
sc->lt_et.et_name = "LPC32x0 Timer0";
sc->lt_et.et_flags = ET_FLAGS_PERIODIC | ET_FLAGS_ONESHOT;
sc->lt_et.et_quality = 1000;
sc->lt_et.et_min_period.sec = 0;
sc->lt_et.et_min_period.frac =
((0x00000002LLU << 32) / sc->lt_et.et_frequency) << 32;
sc->lt_et.et_max_period.sec = 0xfffffff0U / sc->lt_et.et_frequency;
sc->lt_et.et_max_period.frac =
((0xfffffffeLLU << 32) / sc->lt_et.et_frequency) << 32;
sc->lt_et.et_min_period = (0x00000002LLU << 32) / sc->lt_et.et_frequency;
sc->lt_et.et_max_period = (0xfffffffeLLU << 32) / sc->lt_et.et_frequency;
sc->lt_et.et_start = lpc_timer_start;
sc->lt_et.et_stop = lpc_timer_stop;
sc->lt_et.et_priv = sc;
@ -199,27 +195,23 @@ lpc_timer_attach(device_t dev)
}
static int
lpc_timer_start(struct eventtimer *et, struct bintime *first,
struct bintime *period)
lpc_timer_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
{
struct lpc_timer_softc *sc = (struct lpc_timer_softc *)et->et_priv;
uint32_t ticks;
if (period == NULL)
if (period == 0) {
sc->lt_oneshot = 1;
else {
sc->lt_period = 0;
} else {
sc->lt_oneshot = 0;
sc->lt_period = (sc->lt_et.et_frequency * (first->frac >> 32)) >> 32;
sc->lt_period += sc->lt_et.et_frequency * first->sec;
sc->lt_period = ((uint32_t)et->et_frequency * period) >> 32;
}
if (first == NULL)
if (first == 0)
ticks = sc->lt_period;
else {
ticks = (sc->lt_et.et_frequency * (first->frac >> 32)) >> 32;
if (first->sec != 0)
ticks += sc->lt_et.et_frequency * first->sec;
}
else
ticks = ((uint32_t)et->et_frequency * first) >> 32;
/* Reset timer */
timer0_write_4(sc, LPC_TIMER_TCR, LPC_TIMER_TCR_RESET);

View File

@ -93,7 +93,7 @@ static void mv_watchdog_enable(void);
static void mv_watchdog_disable(void);
static void mv_watchdog_event(void *, unsigned int, int *);
static int mv_timer_start(struct eventtimer *et,
struct bintime *first, struct bintime *period);
sbintime_t first, sbintime_t period);
static int mv_timer_stop(struct eventtimer *et);
static void mv_setup_timers(void);
@ -168,12 +168,8 @@ mv_timer_attach(device_t dev)
sc->et.et_quality = 1000;
sc->et.et_frequency = MV_CLOCK_SRC;
sc->et.et_min_period.sec = 0;
sc->et.et_min_period.frac =
((0x00000002LLU << 32) / sc->et.et_frequency) << 32;
sc->et.et_max_period.sec = 0xfffffff0U / sc->et.et_frequency;
sc->et.et_max_period.frac =
((0xfffffffeLLU << 32) / sc->et.et_frequency) << 32;
sc->et.et_min_period = (0x00000002LLU << 32) / sc->et.et_frequency;
sc->et.et_max_period = (0xfffffffeLLU << 32) / sc->et.et_frequency;
sc->et.et_start = mv_timer_start;
sc->et.et_stop = mv_timer_stop;
sc->et.et_priv = sc;
@ -394,25 +390,20 @@ mv_watchdog_event(void *arg, unsigned int cmd, int *error)
}
static int
mv_timer_start(struct eventtimer *et,
struct bintime *first, struct bintime *period)
mv_timer_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
{
struct mv_timer_softc *sc;
uint32_t val, val1;
/* Calculate dividers. */
sc = (struct mv_timer_softc *)et->et_priv;
if (period != NULL) {
val = (sc->et.et_frequency * (period->frac >> 32)) >> 32;
if (period->sec != 0)
val += sc->et.et_frequency * period->sec;
} else
if (period != 0)
val = ((uint32_t)sc->et.et_frequency * period) >> 32;
else
val = 0;
if (first != NULL) {
val1 = (sc->et.et_frequency * (first->frac >> 32)) >> 32;
if (first->sec != 0)
val1 += sc->et.et_frequency * first->sec;
} else
if (first != 0)
val1 = ((uint32_t)sc->et.et_frequency * first) >> 32;
else
val1 = val;
/* Apply configuration. */
@ -420,7 +411,7 @@ mv_timer_start(struct eventtimer *et,
mv_set_timer(0, val1);
val = mv_get_timer_control();
val |= CPU_TIMER0_EN;
if (period != NULL)
if (period != 0)
val |= CPU_TIMER0_AUTO;
else
val &= ~CPU_TIMER0_AUTO;

View File

@ -143,30 +143,24 @@ am335x_dmtimer_tc_get_timecount(struct timecounter *tc)
}
static int
am335x_dmtimer_start(struct eventtimer *et, struct bintime *first,
struct bintime *period)
am335x_dmtimer_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
{
struct am335x_dmtimer *tmr = (struct am335x_dmtimer *)et->et_priv;
uint32_t load, count;
uint32_t tclr = 0;
if (period != NULL) {
load = (et->et_frequency * (period->frac >> 32)) >> 32;
if (period->sec > 0)
load += et->et_frequency * period->sec;
if (period != 0) {
load = ((uint32_t)et->et_frequency * period) >> 32;
tclr |= 2; /* autoreload bit */
panic("periodic timer not implemented\n");
} else {
load = 0;
}
if (first != NULL) {
count = (tmr->et.et_frequency * (first->frac >> 32)) >> 32;
if (first->sec != 0)
count += tmr->et.et_frequency * first->sec;
} else {
if (first != 0)
count = ((uint32_t)et->et_frequency * first) >> 32;
else
count = load;
}
/* Reset Timer */
am335x_dmtimer_et_write_4(DMTIMER_TSICR, 2);
@ -316,12 +310,10 @@ am335x_dmtimer_attach(device_t dev)
sc->t[3].et.et_flags = ET_FLAGS_PERIODIC | ET_FLAGS_ONESHOT;
sc->t[3].et.et_quality = 1000;
sc->t[3].et.et_frequency = sc->sysclk_freq;
sc->t[3].et.et_min_period.sec = 0;
sc->t[3].et.et_min_period.frac =
((0x00000002LLU << 32) / sc->t[3].et.et_frequency) << 32;
sc->t[3].et.et_max_period.sec = 0xfffffff0U / sc->t[3].et.et_frequency;
sc->t[3].et.et_max_period.frac =
((0xfffffffeLLU << 32) / sc->t[3].et.et_frequency) << 32;
sc->t[3].et.et_min_period =
(0x00000002LLU << 32) / sc->t[3].et.et_frequency;
sc->t[3].et.et_max_period =
(0xfffffffeLLU << 32) / sc->t[3].et.et_frequency;
sc->t[3].et.et_start = am335x_dmtimer_start;
sc->t[3].et.et_stop = am335x_dmtimer_stop;
sc->t[3].et.et_priv = &sc->t[3];

View File

@ -120,18 +120,15 @@ sp804_timer_tc_get_timecount(struct timecounter *tc)
}
static int
sp804_timer_start(struct eventtimer *et, struct bintime *first,
struct bintime *period)
sp804_timer_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
{
struct sp804_timer_softc *sc = et->et_priv;
uint32_t count, reg;
if (first != NULL) {
if (first != 0) {
sc->et_enabled = 1;
count = (sc->et.et_frequency * (first->frac >> 32)) >> 32;
if (first->sec != 0)
count += sc->et.et_frequency * first->sec;
count = ((uint32_t)et->et_frequency * first) >> 32;
sp804_timer_tc_write_4(SP804_TIMER2_LOAD, count);
reg = TIMER_CONTROL_32BIT | TIMER_CONTROL_INTREN |
@ -142,7 +139,7 @@ sp804_timer_start(struct eventtimer *et, struct bintime *first,
return (0);
}
if (period != NULL) {
if (period != 0) {
panic("period");
}
@ -264,12 +261,8 @@ sp804_timer_attach(device_t dev)
sc->et.et_flags = ET_FLAGS_PERIODIC | ET_FLAGS_ONESHOT;
sc->et.et_quality = 1000;
sc->et.et_frequency = sc->sysclk_freq / DEFAULT_DIVISOR;
sc->et.et_min_period.sec = 0;
sc->et.et_min_period.frac =
((0x00000002LLU << 32) / sc->et.et_frequency) << 32;
sc->et.et_max_period.sec = 0xfffffff0U / sc->et.et_frequency;
sc->et.et_max_period.frac =
((0xfffffffeLLU << 32) / sc->et.et_frequency) << 32;
sc->et.et_min_period = (0x00000002LLU << 32) / sc->et.et_frequency;
sc->et.et_max_period = (0xfffffffeLLU << 32) / sc->et.et_frequency;
sc->et.et_start = sp804_timer_start;
sc->et.et_stop = sp804_timer_stop;
sc->et.et_priv = sc;

View File

@ -147,8 +147,7 @@ hpet_disable(struct hpet_softc *sc)
}
static int
hpet_start(struct eventtimer *et,
struct bintime *first, struct bintime *period)
hpet_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
{
struct hpet_timer *mt = (struct hpet_timer *)et->et_priv;
struct hpet_timer *t;
@ -156,20 +155,16 @@ hpet_start(struct eventtimer *et,
uint32_t fdiv, now;
t = (mt->pcpu_master < 0) ? mt : &sc->t[mt->pcpu_slaves[curcpu]];
if (period != NULL) {
if (period != 0) {
t->mode = 1;
t->div = (sc->freq * (period->frac >> 32)) >> 32;
if (period->sec != 0)
t->div += sc->freq * period->sec;
t->div = (sc->freq * period) >> 32;
} else {
t->mode = 2;
t->div = 0;
}
if (first != NULL) {
fdiv = (sc->freq * (first->frac >> 32)) >> 32;
if (first->sec != 0)
fdiv += sc->freq * first->sec;
} else
if (first != 0)
fdiv = (sc->freq * first) >> 32;
else
fdiv = t->div;
if (t->irq < 0)
bus_write_4(sc->mem_res, HPET_ISR, 1 << t->num);
@ -684,12 +679,9 @@ hpet_attach(device_t dev)
if ((t->caps & HPET_TCAP_PER_INT) == 0)
t->et.et_quality -= 10;
t->et.et_frequency = sc->freq;
t->et.et_min_period.sec = 0;
t->et.et_min_period.frac =
(((uint64_t)(HPET_MIN_CYCLES * 2) << 32) / sc->freq) << 32;
t->et.et_max_period.sec = 0xfffffffeLLU / sc->freq;
t->et.et_max_period.frac =
((0xfffffffeLLU << 32) / sc->freq) << 32;
t->et.et_min_period =
((uint64_t)(HPET_MIN_CYCLES * 2) << 32) / sc->freq;
t->et.et_max_period = (0xfffffffeLLU << 32) / sc->freq;
t->et.et_start = hpet_start;
t->et.et_stop = hpet_stop;
t->et.et_priv = &sc->t[i];

View File

@ -768,8 +768,7 @@ resettodr()
#endif
static int
xen_et_start(struct eventtimer *et,
struct bintime *first, struct bintime *period)
xen_et_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
{
struct xen_et_state *state = DPCPU_PTR(et_state);
struct shadow_time_info *shadow;
@ -777,21 +776,16 @@ xen_et_start(struct eventtimer *et,
__get_time_values_from_xen();
if (period != NULL) {
if (period != 0) {
state->mode = MODE_PERIODIC;
state->period = (1000000000LL *
(uint32_t)(period->frac >> 32)) >> 32;
if (period->sec != 0)
state->period += 1000000000LL * period->sec;
state->period = (1000000000LLU * period) >> 32;
} else {
state->mode = MODE_ONESHOT;
state->period = 0;
}
if (first != NULL) {
fperiod = (1000000000LL * (uint32_t)(first->frac >> 32)) >> 32;
if (first->sec != 0)
fperiod += 1000000000LL * first->sec;
} else
if (first != 0)
fperiod = (1000000000LLU * first) >> 32;
else
fperiod = state->period;
shadow = &per_cpu(shadow_time, smp_processor_id());
@ -832,11 +826,9 @@ cpu_initclocks(void)
xen_et.et_flags = ET_FLAGS_PERIODIC | ET_FLAGS_ONESHOT |
ET_FLAGS_PERCPU;
xen_et.et_quality = 600;
xen_et.et_frequency = 0;
xen_et.et_min_period.sec = 0;
xen_et.et_min_period.frac = 0x00400000LL << 32;
xen_et.et_max_period.sec = 2;
xen_et.et_max_period.frac = 0;
xen_et.et_frequency = 1000000000;
xen_et.et_min_period = 0x00400000LL;
xen_et.et_max_period = (0xfffffffeLLU << 32) / xen_et.et_frequency;
xen_et.et_start = xen_et_start;
xen_et.et_stop = xen_et_stop;
xen_et.et_priv = NULL;

View File

@ -105,17 +105,14 @@ ia64_ih_clock(struct thread *td, u_int xiv, struct trapframe *tf)
* Event timer start method.
*/
static int
ia64_clock_start(struct eventtimer *et, struct bintime *first,
struct bintime *period)
ia64_clock_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
{
u_long itc, load;
register_t is;
if (period != NULL) {
if (period != 0) {
PCPU_SET(md.clock_mode, CLOCK_ET_PERIODIC);
load = (et->et_frequency * (period->frac >> 32)) >> 32;
if (period->sec > 0)
load += et->et_frequency * period->sec;
load = (et->et_frequency * period) >> 32;
} else {
PCPU_SET(md.clock_mode, CLOCK_ET_ONESHOT);
load = 0;
@ -123,11 +120,8 @@ ia64_clock_start(struct eventtimer *et, struct bintime *first,
PCPU_SET(md.clock_load, load);
if (first != NULL) {
load = (et->et_frequency * (first->frac >> 32)) >> 32;
if (first->sec > 0)
load += et->et_frequency * first->sec;
}
if (first != 0)
load = (et->et_frequency * first) >> 32;
is = intr_disable();
itc = ia64_get_itc();
@ -185,10 +179,8 @@ clock_configure(void *dummy)
et->et_flags = ET_FLAGS_PERIODIC | ET_FLAGS_ONESHOT | ET_FLAGS_PERCPU;
et->et_quality = 1000;
et->et_frequency = itc_freq;
et->et_min_period.sec = 0;
et->et_min_period.frac = (0x8000000000000000ul / (u_long)(10*hz)) << 1;
et->et_max_period.sec = 0xffffffff;
et->et_max_period.frac = ((0xfffffffeul << 32) / itc_freq) << 32;
et->et_min_period = SBT_1S / (10 * hz);
et->et_max_period = (0xfffffffeul << 32) / itc_freq;
et->et_start = ia64_clock_start;
et->et_stop = ia64_clock_stop;
et->et_priv = NULL;

View File

@ -153,6 +153,8 @@ static DPCPU_DEFINE(struct pcpu_state, timerstate);
(((uint64_t)0x8000000000000000 + ((bt)->frac >> 2)) / \
((bt)->frac >> 1))
#define SBT2FREQ(sbt) ((SBT_1S + ((sbt) >> 1)) / (sbt))
/*
* Timer broadcast IPI handler.
*/
@ -442,7 +444,7 @@ loadtimer(struct bintime *now, int start)
new.sec, (u_int)(new.frac >> 32));
*next = new;
bintime_add(next, now);
et_start(timer, &new, &timerperiod);
et_start(timer, bttosbt(new), bttosbt(timerperiod));
}
} else {
getnextevent(&new);
@ -454,7 +456,7 @@ loadtimer(struct bintime *now, int start)
if (!eq) {
*next = new;
bintime_sub(&new, now);
et_start(timer, &new, NULL);
et_start(timer, bttosbt(new), 0);
}
}
}
@ -603,13 +605,13 @@ round_freq(struct eventtimer *et, int freq)
div = 1 << (flsl(div + div / 2) - 1);
freq = (et->et_frequency + div / 2) / div;
}
if (et->et_min_period.sec > 0)
if (et->et_min_period > SBT_1S)
panic("Event timer \"%s\" doesn't support sub-second periods!",
et->et_name);
else if (et->et_min_period.frac != 0)
freq = min(freq, BT2FREQ(&et->et_min_period));
if (et->et_max_period.sec == 0 && et->et_max_period.frac != 0)
freq = max(freq, BT2FREQ(&et->et_max_period));
else if (et->et_min_period != 0)
freq = min(freq, SBT2FREQ(et->et_min_period));
if (et->et_max_period < SBT_1S && et->et_max_period != 0)
freq = max(freq, SBT2FREQ(et->et_max_period));
return (freq);
}

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 2010 Alexander Motin <mav@FreeBSD.org>
* Copyright (c) 2010-2013 Alexander Motin <mav@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -62,6 +62,7 @@ et_register(struct eventtimer *et)
et->et_quality);
}
}
KASSERT(et->et_start, ("et_register: timer has no start function"));
et->et_sysctl = SYSCTL_ADD_NODE(NULL,
SYSCTL_STATIC_CHILDREN(_kern_eventtimer_et), OID_AUTO, et->et_name,
CTLFLAG_RW, 0, "event timer description");
@ -159,43 +160,29 @@ et_init(struct eventtimer *et, et_event_cb_t *event,
* period - period of subsequent periodic ticks.
*/
int
et_start(struct eventtimer *et,
struct bintime *first, struct bintime *period)
et_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
{
if (!et->et_active)
return (ENXIO);
if (first == NULL && period == NULL)
return (EINVAL);
if ((et->et_flags & ET_FLAGS_PERIODIC) == 0 &&
period != NULL)
return (ENODEV);
if ((et->et_flags & ET_FLAGS_ONESHOT) == 0 &&
period == NULL)
return (ENODEV);
if (first != NULL) {
if (first->sec < et->et_min_period.sec ||
(first->sec == et->et_min_period.sec &&
first->frac < et->et_min_period.frac))
first = &et->et_min_period;
if (first->sec > et->et_max_period.sec ||
(first->sec == et->et_max_period.sec &&
first->frac > et->et_max_period.frac))
first = &et->et_max_period;
KASSERT(period >= 0, ("et_start: negative period"));
KASSERT((et->et_flags & ET_FLAGS_PERIODIC) || period == 0,
("et_start: period specified for oneshot-only timer"));
KASSERT((et->et_flags & ET_FLAGS_ONESHOT) && period == 0,
("et_start: period not specified for periodic-only timer"));
if (period != 0) {
if (period < et->et_min_period)
period = et->et_min_period;
else if (period > et->et_max_period)
period = et->et_max_period;
}
if (period != NULL) {
if (period->sec < et->et_min_period.sec ||
(period->sec == et->et_min_period.sec &&
period->frac < et->et_min_period.frac))
period = &et->et_min_period;
if (period->sec > et->et_max_period.sec ||
(period->sec == et->et_max_period.sec &&
period->frac > et->et_max_period.frac))
period = &et->et_max_period;
if (period == 0 || first != 0) {
if (first < et->et_min_period)
first = et->et_min_period;
else if (first > et->et_max_period)
first = et->et_max_period;
}
if (et->et_start)
return (et->et_start(et, first, period));
return (0);
return (et->et_start(et, first, period));
}
/* Stop event timer hardware. */

View File

@ -217,22 +217,17 @@ DELAY(int n)
}
static int
clock_start(struct eventtimer *et,
struct bintime *first, struct bintime *period)
clock_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
{
uint32_t fdiv, div, next;
if (period != NULL) {
div = (et->et_frequency * (period->frac >> 32)) >> 32;
if (period->sec != 0)
div += et->et_frequency * period->sec;
if (period != 0) {
div = (et->et_frequency * period) >> 32;
} else
div = 0;
if (first != NULL) {
fdiv = (et->et_frequency * (first->frac >> 32)) >> 32;
if (first->sec != 0)
fdiv += et->et_frequency * first->sec;
} else
if (first != 0)
fdiv = (et->et_frequency * first) >> 32;
else
fdiv = div;
DPCPU_SET(cycles_per_tick, div);
next = mips_rd_count() + fdiv;
@ -361,11 +356,8 @@ clock_attach(device_t dev)
ET_FLAGS_PERCPU;
sc->et.et_quality = 800;
sc->et.et_frequency = counter_freq;
sc->et.et_min_period.sec = 0;
sc->et.et_min_period.frac = 0x00004000LLU << 32; /* To be safe. */
sc->et.et_max_period.sec = 0xfffffffeU / sc->et.et_frequency;
sc->et.et_max_period.frac =
((0xfffffffeLLU << 32) / sc->et.et_frequency) << 32;
sc->et.et_min_period = 0x00004000LLU; /* To be safe. */
sc->et.et_max_period = (0xfffffffeLLU << 32) / sc->et.et_frequency;
sc->et.et_start = clock_start;
sc->et.et_stop = clock_stop;
sc->et.et_priv = sc;

View File

@ -222,22 +222,17 @@ DELAY(int n)
}
static int
clock_start(struct eventtimer *et,
struct bintime *first, struct bintime *period)
clock_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
{
uint32_t fdiv, div, next;
if (period != NULL) {
div = (et->et_frequency * (period->frac >> 32)) >> 32;
if (period->sec != 0)
div += et->et_frequency * period->sec;
} else
if (period != 0)
div = (et->et_frequency * period) >> 32;
else
div = 0;
if (first != NULL) {
fdiv = (et->et_frequency * (first->frac >> 32)) >> 32;
if (first->sec != 0)
fdiv += et->et_frequency * first->sec;
} else
if (first != 0)
fdiv = (et->et_frequency * first) >> 32;
else
fdiv = div;
DPCPU_SET(cycles_per_tick, div);
next = mips_rd_count() + fdiv;
@ -357,11 +352,8 @@ clock_attach(device_t dev)
sc->et.et_flags = ET_FLAGS_PERIODIC | ET_FLAGS_PERCPU;
sc->et.et_quality = 800;
sc->et.et_frequency = counter_freq;
sc->et.et_min_period.sec = 0;
sc->et.et_min_period.frac = 0x00004000LLU << 32; /* To be safe. */
sc->et.et_max_period.sec = 0xfffffffeU / sc->et.et_frequency;
sc->et.et_max_period.frac =
((0xfffffffeLLU << 32) / sc->et.et_frequency) << 32;
sc->et.et_min_period = 0x00004000LLU; /* To be safe. */
sc->et.et_max_period = (0xfffffffeLLU << 32) / sc->et.et_frequency;
sc->et.et_start = clock_start;
sc->et.et_stop = clock_stop;
sc->et.et_priv = sc;

View File

@ -219,22 +219,17 @@ DELAY(int n)
}
static int
clock_start(struct eventtimer *et,
struct bintime *first, struct bintime *period)
clock_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
{
uint32_t fdiv, div, next;
if (period != NULL) {
div = (et->et_frequency * (period->frac >> 32)) >> 32;
if (period->sec != 0)
div += et->et_frequency * period->sec;
} else
if (period != 0)
div = (et->et_frequency * period) >> 32;
else
div = 0;
if (first != NULL) {
fdiv = (et->et_frequency * (first->frac >> 32)) >> 32;
if (first->sec != 0)
fdiv += et->et_frequency * first->sec;
} else
if (first != 0)
fdiv = (et->et_frequency * first) >> 32;
else
fdiv = div;
DPCPU_SET(cycles_per_tick, div);
next = mips_rd_count() + fdiv;
@ -351,11 +346,8 @@ clock_attach(device_t dev)
ET_FLAGS_PERCPU;
sc->et.et_quality = 800;
sc->et.et_frequency = counter_freq;
sc->et.et_min_period.sec = 0;
sc->et.et_min_period.frac = 0x00004000LLU << 32; /* To be safe. */
sc->et.et_max_period.sec = 0xfffffffeU / sc->et.et_frequency;
sc->et.et_max_period.frac =
((0xfffffffeLLU << 32) / sc->et.et_frequency) << 32;
sc->et.et_min_period = 0x00004000LLU; /* To be safe. */
sc->et.et_max_period = (0xfffffffeLLU << 32) / sc->et.et_frequency;
sc->et.et_start = clock_start;
sc->et.et_stop = clock_stop;
sc->et.et_priv = sc;

View File

@ -85,7 +85,7 @@ static u_long ticks_per_sec = 12500000;
static u_long *decr_counts[MAXCPU];
static int decr_et_start(struct eventtimer *et,
struct bintime *first, struct bintime *period);
sbintime_t first, sbintime_t period);
static int decr_et_stop(struct eventtimer *et);
static timecounter_get_t decr_get_timecount;
@ -195,12 +195,8 @@ decr_tc_init(void)
ET_FLAGS_PERCPU;
decr_et.et_quality = 1000;
decr_et.et_frequency = ticks_per_sec;
decr_et.et_min_period.sec = 0;
decr_et.et_min_period.frac =
((0x00000002LLU << 32) / ticks_per_sec) << 32;
decr_et.et_max_period.sec = 0x7fffffffLLU / ticks_per_sec;
decr_et.et_max_period.frac =
((0x7fffffffLLU << 32) / ticks_per_sec) << 32;
decr_et.et_min_period = (0x00000002LLU << 32) / ticks_per_sec;
decr_et.et_max_period = (0x7fffffffLLU << 32) / ticks_per_sec;
decr_et.et_start = decr_et_start;
decr_et.et_stop = decr_et_stop;
decr_et.et_priv = NULL;
@ -212,24 +208,20 @@ decr_tc_init(void)
*/
static int
decr_et_start(struct eventtimer *et,
struct bintime *first, struct bintime *period)
sbintime_t first, sbintime_t period)
{
struct decr_state *s = DPCPU_PTR(decr_state);
uint32_t fdiv;
if (period != NULL) {
if (period != 0) {
s->mode = 1;
s->div = (decr_et.et_frequency * (period->frac >> 32)) >> 32;
if (period->sec != 0)
s->div += decr_et.et_frequency * period->sec;
s->div = (decr_et.et_frequency * period) >> 32;
} else {
s->mode = 2;
s->div = 0x7fffffff;
s->div = 0;
}
if (first != NULL) {
fdiv = (decr_et.et_frequency * (first->frac >> 32)) >> 32;
if (first->sec != 0)
fdiv += decr_et.et_frequency * first->sec;
if (first != 0) {
fdiv = (decr_et.et_frequency * first) >> 32;
} else
fdiv = s->div;

View File

@ -88,7 +88,7 @@ static u_long *decr_counts[MAXCPU];
#define DIFF19041970 2082844800
static int decr_et_start(struct eventtimer *et,
struct bintime *first, struct bintime *period);
sbintime_t first, sbintime_t period);
static int decr_et_stop(struct eventtimer *et);
static timecounter_get_t decr_get_timecount;
@ -193,12 +193,8 @@ decr_tc_init(void)
ET_FLAGS_PERCPU;
decr_et.et_quality = 1000;
decr_et.et_frequency = ticks_per_sec;
decr_et.et_min_period.sec = 0;
decr_et.et_min_period.frac =
((0x00000002LLU << 32) / ticks_per_sec) << 32;
decr_et.et_max_period.sec = 0xfffffffeLLU / ticks_per_sec;
decr_et.et_max_period.frac =
((0xfffffffeLLU << 32) / ticks_per_sec) << 32;
decr_et.et_min_period = (0x00000002LLU << 32) / ticks_per_sec;
decr_et.et_max_period = (0xfffffffeLLU << 32) / ticks_per_sec;
decr_et.et_start = decr_et_start;
decr_et.et_stop = decr_et_stop;
decr_et.et_priv = NULL;
@ -209,26 +205,21 @@ decr_tc_init(void)
* Event timer start method.
*/
static int
decr_et_start(struct eventtimer *et,
struct bintime *first, struct bintime *period)
decr_et_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
{
struct decr_state *s = DPCPU_PTR(decr_state);
uint32_t fdiv, tcr;
if (period != NULL) {
if (period != 0) {
s->mode = 1;
s->div = (decr_et.et_frequency * (period->frac >> 32)) >> 32;
if (period->sec != 0)
s->div += decr_et.et_frequency * period->sec;
s->div = (decr_et.et_frequency * period) >> 32;
} else {
s->mode = 2;
s->div = 0xffffffff;
s->div = 0;
}
if (first != NULL) {
fdiv = (decr_et.et_frequency * (first->frac >> 32)) >> 32;
if (first->sec != 0)
fdiv += decr_et.et_frequency * first->sec;
} else
if (first != 0)
fdiv = (decr_et.et_frequency * first) >> 32;
else
fdiv = s->div;
tcr = mfspr(SPR_TCR);

View File

@ -93,8 +93,8 @@ static timecounter_get_t stick_get_timecount_mp;
static timecounter_get_t stick_get_timecount_up;
static rd_tick_t stick_rd;
static wr_tick_cmpr_t stick_wr_cmpr;
static int tick_et_start(struct eventtimer *et, struct bintime *first,
struct bintime *period);
static int tick_et_start(struct eventtimer *et, sbintime_t first,
sbintime_t period);
static int tick_et_stop(struct eventtimer *et);
#ifdef SMP
static timecounter_get_t tick_get_timecount_mp;
@ -227,10 +227,8 @@ cpu_initclocks(void)
ET_FLAGS_PERCPU;
tick_et.et_quality = 1000;
tick_et.et_frequency = tick_et_use_stick ? sclock : clock;
tick_et.et_min_period.sec = 0;
tick_et.et_min_period.frac = 0x00010000LLU << 32; /* To be safe. */
tick_et.et_max_period.sec = 3600 * 24; /* No practical limit. */
tick_et.et_max_period.frac = 0;
tick_et.et_min_period = 0x00010000LLU; /* To be safe. */
tick_et.et_max_period = (0xfffffffeLLU << 32) / tick_et.et_frequency;
tick_et.et_start = tick_et_start;
tick_et.et_stop = tick_et_stop;
tick_et.et_priv = NULL;
@ -355,23 +353,18 @@ tick_get_timecount_mp(struct timecounter *tc)
#endif
static int
tick_et_start(struct eventtimer *et, struct bintime *first,
struct bintime *period)
tick_et_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
{
u_long base, div, fdiv;
register_t s;
if (period != NULL) {
div = (tick_et.et_frequency * (period->frac >> 32)) >> 32;
if (period->sec != 0)
div += tick_et.et_frequency * period->sec;
} else
if (period != 0)
div = (tick_et.et_frequency * period) >> 32;
else
div = 0;
if (first != NULL) {
fdiv = (tick_et.et_frequency * (first->frac >> 32)) >> 32;
if (first->sec != 0)
fdiv += tick_et.et_frequency * first->sec;
} else
if (first != 0)
fdiv = (tick_et.et_frequency * first) >> 32;
else
fdiv = div;
PCPU_SET(tickincrement, div);

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 2010 Alexander Motin <mav@FreeBSD.org>
* Copyright (c) 2010-2013 Alexander Motin <mav@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -45,7 +45,7 @@
struct eventtimer;
typedef int et_start_t(struct eventtimer *et,
struct bintime *first, struct bintime *period);
sbintime_t first, sbintime_t period);
typedef int et_stop_t(struct eventtimer *et);
typedef void et_event_cb_t(struct eventtimer *et, void *arg);
typedef int et_deregister_cb_t(struct eventtimer *et, void *arg);
@ -70,8 +70,8 @@ struct eventtimer {
int et_active;
u_int64_t et_frequency;
/* Base frequency in Hz. */
struct bintime et_min_period;
struct bintime et_max_period;
sbintime_t et_min_period;
sbintime_t et_max_period;
et_start_t *et_start;
et_stop_t *et_stop;
et_event_cb_t *et_event_cb;
@ -93,8 +93,7 @@ int et_deregister(struct eventtimer *et);
struct eventtimer *et_find(const char *name, int check, int want);
int et_init(struct eventtimer *et, et_event_cb_t *event,
et_deregister_cb_t *deregister, void *arg);
int et_start(struct eventtimer *et,
struct bintime *first, struct bintime *period);
int et_start(struct eventtimer *et, sbintime_t first, sbintime_t period);
int et_stop(struct eventtimer *et);
int et_ban(struct eventtimer *et);
int et_free(struct eventtimer *et);

View File

@ -164,11 +164,10 @@ struct atrtc_softc {
};
static int
rtc_start(struct eventtimer *et,
struct bintime *first, struct bintime *period)
rtc_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
{
atrtc_rate(max(fls((period->frac + (period->frac >> 1)) >> 32) - 17, 1));
atrtc_rate(max(fls(period + (period >> 1)) - 17, 1));
atrtc_enable_intr();
return (0);
}
@ -277,10 +276,8 @@ atrtc_attach(device_t dev)
sc->et.et_flags = ET_FLAGS_PERIODIC | ET_FLAGS_POW2DIV;
sc->et.et_quality = 0;
sc->et.et_frequency = 32768;
sc->et.et_min_period.sec = 0;
sc->et.et_min_period.frac = 0x0008LLU << 48;
sc->et.et_max_period.sec = 0;
sc->et.et_max_period.frac = 0x8000LLU << 48;
sc->et.et_min_period = 0x00080000;
sc->et.et_max_period = 0x80000000;
sc->et.et_start = rtc_start;
sc->et.et_stop = rtc_stop;
sc->et.et_priv = dev;

View File

@ -589,18 +589,17 @@ i8254_get_timecount(struct timecounter *tc)
}
static int
attimer_start(struct eventtimer *et,
struct bintime *first, struct bintime *period)
attimer_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
{
device_t dev = (device_t)et->et_priv;
struct attimer_softc *sc = device_get_softc(dev);
if (period != NULL) {
if (period != 0) {
sc->mode = MODE_PERIODIC;
sc->period = period->frac >> 32;
sc->period = period;
} else {
sc->mode = MODE_ONESHOT;
sc->period = first->frac >> 32;
sc->period = first;
}
if (!sc->intr_en) {
i8254_intsrc->is_pic->pic_enable_source(i8254_intsrc);
@ -755,12 +754,8 @@ attimer_attach(device_t dev)
sc->et.et_flags |= ET_FLAGS_ONESHOT;
sc->et.et_quality = 100;
sc->et.et_frequency = i8254_freq;
sc->et.et_min_period.sec = 0;
sc->et.et_min_period.frac =
((0x0002LLU << 48) / i8254_freq) << 16;
sc->et.et_max_period.sec = 0xffff / i8254_freq;
sc->et.et_max_period.frac =
((0xfffeLLU << 48) / i8254_freq) << 16;
sc->et.et_min_period = (0x0002LLU << 32) / i8254_freq;
sc->et.et_max_period = (0xfffeLLU << 32) / i8254_freq;
sc->et.et_start = attimer_start;
sc->et.et_stop = attimer_stop;
sc->et.et_priv = dev;

View File

@ -169,7 +169,7 @@ static void lapic_timer_stop(struct lapic *);
static void lapic_timer_set_divisor(u_int divisor);
static uint32_t lvt_mode(struct lapic *la, u_int pin, uint32_t value);
static int lapic_et_start(struct eventtimer *et,
struct bintime *first, struct bintime *period);
sbintime_t first, sbintime_t period);
static int lapic_et_stop(struct eventtimer *et);
struct pic lapic_pic = { .pic_resume = lapic_resume };
@ -268,10 +268,8 @@ lapic_init(vm_paddr_t addr)
}
lapic_et.et_frequency = 0;
/* We don't know frequency yet, so trying to guess. */
lapic_et.et_min_period.sec = 0;
lapic_et.et_min_period.frac = 0x00001000LL << 32;
lapic_et.et_max_period.sec = 1;
lapic_et.et_max_period.frac = 0;
lapic_et.et_min_period = 0x00001000LL;
lapic_et.et_max_period = SBT_1S;
lapic_et.et_start = lapic_et_start;
lapic_et.et_stop = lapic_et_stop;
lapic_et.et_priv = NULL;
@ -487,8 +485,7 @@ lapic_disable_pmc(void)
}
static int
lapic_et_start(struct eventtimer *et,
struct bintime *first, struct bintime *period)
lapic_et_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
{
struct lapic *la;
u_long value;
@ -513,28 +510,18 @@ lapic_et_start(struct eventtimer *et,
printf("lapic: Divisor %lu, Frequency %lu Hz\n",
lapic_timer_divisor, value);
et->et_frequency = value;
et->et_min_period.sec = 0;
et->et_min_period.frac =
((0x00000002LLU << 32) / et->et_frequency) << 32;
et->et_max_period.sec = 0xfffffffeLLU / et->et_frequency;
et->et_max_period.frac =
((0xfffffffeLLU << 32) / et->et_frequency) << 32;
et->et_min_period = (0x00000002LLU << 32) / et->et_frequency;
et->et_max_period = (0xfffffffeLLU << 32) / et->et_frequency;
}
if (la->la_timer_mode == 0)
lapic_timer_set_divisor(lapic_timer_divisor);
if (period != NULL) {
if (period != 0) {
la->la_timer_mode = 1;
la->la_timer_period =
(et->et_frequency * (period->frac >> 32)) >> 32;
if (period->sec != 0)
la->la_timer_period += et->et_frequency * period->sec;
la->la_timer_period = ((uint32_t)et->et_frequency * period) >> 32;
lapic_timer_periodic(la, la->la_timer_period, 1);
} else {
la->la_timer_mode = 2;
la->la_timer_period =
(et->et_frequency * (first->frac >> 32)) >> 32;
if (first->sec != 0)
la->la_timer_period += et->et_frequency * first->sec;
la->la_timer_period = ((uint32_t)et->et_frequency * first) >> 32;
lapic_timer_oneshot(la, la->la_timer_period, 1);
}
return (0);