Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=68e5e9d734503695915734e50e9427624cf8f3b2
Commit:     68e5e9d734503695915734e50e9427624cf8f3b2
Parent:     1ddc28d7e7cb5f501e224a5868d34442c6203eb1
Author:     Ilya Yanok <[EMAIL PROTECTED]>
AuthorDate: Tue Oct 16 01:29:17 2007 -0700
Committer:  Linus Torvalds <[EMAIL PROTECTED]>
CommitDate: Tue Oct 16 09:43:18 2007 -0700

    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 <[EMAIL PROTECTED]>
    Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
    Signed-off-by: Linus Torvalds <[EMAIL PROTECTED]>
---
 drivers/video/vfb.c |   78 ++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 74 insertions(+), 4 deletions(-)

diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c
index 02cfc6a..072638a 100644
--- a/drivers/video/vfb.c
+++ b/drivers/video/vfb.c
@@ -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)
 {
-       return -EINVAL;
+       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;
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to