summaryrefslogtreecommitdiff
path: root/sys/dev/acpi
diff options
context:
space:
mode:
authorGordon Willem Klok <gwk@cvs.openbsd.org>2007-05-31 17:49:17 +0000
committerGordon Willem Klok <gwk@cvs.openbsd.org>2007-05-31 17:49:17 +0000
commit2ff1e8275d4f73445fd38ed3b6ae0767fd684746 (patch)
treea7bcd3fc6eae5f19e8d0cbf9fc15c99ea13f9d88 /sys/dev/acpi
parent7a4d4259325b6c7e8c397b1542f832df8e736a9a (diff)
Make powernow-k8 on amd64 and i386 use the _PSS object from acpi to
retreive p_state data as spelled out in the amd64 bios and kernel developers guide. This code is still a little rough around the edges but has been tested by myself on a tyan machine and by phessler at theapt dot org on an HP DL145. This diff also takes a first stab and cleaning up the acpicpu dmesg spam. ok tedu, marco
Diffstat (limited to 'sys/dev/acpi')
-rw-r--r--sys/dev/acpi/acpicpu.c174
-rw-r--r--sys/dev/acpi/acpidev.h7
-rw-r--r--sys/dev/acpi/acpivar.h3
-rw-r--r--sys/dev/acpi/files.acpi4
4 files changed, 133 insertions, 55 deletions
diff --git a/sys/dev/acpi/acpicpu.c b/sys/dev/acpi/acpicpu.c
index 46cbbdf1df0..8a171529a84 100644
--- a/sys/dev/acpi/acpicpu.c
+++ b/sys/dev/acpi/acpicpu.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: acpicpu.c,v 1.24 2007/05/28 20:22:24 robert Exp $ */
+/* $OpenBSD: acpicpu.c,v 1.25 2007/05/31 17:49:16 gwk Exp $ */
/*
* Copyright (c) 2005 Marco Peereboom <marco@openbsd.org>
*
@@ -52,6 +52,7 @@ void acpicpu_setperf(int);
#define FLAGS_BMCHECK 0x04
#define FLAGS_NOTHROTTLE 0x08
#define FLAGS_NOPSS 0x10
+#define FLAGS_NOPCT 0x20
#define CPU_THT_EN (1L << 4)
#define CPU_MAXSTATE(sc) (1L << (sc)->sc_duty_wid)
@@ -96,6 +97,13 @@ struct acpicpu_softc {
struct acpicpu_pss *sc_pss;
struct acpicpu_pct sc_pct;
+ /* XXX: _PPC Change listener
+ * PPC changes can occur when for example a machine is disconnected
+ * from AC power and can no loger support the highest frequency or
+ * voltage when driven from the battery.
+ * Should probably be reimplemented as a list for now we assume only
+ * one listener */
+ void (*sc_notify)(struct acpicpu_pss *, int);
};
void acpicpu_set_throttle(struct acpicpu_softc *, int);
@@ -185,7 +193,7 @@ acpicpu_add_cstate(struct acpicpu_softc *sc, int type,
return cx;
bad:
- printf("acpicpu%d: C%d not supported", sc->sc_cpu, type);
+ dprintf("acpicpu%d: C%d not supported", sc->sc_cpu, type);
return NULL;
}
@@ -229,15 +237,16 @@ acpicpu_attach(struct device *parent, struct device *self, void *aux)
struct acpi_attach_args *aa = aux;
struct aml_value res;
int i;
+ struct acpi_cstate *cx;
sc->sc_acpi = (struct acpi_softc *)parent;
sc->sc_devnode = aa->aaa_node;
+ acpicpu_sc[sc->sc_dev.dv_unit] = sc;
SLIST_INIT(&sc->sc_cstates);
sc->sc_pss = NULL;
- printf(": %s: ", sc->sc_devnode->name);
if (aml_evalnode(sc->sc_acpi, sc->sc_devnode, 0, NULL, &res) == 0) {
if (res.type == AML_OBJTYPE_PROCESSOR) {
sc->sc_cpu = res.v_processor.proc_id;
@@ -282,50 +291,87 @@ acpicpu_attach(struct device *parent, struct device *self, void *aux)
if (acpicpu_getpss(sc)) {
/* XXX not the right test but has to do for now */
sc->sc_flags |= FLAGS_NOPSS;
- goto nopss;
- }
+ } else {
#ifdef ACPI_DEBUG
- for (i = 0; i < sc->sc_pss_len; i++) {
- dnprintf(20, "%d %d %d %d %d %d\n",
- sc->sc_pss[i].pss_core_freq,
- sc->sc_pss[i].pss_power,
- sc->sc_pss[i].pss_trans_latency,
- sc->sc_pss[i].pss_bus_latency,
- sc->sc_pss[i].pss_ctrl,
- sc->sc_pss[i].pss_status);
- }
- dnprintf(20, "\n");
+ for (i = 0; i < sc->sc_pss_len; i++) {
+ dnprintf(20, "%d %d %d %d %d %d\n",
+ sc->sc_pss[i].pss_core_freq,
+ sc->sc_pss[i].pss_power,
+ sc->sc_pss[i].pss_trans_latency,
+ sc->sc_pss[i].pss_bus_latency,
+ sc->sc_pss[i].pss_ctrl,
+ sc->sc_pss[i].pss_status);
+ }
+ dnprintf(20, "\n");
#endif
- /* XXX this needs to be moved to probe routine */
- if (acpicpu_getpct(sc))
- return;
-
- /* Notify BIOS we are handing p-states */
- if (sc->sc_acpi->sc_fadt->pstate_cnt)
- acpi_write_pmreg(sc->sc_acpi, ACPIREG_SMICMD, 0,
- sc->sc_acpi->sc_fadt->pstate_cnt);
-
- for (i = 0; i < sc->sc_pss_len; i++)
- printf("%d%s", sc->sc_pss[i].pss_core_freq,
- i < sc->sc_pss_len - 1 ? ", " : " MHz\n");
-
- aml_register_notify(sc->sc_devnode, NULL,
- acpicpu_notify, sc, ACPIDEV_NOPOLL);
-
- if (setperf_prio < 30) {
- cpu_setperf = acpicpu_setperf;
- setperf_prio = 30;
- acpi_hasprocfvs = 1;
+ /* XXX this needs to be moved to probe routine */
+ if (acpicpu_getpct(sc))
+ sc->sc_flags |= FLAGS_NOPCT;
+ else {
+
+ /* Notify BIOS we are handing p-states */
+ if (sc->sc_acpi->sc_fadt->pstate_cnt)
+ acpi_write_pmreg(sc->sc_acpi, ACPIREG_SMICMD, 0,
+ sc->sc_acpi->sc_fadt->pstate_cnt);
+
+ aml_register_notify(sc->sc_devnode, NULL,
+ acpicpu_notify, sc, ACPIDEV_NOPOLL);
+
+ if (setperf_prio < 30) {
+ cpu_setperf = acpicpu_setperf;
+ setperf_prio = 30;
+ acpi_hasprocfvs = 1;
+ }
+ }
}
- acpicpu_sc[sc->sc_dev.dv_unit] = sc;
- return;
-
-nopss:
- if (sc->sc_flags & FLAGS_NOTHROTTLE)
- printf("no performance/throttling supported");
+ /*
+ * Nicely enumerate what power management capabilities
+ * ACPI CPU provides.
+ * */
+ i = 0;
+ SLIST_FOREACH(cx, &sc->sc_cstates, link) {
+ if (i)
+ printf(",");
+ switch(cx->type) {
+ case ACPI_STATE_C0:
+ printf(" C0");
+ break;
+ case ACPI_STATE_C1:
+ printf(" C1");
+ break;
+ case ACPI_STATE_C2:
+ printf(" C2");
+ break;
+ case ACPI_STATE_C3:
+ printf(" C3");
+ break;
+ }
+ i++;
+ }
+ if (!(sc->sc_flags & FLAGS_NOPSS) && !(sc->sc_flags & FLAGS_NOPCT)) {
+ if (i)
+ printf(",");
+ printf(" FVS");
+ } else if (!(sc->sc_flags & FLAGS_NOPSS)) {
+ if (i)
+ printf(",");
+ printf(" PSS");
+ }
printf("\n");
+
+ /*
+ * If acpicpu is itself providing the capability to transition
+ * states, enumerate them in the fashion that est and powernow
+ * would.
+ */
+ if (!(sc->sc_flags & FLAGS_NOPSS) && !(sc->sc_flags & FLAGS_NOPCT)) {
+ printf("%s: ", sc->sc_dev.dv_xname);
+ for (i = 0; i < sc->sc_pss_len; i++)
+ printf("%d%s", sc->sc_pss[i].pss_core_freq,
+ i < sc->sc_pss_len - 1 ? ", " : " MHz\n");
+ }
}
int
@@ -336,7 +382,7 @@ acpicpu_getpct(struct acpicpu_softc *sc)
if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_PPC", 0, NULL, &res)) {
dnprintf(20, "%s: no _PPC\n", DEVNAME(sc));
- printf("%s: no _PPC\n", DEVNAME(sc));
+ dnprintf(10, "%s: no _PPC\n", DEVNAME(sc));
return (1);
}
@@ -344,12 +390,12 @@ acpicpu_getpct(struct acpicpu_softc *sc)
aml_freevalue(&res);
if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_PCT", 0, NULL, &res)) {
- printf("%s: no _PCT\n", DEVNAME(sc));
+ dnprintf(20, "%s: no _PCT\n", DEVNAME(sc));
return (1);
}
if (res.length != 2) {
- printf("%s: %s: invalid _PCT length\n", DEVNAME(sc),
+ dnprintf(20, "%s: %s: invalid _PCT length\n", DEVNAME(sc),
sc->sc_devnode->name);
return (1);
}
@@ -358,16 +404,16 @@ acpicpu_getpct(struct acpicpu_softc *sc)
sizeof sc->sc_pct.pct_ctrl);
if (sc->sc_pct.pct_ctrl.grd_gas.address_space_id ==
GAS_FUNCTIONAL_FIXED) {
- printf("CTRL GASIO is CPU manufacturer overridden\n");
- goto bad;
+ dnprintf(20, "CTRL GASIO is functional fixed hardware.\n");
+ goto ffh;
}
memcpy(&sc->sc_pct.pct_status, res.v_package[1]->v_buffer,
sizeof sc->sc_pct.pct_status);
if (sc->sc_pct.pct_status.grd_gas.address_space_id ==
GAS_FUNCTIONAL_FIXED) {
- printf("STATUS GASIO is CPU manufacturer overridden\n");
- goto bad;
+ dnprintf(20, "CTRL GASIO is functional fixed hardware.\n");
+ goto ffh;
}
dnprintf(10, "_PCT(ctrl) : %02x %04x %02x %02x %02x %02x %016x\n",
@@ -389,7 +435,7 @@ acpicpu_getpct(struct acpicpu_softc *sc)
sc->sc_pct.pct_status.grd_gas.address);
rv = 0;
-bad:
+ffh:
aml_freevalue(&res);
return (rv);
}
@@ -401,7 +447,7 @@ acpicpu_getpss(struct acpicpu_softc *sc)
int i;
if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_PSS", 0, NULL, &res)) {
- dnprintf(20, "%s: no _PSS\n", DEVNAME(sc));
+ dprintf("%s: no _PSS\n", DEVNAME(sc));
return (1);
}
@@ -435,6 +481,24 @@ acpicpu_getpss(struct acpicpu_softc *sc)
}
int
+acpicpu_fetch_pss(struct acpicpu_pss **pss) {
+ /*XXX: According to the ACPI spec in an SMP system all processors
+ * are supposed to support the same states. For now we prey
+ * the bios ensures this...
+ */
+ struct acpicpu_softc *sc;
+
+ sc = acpicpu_sc[0];
+ if (!sc) {
+ printf("couldnt fetch acpicpu_softc\n");
+ return 0;
+ }
+ *pss = sc->sc_pss;
+
+ return sc->sc_pss_len;
+}
+
+int
acpicpu_notify(struct aml_node *node, int notify_type, void *arg)
{
struct acpicpu_softc *sc = arg;
@@ -446,6 +510,7 @@ acpicpu_notify(struct aml_node *node, int notify_type, void *arg)
case 0x80: /* _PPC changed, retrieve new values */
acpicpu_getpct(sc);
acpicpu_getpss(sc);
+ sc->sc_notify(sc->sc_pss, sc->sc_pss_len);
break;
default:
printf("%s: unhandled cpu event %x\n", DEVNAME(sc),
@@ -457,6 +522,15 @@ acpicpu_notify(struct aml_node *node, int notify_type, void *arg)
}
void
+acpicpu_set_notify(void (*func)(struct acpicpu_pss *, int)) {
+ struct acpicpu_softc *sc;
+
+ sc = acpicpu_sc[0];
+ if (sc != NULL)
+ sc->sc_notify = func;
+}
+
+void
acpicpu_setperf(int level) {
struct acpicpu_softc *sc;
struct acpicpu_pss *pss = NULL;
diff --git a/sys/dev/acpi/acpidev.h b/sys/dev/acpi/acpidev.h
index 25c066b5d28..8fa10c879bb 100644
--- a/sys/dev/acpi/acpidev.h
+++ b/sys/dev/acpi/acpidev.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: acpidev.h,v 1.24 2007/04/23 17:38:30 mk Exp $ */
+/* $OpenBSD: acpidev.h,v 1.25 2007/05/31 17:49:16 gwk Exp $ */
/*
* Copyright (c) 2005 Marco Peereboom <marco@openbsd.org>
* Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com>
@@ -21,6 +21,7 @@
#include <sys/sensors.h>
#include <sys/rwlock.h>
+#include <dev/acpi/acpireg.h>
#define DEVNAME(s) ((s)->sc_dev.dv_xname)
@@ -226,6 +227,8 @@ struct acpicpu_pss {
u_int32_t pss_status;
};
+int acpicpu_fetch_pss(struct acpicpu_pss **);
+void acpicpu_set_notify(void (*)(struct acpicpu_pss *, int));
/*
* XXX this is returned in a buffer and is not a "natural" type.
*
@@ -290,7 +293,7 @@ struct acpidock_softc {
bus_space_tag_t sc_iot;
bus_space_handle_t sc_ioh;
-
+
struct acpi_softc *sc_acpi;
struct aml_node *sc_devnode;
diff --git a/sys/dev/acpi/acpivar.h b/sys/dev/acpi/acpivar.h
index 0610a6ca068..274b26bc856 100644
--- a/sys/dev/acpi/acpivar.h
+++ b/sys/dev/acpi/acpivar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: acpivar.h,v 1.35 2007/02/19 23:42:39 jordan Exp $ */
+/* $OpenBSD: acpivar.h,v 1.36 2007/05/31 17:49:16 gwk Exp $ */
/*
* Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com>
*
@@ -251,6 +251,7 @@ int acpi_read_pmreg(struct acpi_softc *, int, int);
void acpi_write_pmreg(struct acpi_softc *, int, int, int);
void acpi_poll(void *);
+
#endif
#endif /* !_DEV_ACPI_ACPIVAR_H_ */
diff --git a/sys/dev/acpi/files.acpi b/sys/dev/acpi/files.acpi
index e891ab996f8..542edb2bb2c 100644
--- a/sys/dev/acpi/files.acpi
+++ b/sys/dev/acpi/files.acpi
@@ -1,4 +1,4 @@
-# $OpenBSD: files.acpi,v 1.14 2007/01/22 19:46:23 mk Exp $
+# $OpenBSD: files.acpi,v 1.15 2007/05/31 17:49:16 gwk Exp $
#
# Config file and device description for machine-independent ACPI code.
# Included by ports that need it.
@@ -34,7 +34,7 @@ file dev/acpi/acpibtn.c acpibtn
# cpu device
device acpicpu
attach acpicpu at acpi
-file dev/acpi/acpicpu.c acpicpu
+file dev/acpi/acpicpu.c acpicpu needs-flag
# High Precision Event Timer
device acpihpet