|
@@ -45,6 +45,8 @@
|
|
|
#include <linux/uaccess.h>
|
|
|
#include <linux/io-64-nonatomic-lo-hi.h>
|
|
|
|
|
|
+#include "acpica/accommon.h"
|
|
|
+#include "acpica/acnamesp.h"
|
|
|
#include "internal.h"
|
|
|
|
|
|
#define _COMPONENT ACPI_OS_SERVICES
|
|
@@ -1490,6 +1492,76 @@ int acpi_check_region(resource_size_t start, resource_size_t n,
|
|
|
}
|
|
|
EXPORT_SYMBOL(acpi_check_region);
|
|
|
|
|
|
+static acpi_status acpi_deactivate_mem_region(acpi_handle handle, u32 level,
|
|
|
+ void *_res, void **return_value)
|
|
|
+{
|
|
|
+ struct acpi_mem_space_context **mem_ctx;
|
|
|
+ union acpi_operand_object *handler_obj;
|
|
|
+ union acpi_operand_object *region_obj2;
|
|
|
+ union acpi_operand_object *region_obj;
|
|
|
+ struct resource *res = _res;
|
|
|
+ acpi_status status;
|
|
|
+
|
|
|
+ region_obj = acpi_ns_get_attached_object(handle);
|
|
|
+ if (!region_obj)
|
|
|
+ return AE_OK;
|
|
|
+
|
|
|
+ handler_obj = region_obj->region.handler;
|
|
|
+ if (!handler_obj)
|
|
|
+ return AE_OK;
|
|
|
+
|
|
|
+ if (region_obj->region.space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY)
|
|
|
+ return AE_OK;
|
|
|
+
|
|
|
+ if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE))
|
|
|
+ return AE_OK;
|
|
|
+
|
|
|
+ region_obj2 = acpi_ns_get_secondary_object(region_obj);
|
|
|
+ if (!region_obj2)
|
|
|
+ return AE_OK;
|
|
|
+
|
|
|
+ mem_ctx = (void *)®ion_obj2->extra.region_context;
|
|
|
+
|
|
|
+ if (!(mem_ctx[0]->address >= res->start &&
|
|
|
+ mem_ctx[0]->address < res->end))
|
|
|
+ return AE_OK;
|
|
|
+
|
|
|
+ status = handler_obj->address_space.setup(region_obj,
|
|
|
+ ACPI_REGION_DEACTIVATE,
|
|
|
+ NULL, (void **)mem_ctx);
|
|
|
+ if (ACPI_SUCCESS(status))
|
|
|
+ region_obj->region.flags &= ~(AOPOBJ_SETUP_COMPLETE);
|
|
|
+
|
|
|
+ return status;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * acpi_release_memory - Release any mappings done to a memory region
|
|
|
+ * @handle: Handle to namespace node
|
|
|
+ * @res: Memory resource
|
|
|
+ * @level: A level that terminates the search
|
|
|
+ *
|
|
|
+ * Walks through @handle and unmaps all SystemMemory Operation Regions that
|
|
|
+ * overlap with @res and that have already been activated (mapped).
|
|
|
+ *
|
|
|
+ * This is a helper that allows drivers to place special requirements on memory
|
|
|
+ * region that may overlap with operation regions, primarily allowing them to
|
|
|
+ * safely map the region as non-cached memory.
|
|
|
+ *
|
|
|
+ * The unmapped Operation Regions will be automatically remapped next time they
|
|
|
+ * are called, so the drivers do not need to do anything else.
|
|
|
+ */
|
|
|
+acpi_status acpi_release_memory(acpi_handle handle, struct resource *res,
|
|
|
+ u32 level)
|
|
|
+{
|
|
|
+ if (!(res->flags & IORESOURCE_MEM))
|
|
|
+ return AE_TYPE;
|
|
|
+
|
|
|
+ return acpi_walk_namespace(ACPI_TYPE_REGION, handle, level,
|
|
|
+ acpi_deactivate_mem_region, NULL, res, NULL);
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(acpi_release_memory);
|
|
|
+
|
|
|
/*
|
|
|
* Let drivers know whether the resource checks are effective
|
|
|
*/
|