[RESEND PATCH 2/2] drm: GEM CMA: Add DRM PRIME support

Laurent Pinchart laurent.pinchart at ideasonboard.com
Tue Apr 16 05:09:24 PDT 2013


Hi Rob,

Thank you for the review.

On Monday 15 April 2013 15:00:58 Rob Clark wrote:
> Hi Laurent, a few mostly-minor comments, although from a quick look
> the sg_alloc_table()/sg_free_table() doesn't look quite right in all
> cases.  The other comments could just be a subject for a later patch
> if it is something that somebody needs some day..
> 
> On Mon, Apr 15, 2013 at 9:57 AM, Laurent Pinchart wrote:
> > Signed-off-by: Laurent Pinchart
> > <laurent.pinchart+renesas at ideasonboard.com>
> > ---
> > 
> >  drivers/gpu/drm/drm_gem_cma_helper.c | 311 +++++++++++++++++++++++++++++-
> >  include/drm/drm_gem_cma_helper.h     |   9 +
> >  2 files changed, 317 insertions(+), 3 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/drm_gem_cma_helper.c
> > b/drivers/gpu/drm/drm_gem_cma_helper.c index 8cce330..c428a51 100644
> > --- a/drivers/gpu/drm/drm_gem_cma_helper.c
> > +++ b/drivers/gpu/drm/drm_gem_cma_helper.c

[snip]

> > +static struct sg_table *
> > +drm_gem_cma_dmabuf_map(struct dma_buf_attachment *attach,
> > +                      enum dma_data_direction dir)
> > +{
> > +       struct drm_gem_cma_dmabuf_attachment *cma_attach = attach->priv;
> > +       struct drm_gem_cma_object *cma_obj = attach->dmabuf->priv;
> > +       struct drm_device *drm = cma_obj->base.dev;
> > +       struct scatterlist *rd, *wr;
> > +       struct sg_table *sgt;
> > +       unsigned int i;
> > +       int nents, ret;
> > +
> > +       DRM_DEBUG_PRIME("\n");
> > +
> > +       if (WARN_ON(dir == DMA_NONE))
> > +               return ERR_PTR(-EINVAL);
> > +
> > +       /* Return the cached mapping when possible. */
> > +       if (cma_attach->dir == dir)
> > +               return &cma_attach->sgt;
> > +
> > +       /* Two mappings with different directions for the same attachment
> > +        * are not allowed.
> > +        */
> > +       if (WARN_ON(cma_attach->dir != DMA_NONE))
> > +               return ERR_PTR(-EBUSY);
> > +
> > +       sgt = &cma_attach->sgt;
> > +
> > +       ret = sg_alloc_table(sgt, cma_obj->sgt->orig_nents, GFP_KERNEL);
> > +       if (ret) {
> > +               DRM_ERROR("failed to alloc sgt.\n");
> > +               return ERR_PTR(-ENOMEM);
> > +       }
> > +
> > +       mutex_lock(&drm->struct_mutex);
> > +
> > +       rd = cma_obj->sgt->sgl;
> > +       wr = sgt->sgl;
> > +       for (i = 0; i < sgt->orig_nents; ++i) {
> > +               sg_set_page(wr, sg_page(rd), rd->length, rd->offset);
> > +               rd = sg_next(rd);
> > +               wr = sg_next(wr);
> > +       }
> > +
> > +       nents = dma_map_sg(attach->dev, sgt->sgl, sgt->orig_nents, dir);
> > +       if (!nents) {
> > +               DRM_ERROR("failed to map sgl with iommu.\n");
> > +               sgt = ERR_PTR(-EIO);
> > +               goto err_unlock;
> 
> don't we miss a sg_free_table() in this error path?  Or, well, I guess
> you still call it in _detach(), but if you call _map() again, I think
> we'll re-sg_alloc_table(), which doesn't seem quite right..

Indeed, good catch. I'll fix it.

> > +       }
> > +
> > +       cma_attach->dir = dir;
> > +       attach->priv = cma_attach;
> > +
> > +       DRM_DEBUG_PRIME("buffer size = %zu\n", cma_obj->base.size);
> > +
> > +err_unlock:
> > +       mutex_unlock(&drm->struct_mutex);
> > +       return sgt;
> > +}
> > +
> > +static void drm_gem_cma_dmabuf_unmap(struct dma_buf_attachment *attach,
> > +                                    struct sg_table *sgt,
> > +                                    enum dma_data_direction dir)
> > +{
> > +       /* Nothing to do. */
> 
> hmm, I wonder if it makes sense to support _unmap() and then _map()
> again with a different direction?  Not entirely sure when that would
> be needed and I suppose it is ok to add later.

I don't have a use case for that right now, I would thus vote for adding it 
later if needed :-)

> > +}

[snip]

> > +static void *drm_gem_cma_dmabuf_kmap_atomic(struct dma_buf *dmabuf,
> > +                                           unsigned long page_num)
> > +{
> > +       /* TODO */
> > +
> > +       return NULL;
> > +}
> > +
> > +static void drm_gem_cma_dmabuf_kunmap_atomic(struct dma_buf *dmabuf,
> > +                                            unsigned long page_num, void
> > *addr)
> > +{
> > +       /* TODO */
> > +}
> > +
> > +static void *drm_gem_cma_dmabuf_kmap(struct dma_buf *dmabuf,
> > +                                    unsigned long page_num)
> > +{
> > +       /* TODO */
> > +
> > +       return NULL;
> > +}
> > +
> > +static void drm_gem_cma_dmabuf_kunmap(struct dma_buf *dmabuf,
> > +                                     unsigned long page_num, void *addr)
> > +{
> > +       /* TODO */
> > +}
> 
> again, not really sure if it is required, but it should be pretty
> trivial to support kmap and friends
> 
> > +static int drm_gem_cma_dmabuf_mmap(struct dma_buf *dmabuf,
> > +                                  struct vm_area_struct *vma)
> > +{
> > +       return -ENOTTY;
> > +}
> 
> should also be pretty trivial to redirect _dmabuf_mmap() into
> drm_gem_cma_mmap()..

It will require a bit of code shuffling, but I'll give it a try.

-- 
Regards,

Laurent Pinchart



More information about the dri-devel mailing list