diff options
author | Rafael J. Wysocki <rjw@sisk.pl> | 2011-01-19 16:27:14 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-01-20 21:30:17 -0500 |
commit | 2d6d9fd3a54a28c6f67f26eb6c74803307a1b11e (patch) | |
tree | 0d7c54159ca8e9c4d4e113597d3c7c08d9f98e84 /drivers/acpi | |
parent | 8d99641f6c1af806cd5d9e6badce91910219a161 (diff) |
ACPI: Introduce acpi_os_ioremap()
Commit ca9b600be38c ("ACPI / PM: Make suspend_nvs_save() use
acpi_os_map_memory()") attempted to prevent the code in osl.c and nvs.c
from using different ioremap() variants by making the latter use
acpi_os_map_memory() for mapping the NVS pages. However, that also
requires acpi_os_unmap_memory() to be used for unmapping them, which
causes synchronize_rcu() to be executed many times in a row
unnecessarily and introduces substantial delays during resume on some
systems.
Instead of using acpi_os_map_memory() for mapping the NVS pages in nvs.c
introduce acpi_os_ioremap() calling ioremap_cache() and make the code in
both osl.c and nvs.c use it.
Reported-by: Jeff Chua <jeff.chua.linux@gmail.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/nvs.c | 7 | ||||
-rw-r--r-- | drivers/acpi/osl.c | 12 |
2 files changed, 11 insertions, 8 deletions
diff --git a/drivers/acpi/nvs.c b/drivers/acpi/nvs.c index 54b6ab8040a6..fa5a1df42b79 100644 --- a/drivers/acpi/nvs.c +++ b/drivers/acpi/nvs.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/mm.h> | 12 | #include <linux/mm.h> |
13 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
14 | #include <linux/acpi.h> | 14 | #include <linux/acpi.h> |
15 | #include <linux/acpi_io.h> | ||
15 | #include <acpi/acpiosxf.h> | 16 | #include <acpi/acpiosxf.h> |
16 | 17 | ||
17 | /* | 18 | /* |
@@ -80,7 +81,7 @@ void suspend_nvs_free(void) | |||
80 | free_page((unsigned long)entry->data); | 81 | free_page((unsigned long)entry->data); |
81 | entry->data = NULL; | 82 | entry->data = NULL; |
82 | if (entry->kaddr) { | 83 | if (entry->kaddr) { |
83 | acpi_os_unmap_memory(entry->kaddr, entry->size); | 84 | iounmap(entry->kaddr); |
84 | entry->kaddr = NULL; | 85 | entry->kaddr = NULL; |
85 | } | 86 | } |
86 | } | 87 | } |
@@ -114,8 +115,8 @@ int suspend_nvs_save(void) | |||
114 | 115 | ||
115 | list_for_each_entry(entry, &nvs_list, node) | 116 | list_for_each_entry(entry, &nvs_list, node) |
116 | if (entry->data) { | 117 | if (entry->data) { |
117 | entry->kaddr = acpi_os_map_memory(entry->phys_start, | 118 | entry->kaddr = acpi_os_ioremap(entry->phys_start, |
118 | entry->size); | 119 | entry->size); |
119 | if (!entry->kaddr) { | 120 | if (!entry->kaddr) { |
120 | suspend_nvs_free(); | 121 | suspend_nvs_free(); |
121 | return -ENOMEM; | 122 | return -ENOMEM; |
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index e2dd6de5d50c..b0931818cf98 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/workqueue.h> | 38 | #include <linux/workqueue.h> |
39 | #include <linux/nmi.h> | 39 | #include <linux/nmi.h> |
40 | #include <linux/acpi.h> | 40 | #include <linux/acpi.h> |
41 | #include <linux/acpi_io.h> | ||
41 | #include <linux/efi.h> | 42 | #include <linux/efi.h> |
42 | #include <linux/ioport.h> | 43 | #include <linux/ioport.h> |
43 | #include <linux/list.h> | 44 | #include <linux/list.h> |
@@ -302,9 +303,10 @@ void __iomem *__init_refok | |||
302 | acpi_os_map_memory(acpi_physical_address phys, acpi_size size) | 303 | acpi_os_map_memory(acpi_physical_address phys, acpi_size size) |
303 | { | 304 | { |
304 | struct acpi_ioremap *map, *tmp_map; | 305 | struct acpi_ioremap *map, *tmp_map; |
305 | unsigned long flags, pg_sz; | 306 | unsigned long flags; |
306 | void __iomem *virt; | 307 | void __iomem *virt; |
307 | phys_addr_t pg_off; | 308 | acpi_physical_address pg_off; |
309 | acpi_size pg_sz; | ||
308 | 310 | ||
309 | if (phys > ULONG_MAX) { | 311 | if (phys > ULONG_MAX) { |
310 | printk(KERN_ERR PREFIX "Cannot map memory that high\n"); | 312 | printk(KERN_ERR PREFIX "Cannot map memory that high\n"); |
@@ -320,7 +322,7 @@ acpi_os_map_memory(acpi_physical_address phys, acpi_size size) | |||
320 | 322 | ||
321 | pg_off = round_down(phys, PAGE_SIZE); | 323 | pg_off = round_down(phys, PAGE_SIZE); |
322 | pg_sz = round_up(phys + size, PAGE_SIZE) - pg_off; | 324 | pg_sz = round_up(phys + size, PAGE_SIZE) - pg_off; |
323 | virt = ioremap_cache(pg_off, pg_sz); | 325 | virt = acpi_os_ioremap(pg_off, pg_sz); |
324 | if (!virt) { | 326 | if (!virt) { |
325 | kfree(map); | 327 | kfree(map); |
326 | return NULL; | 328 | return NULL; |
@@ -642,7 +644,7 @@ acpi_os_read_memory(acpi_physical_address phys_addr, u32 * value, u32 width) | |||
642 | virt_addr = acpi_map_vaddr_lookup(phys_addr, size); | 644 | virt_addr = acpi_map_vaddr_lookup(phys_addr, size); |
643 | rcu_read_unlock(); | 645 | rcu_read_unlock(); |
644 | if (!virt_addr) { | 646 | if (!virt_addr) { |
645 | virt_addr = ioremap_cache(phys_addr, size); | 647 | virt_addr = acpi_os_ioremap(phys_addr, size); |
646 | unmap = 1; | 648 | unmap = 1; |
647 | } | 649 | } |
648 | if (!value) | 650 | if (!value) |
@@ -678,7 +680,7 @@ acpi_os_write_memory(acpi_physical_address phys_addr, u32 value, u32 width) | |||
678 | virt_addr = acpi_map_vaddr_lookup(phys_addr, size); | 680 | virt_addr = acpi_map_vaddr_lookup(phys_addr, size); |
679 | rcu_read_unlock(); | 681 | rcu_read_unlock(); |
680 | if (!virt_addr) { | 682 | if (!virt_addr) { |
681 | virt_addr = ioremap_cache(phys_addr, size); | 683 | virt_addr = acpi_os_ioremap(phys_addr, size); |
682 | unmap = 1; | 684 | unmap = 1; |
683 | } | 685 | } |
684 | 686 | ||