From 437b38c51162f8b87beb28a833c4d5dc85fa864e Mon Sep 17 00:00:00 2001 From: Lorenzo Pieralisi Date: Mon, 23 Aug 2021 11:46:18 +0100 Subject: ACPI: Add memory semantics to acpi_os_map_memory() The memory attributes attached to memory regions depend on architecture specific mappings. For some memory regions, the attributes specified by firmware (eg uncached) are not sufficient to determine how a memory region should be mapped by an OS (for instance a region that is define as uncached in firmware can be mapped as Normal or Device memory on arm64) and therefore the OS must be given control on how to map the region to match the expected mapping behaviour (eg if a mapping is requested with memory semantics, it must allow unaligned accesses). Rework acpi_os_map_memory() and acpi_os_ioremap() back-end to split them into two separate code paths: acpi_os_memmap() -> memory semantics acpi_os_ioremap() -> MMIO semantics The split allows the architectural implementation back-ends to detect the default memory attributes required by the mapping in question (ie the mapping API defines the semantics memory vs MMIO) and map the memory accordingly. Link: https://lore.kernel.org/linux-arm-kernel/31ffe8fc-f5ee-2858-26c5-0fd8bdd68702@arm.com Tested-by: Hanjun Guo Signed-off-by: Lorenzo Pieralisi Acked-by: Ard Biesheuvel Acked-by: Catalin Marinas Signed-off-by: Rafael J. Wysocki --- drivers/acpi/osl.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 45c5c0e45e33..a43f1521efe6 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -284,7 +284,8 @@ acpi_map_lookup_virt(void __iomem *virt, acpi_size size) #define should_use_kmap(pfn) page_is_ram(pfn) #endif -static void __iomem *acpi_map(acpi_physical_address pg_off, unsigned long pg_sz) +static void __iomem *acpi_map(acpi_physical_address pg_off, unsigned long pg_sz, + bool memory) { unsigned long pfn; @@ -294,7 +295,8 @@ static void __iomem *acpi_map(acpi_physical_address pg_off, unsigned long pg_sz) return NULL; return (void __iomem __force *)kmap(pfn_to_page(pfn)); } else - return acpi_os_ioremap(pg_off, pg_sz); + return memory ? acpi_os_memmap(pg_off, pg_sz) : + acpi_os_ioremap(pg_off, pg_sz); } static void acpi_unmap(acpi_physical_address pg_off, void __iomem *vaddr) @@ -309,9 +311,10 @@ static void acpi_unmap(acpi_physical_address pg_off, void __iomem *vaddr) } /** - * acpi_os_map_iomem - Get a virtual address for a given physical address range. + * __acpi_os_map_iomem - Get a virtual address for a given physical address range. * @phys: Start of the physical address range to map. * @size: Size of the physical address range to map. + * @memory: true if remapping memory, false if IO * * Look up the given physical address range in the list of existing ACPI memory * mappings. If found, get a reference to it and return a pointer to it (its @@ -321,8 +324,8 @@ static void acpi_unmap(acpi_physical_address pg_off, void __iomem *vaddr) * During early init (when acpi_permanent_mmap has not been set yet) this * routine simply calls __acpi_map_table() to get the job done. */ -void __iomem __ref -*acpi_os_map_iomem(acpi_physical_address phys, acpi_size size) +static void __iomem __ref +*__acpi_os_map_iomem(acpi_physical_address phys, acpi_size size, bool memory) { struct acpi_ioremap *map; void __iomem *virt; @@ -353,7 +356,7 @@ void __iomem __ref pg_off = round_down(phys, PAGE_SIZE); pg_sz = round_up(phys + size, PAGE_SIZE) - pg_off; - virt = acpi_map(phys, size); + virt = acpi_map(phys, size, memory); if (!virt) { mutex_unlock(&acpi_ioremap_lock); kfree(map); @@ -372,11 +375,17 @@ out: mutex_unlock(&acpi_ioremap_lock); return map->virt + (phys - map->phys); } + +void __iomem *__ref +acpi_os_map_iomem(acpi_physical_address phys, acpi_size size) +{ + return __acpi_os_map_iomem(phys, size, false); +} EXPORT_SYMBOL_GPL(acpi_os_map_iomem); void *__ref acpi_os_map_memory(acpi_physical_address phys, acpi_size size) { - return (void *)acpi_os_map_iomem(phys, size); + return (void *)__acpi_os_map_iomem(phys, size, true); } EXPORT_SYMBOL_GPL(acpi_os_map_memory); -- cgit v1.2.3 From 1a20d409c874255086e2f42a729826d490294c91 Mon Sep 17 00:00:00 2001 From: Ulrich Huber Date: Tue, 24 Aug 2021 14:57:44 +0200 Subject: ACPI: button: Add DMI quirk for Lenovo Yoga 9 (14INTL5) The Lenovo Yoga 9 (14INTL5)'s ACPI _LID is bugged: After hibernation the lid is initially reported as closed. Once closing and then reopening the lid reports the lid as open again. This leads to the conclusion that the initial notification of the lid is missing but subsequent notifications are correct. In order fo the Linux LID code to handle this device properly the lid_init_state must be set to ACPI_BUTTON_LID_INIT_OPEN. Signed-off-by: Ulrich Huber Signed-off-by: Rafael J. Wysocki --- drivers/acpi/button.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index f25bd336113b..1f9b9a4c38c7 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c @@ -77,6 +77,17 @@ static const struct dmi_system_id dmi_lid_quirks[] = { }, .driver_data = (void *)(long)ACPI_BUTTON_LID_INIT_DISABLED, }, + { + /* + * Lenovo Yoga 9 14ITL5, initial notification of the LID device + * never happens. + */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "82BG"), + }, + .driver_data = (void *)(long)ACPI_BUTTON_LID_INIT_OPEN, + }, { /* * Medion Akoya E2215T, notification of the LID device only -- cgit v1.2.3 From fad40a624854ad14a88ee0277b9e8207bfc6d95a Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 27 Aug 2021 21:07:58 +0200 Subject: ACPI: power: Use acpi_handle_debug() to print debug messages Use acpi_handle_debug() to print diagnostic messages regarding ACPI power resources so as to make it easier to correlate the kernel messages with the power resource objects in the ACPI namespace that they are about. Signed-off-by: Rafael J. Wysocki --- drivers/acpi/power.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index eba7785047ca..21d42804b2c1 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -356,10 +356,11 @@ void acpi_device_power_remove_dependent(struct acpi_device *adev, static int __acpi_power_on(struct acpi_power_resource *resource) { + acpi_handle handle = resource->device.handle; struct acpi_power_dependent_device *dep; acpi_status status = AE_OK; - status = acpi_evaluate_object(resource->device.handle, "_ON", NULL, NULL); + status = acpi_evaluate_object(handle, "_ON", NULL, NULL); if (ACPI_FAILURE(status)) { resource->state = ACPI_POWER_RESOURCE_STATE_UNKNOWN; return -ENODEV; @@ -367,7 +368,7 @@ static int __acpi_power_on(struct acpi_power_resource *resource) resource->state = ACPI_POWER_RESOURCE_STATE_ON; - pr_debug("Power resource [%s] turned on\n", resource->name); + acpi_handle_debug(handle, "Power resource turned on\n"); /* * If there are other dependents on this power resource we need to @@ -392,7 +393,8 @@ static int acpi_power_on_unlocked(struct acpi_power_resource *resource) int result = 0; if (resource->ref_count++) { - pr_debug("Power resource [%s] already on\n", resource->name); + acpi_handle_debug(resource->device.handle, + "Power resource already on\n"); } else { result = __acpi_power_on(resource); if (result) @@ -413,10 +415,10 @@ static int acpi_power_on(struct acpi_power_resource *resource) static int __acpi_power_off(struct acpi_power_resource *resource) { + acpi_handle handle = resource->device.handle; acpi_status status; - status = acpi_evaluate_object(resource->device.handle, "_OFF", - NULL, NULL); + status = acpi_evaluate_object(handle, "_OFF", NULL, NULL); if (ACPI_FAILURE(status)) { resource->state = ACPI_POWER_RESOURCE_STATE_UNKNOWN; return -ENODEV; @@ -424,7 +426,7 @@ static int __acpi_power_off(struct acpi_power_resource *resource) resource->state = ACPI_POWER_RESOURCE_STATE_OFF; - pr_debug("Power resource [%s] turned off\n", resource->name); + acpi_handle_debug(handle, "Power resource turned off\n"); return 0; } @@ -434,12 +436,14 @@ static int acpi_power_off_unlocked(struct acpi_power_resource *resource) int result = 0; if (!resource->ref_count) { - pr_debug("Power resource [%s] already off\n", resource->name); + acpi_handle_debug(resource->device.handle, + "Power resource already off\n"); return 0; } if (--resource->ref_count) { - pr_debug("Power resource [%s] still in use\n", resource->name); + acpi_handle_debug(resource->device.handle, + "Power resource still in use\n"); } else { result = __acpi_power_off(resource); if (result) @@ -1004,7 +1008,7 @@ void acpi_resume_power_resources(void) if (state == ACPI_POWER_RESOURCE_STATE_OFF && resource->ref_count) { - dev_dbg(&resource->device.dev, "Turning ON\n"); + acpi_handle_debug(resource->device.handle, "Turning ON\n"); __acpi_power_on(resource); } @@ -1034,7 +1038,7 @@ void acpi_turn_off_unused_power_resources(void) */ if (!resource->ref_count && resource->state != ACPI_POWER_RESOURCE_STATE_OFF) { - dev_dbg(&resource->device.dev, "Turning OFF\n"); + acpi_handle_debug(resource->device.handle, "Turning OFF\n"); __acpi_power_off(resource); } -- cgit v1.2.3 From 2bc4eb943b1b27606cd6d63be69f2197cad15173 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 25 Aug 2021 20:31:10 +0200 Subject: ACPI: power: Drop name from struct acpi_power_resource Drop the name field (that only is used in diagnostic messages) from struct acpi_power_resource and use the name of the power resource device object instead of it. Signed-off-by: Rafael J. Wysocki --- drivers/acpi/power.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 21d42804b2c1..b9863e22b952 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -48,7 +48,6 @@ struct acpi_power_dependent_device { struct acpi_power_resource { struct acpi_device device; struct list_head list_node; - char *name; u32 system_level; u32 order; unsigned int ref_count; @@ -70,6 +69,11 @@ static DEFINE_MUTEX(power_resource_list_lock); Power Resource Management -------------------------------------------------------------------------- */ +static inline const char *resource_dev_name(struct acpi_power_resource *pr) +{ + return dev_name(&pr->device.dev); +} + static inline struct acpi_power_resource *to_power_resource(struct acpi_device *device) { @@ -264,7 +268,8 @@ acpi_power_resource_add_dependent(struct acpi_power_resource *resource, dep->dev = dev; list_add_tail(&dep->node, &resource->dependents); - dev_dbg(dev, "added power dependency to [%s]\n", resource->name); + dev_dbg(dev, "added power dependency to [%s]\n", + resource_dev_name(resource)); unlock: mutex_unlock(&resource->resource_lock); @@ -283,7 +288,7 @@ acpi_power_resource_remove_dependent(struct acpi_power_resource *resource, list_del(&dep->node); kfree(dep); dev_dbg(dev, "removed power dependency to [%s]\n", - resource->name); + resource_dev_name(resource)); break; } } @@ -381,7 +386,7 @@ static int __acpi_power_on(struct acpi_power_resource *resource) list_for_each_entry(dep, &resource->dependents, node) { dev_dbg(dep->dev, "runtime resuming because [%s] turned on\n", - resource->name); + resource_dev_name(resource)); pm_request_resume(dep->dev); } @@ -953,7 +958,6 @@ struct acpi_device *acpi_add_power_resource(acpi_handle handle) mutex_init(&resource->resource_lock); INIT_LIST_HEAD(&resource->list_node); INIT_LIST_HEAD(&resource->dependents); - resource->name = device->pnp.bus_id; strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_POWER_CLASS); device->power.state = ACPI_STATE_UNKNOWN; -- cgit v1.2.3