#include <linux/rculist.h>
 #include <linux/interrupt.h>
 #include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/highmem.h>
 #include <acpi/atomicio.h>
 
 #define ACPI_PFX "ACPI: "
                return NULL;
 }
 
+#ifndef CONFIG_IA64
+#define should_use_kmap(pfn)   page_is_ram(pfn)
+#else
+/* ioremap will take care of cache attributes */
+#define should_use_kmap(pfn)   0
+#endif
+
+static void __iomem *acpi_map(phys_addr_t pg_off, unsigned long pg_sz)
+{
+       unsigned long pfn;
+
+       pfn = pg_off >> PAGE_SHIFT;
+       if (should_use_kmap(pfn)) {
+               if (pg_sz > PAGE_SIZE)
+                       return NULL;
+               return (void __iomem __force *)kmap(pfn_to_page(pfn));
+       } else
+               return ioremap(pg_off, pg_sz);
+}
+
+static void acpi_unmap(phys_addr_t pg_off, void __iomem *vaddr)
+{
+       unsigned long pfn;
+
+       pfn = pg_off >> PAGE_SHIFT;
+       if (page_is_ram(pfn))
+               kunmap(pfn_to_page(pfn));
+       else
+               iounmap(vaddr);
+}
+
 /*
  * Used to pre-map the specified IO memory area. First try to find
  * whether the area is already pre-mapped, if it is, increase the
 
        pg_off = paddr & PAGE_MASK;
        pg_sz = ((paddr + size + PAGE_SIZE - 1) & PAGE_MASK) - pg_off;
-       vaddr = ioremap(pg_off, pg_sz);
+       vaddr = acpi_map(pg_off, pg_sz);
        if (!vaddr)
                return NULL;
        map = kmalloc(sizeof(*map), GFP_KERNEL);
        vaddr = __acpi_try_ioremap(paddr, size);
        if (vaddr) {
                spin_unlock_irqrestore(&acpi_iomaps_lock, flags);
-               iounmap(map->vaddr);
+               acpi_unmap(pg_off, map->vaddr);
                kfree(map);
                return vaddr;
        }
 
        return map->vaddr + (paddr - map->paddr);
 err_unmap:
-       iounmap(vaddr);
+       acpi_unmap(pg_off, vaddr);
        return NULL;
 }
 
                return;
 
        synchronize_rcu();
-       iounmap(map->vaddr);
+       acpi_unmap(map->paddr, map->vaddr);
        kfree(map);
 }