diff options
Diffstat (limited to 'drivers/acpi')
30 files changed, 593 insertions, 187 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index ff1689bb3124..e3a7c2aedd5f 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -469,6 +469,9 @@ config ACPI_REDUCED_HARDWARE_ONLY If you are unsure what to do, do not enable this option. +config ACPI_NHLT + bool + source "drivers/acpi/nfit/Kconfig" source "drivers/acpi/numa/Kconfig" source "drivers/acpi/apei/Kconfig" diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 8cc8c0d9c873..39ea5cfa8326 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -14,7 +14,6 @@ tables.o: $(src)/../../include/$(CONFIG_ACPI_CUSTOM_DSDT_FILE) ; endif obj-$(CONFIG_ACPI) += tables.o -obj-$(CONFIG_X86) += blacklist.o # # ACPI Core Subsystem (Interpreter) @@ -46,7 +45,6 @@ acpi-y += ec.o acpi-$(CONFIG_ACPI_DOCK) += dock.o acpi-$(CONFIG_PCI) += pci_root.o pci_link.o pci_irq.o obj-$(CONFIG_ACPI_MCFG) += pci_mcfg.o -acpi-$(CONFIG_PCI) += acpi_lpss.o acpi-y += acpi_apd.o acpi-y += acpi_platform.o acpi-y += acpi_pnp.o @@ -55,10 +53,6 @@ acpi-y += event.o acpi-y += evged.o acpi-y += sysfs.o acpi-y += property.o -acpi-$(CONFIG_X86) += acpi_cmos_rtc.o -acpi-$(CONFIG_X86) += x86/apple.o -acpi-$(CONFIG_X86) += x86/utils.o -acpi-$(CONFIG_X86) += x86/s2idle.o acpi-$(CONFIG_DEBUG_FS) += debugfs.o acpi-y += acpi_lpat.o acpi-$(CONFIG_ACPI_FPDT) += acpi_fpdt.o @@ -93,6 +87,7 @@ obj-$(CONFIG_ACPI_THERMAL_LIB) += thermal_lib.o obj-$(CONFIG_ACPI_THERMAL) += thermal.o obj-$(CONFIG_ACPI_PLATFORM_PROFILE) += platform_profile.o obj-$(CONFIG_ACPI_NFIT) += nfit/ +obj-$(CONFIG_ACPI_NHLT) += nhlt.o obj-$(CONFIG_ACPI_NUMA) += numa/ obj-$(CONFIG_ACPI) += acpi_memhotplug.o obj-$(CONFIG_ACPI_HOTPLUG_IOAPIC) += ioapic.o @@ -132,3 +127,4 @@ obj-$(CONFIG_ARM64) += arm64/ obj-$(CONFIG_ACPI_VIOT) += viot.o obj-$(CONFIG_RISCV) += riscv/ +obj-$(CONFIG_X86) += x86/ diff --git a/drivers/acpi/acpi_ipmi.c b/drivers/acpi/acpi_ipmi.c index 0555f68c2dfd..5fba4dab5d08 100644 --- a/drivers/acpi/acpi_ipmi.c +++ b/drivers/acpi/acpi_ipmi.c @@ -22,6 +22,8 @@ MODULE_LICENSE("GPL"); /* the IPMI timeout is 5s */ #define IPMI_TIMEOUT (5000) #define ACPI_IPMI_MAX_MSG_LENGTH 64 +/* 2s should be suffient for SMI being selected */ +#define ACPI_IPMI_SMI_SELECTION_TIMEOUT (2 * HZ) struct acpi_ipmi_device { /* the device list attached to driver_data.ipmi_devices */ @@ -54,6 +56,7 @@ struct ipmi_driver_data { * to this selected global IPMI system interface. */ struct acpi_ipmi_device *selected_smi; + struct completion smi_selection_done; }; struct acpi_ipmi_msg { @@ -463,8 +466,10 @@ static void ipmi_register_bmc(int iface, struct device *dev) if (temp->handle == handle) goto err_lock; } - if (!driver_data.selected_smi) + if (!driver_data.selected_smi) { driver_data.selected_smi = ipmi_device; + complete(&driver_data.smi_selection_done); + } list_add_tail(&ipmi_device->head, &driver_data.ipmi_devices); mutex_unlock(&driver_data.ipmi_lock); @@ -578,6 +583,20 @@ out_msg: return status; } +int acpi_wait_for_acpi_ipmi(void) +{ + long ret; + + ret = wait_for_completion_interruptible_timeout(&driver_data.smi_selection_done, + ACPI_IPMI_SMI_SELECTION_TIMEOUT); + + if (ret <= 0) + return -ETIMEDOUT; + + return 0; +} +EXPORT_SYMBOL_GPL(acpi_wait_for_acpi_ipmi); + static int __init acpi_ipmi_init(void) { int result; @@ -586,6 +605,8 @@ static int __init acpi_ipmi_init(void) if (acpi_disabled) return 0; + init_completion(&driver_data.smi_selection_done); + status = acpi_install_address_space_handler(ACPI_ROOT_OBJECT, ACPI_ADR_SPACE_IPMI, &acpi_ipmi_space_handler, diff --git a/drivers/acpi/acpica/Makefile b/drivers/acpi/acpica/Makefile index 30f3fc13c29d..8d18af396de9 100644 --- a/drivers/acpi/acpica/Makefile +++ b/drivers/acpi/acpica/Makefile @@ -5,6 +5,7 @@ ccflags-y := -D_LINUX -DBUILDING_ACPICA ccflags-$(CONFIG_ACPI_DEBUG) += -DACPI_DEBUG_OUTPUT +CFLAGS_tbfind.o += $(call cc-disable-warning, stringop-truncation) # use acpi.o to put all files here into acpi.o modparam namespace obj-y += acpi.o diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index 82563b44af35..02012168a087 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h @@ -547,7 +547,7 @@ struct acpi_field_info { struct acpi_ged_handler_info { struct acpi_ged_handler_info *next; - u32 int_id; /* The interrupt ID that triggers the execution ofthe evt_method. */ + u32 int_id; /* The interrupt ID that triggers the execution of the evt_method. */ struct acpi_namespace_node *evt_method; /* The _EVT method to be executed when an interrupt with ID = int_ID is received */ }; diff --git a/drivers/acpi/acpica/acobject.h b/drivers/acpi/acpica/acobject.h index 1bdfeee5d7c5..8fc02946d3cd 100644 --- a/drivers/acpi/acpica/acobject.h +++ b/drivers/acpi/acpica/acobject.h @@ -48,7 +48,7 @@ u8 descriptor_type; /* To differentiate various internal objs */\ u8 type; /* acpi_object_type */\ u16 reference_count; /* For object deletion management */\ - u8 flags; + u8 flags /* * Note: There are 3 bytes available here before the * next natural alignment boundary (for both 32/64 cases) @@ -71,10 +71,12 @@ *****************************************************************************/ struct acpi_object_common { -ACPI_OBJECT_COMMON_HEADER}; + ACPI_OBJECT_COMMON_HEADER; +}; struct acpi_object_integer { - ACPI_OBJECT_COMMON_HEADER u8 fill[3]; /* Prevent warning on some compilers */ + ACPI_OBJECT_COMMON_HEADER; + u8 fill[3]; /* Prevent warning on some compilers */ u64 value; }; @@ -86,23 +88,26 @@ struct acpi_object_integer { */ #define ACPI_COMMON_BUFFER_INFO(_type) \ _type *pointer; \ - u32 length; + u32 length /* Null terminated, ASCII characters only */ struct acpi_object_string { - ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_BUFFER_INFO(char) /* String in AML stream or allocated string */ + ACPI_OBJECT_COMMON_HEADER; + ACPI_COMMON_BUFFER_INFO(char); /* String in AML stream or allocated string */ }; struct acpi_object_buffer { - ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_BUFFER_INFO(u8) /* Buffer in AML stream or allocated buffer */ + ACPI_OBJECT_COMMON_HEADER; + ACPI_COMMON_BUFFER_INFO(u8); /* Buffer in AML stream or allocated buffer */ u32 aml_length; u8 *aml_start; struct acpi_namespace_node *node; /* Link back to parent node */ }; struct acpi_object_package { - ACPI_OBJECT_COMMON_HEADER struct acpi_namespace_node *node; /* Link back to parent node */ + ACPI_OBJECT_COMMON_HEADER; + struct acpi_namespace_node *node; /* Link back to parent node */ union acpi_operand_object **elements; /* Array of pointers to acpi_objects */ u8 *aml_start; u32 aml_length; @@ -116,11 +121,13 @@ struct acpi_object_package { *****************************************************************************/ struct acpi_object_event { - ACPI_OBJECT_COMMON_HEADER acpi_semaphore os_semaphore; /* Actual OS synchronization object */ + ACPI_OBJECT_COMMON_HEADER; + acpi_semaphore os_semaphore; /* Actual OS synchronization object */ }; struct acpi_object_mutex { - ACPI_OBJECT_COMMON_HEADER u8 sync_level; /* 0-15, specified in Mutex() call */ + ACPI_OBJECT_COMMON_HEADER; + u8 sync_level; /* 0-15, specified in Mutex() call */ u16 acquisition_depth; /* Allow multiple Acquires, same thread */ acpi_mutex os_mutex; /* Actual OS synchronization object */ acpi_thread_id thread_id; /* Current owner of the mutex */ @@ -132,7 +139,8 @@ struct acpi_object_mutex { }; struct acpi_object_region { - ACPI_OBJECT_COMMON_HEADER u8 space_id; + ACPI_OBJECT_COMMON_HEADER; + u8 space_id; struct acpi_namespace_node *node; /* Containing namespace node */ union acpi_operand_object *handler; /* Handler for region access */ union acpi_operand_object *next; @@ -142,7 +150,8 @@ struct acpi_object_region { }; struct acpi_object_method { - ACPI_OBJECT_COMMON_HEADER u8 info_flags; + ACPI_OBJECT_COMMON_HEADER; + u8 info_flags; u8 param_count; u8 sync_level; union acpi_operand_object *mutex; @@ -178,33 +187,43 @@ struct acpi_object_method { */ #define ACPI_COMMON_NOTIFY_INFO \ union acpi_operand_object *notify_list[2]; /* Handlers for system/device notifies */\ - union acpi_operand_object *handler; /* Handler for Address space */ + union acpi_operand_object *handler /* Handler for Address space */ /* COMMON NOTIFY for POWER, PROCESSOR, DEVICE, and THERMAL */ struct acpi_object_notify_common { -ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_NOTIFY_INFO}; + ACPI_OBJECT_COMMON_HEADER; + ACPI_COMMON_NOTIFY_INFO; +}; struct acpi_object_device { - ACPI_OBJECT_COMMON_HEADER - ACPI_COMMON_NOTIFY_INFO struct acpi_gpe_block_info *gpe_block; + ACPI_OBJECT_COMMON_HEADER; + ACPI_COMMON_NOTIFY_INFO; + struct acpi_gpe_block_info *gpe_block; }; struct acpi_object_power_resource { - ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_NOTIFY_INFO u32 system_level; + ACPI_OBJECT_COMMON_HEADER; + ACPI_COMMON_NOTIFY_INFO; + u32 system_level; u32 resource_order; }; struct acpi_object_processor { - ACPI_OBJECT_COMMON_HEADER - /* The next two fields take advantage of the 3-byte space before NOTIFY_INFO */ + ACPI_OBJECT_COMMON_HEADER; + + /* The next two fields take advantage of the 3-byte space before NOTIFY_INFO */ + u8 proc_id; u8 length; - ACPI_COMMON_NOTIFY_INFO acpi_io_address address; + ACPI_COMMON_NOTIFY_INFO; + acpi_io_address address; }; struct acpi_object_thermal_zone { -ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_NOTIFY_INFO}; + ACPI_OBJECT_COMMON_HEADER; + ACPI_COMMON_NOTIFY_INFO; +}; /****************************************************************************** * @@ -226,17 +245,21 @@ ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_NOTIFY_INFO}; u32 base_byte_offset; /* Byte offset within containing object */\ u32 value; /* Value to store into the Bank or Index register */\ u8 start_field_bit_offset;/* Bit offset within first field datum (0-63) */\ - u8 access_length; /* For serial regions/fields */ + u8 access_length /* For serial regions/fields */ /* COMMON FIELD (for BUFFER, REGION, BANK, and INDEX fields) */ struct acpi_object_field_common { - ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO union acpi_operand_object *region_obj; /* Parent Operation Region object (REGION/BANK fields only) */ + ACPI_OBJECT_COMMON_HEADER; + ACPI_COMMON_FIELD_INFO; + union acpi_operand_object *region_obj; /* Parent Operation Region object (REGION/BANK fields only) */ }; struct acpi_object_region_field { - ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO u16 resource_length; + ACPI_OBJECT_COMMON_HEADER; + ACPI_COMMON_FIELD_INFO; + u16 resource_length; union acpi_operand_object *region_obj; /* Containing op_region object */ u8 *resource_buffer; /* resource_template for serial regions/fields */ u16 pin_number_index; /* Index relative to previous Connection/Template */ @@ -244,16 +267,20 @@ struct acpi_object_region_field { }; struct acpi_object_bank_field { - ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO union acpi_operand_object *region_obj; /* Containing op_region object */ + ACPI_OBJECT_COMMON_HEADER; + ACPI_COMMON_FIELD_INFO; + union acpi_operand_object *region_obj; /* Containing op_region object */ union acpi_operand_object *bank_obj; /* bank_select Register object */ }; struct acpi_object_index_field { - ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO - /* - * No "RegionObj" pointer needed since the Index and Data registers - * are each field definitions unto themselves. - */ + ACPI_OBJECT_COMMON_HEADER; + ACPI_COMMON_FIELD_INFO; + + /* + * No "RegionObj" pointer needed since the Index and Data registers + * are each field definitions unto themselves. + */ union acpi_operand_object *index_obj; /* Index register */ union acpi_operand_object *data_obj; /* Data register */ }; @@ -261,7 +288,9 @@ struct acpi_object_index_field { /* The buffer_field is different in that it is part of a Buffer, not an op_region */ struct acpi_object_buffer_field { - ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO u8 is_create_field; /* Special case for objects created by create_field() */ + ACPI_OBJECT_COMMON_HEADER; + ACPI_COMMON_FIELD_INFO; + u8 is_create_field; /* Special case for objects created by create_field() */ union acpi_operand_object *buffer_obj; /* Containing Buffer object */ }; @@ -272,7 +301,8 @@ struct acpi_object_buffer_field { *****************************************************************************/ struct acpi_object_notify_handler { - ACPI_OBJECT_COMMON_HEADER struct acpi_namespace_node *node; /* Parent device */ + ACPI_OBJECT_COMMON_HEADER; + struct acpi_namespace_node *node; /* Parent device */ u32 handler_type; /* Type: Device/System/Both */ acpi_notify_handler handler; /* Handler address */ void *context; @@ -280,7 +310,8 @@ struct acpi_object_notify_handler { }; struct acpi_object_addr_handler { - ACPI_OBJECT_COMMON_HEADER u8 space_id; + ACPI_OBJECT_COMMON_HEADER; + u8 space_id; u8 handler_flags; acpi_adr_space_handler handler; struct acpi_namespace_node *node; /* Parent device */ @@ -307,7 +338,8 @@ struct acpi_object_addr_handler { * The Reference.Class differentiates these types. */ struct acpi_object_reference { - ACPI_OBJECT_COMMON_HEADER u8 class; /* Reference Class */ + ACPI_OBJECT_COMMON_HEADER; + u8 class; /* Reference Class */ u8 target_type; /* Used for Index Op */ u8 resolved; /* Reference has been resolved to a value */ void *object; /* name_op=>HANDLE to obj, index_op=>union acpi_operand_object */ @@ -340,7 +372,8 @@ typedef enum { * Currently: Region and field_unit types */ struct acpi_object_extra { - ACPI_OBJECT_COMMON_HEADER struct acpi_namespace_node *method_REG; /* _REG method for this region (if any) */ + ACPI_OBJECT_COMMON_HEADER; + struct acpi_namespace_node *method_REG; /* _REG method for this region (if any) */ struct acpi_namespace_node *scope_node; void *region_context; /* Region-specific data */ u8 *aml_start; @@ -350,14 +383,16 @@ struct acpi_object_extra { /* Additional data that can be attached to namespace nodes */ struct acpi_object_data { - ACPI_OBJECT_COMMON_HEADER acpi_object_handler handler; + ACPI_OBJECT_COMMON_HEADER; + acpi_object_handler handler; void *pointer; }; /* Structure used when objects are cached for reuse */ struct acpi_object_cache_list { - ACPI_OBJECT_COMMON_HEADER union acpi_operand_object *next; /* Link for object cache and internal lists */ + ACPI_OBJECT_COMMON_HEADER; + union acpi_operand_object *next; /* Link for object cache and internal lists */ }; /****************************************************************************** diff --git a/drivers/acpi/acpica/evgpeinit.c b/drivers/acpi/acpica/evgpeinit.c index 0dbc4d88919a..38f408cf13ce 100644 --- a/drivers/acpi/acpica/evgpeinit.c +++ b/drivers/acpi/acpica/evgpeinit.c @@ -413,6 +413,7 @@ acpi_ev_match_gpe_method(acpi_handle obj_handle, gpe_event_info->flags &= ~(ACPI_GPE_DISPATCH_MASK); gpe_event_info->flags |= (u8)(type | ACPI_GPE_DISPATCH_METHOD); gpe_event_info->dispatch.method_node = method_node; + walk_info->count++; ACPI_DEBUG_PRINT((ACPI_DB_LOAD, "Registered GPE method %s as GPE number 0x%.2X\n", diff --git a/drivers/acpi/acpica/tbfadt.c b/drivers/acpi/acpica/tbfadt.c index 44267a92bce5..3c126c6d306b 100644 --- a/drivers/acpi/acpica/tbfadt.c +++ b/drivers/acpi/acpica/tbfadt.c @@ -315,23 +315,19 @@ void acpi_tb_parse_fadt(void) ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL, NULL, FALSE, TRUE, &acpi_gbl_dsdt_index); - /* If Hardware Reduced flag is set, there is no FACS */ - - if (!acpi_gbl_reduced_hardware) { - if (acpi_gbl_FADT.facs) { - acpi_tb_install_standard_table((acpi_physical_address) - acpi_gbl_FADT.facs, - ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL, - 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, - NULL, FALSE, TRUE, - &acpi_gbl_xfacs_index); - } + if (acpi_gbl_FADT.facs) { + acpi_tb_install_standard_table((acpi_physical_address) + acpi_gbl_FADT.facs, + ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL, + 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, + NULL, FALSE, TRUE, + &acpi_gbl_xfacs_index); } } diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c index bb4a56e5673a..15fa68a5ea6e 100644 --- a/drivers/acpi/acpica/tbutils.c +++ b/drivers/acpi/acpica/tbutils.c @@ -36,12 +36,7 @@ acpi_status acpi_tb_initialize_facs(void) { struct acpi_table_facs *facs; - /* If Hardware Reduced flag is set, there is no FACS */ - - if (acpi_gbl_reduced_hardware) { - acpi_gbl_FACS = NULL; - return (AE_OK); - } else if (acpi_gbl_FADT.Xfacs && + if (acpi_gbl_FADT.Xfacs && (!acpi_gbl_FADT.facs || !acpi_gbl_use32_bit_facs_addresses)) { (void)acpi_get_table_by_index(acpi_gbl_xfacs_index, diff --git a/drivers/acpi/acpica/utdebug.c b/drivers/acpi/acpica/utdebug.c index c5f6c85a3a09..3d71bd9245c7 100644 --- a/drivers/acpi/acpica/utdebug.c +++ b/drivers/acpi/acpica/utdebug.c @@ -62,7 +62,12 @@ void acpi_ut_track_stack_ptr(void) acpi_size current_sp; if (¤t_sp < acpi_gbl_lowest_stack_pointer) { +#pragma GCC diagnostic push +#if defined(__GNUC__) && __GNUC__ >= 12 +#pragma GCC diagnostic ignored "-Wdangling-pointer=" +#endif acpi_gbl_lowest_stack_pointer = ¤t_sp; +#pragma GCC diagnostic pop } if (acpi_gbl_nesting_level > acpi_gbl_deepest_nesting) { diff --git a/drivers/acpi/apei/einj-core.c b/drivers/acpi/apei/einj-core.c index 01faca3a238a..9515bcfe5e97 100644 --- a/drivers/acpi/apei/einj-core.c +++ b/drivers/acpi/apei/einj-core.c @@ -851,7 +851,7 @@ err_put_table: return rc; } -static void einj_remove(struct platform_device *pdev) +static void __exit einj_remove(struct platform_device *pdev) { struct apei_exec_context ctx; @@ -873,8 +873,14 @@ static void einj_remove(struct platform_device *pdev) } static struct platform_device *einj_dev; -static struct platform_driver einj_driver = { - .remove_new = einj_remove, +/* + * einj_remove() lives in .exit.text. For drivers registered via + * platform_driver_probe() this is ok because they cannot get unbound at + * runtime. So mark the driver struct with __refdata to prevent modpost + * triggering a section mismatch warning. + */ +static struct platform_driver einj_driver __refdata = { + .remove_new = __exit_p(einj_remove), .driver = { .name = "acpi-einj", }, diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index d9fa730416f1..787eca838410 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -112,6 +112,17 @@ int acpi_bus_get_status(struct acpi_device *device) if (ACPI_FAILURE(status)) return -ENODEV; + if (!device->status.present && device->status.enabled) { + pr_info(FW_BUG "Device [%s] status [%08x]: not present and enabled\n", + device->pnp.bus_id, (u32)sta); + device->status.enabled = 0; + /* + * The status is clearly invalid, so clear the functional bit as + * well to avoid attempting to use the device. + */ + device->status.functional = 0; + } + acpi_set_device_status(device, sta); if (device->status.functional && !device->status.present) { @@ -316,9 +327,14 @@ static void acpi_bus_osc_negotiate_platform_control(void) capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PAD_SUPPORT; if (IS_ENABLED(CONFIG_ACPI_PROCESSOR)) capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PPC_OST_SUPPORT; + if (IS_ENABLED(CONFIG_ACPI_THERMAL)) + capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_FAST_THERMAL_SAMPLING_SUPPORT; capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_HOTPLUG_OST_SUPPORT; capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PCLPI_SUPPORT; + capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_OVER_16_PSTATES_SUPPORT; + capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_GED_SUPPORT; + capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_IRQ_RESOURCE_SOURCE_SUPPORT; if (IS_ENABLED(CONFIG_ACPI_PRMT)) capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PRM_SUPPORT; if (IS_ENABLED(CONFIG_ACPI_FFH)) @@ -990,25 +1006,26 @@ EXPORT_SYMBOL_GPL(acpi_driver_match_device); -------------------------------------------------------------------------- */ /** - * acpi_bus_register_driver - register a driver with the ACPI bus + * __acpi_bus_register_driver - register a driver with the ACPI bus * @driver: driver being registered + * @owner: owning module/driver * * Registers a driver with the ACPI bus. Searches the namespace for all * devices that match the driver's criteria and binds. Returns zero for * success or a negative error status for failure. */ -int acpi_bus_register_driver(struct acpi_driver *driver) +int __acpi_bus_register_driver(struct acpi_driver *driver, struct module *owner) { if (acpi_disabled) return -ENODEV; driver->drv.name = driver->name; driver->drv.bus = &acpi_bus_type; - driver->drv.owner = driver->owner; + driver->drv.owner = owner; return driver_register(&driver->drv); } -EXPORT_SYMBOL(acpi_bus_register_driver); +EXPORT_SYMBOL(__acpi_bus_register_driver); /** * acpi_bus_unregister_driver - unregisters a driver with the ACPI bus diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c index a40b6f3946ef..1d857978f5f4 100644 --- a/drivers/acpi/cppc_acpi.c +++ b/drivers/acpi/cppc_acpi.c @@ -686,8 +686,10 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr) if (!osc_sb_cppc2_support_acked) { pr_debug("CPPC v2 _OSC not acked\n"); - if (!cpc_supported_by_cpu()) + if (!cpc_supported_by_cpu()) { + pr_debug("CPPC is not supported by the CPU\n"); return -ENODEV; + } } /* Parse the ACPI _CPC table for this CPU. */ diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index a7c00ef78086..34affbda295e 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -88,43 +88,29 @@ static void dock_hotplug_event(struct dock_dependent_device *dd, u32 event, enum dock_callback_type cb_type) { struct acpi_device *adev = dd->adev; + acpi_hp_fixup fixup = NULL; + acpi_hp_uevent uevent = NULL; + acpi_hp_notify notify = NULL; acpi_lock_hp_context(); - if (!adev->hp) - goto out; - - if (cb_type == DOCK_CALL_FIXUP) { - void (*fixup)(struct acpi_device *); - - fixup = adev->hp->fixup; - if (fixup) { - acpi_unlock_hp_context(); - fixup(adev); - return; - } - } else if (cb_type == DOCK_CALL_UEVENT) { - void (*uevent)(struct acpi_device *, u32); - - uevent = adev->hp->uevent; - if (uevent) { - acpi_unlock_hp_context(); - uevent(adev, event); - return; - } - } else { - int (*notify)(struct acpi_device *, u32); - - notify = adev->hp->notify; - if (notify) { - acpi_unlock_hp_context(); - notify(adev, event); - return; - } + if (adev->hp) { + if (cb_type == DOCK_CALL_FIXUP) + fixup = adev->hp->fixup; + else if (cb_type == DOCK_CALL_UEVENT) + uevent = adev->hp->uevent; + else + notify = adev->hp->notify; } - out: acpi_unlock_hp_context(); + + if (fixup) + fixup(adev); + else if (uevent) + uevent(adev, event); + else if (notify) + notify(adev, event); } static struct dock_station *find_dock_station(acpi_handle handle) diff --git a/drivers/acpi/dptf/dptf_pch_fivr.c b/drivers/acpi/dptf/dptf_pch_fivr.c index 654aaa53c67f..d202730fafd8 100644 --- a/drivers/acpi/dptf/dptf_pch_fivr.c +++ b/drivers/acpi/dptf/dptf_pch_fivr.c @@ -150,6 +150,7 @@ static const struct acpi_device_id pch_fivr_device_ids[] = { {"INTC1045", 0}, {"INTC1049", 0}, {"INTC1064", 0}, + {"INTC106B", 0}, {"INTC10A3", 0}, {"", 0}, }; diff --git a/drivers/acpi/dptf/dptf_power.c b/drivers/acpi/dptf/dptf_power.c index b8187babbbbb..8023b3e23315 100644 --- a/drivers/acpi/dptf/dptf_power.c +++ b/drivers/acpi/dptf/dptf_power.c @@ -232,6 +232,8 @@ static const struct acpi_device_id int3407_device_ids[] = { {"INTC1061", 0}, {"INTC1065", 0}, {"INTC1066", 0}, + {"INTC106C", 0}, + {"INTC106D", 0}, {"INTC10A4", 0}, {"INTC10A5", 0}, {"", 0}, diff --git a/drivers/acpi/dptf/int340x_thermal.c b/drivers/acpi/dptf/int340x_thermal.c index b7113fa92fa6..014ada759954 100644 --- a/drivers/acpi/dptf/int340x_thermal.c +++ b/drivers/acpi/dptf/int340x_thermal.c @@ -43,6 +43,12 @@ static const struct acpi_device_id int340x_thermal_device_ids[] = { {"INTC1064"}, {"INTC1065"}, {"INTC1066"}, + {"INTC1068"}, + {"INTC1069"}, + {"INTC106A"}, + {"INTC106B"}, + {"INTC106C"}, + {"INTC106D"}, {"INTC10A0"}, {"INTC10A1"}, {"INTC10A2"}, diff --git a/drivers/acpi/fan.h b/drivers/acpi/fan.h index e7b4b4e4a55e..f89d19c922dc 100644 --- a/drivers/acpi/fan.h +++ b/drivers/acpi/fan.h @@ -15,6 +15,7 @@ {"INTC1044", }, /* Fan for Tiger Lake generation */ \ {"INTC1048", }, /* Fan for Alder Lake generation */ \ {"INTC1063", }, /* Fan for Meteor Lake generation */ \ + {"INTC106A", }, /* Fan for Lunar Lake generation */ \ {"INTC10A2", }, /* Fan for Raptor Lake generation */ \ {"PNP0C0B", } /* Generic ACPI fan */ diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index ca72a0dc5715..60c483836756 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -69,7 +69,8 @@ void acpi_debugfs_init(void); #else static inline void acpi_debugfs_init(void) { return; } #endif -#ifdef CONFIG_PCI + +#if defined(CONFIG_X86) && defined(CONFIG_PCI) void acpi_lpss_init(void); #else static inline void acpi_lpss_init(void) {} diff --git a/drivers/acpi/nhlt.c b/drivers/acpi/nhlt.c new file mode 100644 index 000000000000..dc1bd0df9228 --- /dev/null +++ b/drivers/acpi/nhlt.c @@ -0,0 +1,289 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright(c) 2023-2024 Intel Corporation + * + * Authors: Cezary Rojewski <cezary.rojewski@intel.com> + * Amadeusz Slawinski <amadeuszx.slawinski@linux.intel.com> + */ + +#define pr_fmt(fmt) "ACPI: NHLT: " fmt + +#include <linux/acpi.h> +#include <linux/errno.h> +#include <linux/export.h> +#include <linux/minmax.h> +#include <linux/printk.h> +#include <linux/types.h> +#include <acpi/nhlt.h> + +static struct acpi_table_nhlt *acpi_gbl_nhlt; + +static struct acpi_table_nhlt empty_nhlt = { + .header = { + .signature = ACPI_SIG_NHLT, + }, +}; + +/** + * acpi_nhlt_get_gbl_table - Retrieve a pointer to the first NHLT table. + * + * If there is no NHLT in the system, acpi_gbl_nhlt will instead point to an + * empty table. + * + * Return: ACPI status code of the operation. + */ +acpi_status acpi_nhlt_get_gbl_table(void) +{ + acpi_status status; + + status = acpi_get_table(ACPI_SIG_NHLT, 0, (struct acpi_table_header **)(&acpi_gbl_nhlt)); + if (!acpi_gbl_nhlt) + acpi_gbl_nhlt = &empty_nhlt; + return status; +} +EXPORT_SYMBOL_GPL(acpi_nhlt_get_gbl_table); + +/** + * acpi_nhlt_put_gbl_table - Release the global NHLT table. + */ +void acpi_nhlt_put_gbl_table(void) +{ + acpi_put_table((struct acpi_table_header *)acpi_gbl_nhlt); +} +EXPORT_SYMBOL_GPL(acpi_nhlt_put_gbl_table); + +/** + * acpi_nhlt_endpoint_match - Verify if an endpoint matches criteria. + * @ep: the endpoint to check. + * @link_type: the hardware link type, e.g.: PDM or SSP. + * @dev_type: the device type. + * @dir: stream direction. + * @bus_id: the ID of virtual bus hosting the endpoint. + * + * Either of @link_type, @dev_type, @dir or @bus_id may be set to a negative + * value to ignore the parameter when matching. + * + * Return: %true if endpoint matches specified criteria or %false otherwise. + */ +bool acpi_nhlt_endpoint_match(const struct acpi_nhlt_endpoint *ep, + int link_type, int dev_type, int dir, int bus_id) +{ + return ep && + (link_type < 0 || ep->link_type == link_type) && + (dev_type < 0 || ep->device_type == dev_type) && + (bus_id < 0 || ep->virtual_bus_id == bus_id) && + (dir < 0 || ep->direction == dir); +} +EXPORT_SYMBOL_GPL(acpi_nhlt_endpoint_match); + +/** + * acpi_nhlt_tb_find_endpoint - Search a NHLT table for an endpoint. + * @tb: the table to search. + * @link_type: the hardware link type, e.g.: PDM or SSP. + * @dev_type: the device type. + * @dir: stream direction. + * @bus_id: the ID of virtual bus hosting the endpoint. + * + * Either of @link_type, @dev_type, @dir or @bus_id may be set to a negative + * value to ignore the parameter during the search. + * + * Return: A pointer to endpoint matching the criteria, %NULL if not found or + * an ERR_PTR() otherwise. + */ +struct acpi_nhlt_endpoint * +acpi_nhlt_tb_find_endpoint(const struct acpi_table_nhlt *tb, + int link_type, int dev_type, int dir, int bus_id) +{ + struct acpi_nhlt_endpoint *ep; + + for_each_nhlt_endpoint(tb, ep) + if (acpi_nhlt_endpoint_match(ep, link_type, dev_type, dir, bus_id)) + return ep; + return NULL; +} +EXPORT_SYMBOL_GPL(acpi_nhlt_tb_find_endpoint); + +/** + * acpi_nhlt_find_endpoint - Search all NHLT tables for an endpoint. + * @link_type: the hardware link type, e.g.: PDM or SSP. + * @dev_type: the device type. + * @dir: stream direction. + * @bus_id: the ID of virtual bus hosting the endpoint. + * + * Either of @link_type, @dev_type, @dir or @bus_id may be set to a negative + * value to ignore the parameter during the search. + * + * Return: A pointer to endpoint matching the criteria, %NULL if not found or + * an ERR_PTR() otherwise. + */ +struct acpi_nhlt_endpoint * +acpi_nhlt_find_endpoint(int link_type, int dev_type, int dir, int bus_id) +{ + /* TODO: Currently limited to table of index 0. */ + return acpi_nhlt_tb_find_endpoint(acpi_gbl_nhlt, link_type, dev_type, dir, bus_id); +} +EXPORT_SYMBOL_GPL(acpi_nhlt_find_endpoint); + +/** + * acpi_nhlt_endpoint_find_fmtcfg - Search endpoint's formats configuration space + * for a specific format. + * @ep: the endpoint to search. + * @ch: number of channels. + * @rate: samples per second. + * @vbps: valid bits per sample. + * @bps: bits per sample. + * + * Return: A pointer to format matching the criteria, %NULL if not found or + * an ERR_PTR() otherwise. + */ +struct acpi_nhlt_format_config * +acpi_nhlt_endpoint_find_fmtcfg(const struct acpi_nhlt_endpoint *ep, + u16 ch, u32 rate, u16 vbps, u16 bps) +{ + struct acpi_nhlt_wave_formatext *wav; + struct acpi_nhlt_format_config *fmt; + + for_each_nhlt_endpoint_fmtcfg(ep, fmt) { + wav = &fmt->format; + + if (wav->valid_bits_per_sample == vbps && + wav->samples_per_sec == rate && + wav->bits_per_sample == bps && + wav->channel_count == ch) + return fmt; + } + + return NULL; +} +EXPORT_SYMBOL_GPL(acpi_nhlt_endpoint_find_fmtcfg); + +/** + * acpi_nhlt_tb_find_fmtcfg - Search a NHLT table for a specific format. + * @tb: the table to search. + * @link_type: the hardware link type, e.g.: PDM or SSP. + * @dev_type: the device type. + * @dir: stream direction. + * @bus_id: the ID of virtual bus hosting the endpoint. + * + * @ch: number of channels. + * @rate: samples per second. + * @vbps: valid bits per sample. + * @bps: bits per sample. + * + * Either of @link_type, @dev_type, @dir or @bus_id may be set to a negative + * value to ignore the parameter during the search. + * + * Return: A pointer to format matching the criteria, %NULL if not found or + * an ERR_PTR() otherwise. + */ +struct acpi_nhlt_format_config * +acpi_nhlt_tb_find_fmtcfg(const struct acpi_table_nhlt *tb, + int link_type, int dev_type, int dir, int bus_id, + u16 ch, u32 rate, u16 vbps, u16 bps) +{ + struct acpi_nhlt_format_config *fmt; + struct acpi_nhlt_endpoint *ep; + + for_each_nhlt_endpoint(tb, ep) { + if (!acpi_nhlt_endpoint_match(ep, link_type, dev_type, dir, bus_id)) + continue; + + fmt = acpi_nhlt_endpoint_find_fmtcfg(ep, ch, rate, vbps, bps); + if (fmt) + return fmt; + } + + return NULL; +} +EXPORT_SYMBOL_GPL(acpi_nhlt_tb_find_fmtcfg); + +/** + * acpi_nhlt_find_fmtcfg - Search all NHLT tables for a specific format. + * @link_type: the hardware link type, e.g.: PDM or SSP. + * @dev_type: the device type. + * @dir: stream direction. + * @bus_id: the ID of virtual bus hosting the endpoint. + * + * @ch: number of channels. + * @rate: samples per second. + * @vbps: valid bits per sample. + * @bps: bits per sample. + * + * Either of @link_type, @dev_type, @dir or @bus_id may be set to a negative + * value to ignore the parameter during the search. + * + * Return: A pointer to format matching the criteria, %NULL if not found or + * an ERR_PTR() otherwise. + */ +struct acpi_nhlt_format_config * +acpi_nhlt_find_fmtcfg(int link_type, int dev_type, int dir, int bus_id, + u16 ch, u32 rate, u16 vbps, u16 bps) +{ + /* TODO: Currently limited to table of index 0. */ + return acpi_nhlt_tb_find_fmtcfg(acpi_gbl_nhlt, link_type, dev_type, dir, bus_id, + ch, rate, vbps, bps); +} +EXPORT_SYMBOL_GPL(acpi_nhlt_find_fmtcfg); + +static bool acpi_nhlt_config_is_micdevice(struct acpi_nhlt_config *cfg) +{ + return cfg->capabilities_size >= sizeof(struct acpi_nhlt_micdevice_config); +} + +static bool acpi_nhlt_config_is_vendor_micdevice(struct acpi_nhlt_config *cfg) +{ + struct acpi_nhlt_vendor_micdevice_config *devcfg = __acpi_nhlt_config_caps(cfg); + + return cfg->capabilities_size >= sizeof(*devcfg) && + cfg->capabilities_size == struct_size(devcfg, mics, devcfg->mics_count); +} + +/** + * acpi_nhlt_endpoint_mic_count - Retrieve number of digital microphones for a PDM endpoint. + * @ep: the endpoint to return microphones count for. + * + * Return: A number of microphones or an error code if an invalid endpoint is provided. + */ +int acpi_nhlt_endpoint_mic_count(const struct acpi_nhlt_endpoint *ep) +{ + union acpi_nhlt_device_config *devcfg; + struct acpi_nhlt_format_config *fmt; + struct acpi_nhlt_config *cfg; + u16 max_ch = 0; + + if (!ep || ep->link_type != ACPI_NHLT_LINKTYPE_PDM) + return -EINVAL; + + /* Find max number of channels based on formats configuration. */ + for_each_nhlt_endpoint_fmtcfg(ep, fmt) + max_ch = max(fmt->format.channel_count, max_ch); + + cfg = __acpi_nhlt_endpoint_config(ep); + devcfg = __acpi_nhlt_config_caps(cfg); + + /* If @ep is not a mic array, fallback to channels count. */ + if (!acpi_nhlt_config_is_micdevice(cfg) || + devcfg->gen.config_type != ACPI_NHLT_CONFIGTYPE_MICARRAY) + return max_ch; + + switch (devcfg->mic.array_type) { + case ACPI_NHLT_ARRAYTYPE_LINEAR2_SMALL: + case ACPI_NHLT_ARRAYTYPE_LINEAR2_BIG: + return 2; + + case ACPI_NHLT_ARRAYTYPE_LINEAR4_GEO1: + case ACPI_NHLT_ARRAYTYPE_PLANAR4_LSHAPED: + case ACPI_NHLT_ARRAYTYPE_LINEAR4_GEO2: + return 4; + + case ACPI_NHLT_ARRAYTYPE_VENDOR: + if (!acpi_nhlt_config_is_vendor_micdevice(cfg)) + return -EINVAL; + return devcfg->vendor_mic.mics_count; + + default: + pr_warn("undefined mic array type: %#x\n", devcfg->mic.array_type); + return max_ch; + } +} +EXPORT_SYMBOL_GPL(acpi_nhlt_endpoint_mic_count); diff --git a/drivers/acpi/numa/srat.c b/drivers/acpi/numa/srat.c index e45e64993c50..e3f26e71637a 100644 --- a/drivers/acpi/numa/srat.c +++ b/drivers/acpi/numa/srat.c @@ -208,16 +208,26 @@ int __init srat_disabled(void) return acpi_numa < 0; } -#if defined(CONFIG_X86) || defined(CONFIG_ARM64) || defined(CONFIG_LOONGARCH) +__weak int __init numa_fill_memblks(u64 start, u64 end) +{ + return NUMA_NO_MEMBLK; +} + /* * Callback for SLIT parsing. pxm_to_node() returns NUMA_NO_NODE for * I/O localities since SRAT does not list them. I/O localities are * not supported at this point. */ -void __init acpi_numa_slit_init(struct acpi_table_slit *slit) +static int __init acpi_parse_slit(struct acpi_table_header *table) { + struct acpi_table_slit *slit = (struct acpi_table_slit *)table; int i, j; + if (!slit_valid(slit)) { + pr_info("SLIT table looks invalid. Not used.\n"); + return -EINVAL; + } + for (i = 0; i < slit->locality_count; i++) { const int from_node = pxm_to_node(i); @@ -234,28 +244,34 @@ void __init acpi_numa_slit_init(struct acpi_table_slit *slit) slit->entry[slit->locality_count * i + j]); } } + + return 0; } -/* - * Default callback for parsing of the Proximity Domain <-> Memory - * Area mappings - */ -int __init -acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma) +static int parsed_numa_memblks __initdata; + +static int __init +acpi_parse_memory_affinity(union acpi_subtable_headers *header, + const unsigned long table_end) { + struct acpi_srat_mem_affinity *ma; u64 start, end; u32 hotpluggable; int node, pxm; + ma = (struct acpi_srat_mem_affinity *)header; + + acpi_table_print_srat_entry(&header->common); + if (srat_disabled()) - goto out_err; + return 0; if (ma->header.length < sizeof(struct acpi_srat_mem_affinity)) { pr_err("SRAT: Unexpected header length: %d\n", ma->header.length); goto out_err_bad_srat; } if ((ma->flags & ACPI_SRAT_MEM_ENABLED) == 0) - goto out_err; + return 0; hotpluggable = IS_ENABLED(CONFIG_MEMORY_HOTPLUG) && (ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE); @@ -293,11 +309,15 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma) max_possible_pfn = max(max_possible_pfn, PFN_UP(end - 1)); + parsed_numa_memblks++; + return 0; + out_err_bad_srat: + /* Just disable SRAT, but do not fail and ignore errors. */ bad_srat(); -out_err: - return -EINVAL; + + return 0; } static int __init acpi_parse_cfmws(union acpi_subtable_headers *header, @@ -340,26 +360,6 @@ static int __init acpi_parse_cfmws(union acpi_subtable_headers *header, (*fake_pxm)++; return 0; } -#else -static int __init acpi_parse_cfmws(union acpi_subtable_headers *header, - void *arg, const unsigned long table_end) -{ - return 0; -} -#endif /* defined(CONFIG_X86) || defined (CONFIG_ARM64) */ - -static int __init acpi_parse_slit(struct acpi_table_header *table) -{ - struct acpi_table_slit *slit = (struct acpi_table_slit *)table; - - if (!slit_valid(slit)) { - pr_info("SLIT table looks invalid. Not used.\n"); - return -EINVAL; - } - acpi_numa_slit_init(slit); - - return 0; -} void __init __weak acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa) @@ -450,24 +450,6 @@ acpi_parse_gi_affinity(union acpi_subtable_headers *header, } #endif /* defined(CONFIG_X86) || defined (CONFIG_ARM64) */ -static int __initdata parsed_numa_memblks; - -static int __init -acpi_parse_memory_affinity(union acpi_subtable_headers * header, - const unsigned long end) -{ - struct acpi_srat_mem_affinity *memory_affinity; - - memory_affinity = (struct acpi_srat_mem_affinity *)header; - - acpi_table_print_srat_entry(&header->common); - - /* let architecture-dependent part to do it */ - if (!acpi_numa_memory_affinity_init(memory_affinity)) - parsed_numa_memblks++; - return 0; -} - static int __init acpi_parse_srat(struct acpi_table_header *table) { struct acpi_table_srat *srat = (struct acpi_table_srat *)table; diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c index 2b73580c9f36..80a52a4e66dd 100644 --- a/drivers/acpi/property.c +++ b/drivers/acpi/property.c @@ -31,9 +31,14 @@ static int acpi_data_get_property_array(const struct acpi_device_data *data, * not defined without a warning. For instance if any of the properties * from different GUID appear in a property list of another, it will be * accepted by the kernel. Firmware validation tools should catch these. + * + * References: + * + * [1] UEFI DSD Guide. + * https://github.com/UEFI/DSD-Guide/blob/main/src/dsd-guide.adoc */ static const guid_t prp_guids[] = { - /* ACPI _DSD device properties GUID: daffd814-6eba-4d8c-8a91-bc9bbf4aa301 */ + /* ACPI _DSD device properties GUID [1]: daffd814-6eba-4d8c-8a91-bc9bbf4aa301 */ GUID_INIT(0xdaffd814, 0x6eba, 0x4d8c, 0x8a, 0x91, 0xbc, 0x9b, 0xbf, 0x4a, 0xa3, 0x01), /* Hotplug in D3 GUID: 6211e2c0-58a3-4af3-90e1-927a4e0c55a4 */ @@ -53,12 +58,12 @@ static const guid_t prp_guids[] = { 0xa5, 0x61, 0x99, 0xa5, 0x18, 0x97, 0x62, 0xd0), }; -/* ACPI _DSD data subnodes GUID: dbb8e3e6-5886-4ba6-8795-1319f52a966b */ +/* ACPI _DSD data subnodes GUID [1]: dbb8e3e6-5886-4ba6-8795-1319f52a966b */ static const guid_t ads_guid = GUID_INIT(0xdbb8e3e6, 0x5886, 0x4ba6, 0x87, 0x95, 0x13, 0x19, 0xf5, 0x2a, 0x96, 0x6b); -/* ACPI _DSD data buffer GUID: edb12dd0-363d-4085-a3d2-49522ca160c4 */ +/* ACPI _DSD data buffer GUID [1]: edb12dd0-363d-4085-a3d2-49522ca160c4 */ static const guid_t buffer_prop_guid = GUID_INIT(0xedb12dd0, 0x363d, 0x4085, 0xa3, 0xd2, 0x49, 0x52, 0x2c, 0xa1, 0x60, 0xc4); diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c index 59423fe9d0f2..b5bf8b81a050 100644 --- a/drivers/acpi/resource.c +++ b/drivers/acpi/resource.c @@ -518,6 +518,13 @@ static const struct dmi_system_id irq1_level_low_skip_override[] = { }, }, { + /* Asus Vivobook Pro N6506MV */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_BOARD_NAME, "N6506MV"), + }, + }, + { /* LG Electronics 17U70P */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "LG Electronics"), @@ -534,6 +541,12 @@ static const struct dmi_system_id irq1_level_low_skip_override[] = { */ static const struct dmi_system_id irq1_edge_low_force_override[] = { { + /* XMG APEX 17 (M23) */ + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "GMxBGxx"), + }, + }, + { /* TongFang GMxRGxx/XMG CORE 15 (M22)/TUXEDO Stellaris 15 Gen4 AMD */ .matches = { DMI_MATCH(DMI_BOARD_NAME, "GMxRGxx"), @@ -630,6 +643,18 @@ static const struct dmi_system_id irq1_edge_low_force_override[] = { DMI_MATCH(DMI_BOARD_NAME, "X565"), }, }, + { + /* TongFang GXxHRXx/TUXEDO InfinityBook Pro Gen9 AMD */ + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "GXxHRXx"), + }, + }, + { + /* TongFang GMxHGxx/TUXEDO Stellaris Slim Gen1 AMD */ + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "GMxHGxx"), + }, + }, { } }; diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index d1464324de95..e41fb5716bc0 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -73,8 +73,7 @@ void acpi_unlock_hp_context(void) void acpi_initialize_hp_context(struct acpi_device *adev, struct acpi_hotplug_context *hp, - int (*notify)(struct acpi_device *, u32), - void (*uevent)(struct acpi_device *, u32)) + acpi_hp_notify notify, acpi_hp_uevent uevent) { acpi_lock_hp_context(); hp->notify = notify; @@ -428,7 +427,7 @@ void acpi_device_hotplug(struct acpi_device *adev, u32 src) } else if (adev->flags.hotplug_notify) { error = acpi_generic_hotplug_event(adev, src); } else { - int (*notify)(struct acpi_device *, u32); + acpi_hp_notify notify; acpi_lock_hp_context(); notify = adev->hp ? adev->hp->notify : NULL; @@ -1298,10 +1297,10 @@ const char *acpi_device_hid(struct acpi_device *device) { struct acpi_hardware_id *hid; - if (list_empty(&device->pnp.ids)) + hid = list_first_entry_or_null(&device->pnp.ids, struct acpi_hardware_id, list); + if (!hid) return dummy_hid; - hid = list_first_entry(&device->pnp.ids, struct acpi_hardware_id, list); return hid->id; } EXPORT_SYMBOL(acpi_device_hid); @@ -1581,12 +1580,13 @@ int acpi_iommu_fwspec_init(struct device *dev, u32 id, struct fwnode_handle *fwnode, const struct iommu_ops *ops) { - int ret = iommu_fwspec_init(dev, fwnode, ops); + int ret; - if (!ret) - ret = iommu_fwspec_add_ids(dev, &id, 1); + ret = iommu_fwspec_init(dev, fwnode, ops); + if (ret) + return ret; - return ret; + return iommu_fwspec_add_ids(dev, &id, 1); } static inline const struct iommu_ops *acpi_iommu_fwspec_ops(struct device *dev) @@ -1625,12 +1625,11 @@ static int acpi_iommu_configure_id(struct device *dev, const u32 *id_in) if (!err && dev->bus) err = iommu_probe_device(dev); - /* Ignore all other errors apart from EPROBE_DEFER */ - if (err == -EPROBE_DEFER) { + if (err == -EPROBE_DEFER) return err; - } else if (err) { + if (err) { dev_dbg(dev, "Adding to IOMMU failed: %d\n", err); - return -ENODEV; + return err; } if (!acpi_iommu_fwspec_ops(dev)) return -ENODEV; @@ -1671,13 +1670,14 @@ int acpi_dma_configure_id(struct device *dev, enum dev_dma_attr attr, acpi_arch_dma_setup(dev); + /* Ignore all other errors apart from EPROBE_DEFER */ ret = acpi_iommu_configure_id(dev, input_id); if (ret == -EPROBE_DEFER) return -EPROBE_DEFER; /* * Historically this routine doesn't fail driver probing due to errors - * in acpi_iommu_configure_id() + * in acpi_iommu_configure_id(). */ arch_setup_dma_ops(dev, 0, U64_MAX, attr == DEV_DMA_COHERENT); @@ -1962,7 +1962,7 @@ bool acpi_device_is_present(const struct acpi_device *adev) bool acpi_device_is_enabled(const struct acpi_device *adev) { - return adev->status.present && adev->status.enabled; + return adev->status.enabled; } static bool acpi_scan_handler_matching(struct acpi_scan_handler *handler, diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index 9fdcc620c652..2cc3821b2b16 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c @@ -499,6 +499,14 @@ static const struct dmi_system_id video_detect_dmi_table[] = { }, { .callback = video_detect_force_native, + /* Lenovo Slim 7 16ARH7 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "82UX"), + }, + }, + { + .callback = video_detect_force_native, /* Lenovo ThinkPad X131e (3371 AMD version) */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), diff --git a/drivers/acpi/x86/Makefile b/drivers/acpi/x86/Makefile new file mode 100644 index 000000000000..63c99509ed9d --- /dev/null +++ b/drivers/acpi/x86/Makefile @@ -0,0 +1,8 @@ +obj-$(CONFIG_ACPI) += acpi-x86.o +acpi-x86-y += apple.o +acpi-x86-y += cmos_rtc.o +acpi-x86-$(CONFIG_PCI) += lpss.o +acpi-x86-y += s2idle.o +acpi-x86-y += utils.o + +obj-$(CONFIG_X86) += blacklist.o diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/x86/blacklist.c index a558d24fb788..55214d0a12b1 100644 --- a/drivers/acpi/blacklist.c +++ b/drivers/acpi/x86/blacklist.c @@ -17,7 +17,7 @@ #include <linux/acpi.h> #include <linux/dmi.h> -#include "internal.h" +#include "../internal.h" #ifdef CONFIG_DMI static const struct dmi_system_id acpi_rev_dmi_table[] __initconst; diff --git a/drivers/acpi/acpi_cmos_rtc.c b/drivers/acpi/x86/cmos_rtc.c index 9b55d1593d16..51643ff6fe5f 100644 --- a/drivers/acpi/acpi_cmos_rtc.c +++ b/drivers/acpi/x86/cmos_rtc.c @@ -15,7 +15,7 @@ #include <linux/module.h> #include <linux/mc146818rtc.h> -#include "internal.h" +#include "../internal.h" static const struct acpi_device_id acpi_cmos_rtc_ids[] = { { "PNP0B00" }, diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/x86/lpss.c index 04e273167e92..148e29c2c526 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/x86/lpss.c @@ -25,7 +25,7 @@ #include <linux/suspend.h> #include <linux/delay.h> -#include "internal.h" +#include "../internal.h" #ifdef CONFIG_X86_INTEL_LPSS @@ -325,6 +325,7 @@ static const struct lpss_device_desc bsw_i2c_dev_desc = { static const struct property_entry bsw_spi_properties[] = { PROPERTY_ENTRY_U32("intel,spi-pxa2xx-type", LPSS_BSW_SSP), + PROPERTY_ENTRY_U32("num-cs", 2), { } }; @@ -886,10 +887,8 @@ static int acpi_lpss_activate(struct device *dev) if (pdata->dev_desc->flags & (LPSS_SAVE_CTX | LPSS_SAVE_CTX_ONCE)) lpss_deassert_reset(pdata); -#ifdef CONFIG_PM if (pdata->dev_desc->flags & LPSS_SAVE_CTX_ONCE) acpi_lpss_save_ctx(dev, pdata); -#endif return 0; } diff --git a/drivers/acpi/x86/utils.c b/drivers/acpi/x86/utils.c index 90c3d2eab9e9..7dca73417e2b 100644 --- a/drivers/acpi/x86/utils.c +++ b/drivers/acpi/x86/utils.c @@ -101,6 +101,15 @@ static const struct override_status_id override_status_ids[] = { }), /* + * The Dell XPS 15 9550 has a SMO8110 accelerometer / + * HDD freefall sensor which is wrongly marked as not present. + */ + PRESENT_ENTRY_HID("SMO8810", "1", SKYLAKE, { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "XPS 15 9550"), + }), + + /* * The GPD win BIOS dated 20170221 has disabled the accelerometer, the * drivers sometimes cause crashes under Windows and this is how the * manufacturer has solved this :| The DMI match may not seem unique, @@ -260,9 +269,10 @@ bool force_storage_d3(void) #define ACPI_QUIRK_SKIP_I2C_CLIENTS BIT(0) #define ACPI_QUIRK_UART1_SKIP BIT(1) #define ACPI_QUIRK_UART1_TTY_UART2_SKIP BIT(2) -#define ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY BIT(3) -#define ACPI_QUIRK_USE_ACPI_AC_AND_BATTERY BIT(4) -#define ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS BIT(5) +#define ACPI_QUIRK_PNP_UART1_SKIP BIT(3) +#define ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY BIT(4) +#define ACPI_QUIRK_USE_ACPI_AC_AND_BATTERY BIT(5) +#define ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS BIT(6) static const struct dmi_system_id acpi_quirk_skip_dmi_ids[] = { /* @@ -342,6 +352,7 @@ static const struct dmi_system_id acpi_quirk_skip_dmi_ids[] = { DMI_MATCH(DMI_BIOS_VERSION, "BLADE_21"), }, .driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS | + ACPI_QUIRK_PNP_UART1_SKIP | ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY), }, { @@ -440,14 +451,18 @@ static int acpi_dmi_skip_serdev_enumeration(struct device *controller_parent, bo if (ret) return 0; - /* to not match on PNP enumerated debug UARTs */ - if (!dev_is_platform(controller_parent)) - return 0; - dmi_id = dmi_first_match(acpi_quirk_skip_dmi_ids); if (dmi_id) quirks = (unsigned long)dmi_id->driver_data; + if (!dev_is_platform(controller_parent)) { + /* PNP enumerated UARTs */ + if ((quirks & ACPI_QUIRK_PNP_UART1_SKIP) && uid == 1) + *skip = true; + + return 0; + } + if ((quirks & ACPI_QUIRK_UART1_SKIP) && uid == 1) *skip = true; |