* [PATCH net-next v2] net: devmem: allow peer-to-peer dma-buf attach for bindings
@ 2026-10-13 21:09 Erfan Sharafzadeh
2026-10-14 18:19 ` Stanislav Fomichev
0 siblings, 1 reply; 2+ messages in thread
From: Erfan Sharafzadeh @ 2026-10-13 21:09 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
with peer2peer false. Exporters must then keep the buffer reachable
without P2P; amdgpu does so by placing it in GTT (system memory), so a
device memory binding silently ends up in host memory.
Use dma_buf_dynamic_attach() with allow_peer2peer set, so an exporter
that can do P2P to the device keeps the buffer in device memory.
Dynamic attachments are not pinned on map, and devmem cannot handle the
buffer moving, so:
- pin it with dma_buf_pin() before mapping, which keeps it in place for
the lifetime of the binding, as before;
- wait for the exporter's kernel fences after mapping, interruptibly,
as the core does for static attachments.
This follows the pinned RDMA umem path, including its limits: the
binding cannot be revoked by the exporter, and once a P2P binding has
pinned a buffer in device memory, a later attachment to the same buffer
that cannot do P2P may fail to pin it. Exporters that cannot do P2P to
the device place the buffer as before. RX and TX bindings both go
through this function.
Signed-off-by: Erfan Sharafzadeh <erfansh@meta.com>
---
v2:
- Target net-next and drop the Fixes: tag. This adds P2P placement
rather than fixing incorrect behaviour, and it relies on recent
dma-buf core changes, so it should not go to stable.
- Wait for the exporter's fences interruptibly, as the core does.
- Describe the revocation and mixed-attachment limits in the commit
message.
v1: https://lore.kernel.org/netdev/20261012170754.669462-1-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 95d714d46c6f..fd1b72744564 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/mm.h>
#include <linux/netdevice.h>
#include <linux/types.h>
@@ -50,6 +51,10 @@ static void net_iov_free_push(struct net_iov_area *area,
freelist[(*free_count)++] = net_iov_idx(niov);
}
+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 =
@@ -69,8 +74,11 @@ void __net_devmem_dmabuf_binding_free(struct work_struct *wq)
binding->area.num_niovs, binding->free_count);
kvfree(binding->area.niovs);
- 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);
@@ -190,7 +198,7 @@ net_devmem_bind_dmabuf(struct net_device *dev, void *vdev,
unsigned int sg_idx;
size_t niov_idx;
size_t i;
- int err;
+ long err;
if (!dma_dev) {
NL_SET_ERR_MSG(extack, "Device doesn't support DMA");
@@ -226,19 +234,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, true,
+ MAX_SCHEDULE_TIMEOUT);
+ if (err < 0) {
+ NL_SET_ERR_MSG(extack, "Failed to wait for dmabuf fences");
+ goto err_unmap;
}
if (!IS_ALIGNED(dmabuf->size, niov_size)) {
@@ -332,9 +356,12 @@ net_devmem_bind_dmabuf(struct net_device *dev, void *vdev,
kvfree(binding->freelist);
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] 2+ messages in thread* Re: [PATCH net-next v2] net: devmem: allow peer-to-peer dma-buf attach for bindings
2026-10-13 21:09 [PATCH net-next v2] net: devmem: allow peer-to-peer dma-buf attach for bindings Erfan Sharafzadeh
@ 2026-10-14 18:19 ` Stanislav Fomichev
0 siblings, 0 replies; 2+ messages in thread
From: Stanislav Fomichev @ 2026-10-14 18:19 UTC (permalink / raw)
To: Erfan Sharafzadeh
Cc: netdev, davem, edumazet, kuba, pabeni, horms, almasrymina,
kaiyuanz, willemb, asml.silence, sdf, bobbyeshleman
On 10/13, Erfan Sharafzadeh wrote:
> net_devmem_bind_dmabuf() uses dma_buf_attach(), a static attachment
> with peer2peer false. Exporters must then keep the buffer reachable
> without P2P; amdgpu does so by placing it in GTT (system memory), so a
> device memory binding silently ends up in host memory.
>
> Use dma_buf_dynamic_attach() with allow_peer2peer set, so an exporter
> that can do P2P to the device keeps the buffer in device memory.
> Dynamic attachments are not pinned on map, and devmem cannot handle the
> buffer moving, so:
>
> - pin it with dma_buf_pin() before mapping, which keeps it in place for
> the lifetime of the binding, as before;
> - wait for the exporter's kernel fences after mapping, interruptibly,
> as the core does for static attachments.
>
> This follows the pinned RDMA umem path, including its limits: the
> binding cannot be revoked by the exporter, and once a P2P binding has
> pinned a buffer in device memory, a later attachment to the same buffer
> that cannot do P2P may fail to pin it. Exporters that cannot do P2P to
> the device place the buffer as before. RX and TX bindings both go
> through this function.
>
> Signed-off-by: Erfan Sharafzadeh <erfansh@meta.com>
> ---
> v2:
> - Target net-next and drop the Fixes: tag. This adds P2P placement
> rather than fixing incorrect behaviour, and it relies on recent
> dma-buf core changes, so it should not go to stable.
> - Wait for the exporter's fences interruptibly, as the core does.
> - Describe the revocation and mixed-attachment limits in the commit
> message.
>
> v1: https://lore.kernel.org/netdev/20261012170754.669462-1-erfansh@meta.com/
Acked-by: Stanislav Fomichev <sdf@fomichev.me>
We never with proper in-tree exporters (rather than "mock" udmabuf) so
here we are :-(
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-10-14 18:19 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-13 21:09 [PATCH net-next v2] net: devmem: allow peer-to-peer dma-buf attach for bindings Erfan Sharafzadeh
2026-10-14 18:19 ` Stanislav Fomichev
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox