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