Merge branches 'acpi-processor', 'acpi-apei' and 'acpi-ec'

Merge ACPI processor driver changes, APEI changes and ACPI EC driver
changes for v5.20-rc1:

 - Drop leftover acpi_processor_get_limit_info() declaration (Riwen Lu).

 - Split out thermal initialization from ACPI PSS (Riwen Lu).

 - Annotate more functions in the ACPI CPU idle driver to live in the
   cpuidle section (Guilherme G. Piccoli).

 - Fix _EINJ vs "special purpose" EFI memory regions (Dan Williams).

 - Implement a better fix to avoid spamming the console with old error
   logs (Tony Luck).

 - Fix typo in a comment in the APEI code (Xiang wangx).

 - Clean up the ACPI EC driver after previous changes in it (Hans
   de Goede).

* acpi-processor:
  ACPI: processor: Drop leftover acpi_processor_get_limit_info() declaration
  ACPI: processor: Split out thermal initialization from ACPI PSS
  ACPI: processor/idle: Annotate more functions to live in cpuidle section

* acpi-apei:
  ACPI: APEI: Fix _EINJ vs EFI_MEMORY_SP
  ACPI: APEI: Better fix to avoid spamming the console with old error logs
  ACPI: APEI: Fix double word in a comment

* acpi-ec:
  ACPI: EC: Drop unused ident initializers from dmi_system_id tables
  ACPI: EC: Re-use boot_ec when possible even when EC_FLAGS_TRUST_DSDT_GPE is set
  ACPI: EC: Drop the EC_FLAGS_IGNORE_DSDT_GPE quirk
  ACPI: EC: Remove duplicate ThinkPad X1 Carbon 6th entry from DMI quirks
This commit is contained in:
Rafael J. Wysocki 2022-07-29 20:08:25 +02:00
commit 198c414ef2
10 changed files with 148 additions and 175 deletions

View File

@ -255,7 +255,6 @@ config ACPI_DOCK
config ACPI_CPU_FREQ_PSS
bool
select THERMAL
config ACPI_PROCESSOR_CSTATE
def_bool y
@ -287,6 +286,7 @@ config ACPI_PROCESSOR
depends on X86 || IA64 || ARM64 || LOONGARCH
select ACPI_PROCESSOR_IDLE
select ACPI_CPU_FREQ_PSS if X86 || IA64 || LOONGARCH
select THERMAL
default y
help
This driver adds support for the ACPI Processor package. It is required

View File

@ -109,10 +109,9 @@ obj-$(CONFIG_ACPI_PPTT) += pptt.o
obj-$(CONFIG_ACPI_PFRUT) += pfr_update.o pfr_telemetry.o
# processor has its own "processor." module_param namespace
processor-y := processor_driver.o
processor-y := processor_driver.o processor_thermal.o
processor-$(CONFIG_ACPI_PROCESSOR_IDLE) += processor_idle.o
processor-$(CONFIG_ACPI_CPU_FREQ_PSS) += processor_throttling.o \
processor_thermal.o
processor-$(CONFIG_ACPI_CPU_FREQ_PSS) += processor_throttling.o
processor-$(CONFIG_CPU_FREQ) += processor_perflib.o
obj-$(CONFIG_ACPI_PROCESSOR_AGGREGATOR) += acpi_pad.o

View File

@ -3,7 +3,7 @@
* apei-base.c - ACPI Platform Error Interface (APEI) supporting
* infrastructure
*
* APEI allows to report errors (for example from the chipset) to the
* APEI allows to report errors (for example from the chipset) to
* the operating system. This improves NMI handling especially. In
* addition it supports error serialization and error injection.
*

View File

@ -29,16 +29,26 @@
#undef pr_fmt
#define pr_fmt(fmt) "BERT: " fmt
#define ACPI_BERT_PRINT_MAX_RECORDS 5
#define ACPI_BERT_PRINT_MAX_LEN 1024
static int bert_disable;
/*
* Print "all" the error records in the BERT table, but avoid huge spam to
* the console if the BIOS included oversize records, or too many records.
* Skipping some records here does not lose anything because the full
* data is available to user tools in:
* /sys/firmware/acpi/tables/data/BERT
*/
static void __init bert_print_all(struct acpi_bert_region *region,
unsigned int region_len)
{
struct acpi_hest_generic_status *estatus =
(struct acpi_hest_generic_status *)region;
int remain = region_len;
int printed = 0, skipped = 0;
u32 estatus_len;
while (remain >= sizeof(struct acpi_bert_region)) {
@ -46,24 +56,26 @@ static void __init bert_print_all(struct acpi_bert_region *region,
if (remain < estatus_len) {
pr_err(FW_BUG "Truncated status block (length: %u).\n",
estatus_len);
return;
break;
}
/* No more error records. */
if (!estatus->block_status)
return;
break;
if (cper_estatus_check(estatus)) {
pr_err(FW_BUG "Invalid error record.\n");
return;
break;
}
pr_info_once("Error records from previous boot:\n");
if (region_len < ACPI_BERT_PRINT_MAX_LEN)
if (estatus_len < ACPI_BERT_PRINT_MAX_LEN &&
printed < ACPI_BERT_PRINT_MAX_RECORDS) {
pr_info_once("Error records from previous boot:\n");
cper_estatus_print(KERN_INFO HW_ERR, estatus);
else
pr_info_once("Max print length exceeded, table data is available at:\n"
"/sys/firmware/acpi/tables/data/BERT");
printed++;
} else {
skipped++;
}
/*
* Because the boot error source is "one-time polled" type,
@ -75,6 +87,9 @@ static void __init bert_print_all(struct acpi_bert_region *region,
estatus = (void *)estatus + estatus_len;
remain -= estatus_len;
}
if (skipped)
pr_info(HW_ERR "Skipped %d error records\n", skipped);
}
static int __init setup_bert_disable(char *str)

View File

@ -546,6 +546,8 @@ static int einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2,
!= REGION_INTERSECTS) &&
(region_intersects(base_addr, size, IORESOURCE_MEM, IORES_DESC_PERSISTENT_MEMORY)
!= REGION_INTERSECTS) &&
(region_intersects(base_addr, size, IORESOURCE_MEM, IORES_DESC_SOFT_RESERVED)
!= REGION_INTERSECTS) &&
!arch_is_platform_page(base_addr)))
return -EINVAL;

View File

@ -180,7 +180,6 @@ static struct workqueue_struct *ec_wq;
static struct workqueue_struct *ec_query_wq;
static int EC_FLAGS_CORRECT_ECDT; /* Needs ECDT port address correction */
static int EC_FLAGS_IGNORE_DSDT_GPE; /* Needs ECDT GPE as correction setting */
static int EC_FLAGS_TRUST_DSDT_GPE; /* Needs DSDT GPE as correction setting */
static int EC_FLAGS_CLEAR_ON_RESUME; /* Needs acpi_ec_clear() on boot/resume */
@ -1407,24 +1406,16 @@ ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval)
if (ec->data_addr == 0 || ec->command_addr == 0)
return AE_OK;
if (boot_ec && boot_ec_is_ecdt && EC_FLAGS_IGNORE_DSDT_GPE) {
/*
* Always inherit the GPE number setting from the ECDT
* EC.
*/
ec->gpe = boot_ec->gpe;
} else {
/* Get GPE bit assignment (EC events). */
/* TODO: Add support for _GPE returning a package */
status = acpi_evaluate_integer(handle, "_GPE", NULL, &tmp);
if (ACPI_SUCCESS(status))
ec->gpe = tmp;
/* Get GPE bit assignment (EC events). */
/* TODO: Add support for _GPE returning a package */
status = acpi_evaluate_integer(handle, "_GPE", NULL, &tmp);
if (ACPI_SUCCESS(status))
ec->gpe = tmp;
/*
* Errors are non-fatal, allowing for ACPI Reduced Hardware
* platforms which use GpioInt instead of GPE.
*/
/*
* Errors are non-fatal, allowing for ACPI Reduced Hardware
* platforms which use GpioInt instead of GPE.
*/
}
/* Use the global lock for all EC transactions? */
tmp = 0;
acpi_evaluate_integer(handle, "_GLK", NULL, &tmp);
@ -1626,15 +1617,18 @@ static int acpi_ec_add(struct acpi_device *device)
}
if (boot_ec && ec->command_addr == boot_ec->command_addr &&
ec->data_addr == boot_ec->data_addr &&
!EC_FLAGS_TRUST_DSDT_GPE) {
ec->data_addr == boot_ec->data_addr) {
/*
* Trust PNP0C09 namespace location rather than
* ECDT ID. But trust ECDT GPE rather than _GPE
* because of ASUS quirks, so do not change
* boot_ec->gpe to ec->gpe.
* Trust PNP0C09 namespace location rather than ECDT ID.
* But trust ECDT GPE rather than _GPE because of ASUS
* quirks. So do not change boot_ec->gpe to ec->gpe,
* except when the TRUST_DSDT_GPE quirk is set.
*/
boot_ec->handle = ec->handle;
if (EC_FLAGS_TRUST_DSDT_GPE)
boot_ec->gpe = ec->gpe;
acpi_handle_debug(ec->handle, "duplicated.\n");
acpi_ec_free(ec);
ec = boot_ec;
@ -1862,68 +1856,40 @@ static int ec_honor_dsdt_gpe(const struct dmi_system_id *id)
return 0;
}
/*
* Some DSDTs contain wrong GPE setting.
* Asus FX502VD/VE, GL702VMK, X550VXK, X580VD
* https://bugzilla.kernel.org/show_bug.cgi?id=195651
*/
static int ec_honor_ecdt_gpe(const struct dmi_system_id *id)
{
pr_debug("Detected system needing ignore DSDT GPE setting.\n");
EC_FLAGS_IGNORE_DSDT_GPE = 1;
return 0;
}
static const struct dmi_system_id ec_dmi_table[] __initconst = {
{
ec_correct_ecdt, "MSI MS-171F", {
DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star"),
DMI_MATCH(DMI_PRODUCT_NAME, "MS-171F"),}, NULL},
/*
* MSI MS-171F
* https://bugzilla.kernel.org/show_bug.cgi?id=12461
*/
.callback = ec_correct_ecdt,
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star"),
DMI_MATCH(DMI_PRODUCT_NAME, "MS-171F"),
},
},
{
ec_honor_ecdt_gpe, "ASUS FX502VD", {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_PRODUCT_NAME, "FX502VD"),}, NULL},
/*
* HP Pavilion Gaming Laptop 15-cx0xxx
* https://bugzilla.kernel.org/show_bug.cgi?id=209989
*/
.callback = ec_honor_dsdt_gpe,
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "HP"),
DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion Gaming Laptop 15-cx0xxx"),
},
},
{
ec_honor_ecdt_gpe, "ASUS FX502VE", {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_PRODUCT_NAME, "FX502VE"),}, NULL},
{
ec_honor_ecdt_gpe, "ASUS GL702VMK", {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_PRODUCT_NAME, "GL702VMK"),}, NULL},
{
ec_honor_ecdt_gpe, "ASUSTeK COMPUTER INC. X505BA", {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_PRODUCT_NAME, "X505BA"),}, NULL},
{
ec_honor_ecdt_gpe, "ASUSTeK COMPUTER INC. X505BP", {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_PRODUCT_NAME, "X505BP"),}, NULL},
{
ec_honor_ecdt_gpe, "ASUSTeK COMPUTER INC. X542BA", {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_PRODUCT_NAME, "X542BA"),}, NULL},
{
ec_honor_ecdt_gpe, "ASUSTeK COMPUTER INC. X542BP", {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_PRODUCT_NAME, "X542BP"),}, NULL},
{
ec_honor_ecdt_gpe, "ASUS X550VXK", {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_PRODUCT_NAME, "X550VXK"),}, NULL},
{
ec_honor_ecdt_gpe, "ASUS X580VD", {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_PRODUCT_NAME, "X580VD"),}, NULL},
{
/* https://bugzilla.kernel.org/show_bug.cgi?id=209989 */
ec_honor_dsdt_gpe, "HP Pavilion Gaming Laptop 15-cx0xxx", {
DMI_MATCH(DMI_SYS_VENDOR, "HP"),
DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion Gaming Laptop 15-cx0xxx"),}, NULL},
{
ec_clear_on_resume, "Samsung hardware", {
DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD.")}, NULL},
{},
/*
* Samsung hardware
* https://bugzilla.kernel.org/show_bug.cgi?id=44161
*/
.callback = ec_clear_on_resume,
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
},
},
{}
};
void __init acpi_ec_ecdt_probe(void)
@ -2201,28 +2167,18 @@ static int acpi_ec_init_workqueues(void)
static const struct dmi_system_id acpi_ec_no_wakeup[] = {
{
.ident = "Thinkpad X1 Carbon 6th",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_FAMILY, "Thinkpad X1 Carbon 6th"),
},
},
{
.ident = "ThinkPad X1 Carbon 6th",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_FAMILY, "ThinkPad X1 Carbon 6th"),
},
},
{
.ident = "ThinkPad X1 Yoga 3rd",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_FAMILY, "ThinkPad X1 Yoga 3rd"),
},
},
{
.ident = "HP ZHAN 66 Pro",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "HP"),
DMI_MATCH(DMI_PRODUCT_FAMILY, "103C_5336AN HP ZHAN 66 Pro"),

View File

@ -139,75 +139,17 @@ static int acpi_soft_cpu_dead(unsigned int cpu)
}
#ifdef CONFIG_ACPI_CPU_FREQ_PSS
static int acpi_pss_perf_init(struct acpi_processor *pr,
struct acpi_device *device)
static void acpi_pss_perf_init(struct acpi_processor *pr)
{
int result = 0;
acpi_processor_ppc_has_changed(pr, 0);
acpi_processor_get_throttling_info(pr);
if (pr->flags.throttling)
pr->flags.limit = 1;
pr->cdev = thermal_cooling_device_register("Processor", device,
&processor_cooling_ops);
if (IS_ERR(pr->cdev)) {
result = PTR_ERR(pr->cdev);
return result;
}
dev_dbg(&device->dev, "registered as cooling_device%d\n",
pr->cdev->id);
result = sysfs_create_link(&device->dev.kobj,
&pr->cdev->device.kobj,
"thermal_cooling");
if (result) {
dev_err(&device->dev,
"Failed to create sysfs link 'thermal_cooling'\n");
goto err_thermal_unregister;
}
result = sysfs_create_link(&pr->cdev->device.kobj,
&device->dev.kobj,
"device");
if (result) {
dev_err(&pr->cdev->device,
"Failed to create sysfs link 'device'\n");
goto err_remove_sysfs_thermal;
}
return 0;
err_remove_sysfs_thermal:
sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
err_thermal_unregister:
thermal_cooling_device_unregister(pr->cdev);
return result;
}
static void acpi_pss_perf_exit(struct acpi_processor *pr,
struct acpi_device *device)
{
if (pr->cdev) {
sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
sysfs_remove_link(&pr->cdev->device.kobj, "device");
thermal_cooling_device_unregister(pr->cdev);
pr->cdev = NULL;
}
}
#else
static inline int acpi_pss_perf_init(struct acpi_processor *pr,
struct acpi_device *device)
{
return 0;
}
static inline void acpi_pss_perf_exit(struct acpi_processor *pr,
struct acpi_device *device) {}
static inline void acpi_pss_perf_init(struct acpi_processor *pr) {}
#endif /* CONFIG_ACPI_CPU_FREQ_PSS */
static int __acpi_processor_start(struct acpi_device *device)
@ -229,7 +171,9 @@ static int __acpi_processor_start(struct acpi_device *device)
if (!cpuidle_get_driver() || cpuidle_get_driver() == &acpi_idle_driver)
acpi_processor_power_init(pr);
result = acpi_pss_perf_init(pr, device);
acpi_pss_perf_init(pr);
result = acpi_processor_thermal_init(pr, device);
if (result)
goto err_power_exit;
@ -239,7 +183,7 @@ static int __acpi_processor_start(struct acpi_device *device)
return 0;
result = -ENODEV;
acpi_pss_perf_exit(pr, device);
acpi_processor_thermal_exit(pr, device);
err_power_exit:
acpi_processor_power_exit(pr);
@ -277,10 +221,10 @@ static int acpi_processor_stop(struct device *dev)
return 0;
acpi_processor_power_exit(pr);
acpi_pss_perf_exit(pr, device);
acpi_cppc_processor_exit(pr);
acpi_processor_thermal_exit(pr, device);
return 0;
}

View File

@ -607,7 +607,7 @@ static DEFINE_RAW_SPINLOCK(c3_lock);
* @cx: Target state context
* @index: index of target state
*/
static int acpi_idle_enter_bm(struct cpuidle_driver *drv,
static int __cpuidle acpi_idle_enter_bm(struct cpuidle_driver *drv,
struct acpi_processor *pr,
struct acpi_processor_cx *cx,
int index)
@ -664,7 +664,7 @@ static int acpi_idle_enter_bm(struct cpuidle_driver *drv,
return index;
}
static int acpi_idle_enter(struct cpuidle_device *dev,
static int __cpuidle acpi_idle_enter(struct cpuidle_device *dev,
struct cpuidle_driver *drv, int index)
{
struct acpi_processor_cx *cx = per_cpu(acpi_cstate[index], dev->cpu);
@ -693,7 +693,7 @@ static int acpi_idle_enter(struct cpuidle_device *dev,
return index;
}
static int acpi_idle_enter_s2idle(struct cpuidle_device *dev,
static int __cpuidle acpi_idle_enter_s2idle(struct cpuidle_device *dev,
struct cpuidle_driver *drv, int index)
{
struct acpi_processor_cx *cx = per_cpu(acpi_cstate[index], dev->cpu);

View File

@ -266,3 +266,57 @@ const struct thermal_cooling_device_ops processor_cooling_ops = {
.get_cur_state = processor_get_cur_state,
.set_cur_state = processor_set_cur_state,
};
int acpi_processor_thermal_init(struct acpi_processor *pr,
struct acpi_device *device)
{
int result = 0;
pr->cdev = thermal_cooling_device_register("Processor", device,
&processor_cooling_ops);
if (IS_ERR(pr->cdev)) {
result = PTR_ERR(pr->cdev);
return result;
}
dev_dbg(&device->dev, "registered as cooling_device%d\n",
pr->cdev->id);
result = sysfs_create_link(&device->dev.kobj,
&pr->cdev->device.kobj,
"thermal_cooling");
if (result) {
dev_err(&device->dev,
"Failed to create sysfs link 'thermal_cooling'\n");
goto err_thermal_unregister;
}
result = sysfs_create_link(&pr->cdev->device.kobj,
&device->dev.kobj,
"device");
if (result) {
dev_err(&pr->cdev->device,
"Failed to create sysfs link 'device'\n");
goto err_remove_sysfs_thermal;
}
return 0;
err_remove_sysfs_thermal:
sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
err_thermal_unregister:
thermal_cooling_device_unregister(pr->cdev);
return result;
}
void acpi_processor_thermal_exit(struct acpi_processor *pr,
struct acpi_device *device)
{
if (pr->cdev) {
sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
sysfs_remove_link(&pr->cdev->device.kobj, "device");
thermal_cooling_device_unregister(pr->cdev);
pr->cdev = NULL;
}
}

View File

@ -441,9 +441,12 @@ static inline int acpi_processor_hotplug(struct acpi_processor *pr)
#endif /* CONFIG_ACPI_PROCESSOR_IDLE */
/* in processor_thermal.c */
int acpi_processor_get_limit_info(struct acpi_processor *pr);
int acpi_processor_thermal_init(struct acpi_processor *pr,
struct acpi_device *device);
void acpi_processor_thermal_exit(struct acpi_processor *pr,
struct acpi_device *device);
extern const struct thermal_cooling_device_ops processor_cooling_ops;
#if defined(CONFIG_ACPI_CPU_FREQ_PSS) & defined(CONFIG_CPU_FREQ)
#ifdef CONFIG_CPU_FREQ
void acpi_thermal_cpufreq_init(struct cpufreq_policy *policy);
void acpi_thermal_cpufreq_exit(struct cpufreq_policy *policy);
#else
@ -455,6 +458,6 @@ static inline void acpi_thermal_cpufreq_exit(struct cpufreq_policy *policy)
{
return;
}
#endif /* CONFIG_ACPI_CPU_FREQ_PSS */
#endif /* CONFIG_CPU_FREQ */
#endif