Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/acpi From jmcneill@: fix and rework the obscure _OSC...
details: https://anonhg.NetBSD.org/src/rev/efd436b4b8d3
branches: trunk
changeset: 757371:efd436b4b8d3
user: jruoho <jruoho%NetBSD.org@localhost>
date: Fri Aug 27 02:44:05 2010 +0000
description:
>From jmcneill@: fix and rework the obscure _OSC evaluation.
diffstat:
sys/dev/acpi/acpi_cpu.c | 214 ++++++++++++++++++++++++++---------------------
sys/dev/acpi/acpireg.h | 12 ++-
2 files changed, 128 insertions(+), 98 deletions(-)
diffs (truncated from 339 to 300 lines):
diff -r c97308618f45 -r efd436b4b8d3 sys/dev/acpi/acpi_cpu.c
--- a/sys/dev/acpi/acpi_cpu.c Thu Aug 26 22:48:36 2010 +0000
+++ b/sys/dev/acpi/acpi_cpu.c Fri Aug 27 02:44:05 2010 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: acpi_cpu.c,v 1.20 2010/08/19 05:09:53 jruoho Exp $ */
+/* $NetBSD: acpi_cpu.c,v 1.21 2010/08/27 02:44:05 jruoho Exp $ */
/*-
* Copyright (c) 2010 Jukka Ruohonen <jruohonen%iki.fi@localhost>
@@ -27,7 +27,7 @@
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: acpi_cpu.c,v 1.20 2010/08/19 05:09:53 jruoho Exp $");
+__KERNEL_RCSID(0, "$NetBSD: acpi_cpu.c,v 1.21 2010/08/27 02:44:05 jruoho Exp $");
#include <sys/param.h>
#include <sys/cpu.h>
@@ -57,10 +57,9 @@
static int acpicpu_object(ACPI_HANDLE, struct acpicpu_object *);
static cpuid_t acpicpu_id(uint32_t);
static uint32_t acpicpu_cap(struct acpicpu_softc *);
-static ACPI_OBJECT *acpicpu_cap_init(void);
-static ACPI_STATUS acpicpu_cap_pdc(ACPI_HANDLE);
-static ACPI_STATUS acpicpu_cap_osc(ACPI_HANDLE, uint32_t *);
-static const char *acpicpu_cap_oscerr(uint32_t);
+static ACPI_STATUS acpicpu_cap_pdc(struct acpicpu_softc *, uint32_t);
+static ACPI_STATUS acpicpu_cap_osc(struct acpicpu_softc *,
+ uint32_t, uint32_t *);
static void acpicpu_notify(ACPI_HANDLE, uint32_t, void *);
static bool acpicpu_suspend(device_t, const pmf_qual_t *);
static bool acpicpu_resume(device_t, const pmf_qual_t *);
@@ -132,6 +131,9 @@
return;
}
+ aprint_naive("\n");
+ aprint_normal(": ACPI CPU\n");
+
acpicpu_sc[sc->sc_cpuid] = sc;
sc->sc_cap = acpicpu_cap(sc);
@@ -139,9 +141,6 @@
mutex_init(&sc->sc_mtx, MUTEX_DEFAULT, IPL_NONE);
- aprint_naive("\n");
- aprint_normal(": ACPI CPU\n");
-
/*
* We should claim the bus space. However, we do this only
* to announce that the space is in use. As is noted in
@@ -334,123 +333,165 @@
static uint32_t
acpicpu_cap(struct acpicpu_softc *sc)
{
- uint32_t cap[3] = { 0 };
+ uint32_t flags, cap = 0;
+ const char *str;
ACPI_STATUS rv;
- int err;
/*
- * Set machine-dependent processor capabilities.
- *
- * The _PDC was deprecated in ACPI 3.0 in favor of the _OSC,
- * but firmware may expect that we evaluate it nevertheless.
+ * Query and set machine-dependent capabilities.
+ * Note that the Intel-specific _PDC method was
+ * deprecated in the ACPI 3.0 in favor of _OSC.
*/
- rv = acpicpu_cap_pdc(sc->sc_node->ad_handle);
-
- if (ACPI_FAILURE(rv) && rv != AE_NOT_FOUND)
- aprint_error_dev(sc->sc_dev, "failed to evaluate _PDC: "
- "%s\n", AcpiFormatException(rv));
-
- rv = acpicpu_cap_osc(sc->sc_node->ad_handle, cap);
+ flags = acpicpu_md_cap();
+ rv = acpicpu_cap_osc(sc, flags, &cap);
- if (ACPI_FAILURE(rv) && rv != AE_NOT_FOUND)
- aprint_error_dev(sc->sc_dev, "failed to evaluate _OSC: "
- "%s\n", AcpiFormatException(rv));
-
- if (ACPI_SUCCESS(rv)) {
+ if (ACPI_FAILURE(rv) && rv != AE_NOT_FOUND) {
+ str = "_OSC";
+ goto fail;
+ }
- err = cap[0] & ~__BIT(0);
+ rv = acpicpu_cap_pdc(sc, flags);
- if (err != 0) {
- aprint_error_dev(sc->sc_dev, "errors in "
- "_OSC: %s\n", acpicpu_cap_oscerr(err));
- cap[2] = 0;
- }
+ if (ACPI_FAILURE(rv) && rv != AE_NOT_FOUND) {
+ str = "_PDC";
+ goto fail;
}
- return cap[2];
+ if (cap == 0)
+ cap = flags;
+
+ return cap;
+
+fail:
+ aprint_error_dev(sc->sc_dev, "failed to evaluate "
+ "%s: %s\n", str, AcpiFormatException(rv));
+
+ return 0;
}
-static ACPI_OBJECT *
-acpicpu_cap_init(void)
+static ACPI_STATUS
+acpicpu_cap_pdc(struct acpicpu_softc *sc, uint32_t flags)
{
- static uint32_t cap[3];
- static ACPI_OBJECT obj;
+ ACPI_OBJECT_LIST arg;
+ ACPI_OBJECT obj;
+ uint32_t cap[3];
+
+ arg.Count = 1;
+ arg.Pointer = &obj;
cap[0] = ACPICPU_PDC_REVID;
cap[1] = 1;
- cap[2] = acpicpu_md_cap();
+ cap[2] = flags;
obj.Type = ACPI_TYPE_BUFFER;
obj.Buffer.Length = sizeof(cap);
- obj.Buffer.Pointer = (uint8_t *)cap;
+ obj.Buffer.Pointer = (void *)cap;
- return &obj;
+ return AcpiEvaluateObject(sc->sc_node->ad_handle, "_PDC", &arg, NULL);
}
static ACPI_STATUS
-acpicpu_cap_pdc(ACPI_HANDLE hdl)
+acpicpu_cap_osc(struct acpicpu_softc *sc, uint32_t flags, uint32_t *val)
{
- ACPI_OBJECT_LIST arg_list;
-
- arg_list.Count = 1;
- arg_list.Pointer = acpicpu_cap_init();
-
- return AcpiEvaluateObject(hdl, "_PDC", &arg_list, NULL);
-}
-
-static ACPI_STATUS
-acpicpu_cap_osc(ACPI_HANDLE hdl, uint32_t *val)
-{
- ACPI_OBJECT_LIST arg_list;
- ACPI_OBJECT *cap, *obj;
- ACPI_OBJECT arg[4];
+ ACPI_OBJECT_LIST arg;
+ ACPI_OBJECT obj[4];
+ ACPI_OBJECT *osc;
ACPI_BUFFER buf;
ACPI_STATUS rv;
+ uint32_t cap[2];
+ uint32_t *ptr;
+ int i = 5;
- /* Intel. */
- static uint8_t cpu_oscuuid[16] = {
+ static uint8_t intel_uuid[16] = {
0x16, 0xA6, 0x77, 0x40, 0x0C, 0x29, 0xBE, 0x47,
0x9E, 0xBD, 0xD8, 0x70, 0x58, 0x71, 0x39, 0x53
};
- cap = acpicpu_cap_init();
+ cap[0] = ACPI_OSC_QUERY;
+ cap[1] = flags;
- arg_list.Count = 4;
- arg_list.Pointer = arg;
+again:
+ arg.Count = 4;
+ arg.Pointer = obj;
- arg[0].Type = ACPI_TYPE_BUFFER;
- arg[0].Buffer.Length = sizeof(cpu_oscuuid);
- arg[0].Buffer.Pointer = cpu_oscuuid;
+ obj[0].Type = ACPI_TYPE_BUFFER;
+ obj[0].Buffer.Length = sizeof(intel_uuid);
+ obj[0].Buffer.Pointer = intel_uuid;
+
+ obj[1].Type = ACPI_TYPE_INTEGER;
+ obj[1].Integer.Value = ACPICPU_PDC_REVID;
- arg[1].Type = ACPI_TYPE_INTEGER;
- arg[1].Integer.Value = ACPICPU_PDC_REVID;
+ obj[2].Type = ACPI_TYPE_INTEGER;
+ obj[2].Integer.Value = __arraycount(cap);
- arg[2].Type = ACPI_TYPE_INTEGER;
- arg[2].Integer.Value = cap->Buffer.Length / sizeof(uint32_t);
-
- arg[3] = *cap;
+ obj[3].Type = ACPI_TYPE_BUFFER;
+ obj[3].Buffer.Length = sizeof(cap);
+ obj[3].Buffer.Pointer = (void *)cap;
buf.Pointer = NULL;
buf.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
- rv = AcpiEvaluateObject(hdl, "_OSC", &arg_list, &buf);
+ rv = AcpiEvaluateObject(sc->sc_node->ad_handle, "_OSC", &arg, &buf);
if (ACPI_FAILURE(rv))
- return rv;
+ goto out;
- obj = buf.Pointer;
+ osc = buf.Pointer;
- if (obj->Type != ACPI_TYPE_BUFFER) {
+ if (osc->Type != ACPI_TYPE_BUFFER) {
rv = AE_TYPE;
goto out;
}
- if (obj->Buffer.Length != cap->Buffer.Length) {
+ if (osc->Buffer.Length != sizeof(cap)) {
rv = AE_BUFFER_OVERFLOW;
goto out;
}
- (void)memcpy(val, obj->Buffer.Pointer, obj->Buffer.Length);
+ ptr = (uint32_t *)osc->Buffer.Pointer;
+
+ if ((ptr[0] & ACPI_OSC_ERROR) != 0) {
+ rv = AE_ERROR;
+ goto out;
+ }
+
+ if ((ptr[0] & (ACPI_OSC_ERROR_REV | ACPI_OSC_ERROR_UUID)) != 0) {
+ rv = AE_BAD_PARAMETER;
+ goto out;
+ }
+
+ /*
+ * "It is strongly recommended that the OS evaluate
+ * _OSC with the Query Support Flag set until _OSC
+ * returns the Capabilities Masked bit clear, to
+ * negotiate the set of features to be granted to
+ * the OS for native support (ACPI 4.0, 6.2.10)."
+ */
+ if ((ptr[0] & ACPI_OSC_ERROR_MASKED) != 0 && i >= 0) {
+
+ ACPI_FREE(buf.Pointer);
+ i--;
+
+ goto again;
+ }
+
+ if ((cap[0] & ACPI_OSC_QUERY) != 0) {
+
+ ACPI_FREE(buf.Pointer);
+ cap[0] &= ~ACPI_OSC_QUERY;
+
+ goto again;
+ }
+
+ /*
+ * It is permitted for _OSC to return all
+ * bits cleared, but this is specified to
+ * vary on per-device basis. Assume that
+ * everything rather than nothing will be
+ * supported in thise case; we do not need
+ * the firmware to know the CPU features.
+ */
+ *val = (ptr[1] != 0) ? ptr[1] : cap[1];
out:
if (buf.Pointer != NULL)
@@ -459,27 +500,6 @@
return rv;
}
-static const char *
-acpicpu_cap_oscerr(uint32_t err)
-{
-
- KASSERT((err & __BIT(0)) == 0);
-
- if ((err & __BIT(1)) != 0)
- return "_OSC failure";
-
- if ((err & __BIT(2)) != 0)
- return "unrecognized UUID";
Home |
Main Index |
Thread Index |
Old Index