Hi Marek,

On Monday 29 November 2010 14:24:35 Marek Szyprowski wrote:
> On Monday, November 29, 2010 10:39 AM Laurent Pinchart wrote:
> > On Friday 19 November 2010 16:55:39 Marek Szyprowski wrote:
> > > From: Pawel Osciak <p.osc...@samsung.com>
> > > 
> > > Add generic memory handling routines for userspace pointer handling,
> > > contiguous memory verification and mapping.
> > > 
> > > Signed-off-by: Pawel Osciak <p.osc...@samsung.com>
> > > Signed-off-by: Marek Szyprowski <m.szyprow...@samsung.com>
> > > Signed-off-by: Kyungmin Park <kyungmin.p...@samsung.com>
> > > CC: Pawel Osciak <pa...@osciak.com>

[snip]

> > > + if (ret) {
> > > +         printk(KERN_ERR "Invalid userspace address\n");
> > > +         goto done;
> > > + }
> > > +
> > > + *paddr = (curr_pfn << PAGE_SHIFT) + offset;
> > > +
> > > + for (i = 1; i < num_pages; ++i) {
> > > +         prev_pfn = curr_pfn;
> > > +         vaddr += PAGE_SIZE;
> > > +
> > > +         ret = follow_pfn(vma, vaddr, &curr_pfn);
> > > +         if (ret || curr_pfn != prev_pfn + 1) {
> > > +                 printk(KERN_ERR "Invalid userspace address\n");
> > > +                 ret = -EINVAL;
> > 
> > I would use -EFAULT when curr_pfn != prev_pfn + 1.
> 
> I don't think that this situation desires for a EFAULT error code. EINVAL
> is imho enough to let application know that this memory cannot be used for
> the userptr buffer.

-EINVAL is used quite a lot already to report many different error conditions. 
-EFAULT would let application know that the issue is about the pointer address 
as opposed to the buffer index for instance.

[snip]

> > > + * Returns 0 on success.
> > > + */
> > > +int vb2_mmap_pfn_range(struct vm_area_struct *vma, unsigned long
> > > paddr, +                          unsigned long size,
> > > +                         const struct vm_operations_struct *vm_ops,
> > > +                         void *priv)
> > > +{
> > > + int ret;
> > > +
> > > + size = min_t(unsigned long, vma->vm_end - vma->vm_start, size);
> > > +
> > > + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
> > 
> > Now we're getting to the dirty part :-) Do we always want to map the
> > memory uncached ?
> 
> That's how it is handled by the videobuf1 and probably most of drivers that
> use physically contiguous memory. I don't want to change it right now.
> This will be a way too much for a single step. Once drivers will settle
> down on vb2 we may start thinking of adding support for CACHED vs.
> UNCACHED mappings.

OK.

> > I'm not too sure about what the use cases for this function are. It seems
> > to be used by the DMA coherent and CMA allocators. Are you sure they
> > will always use physically contiguous memory ?
> 
> Yes, both of them are designed for physically contiguous memory. I just
> noticed that the videobuf1 used the dma-contig name which is a bit better
> for this case. ;)

OK.

> > > + ret = remap_pfn_range(vma, vma->vm_start, paddr >> PAGE_SHIFT,
> > > +                         size, vma->vm_page_prot);
> > > + if (ret) {
> > > +         printk(KERN_ERR "Remapping memory failed, error: %d\n", ret);
> > > +         return ret;
> > > + }
> > > +
> > > + vma->vm_flags           |= VM_DONTEXPAND | VM_RESERVED;
> > > + vma->vm_private_data    = priv;
> > > + vma->vm_ops             = vm_ops;
> > > +
> > > + vm_ops->open(vma);
> > > +
> > > + printk(KERN_DEBUG "%s: mapped paddr 0x%08lx at 0x%08lx, size %ld\n",
> > > +                 __func__, paddr, vma->vm_start, size);
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +/**
> > > + * vb2_get_userptr() - acquire an area pointed to by userspace addres
> > > vaddr + * @vaddr: virtual userspace address to the given area
> > > + *
> > > + * This function attempts to acquire an area mapped in the userspace
> > > for + * the duration of a hardware operation.
> > > + *
> > > + * Returns a virtual memory region associated with the given vaddr on
> > > success + * or NULL.
> > > + */
> > > +struct vm_area_struct *vb2_get_userptr(unsigned long vaddr)
> > > +{
> > > + struct mm_struct *mm = current->mm;
> > > + struct vm_area_struct *vma;
> > > + struct vm_area_struct *vma_copy;
> > > +
> > > + vma_copy = kmalloc(sizeof(struct vm_area_struct), GFP_KERNEL);
> > > + if (vma_copy == NULL)
> > > +         return NULL;
> > > +
> > > + down_read(&mm->mmap_sem);
> > > +
> > > + vma = find_vma(mm, vaddr);
> > > + if (!vma)
> > > +         goto done;
> > > +
> > > + if (vma->vm_ops && vma->vm_ops->open)
> > > +         vma->vm_ops->open(vma);
> > > +
> > > + if (vma->vm_file)
> > > +         get_file(vma->vm_file);
> > 
> > Could you explain what this is for ?
> 
> This is called when you access physically contiguous memory from different
> device which has been earlier mmaped by the application. This way
> applications uses userptr mode with dmacontig. When doing this, you must
> ensure somehow that this memory won't be released/freed before you finish.
> This is achieved by calling open() callback and increasing the use count
> of the mmaped file. Same things happen when your application calls fork()
> and a new process gets access to your mmaped device.

Good point.

Don't you also need to pin the pages to memory with get_user_pages() ?

-- 
Regards,

Laurent Pinchart
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to