The allocation of dma_buf_attachment is moved to attach callback. The initialization is left in map callback.
Signed-off-by: Tomasz Stanislawski t.stanislaws@samsung.com Signed-off-by: Kyungmin Park kyungmin.park@samsung.com --- drivers/media/video/videobuf2-dma-contig.c | 39 ++++++++++++++++++---------- 1 file changed, 26 insertions(+), 13 deletions(-)
diff --git a/drivers/media/video/videobuf2-dma-contig.c b/drivers/media/video/videobuf2-dma-contig.c index b5caf1d..3bf7c45 100644 --- a/drivers/media/video/videobuf2-dma-contig.c +++ b/drivers/media/video/videobuf2-dma-contig.c @@ -285,7 +285,15 @@ struct vb2_dc_attachment { static int vb2_dc_dmabuf_ops_attach(struct dma_buf *dbuf, struct device *dev, struct dma_buf_attachment *dbuf_attach) { - /* nothing to be done */ + struct vb2_dc_attachment *attach; + + attach = kzalloc(sizeof *attach, GFP_KERNEL); + if (!attach) + return -ENOMEM; + + attach->dir = DMA_NONE; + dbuf_attach->priv = attach; + return 0; }
@@ -300,7 +308,9 @@ static void vb2_dc_dmabuf_ops_detach(struct dma_buf *dbuf,
sgt = &attach->sgt;
- dma_unmap_sg(db_attach->dev, sgt->sgl, sgt->nents, attach->dir); + /* checking if scaterlist was ever mapped */ + if (attach->dir != DMA_NONE) + dma_unmap_sg(db_attach->dev, sgt->sgl, sgt->nents, attach->dir); sg_free_table(sgt); kfree(attach); db_attach->priv = NULL; @@ -314,25 +324,28 @@ static struct sg_table *vb2_dc_dmabuf_ops_map( struct vb2_dc_attachment *attach = db_attach->priv; struct sg_table *sgt; struct scatterlist *rd, *wr; - int i, ret; + int ret; + unsigned int i; + + if (WARN_ON(dir == DMA_NONE)) + return ERR_PTR(-EINVAL);
/* return previously mapped sg table */ - if (attach) + if (attach->dir == dir) return &attach->sgt;
- attach = kzalloc(sizeof *attach, GFP_KERNEL); - if (!attach) - return ERR_PTR(-ENOMEM); + /* reattaching is not allowed */ + if (WARN_ON(attach->dir != DMA_NONE)) + return ERR_PTR(-EBUSY);
sgt = &attach->sgt; - attach->dir = dir;
- /* copying the buf->base_sgt to attachment */ + /* Copy the buf->base_sgt scatter list to the attachment, as we can't + * map the same scatter list to multiple attachments at the same time. + */ ret = sg_alloc_table(sgt, buf->sgt_base.orig_nents, GFP_KERNEL); - if (ret) { - kfree(attach); + if (ret) return ERR_PTR(-ENOMEM); - }
rd = buf->sgt_base.sgl; wr = sgt->sgl; @@ -347,10 +360,10 @@ static struct sg_table *vb2_dc_dmabuf_ops_map( if (ret <= 0) { printk(KERN_ERR "failed to map scatterlist\n"); sg_free_table(sgt); - kfree(attach); return ERR_PTR(-EIO); }
+ attach->dir = dir; db_attach->priv = attach;
return sgt;