Fix cma_heap_buffer mutex lock area to protect vmap_cnt and vaddr. And move struct dma_heap_attachment to dma-heap.h so that vendor dma heaps can use it, the same behaviour as struct dma_buf_attachment.
Fixes: a5d2d29e24be ("dma-buf: heaps: Move heap-helper logic into the cma_heap implementation") Signed-off-by: Weizhao Ouyang o451686892@gmail.com --- Resend to correct email addresses.
drivers/dma-buf/heaps/cma_heap.c | 25 ++++++++++--------------- drivers/dma-buf/heaps/system_heap.c | 12 ++---------- include/linux/dma-heap.h | 15 +++++++++++++++ 3 files changed, 27 insertions(+), 25 deletions(-)
diff --git a/drivers/dma-buf/heaps/cma_heap.c b/drivers/dma-buf/heaps/cma_heap.c index 0c05b79870f9..23dad5b6421e 100644 --- a/drivers/dma-buf/heaps/cma_heap.c +++ b/drivers/dma-buf/heaps/cma_heap.c @@ -40,13 +40,6 @@ struct cma_heap_buffer { void *vaddr; };
-struct dma_heap_attachment { - struct device *dev; - struct sg_table table; - struct list_head list; - bool mapped; -}; - static int cma_heap_attach(struct dma_buf *dmabuf, struct dma_buf_attachment *attachment) { @@ -58,7 +51,7 @@ static int cma_heap_attach(struct dma_buf *dmabuf, if (!a) return -ENOMEM;
- ret = sg_alloc_table_from_pages(&a->table, buffer->pages, + ret = sg_alloc_table_from_pages(a->table, buffer->pages, buffer->pagecount, 0, buffer->pagecount << PAGE_SHIFT, GFP_KERNEL); @@ -90,7 +83,7 @@ static void cma_heap_detach(struct dma_buf *dmabuf, list_del(&a->list); mutex_unlock(&buffer->lock);
- sg_free_table(&a->table); + sg_free_table(a->table); kfree(a); }
@@ -98,12 +91,12 @@ static struct sg_table *cma_heap_map_dma_buf(struct dma_buf_attachment *attachme enum dma_data_direction direction) { struct dma_heap_attachment *a = attachment->priv; - struct sg_table *table = &a->table; + struct sg_table *table = a->table; int ret;
ret = dma_map_sgtable(attachment->dev, table, direction, 0); if (ret) - return ERR_PTR(-ENOMEM); + return ERR_PTR(ret); a->mapped = true; return table; } @@ -124,14 +117,15 @@ static int cma_heap_dma_buf_begin_cpu_access(struct dma_buf *dmabuf, struct cma_heap_buffer *buffer = dmabuf->priv; struct dma_heap_attachment *a;
+ mutex_lock(&buffer->lock); + if (buffer->vmap_cnt) invalidate_kernel_vmap_range(buffer->vaddr, buffer->len);
- mutex_lock(&buffer->lock); list_for_each_entry(a, &buffer->attachments, list) { if (!a->mapped) continue; - dma_sync_sgtable_for_cpu(a->dev, &a->table, direction); + dma_sync_sgtable_for_cpu(a->dev, a->table, direction); } mutex_unlock(&buffer->lock);
@@ -144,14 +138,15 @@ static int cma_heap_dma_buf_end_cpu_access(struct dma_buf *dmabuf, struct cma_heap_buffer *buffer = dmabuf->priv; struct dma_heap_attachment *a;
+ mutex_lock(&buffer->lock); + if (buffer->vmap_cnt) flush_kernel_vmap_range(buffer->vaddr, buffer->len);
- mutex_lock(&buffer->lock); list_for_each_entry(a, &buffer->attachments, list) { if (!a->mapped) continue; - dma_sync_sgtable_for_device(a->dev, &a->table, direction); + dma_sync_sgtable_for_device(a->dev, a->table, direction); } mutex_unlock(&buffer->lock);
diff --git a/drivers/dma-buf/heaps/system_heap.c b/drivers/dma-buf/heaps/system_heap.c index ab7fd896d2c4..aac8fc660ea6 100644 --- a/drivers/dma-buf/heaps/system_heap.c +++ b/drivers/dma-buf/heaps/system_heap.c @@ -17,7 +17,6 @@ #include <linux/highmem.h> #include <linux/mm.h> #include <linux/module.h> -#include <linux/scatterlist.h> #include <linux/slab.h> #include <linux/vmalloc.h>
@@ -33,13 +32,6 @@ struct system_heap_buffer { void *vaddr; };
-struct dma_heap_attachment { - struct device *dev; - struct sg_table *table; - struct list_head list; - bool mapped; -}; - #define LOW_ORDER_GFP (GFP_HIGHUSER | __GFP_ZERO | __GFP_COMP) #define MID_ORDER_GFP (LOW_ORDER_GFP | __GFP_NOWARN) #define HIGH_ORDER_GFP (((GFP_HIGHUSER | __GFP_ZERO | __GFP_NOWARN \ @@ -68,7 +60,7 @@ static struct sg_table *dup_sg_table(struct sg_table *table) ret = sg_alloc_table(new_table, table->orig_nents, GFP_KERNEL); if (ret) { kfree(new_table); - return ERR_PTR(-ENOMEM); + return ERR_PTR(ret); }
new_sg = new_table->sgl; @@ -94,7 +86,7 @@ static int system_heap_attach(struct dma_buf *dmabuf, table = dup_sg_table(&buffer->sg_table); if (IS_ERR(table)) { kfree(a); - return -ENOMEM; + return PTR_ERR(table); }
a->table = table; diff --git a/include/linux/dma-heap.h b/include/linux/dma-heap.h index 0c05561cad6e..7d02aefe0e78 100644 --- a/include/linux/dma-heap.h +++ b/include/linux/dma-heap.h @@ -11,6 +11,7 @@
#include <linux/cdev.h> #include <linux/types.h> +#include <linux/scatterlist.h>
struct dma_heap;
@@ -41,6 +42,20 @@ struct dma_heap_export_info { void *priv; };
+/** + * struct dma_heap_attachment - holds device-heap attachment data + * @dev: device attached to the heap + * @table: sgtables for tracking the associated pages + * @list: list of dma_heap_attachment + * @mapped: true if attachment is actually mapped on the device + */ +struct dma_heap_attachment { + struct device *dev; + struct sg_table *table; + struct list_head list; + bool mapped; +}; + /** * dma_heap_get_drvdata() - get per-heap driver data * @heap: DMA-Heap to retrieve private data for
On Tue, Dec 28, 2021 at 11:09 PM Weizhao Ouyang o451686892@gmail.com wrote:
Fix cma_heap_buffer mutex lock area to protect vmap_cnt and vaddr. And move struct dma_heap_attachment to dma-heap.h so that vendor dma heaps can use it, the same behaviour as struct dma_buf_attachment.
Hey! Thanks for submitting this patch! Apologies for the slow reply (was out for the holidays).
This patch is combining two changes in one patch, so they need to be split up. The locking change looks sane, but moving the dma_heap_attachment may need some extra justification as changing upstream code just to support out of tree code isn't usually done (if there was some benefit to the in-tree code, that would be fine though).
I'd also be eager to try to get the vendor heap to be merged, assuming we can also merge an upstream user for it.
thanks -john
Thanks for reply.
On 2022/1/4 02:45, John Stultz wrote:
On Tue, Dec 28, 2021 at 11:09 PM Weizhao Ouyang o451686892@gmail.com wrote:
Fix cma_heap_buffer mutex lock area to protect vmap_cnt and vaddr. And move struct dma_heap_attachment to dma-heap.h so that vendor dma heaps can use it, the same behaviour as struct dma_buf_attachment.
Hey! Thanks for submitting this patch! Apologies for the slow reply (was out for the holidays).
This patch is combining two changes in one patch, so they need to be split up. The locking change looks sane, but moving the dma_heap_attachment may need some extra justification as changing upstream code just to support out of tree code isn't usually done (if there was some benefit to the in-tree code, that would be fine though).
I'd also be eager to try to get the vendor heap to be merged, assuming we can also merge an upstream user for it.
Yeap moving the dma_heap_attachment need more sufficient reason, and it should add a private area to adapt vendor heap change if we move it to in-tree code. So just drop the idea now :)
I will send a new patch to clarify the locking change later.
Thanks, Weizhao
dri-devel@lists.freedesktop.org