diff options
Diffstat (limited to 'drivers/acpi')
55 files changed, 657 insertions, 372 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 1cc11d2a2a88..ccbeab9500ec 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -564,6 +564,16 @@ config ACPI_PCC Enable this feature if you want to set up and install the PCC Address Space handler to handle PCC OpRegion in the firmware. +config ACPI_FFH + bool "ACPI FFH Address Space" + default n + help + The FFH(Fixed Function Hardware) Address Space also referred as FFH + Operation Region allows to define platform specific opregion. + + Enable this feature if you want to set up and install the FFH Address + Space handler to handle FFH OpRegion in the firmware. + source "drivers/acpi/pmic/Kconfig" config ACPI_VIOT diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 0002eecbf870..feb36c0b9446 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -68,6 +68,7 @@ acpi-$(CONFIG_ACPI_GENERIC_GSI) += irq.o acpi-$(CONFIG_ACPI_WATCHDOG) += acpi_watchdog.o acpi-$(CONFIG_ACPI_PRMT) += prmt.o acpi-$(CONFIG_ACPI_PCC) += acpi_pcc.o +acpi-$(CONFIG_ACPI_FFH) += acpi_ffh.o # Address translation acpi-$(CONFIG_ACPI_ADXL) += acpi_adxl.o diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index bb9fe7984b1a..1ace70b831cd 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c @@ -33,7 +33,7 @@ MODULE_DESCRIPTION("ACPI AC Adapter Driver"); MODULE_LICENSE("GPL"); static int acpi_ac_add(struct acpi_device *device); -static int acpi_ac_remove(struct acpi_device *device); +static void acpi_ac_remove(struct acpi_device *device); static void acpi_ac_notify(struct acpi_device *device, u32 event); static const struct acpi_device_id ac_device_ids[] = { @@ -288,12 +288,12 @@ static int acpi_ac_resume(struct device *dev) #define acpi_ac_resume NULL #endif -static int acpi_ac_remove(struct acpi_device *device) +static void acpi_ac_remove(struct acpi_device *device) { struct acpi_ac *ac = NULL; if (!device || !acpi_driver_data(device)) - return -EINVAL; + return; ac = acpi_driver_data(device); @@ -301,8 +301,6 @@ static int acpi_ac_remove(struct acpi_device *device) unregister_acpi_notifier(&ac->battery_nb); kfree(ac); - - return 0; } static int __init acpi_ac_init(void) diff --git a/drivers/acpi/acpi_ffh.c b/drivers/acpi/acpi_ffh.c new file mode 100644 index 000000000000..19aff808bbb8 --- /dev/null +++ b/drivers/acpi/acpi_ffh.c @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Author: Sudeep Holla <sudeep.holla@arm.com> + * Copyright 2022 Arm Limited + */ +#include <linux/kernel.h> +#include <linux/acpi.h> +#include <linux/completion.h> +#include <linux/idr.h> +#include <linux/io.h> + +#include <linux/arm-smccc.h> + +static struct acpi_ffh_info ffh_ctx; + +int __weak acpi_ffh_address_space_arch_setup(void *handler_ctxt, + void **region_ctxt) +{ + return -EOPNOTSUPP; +} + +int __weak acpi_ffh_address_space_arch_handler(acpi_integer *value, + void *region_context) +{ + return -EOPNOTSUPP; +} + +static acpi_status +acpi_ffh_address_space_setup(acpi_handle region_handle, u32 function, + void *handler_context, void **region_context) +{ + return acpi_ffh_address_space_arch_setup(handler_context, + region_context); +} + +static acpi_status +acpi_ffh_address_space_handler(u32 function, acpi_physical_address addr, + u32 bits, acpi_integer *value, + void *handler_context, void *region_context) +{ + return acpi_ffh_address_space_arch_handler(value, region_context); +} + +void __init acpi_init_ffh(void) +{ + acpi_status status; + + status = acpi_install_address_space_handler(ACPI_ROOT_OBJECT, + ACPI_ADR_SPACE_FIXED_HARDWARE, + &acpi_ffh_address_space_handler, + &acpi_ffh_address_space_setup, + &ffh_ctx); + if (ACPI_FAILURE(status)) + pr_alert("OperationRegion handler could not be installed\n"); +} diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c index ec0e22a1e25d..02f1a1b1143c 100644 --- a/drivers/acpi/acpi_pad.c +++ b/drivers/acpi/acpi_pad.c @@ -287,7 +287,7 @@ static ssize_t rrtime_store(struct device *dev, static ssize_t rrtime_show(struct device *dev, struct device_attribute *attr, char *buf) { - return scnprintf(buf, PAGE_SIZE, "%d\n", round_robin_time); + return sysfs_emit(buf, "%d\n", round_robin_time); } static DEVICE_ATTR_RW(rrtime); @@ -309,7 +309,7 @@ static ssize_t idlepct_store(struct device *dev, static ssize_t idlepct_show(struct device *dev, struct device_attribute *attr, char *buf) { - return scnprintf(buf, PAGE_SIZE, "%d\n", idle_pct); + return sysfs_emit(buf, "%d\n", idle_pct); } static DEVICE_ATTR_RW(idlepct); @@ -449,7 +449,7 @@ static int acpi_pad_add(struct acpi_device *device) return 0; } -static int acpi_pad_remove(struct acpi_device *device) +static void acpi_pad_remove(struct acpi_device *device) { mutex_lock(&isolated_cpus_lock); acpi_pad_idle_cpus(0); @@ -458,7 +458,6 @@ static int acpi_pad_remove(struct acpi_device *device) acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY, acpi_pad_notify); acpi_pad_remove_sysfs(device); - return 0; } static const struct acpi_device_id pad_device_ids[] = { diff --git a/drivers/acpi/acpi_pcc.c b/drivers/acpi/acpi_pcc.c index 3e252be047b8..07a034a53aca 100644 --- a/drivers/acpi/acpi_pcc.c +++ b/drivers/acpi/acpi_pcc.c @@ -53,6 +53,7 @@ acpi_pcc_address_space_setup(acpi_handle region_handle, u32 function, struct pcc_data *data; struct acpi_pcc_info *ctx = handler_context; struct pcc_mbox_chan *pcc_chan; + static acpi_status ret; data = kzalloc(sizeof(*data), GFP_KERNEL); if (!data) @@ -69,23 +70,35 @@ acpi_pcc_address_space_setup(acpi_handle region_handle, u32 function, if (IS_ERR(data->pcc_chan)) { pr_err("Failed to find PCC channel for subspace %d\n", ctx->subspace_id); - kfree(data); - return AE_NOT_FOUND; + ret = AE_NOT_FOUND; + goto err_free_data; } pcc_chan = data->pcc_chan; + if (!pcc_chan->mchan->mbox->txdone_irq) { + pr_err("This channel-%d does not support interrupt.\n", + ctx->subspace_id); + ret = AE_SUPPORT; + goto err_free_channel; + } data->pcc_comm_addr = acpi_os_ioremap(pcc_chan->shmem_base_addr, pcc_chan->shmem_size); if (!data->pcc_comm_addr) { pr_err("Failed to ioremap PCC comm region mem for %d\n", ctx->subspace_id); - pcc_mbox_free_channel(data->pcc_chan); - kfree(data); - return AE_NO_MEMORY; + ret = AE_NO_MEMORY; + goto err_free_channel; } *region_context = data; return AE_OK; + +err_free_channel: + pcc_mbox_free_channel(data->pcc_chan); +err_free_data: + kfree(data); + + return ret; } static acpi_status @@ -106,19 +119,17 @@ acpi_pcc_address_space_handler(u32 function, acpi_physical_address addr, if (ret < 0) return AE_ERROR; - if (data->pcc_chan->mchan->mbox->txdone_irq) { - /* - * pcc_chan->latency is just a Nominal value. In reality the remote - * processor could be much slower to reply. So add an arbitrary - * amount of wait on top of Nominal. - */ - usecs_lat = PCC_CMD_WAIT_RETRIES_NUM * data->pcc_chan->latency; - ret = wait_for_completion_timeout(&data->done, - usecs_to_jiffies(usecs_lat)); - if (ret == 0) { - pr_err("PCC command executed timeout!\n"); - return AE_TIME; - } + /* + * pcc_chan->latency is just a Nominal value. In reality the remote + * processor could be much slower to reply. So add an arbitrary + * amount of wait on top of Nominal. + */ + usecs_lat = PCC_CMD_WAIT_RETRIES_NUM * data->pcc_chan->latency; + ret = wait_for_completion_timeout(&data->done, + usecs_to_jiffies(usecs_lat)); + if (ret == 0) { + pr_err("PCC command executed timeout!\n"); + return AE_TIME; } mbox_chan_txdone(data->pcc_chan->mchan, ret); diff --git a/drivers/acpi/acpi_video.c b/drivers/acpi/acpi_video.c index 32953646caeb..30d8fd03fec7 100644 --- a/drivers/acpi/acpi_video.c +++ b/drivers/acpi/acpi_video.c @@ -86,7 +86,7 @@ static DEFINE_MUTEX(register_count_mutex); static DEFINE_MUTEX(video_list_lock); static LIST_HEAD(video_bus_head); static int acpi_video_bus_add(struct acpi_device *device); -static int acpi_video_bus_remove(struct acpi_device *device); +static void acpi_video_bus_remove(struct acpi_device *device); static void acpi_video_bus_notify(struct acpi_device *device, u32 event); static void acpi_video_bus_register_backlight_work(struct work_struct *ignored); static DECLARE_DELAYED_WORK(video_bus_register_backlight_work, @@ -2067,13 +2067,13 @@ err_free_video: return error; } -static int acpi_video_bus_remove(struct acpi_device *device) +static void acpi_video_bus_remove(struct acpi_device *device) { struct acpi_video_bus *video = NULL; if (!device || !acpi_driver_data(device)) - return -EINVAL; + return; video = acpi_driver_data(device); @@ -2087,8 +2087,6 @@ static int acpi_video_bus_remove(struct acpi_device *device) kfree(video->attached_array); kfree(video); - - return 0; } static void acpi_video_bus_register_backlight_work(struct work_struct *ignored) diff --git a/drivers/acpi/acpica/Makefile b/drivers/acpi/acpica/Makefile index 59700433a96e..9e0d95d76fff 100644 --- a/drivers/acpi/acpica/Makefile +++ b/drivers/acpi/acpica/Makefile @@ -155,6 +155,7 @@ acpi-y += \ utalloc.o \ utascii.o \ utbuffer.o \ + utcksum.o \ utcopy.o \ utexcep.o \ utdebug.o \ diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h index 088d6a7d052c..777457a58340 100644 --- a/drivers/acpi/acpica/acglobal.h +++ b/drivers/acpi/acpica/acglobal.h @@ -24,6 +24,7 @@ ACPI_GLOBAL(struct acpi_table_list, acpi_gbl_root_table_list); ACPI_GLOBAL(struct acpi_table_header *, acpi_gbl_DSDT); ACPI_GLOBAL(struct acpi_table_header, acpi_gbl_original_dsdt_header); +ACPI_INIT_GLOBAL(char *, acpi_gbl_CDAT, NULL); ACPI_INIT_GLOBAL(u32, acpi_gbl_dsdt_index, ACPI_INVALID_TABLE_INDEX); ACPI_INIT_GLOBAL(u32, acpi_gbl_facs_index, ACPI_INVALID_TABLE_INDEX); ACPI_INIT_GLOBAL(u32, acpi_gbl_xfacs_index, ACPI_INVALID_TABLE_INDEX); diff --git a/drivers/acpi/acpica/actables.h b/drivers/acpi/acpica/actables.h index f8d7bfd737df..1c29325e4c7f 100644 --- a/drivers/acpi/acpica/actables.h +++ b/drivers/acpi/acpica/actables.h @@ -124,11 +124,6 @@ void acpi_tb_print_table_header(acpi_physical_address address, struct acpi_table_header *header); -u8 acpi_tb_checksum(u8 *buffer, u32 length); - -acpi_status -acpi_tb_verify_checksum(struct acpi_table_header *table, u32 length); - void acpi_tb_check_dsdt_header(void); struct acpi_table_header *acpi_tb_copy_dsdt(u32 table_index); diff --git a/drivers/acpi/acpica/acutils.h b/drivers/acpi/acpica/acutils.h index 6e6270f96bfb..71175b664f49 100644 --- a/drivers/acpi/acpica/acutils.h +++ b/drivers/acpi/acpica/acutils.h @@ -159,6 +159,19 @@ u8 acpi_ut_valid_name_char(char character, u32 position); void acpi_ut_check_and_repair_ascii(u8 *name, char *repaired_name, u32 count); /* + * utcksum - Checksum utilities + */ +u8 acpi_ut_generate_checksum(void *table, u32 length, u8 original_checksum); + +u8 acpi_ut_checksum(u8 *buffer, u32 length); + +acpi_status +acpi_ut_verify_cdat_checksum(struct acpi_table_cdat *cdat_table, u32 length); + +acpi_status +acpi_ut_verify_checksum(struct acpi_table_header *table, u32 length); + +/* * utnonansi - Non-ANSI C library functions */ void acpi_ut_strupr(char *src_string); diff --git a/drivers/acpi/acpica/dsmethod.c b/drivers/acpi/acpica/dsmethod.c index ae2e768830bf..9332bc688713 100644 --- a/drivers/acpi/acpica/dsmethod.c +++ b/drivers/acpi/acpica/dsmethod.c @@ -517,7 +517,7 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread, info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); if (!info) { status = AE_NO_MEMORY; - goto cleanup; + goto pop_walk_state; } info->parameters = &this_walk_state->operands[0]; @@ -529,7 +529,7 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread, ACPI_FREE(info); if (ACPI_FAILURE(status)) { - goto cleanup; + goto pop_walk_state; } next_walk_state->method_nesting_depth = @@ -575,6 +575,12 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread, return_ACPI_STATUS(status); +pop_walk_state: + + /* On error, pop the walk state to be deleted from thread */ + + acpi_ds_pop_walk_state(thread); + cleanup: /* On error, we must terminate the method properly */ diff --git a/drivers/acpi/acpica/evevent.c b/drivers/acpi/acpica/evevent.c index df596d46dd97..82d1728b9bc6 100644 --- a/drivers/acpi/acpica/evevent.c +++ b/drivers/acpi/acpica/evevent.c @@ -142,6 +142,9 @@ static acpi_status acpi_ev_fixed_event_initialize(void) status = acpi_write_bit_register(acpi_gbl_fixed_event_info [i].enable_register_id, + (i == + ACPI_EVENT_PCIE_WAKE) ? + ACPI_ENABLE_EVENT : ACPI_DISABLE_EVENT); if (ACPI_FAILURE(status)) { return (status); @@ -185,6 +188,11 @@ u32 acpi_ev_fixed_event_detect(void) return (int_status); } + if (fixed_enable & ACPI_BITMASK_PCIEXP_WAKE_DISABLE) + fixed_enable &= ~ACPI_BITMASK_PCIEXP_WAKE_DISABLE; + else + fixed_enable |= ACPI_BITMASK_PCIEXP_WAKE_DISABLE; + ACPI_DEBUG_PRINT((ACPI_DB_INTERRUPTS, "Fixed Event Block: Enable %08X Status %08X\n", fixed_enable, fixed_status)); @@ -250,6 +258,9 @@ static u32 acpi_ev_fixed_event_dispatch(u32 event) if (!acpi_gbl_fixed_event_handlers[event].handler) { (void)acpi_write_bit_register(acpi_gbl_fixed_event_info[event]. enable_register_id, + (event == + ACPI_EVENT_PCIE_WAKE) ? + ACPI_ENABLE_EVENT : ACPI_DISABLE_EVENT); ACPI_ERROR((AE_INFO, diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c index b96b3a7e78e5..d035092799eb 100644 --- a/drivers/acpi/acpica/evregion.c +++ b/drivers/acpi/acpica/evregion.c @@ -172,6 +172,15 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, ctx->subspace_id = (u8)region_obj->region.address; } + if (region_obj->region.space_id == + ACPI_ADR_SPACE_FIXED_HARDWARE) { + struct acpi_ffh_info *ctx = + handler_desc->address_space.context; + + ctx->length = region_obj->region.length; + ctx->offset = region_obj->region.address; + } + /* * We must exit the interpreter because the region setup will * potentially execute control methods (for example, the _REG method diff --git a/drivers/acpi/acpica/exconfig.c b/drivers/acpi/acpica/exconfig.c index d7d74ef87b18..e82faabdf907 100644 --- a/drivers/acpi/acpica/exconfig.c +++ b/drivers/acpi/acpica/exconfig.c @@ -295,8 +295,8 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, target)); } if (target->common.type != ACPI_TYPE_INTEGER) { - ACPI_EXCEPTION((AE_INFO, AE_TYPE, - "Type not integer: %X\n", target->common.type)); + ACPI_ERROR((AE_INFO, "Type not integer: %X", + target->common.type)); return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } diff --git a/drivers/acpi/acpica/exfield.c b/drivers/acpi/acpica/exfield.c index 2b89a496de65..657f4002f9dc 100644 --- a/drivers/acpi/acpica/exfield.c +++ b/drivers/acpi/acpica/exfield.c @@ -141,7 +141,9 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, || obj_desc->field.region_obj->region.space_id == ACPI_ADR_SPACE_IPMI || obj_desc->field.region_obj->region.space_id == - ACPI_ADR_SPACE_PLATFORM_RT)) { + ACPI_ADR_SPACE_PLATFORM_RT + || obj_desc->field.region_obj->region.space_id == + ACPI_ADR_SPACE_FIXED_HARDWARE)) { /* SMBus, GSBus, IPMI serial */ @@ -305,7 +307,9 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, || obj_desc->field.region_obj->region.space_id == ACPI_ADR_SPACE_IPMI || obj_desc->field.region_obj->region.space_id == - ACPI_ADR_SPACE_PLATFORM_RT)) { + ACPI_ADR_SPACE_PLATFORM_RT + || obj_desc->field.region_obj->region.space_id == + ACPI_ADR_SPACE_FIXED_HARDWARE)) { /* SMBus, GSBus, IPMI serial */ diff --git a/drivers/acpi/acpica/exserial.c b/drivers/acpi/acpica/exserial.c index 4da20d7845df..fd63f2042514 100644 --- a/drivers/acpi/acpica/exserial.c +++ b/drivers/acpi/acpica/exserial.c @@ -323,6 +323,12 @@ acpi_ex_write_serial_bus(union acpi_operand_object *source_desc, function = ACPI_WRITE; break; + case ACPI_ADR_SPACE_FIXED_HARDWARE: + + buffer_length = ACPI_FFH_INPUT_BUFFER_SIZE; + function = ACPI_WRITE; + break; + default: return_ACPI_STATUS(AE_AML_INVALID_SPACE_ID); } diff --git a/drivers/acpi/acpica/hwsleep.c b/drivers/acpi/acpica/hwsleep.c index bd936476dda9..37b3f641feaa 100644 --- a/drivers/acpi/acpica/hwsleep.c +++ b/drivers/acpi/acpica/hwsleep.c @@ -311,6 +311,20 @@ acpi_status acpi_hw_legacy_wake(u8 sleep_state) [ACPI_EVENT_SLEEP_BUTTON]. status_register_id, ACPI_CLEAR_STATUS); + /* Enable pcie wake event if support */ + if ((acpi_gbl_FADT.flags & ACPI_FADT_PCI_EXPRESS_WAKE)) { + (void) + acpi_write_bit_register(acpi_gbl_fixed_event_info + [ACPI_EVENT_PCIE_WAKE]. + enable_register_id, + ACPI_DISABLE_EVENT); + (void) + acpi_write_bit_register(acpi_gbl_fixed_event_info + [ACPI_EVENT_PCIE_WAKE]. + status_register_id, + ACPI_CLEAR_STATUS); + } + acpi_hw_execute_sleep_method(METHOD_PATHNAME__SST, ACPI_SST_WORKING); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/tbdata.c b/drivers/acpi/acpica/tbdata.c index a7642b34ce48..1f7677e0dbbe 100644 --- a/drivers/acpi/acpica/tbdata.c +++ b/drivers/acpi/acpica/tbdata.c @@ -522,7 +522,7 @@ acpi_tb_verify_temp_table(struct acpi_table_desc *table_desc, /* Verify the checksum */ status = - acpi_tb_verify_checksum(table_desc->pointer, + acpi_ut_verify_checksum(table_desc->pointer, table_desc->length); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, AE_NO_MEMORY, diff --git a/drivers/acpi/acpica/tbfadt.c b/drivers/acpi/acpica/tbfadt.c index 31d7ea84a360..f04dc6051320 100644 --- a/drivers/acpi/acpica/tbfadt.c +++ b/drivers/acpi/acpica/tbfadt.c @@ -298,7 +298,7 @@ void acpi_tb_parse_fadt(void) * Validate the FADT checksum before we copy the table. Ignore * checksum error as we want to try to get the DSDT and FACS. */ - (void)acpi_tb_verify_checksum(table, length); + (void)acpi_ut_verify_checksum(table, length); /* Create a local copy of the FADT in common ACPI 2.0+ format */ diff --git a/drivers/acpi/acpica/tbprint.c b/drivers/acpi/acpica/tbprint.c index 595547db28c0..f07aa9b46f3f 100644 --- a/drivers/acpi/acpica/tbprint.c +++ b/drivers/acpi/acpica/tbprint.c @@ -10,6 +10,7 @@ #include <acpi/acpi.h> #include "accommon.h" #include "actables.h" +#include "acutils.h" #define _COMPONENT ACPI_TABLES ACPI_MODULE_NAME("tbprint") @@ -39,7 +40,7 @@ static void acpi_tb_fix_string(char *string, acpi_size length) { while (length && *string) { - if (!isprint((int)*string)) { + if (!isprint((int)(u8)*string)) { *string = '?'; } @@ -135,77 +136,3 @@ acpi_tb_print_table_header(acpi_physical_address address, local_header.asl_compiler_revision)); } } - -/******************************************************************************* - * - * FUNCTION: acpi_tb_validate_checksum - * - * PARAMETERS: table - ACPI table to verify - * length - Length of entire table - * - * RETURN: Status - * - * DESCRIPTION: Verifies that the table checksums to zero. Optionally returns - * exception on bad checksum. - * - ******************************************************************************/ - -acpi_status acpi_tb_verify_checksum(struct acpi_table_header *table, u32 length) -{ - u8 checksum; - - /* - * FACS/S3PT: - * They are the odd tables, have no standard ACPI header and no checksum - */ - - if (ACPI_COMPARE_NAMESEG(table->signature, ACPI_SIG_S3PT) || - ACPI_COMPARE_NAMESEG(table->signature, ACPI_SIG_FACS)) { - return (AE_OK); - } - - /* Compute the checksum on the table */ - - checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, table), length); - - /* Checksum ok? (should be zero) */ - - if (checksum) { - ACPI_BIOS_WARNING((AE_INFO, - "Incorrect checksum in table [%4.4s] - 0x%2.2X, " - "should be 0x%2.2X", - table->signature, table->checksum, - (u8)(table->checksum - checksum))); - -#if (ACPI_CHECKSUM_ABORT) - return (AE_BAD_CHECKSUM); -#endif - } - - return (AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_tb_checksum - * - * PARAMETERS: buffer - Pointer to memory region to be checked - * length - Length of this memory region - * - * RETURN: Checksum (u8) - * - * DESCRIPTION: Calculates circular checksum of memory region. - * - ******************************************************************************/ - -u8 acpi_tb_checksum(u8 *buffer, u32 length) -{ - u8 sum = 0; - u8 *end = buffer + length; - - while (buffer < end) { - sum = (u8)(sum + *(buffer++)); - } - - return (sum); -} diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c index 633a823be65f..17ad9c227d42 100644 --- a/drivers/acpi/acpica/tbutils.c +++ b/drivers/acpi/acpica/tbutils.c @@ -299,7 +299,7 @@ acpi_tb_parse_root_table(acpi_physical_address rsdp_address) /* Validate the root table checksum */ - status = acpi_tb_verify_checksum(table, length); + status = acpi_ut_verify_checksum(table, length); if (ACPI_FAILURE(status)) { acpi_os_unmap_memory(table, length); return_ACPI_STATUS(status); diff --git a/drivers/acpi/acpica/tbxfroot.c b/drivers/acpi/acpica/tbxfroot.c index 3d09e3f6bd43..53afd75bbc06 100644 --- a/drivers/acpi/acpica/tbxfroot.c +++ b/drivers/acpi/acpica/tbxfroot.c @@ -74,14 +74,14 @@ acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp) /* Check the standard checksum */ - if (acpi_tb_checksum((u8 *) rsdp, ACPI_RSDP_CHECKSUM_LENGTH) != 0) { + if (acpi_ut_checksum((u8 *)rsdp, ACPI_RSDP_CHECKSUM_LENGTH) != 0) { return (AE_BAD_CHECKSUM); } /* Check extended checksum if table version >= 2 */ if ((rsdp->revision >= 2) && - (acpi_tb_checksum((u8 *) rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0)) { + (acpi_ut_checksum((u8 *)rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0)) { return (AE_BAD_CHECKSUM); } @@ -114,6 +114,7 @@ acpi_find_root_pointer(acpi_physical_address *table_address) u8 *table_ptr; u8 *mem_rover; u32 physical_address; + u32 ebda_window_size; ACPI_FUNCTION_TRACE(acpi_find_root_pointer); @@ -139,26 +140,37 @@ acpi_find_root_pointer(acpi_physical_address *table_address) /* EBDA present? */ - if (physical_address > 0x400) { + /* + * Check that the EBDA pointer from memory is sane and does not point + * above valid low memory + */ + if (physical_address > 0x400 && physical_address < 0xA0000) { + /* + * Calculate the scan window size + * The EBDA is not guaranteed to be larger than a ki_b and in case + * that it is smaller, the scanning function would leave the low + * memory and continue to the VGA range. + */ + ebda_window_size = ACPI_MIN(ACPI_EBDA_WINDOW_SIZE, + 0xA0000 - physical_address); + /* - * 1b) Search EBDA paragraphs (EBDA is required to be a - * minimum of 1K length) + * 1b) Search EBDA paragraphs */ table_ptr = acpi_os_map_memory((acpi_physical_address) physical_address, - ACPI_EBDA_WINDOW_SIZE); + ebda_window_size); if (!table_ptr) { ACPI_ERROR((AE_INFO, "Could not map memory at 0x%8.8X for length %u", - physical_address, ACPI_EBDA_WINDOW_SIZE)); + physical_address, ebda_window_size)); return_ACPI_STATUS(AE_NO_MEMORY); } mem_rover = - acpi_tb_scan_memory_for_rsdp(table_ptr, - ACPI_EBDA_WINDOW_SIZE); - acpi_os_unmap_memory(table_ptr, ACPI_EBDA_WINDOW_SIZE); + acpi_tb_scan_memory_for_rsdp(table_ptr, ebda_window_size); + acpi_os_unmap_memory(table_ptr, ebda_window_size); if (mem_rover) { diff --git a/drivers/acpi/acpica/utcksum.c b/drivers/acpi/acpica/utcksum.c new file mode 100644 index 000000000000..c166e4c05ab6 --- /dev/null +++ b/drivers/acpi/acpica/utcksum.c @@ -0,0 +1,170 @@ +// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 +/****************************************************************************** + * + * Module Name: utcksum - Support generating table checksums + * + * Copyright (C) 2000 - 2022, Intel Corp. + * + *****************************************************************************/ + +#include <acpi/acpi.h> +#include "accommon.h" +#include "acutils.h" + +/* This module used for application-level code only */ + +#define _COMPONENT ACPI_CA_DISASSEMBLER +ACPI_MODULE_NAME("utcksum") + +/******************************************************************************* + * + * FUNCTION: acpi_ut_verify_checksum + * + * PARAMETERS: table - ACPI table to verify + * length - Length of entire table + * + * RETURN: Status + * + * DESCRIPTION: Verifies that the table checksums to zero. Optionally returns + * exception on bad checksum. + * Note: We don't have to check for a CDAT here, since CDAT is + * not in the RSDT/XSDT, and the CDAT table is never installed + * via ACPICA. + * + ******************************************************************************/ +acpi_status acpi_ut_verify_checksum(struct acpi_table_header *table, u32 length) +{ + u8 checksum; + + /* + * FACS/S3PT: + * They are the odd tables, have no standard ACPI header and no checksum + */ + if (ACPI_COMPARE_NAMESEG(table->signature, ACPI_SIG_S3PT) || + ACPI_COMPARE_NAMESEG(table->signature, ACPI_SIG_FACS)) { + return (AE_OK); + } + + /* Compute the checksum on the table */ + + length = table->length; + checksum = + acpi_ut_generate_checksum(ACPI_CAST_PTR(u8, table), length, + table->checksum); + + /* Computed checksum matches table? */ + + if (checksum != table->checksum) { + ACPI_BIOS_WARNING((AE_INFO, + "Incorrect checksum in table [%4.4s] - 0x%2.2X, " + "should be 0x%2.2X", + table->signature, table->checksum, + table->checksum - checksum)); + +#if (ACPI_CHECKSUM_ABORT) + return (AE_BAD_CHECKSUM); +#endif + } + + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_verify_cdat_checksum + * + * PARAMETERS: table - CDAT ACPI table to verify + * length - Length of entire table + * + * RETURN: Status + * + * DESCRIPTION: Verifies that the CDAT table checksums to zero. Optionally + * returns an exception on bad checksum. + * + ******************************************************************************/ + +acpi_status +acpi_ut_verify_cdat_checksum(struct acpi_table_cdat *cdat_table, u32 length) +{ + u8 checksum; + + /* Compute the checksum on the table */ + + checksum = acpi_ut_generate_checksum(ACPI_CAST_PTR(u8, cdat_table), + cdat_table->length, + cdat_table->checksum); + + /* Computed checksum matches table? */ + + if (checksum != cdat_table->checksum) { + ACPI_BIOS_WARNING((AE_INFO, + "Incorrect checksum in table [%4.4s] - 0x%2.2X, " + "should be 0x%2.2X", + acpi_gbl_CDAT, cdat_table->checksum, + checksum)); + +#if (ACPI_CHECKSUM_ABORT) + return (AE_BAD_CHECKSUM); +#endif + } + + cdat_table->checksum = checksum; + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_generate_checksum + * + * PARAMETERS: table - Pointer to table to be checksummed + * length - Length of the table + * original_checksum - Value of the checksum field + * + * RETURN: 8 bit checksum of buffer + * + * DESCRIPTION: Computes an 8 bit checksum of the table. + * + ******************************************************************************/ + +u8 acpi_ut_generate_checksum(void *table, u32 length, u8 original_checksum) +{ + u8 checksum; + + /* Sum the entire table as-is */ + + checksum = acpi_ut_checksum((u8 *)table, length); + + /* Subtract off the existing checksum value in the table */ + + checksum = (u8)(checksum - original_checksum); + + /* Compute and return the final checksum */ + + checksum = (u8)(0 - checksum); + return (checksum); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_checksum + * + * PARAMETERS: buffer - Pointer to memory region to be checked + * length - Length of this memory region + * + * RETURN: Checksum (u8) + * + * DESCRIPTION: Calculates circular checksum of memory region. + * + ******************************************************************************/ + +u8 acpi_ut_checksum(u8 *buffer, u32 length) +{ + u8 sum = 0; + u8 *end = buffer + length; + + while (buffer < end) { + sum = (u8)(sum + *(buffer++)); + } + + return (sum); +} diff --git a/drivers/acpi/acpica/utcopy.c b/drivers/acpi/acpica/utcopy.c index 400b9e15a709..63c17f420fb8 100644 --- a/drivers/acpi/acpica/utcopy.c +++ b/drivers/acpi/acpica/utcopy.c @@ -916,13 +916,6 @@ acpi_ut_copy_ipackage_to_ipackage(union acpi_operand_object *source_obj, status = acpi_ut_walk_package_tree(source_obj, dest_obj, acpi_ut_copy_ielement_to_ielement, walk_state); - if (ACPI_FAILURE(status)) { - - /* On failure, delete the destination package object */ - - acpi_ut_remove_reference(dest_obj); - } - return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/utglobal.c b/drivers/acpi/acpica/utglobal.c index cda6e16dddf7..53afa5edb6ec 100644 --- a/drivers/acpi/acpica/utglobal.c +++ b/drivers/acpi/acpica/utglobal.c @@ -186,6 +186,10 @@ struct acpi_fixed_event_info acpi_gbl_fixed_event_info[ACPI_NUM_FIXED_EVENTS] = ACPI_BITREG_RT_CLOCK_ENABLE, ACPI_BITMASK_RT_CLOCK_STATUS, ACPI_BITMASK_RT_CLOCK_ENABLE}, + /* ACPI_EVENT_PCIE_WAKE */ {ACPI_BITREG_PCIEXP_WAKE_STATUS, + ACPI_BITREG_PCIEXP_WAKE_DISABLE, + ACPI_BITMASK_PCIEXP_WAKE_STATUS, + ACPI_BITMASK_PCIEXP_WAKE_DISABLE}, }; #endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/drivers/acpi/acpica/utstring.c b/drivers/acpi/acpica/utstring.c index c39b5483045d..aae71b8c55d2 100644 --- a/drivers/acpi/acpica/utstring.c +++ b/drivers/acpi/acpica/utstring.c @@ -145,7 +145,7 @@ void acpi_ut_repair_name(char *name) return; } - ACPI_COPY_NAMESEG(&original_name, name); + ACPI_COPY_NAMESEG(&original_name, &name[0]); /* Check each character in the name */ @@ -156,10 +156,10 @@ void acpi_ut_repair_name(char *name) /* * Replace a bad character with something printable, yet technically - * still invalid. This prevents any collisions with existing "good" + * "odd". This prevents any collisions with existing "good" * names in the namespace. */ - name[i] = '*'; + name[i] = '_'; found_bad_char = TRUE; } @@ -169,8 +169,8 @@ void acpi_ut_repair_name(char *name) if (!acpi_gbl_enable_interpreter_slack) { ACPI_WARNING((AE_INFO, - "Invalid character(s) in name (0x%.8X), repaired: [%4.4s]", - original_name, name)); + "Invalid character(s) in name (0x%.8X) %p, repaired: [%4.4s]", + original_name, name, &name[0])); } else { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Invalid character(s) in name (0x%.8X), repaired: [%4.4s]", diff --git a/drivers/acpi/apei/apei-base.c b/drivers/acpi/apei/apei-base.c index 9b52482b4ed5..c7c26872f4ce 100644 --- a/drivers/acpi/apei/apei-base.c +++ b/drivers/acpi/apei/apei-base.c @@ -25,9 +25,9 @@ #include <linux/slab.h> #include <linux/io.h> #include <linux/kref.h> -#include <linux/rculist.h> #include <linux/interrupt.h> #include <linux/debugfs.h> +#include <acpi/apei.h> #include <asm/unaligned.h> #include "apei-internal.h" diff --git a/drivers/acpi/apei/einj.c b/drivers/acpi/apei/einj.c index 6b583373c58a..ab86b2f4e719 100644 --- a/drivers/acpi/apei/einj.c +++ b/drivers/acpi/apei/einj.c @@ -358,6 +358,7 @@ static int __einj_error_trigger(u64 trigger_paddr, u32 type, */ if ((param_extension || acpi5) && (type & MEM_ERROR_MASK) && param2) { struct apei_resources addr_resources; + apei_resources_init(&addr_resources); trigger_param_region = einj_get_trigger_parameter_region( trigger_tab, param1, param2); @@ -432,11 +433,11 @@ static int __einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2, } v5param->flags = vendor_flags; } else if (flags) { - v5param->flags = flags; - v5param->memory_address = param1; - v5param->memory_address_range = param2; - v5param->apicid = param3; - v5param->pcie_sbdf = param4; + v5param->flags = flags; + v5param->memory_address = param1; + v5param->memory_address_range = param2; + v5param->apicid = param3; + v5param->pcie_sbdf = param4; } else { switch (type) { case ACPI_EINJ_PROCESSOR_CORRECTABLE: @@ -466,6 +467,7 @@ static int __einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2, return rc; if (einj_param) { struct einj_parameter *v4param = einj_param; + v4param->param1 = param1; v4param->param2 = param2; } @@ -569,6 +571,20 @@ static u64 error_param2; static u64 error_param3; static u64 error_param4; static struct dentry *einj_debug_dir; +static const char * const einj_error_type_string[] = { + "0x00000001\tProcessor Correctable\n", + "0x00000002\tProcessor Uncorrectable non-fatal\n", + "0x00000004\tProcessor Uncorrectable fatal\n", + "0x00000008\tMemory Correctable\n", + "0x00000010\tMemory Uncorrectable non-fatal\n", + "0x00000020\tMemory Uncorrectable fatal\n", + "0x00000040\tPCI Express Correctable\n", + "0x00000080\tPCI Express Uncorrectable non-fatal\n", + "0x00000100\tPCI Express Uncorrectable fatal\n", + "0x00000200\tPlatform Correctable\n", + "0x00000400\tPlatform Uncorrectable non-fatal\n", + "0x00000800\tPlatform Uncorrectable fatal\n", +}; static int available_error_type_show(struct seq_file *m, void *v) { @@ -578,30 +594,9 @@ static int available_error_type_show(struct seq_file *m, void *v) rc = einj_get_available_error_type(&available_error_type); if (rc) return rc; - if (available_error_type & 0x0001) - seq_printf(m, "0x00000001\tProcessor Correctable\n"); - if (available_error_type & 0x0002) - seq_printf(m, "0x00000002\tProcessor Uncorrectable non-fatal\n"); - if (available_error_type & 0x0004) - seq_printf(m, "0x00000004\tProcessor Uncorrectable fatal\n"); - if (available_error_type & 0x0008) - seq_printf(m, "0x00000008\tMemory Correctable\n"); - if (available_error_type & 0x0010) - seq_printf(m, "0x00000010\tMemory Uncorrectable non-fatal\n"); - if (available_error_type & 0x0020) - seq_printf(m, "0x00000020\tMemory Uncorrectable fatal\n"); - if (available_error_type & 0x0040) - seq_printf(m, "0x00000040\tPCI Express Correctable\n"); - if (available_error_type & 0x0080) - seq_printf(m, "0x00000080\tPCI Express Uncorrectable non-fatal\n"); - if (available_error_type & 0x0100) - seq_printf(m, "0x00000100\tPCI Express Uncorrectable fatal\n"); - if (available_error_type & 0x0200) - seq_printf(m, "0x00000200\tPlatform Correctable\n"); - if (available_error_type & 0x0400) - seq_printf(m, "0x00000400\tPlatform Uncorrectable non-fatal\n"); - if (available_error_type & 0x0800) - seq_printf(m, "0x00000800\tPlatform Uncorrectable fatal\n"); + for (int pos = 0; pos < ARRAY_SIZE(einj_error_type_string); pos++) + if (available_error_type & BIT(pos)) + seq_puts(m, einj_error_type_string[pos]); return 0; } @@ -689,8 +684,7 @@ static int __init einj_init(void) if (status == AE_NOT_FOUND) { pr_warn("EINJ table not found.\n"); return -ENODEV; - } - else if (ACPI_FAILURE(status)) { + } else if (ACPI_FAILURE(status)) { pr_err("Failed to get EINJ table: %s\n", acpi_format_exception(status)); return -EINVAL; diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c index 9952f3a792ba..94c4872ae55f 100644 --- a/drivers/acpi/apei/ghes.c +++ b/drivers/acpi/apei/ghes.c @@ -138,7 +138,7 @@ struct ghes_vendor_record_entry { static struct gen_pool *ghes_estatus_pool; static unsigned long ghes_estatus_pool_size_request; -static struct ghes_estatus_cache *ghes_estatus_caches[GHES_ESTATUS_CACHES_SIZE]; +static struct ghes_estatus_cache __rcu *ghes_estatus_caches[GHES_ESTATUS_CACHES_SIZE]; static atomic_t ghes_estatus_cache_alloced; static int ghes_panic_timeout __read_mostly = 30; @@ -773,48 +773,42 @@ static struct ghes_estatus_cache *ghes_estatus_cache_alloc( return cache; } -static void ghes_estatus_cache_free(struct ghes_estatus_cache *cache) +static void ghes_estatus_cache_rcu_free(struct rcu_head *head) { + struct ghes_estatus_cache *cache; u32 len; + cache = container_of(head, struct ghes_estatus_cache, rcu); len = cper_estatus_len(GHES_ESTATUS_FROM_CACHE(cache)); len = GHES_ESTATUS_CACHE_LEN(len); gen_pool_free(ghes_estatus_pool, (unsigned long)cache, len); atomic_dec(&ghes_estatus_cache_alloced); } -static void ghes_estatus_cache_rcu_free(struct rcu_head *head) -{ - struct ghes_estatus_cache *cache; - - cache = container_of(head, struct ghes_estatus_cache, rcu); - ghes_estatus_cache_free(cache); -} - -static void ghes_estatus_cache_add( - struct acpi_hest_generic *generic, - struct acpi_hest_generic_status *estatus) +static void +ghes_estatus_cache_add(struct acpi_hest_generic *generic, + struct acpi_hest_generic_status *estatus) { - int i, slot = -1, count; unsigned long long now, duration, period, max_period = 0; - struct ghes_estatus_cache *cache, *slot_cache = NULL, *new_cache; + struct ghes_estatus_cache *cache, *new_cache; + struct ghes_estatus_cache __rcu *victim; + int i, slot = -1, count; new_cache = ghes_estatus_cache_alloc(generic, estatus); - if (new_cache == NULL) + if (!new_cache) return; + rcu_read_lock(); now = sched_clock(); for (i = 0; i < GHES_ESTATUS_CACHES_SIZE; i++) { cache = rcu_dereference(ghes_estatus_caches[i]); if (cache == NULL) { slot = i; - slot_cache = NULL; break; } duration = now - cache->time_in; if (duration >= GHES_ESTATUS_IN_CACHE_MAX_NSEC) { slot = i; - slot_cache = cache; break; } count = atomic_read(&cache->count); @@ -823,18 +817,30 @@ static void ghes_estatus_cache_add( if (period > max_period) { max_period = period; slot = i; - slot_cache = cache; } } - /* new_cache must be put into array after its contents are written */ - smp_wmb(); - if (slot != -1 && cmpxchg(ghes_estatus_caches + slot, - slot_cache, new_cache) == slot_cache) { - if (slot_cache) - call_rcu(&slot_cache->rcu, ghes_estatus_cache_rcu_free); - } else - ghes_estatus_cache_free(new_cache); rcu_read_unlock(); + + if (slot != -1) { + /* + * Use release semantics to ensure that ghes_estatus_cached() + * running on another CPU will see the updated cache fields if + * it can see the new value of the pointer. + */ + victim = xchg_release(&ghes_estatus_caches[slot], + RCU_INITIALIZER(new_cache)); + + /* + * At this point, victim may point to a cached item different + * from the one based on which we selected the slot. Instead of + * going to the loop again to pick another slot, let's just + * drop the other item anyway: this may cause a false cache + * miss later on, but that won't cause any problems. + */ + if (victim) + call_rcu(&unrcu_pointer(victim)->rcu, + ghes_estatus_cache_rcu_free); + } } static void __ghes_panic(struct ghes *ghes, @@ -1444,8 +1450,6 @@ static int ghes_remove(struct platform_device *ghes_dev) kfree(ghes); - platform_set_drvdata(ghes_dev, NULL); - return 0; } diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 9482b0b6eadc..f4badcdde76e 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -696,7 +696,8 @@ static void __battery_hook_unregister(struct acpi_battery_hook *hook, int lock) if (lock) mutex_lock(&hook_mutex); list_for_each_entry(battery, &acpi_battery_list, list) { - hook->remove_battery(battery->bat, hook); + if (!hook->remove_battery(battery->bat, hook)) + power_supply_changed(battery->bat); } list_del(&hook->list); if (lock) @@ -735,6 +736,8 @@ void battery_hook_register(struct acpi_battery_hook *hook) __battery_hook_unregister(hook, 0); goto end; } + + power_supply_changed(battery->bat); } pr_info("new extension: %s\n", hook->name); end: @@ -1208,12 +1211,12 @@ fail: return result; } -static int acpi_battery_remove(struct acpi_device *device) +static void acpi_battery_remove(struct acpi_device *device) { struct acpi_battery *battery = NULL; if (!device || !acpi_driver_data(device)) - return -EINVAL; + return; device_init_wakeup(&device->dev, 0); battery = acpi_driver_data(device); unregister_pm_notifier(&battery->pm_nb); @@ -1221,7 +1224,6 @@ static int acpi_battery_remove(struct acpi_device *device) mutex_destroy(&battery->lock); mutex_destroy(&battery->sysfs_lock); kfree(battery); - return 0; } #ifdef CONFIG_PM_SLEEP diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 351208eda9be..0c05ccde1f7a 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -324,6 +324,8 @@ static void acpi_bus_osc_negotiate_platform_control(void) capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PCLPI_SUPPORT; if (IS_ENABLED(CONFIG_ACPI_PRMT)) capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PRM_SUPPORT; + if (IS_ENABLED(CONFIG_ACPI_FFH)) + capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_FFH_OPR_SUPPORT; #ifdef CONFIG_ARM64 capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_GENERIC_INITIATOR_SUPPORT; @@ -1409,6 +1411,7 @@ static int __init acpi_init(void) disable_acpi(); return result; } + acpi_init_ffh(); pci_mmcfg_late_init(); acpi_iort_init(); diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index 1f9b9a4c38c7..475e1eddfa3b 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c @@ -125,7 +125,7 @@ static const struct dmi_system_id dmi_lid_quirks[] = { }; static int acpi_button_add(struct acpi_device *device); -static int acpi_button_remove(struct acpi_device *device); +static void acpi_button_remove(struct acpi_device *device); static void acpi_button_notify(struct acpi_device *device, u32 event); #ifdef CONFIG_PM_SLEEP @@ -580,14 +580,13 @@ static int acpi_button_add(struct acpi_device *device) return error; } -static int acpi_button_remove(struct acpi_device *device) +static void acpi_button_remove(struct acpi_device *device) { struct acpi_button *button = acpi_driver_data(device); acpi_button_remove_fs(device); input_unregister_device(button->input); kfree(button); - return 0; } static int param_set_lid_init_state(const char *val, diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c index 093675b1a1ff..0f17b1c32718 100644 --- a/drivers/acpi/cppc_acpi.c +++ b/drivers/acpi/cppc_acpi.c @@ -148,7 +148,7 @@ __ATTR(_name, 0444, show_##_name, NULL) if (ret) \ return ret; \ \ - return scnprintf(buf, PAGE_SIZE, "%llu\n", \ + return sysfs_emit(buf, "%llu\n", \ (u64)st_name.member_name); \ } \ define_one_cppc_ro(member_name) @@ -174,7 +174,7 @@ static ssize_t show_feedback_ctrs(struct kobject *kobj, if (ret) return ret; - return scnprintf(buf, PAGE_SIZE, "ref:%llu del:%llu\n", + return sysfs_emit(buf, "ref:%llu del:%llu\n", fb_ctrs.reference, fb_ctrs.delivered); } define_one_cppc_ro(feedback_ctrs); diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 9b42628cf21b..2520fb998ce6 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -1663,12 +1663,12 @@ err: return ret; } -static int acpi_ec_remove(struct acpi_device *device) +static void acpi_ec_remove(struct acpi_device *device) { struct acpi_ec *ec; if (!device) - return -EINVAL; + return; ec = acpi_driver_data(device); release_region(ec->data_addr, 1); @@ -1678,7 +1678,6 @@ static int acpi_ec_remove(struct acpi_device *device) ec_remove_handlers(ec); acpi_ec_free(ec); } - return 0; } static acpi_status @@ -1877,6 +1876,16 @@ static const struct dmi_system_id ec_dmi_table[] __initconst = { }, { /* + * HP Pavilion Gaming Laptop 15-cx0041ur + */ + .callback = ec_honor_dsdt_gpe, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "HP"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP 15-cx0041ur"), + }, + }, + { + /* * Samsung hardware * https://bugzilla.kernel.org/show_bug.cgi?id=44161 */ diff --git a/drivers/acpi/fan_attr.c b/drivers/acpi/fan_attr.c index f15157d40713..f4f6e2381f1d 100644 --- a/drivers/acpi/fan_attr.c +++ b/drivers/acpi/fan_attr.c @@ -27,24 +27,24 @@ static ssize_t show_state(struct device *dev, struct device_attribute *attr, cha count = scnprintf(buf, PAGE_SIZE, "%lld:", fps->control); if (fps->trip_point == 0xFFFFFFFF || fps->trip_point > 9) - count += scnprintf(&buf[count], PAGE_SIZE - count, "not-defined:"); + count += sysfs_emit_at(buf, count, "not-defined:"); else - count += scnprintf(&buf[count], PAGE_SIZE - count, "%lld:", fps->trip_point); + count += sysfs_emit_at(buf, count, "%lld:", fps->trip_point); if (fps->speed == 0xFFFFFFFF) - count += scnprintf(&buf[count], PAGE_SIZE - count, "not-defined:"); + count += sysfs_emit_at(buf, count, "not-defined:"); else - count += scnprintf(&buf[count], PAGE_SIZE - count, "%lld:", fps->speed); + count += sysfs_emit_at(buf, count, "%lld:", fps->speed); if (fps->noise_level == 0xFFFFFFFF) - count += scnprintf(&buf[count], PAGE_SIZE - count, "not-defined:"); + count += sysfs_emit_at(buf, count, "not-defined:"); else - count += scnprintf(&buf[count], PAGE_SIZE - count, "%lld:", fps->noise_level * 100); + count += sysfs_emit_at(buf, count, "%lld:", fps->noise_level * 100); if (fps->power == 0xFFFFFFFF) - count += scnprintf(&buf[count], PAGE_SIZE - count, "not-defined\n"); + count += sysfs_emit_at(buf, count, "not-defined\n"); else - count += scnprintf(&buf[count], PAGE_SIZE - count, "%lld\n", fps->power); + count += sysfs_emit_at(buf, count, "%lld\n", fps->power); return count; } diff --git a/drivers/acpi/fan_core.c b/drivers/acpi/fan_core.c index 52a0b303b70a..9dccbae9e8ea 100644 --- a/drivers/acpi/fan_core.c +++ b/drivers/acpi/fan_core.c @@ -236,6 +236,7 @@ static int acpi_fan_get_fif(struct acpi_device *device) if (ACPI_FAILURE(status)) { dev_err(&device->dev, "Invalid _FIF element\n"); status = -EINVAL; + goto err; } fan->fif.revision = fields[0]; diff --git a/drivers/acpi/hed.c b/drivers/acpi/hed.c index 60a2939cde6c..78d44e3fe129 100644 --- a/drivers/acpi/hed.c +++ b/drivers/acpi/hed.c @@ -56,10 +56,9 @@ static int acpi_hed_add(struct acpi_device *device) return 0; } -static int acpi_hed_remove(struct acpi_device *device) +static void acpi_hed_remove(struct acpi_device *device) { hed_handle = NULL; - return 0; } static struct acpi_driver acpi_hed_driver = { diff --git a/drivers/acpi/irq.c b/drivers/acpi/irq.c index 1cc4647f78b8..c2c786eb95ab 100644 --- a/drivers/acpi/irq.c +++ b/drivers/acpi/irq.c @@ -94,6 +94,7 @@ EXPORT_SYMBOL_GPL(acpi_unregister_gsi); /** * acpi_get_irq_source_fwhandle() - Retrieve fwhandle from IRQ resource source. * @source: acpi_resource_source to use for the lookup. + * @gsi: GSI IRQ number * * Description: * Retrieve the fwhandle of the device referenced by the given IRQ resource @@ -297,8 +298,8 @@ EXPORT_SYMBOL_GPL(acpi_irq_get); /** * acpi_set_irq_model - Setup the GSI irqdomain information * @model: the value assigned to acpi_irq_model - * @fwnode: the irq_domain identifier for mapping and looking up - * GSI interrupts + * @fn: a dispatcher function that will return the domain fwnode + * for a given GSI */ void __init acpi_set_irq_model(enum acpi_irq_model_id model, struct fwnode_handle *(*fn)(u32)) diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c index ae5f4acf2675..f1cc5ec6a3b6 100644 --- a/drivers/acpi/nfit/core.c +++ b/drivers/acpi/nfit/core.c @@ -3371,10 +3371,9 @@ static int acpi_nfit_add(struct acpi_device *adev) return devm_add_action_or_reset(dev, acpi_nfit_shutdown, acpi_desc); } -static int acpi_nfit_remove(struct acpi_device *adev) +static void acpi_nfit_remove(struct acpi_device *adev) { /* see acpi_nfit_unregister */ - return 0; } static void acpi_nfit_update_notify(struct device *dev, acpi_handle handle) diff --git a/drivers/acpi/pfr_telemetry.c b/drivers/acpi/pfr_telemetry.c index 9abf350bd7a5..27fb6cdad75f 100644 --- a/drivers/acpi/pfr_telemetry.c +++ b/drivers/acpi/pfr_telemetry.c @@ -144,7 +144,7 @@ static int get_pfrt_log_data_info(struct pfrt_log_data_info *data_info, ret = 0; free_acpi_buffer: - kfree(out_obj); + ACPI_FREE(out_obj); return ret; } @@ -180,7 +180,7 @@ static int set_pfrt_log_level(int level, struct pfrt_log_device *pfrt_log_dev) ret = -EBUSY; } - kfree(out_obj); + ACPI_FREE(out_obj); return ret; } @@ -218,7 +218,7 @@ static int get_pfrt_log_level(struct pfrt_log_device *pfrt_log_dev) ret = obj->integer.value; free_acpi_buffer: - kfree(out_obj); + ACPI_FREE(out_obj); return ret; } diff --git a/drivers/acpi/pfr_update.c b/drivers/acpi/pfr_update.c index 6bb0b778b5da..9d2bdc13253a 100644 --- a/drivers/acpi/pfr_update.c +++ b/drivers/acpi/pfr_update.c @@ -178,7 +178,7 @@ static int query_capability(struct pfru_update_cap_info *cap_hdr, ret = 0; free_acpi_buffer: - kfree(out_obj); + ACPI_FREE(out_obj); return ret; } @@ -224,7 +224,7 @@ static int query_buffer(struct pfru_com_buf_info *info, ret = 0; free_acpi_buffer: - kfree(out_obj); + ACPI_FREE(out_obj); return ret; } @@ -385,7 +385,7 @@ static int start_update(int action, struct pfru_device *pfru_dev) ret = 0; free_acpi_buffer: - kfree(out_obj); + ACPI_FREE(out_obj); return ret; } diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index f2588aba8421..23507d29f000 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -967,7 +967,7 @@ struct acpi_device *acpi_add_power_resource(acpi_handle handle) if (acpi_power_get_state(resource, &state_dummy)) __acpi_power_on(resource); - pr_info("%s [%s]\n", acpi_device_name(device), acpi_device_bid(device)); + acpi_handle_info(handle, "New power resource\n"); result = acpi_tie_acpi_dev(device); if (result) diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index acfabfe07c4f..7bf882fcd64b 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -324,7 +324,7 @@ static void acpi_processor_power_verify_c3(struct acpi_processor *pr, * the erratum), but this is known to disrupt certain ISA * devices thus we take the conservative approach. */ - else if (errata.piix4.fdma) { + if (errata.piix4.fdma) { acpi_handle_debug(pr->handle, "C3 not supported on PIIX4 with Type-F DMA\n"); return; @@ -384,8 +384,6 @@ static void acpi_processor_power_verify_c3(struct acpi_processor *pr, * handle BM_RLD is to set it and leave it set. */ acpi_write_bit_register(ACPI_BITREG_BUS_MASTER_RLD, 1); - - return; } static int acpi_cst_latency_cmp(const void *a, const void *b) @@ -459,7 +457,7 @@ static int acpi_processor_power_verify(struct acpi_processor *pr) lapic_timer_propagate_broadcast(pr); - return (working); + return working; } static int acpi_processor_get_cstate_info(struct acpi_processor *pr) @@ -1134,6 +1132,9 @@ static int acpi_processor_get_lpi_info(struct acpi_processor *pr) status = acpi_get_parent(handle, &pr_ahandle); while (ACPI_SUCCESS(status)) { d = acpi_fetch_acpi_dev(pr_ahandle); + if (!d) + break; + handle = pr_ahandle; if (strcmp(acpi_device_hid(d), ACPI_PROCESSOR_CONTAINER_HID)) diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index 757a98f6d7a2..970f04a958cd 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c @@ -142,6 +142,7 @@ int acpi_processor_get_bios_limit(int cpu, unsigned int *limit) pr = per_cpu(processors, cpu); if (!pr || !pr->performance || !pr->performance->state_count) return -ENODEV; + *limit = pr->performance->states[pr->performance_platform_limit]. core_frequency * 1000; return 0; @@ -201,8 +202,7 @@ static int acpi_processor_get_performance_control(struct acpi_processor *pr) } pct = (union acpi_object *)buffer.pointer; - if (!pct || (pct->type != ACPI_TYPE_PACKAGE) - || (pct->package.count != 2)) { + if (!pct || pct->type != ACPI_TYPE_PACKAGE || pct->package.count != 2) { pr_err("Invalid _PCT data\n"); result = -EFAULT; goto end; @@ -214,9 +214,8 @@ static int acpi_processor_get_performance_control(struct acpi_processor *pr) obj = pct->package.elements[0]; - if ((obj.type != ACPI_TYPE_BUFFER) - || (obj.buffer.length < sizeof(struct acpi_pct_register)) - || (obj.buffer.pointer == NULL)) { + if (!obj.buffer.pointer || obj.type != ACPI_TYPE_BUFFER || + obj.buffer.length < sizeof(struct acpi_pct_register)) { pr_err("Invalid _PCT data (control_register)\n"); result = -EFAULT; goto end; @@ -230,9 +229,8 @@ static int acpi_processor_get_performance_control(struct acpi_processor *pr) obj = pct->package.elements[1]; - if ((obj.type != ACPI_TYPE_BUFFER) - || (obj.buffer.length < sizeof(struct acpi_pct_register)) - || (obj.buffer.pointer == NULL)) { + if (!obj.buffer.pointer || obj.type != ACPI_TYPE_BUFFER || + obj.buffer.length < sizeof(struct acpi_pct_register)) { pr_err("Invalid _PCT data (status_register)\n"); result = -EFAULT; goto end; @@ -260,8 +258,8 @@ static void amd_fixup_frequency(struct acpi_processor_px *px, int i) if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD) return; - if ((boot_cpu_data.x86 == 0x10 && boot_cpu_data.x86_model < 10) - || boot_cpu_data.x86 == 0x11) { + if ((boot_cpu_data.x86 == 0x10 && boot_cpu_data.x86_model < 10) || + boot_cpu_data.x86 == 0x11) { rdmsr(MSR_AMD_PSTATE_DEF_BASE + index, lo, hi); /* * MSR C001_0064+: @@ -300,7 +298,7 @@ static int acpi_processor_get_performance_states(struct acpi_processor *pr) } pss = buffer.pointer; - if (!pss || (pss->type != ACPI_TYPE_PACKAGE)) { + if (!pss || pss->type != ACPI_TYPE_PACKAGE) { pr_err("Invalid _PSS data\n"); result = -EFAULT; goto end; @@ -353,8 +351,7 @@ static int acpi_processor_get_performance_states(struct acpi_processor *pr) * Check that ACPI's u64 MHz will be valid as u32 KHz in cpufreq */ if (!px->core_frequency || - ((u32)(px->core_frequency * 1000) != - (px->core_frequency * 1000))) { + (u32)(px->core_frequency * 1000) != px->core_frequency * 1000) { pr_err(FW_BUG "Invalid BIOS _PSS frequency found for processor %d: 0x%llx MHz\n", pr->id, px->core_frequency); @@ -456,7 +453,7 @@ int acpi_processor_pstate_control(void) int acpi_processor_notify_smm(struct module *calling_module) { static int is_done; - int result; + int result = 0; if (!acpi_processor_cpufreq_init) return -EBUSY; @@ -464,42 +461,41 @@ int acpi_processor_notify_smm(struct module *calling_module) if (!try_module_get(calling_module)) return -EINVAL; - /* is_done is set to negative if an error occurred, - * and to postitive if _no_ error occurred, but SMM - * was already notified. This avoids double notification - * which might lead to unexpected results... + /* + * is_done is set to negative if an error occurs and to 1 if no error + * occurrs, but SMM has been notified already. This avoids repeated + * notification which might lead to unexpected results. */ - if (is_done > 0) { - module_put(calling_module); - return 0; - } else if (is_done < 0) { - module_put(calling_module); - return is_done; - } + if (is_done != 0) { + if (is_done < 0) + result = is_done; - is_done = -EIO; + goto out_put; + } result = acpi_processor_pstate_control(); - if (!result) { - pr_debug("No SMI port or pstate_control\n"); - module_put(calling_module); - return 0; - } - if (result < 0) { - module_put(calling_module); - return result; + if (result <= 0) { + if (result) { + is_done = result; + } else { + pr_debug("No SMI port or pstate_control\n"); + is_done = 1; + } + goto out_put; } - /* Success. If there's no _PPC, we need to fear nothing, so - * we can allow the cpufreq driver to be rmmod'ed. */ is_done = 1; + /* + * Success. If there _PPC, unloading the cpufreq driver would be risky, + * so disallow it in that case. + */ + if (acpi_processor_ppc_in_use) + return 0; - if (!acpi_processor_ppc_in_use) - module_put(calling_module); - - return 0; +out_put: + module_put(calling_module); + return result; } - EXPORT_SYMBOL(acpi_processor_notify_smm); int acpi_processor_get_psd(acpi_handle handle, struct acpi_psd_package *pdomain) @@ -517,7 +513,7 @@ int acpi_processor_get_psd(acpi_handle handle, struct acpi_psd_package *pdomain) } psd = buffer.pointer; - if (!psd || (psd->type != ACPI_TYPE_PACKAGE)) { + if (!psd || psd->type != ACPI_TYPE_PACKAGE) { pr_err("Invalid _PSD data\n"); result = -EFAULT; goto end; @@ -532,8 +528,7 @@ int acpi_processor_get_psd(acpi_handle handle, struct acpi_psd_package *pdomain) state.length = sizeof(struct acpi_psd_package); state.pointer = pdomain; - status = acpi_extract_package(&(psd->package.elements[0]), - &format, &state); + status = acpi_extract_package(&(psd->package.elements[0]), &format, &state); if (ACPI_FAILURE(status)) { pr_err("Invalid _PSD data\n"); result = -EFAULT; @@ -716,9 +711,8 @@ err_out: } EXPORT_SYMBOL(acpi_processor_preregister_performance); -int -acpi_processor_register_performance(struct acpi_processor_performance - *performance, unsigned int cpu) +int acpi_processor_register_performance(struct acpi_processor_performance + *performance, unsigned int cpu) { struct acpi_processor *pr; @@ -751,7 +745,6 @@ acpi_processor_register_performance(struct acpi_processor_performance mutex_unlock(&performance_mutex); return 0; } - EXPORT_SYMBOL(acpi_processor_register_performance); void acpi_processor_unregister_performance(unsigned int cpu) @@ -761,18 +754,15 @@ void acpi_processor_unregister_performance(unsigned int cpu) mutex_lock(&performance_mutex); pr = per_cpu(processors, cpu); - if (!pr) { - mutex_unlock(&performance_mutex); - return; - } + if (!pr) + goto unlock; if (pr->performance) kfree(pr->performance->states); + pr->performance = NULL; +unlock: mutex_unlock(&performance_mutex); - - return; } - EXPORT_SYMBOL(acpi_processor_unregister_performance); diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c index a822fe410dda..00d045e5f524 100644 --- a/drivers/acpi/processor_throttling.c +++ b/drivers/acpi/processor_throttling.c @@ -50,7 +50,7 @@ static int __acpi_processor_set_throttling(struct acpi_processor *pr, static int acpi_processor_update_tsd_coord(void) { - int count, count_target; + int count_target; int retval = 0; unsigned int i, j; cpumask_var_t covered_cpus; @@ -107,7 +107,6 @@ static int acpi_processor_update_tsd_coord(void) /* Validate the Domain info */ count_target = pdomain->num_processors; - count = 1; for_each_possible_cpu(j) { if (i == j) @@ -140,7 +139,6 @@ static int acpi_processor_update_tsd_coord(void) cpumask_set_cpu(j, covered_cpus); cpumask_set_cpu(j, pthrottling->shared_cpu_map); - count++; } for_each_possible_cpu(j) { if (i == j) diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index e6a01a8df1b8..e90752d4f488 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c @@ -96,7 +96,7 @@ struct acpi_sbs { #define to_acpi_sbs(x) power_supply_get_drvdata(x) -static int acpi_sbs_remove(struct acpi_device *device); +static void acpi_sbs_remove(struct acpi_device *device); static int acpi_battery_get_state(struct acpi_battery *battery); static inline int battery_scale(int log) @@ -664,16 +664,16 @@ end: return result; } -static int acpi_sbs_remove(struct acpi_device *device) +static void acpi_sbs_remove(struct acpi_device *device) { struct acpi_sbs *sbs; int id; if (!device) - return -EINVAL; + return; sbs = acpi_driver_data(device); if (!sbs) - return -EINVAL; + return; mutex_lock(&sbs->lock); acpi_smbus_unregister_callback(sbs->hc); for (id = 0; id < MAX_SBS_BAT; ++id) @@ -682,7 +682,6 @@ static int acpi_sbs_remove(struct acpi_device *device) mutex_unlock(&sbs->lock); mutex_destroy(&sbs->lock); kfree(sbs); - return 0; } #ifdef CONFIG_PM_SLEEP diff --git a/drivers/acpi/sbshc.c b/drivers/acpi/sbshc.c index 340e0b61587e..16f2daaa2c45 100644 --- a/drivers/acpi/sbshc.c +++ b/drivers/acpi/sbshc.c @@ -30,7 +30,7 @@ struct acpi_smb_hc { }; static int acpi_smbus_hc_add(struct acpi_device *device); -static int acpi_smbus_hc_remove(struct acpi_device *device); +static void acpi_smbus_hc_remove(struct acpi_device *device); static const struct acpi_device_id sbs_device_ids[] = { {"ACPI0001", 0}, @@ -280,19 +280,18 @@ static int acpi_smbus_hc_add(struct acpi_device *device) extern void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit); -static int acpi_smbus_hc_remove(struct acpi_device *device) +static void acpi_smbus_hc_remove(struct acpi_device *device) { struct acpi_smb_hc *hc; if (!device) - return -EINVAL; + return; hc = acpi_driver_data(device); acpi_ec_remove_query_handler(hc->ec, hc->query_bit); acpi_os_wait_events_complete(); kfree(hc); device->driver_data = NULL; - return 0; } module_acpi_driver(acpi_smb_hc_driver); diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index b47e93a24a9a..274344434282 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -30,7 +30,7 @@ extern struct acpi_device *acpi_root; #define ACPI_BUS_HID "LNXSYBUS" #define ACPI_BUS_DEVICE_NAME "System Bus" -#define INVALID_ACPI_HANDLE ((acpi_handle)empty_zero_page) +#define INVALID_ACPI_HANDLE ((acpi_handle)ZERO_PAGE(0)) static const char *dummy_hid = "device"; diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c index cc2fe0618178..7db3b530279b 100644 --- a/drivers/acpi/sysfs.c +++ b/drivers/acpi/sysfs.c @@ -9,6 +9,7 @@ #include <linux/bitmap.h> #include <linux/init.h> #include <linux/kernel.h> +#include <linux/kstrtox.h> #include <linux/moduleparam.h> #include "internal.h" @@ -197,7 +198,7 @@ static int param_set_trace_method_name(const char *val, static int param_get_trace_method_name(char *buffer, const struct kernel_param *kp) { - return scnprintf(buffer, PAGE_SIZE, "%s\n", acpi_gbl_trace_method_name); + return sysfs_emit(buffer, "%s\n", acpi_gbl_trace_method_name); } static const struct kernel_param_ops param_ops_trace_method = { @@ -992,7 +993,7 @@ static ssize_t force_remove_store(struct kobject *kobj, bool val; int ret; - ret = strtobool(buf, &val); + ret = kstrtobool(buf, &val); if (ret < 0) return ret; diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index 47ec11d4c68e..5fbc32b802d0 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c @@ -210,6 +210,16 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header *header) } break; + case ACPI_MADT_TYPE_CORE_PIC: + { + struct acpi_madt_core_pic *p = (struct acpi_madt_core_pic *)header; + + pr_debug("CORE PIC (processor_id[0x%02x] core_id[0x%02x] %s)\n", + p->processor_id, p->core_id, + (p->flags & ACPI_MADT_ENABLED) ? "enabled" : "disabled"); + } + break; + default: pr_warn("Found unsupported MADT entry (type = 0x%x)\n", header->type); @@ -838,12 +848,11 @@ acpi_status acpi_os_table_override(struct acpi_table_header *existing_table, /* * acpi_locate_initial_tables() * - * find RSDP, find and checksum SDT/XSDT. - * checksum all tables, print SDT/XSDT + * Get the RSDP, then find and checksum all the ACPI tables. * - * result: sdt_entry[] is initialized + * result: initial_tables[] is initialized, and points to + * a list of ACPI tables. */ - int __init acpi_locate_initial_tables(void) { acpi_status status; diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 40b07057983e..0b4b844f9d4c 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -74,7 +74,7 @@ MODULE_PARM_DESC(psv, "Disable or override all passive trip points."); static struct workqueue_struct *acpi_thermal_pm_queue; static int acpi_thermal_add(struct acpi_device *device); -static int acpi_thermal_remove(struct acpi_device *device); +static void acpi_thermal_remove(struct acpi_device *device); static void acpi_thermal_notify(struct acpi_device *device, u32 event); static const struct acpi_device_id thermal_device_ids[] = { @@ -291,7 +291,7 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) "Found critical threshold [%lu]\n", tz->trips.critical.temperature); } - if (tz->trips.critical.flags.valid == 1) { + if (tz->trips.critical.flags.valid) { if (crt == -1) { tz->trips.critical.flags.valid = 0; } else if (crt > 0) { @@ -1059,19 +1059,18 @@ end: return result; } -static int acpi_thermal_remove(struct acpi_device *device) +static void acpi_thermal_remove(struct acpi_device *device) { struct acpi_thermal *tz; if (!device || !acpi_driver_data(device)) - return -EINVAL; + return; flush_workqueue(acpi_thermal_pm_queue); tz = acpi_driver_data(device); acpi_thermal_unregister_thermal_zone(tz); kfree(tz); - return 0; } #ifdef CONFIG_PM_SLEEP diff --git a/drivers/acpi/tiny-power-button.c b/drivers/acpi/tiny-power-button.c index a19f0e4e69f7..598f548b21f3 100644 --- a/drivers/acpi/tiny-power-button.c +++ b/drivers/acpi/tiny-power-button.c @@ -19,11 +19,15 @@ static const struct acpi_device_id tiny_power_button_device_ids[] = { }; MODULE_DEVICE_TABLE(acpi, tiny_power_button_device_ids); -static int acpi_noop_add_remove(struct acpi_device *device) +static int acpi_noop_add(struct acpi_device *device) { return 0; } +static void acpi_noop_remove(struct acpi_device *device) +{ +} + static void acpi_tiny_power_button_notify(struct acpi_device *device, u32 event) { kill_cad_pid(power_signal, 1); @@ -34,8 +38,8 @@ static struct acpi_driver acpi_tiny_power_button_driver = { .class = "tiny-power-button", .ids = tiny_power_button_device_ids, .ops = { - .add = acpi_noop_add_remove, - .remove = acpi_noop_add_remove, + .add = acpi_noop_add, + .remove = acpi_noop_remove, .notify = acpi_tiny_power_button_notify, }, }; diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index b2a616287638..a934bbc9dd37 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c @@ -132,6 +132,10 @@ static int video_detect_force_none(const struct dmi_system_id *d) } static const struct dmi_system_id video_detect_dmi_table[] = { + /* + * Models which should use the vendor backlight interface, + * because of broken ACPI video backlight control. + */ { /* https://bugzilla.redhat.com/show_bug.cgi?id=1128309 */ .callback = video_detect_force_vendor, @@ -166,6 +170,7 @@ static const struct dmi_system_id video_detect_dmi_table[] = { }, }, { + /* https://bugs.launchpad.net/bugs/1000146 */ .callback = video_detect_force_vendor, /* Asus X101CH */ .matches = { @@ -190,6 +195,7 @@ static const struct dmi_system_id video_detect_dmi_table[] = { }, }, { + /* https://bugs.launchpad.net/bugs/1000146 */ .callback = video_detect_force_vendor, /* Asus 1015CX */ .matches = { @@ -199,14 +205,6 @@ static const struct dmi_system_id video_detect_dmi_table[] = { }, { .callback = video_detect_force_vendor, - /* GIGABYTE GB-BXBT-2807 */ - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"), - DMI_MATCH(DMI_PRODUCT_NAME, "GB-BXBT-2807"), - }, - }, - { - .callback = video_detect_force_vendor, /* Samsung N150/N210/N220 */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), @@ -234,18 +232,23 @@ static const struct dmi_system_id video_detect_dmi_table[] = { }, { .callback = video_detect_force_vendor, - /* Sony VPCEH3U1E */ + /* Xiaomi Mi Pad 2 */ .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), - DMI_MATCH(DMI_PRODUCT_NAME, "VPCEH3U1E"), + DMI_MATCH(DMI_SYS_VENDOR, "Xiaomi Inc"), + DMI_MATCH(DMI_PRODUCT_NAME, "Mipad2"), }, }, + + /* + * Models which should use the vendor backlight interface, + * because of broken native backlight control. + */ { .callback = video_detect_force_vendor, - /* Xiaomi Mi Pad 2 */ + /* Sony Vaio PCG-FRV35 */ .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Xiaomi Inc"), - DMI_MATCH(DMI_PRODUCT_NAME, "Mipad2"), + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "PCG-FRV35"), }, }, @@ -400,8 +403,8 @@ static const struct dmi_system_id video_detect_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "530U4E/540U4E"), }, }, - /* https://bugs.launchpad.net/bugs/1894667 */ { + /* https://bugs.launchpad.net/bugs/1894667 */ .callback = video_detect_force_video, /* HP 635 Notebook */ .matches = { @@ -609,6 +612,23 @@ static const struct dmi_system_id video_detect_dmi_table[] = { DMI_MATCH(DMI_BOARD_NAME, "N250P"), }, }, + { + /* https://bugzilla.kernel.org/show_bug.cgi?id=202401 */ + .callback = video_detect_force_native, + /* Sony Vaio VPCEH3U1E */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "VPCEH3U1E"), + }, + }, + { + .callback = video_detect_force_native, + /* Sony Vaio VPCY11S1E */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "VPCY11S1E"), + }, + }, /* * These Toshibas have a broken acpi-video interface for brightness @@ -673,6 +693,14 @@ static const struct dmi_system_id video_detect_dmi_table[] = { }, { .callback = video_detect_force_none, + /* GIGABYTE GB-BXBT-2807 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"), + DMI_MATCH(DMI_PRODUCT_NAME, "GB-BXBT-2807"), + }, + }, + { + .callback = video_detect_force_none, /* MSI MS-7721 */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "MSI"), @@ -688,6 +716,16 @@ static bool google_cros_ec_present(void) } /* + * Windows 8 and newer no longer use the ACPI video interface, so it often + * does not work. So on win8+ systems prefer native brightness control. + * Chromebooks should always prefer native backlight control. + */ +static bool prefer_native_over_acpi_video(void) +{ + return acpi_osi_is_win8() || google_cros_ec_present(); +} + +/* * Determine which type of backlight interface to use on this system, * First check cmdline, then dmi quirks, then do autodetect. */ @@ -732,28 +770,16 @@ static enum acpi_backlight_type __acpi_video_get_backlight_type(bool native) if (apple_gmux_present()) return acpi_backlight_apple_gmux; - /* Chromebooks should always prefer native backlight control. */ - if (google_cros_ec_present() && native_available) - return acpi_backlight_native; + /* Use ACPI video if available, except when native should be preferred. */ + if ((video_caps & ACPI_VIDEO_BACKLIGHT) && + !(native_available && prefer_native_over_acpi_video())) + return acpi_backlight_video; - /* On systems with ACPI video use either native or ACPI video. */ - if (video_caps & ACPI_VIDEO_BACKLIGHT) { - /* - * Windows 8 and newer no longer use the ACPI video interface, - * so it often does not work. If the ACPI tables are written - * for win8 and native brightness ctl is available, use that. - * - * The native check deliberately is inside the if acpi-video - * block on older devices without acpi-video support native - * is usually not the best choice. - */ - if (acpi_osi_is_win8() && native_available) - return acpi_backlight_native; - else - return acpi_backlight_video; - } + /* Use native if available */ + if (native_available) + return acpi_backlight_native; - /* No ACPI video (old hw), use vendor specific fw methods. */ + /* No ACPI video/native (old hw), use vendor specific fw methods. */ return acpi_backlight_vendor; } @@ -765,18 +791,6 @@ EXPORT_SYMBOL(acpi_video_get_backlight_type); bool acpi_video_backlight_use_native(void) { - /* - * Call __acpi_video_get_backlight_type() to let it know that - * a native backlight is available. - */ - __acpi_video_get_backlight_type(true); - - /* - * For now just always return true. There is a whole bunch of laptop - * models where (video_caps & ACPI_VIDEO_BACKLIGHT) is false causing - * __acpi_video_get_backlight_type() to return vendor, while these - * models only have a native backlight control. - */ - return true; + return __acpi_video_get_backlight_type(true) == acpi_backlight_native; } EXPORT_SYMBOL(acpi_video_backlight_use_native); diff --git a/drivers/acpi/x86/utils.c b/drivers/acpi/x86/utils.c index d7d3f1669d4c..4e816bb402f6 100644 --- a/drivers/acpi/x86/utils.c +++ b/drivers/acpi/x86/utils.c @@ -308,7 +308,7 @@ static const struct dmi_system_id acpi_quirk_skip_dmi_ids[] = { ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY), }, { - /* Lenovo Yoga Tablet 1050F/L */ + /* Lenovo Yoga Tablet 2 1050F/L */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Intel Corp."), DMI_MATCH(DMI_PRODUCT_NAME, "VALLEYVIEW C0 PLATFORM"), @@ -320,6 +320,27 @@ static const struct dmi_system_id acpi_quirk_skip_dmi_ids[] = { ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY), }, { + /* Lenovo Yoga Tab 3 Pro X90F */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "CHERRYVIEW D1 PLATFORM"), + DMI_MATCH(DMI_PRODUCT_VERSION, "Blade3-10A-001"), + }, + .driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS | + ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY), + }, + { + /* Medion Lifetab S10346 */ + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), + DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"), + /* Way too generic, also match on BIOS data */ + DMI_MATCH(DMI_BIOS_DATE, "10/22/2015"), + }, + .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"), @@ -348,6 +369,7 @@ static const struct acpi_device_id i2c_acpi_known_good_ids[] = { { "10EC5640", 0 }, /* RealTek ALC5640 audio codec */ { "INT33F4", 0 }, /* X-Powers AXP288 PMIC */ { "INT33FD", 0 }, /* Intel Crystal Cove PMIC */ + { "INT34D3", 0 }, /* Intel Whiskey Cove PMIC */ { "NPCE69A", 0 }, /* Asus Transformer keyboard dock */ {} }; |