Author: mav
Date: Sun Sep 12 11:11:53 2010
New Revision: 212491
URL: http://svn.freebsd.org/changeset/base/212491

Log:
  Instead of storing last event timestamp, store the next event timestamp.
  It corrects handling of the first event offset in emulated periodic mode.

Modified:
  head/sys/dev/acpica/acpi_hpet.c

Modified: head/sys/dev/acpica/acpi_hpet.c
==============================================================================
--- head/sys/dev/acpica/acpi_hpet.c     Sun Sep 12 06:19:35 2010        
(r212490)
+++ head/sys/dev/acpica/acpi_hpet.c     Sun Sep 12 11:11:53 2010        
(r212491)
@@ -98,7 +98,7 @@ struct hpet_softc {
                uint32_t                caps;
                uint32_t                vectors;
                uint32_t                div;
-               uint32_t                last;
+               uint32_t                next;
                char                    name[8];
        }                       t[32];
        int                     num_timers;
@@ -149,7 +149,7 @@ hpet_start(struct eventtimer *et,
        struct hpet_timer *mt = (struct hpet_timer *)et->et_priv;
        struct hpet_timer *t;
        struct hpet_softc *sc = mt->sc;
-       uint32_t fdiv, cmp;
+       uint32_t fdiv, now;
 
        t = (mt->pcpu_master < 0) ? mt : &sc->t[mt->pcpu_slaves[curcpu]];
        if (period != NULL) {
@@ -170,24 +170,28 @@ hpet_start(struct eventtimer *et,
        if (t->irq < 0)
                bus_write_4(sc->mem_res, HPET_ISR, 1 << t->num);
        t->caps |= HPET_TCNF_INT_ENB;
-       t->last = bus_read_4(sc->mem_res, HPET_MAIN_COUNTER);
+       now = bus_read_4(sc->mem_res, HPET_MAIN_COUNTER);
 restart:
-       cmp = t->last + fdiv;
+       t->next = now + fdiv;
        if (t->mode == 1 && (t->caps & HPET_TCAP_PER_INT)) {
                t->caps |= HPET_TCNF_TYPE;
                bus_write_4(sc->mem_res, HPET_TIMER_CAP_CNF(t->num),
                    t->caps | HPET_TCNF_VAL_SET);
-               bus_write_4(sc->mem_res, HPET_TIMER_COMPARATOR(t->num), cmp);
-               bus_write_4(sc->mem_res, HPET_TIMER_COMPARATOR(t->num), t->div);
+               bus_write_4(sc->mem_res, HPET_TIMER_COMPARATOR(t->num),
+                   t->next);
+               bus_write_4(sc->mem_res, HPET_TIMER_COMPARATOR(t->num),
+                   t->div);
        } else {
                t->caps &= ~HPET_TCNF_TYPE;
-               bus_write_4(sc->mem_res, HPET_TIMER_CAP_CNF(t->num), t->caps);
-               bus_write_4(sc->mem_res, HPET_TIMER_COMPARATOR(t->num), cmp);
+               bus_write_4(sc->mem_res, HPET_TIMER_CAP_CNF(t->num),
+                   t->caps);
+               bus_write_4(sc->mem_res, HPET_TIMER_COMPARATOR(t->num),
+                   t->next);
        }
        if (fdiv < 5000) {
                bus_read_4(sc->mem_res, HPET_TIMER_COMPARATOR(t->num));
-               t->last = bus_read_4(sc->mem_res, HPET_MAIN_COUNTER);
-               if ((int32_t)(t->last - cmp) >= 0) {
+               now = bus_read_4(sc->mem_res, HPET_MAIN_COUNTER);
+               if ((int32_t)(now - t->next) >= 0) {
                        fdiv *= 2;
                        goto restart;
                }
@@ -217,6 +221,8 @@ hpet_intr_single(void *arg)
        struct hpet_softc *sc = t->sc;
        uint32_t now;
 
+       if (t->mode == 0)
+               return (FILTER_STRAY);
        /* Check that per-CPU timer interrupt reached right CPU. */
        if (t->pcpu_cpu >= 0 && t->pcpu_cpu != curcpu) {
                if ((++t->pcpu_misrouted) % 32 == 0) {
@@ -231,20 +237,21 @@ hpet_intr_single(void *arg)
                 */
                if ((t->mode == 1 && (t->caps & HPET_TCAP_PER_INT) == 0) ||
                    t->mode == 2) {
-                       t->last = bus_read_4(sc->mem_res, HPET_MAIN_COUNTER);
+                       t->next = bus_read_4(sc->mem_res, HPET_MAIN_COUNTER) +
+                           sc->freq / 8;
                        bus_write_4(sc->mem_res, HPET_TIMER_COMPARATOR(t->num),
-                           t->last + sc->freq / 8);
+                           t->next);
                }
                return (FILTER_HANDLED);
        }
        if (t->mode == 1 &&
            (t->caps & HPET_TCAP_PER_INT) == 0) {
-               t->last += t->div;
+               t->next += t->div;
                now = bus_read_4(sc->mem_res, HPET_MAIN_COUNTER);
-               if ((int32_t)(now - (t->last + t->div / 2)) > 0)
-                       t->last = now - t->div / 2;
+               if ((int32_t)((now + t->div / 2) - t->next) > 0)
+                       t->next = now + t->div / 2;
                bus_write_4(sc->mem_res,
-                   HPET_TIMER_COMPARATOR(t->num), t->last + t->div);
+                   HPET_TIMER_COMPARATOR(t->num), t->next);
        } else if (t->mode == 2)
                t->mode = 0;
        mt = (t->pcpu_master < 0) ? t : &sc->t[t->pcpu_master];
@@ -713,19 +720,21 @@ hpet_resume(device_t dev)
 #endif
                if (t->mode == 0)
                        continue;
-               t->last = bus_read_4(sc->mem_res, HPET_MAIN_COUNTER);
+               t->next = bus_read_4(sc->mem_res, HPET_MAIN_COUNTER);
                if (t->mode == 1 && (t->caps & HPET_TCAP_PER_INT)) {
                        t->caps |= HPET_TCNF_TYPE;
+                       t->next += t->div;
                        bus_write_4(sc->mem_res, HPET_TIMER_CAP_CNF(t->num),
                            t->caps | HPET_TCNF_VAL_SET);
                        bus_write_4(sc->mem_res, HPET_TIMER_COMPARATOR(t->num),
-                           t->last + t->div);
+                           t->next);
                        bus_read_4(sc->mem_res, HPET_TIMER_COMPARATOR(t->num));
                        bus_write_4(sc->mem_res, HPET_TIMER_COMPARATOR(t->num),
                            t->div);
                } else {
+                       t->next += sc->freq / 1024;
                        bus_write_4(sc->mem_res, HPET_TIMER_COMPARATOR(t->num),
-                           t->last + sc->freq / 1024);
+                           t->next);
                }
                bus_write_4(sc->mem_res, HPET_ISR, 1 << t->num);
                bus_write_4(sc->mem_res, HPET_TIMER_CAP_CNF(t->num), t->caps);
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to