[PATCH 3/5] drm/i915/dmabuf: Add LMEM knowledge to dmabuf map handler
Daniel Vetter
daniel at ffwll.ch
Tue Apr 28 19:00:08 UTC 2020
On Tue, Apr 28, 2020 at 05:36:03PM +0000, Ruhl, Michael J wrote:
> >-----Original Message-----
> >From: Daniel Vetter <daniel at ffwll.ch>
> >Sent: Tuesday, April 28, 2020 11:02 AM
> >To: Ruhl, Michael J <michael.j.ruhl at intel.com>
> >Cc: dri-devel at lists.freedesktop.org; daniel at ffwll.ch; Xiong, Jianxin
> ><jianxin.xiong at intel.com>
> >Subject: Re: [PATCH 3/5] drm/i915/dmabuf: Add LMEM knowledge to dmabuf
> >map handler
> >
> >On Wed, Apr 22, 2020 at 05:25:17PM -0400, Michael J. Ruhl wrote:
> >> LMEM backed buffer objects do not have struct page information.
> >> Instead the dma_address of the struct sg is used to store the
> >> LMEM address information (relative to the device, this is not
> >> the CPU physical address).
> >>
> >> The dmabuf map handler requires pages to do a dma_map_xx.
> >>
> >> Add new mapping/unmapping functions, based on the LMEM usage
> >> of the dma_address to allow LMEM backed buffer objects to be
> >> mapped.
> >>
> >> Before mapping check the peer2peer distance to verify that P2P
> >> dma can occur.
> >
> >So this is supposed to check the importer's allow_peer2peer flag, and that
> >one is supposed to require the implementation of ->move_notify. Which
> >requires a pile of locking changes to align with dma_resv.
>
> Yeah, I was avoiding that step for the moment. I am not completely
> comfortable with the how and why of how the move_notify is supposed
> to work, so I left the current mechanism "as is", and am planning on
> adding the move_notify part as a next step.
>
> >By not doing all that you avoid the lockdep splats, but you're also
> >breaking the peer2peer dma-buf contract big time :-)
>
> OK. I have some concerns because of the differences between the
> AMD and i915 implementations. It is not clear to me how compatible
> they currently are, and if "matched" the implementation how that would
> affect the i915 driver.
That's kinda the problem. They're not compatible :-/
I'm also pretty sure that we'll discover a bunch of places where the
current debug checks and lockdep annotations we have are insufficient, and
we'll need to add more to lock down this cross driver interface.
-Daniel
> >I think this needs more work, or I need better glasses in case I'm not
> >spotting where this is all done.
>
> Nope, your glasses are good.
>
> I will take a close look at how to incorporate the peer2peer stuff.
>
> Mike
>
>
> >-Daniel
> >
> >>
> >> Signed-off-by: Michael J. Ruhl <michael.j.ruhl at intel.com>
> >> ---
> >> drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c | 82
> >++++++++++++++++++++--
> >> 1 file changed, 76 insertions(+), 6 deletions(-)
> >>
> >> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
> >b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
> >> index 7ea4abb6a896..402c989cc23d 100644
> >> --- a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
> >> +++ b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
> >> @@ -7,6 +7,7 @@
> >> #include <linux/dma-buf.h>
> >> #include <linux/highmem.h>
> >> #include <linux/dma-resv.h>
> >> +#include <linux/pci-p2pdma.h>
> >> #include <linux/scatterlist.h>
> >>
> >> #include "i915_drv.h"
> >> @@ -18,6 +19,67 @@ static struct drm_i915_gem_object
> >*dma_buf_to_obj(struct dma_buf *buf)
> >> return to_intel_bo(buf->priv);
> >> }
> >>
> >> +static void dmabuf_unmap_addr(struct device *dev, struct scatterlist *sgl,
> >> + int nents, enum dma_data_direction dir)
> >> +{
> >> + struct scatterlist *sg;
> >> + int i;
> >> +
> >> + for_each_sg(sgl, sg, nents, i)
> >> + dma_unmap_resource(dev, sg_dma_address(sg),
> >sg_dma_len(sg),
> >> + dir, 0);
> >> +}
> >> +
> >> +/**
> >> + * dmabuf_map_addr - Update LMEM address to a physical address and
> >map the
> >> + * resource.
> >> + * @dev: valid device
> >> + * @obj: valid i915 GEM object
> >> + * @sg: scatter list to appy mapping to
> >> + * @nents: number of entries in the scatter list
> >> + * @dir: DMA direction
> >> + *
> >> + * The dma_address of the scatter list is the LMEM "address". From this
> >the
> >> + * actual physical address can be determined.
> >> + *
> >> + * Return of 0 means error.
> >> + *
> >> + */
> >> +static int dmabuf_map_addr(struct device *dev, struct
> >drm_i915_gem_object *obj,
> >> + struct scatterlist *sgl, int nents,
> >> + enum dma_data_direction dir)
> >> +{
> >> + struct scatterlist *sg;
> >> + phys_addr_t addr;
> >> + int distance;
> >> + int i;
> >> +
> >> + distance = pci_p2pdma_distance_many(obj->base.dev->pdev, &dev,
> >1,
> >> + true);
> >> + if (distance < 0) {
> >> + pr_info("%s: from: %s to: %s distance: %d\n", __func__,
> >> + pci_name(obj->base.dev->pdev), dev_name(dev),
> >> + distance);
> >> + return 0;
> >> + }
> >> +
> >> + for_each_sg(sgl, sg, nents, i) {
> >> + addr = sg_dma_address(sg) + obj->mm.region->io_start;
> >> +
> >> + sg->dma_address = dma_map_resource(dev, addr, sg-
> >>length, dir,
> >> + 0);
> >> + if (dma_mapping_error(dev, sg->dma_address))
> >> + goto unmap;
> >> + sg->dma_length = sg->length;
> >> + }
> >> +
> >> + return nents;
> >> +
> >> +unmap:
> >> + dmabuf_unmap_addr(dev, sgl, i, dir);
> >> + return 0;
> >> +}
> >> +
> >> static struct sg_table *i915_gem_map_dma_buf(struct
> >dma_buf_attachment *attach,
> >> enum dma_data_direction dir)
> >> {
> >> @@ -44,12 +106,17 @@ static struct sg_table
> >*i915_gem_map_dma_buf(struct dma_buf_attachment *attach,
> >> dst = sgt->sgl;
> >> for_each_sg(obj->mm.pages->sgl, src, obj->mm.pages->nents, i) {
> >> sg_set_page(dst, sg_page(src), src->length, 0);
> >> + sg_dma_address(dst) = sg_dma_address(src);
> >> dst = sg_next(dst);
> >> }
> >>
> >> - if (!dma_map_sg_attrs(attach->dev,
> >> - sgt->sgl, sgt->nents, dir,
> >> - DMA_ATTR_SKIP_CPU_SYNC)) {
> >> + if (i915_gem_object_has_struct_page(obj))
> >> + ret = dma_map_sg_attrs(attach->dev, sgt->sgl, sgt->nents,
> >dir,
> >> + DMA_ATTR_SKIP_CPU_SYNC);
> >> + else
> >> + ret = dmabuf_map_addr(attach->dev, obj, sgt->sgl, sgt-
> >>nents,
> >> + dir);
> >> + if (!ret) {
> >> ret = -ENOMEM;
> >> goto err_free_sg;
> >> }
> >> @@ -72,9 +139,12 @@ static void i915_gem_unmap_dma_buf(struct
> >dma_buf_attachment *attach,
> >> {
> >> struct drm_i915_gem_object *obj = dma_buf_to_obj(attach-
> >>dmabuf);
> >>
> >> - dma_unmap_sg_attrs(attach->dev,
> >> - sgt->sgl, sgt->nents, dir,
> >> - DMA_ATTR_SKIP_CPU_SYNC);
> >> + if (i915_gem_object_has_struct_page(obj))
> >> + dma_unmap_sg_attrs(attach->dev, sgt->sgl, sgt->nents, dir,
> >> + DMA_ATTR_SKIP_CPU_SYNC);
> >> + else
> >> + dmabuf_unmap_addr(attach->dev, sgt->sgl, sgt->nents, dir);
> >> +
> >> sg_free_table(sgt);
> >> kfree(sgt);
> >>
> >> --
> >> 2.21.0
> >>
> >
> >--
> >Daniel Vetter
> >Software Engineer, Intel Corporation
> >http://blog.ffwll.ch
--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
More information about the dri-devel
mailing list