vfb: make virtual framebuffer mmapable
Changed things: 1. vmalloc()/vfree() replaced with rvmalloc()/rvfree() (taken from drivers/media/video/se401.c) 2. mmap method implemented (mostly taken from drivers/media/video/se401.c) 3. smem_start and smem_len fields of struct fb_fix_screeninfo initialized. (smem_start initialized with virtual address, don't know if it is really bad...) [adaplas: sparse warning fix] Signed-off-by: Antonino Daplas <adaplas@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Родитель
1ddc28d7e7
Коммит
68e5e9d734
|
@ -37,6 +37,48 @@ static void *videomemory;
|
|||
static u_long videomemorysize = VIDEOMEMSIZE;
|
||||
module_param(videomemorysize, ulong, 0);
|
||||
|
||||
/**********************************************************************
|
||||
*
|
||||
* Memory management
|
||||
*
|
||||
**********************************************************************/
|
||||
static void *rvmalloc(unsigned long size)
|
||||
{
|
||||
void *mem;
|
||||
unsigned long adr;
|
||||
|
||||
size = PAGE_ALIGN(size);
|
||||
mem = vmalloc_32(size);
|
||||
if (!mem)
|
||||
return NULL;
|
||||
|
||||
memset(mem, 0, size); /* Clear the ram out, no junk to the user */
|
||||
adr = (unsigned long) mem;
|
||||
while (size > 0) {
|
||||
SetPageReserved(vmalloc_to_page((void *)adr));
|
||||
adr += PAGE_SIZE;
|
||||
size -= PAGE_SIZE;
|
||||
}
|
||||
|
||||
return mem;
|
||||
}
|
||||
|
||||
static void rvfree(void *mem, unsigned long size)
|
||||
{
|
||||
unsigned long adr;
|
||||
|
||||
if (!mem)
|
||||
return;
|
||||
|
||||
adr = (unsigned long) mem;
|
||||
while ((long) size > 0) {
|
||||
ClearPageReserved(vmalloc_to_page((void *)adr));
|
||||
adr += PAGE_SIZE;
|
||||
size -= PAGE_SIZE;
|
||||
}
|
||||
vfree(mem);
|
||||
}
|
||||
|
||||
static struct fb_var_screeninfo vfb_default __initdata = {
|
||||
.xres = 640,
|
||||
.yres = 480,
|
||||
|
@ -371,7 +413,33 @@ static int vfb_pan_display(struct fb_var_screeninfo *var,
|
|||
static int vfb_mmap(struct fb_info *info,
|
||||
struct vm_area_struct *vma)
|
||||
{
|
||||
unsigned long start = vma->vm_start;
|
||||
unsigned long size = vma->vm_end - vma->vm_start;
|
||||
unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
|
||||
unsigned long page, pos;
|
||||
|
||||
if (offset + size > info->fix.smem_len) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pos = (unsigned long)info->fix.smem_start + offset;
|
||||
|
||||
while (size > 0) {
|
||||
page = vmalloc_to_pfn((void *)pos);
|
||||
if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
|
||||
return -EAGAIN;
|
||||
}
|
||||
start += PAGE_SIZE;
|
||||
pos += PAGE_SIZE;
|
||||
if (size > PAGE_SIZE)
|
||||
size -= PAGE_SIZE;
|
||||
else
|
||||
size = 0;
|
||||
}
|
||||
|
||||
vma->vm_flags |= VM_RESERVED; /* avoid to swap out this VMA */
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
#ifndef MODULE
|
||||
|
@ -406,7 +474,7 @@ static int __init vfb_probe(struct platform_device *dev)
|
|||
/*
|
||||
* For real video cards we use ioremap.
|
||||
*/
|
||||
if (!(videomemory = vmalloc(videomemorysize)))
|
||||
if (!(videomemory = rvmalloc(videomemorysize)))
|
||||
return retval;
|
||||
|
||||
/*
|
||||
|
@ -429,6 +497,8 @@ static int __init vfb_probe(struct platform_device *dev)
|
|||
|
||||
if (!retval || (retval == 4))
|
||||
info->var = vfb_default;
|
||||
vfb_fix.smem_start = (unsigned long) videomemory;
|
||||
vfb_fix.smem_len = videomemorysize;
|
||||
info->fix = vfb_fix;
|
||||
info->pseudo_palette = info->par;
|
||||
info->par = NULL;
|
||||
|
@ -452,7 +522,7 @@ err2:
|
|||
err1:
|
||||
framebuffer_release(info);
|
||||
err:
|
||||
vfree(videomemory);
|
||||
rvfree(videomemory, videomemorysize);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -462,7 +532,7 @@ static int vfb_remove(struct platform_device *dev)
|
|||
|
||||
if (info) {
|
||||
unregister_framebuffer(info);
|
||||
vfree(videomemory);
|
||||
rvfree(videomemory, videomemorysize);
|
||||
framebuffer_release(info);
|
||||
}
|
||||
return 0;
|
||||
|
|
Загрузка…
Ссылка в новой задаче