summaryrefslogtreecommitdiffstats
path: root/drivers/char/mem.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/mem.c')
-rw-r--r--drivers/char/mem.c56
1 files changed, 37 insertions, 19 deletions
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index f4cd55fdd..6eaa07d23 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -5,22 +5,17 @@
*/
#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/tty.h>
+#include <linux/mm.h>
#include <linux/miscdevice.h>
#include <linux/tpqic02.h>
#include <linux/ftape.h>
#include <linux/malloc.h>
#include <linux/vmalloc.h>
#include <linux/mman.h>
-#include <linux/mm.h>
#include <linux/random.h>
#include <linux/init.h>
#include <linux/joystick.h>
+#include <linux/i2c.h>
#include <asm/uaccess.h>
#include <asm/io.h>
@@ -137,26 +132,49 @@ static ssize_t write_mem(struct file * file, const char * buf,
return do_write_mem(file, __va(p), p, buf, count, ppos);
}
+/*
+ * This should probably be per-architecture in <asm/pgtable.h>
+ */
+static inline unsigned long pgprot_noncached(unsigned long prot)
+{
+#if defined(__i386__)
+ if (boot_cpu_data.x86 > 3)
+ prot |= _PAGE_PCD;
+#elif defined(__powerpc__)
+ prot |= _PAGE_NO_CACHE | _PAGE_GUARDED;
+#elif defined(__mc68000__)
+ if (CPU_IS_020_OR_030)
+ prot |= _PAGE_NOCACHE030;
+ /* Use no-cache mode, serialized */
+ if (CPU_IS_040_OR_060)
+ prot = (prot & _CACHEMASK040) | _PAGE_NOCACHE_S;
+#elif defined(__mips__)
+ prot = (prot & ~_CACHE_MASK) | _CACHE_UNCACHED;
+#endif
+
+ return prot;
+}
+
static int mmap_mem(struct file * file, struct vm_area_struct * vma)
{
unsigned long offset = vma->vm_offset;
if (offset & ~PAGE_MASK)
return -ENXIO;
-#if defined(__i386__)
+
/*
- * hmm.. This disables high-memory caching, as the XFree86 team
- * wondered about that at one time.
- * The surround logic should disable caching for the high device
- * addresses anyway, but right now this seems still needed.
+ * Accessing memory above the top the kernel knows about or
+ * through a file pointer that was marked O_SYNC will be
+ * done non-cached.
+ *
+ * Set VM_IO, as this is likely a non-cached access to an
+ * I/O area, and we don't want to include that in a core
+ * file.
*/
- if (boot_cpu_data.x86 > 3 && offset >= __pa(high_memory))
- pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
-#endif
-#ifdef __powerpc__
- if (offset >= __pa(high_memory))
- pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE|_PAGE_GUARDED;
-#endif
+ if (offset >= __pa(high_memory) || (file->f_flags & O_SYNC)) {
+ pgprot_val(vma->vm_page_prot) = pgprot_noncached(pgprot_val(vma->vm_page_prot));
+ vma->vm_flags |= VM_IO;
+ }
if (remap_page_range(vma->vm_start, offset, vma->vm_end-vma->vm_start,
vma->vm_page_prot))
return -EAGAIN;