mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-23 11:18:54 +00:00
Remove acpi throttling support from the acpi_cpu(4) driver now that this
is supported by acpi_throttle(4).
This commit is contained in:
parent
7150dfc7e5
commit
8c5468e3f5
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=141415
@ -50,8 +50,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/acpica/acpivar.h>
|
||||
|
||||
/*
|
||||
* Support for ACPI Processor devices, including ACPI 2.0 throttling
|
||||
* and C[1-3] sleep states.
|
||||
* Support for ACPI Processor devices, including C[1-3] sleep states.
|
||||
*
|
||||
* TODO: implement scans of all CPUs to be sure all Cx states are
|
||||
* equivalent.
|
||||
@ -77,8 +76,6 @@ struct acpi_cpu_softc {
|
||||
uint32_t cpu_acpi_id; /* ACPI processor id */
|
||||
uint32_t cpu_p_blk; /* ACPI P_BLK location */
|
||||
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. */
|
||||
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. */
|
||||
@ -95,24 +92,12 @@ struct acpi_cpu_device {
|
||||
(bus_space_write_ ## width(rman_get_bustag((reg)), \
|
||||
rman_get_bushandle((reg)), 0, (val)))
|
||||
|
||||
/*
|
||||
* Speeds are stored in counts, from 1 to CPU_MAX_SPEED, and
|
||||
* reported to the user in tenths of a percent.
|
||||
*/
|
||||
static uint32_t cpu_duty_offset;
|
||||
static uint32_t cpu_duty_width;
|
||||
#define CPU_MAX_SPEED (1 << cpu_duty_width)
|
||||
#define CPU_SPEED_PERCENT(x) ((1000 * (x)) / CPU_MAX_SPEED)
|
||||
#define CPU_SPEED_PRINTABLE(x) (CPU_SPEED_PERCENT(x) / 10), \
|
||||
(CPU_SPEED_PERCENT(x) % 10)
|
||||
#define CPU_P_CNT_THT_EN (1<<4)
|
||||
#define PM_USEC(x) ((x) >> 2) /* ~4 clocks per usec (3.57955 Mhz) */
|
||||
|
||||
#define ACPI_CPU_NOTIFY_PERF_STATES 0x80 /* _PSS changed. */
|
||||
#define ACPI_CPU_NOTIFY_CX_STATES 0x81 /* _CST changed. */
|
||||
|
||||
#define CPU_QUIRK_NO_C3 (1<<0) /* C3-type states are not usable. */
|
||||
#define CPU_QUIRK_NO_THROTTLE (1<<1) /* Throttling is not usable. */
|
||||
#define CPU_QUIRK_NO_BM_CTRL (1<<2) /* No bus mastering control. */
|
||||
|
||||
#define PCI_VENDOR_INTEL 0x8086
|
||||
@ -136,8 +121,6 @@ static u_int cpu_cx_stats[MAX_CX_STATES];/* Cx usage history. */
|
||||
/* Values for sysctl. */
|
||||
static struct sysctl_ctx_list acpi_cpu_sysctl_ctx;
|
||||
static struct sysctl_oid *acpi_cpu_sysctl_tree;
|
||||
static uint32_t cpu_throttle_state;
|
||||
static uint32_t cpu_throttle_max;
|
||||
static int cpu_cx_lowest;
|
||||
static char cpu_cx_supported[64];
|
||||
|
||||
@ -156,17 +139,13 @@ static device_t acpi_cpu_add_child(device_t dev, int order, const char *name,
|
||||
static int acpi_cpu_read_ivar(device_t dev, device_t child, int index,
|
||||
uintptr_t *result);
|
||||
static int acpi_cpu_shutdown(device_t dev);
|
||||
static int acpi_cpu_throttle_probe(struct acpi_cpu_softc *sc);
|
||||
static int acpi_cpu_cx_probe(struct acpi_cpu_softc *sc);
|
||||
static int acpi_cpu_cx_cst(struct acpi_cpu_softc *sc);
|
||||
static void acpi_cpu_startup(void *arg);
|
||||
static void acpi_cpu_startup_throttling(void);
|
||||
static void acpi_cpu_startup_cx(void);
|
||||
static void acpi_cpu_throttle_set(uint32_t speed);
|
||||
static void acpi_cpu_idle(void);
|
||||
static void acpi_cpu_notify(ACPI_HANDLE h, UINT32 notify, void *context);
|
||||
static int acpi_cpu_quirks(struct acpi_cpu_softc *sc);
|
||||
static int acpi_cpu_throttle_sysctl(SYSCTL_HANDLER_ARGS);
|
||||
static int acpi_cpu_usage_sysctl(SYSCTL_HANDLER_ARGS);
|
||||
static int acpi_cpu_cx_lowest_sysctl(SYSCTL_HANDLER_ARGS);
|
||||
|
||||
@ -297,7 +276,7 @@ acpi_cpu_attach(device_t dev)
|
||||
struct acpi_cpu_softc *sc;
|
||||
struct acpi_softc *acpi_sc;
|
||||
ACPI_STATUS status;
|
||||
int cx_ret, cpu_id, thr_ret;
|
||||
int cpu_id;
|
||||
|
||||
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
|
||||
|
||||
@ -309,6 +288,8 @@ acpi_cpu_attach(device_t dev)
|
||||
pcpu_data = pcpu_find(cpu_id);
|
||||
pcpu_data->pc_device = dev;
|
||||
sc->cpu_pcpu = pcpu_data;
|
||||
cpu_smi_cmd = AcpiGbl_FADT->SmiCmd;
|
||||
cpu_cst_cnt = AcpiGbl_FADT->CstCnt;
|
||||
|
||||
buf.Pointer = NULL;
|
||||
buf.Length = ACPI_ALLOCATE_BUFFER;
|
||||
@ -333,19 +314,16 @@ acpi_cpu_attach(device_t dev)
|
||||
CTLFLAG_RD, 0, "");
|
||||
|
||||
/*
|
||||
* Probe for throttling and Cx state support.
|
||||
* If none of these is present, free up unused resources.
|
||||
* Probe for Cx state support. If it isn't present, free up unused
|
||||
* resources.
|
||||
*/
|
||||
thr_ret = acpi_cpu_throttle_probe(sc);
|
||||
cx_ret = acpi_cpu_cx_probe(sc);
|
||||
if (thr_ret == 0 || cx_ret == 0) {
|
||||
if (acpi_cpu_cx_probe(sc) == 0) {
|
||||
status = AcpiInstallNotifyHandler(sc->cpu_handle, ACPI_DEVICE_NOTIFY,
|
||||
acpi_cpu_notify, sc);
|
||||
if (device_get_unit(dev) == 0)
|
||||
AcpiOsQueueForExecution(OSD_PRIORITY_LO, acpi_cpu_startup, NULL);
|
||||
} else {
|
||||
} else
|
||||
sysctl_ctx_free(&acpi_cpu_sysctl_ctx);
|
||||
}
|
||||
|
||||
/* Call identify and then probe/attach for cpu child drivers. */
|
||||
bus_generic_probe(dev);
|
||||
@ -454,89 +432,6 @@ acpi_cpu_shutdown(device_t dev)
|
||||
return_VALUE (0);
|
||||
}
|
||||
|
||||
static int
|
||||
acpi_cpu_throttle_probe(struct acpi_cpu_softc *sc)
|
||||
{
|
||||
uint32_t duty_end;
|
||||
ACPI_BUFFER buf;
|
||||
ACPI_OBJECT obj;
|
||||
ACPI_GENERIC_ADDRESS gas;
|
||||
ACPI_STATUS status;
|
||||
|
||||
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
|
||||
|
||||
/* Get throttling parameters from the FADT. 0 means not supported. */
|
||||
if (device_get_unit(sc->cpu_dev) == 0) {
|
||||
cpu_smi_cmd = AcpiGbl_FADT->SmiCmd;
|
||||
cpu_cst_cnt = AcpiGbl_FADT->CstCnt;
|
||||
cpu_duty_offset = AcpiGbl_FADT->DutyOffset;
|
||||
cpu_duty_width = AcpiGbl_FADT->DutyWidth;
|
||||
}
|
||||
if (cpu_duty_width == 0 || (cpu_quirks & CPU_QUIRK_NO_THROTTLE) != 0)
|
||||
return (ENXIO);
|
||||
|
||||
/* Validate the duty offset/width. */
|
||||
duty_end = cpu_duty_offset + cpu_duty_width - 1;
|
||||
if (duty_end > 31) {
|
||||
device_printf(sc->cpu_dev, "CLK_VAL field overflows P_CNT register\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
if (cpu_duty_offset <= 4 && duty_end >= 4) {
|
||||
device_printf(sc->cpu_dev, "CLK_VAL field overlaps THT_EN bit\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/*
|
||||
* If not present, fall back to using the processor's P_BLK to find
|
||||
* the P_CNT register.
|
||||
*
|
||||
* Note that some systems seem to duplicate the P_BLK pointer
|
||||
* across multiple CPUs, so not getting the resource is not fatal.
|
||||
*/
|
||||
buf.Pointer = &obj;
|
||||
buf.Length = sizeof(obj);
|
||||
status = AcpiEvaluateObject(sc->cpu_handle, "_PTC", NULL, &buf);
|
||||
if (ACPI_SUCCESS(status)) {
|
||||
if (obj.Buffer.Length < sizeof(ACPI_GENERIC_ADDRESS) + 3) {
|
||||
device_printf(sc->cpu_dev, "_PTC buffer too small\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
memcpy(&gas, obj.Buffer.Pointer + 3, sizeof(gas));
|
||||
acpi_bus_alloc_gas(sc->cpu_dev, &sc->cpu_p_type, &cpu_rid, &gas,
|
||||
&sc->cpu_p_cnt);
|
||||
if (sc->cpu_p_cnt != NULL) {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "acpi_cpu%d: P_CNT from _PTC\n",
|
||||
device_get_unit(sc->cpu_dev)));
|
||||
}
|
||||
}
|
||||
|
||||
/* If _PTC not present or other failure, try the P_BLK. */
|
||||
if (sc->cpu_p_cnt == NULL) {
|
||||
/*
|
||||
* The spec says P_BLK must be 6 bytes long. However, some
|
||||
* systems use it to indicate a fractional set of features
|
||||
* present so we take anything >= 4.
|
||||
*/
|
||||
if (sc->cpu_p_blk_len < 4)
|
||||
return (ENXIO);
|
||||
gas.Address = sc->cpu_p_blk;
|
||||
gas.AddressSpaceId = ACPI_ADR_SPACE_SYSTEM_IO;
|
||||
gas.RegisterBitWidth = 32;
|
||||
acpi_bus_alloc_gas(sc->cpu_dev, &sc->cpu_p_type, &cpu_rid, &gas,
|
||||
&sc->cpu_p_cnt);
|
||||
if (sc->cpu_p_cnt != NULL) {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "acpi_cpu%d: P_CNT from P_BLK\n",
|
||||
device_get_unit(sc->cpu_dev)));
|
||||
} else {
|
||||
device_printf(sc->cpu_dev, "Failed to attach throttling P_CNT\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
}
|
||||
cpu_rid++;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
acpi_cpu_cx_probe(struct acpi_cpu_softc *sc)
|
||||
{
|
||||
@ -776,50 +671,12 @@ acpi_cpu_startup(void *arg)
|
||||
}
|
||||
cpu_cx_count = count;
|
||||
|
||||
/* Perform throttling and Cx final initialization. */
|
||||
/* Perform Cx final initialization. */
|
||||
sc = device_get_softc(cpu_devices[0]);
|
||||
if (sc->cpu_p_cnt != NULL)
|
||||
acpi_cpu_startup_throttling();
|
||||
if (cpu_cx_count > 0)
|
||||
acpi_cpu_startup_cx();
|
||||
}
|
||||
|
||||
/*
|
||||
* Takes the ACPI lock to avoid fighting anyone over the SMI command
|
||||
* port.
|
||||
*/
|
||||
static void
|
||||
acpi_cpu_startup_throttling()
|
||||
{
|
||||
|
||||
/* If throttling is not usable, don't initialize it. */
|
||||
if (cpu_quirks & CPU_QUIRK_NO_THROTTLE)
|
||||
return;
|
||||
|
||||
/* Initialise throttling states */
|
||||
cpu_throttle_max = CPU_MAX_SPEED;
|
||||
cpu_throttle_state = CPU_MAX_SPEED;
|
||||
|
||||
SYSCTL_ADD_INT(&acpi_cpu_sysctl_ctx,
|
||||
SYSCTL_CHILDREN(acpi_cpu_sysctl_tree),
|
||||
OID_AUTO, "throttle_max", CTLFLAG_RD,
|
||||
&cpu_throttle_max, 0, "maximum CPU speed");
|
||||
SYSCTL_ADD_PROC(&acpi_cpu_sysctl_ctx,
|
||||
SYSCTL_CHILDREN(acpi_cpu_sysctl_tree),
|
||||
OID_AUTO, "throttle_state",
|
||||
CTLTYPE_INT | CTLFLAG_RW, &cpu_throttle_state,
|
||||
0, acpi_cpu_throttle_sysctl, "I", "current CPU speed");
|
||||
|
||||
/* Set initial speed to maximum. */
|
||||
ACPI_SERIAL_BEGIN(cpu);
|
||||
acpi_cpu_throttle_set(cpu_throttle_max);
|
||||
ACPI_SERIAL_END(cpu);
|
||||
|
||||
printf("acpi_cpu: throttling enabled, %d steps (100%% to %d.%d%%), "
|
||||
"currently %d.%d%%\n", CPU_MAX_SPEED, CPU_SPEED_PRINTABLE(1),
|
||||
CPU_SPEED_PRINTABLE(cpu_throttle_state));
|
||||
}
|
||||
|
||||
static void
|
||||
acpi_cpu_startup_cx()
|
||||
{
|
||||
@ -870,49 +727,6 @@ acpi_cpu_startup_cx()
|
||||
cpu_idle_hook = acpi_cpu_idle;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set CPUs to the new state.
|
||||
*
|
||||
* Must be called with the ACPI lock held.
|
||||
*/
|
||||
static void
|
||||
acpi_cpu_throttle_set(uint32_t speed)
|
||||
{
|
||||
struct acpi_cpu_softc *sc;
|
||||
int i;
|
||||
uint32_t p_cnt, clk_val;
|
||||
|
||||
ACPI_SERIAL_ASSERT(cpu);
|
||||
|
||||
/* Iterate over processors */
|
||||
for (i = 0; i < cpu_ndevices; i++) {
|
||||
sc = device_get_softc(cpu_devices[i]);
|
||||
if (sc->cpu_p_cnt == NULL)
|
||||
continue;
|
||||
|
||||
/* Get the current P_CNT value and disable throttling */
|
||||
p_cnt = CPU_GET_REG(sc->cpu_p_cnt, 4);
|
||||
p_cnt &= ~CPU_P_CNT_THT_EN;
|
||||
CPU_SET_REG(sc->cpu_p_cnt, 4, p_cnt);
|
||||
|
||||
/* If we're at maximum speed, that's all */
|
||||
if (speed < CPU_MAX_SPEED) {
|
||||
/* Mask the old CLK_VAL off and or-in the new value */
|
||||
clk_val = (CPU_MAX_SPEED - 1) << cpu_duty_offset;
|
||||
p_cnt &= ~clk_val;
|
||||
p_cnt |= (speed << cpu_duty_offset);
|
||||
|
||||
/* Write the new P_CNT value and then enable throttling */
|
||||
CPU_SET_REG(sc->cpu_p_cnt, 4, p_cnt);
|
||||
p_cnt |= CPU_P_CNT_THT_EN;
|
||||
CPU_SET_REG(sc->cpu_p_cnt, 4, p_cnt);
|
||||
}
|
||||
ACPI_VPRINT(sc->cpu_dev, acpi_device_get_parent_softc(sc->cpu_dev),
|
||||
"set speed to %d.%d%%\n", CPU_SPEED_PRINTABLE(speed));
|
||||
}
|
||||
cpu_throttle_state = speed;
|
||||
}
|
||||
|
||||
/*
|
||||
* Idle the CPU in the lowest state possible. This function is called with
|
||||
* interrupts disabled. Note that once it re-enables interrupts, a task
|
||||
@ -1075,18 +889,6 @@ acpi_cpu_quirks(struct acpi_cpu_softc *sc)
|
||||
acpi_dev = pci_find_device(PCI_VENDOR_INTEL, PCI_DEVICE_82371AB_3);
|
||||
if (acpi_dev != NULL) {
|
||||
switch (pci_get_revid(acpi_dev)) {
|
||||
/*
|
||||
* Disable throttling control on PIIX4 A and B-step.
|
||||
* See specification changes #13 ("Manual Throttle Duty Cycle")
|
||||
* and #14 ("Enabling and Disabling Manual Throttle"), plus
|
||||
* erratum #5 ("STPCLK# Deassertion Time") from the January
|
||||
* 2002 PIIX4 specification update. Note that few (if any)
|
||||
* mobile systems ever used this part.
|
||||
*/
|
||||
case PCI_REVISION_A_STEP:
|
||||
case PCI_REVISION_B_STEP:
|
||||
cpu_quirks |= CPU_QUIRK_NO_THROTTLE;
|
||||
/* FALLTHROUGH */
|
||||
/*
|
||||
* Disable C3 support for all PIIX4 chipsets. Some of these parts
|
||||
* do not report the BMIDE status to the BM status register and
|
||||
@ -1111,35 +913,6 @@ acpi_cpu_quirks(struct acpi_cpu_softc *sc)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Handle changes in the CPU throttling setting. */
|
||||
static int
|
||||
acpi_cpu_throttle_sysctl(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
uint32_t *argp;
|
||||
uint32_t arg;
|
||||
int error;
|
||||
|
||||
argp = (uint32_t *)oidp->oid_arg1;
|
||||
arg = *argp;
|
||||
error = sysctl_handle_int(oidp, &arg, 0, req);
|
||||
|
||||
/* Error or no new value */
|
||||
if (error != 0 || req->newptr == NULL)
|
||||
return (error);
|
||||
if (arg < 1 || arg > cpu_throttle_max)
|
||||
return (EINVAL);
|
||||
|
||||
/* If throttling changed, notify the BIOS of the new rate. */
|
||||
ACPI_SERIAL_BEGIN(cpu);
|
||||
if (*argp != arg) {
|
||||
*argp = arg;
|
||||
acpi_cpu_throttle_set(arg);
|
||||
}
|
||||
ACPI_SERIAL_END(cpu);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
acpi_cpu_usage_sysctl(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user