From b29224c2a0f296516f33a748c4fc33d5ed3f23da Mon Sep 17 00:00:00 2001 From: Nate Lawson Date: Mon, 4 Apr 2005 15:46:57 +0000 Subject: [PATCH] Add the acpi_get_features() method. This method is called on child drivers to see what features they may support before calling identify/probe/attach. This is necessary because the ACPI 3.0 spec requires driver support be advertised before running any methods. For now, the flags are as specified in for the _PDC and _OSC methods but we can support private flags as needed. Add an implementation of this for acpi_cpu. It checks all its children (notably cpufreq drivers) and calls the _PDC method to report the results. --- sys/dev/acpica/acpi_cpu.c | 49 +++++++++++++++++---------------------- sys/dev/acpica/acpi_if.m | 13 +++++++++++ sys/dev/acpica/acpivar.h | 14 +++++++++++ 3 files changed, 48 insertions(+), 28 deletions(-) diff --git a/sys/dev/acpica/acpi_cpu.c b/sys/dev/acpica/acpi_cpu.c index 844111b76a05..d32054386a32 100644 --- a/sys/dev/acpica/acpi_cpu.c +++ b/sys/dev/acpica/acpi_cpu.c @@ -79,6 +79,7 @@ struct acpi_cpu_softc { struct acpi_cx cpu_cx_states[MAX_CX_STATES]; int cpu_cx_count; /* Number of valid Cx states. */ int cpu_prev_sleep;/* Last idle sleep duration. */ + int cpu_features; /* Child driver supported features. */ }; struct acpi_cpu_device { @@ -187,10 +188,9 @@ MODULE_DEPEND(cpu, acpi, 1, 1, 1); static int acpi_cpu_probe(device_t dev) { - int acpi_id, cpu_id, cx_count; + int acpi_id, cpu_id; ACPI_BUFFER buf; ACPI_HANDLE handle; - char msg[32]; ACPI_OBJECT *obj; ACPI_STATUS status; @@ -235,33 +235,10 @@ acpi_cpu_probe(device_t dev) if (cpu_softc[cpu_id] != NULL) return (ENXIO); - /* Get a count of Cx states for our device string. */ - cx_count = 0; - buf.Pointer = NULL; - buf.Length = ACPI_ALLOCATE_BUFFER; - status = AcpiEvaluateObject(handle, "_CST", NULL, &buf); - if (ACPI_SUCCESS(status)) { - obj = (ACPI_OBJECT *)buf.Pointer; - if (ACPI_PKG_VALID(obj, 2)) - acpi_PkgInt32(obj, 0, &cx_count); - AcpiOsFree(obj); - } else { - if (AcpiGbl_FADT->Plvl2Lat <= 100) - cx_count++; - if (AcpiGbl_FADT->Plvl3Lat <= 1000) - cx_count++; - if (cx_count > 0) - cx_count++; - } - if (cx_count > 0) - snprintf(msg, sizeof(msg), "ACPI CPU (%d Cx states)", cx_count); - else - strlcpy(msg, "ACPI CPU", sizeof(msg)); - device_set_desc_copy(dev, msg); - /* Mark this processor as in-use and save our derived id for attach. */ cpu_softc[cpu_id] = (void *)1; acpi_set_magic(dev, cpu_id); + device_set_desc(dev, "ACPI CPU"); return (0); } @@ -275,7 +252,9 @@ acpi_cpu_attach(device_t dev) struct acpi_cpu_softc *sc; struct acpi_softc *acpi_sc; ACPI_STATUS status; - int cpu_id; + u_int features; + int cpu_id, drv_count, i; + driver_t **drivers; ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); @@ -312,6 +291,20 @@ acpi_cpu_attach(device_t dev) SYSCTL_CHILDREN(acpi_sc->acpi_sysctl_tree), OID_AUTO, "cpu", CTLFLAG_RD, 0, ""); + /* + * Before calling any CPU methods, collect child driver feature hints + * and notify ACPI of them. + */ + if (devclass_get_drivers(acpi_cpu_devclass, &drivers, &drv_count) == 0) { + for (i = 0; i < drv_count; i++) { + if (ACPI_GET_FEATURES(drivers[i], &features) == 0) + sc->cpu_features |= features; + } + free(drivers, M_TEMP); + } + if (sc->cpu_features) + acpi_SetInteger(sc->cpu_dev, "_PDC", sc->cpu_features); + /* * Probe for Cx state support. If it isn't present, free up unused * resources. @@ -324,7 +317,7 @@ acpi_cpu_attach(device_t dev) } else sysctl_ctx_free(&acpi_cpu_sysctl_ctx); - /* Call identify and then probe/attach for cpu child drivers. */ + /* Finally, call identify and probe/attach for child devices. */ bus_generic_probe(dev); bus_generic_attach(dev); diff --git a/sys/dev/acpica/acpi_if.m b/sys/dev/acpica/acpi_if.m index a93171dec9ba..8c7706c3ceb4 100644 --- a/sys/dev/acpica/acpi_if.m +++ b/sys/dev/acpica/acpi_if.m @@ -155,6 +155,19 @@ METHOD ACPI_STATUS scan_children { void *arg; }; +# +# Query a given driver for its supported feature(s). This should be +# called by the parent bus before the driver is probed. +# +# driver_t *driver: child driver +# +# u_int *features: returned bitmask of all supported features +# +STATICMETHOD int get_features { + driver_t *driver; + u_int *features; +}; + # # Read embedded controller (EC) address space # diff --git a/sys/dev/acpica/acpivar.h b/sys/dev/acpica/acpivar.h index 053aed215879..393536728812 100644 --- a/sys/dev/acpica/acpivar.h +++ b/sys/dev/acpica/acpivar.h @@ -165,6 +165,20 @@ extern struct mtx acpi_mutex; #define ACPI_INTR_APIC 1 #define ACPI_INTR_SAPIC 2 +/* + * Various features and capabilities for the acpi_get_features() method. + * In particular, these are used for the ACPI 3.0 _PDC and _OSC methods. + */ +#define ACPI_CAP_PERF_MSRS (1 << 0) /* Intel SpeedStep PERF_CTL MSRs */ +#define ACPI_CAP_C1_IO_HALT (1 << 1) /* Intel C1 "IO then halt" sequence */ +#define ACPI_CAP_THR_MSRS (1 << 2) /* Intel OnDemand throttling MSRs */ +#define ACPI_CAP_SMP_SAME (1 << 3) /* MP C1, Px, and Tx (all the same) */ +#define ACPI_CAP_SMP_SAME_C3 (1 << 4) /* MP C2 and C3 (all the same) */ +#define ACPI_CAP_SMP_DIFF_PX (1 << 5) /* MP Px (different, using _PSD) */ +#define ACPI_CAP_SMP_DIFF_CX (1 << 6) /* MP Cx (different, using _CSD) */ +#define ACPI_CAP_SMP_DIFF_TX (1 << 7) /* MP Tx (different, using _TSD) */ +#define ACPI_CAP_SMP_C1_NATIVE (1 << 8) /* MP C1 support other than halt */ + /* * Quirk flags. *