diff options
-rw-r--r-- | drivers/acpi/Kconfig | 2 | ||||
-rw-r--r-- | drivers/acpi/Makefile | 5 | ||||
-rw-r--r-- | drivers/acpi/apei/apei-base.c | 2 | ||||
-rw-r--r-- | drivers/acpi/apei/bert.c | 31 | ||||
-rw-r--r-- | drivers/acpi/apei/einj.c | 2 | ||||
-rw-r--r-- | drivers/acpi/ec.c | 140 | ||||
-rw-r--r-- | drivers/acpi/processor_driver.c | 72 | ||||
-rw-r--r-- | drivers/acpi/processor_idle.c | 6 | ||||
-rw-r--r-- | drivers/acpi/processor_thermal.c | 54 | ||||
-rw-r--r-- | include/acpi/processor.h | 9 |
10 files changed, 148 insertions, 175 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 1e34f846508f..2457ade3f82d 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -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 diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index b5a8d3e00a52..0002eecbf870 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -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 diff --git a/drivers/acpi/apei/apei-base.c b/drivers/acpi/apei/apei-base.c index 33b7fbbeda82..9f49272cad39 100644 --- a/drivers/acpi/apei/apei-base.c +++ b/drivers/acpi/apei/apei-base.c @@ -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. * diff --git a/drivers/acpi/apei/bert.c b/drivers/acpi/apei/bert.c index 598fd19b65fa..45973aa6e06d 100644 --- a/drivers/acpi/apei/bert.c +++ b/drivers/acpi/apei/bert.c @@ -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) diff --git a/drivers/acpi/apei/einj.c b/drivers/acpi/apei/einj.c index d4326ec12d29..6b583373c58a 100644 --- a/drivers/acpi/apei/einj.c +++ b/drivers/acpi/apei/einj.c @@ -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; diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index a1b871a418f8..c95e535035a0 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -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}, - { - ec_honor_ecdt_gpe, "ASUS FX502VD", { - DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), - DMI_MATCH(DMI_PRODUCT_NAME, "FX502VD"),}, NULL}, - { - 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}, + /* + * 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"), + }, + }, { - /* 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}, + /* + * 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_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"), diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index 368a9edefd0c..1278969eec1f 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c @@ -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; } diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 6a5572a1a80c..13200969ccf3 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -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); diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c index d8b2dfcd59b5..db6ac540e924 100644 --- a/drivers/acpi/processor_thermal.c +++ b/drivers/acpi/processor_thermal.c @@ -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; + } +} diff --git a/include/acpi/processor.h b/include/acpi/processor.h index 194027371928..9fa49686957a 100644 --- a/include/acpi/processor.h +++ b/include/acpi/processor.h @@ -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 |