diff options
Diffstat (limited to 'drivers/acpi/osl.c')
| -rw-r--r-- | drivers/acpi/osl.c | 23 | 
1 files changed, 19 insertions, 4 deletions
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 6ad8cb05f672..4a0b07792233 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -350,7 +350,7 @@ void __iomem __ref  	pg_off = round_down(phys, PAGE_SIZE);  	pg_sz = round_up(phys + size, PAGE_SIZE) - pg_off; -	virt = acpi_map(pg_off, pg_sz); +	virt = acpi_map(phys, size);  	if (!virt) {  		mutex_unlock(&acpi_ioremap_lock);  		kfree(map); @@ -358,7 +358,7 @@ void __iomem __ref  	}  	INIT_LIST_HEAD(&map->list); -	map->virt = virt; +	map->virt = (void __iomem __force *)((unsigned long)virt & PAGE_MASK);  	map->phys = pg_off;  	map->size = pg_sz;  	map->track.refcount = 1; @@ -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);  |