From mboxrd@z Thu Jan 1 00:00:00 1970 From: Christoph Hellwig Subject: Re: [RFC][PATCH 2/5 v2] dma-buf: heaps: Add heap helpers Date: Fri, 15 Mar 2019 02:06:46 -0700 Message-ID: <20190315090646.GC4470@infradead.org> References: <1551819273-640-1-git-send-email-john.stultz@linaro.org> <1551819273-640-3-git-send-email-john.stultz@linaro.org> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Return-path: Content-Disposition: inline In-Reply-To: <1551819273-640-3-git-send-email-john.stultz@linaro.org> Sender: linux-kernel-owner@vger.kernel.org To: John Stultz Cc: lkml , Laura Abbott , Benjamin Gaignard , Greg KH , Sumit Semwal , Liam Mark , Brian Starkey , "Andrew F . Davis" , Chenbo Feng , Alistair Strachan , dri-devel@lists.freedesktop.org List-Id: dri-devel@lists.freedesktop.org > +static void *dma_heap_map_kernel(struct heap_helper_buffer *buffer) > +{ > + struct scatterlist *sg; > + int i, j; > + void *vaddr; > + pgprot_t pgprot; > + struct sg_table *table = buffer->sg_table; > + int npages = PAGE_ALIGN(buffer->heap_buffer.size) / PAGE_SIZE; > + struct page **pages = vmalloc(array_size(npages, > + sizeof(struct page *))); > + struct page **tmp = pages; > + > + if (!pages) > + return ERR_PTR(-ENOMEM); > + > + pgprot = PAGE_KERNEL; > + > + for_each_sg(table->sgl, sg, table->nents, i) { > + int npages_this_entry = PAGE_ALIGN(sg->length) / PAGE_SIZE; > + struct page *page = sg_page(sg); > + > + WARN_ON(i >= npages); > + for (j = 0; j < npages_this_entry; j++) > + *(tmp++) = page++; This should probably use nth_page. That being said I really wish we could have a more iterative version of vmap, where the caller does a get_vm_area_caller and then adds each chunk using another call, including the possibility of mapping larger than PAGE_SIZE contigous ones. Any chance you could look into that? > + ret = remap_pfn_range(vma, addr, page_to_pfn(page), len, > + vma->vm_page_prot); So the same chunk could be mapped to userspace and vmap, and later on also DMA mapped. Who is going to take care of cache aliasing as I see nothing of that in this series? > + if (buffer->kmap_cnt) { > + buffer->kmap_cnt++; > + return buffer->vaddr; > + } > + vaddr = dma_heap_map_kernel(buffer); > + if (WARN_ONCE(!vaddr, > + "heap->ops->map_kernel should return ERR_PTR on error")) > + return ERR_PTR(-EINVAL); > + if (IS_ERR(vaddr)) > + return vaddr; > + buffer->vaddr = vaddr; > + buffer->kmap_cnt++; The cnt manioulation is odd. The normal way to make this readable is to use a postfix op on the check, as that makes it clear to everyone, e.g.: if (buffer->kmap_cnt++) return buffer->vaddr; .. > + buffer->kmap_cnt--; > + if (!buffer->kmap_cnt) { > + vunmap(buffer->vaddr); > + buffer->vaddr = NULL; > + } Same here, just with an infix. > +static inline void INIT_HEAP_HELPER_BUFFER(struct heap_helper_buffer *buffer, > + void (*free)(struct heap_helper_buffer *)) > +{ > + buffer->private_flags = 0; > + buffer->priv_virt = NULL; > + mutex_init(&buffer->lock); > + buffer->kmap_cnt = 0; > + buffer->vaddr = NULL; > + buffer->sg_table = NULL; > + INIT_LIST_HEAD(&buffer->attachments); > + buffer->free = free; > +} There is absolutely no reason to inlines this as far as I can tell. Also it would seem much simpler to simply let the caller assign the free callback.