svn commit: r212323 - head/sys/dev/acpica
Alexander Motin
mav at FreeBSD.org
Wed Sep 8 16:59:23 UTC 2010
Author: mav
Date: Wed Sep 8 16:59:22 2010
New Revision: 212323
URL: http://svn.freebsd.org/changeset/base/212323
Log:
During SMP startup there is time window, when SMP started, but interrupts
are still bound to BSP. It confuses timer management logic in per-CPU mode
and may cause timer not being reloaded. Check such cases on interrupt
arival and reload timer to give system some more time to manage proper
binding.
Modified:
head/sys/dev/acpica/acpi_hpet.c
Modified: head/sys/dev/acpica/acpi_hpet.c
==============================================================================
--- head/sys/dev/acpica/acpi_hpet.c Wed Sep 8 16:58:06 2010 (r212322)
+++ head/sys/dev/acpica/acpi_hpet.c Wed Sep 8 16:59:22 2010 (r212323)
@@ -89,6 +89,8 @@ struct hpet_softc {
int mode;
int intr_rid;
int irq;
+ int pcpu_cpu;
+ int pcpu_misrouted;
int pcpu_master;
int pcpu_slaves[MAXCPU];
struct resource *intr_res;
@@ -185,7 +187,7 @@ restart:
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) {
+ if ((int32_t)(t->last - cmp) >= 0) {
fdiv *= 2;
goto restart;
}
@@ -215,6 +217,26 @@ hpet_intr_single(void *arg)
struct hpet_softc *sc = t->sc;
uint32_t now;
+ /* Check that per-CPU timer interrupt reached right CPU. */
+ if (t->pcpu_cpu >= 0 && t->pcpu_cpu != curcpu) {
+ if ((++t->pcpu_misrouted) % 32 == 0) {
+ printf("HPET interrupt routed to the wrong CPU"
+ " (timer %d CPU %d -> %d)!\n",
+ t->num, t->pcpu_cpu, curcpu);
+ }
+
+ /*
+ * Reload timer, hoping that next time may be more lucky
+ * (system will manage proper interrupt binding).
+ */
+ 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);
+ bus_write_4(sc->mem_res, HPET_TIMER_COMPARATOR(t->num),
+ t->last + sc->freq / 8);
+ }
+ return (FILTER_HANDLED);
+ }
if (t->mode == 1 &&
(t->caps & HPET_TCAP_PER_INT) == 0) {
t->last += t->div;
@@ -394,6 +416,8 @@ hpet_attach(device_t dev)
t->mode = 0;
t->intr_rid = -1;
t->irq = -1;
+ t->pcpu_cpu = -1;
+ t->pcpu_misrouted = 0;
t->pcpu_master = -1;
t->caps = bus_read_4(sc->mem_res, HPET_TIMER_CAP_CNF(i));
t->vectors = bus_read_4(sc->mem_res, HPET_TIMER_CAP_CNF(i) + 4);
@@ -534,6 +558,7 @@ hpet_attach(device_t dev)
if (t->irq >= 0 && num_percpu_t > 0) {
if (cur_cpu == CPU_FIRST())
pcpu_master = i;
+ t->pcpu_cpu = cur_cpu;
t->pcpu_master = pcpu_master;
sc->t[pcpu_master].
pcpu_slaves[cur_cpu] = i;
More information about the svn-src-all
mailing list