Re: how to mmap in videobuf-dma-sg.c

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, 2009-05-21 at 18:48 +0800, Figo.zhang wrote:
> On Thu, 2009-05-21 at 07:35 -0300, Mauro Carvalho Chehab wrote:
> > Em Thu, 21 May 2009 12:46:04 +0800
> > "Figo.zhang" <figo1802@xxxxxxxxx> escreveu:
> > 
> > > hi,all,
> > >  I am puzzle that how to mmap ( V4L2_MEMORY_MMAP) in videobuf-dma-sg.c?
> > > 
> > > In this file, it alloc the momery using vmalloc_32() , and put this
> > > momery into sglist table,and then use dma_map_sg() to create sg dma at
> > > __videobuf_iolock() function. but in __videobuf_mmap_mapper(), i canot
> > > understand how it do the mmap? 
> > > why it not use the remap_vmalloc_range() to do the mmap?
> > 
> > The answer is simple: remap_vmalloc_range() is newer than videobuf code. This
> > part of the code was written back to kernel 2.4, and nobody cared to update it
> > to use those newer functions, and simplify its code.
> > 
> > If you want, feel free to propose some cleanups on it
> > 
> > 
> > 
> > Cheers,
> > Mauro
> 
> hi mauro,
> Thank you! 
> But i canot found the similar function code of remap_vmalloc_range() in
> the videobuf-dma-contig.c file. So i want to know the how is work in
> __videobuf_mmap_mapper() function?
> 
> 

hi mauro:
Thank you. But i still have a puzzle question about mmap() in
videobuf-dma-sg.c. I canot find how to remap the dma buffer
(which alloc by vmalloc_32()) to the vma area in
__videobuf_mmap_mapper()? 

there is my test driver code about dma-sg,it work well. i use
remap_pfn_range() to remap the dma buffer to vma area in mmap method.

so would you like to give me some detail about it?

Best Regards,

Figo.zhang


static int mydev_alloc_dma_sg(struct mydev_device *dev, struct mydev_buf
*buf)
{
	int nr_pages;
	
	int i;
	struct page *pg;
	unsigned char * virt;

	nr_pages = mydev_buffer_pages(buf->size);

	buf->nr_pages = nr_pages;

	dprintk("%s:: buf->nr_pages =%d\n", __func__, buf->nr_pages);
	
	buf->sglist = kcalloc(buf->nr_pages, sizeof(struct scatterlist),
GFP_KERNEL);
	if (NULL == buf->sglist)
		return NULL;
	
	sg_init_table(buf->sglist, buf->nr_pages);

	buf->vmalloc = vmalloc_32(buf->nr_pages << PAGE_SHIFT);

	memset(buf->vmalloc,0,buf->nr_pages << PAGE_SHIFT);

	virt = buf->vmalloc;
	
	for(i = 0; i< buf->nr_pages; i++,virt += PAGE_SIZE){
		pg = vmalloc_to_page(virt);
		if (NULL == pg)
			goto nopage;
		BUG_ON(PageHighMem(pg));
		sg_set_page(&buf->sglist[i], pg, PAGE_SIZE, 0);
		
		}

	buf->sglen = dma_map_sg(&dev->pci->dev, buf->sglist,
					buf->nr_pages, DMA_FROM_DEVICE);

	return 0;
	
 nopage:
	dprintk("sgl: oops - no page\n");
	kfree(buf->sglist);
	return 0;
}

in mmap();

static int do_mmap_sg(struct mydev_device  *dev, struct vm_area_struct *
vma)
{
	struct videobuf_mapping *map;
	unsigned long pos,page;
	unsigned long start = vma->vm_start;
	unsigned long size = vma->vm_end - vma->vm_start;
	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
	unsigned int first, last, end;

	int retval = -EINVAL;
	int i;

	/* look for first buffer to map */
	for (first = 0; first < VIDEO_MAX_FRAME; first++) {
	
		if (dev->ktbuf[first].boff == (vma->vm_pgoff << PAGE_SHIFT))
			break;
	}
	if (VIDEO_MAX_FRAME == first) {
		dprintk("mmap app bug: offset invalid [offset=0x%lx]\n",
			(vma->vm_pgoff << PAGE_SHIFT));
		goto done;
	}
	/* create mapping + update buffer list */
	retval = -ENOMEM;
	map = kmalloc(sizeof(struct videobuf_mapping),GFP_KERNEL);
	if (NULL == map)
		goto done;

		pos = (unsigned long)dev->ktbuf[first].vmalloc;

	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;
	}

	map->count    = 1;
	map->start    = vma->vm_start;
	map->end      = vma->vm_end;
	vma->vm_ops   = &mydev_vm_ops;
	vma->vm_flags |=/* VM_DONTEXPAND |*/ VM_RESERVED;
vma->vm_flags &= ~VM_IO; /* using shared anonymous pages */
	vma->vm_private_data = map;

	mydev_vm_open(vma);
	retval = 0;

 done:
	return retval;
}





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

[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux