diff options
Diffstat (limited to 'drivers/acpi/osl.c')
| -rw-r--r-- | drivers/acpi/osl.c | 72 | 
1 files changed, 72 insertions, 0 deletions
| diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 7ca41bf023c9..8df9abfa947b 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -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   */ |