Linux Documentation
 help / color / mirror / Atom feed
From: "Thomas Hellström" <thomas.hellstrom@linux.intel.com>
To: Leon Romanovsky <leon@kernel.org>
Cc: "Bjorn Helgaas" <bhelgaas@google.com>,
	"Logan Gunthorpe" <logang@deltatee.com>,
	"Jonathan Corbet" <corbet@lwn.net>,
	"Shuah Khan" <skhan@linuxfoundation.org>,
	"Christian König" <christian.koenig@amd.com>,
	"Sumit Semwal" <sumit.semwal@linaro.org>,
	linux-pci@vger.kernel.org, linux-doc@vger.kernel.org,
	linux-kernel@vger.kernel.org, linux-media@vger.kernel.org,
	dri-devel@lists.freedesktop.org, linaro-mm-sig@lists.linaro.org
Subject: Re: [Linaro-mm-sig] [PATCH 2/2] dma-buf: Document how exporters and importers agree on mapping lifetime
Date: Mon, 31 Aug 2026 08:39:01 +0200	[thread overview]
Message-ID: <8276d124012e7a335c299b20f6578fc9f751e713.camel@linux.intel.com> (raw)
In-Reply-To: <20260830075828.GA24140@unreal>

On Sun, 2026-08-30 at 10:58 +0300, Leon Romanovsky wrote:
> On Thu, Aug 27, 2026 at 09:18:29PM +0200, Thomas Hellström wrote:
> > Hi,
> > 
> > Some comments below:
> > 
> > On Tue, 2026-08-25 at 09:28 +0300, Leon Romanovsky wrote:
> > > From: Leon Romanovsky <leonro@nvidia.com>
> > > 
> > > Pinned, revoked and movable mappings are selected by which
> > > optional
> > > callbacks each side implements and by whether dma_buf_pin()
> > > succeeds,
> > > not by any flag or enum. Nothing in Documentation/ says so, and
> > > the
> > > rules are spread over the kdoc of dma_buf_ops.pin,
> > > dma_buf_attach_ops.invalidate_mappings and
> > > dma_buf_invalidate_mappings(),
> > > so a driver author has to know the symbol names before finding
> > > them.
> > > 
> > > Name, per flow, the callbacks both sides have to implement to end
> > > up
> > > in
> > > it, describe dma_buf_pin() as the runtime negotiation, and record
> > > that
> > > the pin is what tells a revoke from a move.
> > > 
> > > Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
> > > ---
> > >  Documentation/driver-api/dma-buf.rst |  6 +++
> > >  drivers/dma-buf/dma-buf.c            | 85
> > > +++++++++++++++++++++++++++++++++++-
> > >  2 files changed, 90 insertions(+), 1 deletion(-)
> > > 
> > > diff --git a/Documentation/driver-api/dma-buf.rst
> > > b/Documentation/driver-api/dma-buf.rst
> > > index 2f36c21d9948..39c201f38aa6 100644
> > > --- a/Documentation/driver-api/dma-buf.rst
> > > +++ b/Documentation/driver-api/dma-buf.rst
> > > @@ -113,6 +113,12 @@ Basic Operation and Device DMA Access
> > >  .. kernel-doc:: drivers/dma-buf/dma-buf.c
> > >     :doc: dma buf device access
> > >  
> > > +Mapping Lifetime Negotiation
> > > +~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > > +
> > > +.. kernel-doc:: drivers/dma-buf/dma-buf.c
> > > +   :doc: mapping lifetime negotiation
> > > +
> > >  CPU Access to DMA Buffer Objects
> > >  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > >  
> > > diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-
> > > buf.c
> > > index d504c636dc29..30afec7365bc 100644
> > > --- a/drivers/dma-buf/dma-buf.c
> > > +++ b/drivers/dma-buf/dma-buf.c
> > > @@ -684,7 +684,90 @@ static struct file *dma_buf_getfile(size_t
> > > size,
> > > int flags)
> > >   *    reference acquired with dma_buf_get() by calling
> > > dma_buf_put().
> > >   *
> > >   * For the detailed semantics exporters are expected to
> > > implement
> > > see
> > > - * &dma_buf_ops.
> > > + * &dma_buf_ops. Whether the exporter may still move or destroy
> > > the
> > > backing
> > > + * storage after step 3 depends on what exporter and importer
> > > implement, see
> > > + * the mapping lifetime negotiation section below.
> > > + */
> > > +
> > > +/**
> > > + * DOC: mapping lifetime negotiation
> > > + *
> > > + * No flag or enum says whether the exporter may move or take
> > > away
> > > the backing
> > > + * storage while an importer holds a mapping. Each side
> > > implements a
> > > set of
> > > + * optional callbacks, and dma_buf_pin() settles the result at
> > > runtime. Three
> > > + * flows come out of it:
> > > + *
> > > + * - Pinned: the storage never moves and is never taken away.
> > > + * - Revoked: the storage never moves, but the exporter may take
> > > it
> > > away.
> > > + * - Movable: the exporter may relocate the storage at any time.
> > 
> > Perhaps add "even temporarily to locations that are not available
> > for
> > DMA".
> 
> I don't know. "Not available for DMA" defeats the whole purpose of
> dma-buf,
> which is intended to expose DMA-capable memory to other peers. I
> imagine
> that "everything is optional dmabuf world" this is possible, but it
> looks to me like a partial version of revoked flow.

Not permanently revoked. In practice this would be, for example, a GPU-
exported dma-buf which is only available for p2p access which gets
evicted, or a system memory exported dma-buf that gets hit by a
shrinker and moved to swap. The exporter calls invalidate_mappings() to
notify importers that storage is going away. Importers need to call
map_attachment() to bring it back.

> 
> > 
> > > + *
> > > + * Every exporter implements &dma_buf_ops.map_dma_buf,
> > > + * &dma_buf_ops.unmap_dma_buf and &dma_buf_ops.release.
> > > dma_buf_export()
> > > + * rejects an exporter missing any of them.
> > > + *
> > > + * An importer reaches its flow like this:
> > > + *
> > > + * 1. Attach with dma_buf_dynamic_attach(). Leaving
> > > + *    &dma_buf_attach_ops.invalidate_mappings NULL rules out
> > > everything but the
> > > + *    pinned flow, because the importer can then never be told
> > > anything.
> > > + * 2. Call dma_buf_pin() under the reservation lock.
> > > + * 3. On failure run the movable flow, or give up.
> > > + * 4. On success the storage stays put. Whether the exporter may
> > > still take it
> > > + *    away, which makes this the revoked flow instead of the
> > > pinned
> > > one, is the
> > > + *    exporter's choice and is not reported back.
> > > + *
> > > + * dma_buf_attach() is the shorthand for an importer which only
> > > ever
> > > wants the
> > > + * pinned flow. It passes no &dma_buf_attach_ops, and DMA-buf
> > > then
> > > pins around
> > > + * every dma_buf_map_attachment() and waits for the
> > > DMA_RESV_USAGE_KERNEL
> > > + * fences on the importer's behalf. Peer to peer needs
> > > + * dma_buf_dynamic_attach(), because
> > > &dma_buf_attach_ops.allow_peer2peer lives
> > > + * in the attach ops.
> > > + *
> > > + * Pinned flow:
> > > + *
> > > + * - Exporter: implement &dma_buf_ops.pin and &dma_buf_ops.unpin
> > > to
> > > hold the
> > > + *   storage still on request. An exporter whose storage never
> > > moves
> > > implements
> > > + *   neither, and dma_buf_pin() then succeeds on its own. An
> > > exporter which
> > > + *   refuses to be pinned implements &dma_buf_ops.pin and fails
> > > it.
> > > + * - Importer: nothing more. The mapping stays valid until it
> > > unmaps.
> > > + *
> > > + * Revoked flow:
> > > + *
> > > + * - Exporter: answer dma_buf_pin() as above. Call
> > > + *   dma_buf_invalidate_mappings() when the storage goes away
> > > and
> > > fail
> > > + *   &dma_buf_ops.map_dma_buf while it is gone. The two waits
> > > which
> > > complete a
> > > + *   revocation are described in dma_buf_invalidate_mappings().
> > > + * - Importer: &dma_buf_attach_ops.invalidate_mappings has to
> > > unmap
> > > within
> > > + *   bounded time and drop the pin.
> > > + *
> > > + * Movable flow:
> > > + *
> > > + * - Exporter: call dma_buf_invalidate_mappings() before each
> > > move,
> > > then wait
> > > + *   for the &dma_buf.resv fences. &dma_buf_ops.pin and
> > > &dma_buf_ops.unpin play
> > > + *   no part here.
> > > + * - Importer: hold no pin.
> > > &dma_buf_attach_ops.invalidate_mappings
> > > drops the
> > > + *   cached mapping and has to lead to
> > > dma_buf_unmap_attachment()
> > > within
> > > + *   bounded time.
> > 
> > Hear I would want to see the exporter being allowed to force unmap
> > the
> > dma mappings and reclaim thestorage when the fences mentioned above
> > have signaled, but the importer has not yet called
> > dma_buf_unmap_attachment(). That would allow importers to call
> > dma_buf_unmap_attachment() lazily, just before the next
> > map_attachment,
> > which would allow simplifying importer implementations. 
> 
> How? It will move one piece of code as is to another place. In
> addition,
> both exporter and importer need to stop HW access to same region.

A typical GPU example: A GPU importer receives invalidate_mappings() on
an imported dma-buf. The dma-buf is still accessed by the GPU and thus
has a couple of dma-fences attached. The importer can't immediately
call dma_buf_unmap_attachment(). In fact, typically the easiest thing
for the importer is to call dma_buf_unmap_attachment() on the next gpu
command submission immediately followed by a dma_buf_map_attachment(),
but it can't guarantee that would happen within bounded time.

A well behaved importer would therefore currently have to schedule an
async worker or similar to wait for its dma-fences to signal and then
grab the resv lock from worker context and call
dma_buf_unmap_attachment().

A well-behaved exporter on the other hand, would have to wait for all
dma-fences to signal, then wait for all unmap_attachment() calls before
reclaiming.

TBH I'm not sure what the best solution is here, but the importer flow
doesn't fit well in a typical gpu command submission model IMO.

Thanks,
Thomas




> 
> > More of a related idea than something that needs fixing for this
> > patch.
> > 
> > >  It need not stop the hardware, because access runs until the
> > > + *   importer's &dma_buf.resv fences retire. Map again before
> > > the
> > > next DMA.
> > 
> > A successful map will mean the exporter has placed the data in
> > storage
> > compatible with what was agreed during attachment?
> 
> Yes.
> 
> > 
> > Thanks,
> > Thomas
> > 

  reply	other threads:[~2026-08-31  6:39 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-25  6:28 [PATCH 0/2] Document the DMA-buf mapping lifetime negotiation Leon Romanovsky
2026-08-25  6:28 ` [PATCH 1/2] PCI/P2PDMA: Update DMABUF lifecycle docs after move_notify() rename Leon Romanovsky
2026-08-25 20:05   ` Logan Gunthorpe
2026-08-26 11:50   ` Christian König
2026-08-25  6:28 ` [PATCH 2/2] dma-buf: Document how exporters and importers agree on mapping lifetime Leon Romanovsky
2026-08-26 11:41   ` Christian König
2026-08-26 12:43     ` Leon Romanovsky
2026-08-26 13:06       ` Christian König
2026-08-26 14:02         ` Leon Romanovsky
2026-08-31  9:22           ` Christian König
2026-09-01 14:08             ` Jason Gunthorpe
2026-08-27 19:18   ` [Linaro-mm-sig] " Thomas Hellström
2026-08-30  7:58     ` Leon Romanovsky
2026-08-31  6:39       ` Thomas Hellström [this message]
2026-08-31  8:56       ` Christian König

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=8276d124012e7a335c299b20f6578fc9f751e713.camel@linux.intel.com \
    --to=thomas.hellstrom@linux.intel.com \
    --cc=bhelgaas@google.com \
    --cc=christian.koenig@amd.com \
    --cc=corbet@lwn.net \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=leon@kernel.org \
    --cc=linaro-mm-sig@lists.linaro.org \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-media@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=logang@deltatee.com \
    --cc=skhan@linuxfoundation.org \
    --cc=sumit.semwal@linaro.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox