From mboxrd@z Thu Jan 1 00:00:00 1970 From: Paulius Zaleckas Date: Tue, 08 Jul 2008 14:33:07 +0000 Subject: Re: [PATCH 03/04] videobuf: Add physically contiguous queue code Message-Id: <48737AA3.3080902@teltonika.lt> List-Id: References: <20080705025335.27137.98068.sendpatchset@rx1.opensource.se> <20080705025405.27137.16206.sendpatchset@rx1.opensource.se> In-Reply-To: <20080705025405.27137.16206.sendpatchset@rx1.opensource.se> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: video4linux-list@redhat.com Cc: linux-sh@vger.kernel.org Magnus Damm wrote: > This is V2 of the physically contiguous videobuf queues patch. > Useful for hardware such as the SuperH Mobile CEU which doesn't > support scatter gatter bus mastering. spelling gatther :) > +static int __videobuf_mmap_mapper(struct videobuf_queue *q, > + struct vm_area_struct *vma) > +{ > + struct videobuf_dma_contig_memory *mem; > + struct videobuf_mapping *map; > + unsigned int first; > + int retval; > + unsigned long size, offset = vma->vm_pgoff << PAGE_SHIFT; > + > + dev_dbg(q->dev, "%s\n", __func__); > + if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED)) > + return -EINVAL; > + > + /* look for first buffer to map */ > + for (first = 0; first < VIDEO_MAX_FRAME; first++) { > + if (!q->bufs[first]) > + continue; > + > + if (V4L2_MEMORY_MMAP != q->bufs[first]->memory) > + continue; > + if (q->bufs[first]->boff = offset) > + break; > + } > + if (VIDEO_MAX_FRAME = first) { > + dev_dbg(q->dev, "invalid user space offset [offset=0x%lx]\n", > + offset); > + return -EINVAL; > + } > + > + /* create mapping + update buffer list */ > + map = kzalloc(sizeof(struct videobuf_mapping), GFP_KERNEL); > + if (!map) > + return -ENOMEM; > + > + q->bufs[first]->map = map; > + map->start = vma->vm_start; > + map->end = vma->vm_end; > + map->q = q; > + > + q->bufs[first]->baddr = vma->vm_start; > + > + mem = q->bufs[first]->priv; > + BUG_ON(!mem); > + MAGIC_CHECK(mem->magic, MAGIC_DC_MEM); > + > + mem->size = PAGE_ALIGN(q->bufs[first]->bsize); > + mem->vaddr = dma_alloc_coherent(q->dev, mem->size, > + &mem->dma_handle, GFP_KERNEL); > + if (!mem->vaddr) { > + dev_err(q->dev, "dma_alloc_coherent size %ld failed\n", > + mem->size); > + goto error; > + } > + dev_dbg(q->dev, "dma_alloc_coherent data is at addr %p (size %ld)\n", > + mem->vaddr, mem->size); > + > + /* Try to remap memory */ > + > + size = vma->vm_end - vma->vm_start; > + size = (size < mem->size) ? size : mem->size; > + > + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); > + retval = remap_pfn_range(vma, vma->vm_start, > + __pa(mem->vaddr) >> PAGE_SHIFT, __pa(mem->vaddr) doesn't work on ARM architecture... It is a long story about handling memory allocations and mapping for ARM (there is dma_mmap_coherent to deal with this), but there is a workaround: mem->dma_handle >> PAGE_SHIFT, It is safe to do it this way and also saves some CPU instructions :) > + size, vma->vm_page_prot); > + if (retval) { > + dev_err(q->dev, "mmap: remap failed with error %d. ", retval); > + dma_free_coherent(q->dev, mem->size, > + mem->vaddr, mem->dma_handle); > + goto error; > + } > + > + vma->vm_ops = &videobuf_vm_ops; > + vma->vm_flags |= VM_DONTEXPAND; > + vma->vm_private_data = map; > + > + dev_dbg(q->dev, "mmap %p: q=%p %08lx-%08lx (%lx) pgoff %08lx buf %d\n", > + map, q, vma->vm_start, vma->vm_end, > + (long int) q->bufs[first]->bsize, > + vma->vm_pgoff, first); > + > + videobuf_vm_open(vma); > + > + return 0; > + > +error: > + kfree(map); > + return -ENOMEM; > +}