aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/osl.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2020-08-21 19:42:55 +0200
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2020-08-25 16:22:08 +0200
commit33f61d725a86e9ae02bf504e9372ba973c010ddc (patch)
tree1a8f240d222c3a6351afc3e56011ef80bf91777e /drivers/acpi/osl.c
parentACPI: ioremap: avoid redundant rounding to OS page size (diff)
downloadlinux-dev-33f61d725a86e9ae02bf504e9372ba973c010ddc.tar.xz
linux-dev-33f61d725a86e9ae02bf504e9372ba973c010ddc.zip
ACPI: OSL: Prevent acpi_release_memory() from returning too early
After commit 1757659d022b ("ACPI: OSL: Implement deferred unmapping of ACPI memory") in some cases acpi_release_memory() may return before the target memory mappings actually go away, because they are released asynchronously now. Prevent it from returning prematurely by making it wait for the next RCU grace period to elapse, for all of the RCU callbacks to complete and for all of the scheduled work items to be flushed before returning. Fixes: 1757659d022b ("ACPI: OSL: Implement deferred unmapping of ACPI memory") Reported-by: Kenneth R. Crudup <kenny@panix.com> Tested-by: Kenneth R. Crudup <kenny@panix.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com> Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Diffstat (limited to 'drivers/acpi/osl.c')
-rw-r--r--drivers/acpi/osl.c19
1 files changed, 17 insertions, 2 deletions
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 74486bb5029a..4a0b07792233 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -1575,11 +1575,26 @@ 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 status;
+
if (!(res->flags & IORESOURCE_MEM))
return AE_TYPE;
- return acpi_walk_namespace(ACPI_TYPE_REGION, handle, level,
- acpi_deactivate_mem_region, NULL, res, NULL);
+ status = acpi_walk_namespace(ACPI_TYPE_REGION, handle, level,
+ acpi_deactivate_mem_region, NULL,
+ res, NULL);
+ if (ACPI_FAILURE(status))
+ return status;
+
+ /*
+ * Wait for all of the mappings queued up for removal by
+ * acpi_deactivate_mem_region() to actually go away.
+ */
+ synchronize_rcu();
+ rcu_barrier();
+ flush_scheduled_work();
+
+ return AE_OK;
}
EXPORT_SYMBOL_GPL(acpi_release_memory);