* [PATCH net] net: devmem: allow peer-to-peer dma-buf attach for bindings
@ 2026-10-12 17:07 Erfan Sharafzadeh
0 siblings, 0 replies; only message in thread
From: Erfan Sharafzadeh @ 2026-10-12 17:07 UTC (permalink / raw)
To: netdev
Cc: davem, edumazet, kuba, pabeni, horms, almasrymina, kaiyuanz,
willemb, asml.silence, sdf, bobbyeshleman
net_devmem_bind_dmabuf() uses dma_buf_attach(), a static attachment:
- peer2peer is false, so exporters must keep the buffer reachable
without P2P. amdgpu migrates a VRAM buffer to GTT (system memory)
for that, so device memory bindings silently land in host memory.
- the core pins the buffer on map (dma_buf_pin_on_map()), so it never
moves while bound.
Switch to dma_buf_dynamic_attach() with allow_peer2peer set, so the
exporter can keep the buffer in device memory. Dynamic attachments are
not pinned on map, and devmem cannot handle the buffer moving, so:
- pin it explicitly with dma_buf_pin() before mapping, which keeps it
non-movable for the lifetime of the binding, as before;
- wait for the exporter's kernel fences after mapping, which the core
only does for static attachments.
This matches the pinned RDMA umem path. Exporters that cannot do P2P
to the device fall back as before. RX and TX bindings both go through
this function.
Fixes: 170aafe35cb9 ("netdev: support binding dma-buf to netdevice")
Signed-off-by: Erfan Sharafzadeh <erfansh@meta.com>
---
net/core/devmem.c | 47 +++++++++++++++++++++++++++++++++++++----------
1 file changed, 37 insertions(+), 10 deletions(-)
diff --git a/net/core/devmem.c b/net/core/devmem.c
index f4d60654ce7f..3721a47426fa 100644
--- a/net/core/devmem.c
+++ b/net/core/devmem.c
@@ -8,6 +8,7 @@
*/
#include <linux/dma-buf.h>
+#include <linux/dma-resv.h>
#include <linux/genalloc.h>
#include <linux/mm.h>
#include <linux/netdevice.h>
@@ -49,6 +50,10 @@ static dma_addr_t net_devmem_get_dma_addr(const struct net_iov *niov)
((dma_addr_t)net_iov_idx(niov) << owner->binding->niov_shift);
}
+static const struct dma_buf_attach_ops net_devmem_dmabuf_attach_ops = {
+ .allow_peer2peer = true,
+};
+
static void net_devmem_dmabuf_binding_release(struct percpu_ref *ref)
{
struct net_devmem_dmabuf_binding *binding =
@@ -74,8 +79,11 @@ void __net_devmem_dmabuf_binding_free(struct work_struct *wq)
size, avail))
gen_pool_destroy(binding->chunk_pool);
- dma_buf_unmap_attachment_unlocked(binding->attachment, binding->sgt,
- binding->direction);
+ dma_resv_lock(binding->dmabuf->resv, NULL);
+ dma_buf_unmap_attachment(binding->attachment, binding->sgt,
+ binding->direction);
+ dma_buf_unpin(binding->attachment);
+ dma_resv_unlock(binding->dmabuf->resv);
dma_buf_detach(binding->dmabuf, binding->attachment);
dma_buf_put(binding->dmabuf);
xa_destroy(&binding->bound_rxqs);
@@ -200,7 +208,7 @@ net_devmem_bind_dmabuf(struct net_device *dev, void *vdev,
struct dma_buf *dmabuf;
unsigned int sg_idx, i;
unsigned long virtual;
- int err;
+ long err;
if (!dma_dev) {
NL_SET_ERR_MSG(extack, "Device doesn't support DMA");
@@ -234,19 +242,35 @@ net_devmem_bind_dmabuf(struct net_device *dev, void *vdev,
binding->dmabuf = dmabuf;
binding->direction = direction;
- binding->attachment = dma_buf_attach(binding->dmabuf, dma_dev);
+ binding->attachment =
+ dma_buf_dynamic_attach(binding->dmabuf, dma_dev,
+ &net_devmem_dmabuf_attach_ops, binding);
if (IS_ERR(binding->attachment)) {
err = PTR_ERR(binding->attachment);
NL_SET_ERR_MSG(extack, "Failed to bind dmabuf to device");
goto err_exit_ref;
}
- binding->sgt = dma_buf_map_attachment_unlocked(binding->attachment,
- direction);
+ dma_resv_lock(dmabuf->resv, NULL);
+ err = dma_buf_pin(binding->attachment);
+ if (err) {
+ NL_SET_ERR_MSG(extack, "Failed to pin dmabuf");
+ goto err_unlock;
+ }
+
+ binding->sgt = dma_buf_map_attachment(binding->attachment, direction);
if (IS_ERR(binding->sgt)) {
err = PTR_ERR(binding->sgt);
NL_SET_ERR_MSG(extack, "Failed to map dmabuf attachment");
- goto err_detach;
+ goto err_unpin;
+ }
+ dma_resv_unlock(dmabuf->resv);
+
+ err = dma_resv_wait_timeout(dmabuf->resv, DMA_RESV_USAGE_KERNEL, false,
+ MAX_SCHEDULE_TIMEOUT);
+ if (err < 0) {
+ NL_SET_ERR_MSG(extack, "Failed to wait for dmabuf fences");
+ goto err_unmap;
}
if (direction == DMA_TO_DEVICE) {
@@ -343,9 +367,12 @@ net_devmem_bind_dmabuf(struct net_device *dev, void *vdev,
err_tx_vec:
kvfree(binding->tx_vec);
err_unmap:
- dma_buf_unmap_attachment_unlocked(binding->attachment, binding->sgt,
- direction);
-err_detach:
+ dma_resv_lock(dmabuf->resv, NULL);
+ dma_buf_unmap_attachment(binding->attachment, binding->sgt, direction);
+err_unpin:
+ dma_buf_unpin(binding->attachment);
+err_unlock:
+ dma_resv_unlock(dmabuf->resv);
dma_buf_detach(dmabuf, binding->attachment);
err_exit_ref:
percpu_ref_exit(&binding->ref);
--
2.53.0-Meta
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2026-10-12 17:08 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-12 17:07 [PATCH net] net: devmem: allow peer-to-peer dma-buf attach for bindings Erfan Sharafzadeh
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox