From patchwork Mon Jun 22 13:52:34 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Rafael J. Wysocki" X-Patchwork-Id: 11617875 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 0415B138C for ; Mon, 22 Jun 2020 14:03:27 +0000 (UTC) Received: from ml01.01.org (ml01.01.org [198.145.21.10]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id E133D206E2 for ; Mon, 22 Jun 2020 14:03:26 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org E133D206E2 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=rjwysocki.net Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-nvdimm-bounces@lists.01.org Received: from ml01.vlan13.01.org (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id C789610FCC6CB; Mon, 22 Jun 2020 07:03:25 -0700 (PDT) Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=79.96.170.134; helo=cloudserver094114.home.pl; envelope-from=rjw@rjwysocki.net; receiver= Received: from cloudserver094114.home.pl (cloudserver094114.home.pl [79.96.170.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 4304F10FCBAA8 for ; Mon, 22 Jun 2020 07:03:23 -0700 (PDT) Received: from 89-64-85-91.dynamic.chello.pl (89.64.85.91) (HELO kreacher.localnet) by serwer1319399.home.pl (79.96.170.134) with SMTP (IdeaSmtpServer 0.83.415) id 43d1fddb106f0010; Mon, 22 Jun 2020 16:03:21 +0200 From: "Rafael J. Wysocki" To: Dan Williams , Erik Kaneda Subject: [RFT][PATCH v2 1/4] ACPICA: Defer unmapping of opregion memory if supported by OS Date: Mon, 22 Jun 2020 15:52:34 +0200 Message-ID: <1905235.LigdQVVlvn@kreacher> In-Reply-To: <2713141.s8EVnczdoM@kreacher> References: <158889473309.2292982.18007035454673387731.stgit@dwillia2-desk3.amr.corp.intel.com> <2713141.s8EVnczdoM@kreacher> MIME-Version: 1.0 Message-ID-Hash: HHIYGYZWUE5ABGBBQLZBCR4765FVPCEC X-Message-ID-Hash: HHIYGYZWUE5ABGBBQLZBCR4765FVPCEC X-MailFrom: rjw@rjwysocki.net X-Mailman-Rule-Hits: nonmember-moderation X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation CC: rafael.j.wysocki@intel.com, Len Brown , Borislav Petkov , James Morse , Myron Stowe , Andy Shevchenko , linux-kernel@vger.kernel.org, linux-acpi@vger.kernel.org, linux-nvdimm@lists.01.org, Bob Moore X-Mailman-Version: 3.1.1 Precedence: list List-Id: "Linux-nvdimm developer list." Archived-At: List-Archive: List-Help: List-Post: List-Subscribe: List-Unsubscribe: From: "Rafael J. Wysocki" The ACPI OS layer in Linux uses RCU to protect the walkers of the list of ACPI memory mappings from seeing an inconsistent state while it is being updated. Among other situations, that list can be walked in (NMI and non-NMI) interrupt context, so using a sleeping lock to protect it is not an option. However, performance issues related to the RCU usage in there appear, as described by Dan Williams: "Recently a performance problem was reported for a process invoking a non-trival ASL program. The method call in this case ends up repetitively triggering a call path like: acpi_ex_store acpi_ex_store_object_to_node acpi_ex_write_data_to_field acpi_ex_insert_into_field acpi_ex_write_with_update_rule acpi_ex_field_datum_io acpi_ex_access_region acpi_ev_address_space_dispatch acpi_ex_system_memory_space_handler acpi_os_map_cleanup.part.14 _synchronize_rcu_expedited.constprop.89 schedule The end result of frequent synchronize_rcu_expedited() invocation is tiny sub-millisecond spurts of execution where the scheduler freely migrates this apparently sleepy task. The overhead of frequent scheduler invocation multiplies the execution time by a factor of 2-3X." The source of this is that acpi_ex_system_memory_space_handler() unmaps the memory mapping currently cached by it at the access time if that mapping doesn't cover the memory area being accessed. Consequently, if there is a memory opregion with two fields separated from each other by an unused chunk of address space that is large enough for not being covered by a single mapping, and they happen to be used in an alternating pattern, the unmapping will occur on every acpi_ex_system_memory_space_handler() invocation for that memory opregion and that will lead to significant overhead. However, if the OS supports deferred unmapping of ACPI memory, such that the unused mappings will not be unmapped immediately, but collected for unmapping when directly requested later, acpi_ex_system_memory_space_handler() can be optimized to avoid the above issue. Namely, if ACPI_USE_DEFERRED_UNMAPPING is set for the given OS, it is expected to provide acpi_os_unmap_deferred(), for dropping references to memory mapping and queuing up the unused ones for later unmapping, and acpi_os_release_unused_mappings(), for the eventual unmapping of the unused mappings queued up earlier. Accordingly, if ACPI_USE_DEFERRED_UNMAPPING is set, acpi_ex_system_memory_space_handler() can use acpi_os_unmap_deferred() to unmap memory ranges mapped by it, so they are not unmapped right away, which addresses the issue described above, and the unused mappings queued up by it for removal can be unmapped later via acpi_os_release_unused_mappings(). Implement the ACPICA side of the described mechanism so as to avoid the RCU-related performance issues with memory opregions. Reported-by: Dan Williams Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/acinterp.h | 2 ++ drivers/acpi/acpica/dbtest.c | 2 ++ drivers/acpi/acpica/evrgnini.c | 5 +---- drivers/acpi/acpica/exregion.c | 29 +++++++++++++++++++++++++++-- drivers/acpi/acpica/exutils.c | 2 ++ drivers/acpi/acpica/utxface.c | 24 ++++++++++++++++++++++++ include/acpi/acpixf.h | 1 + 7 files changed, 59 insertions(+), 6 deletions(-) diff --git a/drivers/acpi/acpica/acinterp.h b/drivers/acpi/acpica/acinterp.h index a6d896cda2a5..1f1026fb06e9 100644 --- a/drivers/acpi/acpica/acinterp.h +++ b/drivers/acpi/acpica/acinterp.h @@ -479,6 +479,8 @@ void acpi_ex_pci_cls_to_string(char *dest, u8 class_code[3]); u8 acpi_is_valid_space_id(u8 space_id); +void acpi_ex_unmap_region_memory(struct acpi_mem_space_context *mem_info); + /* * exregion - default op_region handlers */ diff --git a/drivers/acpi/acpica/dbtest.c b/drivers/acpi/acpica/dbtest.c index 6db44a5ac786..a3d119bb2857 100644 --- a/drivers/acpi/acpica/dbtest.c +++ b/drivers/acpi/acpica/dbtest.c @@ -768,6 +768,8 @@ acpi_db_test_field_unit_type(union acpi_operand_object *obj_desc) acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); acpi_ut_release_mutex(ACPI_MTX_INTERPRETER); + acpi_release_unused_memory_mappings(); + bit_length = obj_desc->common_field.bit_length; byte_length = ACPI_ROUND_BITS_UP_TO_BYTES(bit_length); diff --git a/drivers/acpi/acpica/evrgnini.c b/drivers/acpi/acpica/evrgnini.c index aefc0145e583..9f33114a74ca 100644 --- a/drivers/acpi/acpica/evrgnini.c +++ b/drivers/acpi/acpica/evrgnini.c @@ -49,10 +49,7 @@ acpi_ev_system_memory_region_setup(acpi_handle handle, /* Delete a cached mapping if present */ if (local_region_context->mapped_length) { - acpi_os_unmap_memory(local_region_context-> - mapped_logical_address, - local_region_context-> - mapped_length); + acpi_ex_unmap_region_memory(local_region_context); } ACPI_FREE(local_region_context); *region_context = NULL; diff --git a/drivers/acpi/acpica/exregion.c b/drivers/acpi/acpica/exregion.c index d15a66de26c0..af777b7fccb0 100644 --- a/drivers/acpi/acpica/exregion.c +++ b/drivers/acpi/acpica/exregion.c @@ -14,6 +14,32 @@ #define _COMPONENT ACPI_EXECUTER ACPI_MODULE_NAME("exregion") +/***************************************************************************** + * + * FUNCTION: acpi_ex_unmap_region_memory + * + * PARAMETERS: mem_info - Region specific context + * + * RETURN: None + * + * DESCRIPTION: Unmap memory associated with a memory operation region. + * + ****************************************************************************/ +void acpi_ex_unmap_region_memory(struct acpi_mem_space_context *mem_info) +{ + ACPI_FUNCTION_TRACE(acpi_ex_unmap_region_memory); + +#ifdef ACPI_USE_DEFERRED_UNMAPPING + acpi_os_unmap_deferred(mem_info->mapped_logical_address, + mem_info->mapped_length); +#else + acpi_os_unmap_memory(mem_info->mapped_logical_address, + mem_info->mapped_length); +#endif + + return_VOID; +} + /******************************************************************************* * * FUNCTION: acpi_ex_system_memory_space_handler @@ -108,8 +134,7 @@ acpi_ex_system_memory_space_handler(u32 function, /* Valid mapping, delete it */ - acpi_os_unmap_memory(mem_info->mapped_logical_address, - mem_info->mapped_length); + acpi_ex_unmap_region_memory(mem_info); } /* diff --git a/drivers/acpi/acpica/exutils.c b/drivers/acpi/acpica/exutils.c index 8fefa6feac2f..9597baf33eb4 100644 --- a/drivers/acpi/acpica/exutils.c +++ b/drivers/acpi/acpica/exutils.c @@ -106,6 +106,8 @@ void acpi_ex_exit_interpreter(void) "Could not release AML Interpreter mutex")); } + acpi_release_unused_memory_mappings(); + return_VOID; } diff --git a/drivers/acpi/acpica/utxface.c b/drivers/acpi/acpica/utxface.c index ca7c9f0144ef..a70ac19a207b 100644 --- a/drivers/acpi/acpica/utxface.c +++ b/drivers/acpi/acpica/utxface.c @@ -244,6 +244,30 @@ acpi_status acpi_purge_cached_objects(void) ACPI_EXPORT_SYMBOL(acpi_purge_cached_objects) +/***************************************************************************** + * + * FUNCTION: acpi_release_unused_memory_mappings + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Remove memory mappings that are not used any more. + * + ****************************************************************************/ +void acpi_release_unused_memory_mappings(void) +{ + ACPI_FUNCTION_TRACE(acpi_release_unused_memory_mappings); + +#ifdef ACPI_USE_DEFERRED_UNMAPPING + acpi_os_release_unused_mappings(); +#endif + + return_VOID; +} + +ACPI_EXPORT_SYMBOL(acpi_release_unused_memory_mappings) + /***************************************************************************** * * FUNCTION: acpi_install_interface diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index 459d6981ca96..068ed92f5e28 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -449,6 +449,7 @@ ACPI_EXTERNAL_RETURN_STATUS(acpi_status acpi_size length, struct acpi_pld_info **return_buffer)) +ACPI_EXTERNAL_RETURN_VOID(void acpi_release_unused_memory_mappings(void)) /* * ACPI table load/unload interfaces From patchwork Mon Jun 22 13:53:40 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Rafael J. Wysocki" X-Patchwork-Id: 11617871 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 3815113A0 for ; Mon, 22 Jun 2020 14:03:25 +0000 (UTC) Received: from ml01.01.org (ml01.01.org [198.145.21.10]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 2047B2075A for ; Mon, 22 Jun 2020 14:03:25 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 2047B2075A Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=rjwysocki.net Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-nvdimm-bounces@lists.01.org Received: from ml01.vlan13.01.org (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id A219510FCBC5B; Mon, 22 Jun 2020 07:03:23 -0700 (PDT) Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=79.96.170.134; helo=cloudserver094114.home.pl; envelope-from=rjw@rjwysocki.net; receiver= Received: from cloudserver094114.home.pl (cloudserver094114.home.pl [79.96.170.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 664A310FC61BF for ; Mon, 22 Jun 2020 07:03:21 -0700 (PDT) Received: from 89-64-85-91.dynamic.chello.pl (89.64.85.91) (HELO kreacher.localnet) by serwer1319399.home.pl (79.96.170.134) with SMTP (IdeaSmtpServer 0.83.415) id b9bc4d710fe8cc24; Mon, 22 Jun 2020 16:03:19 +0200 From: "Rafael J. Wysocki" To: Dan Williams , Erik Kaneda Subject: [RFT][PATCH v2 2/4] ACPI: OSL: Add support for deferred unmapping of ACPI memory Date: Mon, 22 Jun 2020 15:53:40 +0200 Message-ID: <1821880.vZFEW4x2Ui@kreacher> In-Reply-To: <2713141.s8EVnczdoM@kreacher> References: <158889473309.2292982.18007035454673387731.stgit@dwillia2-desk3.amr.corp.intel.com> <2713141.s8EVnczdoM@kreacher> MIME-Version: 1.0 Message-ID-Hash: SJZX6FLTMLIQITIO5IRPN2QI5EQUJ2VX X-Message-ID-Hash: SJZX6FLTMLIQITIO5IRPN2QI5EQUJ2VX X-MailFrom: rjw@rjwysocki.net X-Mailman-Rule-Hits: nonmember-moderation X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation CC: rafael.j.wysocki@intel.com, Len Brown , Borislav Petkov , James Morse , Myron Stowe , Andy Shevchenko , linux-kernel@vger.kernel.org, linux-acpi@vger.kernel.org, linux-nvdimm@lists.01.org, Bob Moore X-Mailman-Version: 3.1.1 Precedence: list List-Id: "Linux-nvdimm developer list." Archived-At: List-Archive: List-Help: List-Post: List-Subscribe: List-Unsubscribe: From: "Rafael J. Wysocki" Implement acpi_os_unmap_deferred() and acpi_os_release_unused_mappings() and set ACPI_USE_DEFERRED_UNMAPPING to allow ACPICA to use deferred unmapping of memory in acpi_ex_system_memory_space_handler() so as to avoid RCU-related performance issues with memory opregions. Reported-by: Dan Williams Signed-off-by: Rafael J. Wysocki --- drivers/acpi/osl.c | 160 +++++++++++++++++++++++------- include/acpi/platform/aclinuxex.h | 4 + 2 files changed, 128 insertions(+), 36 deletions(-) diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 762c5d50b8fe..28863d908fa8 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -77,12 +77,16 @@ struct acpi_ioremap { void __iomem *virt; acpi_physical_address phys; acpi_size size; - unsigned long refcount; + union { + unsigned long refcount; + struct list_head gc; + } track; }; static LIST_HEAD(acpi_ioremaps); static DEFINE_MUTEX(acpi_ioremap_lock); #define acpi_ioremap_lock_held() lock_is_held(&acpi_ioremap_lock.dep_map) +static LIST_HEAD(unused_mappings); static void __init acpi_request_region (struct acpi_generic_address *gas, unsigned int length, char *desc) @@ -250,7 +254,7 @@ void __iomem *acpi_os_get_iomem(acpi_physical_address phys, unsigned int size) map = acpi_map_lookup(phys, size); if (map) { virt = map->virt + (phys - map->phys); - map->refcount++; + map->track.refcount++; } mutex_unlock(&acpi_ioremap_lock); return virt; @@ -335,7 +339,7 @@ void __iomem __ref /* Check if there's a suitable mapping already. */ map = acpi_map_lookup(phys, size); if (map) { - map->refcount++; + map->track.refcount++; goto out; } @@ -358,7 +362,7 @@ void __iomem __ref map->virt = virt; map->phys = pg_off; map->size = pg_sz; - map->refcount = 1; + map->track.refcount = 1; list_add_tail_rcu(&map->list, &acpi_ioremaps); @@ -375,40 +379,41 @@ void *__ref acpi_os_map_memory(acpi_physical_address phys, acpi_size size) EXPORT_SYMBOL_GPL(acpi_os_map_memory); /* Must be called with mutex_lock(&acpi_ioremap_lock) */ -static unsigned long acpi_os_drop_map_ref(struct acpi_ioremap *map) +static bool acpi_os_drop_map_ref(struct acpi_ioremap *map, bool defer) { - unsigned long refcount = --map->refcount; + if (--map->track.refcount) + return true; - if (!refcount) - list_del_rcu(&map->list); - return refcount; + list_del_rcu(&map->list); + + if (defer) { + INIT_LIST_HEAD(&map->track.gc); + list_add_tail(&map->track.gc, &unused_mappings); + return true; + } + + return false; } -static void acpi_os_map_cleanup(struct acpi_ioremap *map) +static void __acpi_os_map_cleanup(struct acpi_ioremap *map) { - synchronize_rcu_expedited(); acpi_unmap(map->phys, map->virt); kfree(map); } -/** - * acpi_os_unmap_iomem - Drop a memory mapping reference. - * @virt: Start of the address range to drop a reference to. - * @size: Size of the address range to drop a reference to. - * - * Look up the given virtual address range in the list of existing ACPI memory - * mappings, drop a reference to it and unmap it if there are no more active - * references to it. - * - * During early init (when acpi_permanent_mmap has not been set yet) this - * routine simply calls __acpi_unmap_table() to get the job done. Since - * __acpi_unmap_table() is an __init function, the __ref annotation is needed - * here. - */ -void __ref acpi_os_unmap_iomem(void __iomem *virt, acpi_size size) +static void acpi_os_map_cleanup(struct acpi_ioremap *map) +{ + if (!map) + return; + + synchronize_rcu_expedited(); + __acpi_os_map_cleanup(map); +} + +static void __ref __acpi_os_unmap_iomem(void __iomem *virt, acpi_size size, + bool defer) { struct acpi_ioremap *map; - unsigned long refcount; if (!acpi_permanent_mmap) { __acpi_unmap_table(virt, size); @@ -416,26 +421,102 @@ void __ref acpi_os_unmap_iomem(void __iomem *virt, acpi_size size) } mutex_lock(&acpi_ioremap_lock); + map = acpi_map_lookup_virt(virt, size); if (!map) { mutex_unlock(&acpi_ioremap_lock); WARN(true, PREFIX "%s: bad address %p\n", __func__, virt); return; } - refcount = acpi_os_drop_map_ref(map); + if (acpi_os_drop_map_ref(map, defer)) + map = NULL; + mutex_unlock(&acpi_ioremap_lock); - if (!refcount) - acpi_os_map_cleanup(map); + acpi_os_map_cleanup(map); +} + +/** + * acpi_os_unmap_iomem - Drop a memory mapping reference. + * @virt: Start of the address range to drop a reference to. + * @size: Size of the address range to drop a reference to. + * + * Look up the given virtual address range in the list of existing ACPI memory + * mappings, drop a reference to it and unmap it if there are no more active + * references to it. + * + * During early init (when acpi_permanent_mmap has not been set yet) this + * routine simply calls __acpi_unmap_table() to get the job done. Since + * __acpi_unmap_table() is an __init function, the __ref annotation is needed + * here. + */ +void __ref acpi_os_unmap_iomem(void __iomem *virt, acpi_size size) +{ + __acpi_os_unmap_iomem(virt, size, false); } EXPORT_SYMBOL_GPL(acpi_os_unmap_iomem); void __ref acpi_os_unmap_memory(void *virt, acpi_size size) { - return acpi_os_unmap_iomem((void __iomem *)virt, size); + acpi_os_unmap_iomem((void __iomem *)virt, size); } EXPORT_SYMBOL_GPL(acpi_os_unmap_memory); +/** + * acpi_os_unmap_deferred - Drop a memory mapping reference. + * @virt: Start of the address range to drop a reference to. + * @size: Size of the address range to drop a reference to. + * + * Look up the given virtual address range in the list of existing ACPI memory + * mappings, drop a reference to it and if there are no more active references + * to it, put it in the list of unused memory mappings. + * + * During early init (when acpi_permanent_mmap has not been set yet) this + * routine behaves like acpi_os_unmap_memory(). + */ +void __ref acpi_os_unmap_deferred(void *virt, acpi_size size) +{ + __acpi_os_unmap_iomem((void __iomem *)virt, size, true); +} + +/** + * acpi_os_release_unused_mappings - Release unused ACPI memory mappings. + */ +void acpi_os_release_unused_mappings(void) +{ + struct list_head list; + + INIT_LIST_HEAD(&list); + + /* + * First avoid looking at mappings that may be added to the "unused" + * list while the synchronize_rcu() below is running. + */ + mutex_lock(&acpi_ioremap_lock); + + list_splice_init(&unused_mappings, &list); + + mutex_unlock(&acpi_ioremap_lock); + + if (list_empty(&list)) + return; + + /* + * Wait for the possible users of the mappings in the "unused" list to + * stop using them. + */ + synchronize_rcu(); + + /* Release the unused mappings in the list. */ + while (!list_empty(&list)) { + struct acpi_ioremap *map; + + map = list_entry(list.next, struct acpi_ioremap, track.gc); + list_del(&map->track.gc); + __acpi_os_map_cleanup(map); + } +} + int acpi_os_map_generic_address(struct acpi_generic_address *gas) { u64 addr; @@ -461,7 +542,6 @@ void acpi_os_unmap_generic_address(struct acpi_generic_address *gas) { u64 addr; struct acpi_ioremap *map; - unsigned long refcount; if (gas->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) return; @@ -472,16 +552,18 @@ void acpi_os_unmap_generic_address(struct acpi_generic_address *gas) return; mutex_lock(&acpi_ioremap_lock); + map = acpi_map_lookup(addr, gas->bit_width / 8); if (!map) { mutex_unlock(&acpi_ioremap_lock); return; } - refcount = acpi_os_drop_map_ref(map); + if (acpi_os_drop_map_ref(map, false)) + map = NULL; + mutex_unlock(&acpi_ioremap_lock); - if (!refcount) - acpi_os_map_cleanup(map); + acpi_os_map_cleanup(map); } EXPORT_SYMBOL(acpi_os_unmap_generic_address); @@ -1566,11 +1648,17 @@ static acpi_status acpi_deactivate_mem_region(acpi_handle handle, u32 level, acpi_status acpi_release_memory(acpi_handle handle, struct resource *res, u32 level) { + acpi_status ret; + if (!(res->flags & IORESOURCE_MEM)) return AE_TYPE; - return acpi_walk_namespace(ACPI_TYPE_REGION, handle, level, + ret = acpi_walk_namespace(ACPI_TYPE_REGION, handle, level, acpi_deactivate_mem_region, NULL, res, NULL); + + acpi_os_release_unused_mappings(); + + return ret; } EXPORT_SYMBOL_GPL(acpi_release_memory); diff --git a/include/acpi/platform/aclinuxex.h b/include/acpi/platform/aclinuxex.h index 04f88f2de781..e13f364d6c69 100644 --- a/include/acpi/platform/aclinuxex.h +++ b/include/acpi/platform/aclinuxex.h @@ -138,6 +138,10 @@ static inline void acpi_os_terminate_debugger(void) /* * OSL interfaces added by Linux */ +void acpi_os_unmap_deferred(void *virt, acpi_size size); +void acpi_os_release_unused_mappings(void); + +#define ACPI_USE_DEFERRED_UNMAPPING #endif /* __KERNEL__ */ From patchwork Mon Jun 22 14:01:55 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Rafael J. Wysocki" X-Patchwork-Id: 11617865 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 3CC07161F for ; Mon, 22 Jun 2020 14:03:23 +0000 (UTC) Received: from ml01.01.org (ml01.01.org [198.145.21.10]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 259F8206E2 for ; Mon, 22 Jun 2020 14:03:23 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 259F8206E2 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=rjwysocki.net Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-nvdimm-bounces@lists.01.org Received: from ml01.vlan13.01.org (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 8CEAF10FCB710; Mon, 22 Jun 2020 07:03:22 -0700 (PDT) Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=79.96.170.134; helo=cloudserver094114.home.pl; envelope-from=rjw@rjwysocki.net; receiver= Received: from cloudserver094114.home.pl (cloudserver094114.home.pl [79.96.170.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id CDBB310FC729B for ; Mon, 22 Jun 2020 07:03:19 -0700 (PDT) Received: from 89-64-85-91.dynamic.chello.pl (89.64.85.91) (HELO kreacher.localnet) by serwer1319399.home.pl (79.96.170.134) with SMTP (IdeaSmtpServer 0.83.415) id 053a9db2a1335a90; Mon, 22 Jun 2020 16:03:17 +0200 From: "Rafael J. Wysocki" To: Dan Williams , Erik Kaneda Subject: [RFT][PATCH v2 3/4] ACPICA: Preserve memory opregion mappings if supported by OS Date: Mon, 22 Jun 2020 16:01:55 +0200 Message-ID: <13749323.0m2ImmhSHx@kreacher> In-Reply-To: <2713141.s8EVnczdoM@kreacher> References: <158889473309.2292982.18007035454673387731.stgit@dwillia2-desk3.amr.corp.intel.com> <2713141.s8EVnczdoM@kreacher> MIME-Version: 1.0 Message-ID-Hash: LMYATE65NJSNLT7SO5OFU57MAFZEUXZT X-Message-ID-Hash: LMYATE65NJSNLT7SO5OFU57MAFZEUXZT X-MailFrom: rjw@rjwysocki.net X-Mailman-Rule-Hits: nonmember-moderation X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation CC: rafael.j.wysocki@intel.com, Len Brown , Borislav Petkov , James Morse , Myron Stowe , Andy Shevchenko , linux-kernel@vger.kernel.org, linux-acpi@vger.kernel.org, linux-nvdimm@lists.01.org, Bob Moore X-Mailman-Version: 3.1.1 Precedence: list List-Id: "Linux-nvdimm developer list." Archived-At: List-Archive: List-Help: List-Post: List-Subscribe: List-Unsubscribe: From: "Rafael J. Wysocki" The ACPICA's strategy with respect to the handling of memory mappings associated with memory operation regions is to avoid mapping the entire region at once which may be problematic at least in principle (for example, it may lead to conflicts with overlapping mappings having different attributes created by drivers). It may also be wasteful, because memory opregions on some systems take up vast chunks of address space while the fields in those regions actually accessed by AML are sparsely distributed. For this reason, a one-page "window" is mapped for a given opregion on the first memory access through it and if that "window" does not cover an address range accessed through that opregion subsequently, it is unmapped and a new "window" is mapped to replace it. Next, if the new "window" is not sufficient to access memory through the opregion in question in the future, it will be replaced with yet another "window" and so on. That may lead to a suboptimal sequence of memory mapping and unmapping operations, for example if two fields in one opregion separated from each other by a sufficiently wide chunk of unused address space are accessed in an alternating pattern. The situation may still be suboptimal if the deferred unmapping introduced previously is supported by the OS layer. For instance, the alternating memory access pattern mentioned above may produce a relatively long list of mappings to release with substantial duplication among the entries in it, which could be avoided if acpi_ex_system_memory_space_handler() did not release the mapping used by it previously as soon as the current access was not covered by it. In order to improve that, modify acpi_ex_system_memory_space_handler() to take advantage of the memory mappings reference counting at the OS level if a suitable interface is provided. Namely, if ACPI_USE_FAST_PATH_MAPPING is set, the OS is expected to implement acpi_os_map_memory_fast_path() that will return NULL if there is no mapping covering the given address range known to it. If such a mapping is there, however, its reference counter will be incremented and a pointer representing the requested virtual address will be returned right away without any additional consequences. That allows acpi_ex_system_memory_space_handler() to acquire additional references to all new memory mappings with the help of acpi_os_map_memory_fast_path() so as to retain them until the memory opregions associated with them go away. The function will still use a new "window" mapping if the current one does not cover the address range at hand, but it will avoid unmapping the current one right away by adding it to a list of "known" mappings associated with the given memory opregion which will be deleted at the opregion deactivation time. The mappings in that list can be used every time a "new window" is needed so as to avoid overhead related to the mapping and unmapping of memory. Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/acinterp.h | 4 + drivers/acpi/acpica/evrgnini.c | 7 +- drivers/acpi/acpica/exregion.c | 159 ++++++++++++++++++++++++++++++++- 3 files changed, 162 insertions(+), 8 deletions(-) diff --git a/drivers/acpi/acpica/acinterp.h b/drivers/acpi/acpica/acinterp.h index 1f1026fb06e9..db9c279baa2e 100644 --- a/drivers/acpi/acpica/acinterp.h +++ b/drivers/acpi/acpica/acinterp.h @@ -479,8 +479,12 @@ void acpi_ex_pci_cls_to_string(char *dest, u8 class_code[3]); u8 acpi_is_valid_space_id(u8 space_id); +struct acpi_mem_space_context *acpi_ex_alloc_mem_space_context(void); + void acpi_ex_unmap_region_memory(struct acpi_mem_space_context *mem_info); +void acpi_ex_unmap_all_region_mappings(struct acpi_mem_space_context *mem_info); + /* * exregion - default op_region handlers */ diff --git a/drivers/acpi/acpica/evrgnini.c b/drivers/acpi/acpica/evrgnini.c index 9f33114a74ca..f6c5feea10bc 100644 --- a/drivers/acpi/acpica/evrgnini.c +++ b/drivers/acpi/acpica/evrgnini.c @@ -46,10 +46,10 @@ acpi_ev_system_memory_region_setup(acpi_handle handle, local_region_context = (struct acpi_mem_space_context *)*region_context; - /* Delete a cached mapping if present */ + /* Delete memory mappings if present */ if (local_region_context->mapped_length) { - acpi_ex_unmap_region_memory(local_region_context); + acpi_ex_unmap_all_region_mappings(local_region_context); } ACPI_FREE(local_region_context); *region_context = NULL; @@ -59,8 +59,7 @@ acpi_ev_system_memory_region_setup(acpi_handle handle, /* Create a new context */ - local_region_context = - ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_mem_space_context)); + local_region_context = acpi_ex_alloc_mem_space_context(); if (!(local_region_context)) { return_ACPI_STATUS(AE_NO_MEMORY); } diff --git a/drivers/acpi/acpica/exregion.c b/drivers/acpi/acpica/exregion.c index af777b7fccb0..9d97b6a67074 100644 --- a/drivers/acpi/acpica/exregion.c +++ b/drivers/acpi/acpica/exregion.c @@ -14,6 +14,40 @@ #define _COMPONENT ACPI_EXECUTER ACPI_MODULE_NAME("exregion") +struct acpi_mem_mapping { + acpi_physical_address physical_address; + u8 *logical_address; + acpi_size length; + struct acpi_mem_mapping *next_mm; +}; + +struct acpi_mm_context { + struct acpi_mem_space_context mem_info; + struct acpi_mem_mapping *first_mm; +}; + +/***************************************************************************** + * + * FUNCTION: acpi_ex_alloc_mem_space_context + * + * PARAMETERS: None + * + * RETURN: Pointer to a new region context object. + * + * DESCRIPTION: Allocate memory for memory operation region representation. + * + ****************************************************************************/ +struct acpi_mem_space_context *acpi_ex_alloc_mem_space_context(void) +{ + ACPI_FUNCTION_TRACE(acpi_ex_alloc_mem_space_context); + +#ifdef ACPI_USE_FAST_PATH_MAPPING + return ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_mm_context)); +#else + return ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_mem_space_context)); +#endif +} + /***************************************************************************** * * FUNCTION: acpi_ex_unmap_region_memory @@ -40,6 +74,44 @@ void acpi_ex_unmap_region_memory(struct acpi_mem_space_context *mem_info) return_VOID; } +/***************************************************************************** + * + * FUNCTION: acpi_ex_unmap_all_region_mappings + * + * PARAMETERS: mem_info - Region specific context + * + * RETURN: None + * + * DESCRIPTION: Unmap all mappings associated with a memory operation region. + * + ****************************************************************************/ +void acpi_ex_unmap_all_region_mappings(struct acpi_mem_space_context *mem_info) +{ +#ifdef ACPI_USE_FAST_PATH_MAPPING + struct acpi_mm_context *mm_context = (struct acpi_mm_context *)mem_info; + struct acpi_mem_mapping *mm; +#endif + + ACPI_FUNCTION_TRACE(acpi_ex_unmap_all_region_mappings); + + acpi_ex_unmap_region_memory(mem_info); + +#ifdef ACPI_USE_FAST_PATH_MAPPING + while (mm_context->first_mm) { + mm = mm_context->first_mm; + mm_context->first_mm = mm->next_mm; +#ifdef ACPI_USE_DEFERRED_UNMAPPING + acpi_os_unmap_deferred(mm->logical_address, mm->length); +#else + acpi_os_unmap_memory(mm->logical_address, mm->length); +#endif + ACPI_FREE(mm); + } +#endif /* ACPI_USE_FAST_PATH_MAPPING */ + + return_VOID; +} + /******************************************************************************* * * FUNCTION: acpi_ex_system_memory_space_handler @@ -70,6 +142,10 @@ acpi_ex_system_memory_space_handler(u32 function, u32 length; acpi_size map_length; acpi_size page_boundary_map_length; +#ifdef ACPI_USE_FAST_PATH_MAPPING + struct acpi_mm_context *mm_context = (struct acpi_mm_context *)mem_info; + struct acpi_mem_mapping *mm; +#endif #ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED u32 remainder; #endif @@ -128,7 +204,7 @@ acpi_ex_system_memory_space_handler(u32 function, mem_info->mapped_length))) { /* * The request cannot be resolved by the current memory mapping; - * Delete the existing mapping and create a new one. + * Delete the current cached mapping and get a new one. */ if (mem_info->mapped_length) { @@ -137,6 +213,36 @@ acpi_ex_system_memory_space_handler(u32 function, acpi_ex_unmap_region_memory(mem_info); } +#ifdef ACPI_USE_FAST_PATH_MAPPING + /* + * Look for an existing saved mapping matching the address range + * at hand. If found, make the OS layer bump up the reference + * counter of that mapping, cache it and carry out the access. + */ + for (mm = mm_context->first_mm; mm; mm = mm->next_mm) { + if (address < mm->physical_address) + continue; + + if ((u64)address + length > + (u64)mm->physical_address + mm->length) + continue; + + /* + * When called on a known-existing memory mapping, + * acpi_os_map_memory_fast_path() must return the same + * logical address as before or NULL. + */ + if (!acpi_os_map_memory_fast_path(mm->physical_address, + mm->length)) + continue; + + mem_info->mapped_logical_address = mm->logical_address; + mem_info->mapped_physical_address = mm->physical_address; + mem_info->mapped_length = mm->length; + goto access; + } +#endif /* ACPI_USE_FAST_PATH_MAPPING */ + /* * October 2009: Attempt to map from the requested address to the * end of the region. However, we will never map more than one @@ -168,9 +274,8 @@ acpi_ex_system_memory_space_handler(u32 function, /* Create a new mapping starting at the address given */ - mem_info->mapped_logical_address = - acpi_os_map_memory(address, map_length); - if (!mem_info->mapped_logical_address) { + logical_addr_ptr = acpi_os_map_memory(address, map_length); + if (!logical_addr_ptr) { ACPI_ERROR((AE_INFO, "Could not map memory at 0x%8.8X%8.8X, size %u", ACPI_FORMAT_UINT64(address), @@ -181,10 +286,56 @@ acpi_ex_system_memory_space_handler(u32 function, /* Save the physical address and mapping size */ + mem_info->mapped_logical_address = logical_addr_ptr; mem_info->mapped_physical_address = address; mem_info->mapped_length = map_length; + +#ifdef ACPI_USE_FAST_PATH_MAPPING + /* + * Create a new mm list entry to save the new mapping for + * removal at the operation region deactivation time. + */ + mm = ACPI_ALLOCATE_ZEROED(sizeof(*mm)); + if (!mm) { + /* + * No room to save the new mapping, but this is not + * critical. Just log the error and carry out the + * access as requested. + */ + ACPI_ERROR((AE_INFO, + "Not enough memory to save memory mapping at 0x%8.8X%8.8X, size %u", + ACPI_FORMAT_UINT64(address), + (u32)map_length)); + goto access; + } + /* + * Bump up the new mapping's reference counter in the OS layer + * to prevent it from getting dropped prematurely. + */ + if (!acpi_os_map_memory_fast_path(address, map_length)) { + /* + * Something has gone wrong, but this is not critical. + * Log the error, free the mm list entry that won't be + * used and carry out the access as requested. + */ + ACPI_ERROR((AE_INFO, + "Unable to save memory mapping at 0x%8.8X%8.8X, size %u", + ACPI_FORMAT_UINT64(address), + (u32)map_length)); + ACPI_FREE(mm); + goto access; + } + mm->physical_address = address; + mm->logical_address = logical_addr_ptr; + mm->length = map_length; + mm->next_mm = mm_context->first_mm; + mm_context->first_mm = mm; } +access: +#else /* !ACPI_USE_FAST_PATH_MAPPING */ + } +#endif /* !ACPI_USE_FAST_PATH_MAPPING */ /* * Generate a logical pointer corresponding to the address we want to * access From patchwork Fri Jun 26 17:33:53 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Rafael J. Wysocki" X-Patchwork-Id: 11628111 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D64A3912 for ; Fri, 26 Jun 2020 17:34:16 +0000 (UTC) Received: from ml01.01.org (ml01.01.org [198.145.21.10]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id AD98220707 for ; Fri, 26 Jun 2020 17:34:16 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org AD98220707 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=rjwysocki.net Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-nvdimm-bounces@lists.01.org Received: from ml01.vlan13.01.org (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 8038611001ABE; Fri, 26 Jun 2020 10:34:16 -0700 (PDT) Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=79.96.170.134; helo=cloudserver094114.home.pl; envelope-from=rjw@rjwysocki.net; receiver= Received: from cloudserver094114.home.pl (cloudserver094114.home.pl [79.96.170.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id B8DD010FE3541 for ; Fri, 26 Jun 2020 10:34:13 -0700 (PDT) Received: from 89-64-83-223.dynamic.chello.pl (89.64.83.223) (HELO kreacher.localnet) by serwer1319399.home.pl (79.96.170.134) with SMTP (IdeaSmtpServer 0.83.415) id 69d62dc03bd9ee5c; Fri, 26 Jun 2020 19:34:10 +0200 From: "Rafael J. Wysocki" To: Dan Williams , Erik Kaneda Subject: [RFT][PATCH v3 4/4] ACPI: OSL: Implement acpi_os_map_memory_fast_path() Date: Fri, 26 Jun 2020 19:33:53 +0200 Message-ID: <14649052.BMOpmyQVCI@kreacher> In-Reply-To: <2788992.3K7huLjdjL@kreacher> References: <158889473309.2292982.18007035454673387731.stgit@dwillia2-desk3.amr.corp.intel.com> <2713141.s8EVnczdoM@kreacher> <2788992.3K7huLjdjL@kreacher> MIME-Version: 1.0 Message-ID-Hash: CCXVYPHRLVRLM3DCRBAXWJ636JFK36QT X-Message-ID-Hash: CCXVYPHRLVRLM3DCRBAXWJ636JFK36QT X-MailFrom: rjw@rjwysocki.net X-Mailman-Rule-Hits: nonmember-moderation X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation CC: rafael.j.wysocki@intel.com, Len Brown , Borislav Petkov , James Morse , Myron Stowe , Andy Shevchenko , linux-kernel@vger.kernel.org, linux-acpi@vger.kernel.org, linux-nvdimm@lists.01.org, Bob Moore X-Mailman-Version: 3.1.1 Precedence: list List-Id: "Linux-nvdimm developer list." Archived-At: List-Archive: List-Help: List-Post: List-Subscribe: List-Unsubscribe: From: "Rafael J. Wysocki" Add acpi_os_map_memory_fast_path() and set ACPI_USE_FAST_PATH_MAPPING to allow acpi_ex_system_memory_space_handler() to avoid unnecessary memory mapping and unmapping overhead by retaining all memory mappings created by it until the memory opregions associated with them go away. Signed-off-by: Rafael J. Wysocki --- drivers/acpi/osl.c | 65 +++++++++++++++++++++++-------- include/acpi/platform/aclinux.h | 4 ++ include/acpi/platform/aclinuxex.h | 3 ++ 3 files changed, 56 insertions(+), 16 deletions(-) diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 749ae3e32193..b8537ce89ea2 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -306,21 +306,8 @@ static void acpi_unmap(acpi_physical_address pg_off, void __iomem *vaddr) iounmap(vaddr); } -/** - * 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. - * - * 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 - * virtual address). If not found, map it, add it to that list and return a - * pointer to it. - * - * 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 fast_path) { struct acpi_ioremap *map; void __iomem *virt; @@ -332,8 +319,12 @@ void __iomem __ref return NULL; } - if (!acpi_permanent_mmap) + if (!acpi_permanent_mmap) { + if (WARN_ON(fast_path)) + return NULL; + return __acpi_map_table((unsigned long)phys, size); + } mutex_lock(&acpi_ioremap_lock); /* Check if there's a suitable mapping already. */ @@ -343,6 +334,11 @@ void __iomem __ref goto out; } + if (fast_path) { + mutex_unlock(&acpi_ioremap_lock); + return NULL; + } + map = kzalloc(sizeof(*map), GFP_KERNEL); if (!map) { mutex_unlock(&acpi_ioremap_lock); @@ -370,6 +366,25 @@ void __iomem __ref mutex_unlock(&acpi_ioremap_lock); return map->virt + (phys - map->phys); } + +/** + * 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. + * + * 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 representing + * its virtual address. If not found, map it, add it to that list and return a + * pointer representing its virtual address. + * + * During early init (when acpi_permanent_mmap has not been set yet) call + * __acpi_map_table() to obtain the mapping. + */ +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) @@ -378,6 +393,24 @@ void *__ref acpi_os_map_memory(acpi_physical_address phys, acpi_size size) } EXPORT_SYMBOL_GPL(acpi_os_map_memory); +/** + * acpi_os_map_memory_fast_path - Fast-path physical-to-virtual address mapping. + * @phys: Start of the physical address range to map. + * @size: Size of the physical address range to map. + * + * 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 representing + * its virtual address. If not found, return NULL. + * + * During early init (when acpi_permanent_mmap has not been set yet) log a + * warning and return NULL. + */ +void __ref *acpi_os_map_memory_fast_path(acpi_physical_address phys, + acpi_size size) +{ + return __acpi_os_map_iomem(phys, size, true); +} + /* Must be called with mutex_lock(&acpi_ioremap_lock) */ static bool acpi_os_drop_map_ref(struct acpi_ioremap *map, bool defer) { diff --git a/include/acpi/platform/aclinux.h b/include/acpi/platform/aclinux.h index 784e294dc74c..1a5f8037e3d5 100644 --- a/include/acpi/platform/aclinux.h +++ b/include/acpi/platform/aclinux.h @@ -118,6 +118,10 @@ #define USE_NATIVE_ALLOCATE_ZEROED +/* Use fast-path memory mapping to optimize memory opregions handling */ + +#define ACPI_USE_FAST_PATH_MAPPING + /* * Overrides for in-kernel ACPICA */ diff --git a/include/acpi/platform/aclinuxex.h b/include/acpi/platform/aclinuxex.h index ad6b905358c5..c64b836ba455 100644 --- a/include/acpi/platform/aclinuxex.h +++ b/include/acpi/platform/aclinuxex.h @@ -141,6 +141,9 @@ static inline void acpi_os_terminate_debugger(void) * OSL interfaces added by Linux */ +void *acpi_os_map_memory_fast_path(acpi_physical_address where, + acpi_size length); + #endif /* __KERNEL__ */ #endif /* __ACLINUXEX_H__ */