ioremap_nocache(), 2.1.30

Ingo Molnar (mingo@pc5829.hil.siemens.at)
Fri, 28 Mar 1997 19:24:19 +0100 (MET)


this patch adds ioremap_nocache() for x86. The PCI device problem reported
by Rakesh Dubey got fixed when mapping the device with caching turned off.
the original ioremap() behavior is not changed.

-- mingo

--- linux-2.1.30_vanilla/include/asm-i386/io.h Tue Oct 15 07:31:45 1996
+++ linux/include/asm-i386/io.h Fri Mar 28 20:02:33 1997
@@ -1,6 +1,8 @@
#ifndef _ASM_IO_H
#define _ASM_IO_H

+#include <linux/vmalloc.h>
+
/*
* This file contains the definitions for the x86 IO instructions
* inb/inw/inl/outb/outw/outl and the "string versions" of the same
@@ -184,7 +186,23 @@
return __io_virt(address);
}

-extern void * ioremap(unsigned long offset, unsigned long size);
+extern void * __ioremap(unsigned long offset, unsigned long size, unsigned long flags);
+
+extern inline void * ioremap (unsigned long offset, unsigned long size)
+{
+ return __ioremap(offset, size, 0);
+}
+
+/*
+ * This one maps high address device memory and turns off caching for that area.
+ * it's useful if some control registers are in such an area and write combining
+ * or read caching is not desirable:
+ */
+extern inline void * ioremap_nocache (unsigned long offset, unsigned long size)
+{
+ return __ioremap(offset, size, _PAGE_PCD);
+}
+
extern void iounmap(void *addr);

/*
--- linux-2.1.30_vanilla/arch/i386/mm/ioremap.c Wed Sep 25 11:12:50 1996
+++ linux/arch/i386/mm/ioremap.c Fri Mar 28 20:07:15 1997
@@ -9,11 +9,10 @@
*/

#include <linux/vmalloc.h>
-
#include <asm/io.h>

static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size,
- unsigned long phys_addr)
+ unsigned long phys_addr, unsigned long flags)
{
unsigned long end;

@@ -24,7 +23,8 @@
do {
if (!pte_none(*pte))
printk("remap_area_pte: page already exists\n");
- set_pte(pte, mk_pte_phys(phys_addr, PAGE_KERNEL));
+ set_pte(pte, mk_pte_phys(phys_addr, __pgprot(_PAGE_PRESENT | _PAGE_RW |
+ _PAGE_DIRTY | _PAGE_ACCESSED | flags)));
address += PAGE_SIZE;
phys_addr += PAGE_SIZE;
pte++;
@@ -32,7 +32,7 @@
}

static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size,
- unsigned long phys_addr)
+ unsigned long phys_addr, unsigned long flags)
{
unsigned long end;

@@ -45,14 +45,15 @@
pte_t * pte = pte_alloc_kernel(pmd, address);
if (!pte)
return -ENOMEM;
- remap_area_pte(pte, address, end - address, address + phys_addr);
+ remap_area_pte(pte, address, end - address, address + phys_addr, flags);
address = (address + PMD_SIZE) & PMD_MASK;
pmd++;
} while (address < end);
return 0;
}

-static int remap_area_pages(unsigned long address, unsigned long phys_addr, unsigned long size)
+static int remap_area_pages(unsigned long address, unsigned long phys_addr,
+ unsigned long size, unsigned long flags)
{
pgd_t * dir;
unsigned long end = address + size;
@@ -64,7 +65,8 @@
pmd_t *pmd = pmd_alloc_kernel(dir, address);
if (!pmd)
return -ENOMEM;
- if (remap_area_pmd(pmd, address, end - address, phys_addr + address))
+ if (remap_area_pmd(pmd, address, end - address,
+ phys_addr + address, flags))
return -ENOMEM;
set_pgdir(address, *dir);
address = (address + PGDIR_SIZE) & PGDIR_MASK;
@@ -75,11 +77,15 @@
}

/*
+ * Generic mapping function (not visible outside):
+ */
+
+/*
* Remap an arbitrary physical address space into the kernel virtual
* address space. Needed when the kernel wants to access high addresses
* directly.
*/
-void * ioremap(unsigned long phys_addr, unsigned long size)
+void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)
{
void * addr;
struct vm_struct * area;
@@ -95,7 +101,7 @@
if (!area)
return NULL;
addr = area->addr;
- if (remap_area_pages(VMALLOC_VMADDR(addr), phys_addr, size)) {
+ if (remap_area_pages(VMALLOC_VMADDR(addr), phys_addr, size, flags)) {
vfree(addr);
return NULL;
}
--- linux-2.1.30_vanilla/arch/i386/kernel/i386_ksyms.c Fri Mar 28 12:30:22 1997
+++ linux/arch/i386/kernel/i386_ksyms.c Fri Mar 28 20:10:25 1997
@@ -24,7 +24,7 @@
EXPORT_SYMBOL(__verify_write);
EXPORT_SYMBOL(dump_thread);
EXPORT_SYMBOL(dump_fpu);
-EXPORT_SYMBOL(ioremap);
+EXPORT_SYMBOL(__ioremap);
EXPORT_SYMBOL(iounmap);
EXPORT_SYMBOL_NOVERS(__down_failed);
EXPORT_SYMBOL_NOVERS(__down_failed_interruptible);