All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Rafael J. Wysocki" <rjw@rjwysocki.net>
To: Dan Williams <dan.j.williams@intel.com>,
	Erik Kaneda <erik.kaneda@intel.com>
Cc: rafael.j.wysocki@intel.com, Len Brown <lenb@kernel.org>,
	Borislav Petkov <bp@alien8.de>, James Morse <james.morse@arm.com>,
	Myron Stowe <myron.stowe@redhat.com>,
	Andy Shevchenko <andriy.shevchenko@linux.intel.com>,
	linux-kernel@vger.kernel.org, linux-acpi@vger.kernel.org,
	linux-nvdimm@lists.01.org, Bob Moore <robert.moore@intel.com>
Subject: [RFT][PATCH v3 2/4] ACPI: OSL: Implement deferred unmapping of ACPI memory
Date: Fri, 26 Jun 2020 19:31:24 +0200	[thread overview]
Message-ID: <4507864.RZ40Oy75i1@kreacher> (raw)
In-Reply-To: <2788992.3K7huLjdjL@kreacher>

From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>

Rework acpi_os_unmap_memory() so that it does not release the memory
mapping matching the given address range right away but queues it
up for later removal, implement acpi_os_release_unused_mappings()
that will remove the unused ACPI memory mappings and add invocations
of it to acpi_release_memory() and to the table loading/unloading
code, to get rid of memory mappings that may be left behind.

Reported-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/acpi_configfs.c      |   3 +
 drivers/acpi/osl.c                | 153 +++++++++++++++++++++++-------
 drivers/acpi/tables.c             |   2 +
 include/acpi/platform/aclinux.h   |   1 +
 include/acpi/platform/aclinuxex.h |   2 +
 5 files changed, 125 insertions(+), 36 deletions(-)

diff --git a/drivers/acpi/acpi_configfs.c b/drivers/acpi/acpi_configfs.c
index ece8c1a921cc..dd167ff87dc4 100644
--- a/drivers/acpi/acpi_configfs.c
+++ b/drivers/acpi/acpi_configfs.c
@@ -59,6 +59,8 @@ static ssize_t acpi_table_aml_write(struct config_item *cfg,
 		table->header = NULL;
 	}
 
+	acpi_os_release_unused_mappings();
+
 	return ret;
 }
 
@@ -224,6 +226,7 @@ static void acpi_table_drop_item(struct config_group *group,
 
 	ACPI_INFO(("Host-directed Dynamic ACPI Table Unload"));
 	acpi_unload_table(table->index);
+	acpi_os_release_unused_mappings();
 }
 
 static struct configfs_group_operations acpi_table_group_ops = {
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 762c5d50b8fe..749ae3e32193 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,39 @@ 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 defer;
 }
 
-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 +419,97 @@ 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);
 
+/**
+ * acpi_os_unmap_memory - 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_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, true);
 }
 EXPORT_SYMBOL_GPL(acpi_os_unmap_memory);
 
+/**
+ * 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. */
+	do {
+		struct acpi_ioremap *map;
+
+		map = list_entry(list.next, struct acpi_ioremap, track.gc);
+		list_del(&map->track.gc);
+		__acpi_os_map_cleanup(map);
+	} while (!list_empty(&list));
+}
+
 int acpi_os_map_generic_address(struct acpi_generic_address *gas)
 {
 	u64 addr;
@@ -461,7 +535,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 +545,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 +1641,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/drivers/acpi/tables.c b/drivers/acpi/tables.c
index 0e905c3d1645..939484a860a1 100644
--- a/drivers/acpi/tables.c
+++ b/drivers/acpi/tables.c
@@ -816,6 +816,8 @@ int __init acpi_table_init(void)
 		return -EINVAL;
 	acpi_table_initrd_scan();
 
+	acpi_os_release_unused_mappings();
+
 	check_multiple_madt();
 	return 0;
 }
diff --git a/include/acpi/platform/aclinux.h b/include/acpi/platform/aclinux.h
index 987e2af7c335..784e294dc74c 100644
--- a/include/acpi/platform/aclinux.h
+++ b/include/acpi/platform/aclinux.h
@@ -133,6 +133,7 @@
 #define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_delete_raw_lock
 #define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_acquire_raw_lock
 #define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_release_raw_lock
+#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_release_unused_mappings
 
 /*
  * OSL interfaces used by debugger/disassembler
diff --git a/include/acpi/platform/aclinuxex.h b/include/acpi/platform/aclinuxex.h
index 04f88f2de781..ad6b905358c5 100644
--- a/include/acpi/platform/aclinuxex.h
+++ b/include/acpi/platform/aclinuxex.h
@@ -120,6 +120,8 @@ static inline void acpi_os_delete_raw_lock(acpi_raw_spinlock handle)
 	ACPI_FREE(handle);
 }
 
+void acpi_os_release_unused_mappings(void);
+
 static inline u8 acpi_os_readable(void *pointer, acpi_size length)
 {
 	return TRUE;
-- 
2.26.2



_______________________________________________
Linux-nvdimm mailing list -- linux-nvdimm@lists.01.org
To unsubscribe send an email to linux-nvdimm-leave@lists.01.org

WARNING: multiple messages have this Message-ID (diff)
From: "Rafael J. Wysocki" <rjw@rjwysocki.net>
To: Dan Williams <dan.j.williams@intel.com>,
	Erik Kaneda <erik.kaneda@intel.com>
Cc: rafael.j.wysocki@intel.com, Len Brown <lenb@kernel.org>,
	Borislav Petkov <bp@alien8.de>, Ira Weiny <ira.weiny@intel.com>,
	James Morse <james.morse@arm.com>,
	Myron Stowe <myron.stowe@redhat.com>,
	Andy Shevchenko <andriy.shevchenko@linux.intel.com>,
	linux-kernel@vger.kernel.org, linux-acpi@vger.kernel.org,
	linux-nvdimm@lists.01.org, Bob Moore <robert.moore@intel.com>
Subject: [RFT][PATCH v3 2/4] ACPI: OSL: Implement deferred unmapping of ACPI memory
Date: Fri, 26 Jun 2020 19:31:24 +0200	[thread overview]
Message-ID: <4507864.RZ40Oy75i1@kreacher> (raw)
In-Reply-To: <2788992.3K7huLjdjL@kreacher>

From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>

Rework acpi_os_unmap_memory() so that it does not release the memory
mapping matching the given address range right away but queues it
up for later removal, implement acpi_os_release_unused_mappings()
that will remove the unused ACPI memory mappings and add invocations
of it to acpi_release_memory() and to the table loading/unloading
code, to get rid of memory mappings that may be left behind.

Reported-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/acpi_configfs.c      |   3 +
 drivers/acpi/osl.c                | 153 +++++++++++++++++++++++-------
 drivers/acpi/tables.c             |   2 +
 include/acpi/platform/aclinux.h   |   1 +
 include/acpi/platform/aclinuxex.h |   2 +
 5 files changed, 125 insertions(+), 36 deletions(-)

diff --git a/drivers/acpi/acpi_configfs.c b/drivers/acpi/acpi_configfs.c
index ece8c1a921cc..dd167ff87dc4 100644
--- a/drivers/acpi/acpi_configfs.c
+++ b/drivers/acpi/acpi_configfs.c
@@ -59,6 +59,8 @@ static ssize_t acpi_table_aml_write(struct config_item *cfg,
 		table->header = NULL;
 	}
 
+	acpi_os_release_unused_mappings();
+
 	return ret;
 }
 
@@ -224,6 +226,7 @@ static void acpi_table_drop_item(struct config_group *group,
 
 	ACPI_INFO(("Host-directed Dynamic ACPI Table Unload"));
 	acpi_unload_table(table->index);
+	acpi_os_release_unused_mappings();
 }
 
 static struct configfs_group_operations acpi_table_group_ops = {
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 762c5d50b8fe..749ae3e32193 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,39 @@ 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 defer;
 }
 
-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 +419,97 @@ 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);
 
+/**
+ * acpi_os_unmap_memory - 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_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, true);
 }
 EXPORT_SYMBOL_GPL(acpi_os_unmap_memory);
 
+/**
+ * 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. */
+	do {
+		struct acpi_ioremap *map;
+
+		map = list_entry(list.next, struct acpi_ioremap, track.gc);
+		list_del(&map->track.gc);
+		__acpi_os_map_cleanup(map);
+	} while (!list_empty(&list));
+}
+
 int acpi_os_map_generic_address(struct acpi_generic_address *gas)
 {
 	u64 addr;
@@ -461,7 +535,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 +545,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 +1641,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/drivers/acpi/tables.c b/drivers/acpi/tables.c
index 0e905c3d1645..939484a860a1 100644
--- a/drivers/acpi/tables.c
+++ b/drivers/acpi/tables.c
@@ -816,6 +816,8 @@ int __init acpi_table_init(void)
 		return -EINVAL;
 	acpi_table_initrd_scan();
 
+	acpi_os_release_unused_mappings();
+
 	check_multiple_madt();
 	return 0;
 }
diff --git a/include/acpi/platform/aclinux.h b/include/acpi/platform/aclinux.h
index 987e2af7c335..784e294dc74c 100644
--- a/include/acpi/platform/aclinux.h
+++ b/include/acpi/platform/aclinux.h
@@ -133,6 +133,7 @@
 #define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_delete_raw_lock
 #define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_acquire_raw_lock
 #define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_release_raw_lock
+#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_release_unused_mappings
 
 /*
  * OSL interfaces used by debugger/disassembler
diff --git a/include/acpi/platform/aclinuxex.h b/include/acpi/platform/aclinuxex.h
index 04f88f2de781..ad6b905358c5 100644
--- a/include/acpi/platform/aclinuxex.h
+++ b/include/acpi/platform/aclinuxex.h
@@ -120,6 +120,8 @@ static inline void acpi_os_delete_raw_lock(acpi_raw_spinlock handle)
 	ACPI_FREE(handle);
 }
 
+void acpi_os_release_unused_mappings(void);
+
 static inline u8 acpi_os_readable(void *pointer, acpi_size length)
 {
 	return TRUE;
-- 
2.26.2





  parent reply	other threads:[~2020-06-26 17:34 UTC|newest]

Thread overview: 107+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-05-07 23:39 [PATCH v2] ACPI: Drop rcu usage for MMIO mappings Dan Williams
2020-05-07 23:39 ` Dan Williams
2020-05-09 12:30 ` Sasha Levin
2020-05-13  8:52 ` [ACPI] 5a91d41f89: BUG:sleeping_function_called_from_invalid_context_at_kernel/locking/mutex.c kernel test robot
2020-05-13  8:52   ` kernel test robot
2020-05-13  8:52   ` kernel test robot
2020-06-05 13:32 ` [PATCH v2] ACPI: Drop rcu usage for MMIO mappings Rafael J. Wysocki
2020-06-05 13:32   ` Rafael J. Wysocki
2020-06-05 16:18   ` Dan Williams
2020-06-05 16:18     ` Dan Williams
2020-06-05 16:21     ` Rafael J. Wysocki
2020-06-05 16:21       ` Rafael J. Wysocki
2020-06-05 16:39       ` Dan Williams
2020-06-05 16:39         ` Dan Williams
2020-06-05 17:02         ` Rafael J. Wysocki
2020-06-05 17:02           ` Rafael J. Wysocki
2020-06-05 14:06 ` [RFT][PATCH] ACPI: OSL: Use rwlock instead of RCU for memory management Rafael J. Wysocki
2020-06-05 14:06   ` Rafael J. Wysocki
2020-06-05 17:08   ` Dan Williams
2020-06-05 17:08     ` Dan Williams
2020-06-06  6:56     ` Rafael J. Wysocki
2020-06-06  6:56       ` Rafael J. Wysocki
2020-06-08 15:33       ` Rafael J. Wysocki
2020-06-08 15:33         ` Rafael J. Wysocki
2020-06-08 16:29         ` Rafael J. Wysocki
2020-06-08 16:29           ` Rafael J. Wysocki
2020-06-05 19:40   ` Andy Shevchenko
2020-06-05 19:40     ` Andy Shevchenko
2020-06-06  6:48     ` Rafael J. Wysocki
2020-06-06  6:48       ` Rafael J. Wysocki
2020-06-10 12:17 ` [RFT][PATCH 0/3] ACPI: ACPICA / OSL: Avoid unmapping ACPI memory inside of the AML interpreter Rafael J. Wysocki
2020-06-10 12:17   ` Rafael J. Wysocki
2020-06-10 12:20   ` [RFT][PATCH 1/3] ACPICA: Defer unmapping of memory used in memory opregions Rafael J. Wysocki
2020-06-10 12:20     ` Rafael J. Wysocki
2020-06-10 12:21   ` [RFT][PATCH 2/3] ACPICA: Remove unused memory mappings on interpreter exit Rafael J. Wysocki
2020-06-10 12:21     ` Rafael J. Wysocki
2020-06-12  0:12     ` Kaneda, Erik
2020-06-12  0:12       ` Kaneda, Erik
2020-06-12 12:05       ` Rafael J. Wysocki
2020-06-12 12:05         ` Rafael J. Wysocki
2020-06-13 19:28         ` Rafael J. Wysocki
2020-06-13 19:28           ` Rafael J. Wysocki
2020-06-15 19:06           ` Dan Williams
2020-06-15 19:06             ` Dan Williams
2020-06-10 12:22   ` [RFT][PATCH 3/3] ACPI: OSL: Define ACPI_OS_MAP_MEMORY_FAST_PATH() Rafael J. Wysocki
2020-06-10 12:22     ` Rafael J. Wysocki
2020-06-13 19:19   ` [RFT][PATCH 0/3] ACPI: ACPICA / OSL: Avoid unmapping ACPI memory inside of the AML interpreter Rafael J. Wysocki
2020-06-13 19:19     ` Rafael J. Wysocki
2020-06-22 13:50 ` [RFT][PATCH v2 0/4] " Rafael J. Wysocki
2020-06-22 13:50   ` Rafael J. Wysocki
2020-06-22 13:52   ` [RFT][PATCH v2 1/4] ACPICA: Defer unmapping of opregion memory if supported by OS Rafael J. Wysocki
2020-06-22 13:52     ` Rafael J. Wysocki
2020-06-22 13:53   ` [RFT][PATCH v2 2/4] ACPI: OSL: Add support for deferred unmapping of ACPI memory Rafael J. Wysocki
2020-06-22 13:53     ` Rafael J. Wysocki
2020-06-22 14:56     ` Andy Shevchenko
2020-06-22 14:56       ` Andy Shevchenko
2020-06-22 15:27       ` Rafael J. Wysocki
2020-06-22 15:27         ` Rafael J. Wysocki
2020-06-22 15:46         ` Andy Shevchenko
2020-06-22 15:46           ` Andy Shevchenko
2020-06-22 14:01   ` [RFT][PATCH v2 3/4] ACPICA: Preserve memory opregion mappings if supported by OS Rafael J. Wysocki
2020-06-22 14:01     ` Rafael J. Wysocki
2020-06-26 22:53     ` Kaneda, Erik
2020-06-26 22:53       ` Kaneda, Erik
2020-06-29 13:02       ` Rafael J. Wysocki
2020-06-29 13:02         ` Rafael J. Wysocki
2020-06-22 14:02   ` [RFT][PATCH v2 4/4] ACPI: OSL: Implement acpi_os_map_memory_fast_path() Rafael J. Wysocki
2020-06-22 14:02     ` Rafael J. Wysocki
2020-06-26 17:28   ` [RFT][PATCH v3 0/4] ACPI: ACPICA / OSL: Avoid unmapping ACPI memory inside of the AML interpreter Rafael J. Wysocki
2020-06-26 17:28     ` Rafael J. Wysocki
2020-06-26 17:31     ` [RFT][PATCH v3 1/4] ACPICA: Take deferred unmapping of memory into account Rafael J. Wysocki
2020-06-26 17:31       ` Rafael J. Wysocki
2020-06-26 17:31     ` Rafael J. Wysocki [this message]
2020-06-26 17:31       ` [RFT][PATCH v3 2/4] ACPI: OSL: Implement deferred unmapping of ACPI memory Rafael J. Wysocki
2020-06-27 11:32       ` kernel test robot
2020-06-26 17:32     ` [RFT][PATCH v3 3/4] ACPICA: Preserve memory opregion mappings if supported by OS Rafael J. Wysocki
2020-06-26 17:32       ` Rafael J. Wysocki
2020-06-26 17:33     ` [RFT][PATCH v3 4/4] ACPI: OSL: Implement acpi_os_map_memory_fast_path() Rafael J. Wysocki
2020-06-26 17:33       ` Rafael J. Wysocki
2020-06-26 18:41     ` [RFT][PATCH v3 0/4] ACPI: ACPICA / OSL: Avoid unmapping ACPI memory inside of the AML interpreter Dan Williams
2020-06-26 18:41       ` Dan Williams
2020-06-28 17:09       ` Rafael J. Wysocki
2020-06-28 17:09         ` Rafael J. Wysocki
2020-06-29 20:46         ` Dan Williams
2020-06-29 20:46           ` Dan Williams
2020-06-30 11:04           ` Rafael J. Wysocki
2020-06-30 11:04             ` Rafael J. Wysocki
2020-06-29 16:31     ` [PATCH v4 0/2] " Rafael J. Wysocki
2020-06-29 16:31       ` Rafael J. Wysocki
2020-06-29 16:33       ` [PATCH v4 1/2] ACPI: OSL: Implement deferred unmapping of ACPI memory Rafael J. Wysocki
2020-06-29 16:33         ` Rafael J. Wysocki
2020-06-29 16:33       ` [PATCH v4 2/2] ACPICA: Preserve memory opregion mappings Rafael J. Wysocki
2020-06-29 16:33         ` Rafael J. Wysocki
2020-06-29 20:57         ` Al Stone
2020-06-29 20:57           ` Al Stone
2020-06-30 11:44           ` Rafael J. Wysocki
2020-06-30 11:44             ` Rafael J. Wysocki
2020-06-30 15:31             ` Al Stone
2020-06-30 15:31               ` Al Stone
2020-06-30 15:52               ` Rafael J. Wysocki
2020-06-30 15:52                 ` Rafael J. Wysocki
2020-06-30 19:57                 ` Al Stone
2020-06-30 19:57                   ` Al Stone
2020-07-16 19:22         ` Verma, Vishal L
2020-07-16 19:22           ` Verma, Vishal L
2020-07-19 19:14           ` Rafael J. Wysocki
2020-07-19 19:14             ` Rafael J. Wysocki

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4507864.RZ40Oy75i1@kreacher \
    --to=rjw@rjwysocki.net \
    --cc=andriy.shevchenko@linux.intel.com \
    --cc=bp@alien8.de \
    --cc=dan.j.williams@intel.com \
    --cc=erik.kaneda@intel.com \
    --cc=james.morse@arm.com \
    --cc=lenb@kernel.org \
    --cc=linux-acpi@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-nvdimm@lists.01.org \
    --cc=myron.stowe@redhat.com \
    --cc=rafael.j.wysocki@intel.com \
    --cc=robert.moore@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.