Module Name: src
Committed By: jruoho
Date: Fri Aug 27 02:44:05 UTC 2010
Modified Files:
src/sys/dev/acpi: acpi_cpu.c acpireg.h
Log Message:
>From jmcneill@: fix and rework the obscure _OSC evaluation.
To generate a diff of this commit:
cvs rdiff -u -r1.20 -r1.21 src/sys/dev/acpi/acpi_cpu.c
cvs rdiff -u -r1.9 -r1.10 src/sys/dev/acpi/acpireg.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/dev/acpi/acpi_cpu.c
diff -u src/sys/dev/acpi/acpi_cpu.c:1.20 src/sys/dev/acpi/acpi_cpu.c:1.21
--- src/sys/dev/acpi/acpi_cpu.c:1.20 Thu Aug 19 05:09:53 2010
+++ src/sys/dev/acpi/acpi_cpu.c Fri Aug 27 02:44:05 2010
@@ -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 <[email protected]>
@@ -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,150 +333,171 @@
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);
+ 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 _PDC: "
- "%s\n", AcpiFormatException(rv));
+ if (ACPI_FAILURE(rv) && rv != AE_NOT_FOUND) {
+ str = "_OSC";
+ goto fail;
+ }
- rv = acpicpu_cap_osc(sc->sc_node->ad_handle, cap);
+ rv = acpicpu_cap_pdc(sc, flags);
- if (ACPI_FAILURE(rv) && rv != AE_NOT_FOUND)
- aprint_error_dev(sc->sc_dev, "failed to evaluate _OSC: "
- "%s\n", AcpiFormatException(rv));
+ if (ACPI_FAILURE(rv) && rv != AE_NOT_FOUND) {
+ str = "_PDC";
+ goto fail;
+ }
- if (ACPI_SUCCESS(rv)) {
+ if (cap == 0)
+ cap = flags;
- err = cap[0] & ~__BIT(0);
+ return cap;
- if (err != 0) {
- aprint_error_dev(sc->sc_dev, "errors in "
- "_OSC: %s\n", acpicpu_cap_oscerr(err));
- cap[2] = 0;
- }
- }
+fail:
+ aprint_error_dev(sc->sc_dev, "failed to evaluate "
+ "%s: %s\n", str, AcpiFormatException(rv));
- return cap[2];
+ 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();
-
- arg_list.Count = 4;
- arg_list.Pointer = arg;
-
- arg[0].Type = ACPI_TYPE_BUFFER;
- arg[0].Buffer.Length = sizeof(cpu_oscuuid);
- arg[0].Buffer.Pointer = cpu_oscuuid;
+ cap[0] = ACPI_OSC_QUERY;
+ cap[1] = flags;
- arg[1].Type = ACPI_TYPE_INTEGER;
- arg[1].Integer.Value = ACPICPU_PDC_REVID;
-
- arg[2].Type = ACPI_TYPE_INTEGER;
- arg[2].Integer.Value = cap->Buffer.Length / sizeof(uint32_t);
-
- arg[3] = *cap;
+again:
+ arg.Count = 4;
+ arg.Pointer = obj;
+
+ 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;
+
+ obj[2].Type = ACPI_TYPE_INTEGER;
+ obj[2].Integer.Value = __arraycount(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;
-out:
- if (buf.Pointer != NULL)
- ACPI_FREE(buf.Pointer);
+ if ((ptr[0] & ACPI_OSC_ERROR) != 0) {
+ rv = AE_ERROR;
+ goto out;
+ }
- return rv;
-}
+ if ((ptr[0] & (ACPI_OSC_ERROR_REV | ACPI_OSC_ERROR_UUID)) != 0) {
+ rv = AE_BAD_PARAMETER;
+ goto out;
+ }
-static const char *
-acpicpu_cap_oscerr(uint32_t err)
-{
+ /*
+ * "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) {
- KASSERT((err & __BIT(0)) == 0);
+ ACPI_FREE(buf.Pointer);
+ i--;
- if ((err & __BIT(1)) != 0)
- return "_OSC failure";
+ goto again;
+ }
- if ((err & __BIT(2)) != 0)
- return "unrecognized UUID";
+ if ((cap[0] & ACPI_OSC_QUERY) != 0) {
- if ((err & __BIT(3)) != 0)
- return "unrecognized revision";
+ ACPI_FREE(buf.Pointer);
+ cap[0] &= ~ACPI_OSC_QUERY;
- if ((err & __BIT(4)) != 0)
- return "capabilities masked";
+ goto again;
+ }
- return "unknown error";
+ /*
+ * 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)
+ ACPI_FREE(buf.Pointer);
+
+ return rv;
}
static void
Index: src/sys/dev/acpi/acpireg.h
diff -u src/sys/dev/acpi/acpireg.h:1.9 src/sys/dev/acpi/acpireg.h:1.10
--- src/sys/dev/acpi/acpireg.h:1.9 Tue Apr 27 05:57:43 2010
+++ src/sys/dev/acpi/acpireg.h Fri Aug 27 02:44:05 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: acpireg.h,v 1.9 2010/04/27 05:57:43 jruoho Exp $ */
+/* $NetBSD: acpireg.h,v 1.10 2010/08/27 02:44:05 jruoho Exp $ */
/*
* Copyright 2001 Wasabi Systems, Inc.
@@ -44,6 +44,16 @@
#define ACPI_STA_OK (ACPI_STA_DEVICE_PRESENT | \
ACPI_STA_DEVICE_ENABLED | \
ACPI_STA_DEVICE_FUNCTIONING)
+
+/*
+ * Operating System Capabilities, _OSC.
+ */
+#define ACPI_OSC_QUERY __BIT(0)
+#define ACPI_OSC_ERROR __BIT(1)
+#define ACPI_OSC_ERROR_UUID __BIT(2)
+#define ACPI_OSC_ERROR_REV __BIT(3)
+#define ACPI_OSC_ERROR_MASKED __BIT(4)
+
/*
* PCI functions.
*/