Chinaunix首页 | 论坛 | 博客
  • 博客访问: 15483030
  • 博文数量: 2005
  • 博客积分: 11986
  • 博客等级: 上将
  • 技术积分: 22535
  • 用 户 组: 普通用户
  • 注册时间: 2007-05-17 13:56
文章分类

全部博文(2005)

文章存档

2014年(2)

2013年(2)

2012年(16)

2011年(66)

2010年(368)

2009年(743)

2008年(491)

2007年(317)

分类: LINUX

2009-09-27 21:21:58

#define _PAGE_BIT_PCD        4    /* page cache disabled *
#define _PAGE_PCD    (_AT(pteval_t, 1) << _PAGE_BIT_PCD)

不知道为什么fb_mmap要调用fb_pgprotect(file, vma, off);将page的cache关掉呢,向该page写入数据访问速度奇慢无比,尤其对几十M的大数据量操作时,更是难以忍受,将其去掉之后,速度那是缸缸的!
/* This is an IO map - tell maydump to skip this VMA */
static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
                unsigned long off)
{
    if (boot_cpu_data.x86 > 3)
        pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
}

后来在http://blog.163.com/shenbin62349962/blog/static/5800864020083169180610/
找到了原因:因为lcd的framebuffer如果是直接位于LCD面板上的话,那么当然需要配置为IO空间,进而也就不应该有cpu缓存,在fbmem.c的fb_mmap中,如果lcd驱动程序没有提供fb->fb_mmap方法,那么于fbmem.c默认使用lcd内部的硬件ram,所以加入了_PAGE_PCD位,禁止缓存该区间内的所有页,引用设备内存不应当被处理器缓存

PS:
从drivers/video/vfb.c获得的信息是,VM_RESERVED必须设置.
vma->vm_flags |= VM_RESERVED;    /* avoid to swap out this VMA */

PS:
drivers/video/bfin-t350mcqb-fb.c
static int bfin_bf54x_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
{

    struct bfin_bf54xfb_info *fbi = info->par;

    if (fbi->lq043_mmap)
        return -1;

    spin_lock(&fbi->lock);
    fbi->lq043_mmap = 1;
    spin_unlock(&fbi->lock);

    vma->vm_start = (unsigned long)(fbi->fb_buffer);

    vma->vm_end = vma->vm_start + info->fix.smem_len;
    /* For those who don't understand how mmap works, go read
     *   Documentation/nommu-mmap.txt.
     * For those that do, you will know that the VM_MAYSHARE flag
     * must be set in the vma->vm_flags structure on noMMU
     *   Other flags can be set, and are documented in
     *   include/linux/mm.h
     */
    vma->vm_flags |=  VM_MAYSHARE | VM_SHARED;  // 这个是我们需要的.[luther.gliethttp]

    return 0;
}

PS:
来自include/asm-generic/cacheflush.h文件的信息
/*
 * The cache doesn't need to be flushed when TLB entries change when
 * the cache is mapped to physical memory, not virtual memory
 */
从这里来看,如果mmap或者自己用do_mmap_pgoff()自定义一块kmalloc到的内核内存到user空间,
那么当user空间拷贝完数据之后,如果执行了ioctl或者user空间进程被调度,将导致调度程序,切换时
执行flush操作,所以用户空间直接写入的到kmalloc内核空间的数据,也就被flush到DDR上,因此数据不会发生非一致性问题,所以像flush_dcache_page(pages[i]);等回写函数也就不用单独去调用了.

.mmap       = gliethttp_card_mmap,
static int gliethttp_card_mmap(struct file *file, struct vm_area_struct * vma)
{
    vma->vm_pgoff = page_to_pfn(virt_to_page(file->private_data)) << PAGE_SHIFT;
    /*
    // This is an IO map - tell maydump to skip this VMA
    vma->vm_flags |= VM_IO | VM_RESERVED;

    if (boot_cpu_data.x86 > 3) {
        log_printf("boot_cpu_data.x86\n");
        pgprot_val(vma->vm_page_prot) |= _PAGE_PCD; // fb_mmap==>fb_pgprotect
    }*/
    vma->vm_flags |= VM_RESERVED;    /* avoid to swap out this VMA */
    if (io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff >> PAGE_SHIFT,
                 vma->vm_end - vma->vm_start, vma->vm_page_prot))
        return -EAGAIN;
    return 0;
}

static long gliethttp_do_mmap(struct file *file, void *phy, size_t len)
{
    int error = -EBADF;
    struct mm_struct *mm = current->mm;
    unsigned long prot = PROT_READ | PROT_WRITE;
    unsigned long flags = MAP_SHARED;

    file->private_data = phy;
    flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);

    down_write(&mm->mmap_sem);
    error = do_mmap_pgoff(file, 0, len, prot, flags, 0);
    up_write(&mm->mmap_sem);

    return error;
}
阅读(4796) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

2011-05-22 15:39:15

学习了,多谢楼主分享哦!也欢迎广大linux爱好者来我的论坛一起讨论arm哦!www.lt-net.cn