title: mmap'ed memory access very slow
body: <p>I use v4l2 to get video frame from camera using streaming io and need to do some calculation on the frame.</p>
  
  <p>However, accessing the frame memory is 10 times slower than allocating
  a malloc'ed memory.</p>
  
  <p><strong>I guess the mmap'ed frame memory is not cacheable by cpu.</strong></p>
  
  <p>Here is the test code.</p>
  
  <pre><code>//mmap video buffers
  struct v4l2_buffer buf;
  CLEAR(buf);
  buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  buf.memory = V4L2_MEMORY_MMAP;
  buf.index = i;
  if (-1 == xioctl(_fdCamera, VIDIOC_QUERYBUF, &amp;buf)) {
      ERROR("VIDIOC_QUERYBUF");
      goto error_querybuf;
  }
  _buffers[i].start = mmap(NULL, buf.length,
  PROT_READ | PROT_WRITE,
  MAP_SHARED, _fdCamera, buf.m.offset);
  
  
  //use mmap'ed buffer to do some calculation
  u16* frame=_buffers[0].start;
  
  u64 sum=0;
  u16* p=frame;
  time[0]=GetMicrosecond64();
  while(p!=frame+PIXELS){
      sum+=*p;
      p++;
  }
  time[1]=GetMicrosecond64();
  printf("mmap:sum %lld,time %lld\n",sum, time[1] - time[0]);
  
  //use a copy of data to do some calculation
  u16* frame_copy=(u16*)malloc(PIXELS*2);
  memcpy(frame_copy,frame,PIXELS*2);
  sum=0;
  p=frame_copy;
  time[0]=GetMicrosecond64();
  while(p!=frame_copy+PIXELS){
      sum+=*p;
      p++;
  }
  time[1]=GetMicrosecond64();
  printf("malloc:sum %lld,time %lld\n",sum, time[1] - time[0]);
  </code></pre>
  
  <p><strong>update</strong>:</p>
  
  <p>I use s5pv210 with linux-2.6.35.The fimc_dev.c indicates the mmaped is uncached.</p>
  
  <p><strong>How to make the frame buffer memory support both DMA and cache?</strong></p>
  
  <pre><code>static inline int fimc_mmap_cap(struct file *filp, struct vm_area_struct *vma)
  {
      struct fimc_prv_data *prv_data =
                  (struct fimc_prv_data *)filp-&gt;private_data;
      struct fimc_control *ctrl = prv_data-&gt;ctrl;
      u32 size = vma-&gt;vm_end - vma-&gt;vm_start;
      u32 pfn, idx = vma-&gt;vm_pgoff;
  
      vma-&gt;vm_page_prot = pgprot_noncached(vma-&gt;vm_page_prot);
      vma-&gt;vm_flags |= VM_RESERVED;
  
      /*
       * page frame number of the address for a source frame
       * to be stored at.
       */
      pfn = __phys_to_pfn(ctrl-&gt;cap-&gt;bufs[idx].base[0]);
  
      if ((vma-&gt;vm_flags &amp; VM_WRITE) &amp;&amp; !(vma-&gt;vm_flags &amp; VM_SHARED)) {
          fimc_err("%s: writable mapping must be shared\n", __func__);
          return -EINVAL;
      }
  
      if (remap_pfn_range(vma, vma-&gt;vm_start, pfn, size, vma-&gt;vm_page_prot)) {
          fimc_err("%s: mmap fail\n", __func__);
          return -EINVAL;
      }
  
      return 0;
  }
  </code></pre>