Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Rafael J. Wysocki and committed by
Linus Torvalds
2d6d9fd3 8d99641f

+27 -11
+4 -3
drivers/acpi/nvs.c
··· 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 /* ··· 81 80 free_page((unsigned long)entry->data); 82 81 entry->data = NULL; 83 82 if (entry->kaddr) { 84 - acpi_os_unmap_memory(entry->kaddr, entry->size); 83 + iounmap(entry->kaddr); 85 84 entry->kaddr = NULL; 86 85 } 87 86 } ··· 115 114 116 115 list_for_each_entry(entry, &nvs_list, node) 117 116 if (entry->data) { 118 - entry->kaddr = acpi_os_map_memory(entry->phys_start, 119 - entry->size); 117 + entry->kaddr = acpi_os_ioremap(entry->phys_start, 118 + entry->size); 120 119 if (!entry->kaddr) { 121 120 suspend_nvs_free(); 122 121 return -ENOMEM;
+7 -5
drivers/acpi/osl.c
··· 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> ··· 303 302 acpi_os_map_memory(acpi_physical_address phys, acpi_size size) 304 303 { 305 304 struct acpi_ioremap *map, *tmp_map; 306 - unsigned long flags, pg_sz; 305 + unsigned long flags; 307 306 void __iomem *virt; 308 - phys_addr_t pg_off; 307 + acpi_physical_address pg_off; 308 + acpi_size pg_sz; 309 309 310 310 if (phys > ULONG_MAX) { 311 311 printk(KERN_ERR PREFIX "Cannot map memory that high\n"); ··· 322 320 323 321 pg_off = round_down(phys, PAGE_SIZE); 324 322 pg_sz = round_up(phys + size, PAGE_SIZE) - pg_off; 325 - virt = ioremap_cache(pg_off, pg_sz); 323 + virt = acpi_os_ioremap(pg_off, pg_sz); 326 324 if (!virt) { 327 325 kfree(map); 328 326 return NULL; ··· 644 642 virt_addr = acpi_map_vaddr_lookup(phys_addr, size); 645 643 rcu_read_unlock(); 646 644 if (!virt_addr) { 647 - virt_addr = ioremap_cache(phys_addr, size); 645 + virt_addr = acpi_os_ioremap(phys_addr, size); 648 646 unmap = 1; 649 647 } 650 648 if (!value) ··· 680 678 virt_addr = acpi_map_vaddr_lookup(phys_addr, size); 681 679 rcu_read_unlock(); 682 680 if (!virt_addr) { 683 - virt_addr = ioremap_cache(phys_addr, size); 681 + virt_addr = acpi_os_ioremap(phys_addr, size); 684 682 unmap = 1; 685 683 } 686 684
-3
include/linux/acpi.h
··· 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
+16
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