Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 12 Sep 2010 11:11:53 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r212491 - head/sys/dev/acpica
Message-ID:  <201009121111.o8CBBrW0025912@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201009121111.o8CBBrW0025912>