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.
This commit is contained in:
Nate Lawson 2005-04-04 15:46:57 +00:00
parent 4abfd70c87
commit b29224c2a0
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=144629
3 changed files with 48 additions and 28 deletions

View File

@ -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);

View File

@ -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
#

View File

@ -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.
*