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:
parent
f9c3ff58ce
commit
d86c0f0246
@ -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);
|
||||
|
||||
|
@ -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
|
||||
#
|
||||
|
@ -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.
|
||||
*
|
||||
|
Loading…
x
Reference in New Issue
Block a user