From 6fd13452c1a2e6dfe5b9a4c84c1144383cc55472 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 10 Nov 2021 13:16:40 +0200 Subject: ACPI: processor: Replace kernel.h with the necessary inclusions When kernel.h is used in the headers it adds a lot into dependency hell, especially when there are circular dependencies are involved. Replace kernel.h inclusion with the list of what is really being used. Signed-off-by: Andy Shevchenko Signed-off-by: Rafael J. Wysocki --- include/acpi/acpi_numa.h | 1 - include/acpi/processor.h | 7 ++++++- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'include/acpi') diff --git a/include/acpi/acpi_numa.h b/include/acpi/acpi_numa.h index 68e4d80c1b32..b5f594754a9e 100644 --- a/include/acpi/acpi_numa.h +++ b/include/acpi/acpi_numa.h @@ -3,7 +3,6 @@ #define __ACPI_NUMA_H #ifdef CONFIG_ACPI_NUMA -#include #include /* Proximity bitmap length */ diff --git a/include/acpi/processor.h b/include/acpi/processor.h index 683e124ad517..194027371928 100644 --- a/include/acpi/processor.h +++ b/include/acpi/processor.h @@ -2,11 +2,16 @@ #ifndef __ACPI_PROCESSOR_H #define __ACPI_PROCESSOR_H -#include #include #include #include +#include +#include +#include #include +#include +#include + #include #define ACPI_PROCESSOR_CLASS "processor" -- cgit v1.2.3-70-g09d2 From 1a68b346a2c9969c05e80a3b99a9ab160b5655c0 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 22 Nov 2021 18:05:31 +0100 Subject: ACPI: Change acpi_device_always_present() into acpi_device_override_status() Currently, acpi_bus_get_status() calls acpi_device_always_present() to allow platform quirks to override the _STA return to report that a device is present (status = ACPI_STA_DEFAULT) independent of the _STA return. In some cases it might also be useful to have the opposite functionality and have a platform quirk which marks a device as not present (status = 0) to work around ACPI table bugs. Change acpi_device_always_present() into a more generic acpi_device_override_status() function to allow this. Signed-off-by: Hans de Goede Signed-off-by: Rafael J. Wysocki --- drivers/acpi/bus.c | 4 +-- drivers/acpi/x86/utils.c | 64 ++++++++++++++++++++++++++++-------------------- include/acpi/acpi_bus.h | 5 ++-- 3 files changed, 42 insertions(+), 31 deletions(-) (limited to 'include/acpi') diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index fa923a929224..dd535b4b9a16 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -98,8 +98,8 @@ int acpi_bus_get_status(struct acpi_device *device) acpi_status status; unsigned long long sta; - if (acpi_device_always_present(device)) { - acpi_set_device_status(device, ACPI_STA_DEFAULT); + if (acpi_device_override_status(device, &sta)) { + acpi_set_device_status(device, sta); return 0; } diff --git a/drivers/acpi/x86/utils.c b/drivers/acpi/x86/utils.c index 3bcac98f6eca..edb4f3fd93dc 100644 --- a/drivers/acpi/x86/utils.c +++ b/drivers/acpi/x86/utils.c @@ -22,54 +22,63 @@ * Some BIOS-es (temporarily) hide specific APCI devices to work around Windows * driver bugs. We use DMI matching to match known cases of this. * - * We work around this by always reporting ACPI_STA_DEFAULT for these - * devices. Note this MUST only be done for devices where this is safe. + * Likewise sometimes some not-actually present devices are sometimes + * reported as present, which may cause issues. * - * This forcing of devices to be present is limited to specific CPU (SoC) - * models both to avoid potentially causing trouble on other models and - * because some HIDs are re-used on different SoCs for completely - * different devices. + * We work around this by using the below quirk list to override the status + * reported by the _STA method with a fixed value (ACPI_STA_DEFAULT or 0). + * Note this MUST only be done for devices where this is safe. + * + * This status overriding is limited to specific CPU (SoC) models both to + * avoid potentially causing trouble on other models and because some HIDs + * are re-used on different SoCs for completely different devices. */ -struct always_present_id { +struct override_status_id { struct acpi_device_id hid[2]; struct x86_cpu_id cpu_ids[2]; struct dmi_system_id dmi_ids[2]; /* Optional */ const char *uid; + unsigned long long status; }; -#define X86_MATCH(model) X86_MATCH_INTEL_FAM6_MODEL(model, NULL) - -#define ENTRY(hid, uid, cpu_models, dmi...) { \ +#define ENTRY(status, hid, uid, cpu_model, dmi...) { \ { { hid, }, {} }, \ - { cpu_models, {} }, \ + { X86_MATCH_INTEL_FAM6_MODEL(cpu_model, NULL), {} }, \ { { .matches = dmi }, {} }, \ uid, \ + status, \ } -static const struct always_present_id always_present_ids[] = { +#define PRESENT_ENTRY_HID(hid, uid, cpu_model, dmi...) \ + ENTRY(ACPI_STA_DEFAULT, hid, uid, cpu_model, dmi) + +#define NOT_PRESENT_ENTRY_HID(hid, uid, cpu_model, dmi...) \ + ENTRY(0, hid, uid, cpu_model, dmi) + +static const struct override_status_id override_status_ids[] = { /* * Bay / Cherry Trail PWM directly poked by GPU driver in win10, * but Linux uses a separate PWM driver, harmless if not used. */ - ENTRY("80860F09", "1", X86_MATCH(ATOM_SILVERMONT), {}), - ENTRY("80862288", "1", X86_MATCH(ATOM_AIRMONT), {}), + PRESENT_ENTRY_HID("80860F09", "1", ATOM_SILVERMONT, {}), + PRESENT_ENTRY_HID("80862288", "1", ATOM_AIRMONT, {}), /* * The INT0002 device is necessary to clear wakeup interrupt sources * on Cherry Trail devices, without it we get nobody cared IRQ msgs. */ - ENTRY("INT0002", "1", X86_MATCH(ATOM_AIRMONT), {}), + PRESENT_ENTRY_HID("INT0002", "1", ATOM_AIRMONT, {}), /* * On the Dell Venue 11 Pro 7130 and 7139, the DSDT hides * the touchscreen ACPI device until a certain time * after _SB.PCI0.GFX0.LCD.LCD1._ON gets called has passed * *and* _STA has been called at least 3 times since. */ - ENTRY("SYNA7500", "1", X86_MATCH(HASWELL_L), { + PRESENT_ENTRY_HID("SYNA7500", "1", HASWELL_L, { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), DMI_MATCH(DMI_PRODUCT_NAME, "Venue 11 Pro 7130"), }), - ENTRY("SYNA7500", "1", X86_MATCH(HASWELL_L), { + PRESENT_ENTRY_HID("SYNA7500", "1", HASWELL_L, { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), DMI_MATCH(DMI_PRODUCT_NAME, "Venue 11 Pro 7139"), }), @@ -85,19 +94,19 @@ static const struct always_present_id always_present_ids[] = { * was copy-pasted from the GPD win, so it has a disabled KIOX000A * node which we should not enable, thus we also check the BIOS date. */ - ENTRY("KIOX000A", "1", X86_MATCH(ATOM_AIRMONT), { + PRESENT_ENTRY_HID("KIOX000A", "1", ATOM_AIRMONT, { DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), DMI_MATCH(DMI_BOARD_NAME, "Default string"), DMI_MATCH(DMI_PRODUCT_NAME, "Default string"), DMI_MATCH(DMI_BIOS_DATE, "02/21/2017") }), - ENTRY("KIOX000A", "1", X86_MATCH(ATOM_AIRMONT), { + PRESENT_ENTRY_HID("KIOX000A", "1", ATOM_AIRMONT, { DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), DMI_MATCH(DMI_BOARD_NAME, "Default string"), DMI_MATCH(DMI_PRODUCT_NAME, "Default string"), DMI_MATCH(DMI_BIOS_DATE, "03/20/2017") }), - ENTRY("KIOX000A", "1", X86_MATCH(ATOM_AIRMONT), { + PRESENT_ENTRY_HID("KIOX000A", "1", ATOM_AIRMONT, { DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), DMI_MATCH(DMI_BOARD_NAME, "Default string"), DMI_MATCH(DMI_PRODUCT_NAME, "Default string"), @@ -105,26 +114,27 @@ static const struct always_present_id always_present_ids[] = { }), }; -bool acpi_device_always_present(struct acpi_device *adev) +bool acpi_device_override_status(struct acpi_device *adev, unsigned long long *status) { bool ret = false; unsigned int i; - for (i = 0; i < ARRAY_SIZE(always_present_ids); i++) { - if (acpi_match_device_ids(adev, always_present_ids[i].hid)) + for (i = 0; i < ARRAY_SIZE(override_status_ids); i++) { + if (acpi_match_device_ids(adev, override_status_ids[i].hid)) continue; if (!adev->pnp.unique_id || - strcmp(adev->pnp.unique_id, always_present_ids[i].uid)) + strcmp(adev->pnp.unique_id, override_status_ids[i].uid)) continue; - if (!x86_match_cpu(always_present_ids[i].cpu_ids)) + if (!x86_match_cpu(override_status_ids[i].cpu_ids)) continue; - if (always_present_ids[i].dmi_ids[0].matches[0].slot && - !dmi_check_system(always_present_ids[i].dmi_ids)) + if (override_status_ids[i].dmi_ids[0].matches[0].slot && + !dmi_check_system(override_status_ids[i].dmi_ids)) continue; + *status = override_status_ids[i].status; ret = true; break; } diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 480f9207a4c6..d6fe27b695c3 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -613,9 +613,10 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int state); int acpi_disable_wakeup_device_power(struct acpi_device *dev); #ifdef CONFIG_X86 -bool acpi_device_always_present(struct acpi_device *adev); +bool acpi_device_override_status(struct acpi_device *adev, unsigned long long *status); #else -static inline bool acpi_device_always_present(struct acpi_device *adev) +static inline bool acpi_device_override_status(struct acpi_device *adev, + unsigned long long *status) { return false; } -- cgit v1.2.3-70-g09d2 From e3c963c498871e0d4b2eceb32e2b989493838ccc Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 3 Dec 2021 17:36:20 +0100 Subject: ACPI: scan: Introduce acpi_fetch_acpi_dev() Introduce acpi_fetch_acpi_dev() as a more reasonable replacement for acpi_bus_get_device() and modify the code in scan.c to use it instead of the latter. No expected functional impact. Signed-off-by: Rafael J. Wysocki Reviewed-by: Mika Westerberg Reviewed-by: Hans de Goede --- drivers/acpi/scan.c | 34 ++++++++++++++++++++++++---------- include/acpi/acpi_bus.h | 1 + 2 files changed, 25 insertions(+), 10 deletions(-) (limited to 'include/acpi') diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 5991dddbc9ce..a9adcda39d40 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -135,12 +135,12 @@ bool acpi_scan_is_offline(struct acpi_device *adev, bool uevent) static acpi_status acpi_bus_offline(acpi_handle handle, u32 lvl, void *data, void **ret_p) { - struct acpi_device *device = NULL; + struct acpi_device *device = acpi_fetch_acpi_dev(handle); struct acpi_device_physical_node *pn; bool second_pass = (bool)data; acpi_status status = AE_OK; - if (acpi_bus_get_device(handle, &device)) + if (!device) return AE_OK; if (device->handler && !device->handler->hotplug.enabled) { @@ -180,10 +180,10 @@ static acpi_status acpi_bus_offline(acpi_handle handle, u32 lvl, void *data, static acpi_status acpi_bus_online(acpi_handle handle, u32 lvl, void *data, void **ret_p) { - struct acpi_device *device = NULL; + struct acpi_device *device = acpi_fetch_acpi_dev(handle); struct acpi_device_physical_node *pn; - if (acpi_bus_get_device(handle, &device)) + if (!device) return AE_OK; mutex_lock(&device->physical_node_lock); @@ -599,6 +599,19 @@ int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device) } EXPORT_SYMBOL(acpi_bus_get_device); +/** + * acpi_fetch_acpi_dev - Retrieve ACPI device object. + * @handle: ACPI handle associated with the requested ACPI device object. + * + * Return a pointer to the ACPI device object associated with @handle, if + * present, or NULL otherwise. + */ +struct acpi_device *acpi_fetch_acpi_dev(acpi_handle handle) +{ + return handle_to_device(handle, NULL); +} +EXPORT_SYMBOL_GPL(acpi_fetch_acpi_dev); + static void get_acpi_device(void *dev) { acpi_dev_get(dev); @@ -799,7 +812,7 @@ static const char * const acpi_ignore_dep_ids[] = { static struct acpi_device *acpi_bus_get_parent(acpi_handle handle) { - struct acpi_device *device = NULL; + struct acpi_device *device; acpi_status status; /* @@ -814,7 +827,9 @@ static struct acpi_device *acpi_bus_get_parent(acpi_handle handle) status = acpi_get_parent(handle, &handle); if (ACPI_FAILURE(status)) return status == AE_NULL_ENTRY ? NULL : acpi_root; - } while (acpi_bus_get_device(handle, &device)); + + device = acpi_fetch_acpi_dev(handle); + } while (!device); return device; } @@ -2003,11 +2018,10 @@ static bool acpi_bus_scan_second_pass; static acpi_status acpi_bus_check_add(acpi_handle handle, bool check_dep, struct acpi_device **adev_p) { - struct acpi_device *device = NULL; + struct acpi_device *device = acpi_fetch_acpi_dev(handle); acpi_object_type acpi_type; int type; - acpi_bus_get_device(handle, &device); if (device) goto out; @@ -2548,8 +2562,8 @@ int __init acpi_scan_init(void) if (result) goto out; - result = acpi_bus_get_device(ACPI_ROOT_OBJECT, &acpi_root); - if (result) + acpi_root = acpi_fetch_acpi_dev(ACPI_ROOT_OBJECT); + if (!acpi_root) goto out; /* Fixed feature devices do not exist on HW-reduced platform */ diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 480f9207a4c6..17f700c9a4f9 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -505,6 +505,7 @@ extern int unregister_acpi_notifier(struct notifier_block *); */ int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device); +struct acpi_device *acpi_fetch_acpi_dev(acpi_handle handle); acpi_status acpi_bus_get_status_handle(acpi_handle handle, unsigned long long *sta); int acpi_bus_get_status(struct acpi_device *device); -- cgit v1.2.3-70-g09d2 From f81bdeaf816142e0729eea0cc84c395ec9673151 Mon Sep 17 00:00:00 2001 From: Mark Langsdorf Date: Wed, 22 Dec 2021 16:57:34 +0100 Subject: ACPICA: actypes.h: Expand the ACPI_ACCESS_ definitions ACPICA commit bc02c76d518135531483dfc276ed28b7ee632ce1 The current ACPI_ACCESS_*_WIDTH defines do not provide a way to test that size is small enough to not cause an overflow when applied to a 32-bit integer. Rather than adding more magic numbers, add ACPI_ACCESS_*_SHIFT, ACPI_ACCESS_*_MAX, and ACPI_ACCESS_*_DEFAULT #defines and redefine ACPI_ACCESS_*_WIDTH in terms of the new #defines. This was inititally reported on Linux where a size of 102 in ACPI_ACCESS_BIT_WIDTH caused an overflow error in the SPCR initialization code. Link: https://github.com/acpica/acpica/commit/bc02c76d Signed-off-by: Mark Langsdorf Signed-off-by: Bob Moore Signed-off-by: Rafael J. Wysocki --- include/acpi/actypes.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'include/acpi') diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index ff8b3c913f21..248242dca28d 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -536,8 +536,14 @@ typedef u64 acpi_integer; * Can be used with access_width of struct acpi_generic_address and access_size of * struct acpi_resource_generic_register. */ -#define ACPI_ACCESS_BIT_WIDTH(size) (1 << ((size) + 2)) -#define ACPI_ACCESS_BYTE_WIDTH(size) (1 << ((size) - 1)) +#define ACPI_ACCESS_BIT_SHIFT 2 +#define ACPI_ACCESS_BYTE_SHIFT -1 +#define ACPI_ACCESS_BIT_MAX (31 - ACPI_ACCESS_BIT_SHIFT) +#define ACPI_ACCESS_BYTE_MAX (31 - ACPI_ACCESS_BYTE_SHIFT) +#define ACPI_ACCESS_BIT_DEFAULT (8 - ACPI_ACCESS_BIT_SHIFT) +#define ACPI_ACCESS_BYTE_DEFAULT (8 - ACPI_ACCESS_BYTE_SHIFT) +#define ACPI_ACCESS_BIT_WIDTH(size) (1 << ((size) + ACPI_ACCESS_BIT_SHIFT)) +#define ACPI_ACCESS_BYTE_WIDTH(size) (1 << ((size) + ACPI_ACCESS_BYTE_SHIFT)) /******************************************************************************* * -- cgit v1.2.3-70-g09d2 From ca25f92b72d25457653dbf2a81f322235804fb05 Mon Sep 17 00:00:00 2001 From: Jessica Clarke Date: Wed, 22 Dec 2021 17:21:25 +0100 Subject: ACPICA: Use original data_table_region pointer for accesses ACPICA commit d9eb82bd7515989f0b29d79deeeb758db4d6529c Currently the pointer to the table is cast to acpi_physical_address and later cast back to a pointer to be dereferenced. Whether or not this is supported is implementation-defined. On CHERI, and thus Arm's experimental Morello prototype architecture, pointers are represented as capabilities, which are unforgeable bounded pointers, providing always-on fine-grained spatial memory safety. This means that any pointer cast to a plain integer will lose all its associated metadata, and when cast back to a pointer it will give a null-derived pointer (one that has the same metadata as null but an address equal to the integer) that will trap on any dereference. As a result, this is an implementation where acpi_physical_address cannot be used as a hack to store real pointers. Thus, add a new field to struct acpi_object_region to store the pointer for table regions, and propagate it to acpi_ex_data_table_space_handler via the region context, to use a more portable implementation that supports CHERI. Link: https://github.com/acpica/acpica/commit/d9eb82bd Signed-off-by: Bob Moore Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/acevents.h | 5 ++++ drivers/acpi/acpica/acobject.h | 1 + drivers/acpi/acpica/dsopcode.c | 1 + drivers/acpi/acpica/evhandler.c | 2 +- drivers/acpi/acpica/evrgnini.c | 52 +++++++++++++++++++++++++++++++++++++++++ drivers/acpi/acpica/excreate.c | 1 + drivers/acpi/acpica/exregion.c | 15 ++++++++---- include/acpi/actypes.h | 4 ++++ 8 files changed, 76 insertions(+), 5 deletions(-) (limited to 'include/acpi') diff --git a/drivers/acpi/acpica/acevents.h b/drivers/acpi/acpica/acevents.h index 82a75964343b..b29ba436944a 100644 --- a/drivers/acpi/acpica/acevents.h +++ b/drivers/acpi/acpica/acevents.h @@ -223,6 +223,11 @@ acpi_ev_pci_bar_region_setup(acpi_handle handle, u32 function, void *handler_context, void **region_context); +acpi_status +acpi_ev_data_table_region_setup(acpi_handle handle, + u32 function, + void *handler_context, void **region_context); + acpi_status acpi_ev_default_region_setup(acpi_handle handle, u32 function, diff --git a/drivers/acpi/acpica/acobject.h b/drivers/acpi/acpica/acobject.h index 9db5ae0f79ea..0aa0d847cb25 100644 --- a/drivers/acpi/acpica/acobject.h +++ b/drivers/acpi/acpica/acobject.h @@ -138,6 +138,7 @@ struct acpi_object_region { union acpi_operand_object *next; acpi_physical_address address; u32 length; + void *pointer; /* Only for data table regions */ }; struct acpi_object_method { diff --git a/drivers/acpi/acpica/dsopcode.c b/drivers/acpi/acpica/dsopcode.c index 639635291ab7..44c448269861 100644 --- a/drivers/acpi/acpica/dsopcode.c +++ b/drivers/acpi/acpica/dsopcode.c @@ -531,6 +531,7 @@ acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state, obj_desc->region.address = ACPI_PTR_TO_PHYSADDR(table); obj_desc->region.length = table->length; + obj_desc->region.pointer = table; ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n", obj_desc, diff --git a/drivers/acpi/acpica/evhandler.c b/drivers/acpi/acpica/evhandler.c index c0cd7147a5a3..8f43d38dc4ca 100644 --- a/drivers/acpi/acpica/evhandler.c +++ b/drivers/acpi/acpica/evhandler.c @@ -386,7 +386,7 @@ acpi_ev_install_space_handler(struct acpi_namespace_node *node, case ACPI_ADR_SPACE_DATA_TABLE: handler = acpi_ex_data_table_space_handler; - setup = NULL; + setup = acpi_ev_data_table_region_setup; break; default: diff --git a/drivers/acpi/acpica/evrgnini.c b/drivers/acpi/acpica/evrgnini.c index 984c172453bf..d28dee929e61 100644 --- a/drivers/acpi/acpica/evrgnini.c +++ b/drivers/acpi/acpica/evrgnini.c @@ -406,6 +406,58 @@ acpi_ev_cmos_region_setup(acpi_handle handle, return_ACPI_STATUS(AE_OK); } +/******************************************************************************* + * + * FUNCTION: acpi_ev_data_table_region_setup + * + * PARAMETERS: handle - Region we are interested in + * function - Start or stop + * handler_context - Address space handler context + * region_context - Region specific context + * + * RETURN: Status + * + * DESCRIPTION: Setup a data_table_region + * + * MUTEX: Assumes namespace is not locked + * + ******************************************************************************/ + +acpi_status +acpi_ev_data_table_region_setup(acpi_handle handle, + u32 function, + void *handler_context, void **region_context) +{ + union acpi_operand_object *region_desc = + (union acpi_operand_object *)handle; + struct acpi_data_table_space_context *local_region_context; + + ACPI_FUNCTION_TRACE(ev_data_table_region_setup); + + if (function == ACPI_REGION_DEACTIVATE) { + if (*region_context) { + ACPI_FREE(*region_context); + *region_context = NULL; + } + return_ACPI_STATUS(AE_OK); + } + + /* Create a new context */ + + local_region_context = + ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_data_table_space_context)); + if (!(local_region_context)) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* Save the data table pointer for use in the handler */ + + local_region_context->pointer = region_desc->region.pointer; + + *region_context = local_region_context; + return_ACPI_STATUS(AE_OK); +} + /******************************************************************************* * * FUNCTION: acpi_ev_default_region_setup diff --git a/drivers/acpi/acpica/excreate.c b/drivers/acpi/acpica/excreate.c index 80b52ad55775..deb3674ae726 100644 --- a/drivers/acpi/acpica/excreate.c +++ b/drivers/acpi/acpica/excreate.c @@ -279,6 +279,7 @@ acpi_ex_create_region(u8 * aml_start, obj_desc->region.space_id = space_id; obj_desc->region.address = 0; obj_desc->region.length = 0; + obj_desc->region.pointer = NULL; obj_desc->region.node = node; obj_desc->region.handler = NULL; obj_desc->common.flags &= diff --git a/drivers/acpi/acpica/exregion.c b/drivers/acpi/acpica/exregion.c index 82b713a9a193..48c19908fa4e 100644 --- a/drivers/acpi/acpica/exregion.c +++ b/drivers/acpi/acpica/exregion.c @@ -509,8 +509,15 @@ acpi_ex_data_table_space_handler(u32 function, u64 *value, void *handler_context, void *region_context) { + struct acpi_data_table_space_context *mapping; + char *pointer; + ACPI_FUNCTION_TRACE(ex_data_table_space_handler); + mapping = (struct acpi_data_table_space_context *) region_context; + pointer = ACPI_CAST_PTR(char, mapping->pointer) + + (address - ACPI_PTR_TO_PHYSADDR(mapping->pointer)); + /* * Perform the memory read or write. The bit_width was already * validated. @@ -518,14 +525,14 @@ acpi_ex_data_table_space_handler(u32 function, switch (function) { case ACPI_READ: - memcpy(ACPI_CAST_PTR(char, value), - ACPI_PHYSADDR_TO_PTR(address), ACPI_DIV_8(bit_width)); + memcpy(ACPI_CAST_PTR(char, value), pointer, + ACPI_DIV_8(bit_width)); break; case ACPI_WRITE: - memcpy(ACPI_PHYSADDR_TO_PTR(address), - ACPI_CAST_PTR(char, value), ACPI_DIV_8(bit_width)); + memcpy(pointer, ACPI_CAST_PTR(char, value), + ACPI_DIV_8(bit_width)); break; default: diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index 248242dca28d..700c2449e85a 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -1221,6 +1221,10 @@ struct acpi_mem_space_context { struct acpi_mem_mapping *first_mm; }; +struct acpi_data_table_space_context { + void *pointer; +}; + /* * struct acpi_memory_list is used only if the ACPICA local cache is enabled */ -- cgit v1.2.3-70-g09d2 From 5d6e59665d8bb0f8fa4d47726a93326f8ddfb448 Mon Sep 17 00:00:00 2001 From: Jessica Clarke Date: Wed, 22 Dec 2021 17:22:28 +0100 Subject: ACPICA: Use original pointer for virtual origin tables ACPICA commit dfa3feffa8f760b686207d09dc880cd2f26c72af Currently the pointer to the table is cast to acpi_physical_address and later cast back to a pointer to be dereferenced. Whether or not this is supported is implementation-defined. On CHERI, and thus Arm's experimental Morello prototype architecture, pointers are represented as capabilities, which are unforgeable bounded pointers, providing always-on fine-grained spatial memory safety. This means that any pointer cast to a plain integer will lose all its associated metadata, and when cast back to a pointer it will give a null-derived pointer (one that has the same metadata as null but an address equal to the integer) that will trap on any dereference. As a result, this is an implementation where acpi_physical_address cannot be used as a hack to store real pointers. Thus, alter the lifecycle of table descriptors. Internal physical tables keep the current behaviour where only the address is set on install, and the pointer is set on acquire. Virtual tables (internal and external) now store the pointer on initialisation and use that on acquire (which will redundantly set *table_ptr to itself, but changing that is both unnecessary and overly complicated as acpi_tb_acquire_table is called with both a pointer to a variable and a pointer to Table->Pointer itself). This requires propagating the (possible) table pointer everywhere in order to make sure pointers make it through to acpi_tb_acquire_temp_table, which requires a change to the acpi_install_table interface. Instead of taking an ACPI_PHYSADDR_TYPE and a boolean indicating whether it's physical or virtual, it is now split into acpi_install_table (that takes an external virtual table pointer) and acpi_install_physical_table (that takes an ACPI_PHYSADDR_TYPE for an internal physical table address). This also has the benefit of providing a cleaner API. Link: https://github.com/acpica/acpica/commit/dfa3feff Signed-off-by: Bob Moore [ rjw: Adjust the code in tables.c to match interface changes ] Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/actables.h | 8 +++- drivers/acpi/acpica/exconfig.c | 2 +- drivers/acpi/acpica/tbdata.c | 93 ++++++++++++++++++++++++++++-------------- drivers/acpi/acpica/tbfadt.c | 6 +-- drivers/acpi/acpica/tbinstal.c | 15 +++++-- drivers/acpi/acpica/tbutils.c | 2 +- drivers/acpi/acpica/tbxfload.c | 52 ++++++++++++++++------- drivers/acpi/tables.c | 4 +- include/acpi/acpixf.h | 6 ++- 9 files changed, 129 insertions(+), 59 deletions(-) (limited to 'include/acpi') diff --git a/drivers/acpi/acpica/actables.h b/drivers/acpi/acpica/actables.h index e2d0046799a2..533802fe73e9 100644 --- a/drivers/acpi/acpica/actables.h +++ b/drivers/acpi/acpica/actables.h @@ -35,7 +35,8 @@ acpi_tb_init_table_descriptor(struct acpi_table_desc *table_desc, acpi_status acpi_tb_acquire_temp_table(struct acpi_table_desc *table_desc, - acpi_physical_address address, u8 flags); + acpi_physical_address address, + u8 flags, struct acpi_table_header *table); void acpi_tb_release_temp_table(struct acpi_table_desc *table_desc); @@ -86,6 +87,7 @@ acpi_tb_release_table(struct acpi_table_header *table, acpi_status acpi_tb_install_standard_table(acpi_physical_address address, u8 flags, + struct acpi_table_header *table, u8 reload, u8 override, u32 *table_index); void acpi_tb_uninstall_table(struct acpi_table_desc *table_desc); @@ -95,7 +97,9 @@ acpi_tb_load_table(u32 table_index, struct acpi_namespace_node *parent_node); acpi_status acpi_tb_install_and_load_table(acpi_physical_address address, - u8 flags, u8 override, u32 *table_index); + u8 flags, + struct acpi_table_header *table, + u8 override, u32 *table_index); acpi_status acpi_tb_unload_table(u32 table_index); diff --git a/drivers/acpi/acpica/exconfig.c b/drivers/acpi/acpica/exconfig.c index 0cd9b3738e76..6c2685a6a4c1 100644 --- a/drivers/acpi/acpica/exconfig.c +++ b/drivers/acpi/acpica/exconfig.c @@ -411,7 +411,7 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, acpi_ex_exit_interpreter(); status = acpi_tb_install_and_load_table(ACPI_PTR_TO_PHYSADDR(table), ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL, - TRUE, &table_index); + table, TRUE, &table_index); acpi_ex_enter_interpreter(); if (ACPI_FAILURE(status)) { diff --git a/drivers/acpi/acpica/tbdata.c b/drivers/acpi/acpica/tbdata.c index ebbca109edcb..89f08de67e6d 100644 --- a/drivers/acpi/acpica/tbdata.c +++ b/drivers/acpi/acpica/tbdata.c @@ -89,14 +89,27 @@ acpi_tb_init_table_descriptor(struct acpi_table_desc *table_desc, { /* - * Initialize the table descriptor. Set the pointer to NULL, since the - * table is not fully mapped at this time. + * Initialize the table descriptor. Set the pointer to NULL for external + * tables, since the table is not fully mapped at this time. */ memset(table_desc, 0, sizeof(struct acpi_table_desc)); table_desc->address = address; table_desc->length = table->length; table_desc->flags = flags; ACPI_MOVE_32_TO_32(table_desc->signature.ascii, table->signature); + + switch (table_desc->flags & ACPI_TABLE_ORIGIN_MASK) { + case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL: + case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL: + + table_desc->pointer = table; + break; + + case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL: + default: + + break; + } } /******************************************************************************* @@ -132,9 +145,7 @@ acpi_tb_acquire_table(struct acpi_table_desc *table_desc, case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL: case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL: - table = ACPI_CAST_PTR(struct acpi_table_header, - ACPI_PHYSADDR_TO_PTR(table_desc-> - address)); + table = table_desc->pointer; break; default: @@ -196,6 +207,8 @@ acpi_tb_release_table(struct acpi_table_header *table, * PARAMETERS: table_desc - Table descriptor to be acquired * address - Address of the table * flags - Allocation flags of the table + * table - Pointer to the table (required for virtual + * origins, optional for physical) * * RETURN: Status * @@ -208,49 +221,52 @@ acpi_tb_release_table(struct acpi_table_header *table, acpi_status acpi_tb_acquire_temp_table(struct acpi_table_desc *table_desc, - acpi_physical_address address, u8 flags) + acpi_physical_address address, + u8 flags, struct acpi_table_header *table) { - struct acpi_table_header *table_header; + u8 mapped_table = FALSE; switch (flags & ACPI_TABLE_ORIGIN_MASK) { case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL: /* Get the length of the full table from the header */ - table_header = - acpi_os_map_memory(address, - sizeof(struct acpi_table_header)); - if (!table_header) { - return (AE_NO_MEMORY); + if (!table) { + table = + acpi_os_map_memory(address, + sizeof(struct + acpi_table_header)); + if (!table) { + return (AE_NO_MEMORY); + } + + mapped_table = TRUE; } - acpi_tb_init_table_descriptor(table_desc, address, flags, - table_header); - acpi_os_unmap_memory(table_header, - sizeof(struct acpi_table_header)); - return (AE_OK); + break; case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL: case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL: - table_header = ACPI_CAST_PTR(struct acpi_table_header, - ACPI_PHYSADDR_TO_PTR(address)); - if (!table_header) { - return (AE_NO_MEMORY); + if (!table) { + return_ACPI_STATUS(AE_BAD_PARAMETER); } - acpi_tb_init_table_descriptor(table_desc, address, flags, - table_header); - return (AE_OK); + break; default: - break; + /* Table is not valid yet */ + + return (AE_NO_MEMORY); } - /* Table is not valid yet */ + acpi_tb_init_table_descriptor(table_desc, address, flags, table); + if (mapped_table) { + acpi_os_unmap_memory(table, sizeof(struct acpi_table_header)); + } - return (AE_NO_MEMORY); + return (AE_OK); } /******************************************************************************* @@ -335,7 +351,19 @@ void acpi_tb_invalidate_table(struct acpi_table_desc *table_desc) acpi_tb_release_table(table_desc->pointer, table_desc->length, table_desc->flags); - table_desc->pointer = NULL; + + switch (table_desc->flags & ACPI_TABLE_ORIGIN_MASK) { + case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL: + + table_desc->pointer = NULL; + break; + + case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL: + case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL: + default: + + break; + } return_VOID; } @@ -959,6 +987,9 @@ acpi_tb_load_table(u32 table_index, struct acpi_namespace_node *parent_node) * * PARAMETERS: address - Physical address of the table * flags - Allocation flags of the table + * table - Pointer to the table (required for + * virtual origins, optional for + * physical) * override - Whether override should be performed * table_index - Where table index is returned * @@ -970,7 +1001,9 @@ acpi_tb_load_table(u32 table_index, struct acpi_namespace_node *parent_node) acpi_status acpi_tb_install_and_load_table(acpi_physical_address address, - u8 flags, u8 override, u32 *table_index) + u8 flags, + struct acpi_table_header *table, + u8 override, u32 *table_index) { acpi_status status; u32 i; @@ -979,7 +1012,7 @@ acpi_tb_install_and_load_table(acpi_physical_address address, /* Install the table and load it into the namespace */ - status = acpi_tb_install_standard_table(address, flags, TRUE, + status = acpi_tb_install_standard_table(address, flags, table, TRUE, override, &i); if (ACPI_FAILURE(status)) { goto exit; diff --git a/drivers/acpi/acpica/tbfadt.c b/drivers/acpi/acpica/tbfadt.c index 5174abfa8af9..047bd094ba68 100644 --- a/drivers/acpi/acpica/tbfadt.c +++ b/drivers/acpi/acpica/tbfadt.c @@ -313,7 +313,7 @@ void acpi_tb_parse_fadt(void) acpi_tb_install_standard_table((acpi_physical_address)acpi_gbl_FADT. Xdsdt, ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL, - FALSE, TRUE, &acpi_gbl_dsdt_index); + NULL, FALSE, TRUE, &acpi_gbl_dsdt_index); /* If Hardware Reduced flag is set, there is no FACS */ @@ -322,14 +322,14 @@ void acpi_tb_parse_fadt(void) acpi_tb_install_standard_table((acpi_physical_address) acpi_gbl_FADT.facs, ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL, - FALSE, TRUE, + NULL, FALSE, TRUE, &acpi_gbl_facs_index); } if (acpi_gbl_FADT.Xfacs) { acpi_tb_install_standard_table((acpi_physical_address) acpi_gbl_FADT.Xfacs, ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL, - FALSE, TRUE, + NULL, FALSE, TRUE, &acpi_gbl_xfacs_index); } } diff --git a/drivers/acpi/acpica/tbinstal.c b/drivers/acpi/acpica/tbinstal.c index 8d1e5b572493..5649f493a1ed 100644 --- a/drivers/acpi/acpica/tbinstal.c +++ b/drivers/acpi/acpica/tbinstal.c @@ -79,6 +79,8 @@ acpi_tb_install_table_with_override(struct acpi_table_desc *new_table_desc, * PARAMETERS: address - Address of the table (might be a virtual * address depending on the table_flags) * flags - Flags for the table + * table - Pointer to the table (required for virtual + * origins, optional for physical) * reload - Whether reload should be performed * override - Whether override should be performed * table_index - Where the table index is returned @@ -96,6 +98,7 @@ acpi_tb_install_table_with_override(struct acpi_table_desc *new_table_desc, acpi_status acpi_tb_install_standard_table(acpi_physical_address address, u8 flags, + struct acpi_table_header *table, u8 reload, u8 override, u32 *table_index) { u32 i; @@ -106,7 +109,8 @@ acpi_tb_install_standard_table(acpi_physical_address address, /* Acquire a temporary table descriptor for validation */ - status = acpi_tb_acquire_temp_table(&new_table_desc, address, flags); + status = + acpi_tb_acquire_temp_table(&new_table_desc, address, flags, table); if (ACPI_FAILURE(status)) { ACPI_ERROR((AE_INFO, "Could not acquire table length at %8.8X%8.8X", @@ -209,7 +213,8 @@ void acpi_tb_override_table(struct acpi_table_desc *old_table_desc) if (ACPI_SUCCESS(status) && table) { acpi_tb_acquire_temp_table(&new_table_desc, ACPI_PTR_TO_PHYSADDR(table), - ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL); + ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL, + table); ACPI_ERROR_ONLY(override_type = "Logical"); goto finish_override; } @@ -220,7 +225,8 @@ void acpi_tb_override_table(struct acpi_table_desc *old_table_desc) &address, &length); if (ACPI_SUCCESS(status) && address && length) { acpi_tb_acquire_temp_table(&new_table_desc, address, - ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL); + ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL, + NULL); ACPI_ERROR_ONLY(override_type = "Physical"); goto finish_override; } @@ -289,7 +295,8 @@ void acpi_tb_uninstall_table(struct acpi_table_desc *table_desc) if ((table_desc->flags & ACPI_TABLE_ORIGIN_MASK) == ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL) { - ACPI_FREE(ACPI_PHYSADDR_TO_PTR(table_desc->address)); + ACPI_FREE(table_desc->pointer); + table_desc->pointer = NULL; } table_desc->address = ACPI_PTR_TO_PHYSADDR(NULL); diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c index 4b9b329a5a92..5e8d50a4b6a9 100644 --- a/drivers/acpi/acpica/tbutils.c +++ b/drivers/acpi/acpica/tbutils.c @@ -328,7 +328,7 @@ acpi_tb_parse_root_table(acpi_physical_address rsdp_address) status = acpi_tb_install_standard_table(address, ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL, - FALSE, TRUE, + NULL, FALSE, TRUE, &table_index); if (ACPI_SUCCESS(status) && diff --git a/drivers/acpi/acpica/tbxfload.c b/drivers/acpi/acpica/tbxfload.c index 38623049b962..87356d9ad613 100644 --- a/drivers/acpi/acpica/tbxfload.c +++ b/drivers/acpi/acpica/tbxfload.c @@ -227,9 +227,7 @@ unlock_and_exit: * * FUNCTION: acpi_install_table * - * PARAMETERS: address - Address of the ACPI table to be installed. - * physical - Whether the address is a physical table - * address or not + * PARAMETERS: table - Pointer to the ACPI table to be installed. * * RETURN: Status * @@ -240,28 +238,54 @@ unlock_and_exit: ******************************************************************************/ acpi_status ACPI_INIT_FUNCTION -acpi_install_table(acpi_physical_address address, u8 physical) +acpi_install_table(struct acpi_table_header *table) { acpi_status status; - u8 flags; u32 table_index; ACPI_FUNCTION_TRACE(acpi_install_table); - if (physical) { - flags = ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL; - } else { - flags = ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL; - } - - status = acpi_tb_install_standard_table(address, flags, - FALSE, FALSE, &table_index); + status = acpi_tb_install_standard_table(ACPI_PTR_TO_PHYSADDR(table), + ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL, + table, FALSE, FALSE, + &table_index); return_ACPI_STATUS(status); } ACPI_EXPORT_SYMBOL_INIT(acpi_install_table) +/******************************************************************************* + * + * FUNCTION: acpi_install_physical_table + * + * PARAMETERS: address - Address of the ACPI table to be installed. + * + * RETURN: Status + * + * DESCRIPTION: Dynamically install an ACPI table. + * Note: This function should only be invoked after + * acpi_initialize_tables() and before acpi_load_tables(). + * + ******************************************************************************/ +acpi_status ACPI_INIT_FUNCTION +acpi_install_physical_table(acpi_physical_address address) +{ + acpi_status status; + u32 table_index; + + ACPI_FUNCTION_TRACE(acpi_install_physical_table); + + status = acpi_tb_install_standard_table(address, + ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL, + NULL, FALSE, FALSE, + &table_index); + + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL_INIT(acpi_install_physical_table) + /******************************************************************************* * * FUNCTION: acpi_load_table @@ -298,7 +322,7 @@ acpi_status acpi_load_table(struct acpi_table_header *table, u32 *table_idx) ACPI_INFO(("Host-directed Dynamic ACPI Table Load:")); status = acpi_tb_install_and_load_table(ACPI_PTR_TO_PHYSADDR(table), ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL, - FALSE, &table_index); + table, FALSE, &table_index); if (table_idx) { *table_idx = table_index; } diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index 71419eb16e09..2fa8f611d0a7 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c @@ -723,7 +723,7 @@ static void __init acpi_table_initrd_scan(void) /* * Mark the table to avoid being used in * acpi_table_initrd_override(). Though this is not possible - * because override is disabled in acpi_install_table(). + * because override is disabled in acpi_install_physical_table(). */ if (test_and_set_bit(table_index, acpi_initrd_installed)) { acpi_os_unmap_memory(table, ACPI_HEADER_SIZE); @@ -734,7 +734,7 @@ static void __init acpi_table_initrd_scan(void) table->signature, table->oem_id, table->oem_table_id); acpi_os_unmap_memory(table, ACPI_HEADER_SIZE); - acpi_install_table(acpi_tables_addr + table_offset, TRUE); + acpi_install_physical_table(acpi_tables_addr + table_offset); next_table: table_offset += table_length; table_index++; diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index 73ba13914321..987bb0aa042e 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -454,9 +454,11 @@ ACPI_EXTERNAL_RETURN_STATUS(acpi_status * ACPI table load/unload interfaces */ ACPI_EXTERNAL_RETURN_STATUS(acpi_status ACPI_INIT_FUNCTION - acpi_install_table(acpi_physical_address address, - u8 physical)) + acpi_install_table(struct acpi_table_header *table)) +ACPI_EXTERNAL_RETURN_STATUS(acpi_status ACPI_INIT_FUNCTION + acpi_install_physical_table(acpi_physical_address + address)) ACPI_EXTERNAL_RETURN_STATUS(acpi_status acpi_load_table(struct acpi_table_header *table, u32 *table_idx)) -- cgit v1.2.3-70-g09d2 From 339651be3704f336634d90c000a7778b86e1be99 Mon Sep 17 00:00:00 2001 From: Jessica Clarke Date: Wed, 22 Dec 2021 17:23:28 +0100 Subject: ACPICA: Macros: Remove ACPI_PHYSADDR_TO_PTR ACPICA commit 52abebd410945ec55afb4dd8b7150e8a39b5c960 This macro was only ever used when stuffing pointers into physical addresses and trying to later reconstruct the pointer, which is implementation-defined as to whether that can be done. Now that all such operations are gone, the macro is unused, and should be removed to avoid such practices being reintroduced. Link: https://github.com/acpica/acpica/commit/52abebd4 Signed-off-by: Bob Moore Signed-off-by: Rafael J. Wysocki --- include/acpi/actypes.h | 1 - 1 file changed, 1 deletion(-) (limited to 'include/acpi') diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index 700c2449e85a..83a7ee1fbd7c 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -509,7 +509,6 @@ typedef u64 acpi_integer; #define ACPI_TO_POINTER(i) ACPI_CAST_PTR (void, (acpi_size) (i)) #define ACPI_TO_INTEGER(p) ACPI_PTR_DIFF (p, (void *) 0) #define ACPI_OFFSET(d, f) ACPI_PTR_DIFF (&(((d *) 0)->f), (void *) 0) -#define ACPI_PHYSADDR_TO_PTR(i) ACPI_TO_POINTER(i) #define ACPI_PTR_TO_PHYSADDR(i) ACPI_TO_INTEGER(i) /* Optimizations for 4-character (32-bit) acpi_name manipulation */ -- cgit v1.2.3-70-g09d2 From e4a07f5acd730802ada629d52a29c4873f9826a4 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Wed, 22 Dec 2021 17:25:40 +0100 Subject: ACPICA: iASL/Disassembler: Additional support for NHLT table ACPICA commit 0420852ffc520b81960e877852703b739c16025c Added support for Vendor-defined microphone arrays and SNR (signal-to-noise) extension. Link: https://github.com/acpica/acpica/commit/0420852f Signed-off-by: Bob Moore Signed-off-by: Rafael J. Wysocki --- include/acpi/actbl2.h | 72 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 42 insertions(+), 30 deletions(-) (limited to 'include/acpi') diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h index 71ca090fd61b..380bff6bb2fd 100644 --- a/include/acpi/actbl2.h +++ b/include/acpi/actbl2.h @@ -1495,12 +1495,10 @@ struct acpi_nhlt_device_specific_config_a { /* Values for Config Type above */ -#define ACPI_NHLT_TYPE_MIC_ARRAY 0x01 -#define ACPI_NHLT_TYPE_GENERIC 0x00 - -/* Mask for Extension field of array_type */ - -#define ACPI_NHLT_ARRAY_TYPE_MASK 0x10 +#define ACPI_NHLT_CONFIG_TYPE_GENERIC 0x00 +#define ACPI_NHLT_CONFIG_TYPE_MIC_ARRAY 0x01 +#define ACPI_NHLT_CONFIG_TYPE_RENDER_FEEDBACK 0x03 +#define ACPI_NHLT_CONFIG_TYPE_RESERVED 0x04 /* 4 and above are reserved */ struct acpi_nhlt_device_specific_config_b { u32 capabilities_size; @@ -1511,6 +1509,11 @@ struct acpi_nhlt_device_specific_config_c { u8 virtual_slot; }; +struct acpi_nhlt_render_device_specific_config { + u32 capabilities_size; + u8 virtual_slot; +}; + struct acpi_nhlt_wave_extensible { u16 format_tag; u16 channel_count; @@ -1573,17 +1576,22 @@ struct acpi_nhlt_mic_device_specific_config { /* Values for array_type_ext above */ -#define SMALL_LINEAR_2ELEMENT 0x0A -#define BIG_LINEAR_2ELEMENT 0x0B -#define FIRST_GEOMETRY_LINEAR_4ELEMENT 0x0C -#define PLANAR_LSHAPED_4ELEMENT 0x0D -#define SECOND_GEOMETRY_LINEAR_4ELEMENT 0x0E -#define VENDOR_DEFINED 0x0F -#define ARRAY_TYPE_MASK 0x0F -#define ARRAY_TYPE_EXT_MASK 0x10 +#define ACPI_NHLT_ARRAY_TYPE_RESERVED 0x09 // 9 and below are reserved +#define ACPI_NHLT_SMALL_LINEAR_2ELEMENT 0x0A +#define ACPI_NHLT_BIG_LINEAR_2ELEMENT 0x0B +#define ACPI_NHLT_FIRST_GEOMETRY_LINEAR_4ELEMENT 0x0C +#define ACPI_NHLT_PLANAR_LSHAPED_4ELEMENT 0x0D +#define ACPI_NHLT_SECOND_GEOMETRY_LINEAR_4ELEMENT 0x0E +#define ACPI_NHLT_VENDOR_DEFINED 0x0F +#define ACPI_NHLT_ARRAY_TYPE_MASK 0x0F +#define ACPI_NHLT_ARRAY_TYPE_EXT_MASK 0x10 + +#define ACPI_NHLT_NO_EXTENSION 0x0 +#define ACPI_NHLT_MIC_SNR_SENSITIVITY_EXT (1<<4) -#define NO_EXTENSION 0x0 -#define MIC_SNR_SENSITIVITY_EXT 0x1 +struct acpi_nhlt_vendor_mic_count { + u8 microphone_count; +}; struct acpi_nhlt_vendor_mic_config { u8 type; @@ -1603,22 +1611,25 @@ struct acpi_nhlt_vendor_mic_config { /* Values for Type field above */ -#define MIC_OMNIDIRECTIONAL 0 -#define MIC_SUBCARDIOID 1 -#define MIC_CARDIOID 2 -#define MIC_SUPER_CARDIOID 3 -#define MIC_HYPER_CARDIOID 4 -#define MIC_8_SHAPED 5 -#define MIC_VENDOR_DEFINED 7 +#define ACPI_NHLT_MIC_OMNIDIRECTIONAL 0 +#define ACPI_NHLT_MIC_SUBCARDIOID 1 +#define ACPI_NHLT_MIC_CARDIOID 2 +#define ACPI_NHLT_MIC_SUPER_CARDIOID 3 +#define ACPI_NHLT_MIC_HYPER_CARDIOID 4 +#define ACPI_NHLT_MIC_8_SHAPED 5 +#define ACPI_NHLT_MIC_RESERVED6 6 // 6 is reserved +#define ACPI_NHLT_MIC_VENDOR_DEFINED 7 +#define ACPI_NHLT_MIC_RESERVED 8 // 8 and above are reserved /* Values for Panel field above */ -#define MIC_TOP 0 -#define MIC_BOTTOM 1 -#define MIC_LEFT 2 -#define MIC_RIGHT 3 -#define MIC_FRONT 4 -#define MIC_REAR 5 +#define ACPI_NHLT_MIC_POSITION_TOP 0 +#define ACPI_NHLT_MIC_POSITION_BOTTOM 1 +#define ACPI_NHLT_MIC_POSITION_LEFT 2 +#define ACPI_NHLT_MIC_POSITION_RIGHT 3 +#define ACPI_NHLT_MIC_POSITION_FRONT 4 +#define ACPI_NHLT_MIC_POSITION_BACK 5 +#define ACPI_NHLT_MIC_POSITION_RESERVED 6 // 6 and above are reserved struct acpi_nhlt_vendor_mic_device_specific_config { struct acpi_nhlt_mic_device_specific_config mic_array_device_config; @@ -1633,8 +1644,9 @@ struct acpi_nhlt_mic_snr_sensitivity_extension { u32 sensitivity; }; +/* Render device with feedback */ + struct acpi_nhlt_render_feedback_device_specific_config { - struct acpi_nhlt_device_specific_config device_config; u8 feedback_virtual_slot; // render slot in case of capture u16 feedback_channels; // informative only u16 feedback_valid_bits_per_sample; -- cgit v1.2.3-70-g09d2 From 00395b74d57ff81795ec392627db7e1764c94941 Mon Sep 17 00:00:00 2001 From: Shuuichirou Ishii Date: Wed, 22 Dec 2021 17:28:34 +0100 Subject: ACPICA: Fix AEST Processor generic resource substructure data field byte length ACPICA commit 13b9327761955f6e1e5dbf748b3112940c0dc539 The byte length of the Data field in the AEST Processor generic resource substructure defined in ACPI for the Armv8 RAS Extensions 1.1 is 4Byte. However, it is defined as a pointer type, and on a 64-bit machine, it is interpreted as 8 bytes. Therefore, it is changed from a pointer type unsigned integer 1 byte to an unsigned integer 4 bytes. Link: https://github.com/acpica/acpica/commit/13b93277 Signed-off-by: Shuuichirou Ishii Signed-off-by: Bob Moore Signed-off-by: Rafael J. Wysocki --- include/acpi/actbl2.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/acpi') diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h index 380bff6bb2fd..1b0fac6ffc3f 100644 --- a/include/acpi/actbl2.h +++ b/include/acpi/actbl2.h @@ -154,7 +154,7 @@ typedef struct acpi_aest_processor_tlb { /* 2R: Processor Generic Resource Substructure */ typedef struct acpi_aest_processor_generic { - u8 *resource; + u32 resource; } acpi_aest_processor_generic; -- cgit v1.2.3-70-g09d2 From 0acf24ad7e10f547809faefb8069f8f5482eb4d9 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Wed, 22 Dec 2021 17:32:54 +0100 Subject: ACPICA: Add support for PCC Opregion special context data ACPICA commit 55526e8a6133cbf5a9cc0fb75a95dbbac6eb98e6 PCC Opregion added in ACPIC 6.3 requires special context data similar to GPIO and Generic Serial Bus as it needs to know the internal PCC buffer and its length as well as the PCC channel index when the opregion handler is being executed by the OSPM. Lets add support for the special context data needed by PCC Opregion. Link: https://github.com/acpica/acpica/commit/55526e8a Signed-off-by: Sudeep Holla Signed-off-by: Bob Moore Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/evregion.c | 10 ++++++++++ include/acpi/actypes.h | 8 ++++++++ 2 files changed, 18 insertions(+) (limited to 'include/acpi') diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c index 4ef43c8ef5e7..80b68f216b46 100644 --- a/drivers/acpi/acpica/evregion.c +++ b/drivers/acpi/acpica/evregion.c @@ -162,6 +162,16 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, return_ACPI_STATUS(AE_NOT_EXIST); } + if (region_obj->region.space_id == ACPI_ADR_SPACE_PLATFORM_COMM) { + struct acpi_pcc_info *ctx = + handler_desc->address_space.context; + + ctx->internal_buffer = + field_obj->field.internal_pcc_buffer; + ctx->length = region_obj->region.length; + ctx->subspace_id = 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/include/acpi/actypes.h b/include/acpi/actypes.h index 83a7ee1fbd7c..69e89d572b9e 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -1103,6 +1103,14 @@ struct acpi_connection_info { u8 access_length; }; +/* Special Context data for PCC Opregion (ACPI 6.3) */ + +struct acpi_pcc_info { + u8 subspace_id; + u16 length; + u8 *internal_buffer; +}; + typedef acpi_status (*acpi_adr_space_setup) (acpi_handle region_handle, u32 function, -- cgit v1.2.3-70-g09d2 From 2de6bb92ebbb0e8803554bb24391514b552cb481 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Wed, 22 Dec 2021 17:36:30 +0100 Subject: ACPICA: iASL: Add TDEL table to both compiler/disassembler ACPICA commit 403f9965aba7ff9d2ed5b41bbffdd2a1ed0f596f Added struct acpi_pcc_info to acpi_src. Link: https://github.com/acpica/acpica/commit/403f9965 Signed-off-by: Bob Moore Signed-off-by: Rafael J. Wysocki --- include/acpi/actbl2.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'include/acpi') diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h index 1b0fac6ffc3f..18b7b9138607 100644 --- a/include/acpi/actbl2.h +++ b/include/acpi/actbl2.h @@ -48,6 +48,7 @@ #define ACPI_SIG_SDEI "SDEI" /* Software Delegated Exception Interface Table */ #define ACPI_SIG_SDEV "SDEV" /* Secure Devices table */ #define ACPI_SIG_SVKL "SVKL" /* Storage Volume Key Location Table */ +#define ACPI_SIG_TDEL "TDEL" /* TD Event Log Table */ /* * All tables must be byte-packed to match the ACPI specification, since @@ -2467,6 +2468,22 @@ enum acpi_svkl_format { ACPI_SVKL_FORMAT_RESERVED = 1 /* 1 and greater are reserved */ }; +/******************************************************************************* + * + * TDEL - TD-Event Log + * From: "Guest-Host-Communication Interface (GHCI) for Intel + * Trust Domain Extensions (Intel TDX)". + * September 2020 + * + ******************************************************************************/ + +struct acpi_table_tdel { + struct acpi_table_header header; /* Common ACPI table header */ + u32 reserved; + u64 log_area_minimum_length; + u64 log_area_start_address; +}; + /* Reset to default packing */ #pragma pack() -- cgit v1.2.3-70-g09d2 From 5579649e7eb756a4e3d5784b6958374e5bfc41de Mon Sep 17 00:00:00 2001 From: Ilkka Koskinen Date: Wed, 22 Dec 2021 17:37:21 +0100 Subject: ACPICA: iASL: Add suppport for AGDI table ACPICA commit cf36a6d658ca5aa8c329c2edfc3322c095ffd844 Add support for Arm Generic Diagnostic Dump and Reset Interface, which is described by "ACPI for Arm Components 1.1 Platform Design Document" ARM DEN0093. Add the necessary types in the ACPICA header files and support for compiling and decompiling the table. Link: https://github.com/acpica/acpica/commit/cf36a6d6 Signed-off-by: Ilkka Koskinen Signed-off-by: Bob Moore Signed-off-by: Rafael J. Wysocki --- include/acpi/actbl2.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'include/acpi') diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h index 18b7b9138607..57481f6f1ca5 100644 --- a/include/acpi/actbl2.h +++ b/include/acpi/actbl2.h @@ -24,6 +24,7 @@ * file. Useful because they make it more difficult to inadvertently type in * the wrong signature. */ +#define ACPI_SIG_AGDI "AGDI" /* Arm Generic Diagnostic Dump and Reset Device Interface */ #define ACPI_SIG_BDAT "BDAT" /* BIOS Data ACPI Table */ #define ACPI_SIG_IORT "IORT" /* IO Remapping Table */ #define ACPI_SIG_IVRS "IVRS" /* I/O Virtualization Reporting Structure */ @@ -238,6 +239,25 @@ typedef struct acpi_aest_node_interrupt { #define ACPI_AEST_NODE_ERROR_RECOVERY 1 #define ACPI_AEST_XRUPT_RESERVED 2 /* 2 and above are reserved */ +/******************************************************************************* + * AGDI - Arm Generic Diagnostic Dump and Reset Device Interface + * + * Conforms to "ACPI for Arm Components 1.1, Platform Design Document" + * ARM DEN0093 v1.1 + * + ******************************************************************************/ +struct acpi_table_agdi { + struct acpi_table_header header; /* Common ACPI table header */ + u8 flags; + u8 reserved[3]; + u32 sdei_event; + u32 gsiv; +}; + +/* Mask for Flags field above */ + +#define ACPI_AGDI_SIGNALING_MODE (1) + /******************************************************************************* * * BDAT - BIOS Data ACPI Table -- cgit v1.2.3-70-g09d2 From 0c9a672729d62d27d0c9993e106707be0b0c2bc0 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Wed, 22 Dec 2021 17:37:56 +0100 Subject: ACPICA: iASL/NHLT table: "Specific Data" field support ACPICA commit 26f8c721fb01e4a26eec8c85dffcbe950d5e61a9 Add support for optional "Specific Data" field for the optional Linux-specific structure that appears at the end of an Endpoint Descriptor. Link: https://github.com/acpica/acpica/commit/26f8c721 Signed-off-by: Bob Moore Signed-off-by: Rafael J. Wysocki --- include/acpi/actbl2.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'include/acpi') diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h index 57481f6f1ca5..16847c8d9d5f 100644 --- a/include/acpi/actbl2.h +++ b/include/acpi/actbl2.h @@ -1683,7 +1683,10 @@ struct acpi_nhlt_linux_specific_data { u8 device_id[16]; u8 device_instance_id; u8 device_port_id; - u8 filler[18]; +}; + +struct acpi_nhlt_linux_specific_data_b { + u8 specific_data[18]; }; struct acpi_nhlt_table_terminator { -- cgit v1.2.3-70-g09d2 From c95545a036705e1a78b40a83701c8d3868898114 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Wed, 22 Dec 2021 17:38:29 +0100 Subject: ACPICA: Update version to 20211217 ACPICA commit 90088defcb99e122edf41038ae5c901206c86dc9 Version 20211217. Link: https://github.com/acpica/acpica/commit/90088def Signed-off-by: Bob Moore Signed-off-by: Rafael J. Wysocki --- include/acpi/acpixf.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/acpi') diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index 987bb0aa042e..7417731472b7 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -12,7 +12,7 @@ /* Current ACPICA subsystem version in YYYYMMDD format */ -#define ACPI_CA_VERSION 0x20210930 +#define ACPI_CA_VERSION 0x20211217 #include #include -- cgit v1.2.3-70-g09d2 From 35f9e773bb883a1be87410570f92c8c438e0478b Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 30 Dec 2021 15:17:20 +0100 Subject: ACPI / x86: Add acpi_quirk_skip_[i2c_client|serdev]_enumeration() helpers x86 ACPI boards which ship with only Android as their factory image usually declare a whole bunch of bogus I2C devs in their ACPI tables and sometimes there are issues with serdev devices on these boards too, e.g. the resource points to the wrong serdev_controller. Instantiating I2C / serdev devs for these bogus devs causes various issues, e.g. GPIO/IRQ resource conflicts because sometimes drivers do bind to them. The Android x86 kernel fork shipped on these devices has some special code to remove the bogus I2C clients (and serdevs are ignored completely). Introduce acpi_quirk_skip_i2c_client_enumeration() and acpi_quirk_skip_serdev_enumeration() helpers. Which can be used by the I2C/ serdev code to skip instantiating any I2C or serdev devs on broken boards. These 2 helpers are added to drivers/acpi/x86/utils.c so that the DMI table can be shared between the I2C and serdev code. Note these boards typically do actually have I2C and serdev devices, just different ones then the ones described in their DSDT. The devices which are actually present are manually instantiated by the drivers/platform/x86/x86-android-tablets.c kernel module. The new helpers are only build if CONFIG_X86_ANDROID_TABLETS is enabled, otherwise they are empty stubs to not unnecessarily grow the kernel size. Signed-off-by: Hans de Goede Signed-off-by: Rafael J. Wysocki --- drivers/acpi/x86/utils.c | 111 +++++++++++++++++++++++++++++++++++++++++++++++ include/acpi/acpi_bus.h | 16 +++++++ 2 files changed, 127 insertions(+) (limited to 'include/acpi') diff --git a/drivers/acpi/x86/utils.c b/drivers/acpi/x86/utils.c index f22f23933063..ef9ee8bbe4e6 100644 --- a/drivers/acpi/x86/utils.c +++ b/drivers/acpi/x86/utils.c @@ -10,6 +10,7 @@ #include #include +#include #include #include #include "../internal.h" @@ -160,3 +161,113 @@ bool force_storage_d3(void) { return x86_match_cpu(storage_d3_cpu_ids); } + +#if IS_ENABLED(CONFIG_X86_ANDROID_TABLETS) +/* + * x86 ACPI boards which ship with only Android as their factory image usually + * declare a whole bunch of bogus I2C devices in their ACPI tables and sometimes + * there are issues with serdev devices on these boards too, e.g. the resource + * points to the wrong serdev_controller. + * + * Instantiating I2C / serdev devs for these bogus devs causes various issues, + * e.g. GPIO/IRQ resource conflicts because sometimes drivers do bind to them. + * The Android x86 kernel fork shipped on these devices has some special code + * to remove the bogus I2C clients (and AFAICT serdevs are ignored completely). + * + * The acpi_quirk_skip_*_enumeration() functions below are used by the I2C or + * serdev code to skip instantiating any I2C or serdev devs on broken boards. + * + * In case of I2C an exception is made for HIDs on the i2c_acpi_known_good_ids + * list. These are known to always be correct (and in case of the audio-codecs + * the drivers heavily rely on the codec being enumerated through ACPI). + * + * Note these boards typically do actually have I2C and serdev devices, + * just different ones then the ones described in their DSDT. The devices + * which are actually present are manually instantiated by the + * drivers/platform/x86/x86-android-tablets.c kernel module. + */ +#define ACPI_QUIRK_SKIP_I2C_CLIENTS BIT(0) +#define ACPI_QUIRK_UART1_TTY_UART2_SKIP BIT(1) + +static const struct dmi_system_id acpi_skip_serial_bus_enumeration_ids[] = { + { + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ME176C"), + }, + .driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS | + ACPI_QUIRK_UART1_TTY_UART2_SKIP), + }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "TF103C"), + }, + .driver_data = (void *)ACPI_QUIRK_SKIP_I2C_CLIENTS, + }, + { + /* Whitelabel (sold as various brands) TM800A550L */ + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), + DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"), + /* Above strings are too generic, also match on BIOS version */ + DMI_MATCH(DMI_BIOS_VERSION, "ZY-8-BI-PX4S70VTR400-X423B-005-D"), + }, + .driver_data = (void *)ACPI_QUIRK_SKIP_I2C_CLIENTS, + }, + {} +}; + +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 */ + { "NPCE69A", 0 }, /* Asus Transformer keyboard dock */ + {} +}; + +bool acpi_quirk_skip_i2c_client_enumeration(struct acpi_device *adev) +{ + const struct dmi_system_id *dmi_id; + long quirks; + + dmi_id = dmi_first_match(acpi_skip_serial_bus_enumeration_ids); + if (!dmi_id) + return false; + + quirks = (unsigned long)dmi_id->driver_data; + if (!(quirks & ACPI_QUIRK_SKIP_I2C_CLIENTS)) + return false; + + return acpi_match_device_ids(adev, i2c_acpi_known_good_ids); +} +EXPORT_SYMBOL_GPL(acpi_quirk_skip_i2c_client_enumeration); + +int acpi_quirk_skip_serdev_enumeration(struct device *controller_parent, bool *skip) +{ + struct acpi_device *adev = ACPI_COMPANION(controller_parent); + const struct dmi_system_id *dmi_id; + long quirks = 0; + + *skip = false; + + /* !dev_is_platform() to not match on PNP enumerated debug UARTs */ + if (!adev || !adev->pnp.unique_id || !dev_is_platform(controller_parent)) + return 0; + + dmi_id = dmi_first_match(acpi_skip_serial_bus_enumeration_ids); + if (dmi_id) + quirks = (unsigned long)dmi_id->driver_data; + + if (quirks & ACPI_QUIRK_UART1_TTY_UART2_SKIP) { + if (!strcmp(adev->pnp.unique_id, "1")) + return -ENODEV; /* Create tty cdev instead of serdev */ + + if (!strcmp(adev->pnp.unique_id, "2")) + *skip = true; + } + + return 0; +} +EXPORT_SYMBOL_GPL(acpi_quirk_skip_serdev_enumeration); +#endif diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 17f700c9a4f9..88f21780447b 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -622,6 +622,22 @@ static inline bool acpi_device_always_present(struct acpi_device *adev) } #endif +#if IS_ENABLED(CONFIG_X86_ANDROID_TABLETS) +bool acpi_quirk_skip_i2c_client_enumeration(struct acpi_device *adev); +int acpi_quirk_skip_serdev_enumeration(struct device *controller_parent, bool *skip); +#else +static inline bool acpi_quirk_skip_i2c_client_enumeration(struct acpi_device *adev) +{ + return false; +} +static inline int +acpi_quirk_skip_serdev_enumeration(struct device *controller_parent, bool *skip) +{ + *skip = false; + return 0; +} +#endif + #ifdef CONFIG_PM void acpi_pm_wakeup_event(struct device *dev); acpi_status acpi_add_pm_notifier(struct acpi_device *adev, struct device *dev, -- cgit v1.2.3-70-g09d2 From 57a18322227134e37b693ef8ef216ed7ce7ba7d6 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 30 Dec 2021 20:31:19 +0100 Subject: ACPI / x86: Introduce an acpi_quirk_skip_acpi_ac_and_battery() helper Some x86 ACPI boards have broken AC and battery ACPI devices in their ACPI tables. This is often tied to these devices using certain PMICs where the factory OS image seems to be using native charger and fuel-gauge drivers instead. So far both the AC and battery drivers have almost identical checks for these PMICs including both of them having a DMI based mechanism to force usage of the ACPI AC and battery drivers on some boards even though one of these PMICs is present, with the same 2 boards listed in both driver's DMI tables for this. The only difference is that the AC driver checks for 2 PMICs and the battery driver only for one. This has grown this way because the other (Whiskey Cove) PMIC is only used on a few boards (3 known boards) and although some of these do have non working ACPI battery devices, their _STA method always returns 0, but that really should not be relied on. This patch factors out the shared checks into a new acpi_quirk_skip_acpi_ac_and_battery() helper and moves the AC and battery drivers over to this new helper. Note the DMI table is shared with acpi_quirk_skip_i2c_client_enumeration() and acpi_quirk_skip_serdev_enumeration(), because boards needing DMI quirks for either of these typically also have broken AC and battery ACPI devices. The ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY quirk is not set yet on boards already in this DMI table, to avoid introducing any functional changes in this refactoring patch. Besided sharing the code between the AC and battery drivers this refactoring also moves this quirk handling to under #ifdef CONFIG_X86, removing this x86 specific code from non x86 ACPI builds. Signed-off-by: Hans de Goede Signed-off-by: Rafael J. Wysocki --- drivers/acpi/ac.c | 43 ++------------------------- drivers/acpi/battery.c | 42 ++------------------------ drivers/acpi/x86/utils.c | 77 +++++++++++++++++++++++++++++++++++++++++++++--- include/acpi/acpi_bus.h | 5 ++++ 4 files changed, 84 insertions(+), 83 deletions(-) (limited to 'include/acpi') diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index 81aff651a0d4..db487ff9dd1b 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c @@ -48,19 +48,12 @@ static const struct acpi_device_id ac_device_ids[] = { }; MODULE_DEVICE_TABLE(acpi, ac_device_ids); -/* Lists of PMIC ACPI HIDs with an (often better) native charger driver */ -static const struct acpi_ac_bl acpi_ac_blacklist[] = { - { "INT33F4", -1 }, /* X-Powers AXP288 PMIC */ - { "INT34D3", 3 }, /* Intel Cherrytrail Whiskey Cove PMIC */ -}; - #ifdef CONFIG_PM_SLEEP static int acpi_ac_resume(struct device *dev); #endif static SIMPLE_DEV_PM_OPS(acpi_ac_pm, NULL, acpi_ac_resume); static int ac_sleep_before_get_state_ms; -static int ac_check_pmic = 1; static int ac_only; static struct acpi_driver acpi_ac_driver = { @@ -200,12 +193,6 @@ static int __init thinkpad_e530_quirk(const struct dmi_system_id *d) return 0; } -static int __init ac_do_not_check_pmic_quirk(const struct dmi_system_id *d) -{ - ac_check_pmic = 0; - return 0; -} - static int __init ac_only_quirk(const struct dmi_system_id *d) { ac_only = 1; @@ -214,13 +201,6 @@ static int __init ac_only_quirk(const struct dmi_system_id *d) /* Please keep this list alphabetically sorted */ static const struct dmi_system_id ac_dmi_table[] __initconst = { - { - /* ECS EF20EA, AXP288 PMIC but uses separate fuel-gauge */ - .callback = ac_do_not_check_pmic_quirk, - .matches = { - DMI_MATCH(DMI_PRODUCT_NAME, "EF20EA"), - }, - }, { /* Kodlix GK45 returning incorrect state */ .callback = ac_only_quirk, @@ -228,15 +208,6 @@ static const struct dmi_system_id ac_dmi_table[] __initconst = { DMI_MATCH(DMI_PRODUCT_NAME, "GK45"), }, }, - { - /* Lenovo Ideapad Miix 320, AXP288 PMIC, separate fuel-gauge */ - .callback = ac_do_not_check_pmic_quirk, - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_NAME, "80XF"), - DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo MIIX 320-10ICR"), - }, - }, { /* Lenovo Thinkpad e530, see comment in acpi_ac_notify() */ .callback = thinkpad_e530_quirk, @@ -341,23 +312,15 @@ static int acpi_ac_remove(struct acpi_device *device) static int __init acpi_ac_init(void) { - unsigned int i; int result; if (acpi_disabled) return -ENODEV; - dmi_check_system(ac_dmi_table); + if (acpi_quirk_skip_acpi_ac_and_battery()) + return -ENODEV; - if (ac_check_pmic) { - for (i = 0; i < ARRAY_SIZE(acpi_ac_blacklist); i++) - if (acpi_dev_present(acpi_ac_blacklist[i].hid, "1", - acpi_ac_blacklist[i].hrv)) { - pr_info("found native %s PMIC, not loading\n", - acpi_ac_blacklist[i].hid); - return -ENODEV; - } - } + dmi_check_system(ac_dmi_table); result = acpi_bus_register_driver(&acpi_ac_driver); if (result < 0) diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 8afa85d6eb6a..bf4b7f0b627a 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -52,7 +52,6 @@ static bool battery_driver_registered; static int battery_bix_broken_package; static int battery_notification_delay_ms; static int battery_ac_is_broken; -static int battery_check_pmic = 1; static unsigned int cache_time = 1000; module_param(cache_time, uint, 0644); MODULE_PARM_DESC(cache_time, "cache time in milliseconds"); @@ -64,11 +63,6 @@ static const struct acpi_device_id battery_device_ids[] = { MODULE_DEVICE_TABLE(acpi, battery_device_ids); -/* Lists of PMIC ACPI HIDs with an (often better) native battery driver */ -static const char * const acpi_battery_blacklist[] = { - "INT33F4", /* X-Powers AXP288 PMIC */ -}; - enum { ACPI_BATTERY_ALARM_PRESENT, ACPI_BATTERY_XINFO_PRESENT, @@ -1104,13 +1098,6 @@ battery_ac_is_broken_quirk(const struct dmi_system_id *d) return 0; } -static int __init -battery_do_not_check_pmic_quirk(const struct dmi_system_id *d) -{ - battery_check_pmic = 0; - return 0; -} - static const struct dmi_system_id bat_dmi_table[] __initconst = { { /* NEC LZ750/LS */ @@ -1139,22 +1126,6 @@ static const struct dmi_system_id bat_dmi_table[] __initconst = { DMI_MATCH(DMI_BIOS_DATE, "08/22/2014"), }, }, - { - /* ECS EF20EA, AXP288 PMIC but uses separate fuel-gauge */ - .callback = battery_do_not_check_pmic_quirk, - .matches = { - DMI_MATCH(DMI_PRODUCT_NAME, "EF20EA"), - }, - }, - { - /* Lenovo Ideapad Miix 320, AXP288 PMIC, separate fuel-gauge */ - .callback = battery_do_not_check_pmic_quirk, - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_NAME, "80XF"), - DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo MIIX 320-10ICR"), - }, - }, {}, }; @@ -1279,19 +1250,12 @@ static struct acpi_driver acpi_battery_driver = { static void __init acpi_battery_init_async(void *unused, async_cookie_t cookie) { - unsigned int i; int result; - dmi_check_system(bat_dmi_table); + if (acpi_quirk_skip_acpi_ac_and_battery()) + return; - if (battery_check_pmic) { - for (i = 0; i < ARRAY_SIZE(acpi_battery_blacklist); i++) - if (acpi_dev_present(acpi_battery_blacklist[i], "1", -1)) { - pr_info("found native %s PMIC, not loading\n", - acpi_battery_blacklist[i]); - return; - } - } + dmi_check_system(bat_dmi_table); result = acpi_bus_register_driver(&acpi_battery_driver); battery_driver_registered = (result == 0); diff --git a/drivers/acpi/x86/utils.c b/drivers/acpi/x86/utils.c index 375a0911f06d..5411f2f1254e 100644 --- a/drivers/acpi/x86/utils.c +++ b/drivers/acpi/x86/utils.c @@ -8,6 +8,8 @@ * Copyright (C) 2013-2015 Intel Corporation. All rights reserved. */ +#define pr_fmt(fmt) "ACPI: " fmt + #include #include #include @@ -210,7 +212,6 @@ bool force_storage_d3(void) return x86_match_cpu(storage_d3_cpu_ids); } -#if IS_ENABLED(CONFIG_X86_ANDROID_TABLETS) /* * x86 ACPI boards which ship with only Android as their factory image usually * declare a whole bunch of bogus I2C devices in their ACPI tables and sometimes @@ -236,8 +237,36 @@ bool force_storage_d3(void) */ #define ACPI_QUIRK_SKIP_I2C_CLIENTS BIT(0) #define ACPI_QUIRK_UART1_TTY_UART2_SKIP BIT(1) +#define ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY BIT(2) +#define ACPI_QUIRK_USE_ACPI_AC_AND_BATTERY BIT(3) + +static const struct dmi_system_id acpi_quirk_skip_dmi_ids[] = { + /* + * 1. Devices with only the skip / don't-skip AC and battery quirks, + * sorted alphabetically. + */ + { + /* ECS EF20EA, AXP288 PMIC but uses separate fuel-gauge */ + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "EF20EA"), + }, + .driver_data = (void *)ACPI_QUIRK_USE_ACPI_AC_AND_BATTERY + }, + { + /* Lenovo Ideapad Miix 320, AXP288 PMIC, separate fuel-gauge */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "80XF"), + DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo MIIX 320-10ICR"), + }, + .driver_data = (void *)ACPI_QUIRK_USE_ACPI_AC_AND_BATTERY + }, -static const struct dmi_system_id acpi_skip_serial_bus_enumeration_ids[] = { + /* + * 2. Devices which also have the skip i2c/serdev quirks and which + * need the x86-android-tablets module to properly work. + */ +#if IS_ENABLED(CONFIG_X86_ANDROID_TABLETS) { .matches = { DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), @@ -263,9 +292,11 @@ static const struct dmi_system_id acpi_skip_serial_bus_enumeration_ids[] = { }, .driver_data = (void *)ACPI_QUIRK_SKIP_I2C_CLIENTS, }, +#endif {} }; +#if IS_ENABLED(CONFIG_X86_ANDROID_TABLETS) static const struct acpi_device_id i2c_acpi_known_good_ids[] = { { "10EC5640", 0 }, /* RealTek ALC5640 audio codec */ { "INT33F4", 0 }, /* X-Powers AXP288 PMIC */ @@ -279,7 +310,7 @@ bool acpi_quirk_skip_i2c_client_enumeration(struct acpi_device *adev) const struct dmi_system_id *dmi_id; long quirks; - dmi_id = dmi_first_match(acpi_skip_serial_bus_enumeration_ids); + dmi_id = dmi_first_match(acpi_quirk_skip_dmi_ids); if (!dmi_id) return false; @@ -303,7 +334,7 @@ int acpi_quirk_skip_serdev_enumeration(struct device *controller_parent, bool *s if (!adev || !adev->pnp.unique_id || !dev_is_platform(controller_parent)) return 0; - dmi_id = dmi_first_match(acpi_skip_serial_bus_enumeration_ids); + dmi_id = dmi_first_match(acpi_quirk_skip_dmi_ids); if (dmi_id) quirks = (unsigned long)dmi_id->driver_data; @@ -319,3 +350,41 @@ int acpi_quirk_skip_serdev_enumeration(struct device *controller_parent, bool *s } EXPORT_SYMBOL_GPL(acpi_quirk_skip_serdev_enumeration); #endif + +/* Lists of PMIC ACPI HIDs with an (often better) native charger driver */ +static const struct { + const char *hid; + int hrv; +} acpi_skip_ac_and_battery_pmic_ids[] = { + { "INT33F4", -1 }, /* X-Powers AXP288 PMIC */ + { "INT34D3", 3 }, /* Intel Cherrytrail Whiskey Cove PMIC */ +}; + +bool acpi_quirk_skip_acpi_ac_and_battery(void) +{ + const struct dmi_system_id *dmi_id; + long quirks = 0; + int i; + + dmi_id = dmi_first_match(acpi_quirk_skip_dmi_ids); + if (dmi_id) + quirks = (unsigned long)dmi_id->driver_data; + + if (quirks & ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY) + return true; + + if (quirks & ACPI_QUIRK_USE_ACPI_AC_AND_BATTERY) + return false; + + for (i = 0; i < ARRAY_SIZE(acpi_skip_ac_and_battery_pmic_ids); i++) { + if (acpi_dev_present(acpi_skip_ac_and_battery_pmic_ids[i].hid, "1", + acpi_skip_ac_and_battery_pmic_ids[i].hrv)) { + pr_info_once("found native %s PMIC, skipping ACPI AC and battery devices\n", + acpi_skip_ac_and_battery_pmic_ids[i].hid); + return true; + } + } + + return false; +} +EXPORT_SYMBOL_GPL(acpi_quirk_skip_acpi_ac_and_battery); diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 80c425bc98a7..04b9ace9689b 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -615,12 +615,17 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev); #ifdef CONFIG_X86 bool acpi_device_override_status(struct acpi_device *adev, unsigned long long *status); +bool acpi_quirk_skip_acpi_ac_and_battery(void); #else static inline bool acpi_device_override_status(struct acpi_device *adev, unsigned long long *status) { return false; } +static inline bool acpi_quirk_skip_acpi_ac_and_battery(void) +{ + return false; +} #endif #if IS_ENABLED(CONFIG_X86_ANDROID_TABLETS) -- cgit v1.2.3-70-g09d2