diff options
| author | Rafael J. Wysocki <rjw@sisk.pl> | 2011-02-08 17:38:05 -0500 |
|---|---|---|
| committer | Rafael J. Wysocki <rjw@sisk.pl> | 2011-02-24 13:58:41 -0500 |
| commit | 7ffd0443f2502478545e23e194b7eb8e16376072 (patch) | |
| tree | 467a47d0d8b9ce4de3c95aa11d25b8c9b5ce05a1 /drivers | |
| parent | 7fe135dc058faea0ce319a03e3b6f98c5049955c (diff) | |
ACPI: Make acpi_os_map_memory() avoid creating unnecessary mappings
Modify acpi_os_map_memory() so that it doesn't call acpi_os_ioremap()
unconditionally every time it is executed (except when
acpi_gbl_permanent_mmap is unset), which pretty much defeats the
purpose of maintaining the list of ACPI iomaps in osl.c.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/acpi/osl.c | 28 |
1 files changed, 15 insertions, 13 deletions
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index f6785bced215..445f205752a2 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c | |||
| @@ -302,7 +302,7 @@ acpi_map_lookup_virt(void __iomem *virt, acpi_size size) | |||
| 302 | void __iomem *__init_refok | 302 | void __iomem *__init_refok |
| 303 | acpi_os_map_memory(acpi_physical_address phys, acpi_size size) | 303 | acpi_os_map_memory(acpi_physical_address phys, acpi_size size) |
| 304 | { | 304 | { |
| 305 | struct acpi_ioremap *map, *tmp_map; | 305 | struct acpi_ioremap *map; |
| 306 | void __iomem *virt; | 306 | void __iomem *virt; |
| 307 | acpi_physical_address pg_off; | 307 | acpi_physical_address pg_off; |
| 308 | acpi_size pg_sz; | 308 | acpi_size pg_sz; |
| @@ -315,14 +315,25 @@ acpi_os_map_memory(acpi_physical_address phys, acpi_size size) | |||
| 315 | if (!acpi_gbl_permanent_mmap) | 315 | if (!acpi_gbl_permanent_mmap) |
| 316 | return __acpi_map_table((unsigned long)phys, size); | 316 | return __acpi_map_table((unsigned long)phys, size); |
| 317 | 317 | ||
| 318 | mutex_lock(&acpi_ioremap_lock); | ||
| 319 | /* Check if there's a suitable mapping already. */ | ||
| 320 | map = acpi_map_lookup(phys, size); | ||
| 321 | if (map) { | ||
| 322 | kref_get(&map->ref); | ||
| 323 | goto out; | ||
| 324 | } | ||
| 325 | |||
| 318 | map = kzalloc(sizeof(*map), GFP_KERNEL); | 326 | map = kzalloc(sizeof(*map), GFP_KERNEL); |
| 319 | if (!map) | 327 | if (!map) { |
| 328 | mutex_unlock(&acpi_ioremap_lock); | ||
| 320 | return NULL; | 329 | return NULL; |
| 330 | } | ||
| 321 | 331 | ||
| 322 | pg_off = round_down(phys, PAGE_SIZE); | 332 | pg_off = round_down(phys, PAGE_SIZE); |
| 323 | pg_sz = round_up(phys + size, PAGE_SIZE) - pg_off; | 333 | pg_sz = round_up(phys + size, PAGE_SIZE) - pg_off; |
| 324 | virt = acpi_os_ioremap(pg_off, pg_sz); | 334 | virt = acpi_os_ioremap(pg_off, pg_sz); |
| 325 | if (!virt) { | 335 | if (!virt) { |
| 336 | mutex_unlock(&acpi_ioremap_lock); | ||
| 326 | kfree(map); | 337 | kfree(map); |
| 327 | return NULL; | 338 | return NULL; |
| 328 | } | 339 | } |
| @@ -333,19 +344,10 @@ acpi_os_map_memory(acpi_physical_address phys, acpi_size size) | |||
| 333 | map->size = pg_sz; | 344 | map->size = pg_sz; |
| 334 | kref_init(&map->ref); | 345 | kref_init(&map->ref); |
| 335 | 346 | ||
| 336 | mutex_lock(&acpi_ioremap_lock); | ||
| 337 | /* Check if page has already been mapped. */ | ||
| 338 | tmp_map = acpi_map_lookup(phys, size); | ||
| 339 | if (tmp_map) { | ||
| 340 | kref_get(&tmp_map->ref); | ||
| 341 | mutex_unlock(&acpi_ioremap_lock); | ||
| 342 | iounmap(map->virt); | ||
| 343 | kfree(map); | ||
| 344 | return tmp_map->virt + (phys - tmp_map->phys); | ||
| 345 | } | ||
| 346 | list_add_tail_rcu(&map->list, &acpi_ioremaps); | 347 | list_add_tail_rcu(&map->list, &acpi_ioremaps); |
| 347 | mutex_unlock(&acpi_ioremap_lock); | ||
| 348 | 348 | ||
| 349 | out: | ||
| 350 | mutex_unlock(&acpi_ioremap_lock); | ||
| 349 | return map->virt + (phys - map->phys); | 351 | return map->virt + (phys - map->phys); |
| 350 | } | 352 | } |
| 351 | EXPORT_SYMBOL_GPL(acpi_os_map_memory); | 353 | EXPORT_SYMBOL_GPL(acpi_os_map_memory); |
