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); |