linux/arch/blackfin/kernel/sys_bfin.c
Thomas Chou 59bd00c850 Blackfin: fix framebuffer mmap bug for nommu
The patch added a special get_unmapped_area for framebuffer which
was hooked to the file ops in drivers/video/fbmem.c.

This is needed since v2.6.29-rc1 where nommu vma management was
updated, and mmap of framebuffer caused kernel BUG panic. You may turn
on "Debug the global anon/private NOMMU mapping region tree" config to
such message.

As Documentation/nommu-mmap.txt said,
"To provide shareable character device support, a driver must provide
a file->f_op->get_unmapped_area() operation. The mmap() routines will
call this to get a proposed address for the mapping."

With this change, user space should call mmap for framebuffer using
shared map. Or it can try shared map first, then private map if
failed. This shared map usage is now consistent between mmu and nommu.

The sys_ file may not be a good place for this patch. But there is a
similar one for sparc. I tested a similar patch on nios2nommu, though
I don't have a blackfin board to test.

Signed-off-by: Thomas Chou <thomas@wytron.com.tw>
Signed-off-by: Graf Yang <graf.yang@analog.com>
Signed-off-by: Michael Hennerich <michael.hennerich@analog.com>
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
2009-10-08 00:58:15 -04:00

83 lines
1.9 KiB
C

/*
* contains various random system calls that have a non-standard
* calling sequence on the Linux/Blackfin platform.
*
* Copyright 2004-2009 Analog Devices Inc.
*
* Licensed under the GPL-2 or later
*/
#include <linux/spinlock.h>
#include <linux/sem.h>
#include <linux/msg.h>
#include <linux/shm.h>
#include <linux/syscalls.h>
#include <linux/mman.h>
#include <linux/file.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/ipc.h>
#include <linux/unistd.h>
#include <asm/cacheflush.h>
#include <asm/dma.h>
/* common code for old and new mmaps */
static inline long
do_mmap2(unsigned long addr, unsigned long len,
unsigned long prot, unsigned long flags,
unsigned long fd, unsigned long pgoff)
{
int error = -EBADF;
struct file *file = NULL;
flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
if (!(flags & MAP_ANONYMOUS)) {
file = fget(fd);
if (!file)
goto out;
}
down_write(&current->mm->mmap_sem);
error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
up_write(&current->mm->mmap_sem);
if (file)
fput(file);
out:
return error;
}
asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
unsigned long prot, unsigned long flags,
unsigned long fd, unsigned long pgoff)
{
return do_mmap2(addr, len, prot, flags, fd, pgoff);
}
asmlinkage void *sys_sram_alloc(size_t size, unsigned long flags)
{
return sram_alloc_with_lsl(size, flags);
}
asmlinkage int sys_sram_free(const void *addr)
{
return sram_free_with_lsl(addr);
}
asmlinkage void *sys_dma_memcpy(void *dest, const void *src, size_t len)
{
return safe_dma_memcpy(dest, src, len);
}
#if defined(CONFIG_FB) || defined(CONFIG_FB_MODULE)
#include <linux/fb.h>
unsigned long get_fb_unmapped_area(struct file *filp, unsigned long orig_addr,
unsigned long len, unsigned long pgoff, unsigned long flags)
{
struct fb_info *info = filp->private_data;
return (unsigned long)info->screen_base;
}
EXPORT_SYMBOL(get_fb_unmapped_area);
#endif