mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
page_pool: convert to use netmem
Abstract the memory type from the page_pool so we can later add support for new memory types. Convert the page_pool to use the new netmem type abstraction, rather than use struct page directly. As of this patch the netmem type is a no-op abstraction: it's always a struct page underneath. All the page pool internals are converted to use struct netmem instead of struct page, and the page pool now exports 2 APIs: 1. The existing struct page API. 2. The new struct netmem API. Keeping the existing API is transitional; we do not want to refactor all the current drivers using the page pool at once. The netmem abstraction is currently a no-op. The page_pool uses page_to_netmem() to convert allocated pages to netmem, and uses netmem_to_page() to convert the netmem back to pages to pass to mm APIs, Follow up patches to this series add non-paged netmem support to the page_pool. This change is factored out on its own to limit the code churn to this 1 patch, for ease of code review. Signed-off-by: Mina Almasry <almasrymina@google.com> Reviewed-by: Pavel Begunkov <asml.silence@gmail.com> Link: https://patch.msgid.link/20240628003253.1694510-6-almasrymina@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
committed by
Jakub Kicinski
parent
ac26327635
commit
4dec64c52e
@@ -32,13 +32,13 @@ static inline void skb_frag_ref(struct sk_buff *skb, int f)
|
||||
__skb_frag_ref(&skb_shinfo(skb)->frags[f]);
|
||||
}
|
||||
|
||||
bool napi_pp_put_page(struct page *page);
|
||||
bool napi_pp_put_page(netmem_ref netmem);
|
||||
|
||||
static inline void
|
||||
skb_page_unref(struct page *page, bool recycle)
|
||||
{
|
||||
#ifdef CONFIG_PAGE_POOL
|
||||
if (recycle && napi_pp_put_page(page))
|
||||
if (recycle && napi_pp_put_page(page_to_netmem(page)))
|
||||
return;
|
||||
#endif
|
||||
put_page(page);
|
||||
|
||||
@@ -38,4 +38,19 @@ static inline netmem_ref page_to_netmem(struct page *page)
|
||||
return (__force netmem_ref)page;
|
||||
}
|
||||
|
||||
static inline int netmem_ref_count(netmem_ref netmem)
|
||||
{
|
||||
return page_ref_count(netmem_to_page(netmem));
|
||||
}
|
||||
|
||||
static inline unsigned long netmem_to_pfn(netmem_ref netmem)
|
||||
{
|
||||
return page_to_pfn(netmem_to_page(netmem));
|
||||
}
|
||||
|
||||
static inline netmem_ref netmem_compound_head(netmem_ref netmem)
|
||||
{
|
||||
return page_to_netmem(compound_head(netmem_to_page(netmem)));
|
||||
}
|
||||
|
||||
#endif /* _NET_NETMEM_H */
|
||||
|
||||
@@ -55,6 +55,8 @@
|
||||
#include <linux/dma-mapping.h>
|
||||
|
||||
#include <net/page_pool/types.h>
|
||||
#include <net/net_debug.h>
|
||||
#include <net/netmem.h>
|
||||
|
||||
#ifdef CONFIG_PAGE_POOL_STATS
|
||||
/* Deprecated driver-facing API, use netlink instead */
|
||||
@@ -212,6 +214,11 @@ page_pool_get_dma_dir(const struct page_pool *pool)
|
||||
return pool->p.dma_dir;
|
||||
}
|
||||
|
||||
static inline void page_pool_fragment_netmem(netmem_ref netmem, long nr)
|
||||
{
|
||||
atomic_long_set(&netmem_to_page(netmem)->pp_ref_count, nr);
|
||||
}
|
||||
|
||||
/**
|
||||
* page_pool_fragment_page() - split a fresh page into fragments
|
||||
* @page: page to split
|
||||
@@ -232,11 +239,12 @@ page_pool_get_dma_dir(const struct page_pool *pool)
|
||||
*/
|
||||
static inline void page_pool_fragment_page(struct page *page, long nr)
|
||||
{
|
||||
atomic_long_set(&page->pp_ref_count, nr);
|
||||
page_pool_fragment_netmem(page_to_netmem(page), nr);
|
||||
}
|
||||
|
||||
static inline long page_pool_unref_page(struct page *page, long nr)
|
||||
static inline long page_pool_unref_netmem(netmem_ref netmem, long nr)
|
||||
{
|
||||
struct page *page = netmem_to_page(netmem);
|
||||
long ret;
|
||||
|
||||
/* If nr == pp_ref_count then we have cleared all remaining
|
||||
@@ -279,15 +287,41 @@ static inline long page_pool_unref_page(struct page *page, long nr)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void page_pool_ref_page(struct page *page)
|
||||
static inline long page_pool_unref_page(struct page *page, long nr)
|
||||
{
|
||||
atomic_long_inc(&page->pp_ref_count);
|
||||
return page_pool_unref_netmem(page_to_netmem(page), nr);
|
||||
}
|
||||
|
||||
static inline bool page_pool_is_last_ref(struct page *page)
|
||||
static inline void page_pool_ref_netmem(netmem_ref netmem)
|
||||
{
|
||||
atomic_long_inc(&netmem_to_page(netmem)->pp_ref_count);
|
||||
}
|
||||
|
||||
static inline void page_pool_ref_page(struct page *page)
|
||||
{
|
||||
page_pool_ref_netmem(page_to_netmem(page));
|
||||
}
|
||||
|
||||
static inline bool page_pool_is_last_ref(netmem_ref netmem)
|
||||
{
|
||||
/* If page_pool_unref_page() returns 0, we were the last user */
|
||||
return page_pool_unref_page(page, 1) == 0;
|
||||
return page_pool_unref_netmem(netmem, 1) == 0;
|
||||
}
|
||||
|
||||
static inline void page_pool_put_netmem(struct page_pool *pool,
|
||||
netmem_ref netmem,
|
||||
unsigned int dma_sync_size,
|
||||
bool allow_direct)
|
||||
{
|
||||
/* When page_pool isn't compiled-in, net/core/xdp.c doesn't
|
||||
* allow registering MEM_TYPE_PAGE_POOL, but shield linker.
|
||||
*/
|
||||
#ifdef CONFIG_PAGE_POOL
|
||||
if (!page_pool_is_last_ref(netmem))
|
||||
return;
|
||||
|
||||
page_pool_put_unrefed_netmem(pool, netmem, dma_sync_size, allow_direct);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -308,15 +342,15 @@ static inline void page_pool_put_page(struct page_pool *pool,
|
||||
unsigned int dma_sync_size,
|
||||
bool allow_direct)
|
||||
{
|
||||
/* When page_pool isn't compiled-in, net/core/xdp.c doesn't
|
||||
* allow registering MEM_TYPE_PAGE_POOL, but shield linker.
|
||||
*/
|
||||
#ifdef CONFIG_PAGE_POOL
|
||||
if (!page_pool_is_last_ref(page))
|
||||
return;
|
||||
page_pool_put_netmem(pool, page_to_netmem(page), dma_sync_size,
|
||||
allow_direct);
|
||||
}
|
||||
|
||||
page_pool_put_unrefed_page(pool, page, dma_sync_size, allow_direct);
|
||||
#endif
|
||||
static inline void page_pool_put_full_netmem(struct page_pool *pool,
|
||||
netmem_ref netmem,
|
||||
bool allow_direct)
|
||||
{
|
||||
page_pool_put_netmem(pool, netmem, -1, allow_direct);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -331,7 +365,7 @@ static inline void page_pool_put_page(struct page_pool *pool,
|
||||
static inline void page_pool_put_full_page(struct page_pool *pool,
|
||||
struct page *page, bool allow_direct)
|
||||
{
|
||||
page_pool_put_page(pool, page, -1, allow_direct);
|
||||
page_pool_put_netmem(pool, page_to_netmem(page), -1, allow_direct);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -365,6 +399,18 @@ static inline void page_pool_free_va(struct page_pool *pool, void *va,
|
||||
page_pool_put_page(pool, virt_to_head_page(va), -1, allow_direct);
|
||||
}
|
||||
|
||||
static inline dma_addr_t page_pool_get_dma_addr_netmem(netmem_ref netmem)
|
||||
{
|
||||
struct page *page = netmem_to_page(netmem);
|
||||
|
||||
dma_addr_t ret = page->dma_addr;
|
||||
|
||||
if (PAGE_POOL_32BIT_ARCH_WITH_64BIT_DMA)
|
||||
ret <<= PAGE_SHIFT;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* page_pool_get_dma_addr() - Retrieve the stored DMA address.
|
||||
* @page: page allocated from a page pool
|
||||
@@ -374,16 +420,14 @@ static inline void page_pool_free_va(struct page_pool *pool, void *va,
|
||||
*/
|
||||
static inline dma_addr_t page_pool_get_dma_addr(const struct page *page)
|
||||
{
|
||||
dma_addr_t ret = page->dma_addr;
|
||||
|
||||
if (PAGE_POOL_32BIT_ARCH_WITH_64BIT_DMA)
|
||||
ret <<= PAGE_SHIFT;
|
||||
|
||||
return ret;
|
||||
return page_pool_get_dma_addr_netmem(page_to_netmem((struct page *)page));
|
||||
}
|
||||
|
||||
static inline bool page_pool_set_dma_addr(struct page *page, dma_addr_t addr)
|
||||
static inline bool page_pool_set_dma_addr_netmem(netmem_ref netmem,
|
||||
dma_addr_t addr)
|
||||
{
|
||||
struct page *page = netmem_to_page(netmem);
|
||||
|
||||
if (PAGE_POOL_32BIT_ARCH_WITH_64BIT_DMA) {
|
||||
page->dma_addr = addr >> PAGE_SHIFT;
|
||||
|
||||
@@ -419,6 +463,11 @@ static inline void page_pool_dma_sync_for_cpu(const struct page_pool *pool,
|
||||
page_pool_get_dma_dir(pool));
|
||||
}
|
||||
|
||||
static inline bool page_pool_set_dma_addr(struct page *page, dma_addr_t addr)
|
||||
{
|
||||
return page_pool_set_dma_addr_netmem(page_to_netmem(page), addr);
|
||||
}
|
||||
|
||||
static inline bool page_pool_put(struct page_pool *pool)
|
||||
{
|
||||
return refcount_dec_and_test(&pool->user_cnt);
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <linux/dma-direction.h>
|
||||
#include <linux/ptr_ring.h>
|
||||
#include <linux/types.h>
|
||||
#include <net/netmem.h>
|
||||
|
||||
#define PP_FLAG_DMA_MAP BIT(0) /* Should page_pool do the DMA
|
||||
* map/unmap
|
||||
@@ -40,7 +41,7 @@
|
||||
#define PP_ALLOC_CACHE_REFILL 64
|
||||
struct pp_alloc_cache {
|
||||
u32 count;
|
||||
struct page *cache[PP_ALLOC_CACHE_SIZE];
|
||||
netmem_ref cache[PP_ALLOC_CACHE_SIZE];
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -73,7 +74,7 @@ struct page_pool_params {
|
||||
struct net_device *netdev;
|
||||
unsigned int flags;
|
||||
/* private: used by test code only */
|
||||
void (*init_callback)(struct page *page, void *arg);
|
||||
void (*init_callback)(netmem_ref netmem, void *arg);
|
||||
void *init_arg;
|
||||
);
|
||||
};
|
||||
@@ -151,7 +152,7 @@ struct page_pool {
|
||||
*/
|
||||
__cacheline_group_begin(frag) __aligned(4 * sizeof(long));
|
||||
long frag_users;
|
||||
struct page *frag_page;
|
||||
netmem_ref frag_page;
|
||||
unsigned int frag_offset;
|
||||
__cacheline_group_end(frag);
|
||||
|
||||
@@ -220,8 +221,12 @@ struct page_pool {
|
||||
};
|
||||
|
||||
struct page *page_pool_alloc_pages(struct page_pool *pool, gfp_t gfp);
|
||||
netmem_ref page_pool_alloc_netmem(struct page_pool *pool, gfp_t gfp);
|
||||
struct page *page_pool_alloc_frag(struct page_pool *pool, unsigned int *offset,
|
||||
unsigned int size, gfp_t gfp);
|
||||
netmem_ref page_pool_alloc_frag_netmem(struct page_pool *pool,
|
||||
unsigned int *offset, unsigned int size,
|
||||
gfp_t gfp);
|
||||
struct page_pool *page_pool_create(const struct page_pool_params *params);
|
||||
struct page_pool *page_pool_create_percpu(const struct page_pool_params *params,
|
||||
int cpuid);
|
||||
@@ -252,6 +257,9 @@ static inline void page_pool_put_page_bulk(struct page_pool *pool, void **data,
|
||||
}
|
||||
#endif
|
||||
|
||||
void page_pool_put_unrefed_netmem(struct page_pool *pool, netmem_ref netmem,
|
||||
unsigned int dma_sync_size,
|
||||
bool allow_direct);
|
||||
void page_pool_put_unrefed_page(struct page_pool *pool, struct page *page,
|
||||
unsigned int dma_sync_size,
|
||||
bool allow_direct);
|
||||
|
||||
@@ -42,51 +42,53 @@ TRACE_EVENT(page_pool_release,
|
||||
TRACE_EVENT(page_pool_state_release,
|
||||
|
||||
TP_PROTO(const struct page_pool *pool,
|
||||
const struct page *page, u32 release),
|
||||
netmem_ref netmem, u32 release),
|
||||
|
||||
TP_ARGS(pool, page, release),
|
||||
TP_ARGS(pool, netmem, release),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(const struct page_pool *, pool)
|
||||
__field(const struct page *, page)
|
||||
__field(unsigned long, netmem)
|
||||
__field(u32, release)
|
||||
__field(unsigned long, pfn)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->pool = pool;
|
||||
__entry->page = page;
|
||||
__entry->netmem = (__force unsigned long)netmem;
|
||||
__entry->release = release;
|
||||
__entry->pfn = page_to_pfn(page);
|
||||
__entry->pfn = netmem_to_pfn(netmem);
|
||||
),
|
||||
|
||||
TP_printk("page_pool=%p page=%p pfn=0x%lx release=%u",
|
||||
__entry->pool, __entry->page, __entry->pfn, __entry->release)
|
||||
TP_printk("page_pool=%p netmem=%p pfn=0x%lx release=%u",
|
||||
__entry->pool, (void *)__entry->netmem,
|
||||
__entry->pfn, __entry->release)
|
||||
);
|
||||
|
||||
TRACE_EVENT(page_pool_state_hold,
|
||||
|
||||
TP_PROTO(const struct page_pool *pool,
|
||||
const struct page *page, u32 hold),
|
||||
netmem_ref netmem, u32 hold),
|
||||
|
||||
TP_ARGS(pool, page, hold),
|
||||
TP_ARGS(pool, netmem, hold),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(const struct page_pool *, pool)
|
||||
__field(const struct page *, page)
|
||||
__field(unsigned long, netmem)
|
||||
__field(u32, hold)
|
||||
__field(unsigned long, pfn)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->pool = pool;
|
||||
__entry->page = page;
|
||||
__entry->netmem = (__force unsigned long)netmem;
|
||||
__entry->hold = hold;
|
||||
__entry->pfn = page_to_pfn(page);
|
||||
__entry->pfn = netmem_to_pfn(netmem);
|
||||
),
|
||||
|
||||
TP_printk("page_pool=%p page=%p pfn=0x%lx hold=%u",
|
||||
__entry->pool, __entry->page, __entry->pfn, __entry->hold)
|
||||
TP_printk("page_pool=%p netmem=%p pfn=0x%lx hold=%u",
|
||||
__entry->pool, (void *)__entry->netmem,
|
||||
__entry->pfn, __entry->hold)
|
||||
);
|
||||
|
||||
TRACE_EVENT(page_pool_update_nid,
|
||||
|
||||
+3
-2
@@ -127,9 +127,10 @@ struct xdp_test_data {
|
||||
#define TEST_XDP_FRAME_SIZE (PAGE_SIZE - sizeof(struct xdp_page_head))
|
||||
#define TEST_XDP_MAX_BATCH 256
|
||||
|
||||
static void xdp_test_run_init_page(struct page *page, void *arg)
|
||||
static void xdp_test_run_init_page(netmem_ref netmem, void *arg)
|
||||
{
|
||||
struct xdp_page_head *head = phys_to_virt(page_to_phys(page));
|
||||
struct xdp_page_head *head =
|
||||
phys_to_virt(page_to_phys(netmem_to_page(netmem)));
|
||||
struct xdp_buff *new_ctx, *orig_ctx;
|
||||
u32 headroom = XDP_PACKET_HEADROOM;
|
||||
struct xdp_test_data *xdp = arg;
|
||||
|
||||
+165
-139
File diff suppressed because it is too large
Load Diff
+5
-3
@@ -1015,8 +1015,10 @@ int skb_cow_data_for_xdp(struct page_pool *pool, struct sk_buff **pskb,
|
||||
EXPORT_SYMBOL(skb_cow_data_for_xdp);
|
||||
|
||||
#if IS_ENABLED(CONFIG_PAGE_POOL)
|
||||
bool napi_pp_put_page(struct page *page)
|
||||
bool napi_pp_put_page(netmem_ref netmem)
|
||||
{
|
||||
struct page *page = netmem_to_page(netmem);
|
||||
|
||||
page = compound_head(page);
|
||||
|
||||
/* page->pp_magic is OR'ed with PP_SIGNATURE after the allocation
|
||||
@@ -1029,7 +1031,7 @@ bool napi_pp_put_page(struct page *page)
|
||||
if (unlikely(!is_pp_page(page)))
|
||||
return false;
|
||||
|
||||
page_pool_put_full_page(page->pp, page, false);
|
||||
page_pool_put_full_netmem(page->pp, page_to_netmem(page), false);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1040,7 +1042,7 @@ static bool skb_pp_recycle(struct sk_buff *skb, void *data)
|
||||
{
|
||||
if (!IS_ENABLED(CONFIG_PAGE_POOL) || !skb->pp_recycle)
|
||||
return false;
|
||||
return napi_pp_put_page(virt_to_page(data));
|
||||
return napi_pp_put_page(page_to_netmem(virt_to_page(data)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user