Commit 2d6d9fd3a54a28c6f67f26eb6c74803307a1b11e
Committed by
Linus Torvalds
1 parent
8d99641f6c
Exists in
master
and in
7 other branches
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>
Showing 4 changed files with 27 additions and 11 deletions Side-by-side Diff
drivers/acpi/nvs.c
... | ... | @@ -12,6 +12,7 @@ |
12 | 12 | #include <linux/mm.h> |
13 | 13 | #include <linux/slab.h> |
14 | 14 | #include <linux/acpi.h> |
15 | +#include <linux/acpi_io.h> | |
15 | 16 | #include <acpi/acpiosxf.h> |
16 | 17 | |
17 | 18 | /* |
... | ... | @@ -80,7 +81,7 @@ |
80 | 81 | free_page((unsigned long)entry->data); |
81 | 82 | entry->data = NULL; |
82 | 83 | if (entry->kaddr) { |
83 | - acpi_os_unmap_memory(entry->kaddr, entry->size); | |
84 | + iounmap(entry->kaddr); | |
84 | 85 | entry->kaddr = NULL; |
85 | 86 | } |
86 | 87 | } |
... | ... | @@ -114,8 +115,8 @@ |
114 | 115 | |
115 | 116 | list_for_each_entry(entry, &nvs_list, node) |
116 | 117 | if (entry->data) { |
117 | - entry->kaddr = acpi_os_map_memory(entry->phys_start, | |
118 | - entry->size); | |
118 | + entry->kaddr = acpi_os_ioremap(entry->phys_start, | |
119 | + entry->size); | |
119 | 120 | if (!entry->kaddr) { |
120 | 121 | suspend_nvs_free(); |
121 | 122 | return -ENOMEM; |
drivers/acpi/osl.c
... | ... | @@ -38,6 +38,7 @@ |
38 | 38 | #include <linux/workqueue.h> |
39 | 39 | #include <linux/nmi.h> |
40 | 40 | #include <linux/acpi.h> |
41 | +#include <linux/acpi_io.h> | |
41 | 42 | #include <linux/efi.h> |
42 | 43 | #include <linux/ioport.h> |
43 | 44 | #include <linux/list.h> |
44 | 45 | |
... | ... | @@ -302,9 +303,10 @@ |
302 | 303 | acpi_os_map_memory(acpi_physical_address phys, acpi_size size) |
303 | 304 | { |
304 | 305 | struct acpi_ioremap *map, *tmp_map; |
305 | - unsigned long flags, pg_sz; | |
306 | + unsigned long flags; | |
306 | 307 | void __iomem *virt; |
307 | - phys_addr_t pg_off; | |
308 | + acpi_physical_address pg_off; | |
309 | + acpi_size pg_sz; | |
308 | 310 | |
309 | 311 | if (phys > ULONG_MAX) { |
310 | 312 | printk(KERN_ERR PREFIX "Cannot map memory that high\n"); |
... | ... | @@ -320,7 +322,7 @@ |
320 | 322 | |
321 | 323 | pg_off = round_down(phys, PAGE_SIZE); |
322 | 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 | 326 | if (!virt) { |
325 | 327 | kfree(map); |
326 | 328 | return NULL; |
... | ... | @@ -642,7 +644,7 @@ |
642 | 644 | virt_addr = acpi_map_vaddr_lookup(phys_addr, size); |
643 | 645 | rcu_read_unlock(); |
644 | 646 | if (!virt_addr) { |
645 | - virt_addr = ioremap_cache(phys_addr, size); | |
647 | + virt_addr = acpi_os_ioremap(phys_addr, size); | |
646 | 648 | unmap = 1; |
647 | 649 | } |
648 | 650 | if (!value) |
... | ... | @@ -678,7 +680,7 @@ |
678 | 680 | virt_addr = acpi_map_vaddr_lookup(phys_addr, size); |
679 | 681 | rcu_read_unlock(); |
680 | 682 | if (!virt_addr) { |
681 | - virt_addr = ioremap_cache(phys_addr, size); | |
683 | + virt_addr = acpi_os_ioremap(phys_addr, size); | |
682 | 684 | unmap = 1; |
683 | 685 | } |
684 | 686 |
include/linux/acpi.h
... | ... | @@ -306,9 +306,6 @@ |
306 | 306 | u32 *mask, u32 req); |
307 | 307 | extern void acpi_early_init(void); |
308 | 308 | |
309 | -int acpi_os_map_generic_address(struct acpi_generic_address *addr); | |
310 | -void acpi_os_unmap_generic_address(struct acpi_generic_address *addr); | |
311 | - | |
312 | 309 | #else /* !CONFIG_ACPI */ |
313 | 310 | |
314 | 311 | #define acpi_disabled 1 |
include/linux/acpi_io.h
1 | +#ifndef _ACPI_IO_H_ | |
2 | +#define _ACPI_IO_H_ | |
3 | + | |
4 | +#include <linux/io.h> | |
5 | +#include <acpi/acpi.h> | |
6 | + | |
7 | +static inline void __iomem *acpi_os_ioremap(acpi_physical_address phys, | |
8 | + acpi_size size) | |
9 | +{ | |
10 | + return ioremap_cache(phys, size); | |
11 | +} | |
12 | + | |
13 | +int acpi_os_map_generic_address(struct acpi_generic_address *addr); | |
14 | +void acpi_os_unmap_generic_address(struct acpi_generic_address *addr); | |
15 | + | |
16 | +#endif |