Merge branches 'acpi-pm', 'acpi-properties', 'acpi-misc' and 'acpi-x86'
Merge ACPI power management changes, ACPI device properties handling changes, x86-specific ACPI changes and miscellaneous ACPI changes for 5.18-rc1: - Add power management debug messages related to suspend-to-idle in two places (Rafael Wysocki). - Fix __acpi_node_get_property_reference() return value and clean up that function (Andy Shevchenko, Sakari Ailus). - Fix return value of the __setup handler in the ACPI PM timer clock source driver (Randy Dunlap). - Clean up double words in two comments (Tom Rix). - Add "skip i2c clients" quirks for Lenovo Yoga Tablet 1050F/L and Nextbook Ares 8 (Hans de Goede). - Clean up frequency invariance handling on x86 in the ACPI CPPC library (Huang Rui). - Work around broken XSDT on the Advantech DAC-BJ01 board (Mark Cilissen). * acpi-pm: ACPI: EC / PM: Print additional debug message in acpi_ec_dispatch_gpe() ACPI: PM: Print additional debug message in acpi_s2idle_wake() * acpi-properties: ACPI: property: Get rid of redundant 'else' ACPI: properties: Consistently return -ENOENT if there are no more references * acpi-misc: clocksource: acpi_pm: fix return value of __setup handler ACPI: clean up double words in two comments * acpi-x86: ACPI / x86: Work around broken XSDT on Advantech DAC-BJ01 board x86/ACPI: CPPC: Move init_freq_invariance_cppc() into x86 CPPC x86: Expose init_freq_invariance() to topology header x86/ACPI: CPPC: Move AMD maximum frequency ratio setting function into x86 CPPC x86/ACPI: CPPC: Rename cppc_msr.c to cppc.c ACPI / x86: Add skip i2c clients quirk for Lenovo Yoga Tablet 1050F/L ACPI / x86: Add skip i2c clients quirk for Nextbook Ares 8
This commit is contained in:
Коммит
03d5c98d91
|
@ -215,15 +215,26 @@ extern void arch_scale_freq_tick(void);
|
|||
#define arch_scale_freq_tick arch_scale_freq_tick
|
||||
|
||||
extern void arch_set_max_freq_ratio(bool turbo_disabled);
|
||||
void init_freq_invariance(bool secondary, bool cppc_ready);
|
||||
#else
|
||||
static inline void arch_set_max_freq_ratio(bool turbo_disabled)
|
||||
{
|
||||
}
|
||||
static inline void init_freq_invariance(bool secondary, bool cppc_ready)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_ACPI_CPPC_LIB) && defined(CONFIG_SMP)
|
||||
#ifdef CONFIG_ACPI_CPPC_LIB
|
||||
void init_freq_invariance_cppc(void);
|
||||
#define init_freq_invariance_cppc init_freq_invariance_cppc
|
||||
|
||||
bool amd_set_max_freq_ratio(u64 *ratio);
|
||||
#else
|
||||
static inline bool amd_set_max_freq_ratio(u64 *ratio)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ASM_X86_TOPOLOGY_H */
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
obj-$(CONFIG_ACPI) += boot.o
|
||||
obj-$(CONFIG_ACPI_SLEEP) += sleep.o wakeup_$(BITS).o
|
||||
obj-$(CONFIG_ACPI_APEI) += apei.o
|
||||
obj-$(CONFIG_ACPI_CPPC_LIB) += cppc_msr.o
|
||||
obj-$(CONFIG_ACPI_CPPC_LIB) += cppc.o
|
||||
|
||||
ifneq ($(CONFIG_ACPI_PROCESSOR),)
|
||||
obj-y += cstate.o
|
||||
|
|
|
@ -1328,6 +1328,17 @@ static int __init disable_acpi_pci(const struct dmi_system_id *d)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int __init disable_acpi_xsdt(const struct dmi_system_id *d)
|
||||
{
|
||||
if (!acpi_force) {
|
||||
pr_notice("%s detected: force use of acpi=rsdt\n", d->ident);
|
||||
acpi_gbl_do_not_use_xsdt = TRUE;
|
||||
} else {
|
||||
pr_notice("Warning: DMI blacklist says broken, but acpi XSDT forced\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init dmi_disable_acpi(const struct dmi_system_id *d)
|
||||
{
|
||||
if (!acpi_force) {
|
||||
|
@ -1451,6 +1462,19 @@ static const struct dmi_system_id acpi_dmi_table[] __initconst = {
|
|||
DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 360"),
|
||||
},
|
||||
},
|
||||
/*
|
||||
* Boxes that need ACPI XSDT use disabled due to corrupted tables
|
||||
*/
|
||||
{
|
||||
.callback = disable_acpi_xsdt,
|
||||
.ident = "Advantech DAC-BJ01",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "NEC"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Bearlake CRB Board"),
|
||||
DMI_MATCH(DMI_BIOS_VERSION, "V1.12"),
|
||||
DMI_MATCH(DMI_BIOS_DATE, "02/01/2011"),
|
||||
},
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* cppc.c: CPPC Interface for x86
|
||||
* Copyright (c) 2016, Intel Corporation.
|
||||
*/
|
||||
|
||||
#include <acpi/cppc_acpi.h>
|
||||
#include <asm/msr.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/topology.h>
|
||||
|
||||
/* Refer to drivers/acpi/cppc_acpi.c for the description of functions */
|
||||
|
||||
bool cpc_ffh_supported(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int cpc_read_ffh(int cpunum, struct cpc_reg *reg, u64 *val)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = rdmsrl_safe_on_cpu(cpunum, reg->address, val);
|
||||
if (!err) {
|
||||
u64 mask = GENMASK_ULL(reg->bit_offset + reg->bit_width - 1,
|
||||
reg->bit_offset);
|
||||
|
||||
*val &= mask;
|
||||
*val >>= reg->bit_offset;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int cpc_write_ffh(int cpunum, struct cpc_reg *reg, u64 val)
|
||||
{
|
||||
u64 rd_val;
|
||||
int err;
|
||||
|
||||
err = rdmsrl_safe_on_cpu(cpunum, reg->address, &rd_val);
|
||||
if (!err) {
|
||||
u64 mask = GENMASK_ULL(reg->bit_offset + reg->bit_width - 1,
|
||||
reg->bit_offset);
|
||||
|
||||
val <<= reg->bit_offset;
|
||||
val &= mask;
|
||||
rd_val &= ~mask;
|
||||
rd_val |= val;
|
||||
err = wrmsrl_safe_on_cpu(cpunum, reg->address, rd_val);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
bool amd_set_max_freq_ratio(u64 *ratio)
|
||||
{
|
||||
struct cppc_perf_caps perf_caps;
|
||||
u64 highest_perf, nominal_perf;
|
||||
u64 perf_ratio;
|
||||
int rc;
|
||||
|
||||
if (!ratio)
|
||||
return false;
|
||||
|
||||
rc = cppc_get_perf_caps(0, &perf_caps);
|
||||
if (rc) {
|
||||
pr_debug("Could not retrieve perf counters (%d)\n", rc);
|
||||
return false;
|
||||
}
|
||||
|
||||
highest_perf = amd_get_highest_perf();
|
||||
nominal_perf = perf_caps.nominal_perf;
|
||||
|
||||
if (!highest_perf || !nominal_perf) {
|
||||
pr_debug("Could not retrieve highest or nominal performance\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
perf_ratio = div_u64(highest_perf * SCHED_CAPACITY_SCALE, nominal_perf);
|
||||
/* midpoint between max_boost and max_P */
|
||||
perf_ratio = (perf_ratio + SCHED_CAPACITY_SCALE) >> 1;
|
||||
if (!perf_ratio) {
|
||||
pr_debug("Non-zero highest/nominal perf values led to a 0 ratio\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
*ratio = perf_ratio;
|
||||
arch_set_max_freq_ratio(false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static DEFINE_MUTEX(freq_invariance_lock);
|
||||
|
||||
void init_freq_invariance_cppc(void)
|
||||
{
|
||||
static bool secondary;
|
||||
|
||||
mutex_lock(&freq_invariance_lock);
|
||||
|
||||
init_freq_invariance(secondary, true);
|
||||
secondary = true;
|
||||
|
||||
mutex_unlock(&freq_invariance_lock);
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* cppc_msr.c: MSR Interface for CPPC
|
||||
* Copyright (c) 2016, Intel Corporation.
|
||||
*/
|
||||
|
||||
#include <acpi/cppc_acpi.h>
|
||||
#include <asm/msr.h>
|
||||
|
||||
/* Refer to drivers/acpi/cppc_acpi.c for the description of functions */
|
||||
|
||||
bool cpc_ffh_supported(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int cpc_read_ffh(int cpunum, struct cpc_reg *reg, u64 *val)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = rdmsrl_safe_on_cpu(cpunum, reg->address, val);
|
||||
if (!err) {
|
||||
u64 mask = GENMASK_ULL(reg->bit_offset + reg->bit_width - 1,
|
||||
reg->bit_offset);
|
||||
|
||||
*val &= mask;
|
||||
*val >>= reg->bit_offset;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int cpc_write_ffh(int cpunum, struct cpc_reg *reg, u64 val)
|
||||
{
|
||||
u64 rd_val;
|
||||
int err;
|
||||
|
||||
err = rdmsrl_safe_on_cpu(cpunum, reg->address, &rd_val);
|
||||
if (!err) {
|
||||
u64 mask = GENMASK_ULL(reg->bit_offset + reg->bit_width - 1,
|
||||
reg->bit_offset);
|
||||
|
||||
val <<= reg->bit_offset;
|
||||
val &= mask;
|
||||
rd_val &= ~mask;
|
||||
rd_val |= val;
|
||||
err = wrmsrl_safe_on_cpu(cpunum, reg->address, rd_val);
|
||||
}
|
||||
return err;
|
||||
}
|
|
@ -83,10 +83,6 @@
|
|||
#include <asm/hw_irq.h>
|
||||
#include <asm/stackprotector.h>
|
||||
|
||||
#ifdef CONFIG_ACPI_CPPC_LIB
|
||||
#include <acpi/cppc_acpi.h>
|
||||
#endif
|
||||
|
||||
/* representing HT siblings of each logical CPU */
|
||||
DEFINE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_sibling_map);
|
||||
EXPORT_PER_CPU_SYMBOL(cpu_sibling_map);
|
||||
|
@ -155,8 +151,6 @@ static inline void smpboot_restore_warm_reset_vector(void)
|
|||
*((volatile u32 *)phys_to_virt(TRAMPOLINE_PHYS_LOW)) = 0;
|
||||
}
|
||||
|
||||
static void init_freq_invariance(bool secondary, bool cppc_ready);
|
||||
|
||||
/*
|
||||
* Report back to the Boot Processor during boot time or to the caller processor
|
||||
* during CPU online.
|
||||
|
@ -2097,48 +2091,6 @@ out:
|
|||
return true;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ACPI_CPPC_LIB
|
||||
static bool amd_set_max_freq_ratio(void)
|
||||
{
|
||||
struct cppc_perf_caps perf_caps;
|
||||
u64 highest_perf, nominal_perf;
|
||||
u64 perf_ratio;
|
||||
int rc;
|
||||
|
||||
rc = cppc_get_perf_caps(0, &perf_caps);
|
||||
if (rc) {
|
||||
pr_debug("Could not retrieve perf counters (%d)\n", rc);
|
||||
return false;
|
||||
}
|
||||
|
||||
highest_perf = amd_get_highest_perf();
|
||||
nominal_perf = perf_caps.nominal_perf;
|
||||
|
||||
if (!highest_perf || !nominal_perf) {
|
||||
pr_debug("Could not retrieve highest or nominal performance\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
perf_ratio = div_u64(highest_perf * SCHED_CAPACITY_SCALE, nominal_perf);
|
||||
/* midpoint between max_boost and max_P */
|
||||
perf_ratio = (perf_ratio + SCHED_CAPACITY_SCALE) >> 1;
|
||||
if (!perf_ratio) {
|
||||
pr_debug("Non-zero highest/nominal perf values led to a 0 ratio\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
arch_turbo_freq_ratio = perf_ratio;
|
||||
arch_set_max_freq_ratio(false);
|
||||
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
static bool amd_set_max_freq_ratio(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void init_counter_refs(void)
|
||||
{
|
||||
u64 aperf, mperf;
|
||||
|
@ -2167,7 +2119,7 @@ static void register_freq_invariance_syscore_ops(void)
|
|||
static inline void register_freq_invariance_syscore_ops(void) {}
|
||||
#endif
|
||||
|
||||
static void init_freq_invariance(bool secondary, bool cppc_ready)
|
||||
void init_freq_invariance(bool secondary, bool cppc_ready)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
|
@ -2187,7 +2139,7 @@ static void init_freq_invariance(bool secondary, bool cppc_ready)
|
|||
if (!cppc_ready) {
|
||||
return;
|
||||
}
|
||||
ret = amd_set_max_freq_ratio();
|
||||
ret = amd_set_max_freq_ratio(&arch_turbo_freq_ratio);
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
|
@ -2200,22 +2152,6 @@ static void init_freq_invariance(bool secondary, bool cppc_ready)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ACPI_CPPC_LIB
|
||||
static DEFINE_MUTEX(freq_invariance_lock);
|
||||
|
||||
void init_freq_invariance_cppc(void)
|
||||
{
|
||||
static bool secondary;
|
||||
|
||||
mutex_lock(&freq_invariance_lock);
|
||||
|
||||
init_freq_invariance(secondary, true);
|
||||
secondary = true;
|
||||
|
||||
mutex_unlock(&freq_invariance_lock);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void disable_freq_invariance_workfn(struct work_struct *work)
|
||||
{
|
||||
static_branch_disable(&arch_scale_freq_key);
|
||||
|
@ -2264,8 +2200,4 @@ error:
|
|||
pr_warn("Scheduler frequency invariance went wobbly, disabling!\n");
|
||||
schedule_work(&disable_freq_invariance_work);
|
||||
}
|
||||
#else
|
||||
static inline void init_freq_invariance(bool secondary, bool cppc_ready)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_X86_64 */
|
||||
|
|
|
@ -302,7 +302,7 @@ config ACPI_IPMI
|
|||
help
|
||||
This driver enables the ACPI to access the BMC controller. And it
|
||||
uses the IPMI request/response message to communicate with BMC
|
||||
controller, which can be found on on the server.
|
||||
controller, which can be found on the server.
|
||||
|
||||
To compile this driver as a module, choose M here:
|
||||
the module will be called as acpi_ipmi.
|
||||
|
|
|
@ -2081,8 +2081,11 @@ bool acpi_ec_dispatch_gpe(void)
|
|||
*/
|
||||
spin_lock_irq(&first_ec->lock);
|
||||
|
||||
if (acpi_ec_gpe_status_set(first_ec))
|
||||
if (acpi_ec_gpe_status_set(first_ec)) {
|
||||
pm_pr_dbg("ACPI EC GPE status set\n");
|
||||
|
||||
work_in_progress = advance_transaction(first_ec, false);
|
||||
}
|
||||
|
||||
spin_unlock_irq(&first_ec->lock);
|
||||
|
||||
|
|
|
@ -185,7 +185,7 @@ static acpi_status acpi_pci_link_check_current(struct acpi_resource *resource,
|
|||
if (!p || !p->interrupt_count) {
|
||||
/*
|
||||
* IRQ descriptors may have no IRQ# bits set,
|
||||
* particularly those those w/ _STA disabled
|
||||
* particularly those w/ _STA disabled
|
||||
*/
|
||||
pr_debug("Blank _CRS IRQ resource\n");
|
||||
return AE_OK;
|
||||
|
|
|
@ -541,7 +541,8 @@ acpi_device_data_of_node(const struct fwnode_handle *fwnode)
|
|||
if (is_acpi_device_node(fwnode)) {
|
||||
const struct acpi_device *adev = to_acpi_device_node(fwnode);
|
||||
return &adev->data;
|
||||
} else if (is_acpi_data_node(fwnode)) {
|
||||
}
|
||||
if (is_acpi_data_node(fwnode)) {
|
||||
const struct acpi_data_node *dn = to_acpi_data_node(fwnode);
|
||||
return &dn->data;
|
||||
}
|
||||
|
@ -685,7 +686,7 @@ int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode,
|
|||
*/
|
||||
if (obj->type == ACPI_TYPE_LOCAL_REFERENCE) {
|
||||
if (index)
|
||||
return -EINVAL;
|
||||
return -ENOENT;
|
||||
|
||||
device = acpi_fetch_acpi_dev(obj->reference.handle);
|
||||
if (!device)
|
||||
|
@ -739,14 +740,19 @@ int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* assume following integer elements are all args */
|
||||
/*
|
||||
* Assume the following integer elements are all args.
|
||||
* Stop counting on the first reference or end of the
|
||||
* package arguments. In case of neither reference,
|
||||
* nor integer, return an error, we can't parse it.
|
||||
*/
|
||||
for (i = 0; element + i < end && i < num_args; i++) {
|
||||
int type = element[i].type;
|
||||
|
||||
if (type == ACPI_TYPE_LOCAL_REFERENCE)
|
||||
break;
|
||||
if (type == ACPI_TYPE_INTEGER)
|
||||
nargs++;
|
||||
else if (type == ACPI_TYPE_LOCAL_REFERENCE)
|
||||
break;
|
||||
else
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -950,7 +956,7 @@ static int acpi_data_prop_read(const struct acpi_device_data *data,
|
|||
|
||||
if (proptype != DEV_PROP_STRING && nval > obj->package.count)
|
||||
return -EOVERFLOW;
|
||||
else if (nval <= 0)
|
||||
if (nval == 0)
|
||||
return -EINVAL;
|
||||
|
||||
items = obj->package.elements;
|
||||
|
@ -1012,14 +1018,10 @@ struct fwnode_handle *acpi_get_next_subnode(const struct fwnode_handle *fwnode,
|
|||
const struct list_head *head;
|
||||
struct list_head *next;
|
||||
|
||||
if (!child || is_acpi_device_node(child)) {
|
||||
if ((!child || is_acpi_device_node(child)) && adev) {
|
||||
struct acpi_device *child_adev;
|
||||
|
||||
if (adev)
|
||||
head = &adev->children;
|
||||
else
|
||||
goto nondev;
|
||||
|
||||
head = &adev->children;
|
||||
if (list_empty(head))
|
||||
goto nondev;
|
||||
|
||||
|
@ -1089,7 +1091,8 @@ acpi_node_get_parent(const struct fwnode_handle *fwnode)
|
|||
if (is_acpi_data_node(fwnode)) {
|
||||
/* All data nodes have parent pointer so just return that */
|
||||
return to_acpi_data_node(fwnode)->parent;
|
||||
} else if (is_acpi_device_node(fwnode)) {
|
||||
}
|
||||
if (is_acpi_device_node(fwnode)) {
|
||||
struct device *dev = to_acpi_device_node(fwnode)->dev.parent;
|
||||
|
||||
if (dev)
|
||||
|
|
|
@ -758,6 +758,8 @@ bool acpi_s2idle_wake(void)
|
|||
return true;
|
||||
}
|
||||
|
||||
pm_pr_dbg("Rearming ACPI SCI for wakeup\n");
|
||||
|
||||
pm_wakeup_clear(acpi_sci_irq);
|
||||
rearm_wake_irq(acpi_sci_irq);
|
||||
}
|
||||
|
|
|
@ -284,6 +284,27 @@ static const struct dmi_system_id acpi_quirk_skip_dmi_ids[] = {
|
|||
.driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS |
|
||||
ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY),
|
||||
},
|
||||
{
|
||||
/* Lenovo Yoga Tablet 1050F/L */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Intel Corp."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "VALLEYVIEW C0 PLATFORM"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "BYT-T FFD8"),
|
||||
/* Partial match on beginning of BIOS version */
|
||||
DMI_MATCH(DMI_BIOS_VERSION, "BLADE_21"),
|
||||
},
|
||||
.driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS |
|
||||
ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY),
|
||||
},
|
||||
{
|
||||
/* Nextbook Ares 8 */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "M890BAP"),
|
||||
},
|
||||
.driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS |
|
||||
ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY),
|
||||
},
|
||||
{
|
||||
/* Whitelabel (sold as various brands) TM800A550L */
|
||||
.matches = {
|
||||
|
|
|
@ -229,8 +229,10 @@ static int __init parse_pmtmr(char *arg)
|
|||
int ret;
|
||||
|
||||
ret = kstrtouint(arg, 16, &base);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (ret) {
|
||||
pr_warn("PMTMR: invalid 'pmtmr=' value: '%s'\n", arg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
pr_info("PMTMR IOPort override: 0x%04x -> 0x%04x\n", pmtmr_ioport,
|
||||
base);
|
||||
|
|
Загрузка…
Ссылка в новой задаче