summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornjl <njl@FreeBSD.org>2005-02-13 05:34:52 +0000
committernjl <njl@FreeBSD.org>2005-02-13 05:34:52 +0000
commit924e5aa5c357055fb16e98a3a906c22cc6deb278 (patch)
tree8694903ff2d5efb5f4ed026038cb3054dcf18c05
parent5b155d6843a2af911a7bb288fce45d486d142169 (diff)
downloadFreeBSD-src-924e5aa5c357055fb16e98a3a906c22cc6deb278.zip
FreeBSD-src-924e5aa5c357055fb16e98a3a906c22cc6deb278.tar.gz
Be sure to register with cpufreq(4). On systems that only supported
throttling, neglecting to do this kept the sysctls from appearing. Attach an acpi_throttle device to each CPU that supports it. Don't add a device if the P_BLK is invalid or if _PTC is not present. This removes extraneous probe/attach failure messages on some machines. Make the cpu throttle state local to the softc to account for partial successes when changing the clock rate on MP machines.
-rw-r--r--sys/dev/acpica/acpi_throttle.c45
1 files changed, 36 insertions, 9 deletions
diff --git a/sys/dev/acpica/acpi_throttle.c b/sys/dev/acpica/acpi_throttle.c
index 2bdb923..22aa71f 100644
--- a/sys/dev/acpica/acpi_throttle.c
+++ b/sys/dev/acpica/acpi_throttle.c
@@ -60,6 +60,7 @@ struct acpi_throttle_softc {
uint32_t cpu_p_blk_len; /* P_BLK length (must be 6). */
struct resource *cpu_p_cnt; /* Throttling control register */
int cpu_p_type; /* Resource type for cpu_p_cnt. */
+ uint32_t cpu_thr_state; /* Current throttle setting. */
};
#define THR_GET_REG(reg) \
@@ -87,7 +88,6 @@ struct acpi_throttle_softc {
static uint32_t cpu_duty_offset; /* Offset in P_CNT of throttle val. */
static uint32_t cpu_duty_width; /* Bit width of throttle value. */
-static uint32_t cpu_throttle_state; /* Current throttle setting. */
static int thr_rid; /* Driver-wide resource id. */
static int thr_quirks; /* Indicate any hardware bugs. */
@@ -127,19 +127,37 @@ DRIVER_MODULE(acpi_throttle, cpu, acpi_throttle_driver, acpi_throttle_devclass,
static void
acpi_throttle_identify(driver_t *driver, device_t parent)
{
+ ACPI_BUFFER buf;
+ ACPI_HANDLE handle;
+ ACPI_OBJECT *obj;
/* Make sure we're not being doubly invoked. */
- if (device_find_child(parent, "acpi_throttle", 0) != NULL)
+ if (device_find_child(parent, "acpi_throttle", -1) != NULL)
return;
/* Check for a valid duty width and parent CPU type. */
- if (acpi_get_handle(parent) == NULL)
+ handle = acpi_get_handle(parent);
+ if (handle == NULL)
return;
if (AcpiGbl_FADT->DutyWidth == 0 ||
acpi_get_type(parent) != ACPI_TYPE_PROCESSOR)
return;
- if (BUS_ADD_CHILD(parent, 0, "acpi_throttle", 0) == NULL)
- device_printf(parent, "acpi_throttle: add child failed\n");
+
+ /*
+ * Add a child if there's a non-NULL P_BLK and correct length, or
+ * if the _PTC method is present.
+ */
+ buf.Pointer = NULL;
+ buf.Length = ACPI_ALLOCATE_BUFFER;
+ if (ACPI_FAILURE(AcpiEvaluateObject(handle, NULL, NULL, &buf)))
+ return;
+ obj = (ACPI_OBJECT *)buf.Pointer;
+ if ((obj->Processor.PblkAddress && obj->Processor.PblkLength >= 4) ||
+ ACPI_SUCCESS(AcpiEvaluateObject(handle, "_PTC", NULL, NULL))) {
+ if (BUS_ADD_CHILD(parent, 0, "acpi_throttle", -1) == NULL)
+ device_printf(parent, "add throttle child failed\n");
+ }
+ AcpiOsFree(obj);
}
static int
@@ -155,8 +173,9 @@ acpi_throttle_attach(device_t dev)
{
struct acpi_throttle_softc *sc;
ACPI_BUFFER buf;
- ACPI_OBJECT*obj;
+ ACPI_OBJECT *obj;
ACPI_STATUS status;
+ int error;
sc = device_get_softc(dev);
sc->cpu_dev = dev;
@@ -179,7 +198,14 @@ acpi_throttle_attach(device_t dev)
if (device_get_unit(dev) == 0)
acpi_throttle_quirks(sc);
- return (acpi_throttle_evaluate(sc));
+ /* Attempt to attach the actual throttling register. */
+ error = acpi_throttle_evaluate(sc);
+ if (error)
+ return (error);
+
+ /* Everything went ok, register with cpufreq(4). */
+ cpufreq_register(dev);
+ return (0);
}
static int
@@ -337,7 +363,7 @@ acpi_thr_set(device_t dev, const struct cf_setting *set)
return (EINVAL);
/* If we're at this setting, don't bother applying it again. */
- if (speed == cpu_throttle_state)
+ if (speed == sc->cpu_thr_state)
return (0);
/* Get the current P_CNT value and disable throttling */
@@ -357,7 +383,7 @@ acpi_thr_set(device_t dev, const struct cf_setting *set)
p_cnt |= CPU_P_CNT_THT_EN;
THR_SET_REG(sc->cpu_p_cnt, p_cnt);
}
- cpu_throttle_state = speed;
+ sc->cpu_thr_state = speed;
return (0);
}
@@ -375,6 +401,7 @@ acpi_thr_get(device_t dev, struct cf_setting *set)
/* Get the current throttling setting from P_CNT. */
p_cnt = THR_GET_REG(sc->cpu_p_cnt);
clk_val = (p_cnt >> cpu_duty_offset) & (CPU_MAX_SPEED - 1);
+ sc->cpu_thr_state = clk_val;
memset(set, CPUFREQ_VAL_UNKNOWN, sizeof(*set));
set->freq = CPU_SPEED_PERCENT(clk_val);
OpenPOWER on IntegriCloud