summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/dev/acpi/acpitz.c91
1 files changed, 51 insertions, 40 deletions
diff --git a/sys/dev/acpi/acpitz.c b/sys/dev/acpi/acpitz.c
index b7f4579e5a4..811b0548742 100644
--- a/sys/dev/acpi/acpitz.c
+++ b/sys/dev/acpi/acpitz.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: acpitz.c,v 1.34 2009/12/09 04:55:00 marco Exp $ */
+/* $OpenBSD: acpitz.c,v 1.35 2010/01/13 23:31:25 marco Exp $ */
/*
* Copyright (c) 2006 Can Erkin Acar <canacar@openbsd.org>
* Copyright (c) 2005 Marco Peereboom <marco@openbsd.org>
@@ -23,6 +23,7 @@
#include <sys/device.h>
#include <sys/malloc.h>
#include <sys/kernel.h>
+#include <sys/kthread.h>
#include <machine/bus.h>
@@ -73,6 +74,8 @@ struct cfdriver acpitz_cd = {
NULL, "acpitz", DV_DULL
};
+void acpitz_init_perf(void *);
+void acpitz_setperf(int);
void acpitz_monitor(struct acpitz_softc *);
void acpitz_refresh(void *);
int acpitz_notify(struct aml_node *, int, void *);
@@ -80,12 +83,11 @@ int acpitz_gettempreading(struct acpitz_softc *, char *);
int acpitz_getreading(struct acpitz_softc *, char *);
int acpitz_setfan(struct acpitz_softc *, int, char *);
void acpitz_init(struct acpitz_softc *, int);
-#if 0
-int acpitz_setcpu(struct acpitz_softc *, int);
-#endif
-extern void (*cpu_setperf)(int);
-extern int perflevel;
+void (*acpitz_cpu_setperf)(int);
+int acpitz_perflevel = -1;
+extern void (*cpu_setperf)(int);
+extern int perflevel;
#define PERFSTEP 10
#define ACPITZ_TRIPS (1L << 0)
@@ -95,6 +97,35 @@ extern int perflevel;
extern struct aml_node aml_root;
void
+acpitz_init_perf(void *arg)
+{
+ if (acpitz_perflevel == -1)
+ acpitz_perflevel = perflevel;
+
+ if (cpu_setperf != acpitz_setperf) {
+ acpitz_cpu_setperf = cpu_setperf;
+ cpu_setperf = acpitz_setperf;
+ }
+}
+
+void
+acpitz_setperf(int level)
+{
+ extern struct acpi_softc *acpi_softc;
+
+ if (level < 0 || level > 100)
+ return;
+
+ if (acpi_softc == NULL)
+ return;
+ if (acpi_softc->sc_pse && level > acpitz_perflevel)
+ return;
+
+ if (acpitz_cpu_setperf)
+ acpitz_cpu_setperf(level);
+}
+
+void
acpitz_init(struct acpitz_softc *sc, int flag)
{
int i;
@@ -196,38 +227,14 @@ acpitz_attach(struct device *parent, struct device *self, void *aux)
aml_register_notify(sc->sc_devnode, NULL,
acpitz_notify, sc, ACPIDEV_POLL);
-}
-
-#if 0
-int
-acpitz_setcpu(struct acpitz_softc *sc, int perc)
-{
- struct aml_value res0, *ref;
- int x;
- if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_PSL", 0, NULL, &res0)) {
- printf("%s: _PSL failed\n", DEVNAME(sc));
- goto out;
- }
- if (res0.type != AML_OBJTYPE_PACKAGE) {
- printf("%s: not a package\n", DEVNAME(sc));
- goto out;
- }
- for (x = 0; x < res0.length; x++) {
- if (res0.v_package[x]->type != AML_OBJTYPE_OBJREF) {
- printf("%s: _PSL[%d] not a object ref\n",
- DEVNAME(sc), x);
- continue;
- }
- ref = res0.v_package[x]->v_objref.ref;
- if (ref->type != AML_OBJTYPE_PROCESSOR)
- printf("%s: _PSL[%d] not a CPU\n", DEVNAME(sc), x);
- }
- out:
- aml_freevalue(&res0);
- return (0);
+ /*
+ * XXX use kthread_create_deferred to ensure we are the very last
+ * piece of code that touches this pointer after all CPUs have been
+ * fully attached
+ */
+ kthread_create_deferred(acpitz_init_perf, sc);
}
-#endif
int
acpitz_setfan(struct acpitz_softc *sc, int i, char *method)
@@ -331,7 +338,7 @@ acpitz_refresh(void *arg)
"tc2: %d psv: %d\n", DEVNAME(sc), sc->sc_lasttmp,
sc->sc_tc1, sc->sc_tc2, sc->sc_psv);
- nperf = perflevel;
+ nperf = acpitz_perflevel;
if (sc->sc_psv <= sc->sc_tmp) {
/* Passive cooling enabled */
dnprintf(1, "%s: enabling passive %d %d\n",
@@ -363,10 +370,14 @@ acpitz_refresh(void *arg)
else if (nperf > 100)
nperf = 100;
+ /* clamp passive cooling request */
+ if (nperf > perflevel)
+ nperf = perflevel;
+
/* Perform CPU setperf */
- if (cpu_setperf && nperf != perflevel) {
- perflevel = nperf;
- cpu_setperf(nperf);
+ if (acpitz_cpu_setperf && nperf != acpitz_perflevel) {
+ acpitz_perflevel = nperf;
+ acpitz_cpu_setperf(nperf);
}
}
sc->sc_lasttmp = sc->sc_tmp;