]> www.infradead.org Git - linux.git/commitdiff
netdev: netdevice devmem allocator
authorMina Almasry <almasrymina@google.com>
Tue, 10 Sep 2024 17:14:48 +0000 (17:14 +0000)
committerJakub Kicinski <kuba@kernel.org>
Thu, 12 Sep 2024 03:44:31 +0000 (20:44 -0700)
Implement netdev devmem allocator. The allocator takes a given struct
netdev_dmabuf_binding as input and allocates net_iov from that
binding.

The allocation simply delegates to the binding's genpool for the
allocation logic and wraps the returned memory region in a net_iov
struct.

Signed-off-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: Kaiyuan Zhang <kaiyuanz@google.com>
Signed-off-by: Mina Almasry <almasrymina@google.com>
Reviewed-by: Pavel Begunkov <asml.silence@gmail.com>
Reviewed-by: Jakub Kicinski <kuba@kernel.org>
Link: https://patch.msgid.link/20240910171458.219195-5-almasrymina@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/core/devmem.c
net/core/devmem.h

index 8dd7beb080d2ce5f7ff57885e74b963aa7e41af9..9beb03763dc93ae9d3be2ad456a2d9fa4856513a 100644 (file)
@@ -34,6 +34,14 @@ static void net_devmem_dmabuf_free_chunk_owner(struct gen_pool *genpool,
        kfree(owner);
 }
 
+static dma_addr_t net_devmem_get_dma_addr(const struct net_iov *niov)
+{
+       struct dmabuf_genpool_chunk_owner *owner = net_iov_owner(niov);
+
+       return owner->base_dma_addr +
+              ((dma_addr_t)net_iov_idx(niov) << PAGE_SHIFT);
+}
+
 void __net_devmem_dmabuf_binding_free(struct net_devmem_dmabuf_binding *binding)
 {
        size_t size, avail;
@@ -56,6 +64,39 @@ void __net_devmem_dmabuf_binding_free(struct net_devmem_dmabuf_binding *binding)
        kfree(binding);
 }
 
+struct net_iov *
+net_devmem_alloc_dmabuf(struct net_devmem_dmabuf_binding *binding)
+{
+       struct dmabuf_genpool_chunk_owner *owner;
+       unsigned long dma_addr;
+       struct net_iov *niov;
+       ssize_t offset;
+       ssize_t index;
+
+       dma_addr = gen_pool_alloc_owner(binding->chunk_pool, PAGE_SIZE,
+                                       (void **)&owner);
+       if (!dma_addr)
+               return NULL;
+
+       offset = dma_addr - owner->base_dma_addr;
+       index = offset / PAGE_SIZE;
+       niov = &owner->niovs[index];
+
+       return niov;
+}
+
+void net_devmem_free_dmabuf(struct net_iov *niov)
+{
+       struct net_devmem_dmabuf_binding *binding = net_iov_binding(niov);
+       unsigned long dma_addr = net_devmem_get_dma_addr(niov);
+
+       if (WARN_ON(!gen_pool_has_addr(binding->chunk_pool, dma_addr,
+                                      PAGE_SIZE)))
+               return;
+
+       gen_pool_free(binding->chunk_pool, dma_addr, PAGE_SIZE);
+}
+
 void net_devmem_unbind_dmabuf(struct net_devmem_dmabuf_binding *binding)
 {
        struct netdev_rx_queue *rxq;
index c50f91d858ddfea598701b8d95415212728ff49a..b1db4877cff9b6d54580fed068644063ee418ead 100644 (file)
@@ -74,6 +74,23 @@ int net_devmem_bind_dmabuf_to_queue(struct net_device *dev, u32 rxq_idx,
                                    struct netlink_ext_ack *extack);
 void dev_dmabuf_uninstall(struct net_device *dev);
 
+static inline struct dmabuf_genpool_chunk_owner *
+net_iov_owner(const struct net_iov *niov)
+{
+       return niov->owner;
+}
+
+static inline unsigned int net_iov_idx(const struct net_iov *niov)
+{
+       return niov - net_iov_owner(niov)->niovs;
+}
+
+static inline struct net_devmem_dmabuf_binding *
+net_iov_binding(const struct net_iov *niov)
+{
+       return net_iov_owner(niov)->binding;
+}
+
 static inline void
 net_devmem_dmabuf_binding_get(struct net_devmem_dmabuf_binding *binding)
 {
@@ -89,7 +106,13 @@ net_devmem_dmabuf_binding_put(struct net_devmem_dmabuf_binding *binding)
        __net_devmem_dmabuf_binding_free(binding);
 }
 
+struct net_iov *
+net_devmem_alloc_dmabuf(struct net_devmem_dmabuf_binding *binding);
+void net_devmem_free_dmabuf(struct net_iov *ppiov);
+
 #else
+struct net_devmem_dmabuf_binding;
+
 static inline void
 __net_devmem_dmabuf_binding_free(struct net_devmem_dmabuf_binding *binding)
 {
@@ -119,6 +142,17 @@ net_devmem_bind_dmabuf_to_queue(struct net_device *dev, u32 rxq_idx,
 static inline void dev_dmabuf_uninstall(struct net_device *dev)
 {
 }
+
+static inline struct net_iov *
+net_devmem_alloc_dmabuf(struct net_devmem_dmabuf_binding *binding)
+{
+       return NULL;
+}
+
+static inline void net_devmem_free_dmabuf(struct net_iov *ppiov)
+{
+}
+
 #endif
 
 #endif /* _NET_DEVMEM_H */