Rename net_devmem_alloc_dmabuf() into net_devmem_alloc_dmabuf_bulk() and make it refill page pool with up to PP_ALLOC_CACHE_REFILL NIOVs, similar to io_pp_zc_alloc_netmems(). That should amortize recently introduced freelist_lock. Signed-off-by: Stanislav Fomichev --- net/core/devmem.c | 59 +++++++++++++++++++++++++++++------------------ net/core/devmem.h | 8 ------- 2 files changed, 37 insertions(+), 30 deletions(-) diff --git a/net/core/devmem.c b/net/core/devmem.c index 7949f8425bcd..a0dcc896dd12 100644 --- a/net/core/devmem.c +++ b/net/core/devmem.c @@ -58,25 +58,25 @@ void __net_devmem_dmabuf_binding_free(struct work_struct *wq) kfree(binding); } -struct net_iov * -net_devmem_alloc_dmabuf(struct net_devmem_dmabuf_binding *binding) +static unsigned int +net_devmem_alloc_dmabuf_bulk(struct net_devmem_dmabuf_binding *binding, + netmem_ref *netmems, unsigned int count) { - struct net_iov *niov; + unsigned int i; + spin_lock_bh(&binding->freelist_lock); - if (unlikely(!binding->free_count)) { - spin_unlock_bh(&binding->freelist_lock); - return NULL; + + count = min_t(size_t, count, binding->free_count); + for (i = 0; i < count; i++) { + struct net_iov *niov = binding->freelist[--binding->free_count]; + + binding->freelist[binding->free_count] = NULL; + netmems[i] = net_iov_to_netmem(niov); } - niov = binding->freelist[--binding->free_count]; - binding->freelist[binding->free_count] = NULL; spin_unlock_bh(&binding->freelist_lock); - niov->desc.pp_magic = 0; - niov->desc.pp = NULL; - atomic_long_set(&niov->desc.pp_ref_count, 0); - - return niov; + return count; } void net_devmem_free_dmabuf(struct net_iov *niov) @@ -434,20 +434,35 @@ int mp_dmabuf_devmem_init(struct page_pool *pool) netmem_ref mp_dmabuf_devmem_alloc_netmems(struct page_pool *pool, gfp_t gfp) { struct net_devmem_dmabuf_binding *binding = pool->mp_priv; - struct net_iov *niov; - netmem_ref netmem; + netmem_ref *netmems = pool->alloc.cache; + unsigned int allocated, i; + + if (WARN_ON_ONCE(pool->alloc.count)) + return 0; - niov = net_devmem_alloc_dmabuf(binding); - if (!niov) + allocated = net_devmem_alloc_dmabuf_bulk(binding, netmems, + PP_ALLOC_CACHE_REFILL); + if (unlikely(!allocated)) return 0; - netmem = net_iov_to_netmem(niov); + for (i = 0; i < allocated; i++) { + struct net_iov *niov = netmem_to_net_iov(netmems[i]); - page_pool_set_pp_info(pool, netmem); + niov->desc.pp_magic = 0; + niov->desc.pp = NULL; + atomic_long_set(&niov->desc.pp_ref_count, 0); + + page_pool_set_pp_info(pool, netmems[i]); + + pool->pages_state_hold_cnt++; + trace_page_pool_state_hold(pool, netmems[i], + pool->pages_state_hold_cnt); + } - pool->pages_state_hold_cnt++; - trace_page_pool_state_hold(pool, netmem, pool->pages_state_hold_cnt); - return netmem; + /* Return the last one, the rest stay in the page_pool cache. */ + allocated--; + pool->alloc.count = allocated; + return netmems[allocated]; } void mp_dmabuf_devmem_destroy(struct page_pool *pool) diff --git a/net/core/devmem.h b/net/core/devmem.h index 20a3eb90ea7f..7195769b8bd1 100644 --- a/net/core/devmem.h +++ b/net/core/devmem.h @@ -133,8 +133,6 @@ net_devmem_dmabuf_binding_put(struct net_devmem_dmabuf_binding *binding) void net_devmem_get_net_iov(struct net_iov *niov); void net_devmem_put_net_iov(struct net_iov *niov); -struct net_iov * -net_devmem_alloc_dmabuf(struct net_devmem_dmabuf_binding *binding); void net_devmem_free_dmabuf(struct net_iov *ppiov); @@ -191,12 +189,6 @@ net_devmem_bind_dmabuf_to_queue(struct net_device *dev, u32 rxq_idx, return -EOPNOTSUPP; } -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) { } -- 2.53.0-Meta