Netdev Archive on lore.kernel.org help / color / mirror / Atom feed
From: Yunsheng Lin <linyunsheng@huawei.com> To: <davem@davemloft.net>, <kuba@kernel.org> Cc: <alexander.duyck@gmail.com>, <linux@armlinux.org.uk>, <mw@semihalf.com>, <linuxarm@openeuler.org>, <yisen.zhuang@huawei.com>, <salil.mehta@huawei.com>, <thomas.petazzoni@bootlin.com>, <hawk@kernel.org>, <ilias.apalodimas@linaro.org>, <ast@kernel.org>, <daniel@iogearbox.net>, <john.fastabend@gmail.com>, <akpm@linux-foundation.org>, <peterz@infradead.org>, <will@kernel.org>, <willy@infradead.org>, <vbabka@suse.cz>, <fenghua.yu@intel.com>, <guro@fb.com>, <peterx@redhat.com>, <feng.tang@intel.com>, <jgg@ziepe.ca>, <mcroce@microsoft.com>, <hughd@google.com>, <jonathan.lemon@gmail.com>, <alobakin@pm.me>, <willemb@google.com>, <wenxu@ucloud.cn>, <cong.wang@bytedance.com>, <haokexin@gmail.com>, <nogikh@google.com>, <elver@google.com>, <yhs@fb.com>, <kpsingh@kernel.org>, <andrii@kernel.org>, <kafai@fb.com>, <songliubraving@fb.com>, <netdev@vger.kernel.org>, <linux-kernel@vger.kernel.org>, <bpf@vger.kernel.org>, <chenhao288@hisilicon.com> Subject: [PATCH net-next v2 3/4] page_pool: add frag page recycling support in page pool Date: Fri, 6 Aug 2021 10:46:21 +0800 [thread overview] Message-ID: <1628217982-53533-4-git-send-email-linyunsheng@huawei.com> (raw) In-Reply-To: <1628217982-53533-1-git-send-email-linyunsheng@huawei.com> Currently page pool only support page recycling when there is only one user of the page, and the split page reusing implemented in the most driver can not use the page pool as bing-pong way of reusing requires the multi user support in page pool. Those reusing or recycling has below limitations: 1. page from page pool can only be used be one user in order for the page recycling to happen. 2. Bing-pong way of reusing in most driver does not support multi desc using different part of the same page in order to save memory. So add multi-users support and frag page recycling in page pool to overcome the above limitation. Signed-off-by: Yunsheng Lin <linyunsheng@huawei.com> --- include/net/page_pool.h | 15 +++++++++ net/core/page_pool.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+) diff --git a/include/net/page_pool.h b/include/net/page_pool.h index 42e6997..a408240 100644 --- a/include/net/page_pool.h +++ b/include/net/page_pool.h @@ -91,6 +91,9 @@ struct page_pool { unsigned long defer_warn; u32 pages_state_hold_cnt; + unsigned int frag_offset; + struct page *frag_page; + long frag_users; /* * Data structure for allocation side @@ -140,6 +143,18 @@ static inline struct page *page_pool_dev_alloc_pages(struct page_pool *pool) return page_pool_alloc_pages(pool, gfp); } +struct page *page_pool_alloc_frag(struct page_pool *pool, unsigned int *offset, + unsigned int size, gfp_t gfp); + +static inline struct page *page_pool_dev_alloc_frag(struct page_pool *pool, + unsigned int *offset, + unsigned int size) +{ + gfp_t gfp = (GFP_ATOMIC | __GFP_NOWARN); + + return page_pool_alloc_frag(pool, offset, size, gfp); +} + /* get the stored dma direction. A driver might decide to treat this locally and * avoid the extra cache line from page_pool to determine the direction */ diff --git a/net/core/page_pool.c b/net/core/page_pool.c index 68fab94..ac11604 100644 --- a/net/core/page_pool.c +++ b/net/core/page_pool.c @@ -24,6 +24,8 @@ #define DEFER_TIME (msecs_to_jiffies(1000)) #define DEFER_WARN_INTERVAL (60 * HZ) +#define BIAS_MAX LONG_MAX + static int page_pool_init(struct page_pool *pool, const struct page_pool_params *params) { @@ -423,6 +425,11 @@ static __always_inline struct page * __page_pool_put_page(struct page_pool *pool, struct page *page, unsigned int dma_sync_size, bool allow_direct) { + /* It is not the last user for the page frag case */ + if (pool->p.flags & PP_FLAG_PAGE_FRAG && + page_pool_atomic_sub_frag_count_return(page, 1)) + return NULL; + /* This allocator is optimized for the XDP mode that uses * one-frame-per-page, but have fallbacks that act like the * regular page allocator APIs. @@ -515,6 +522,84 @@ void page_pool_put_page_bulk(struct page_pool *pool, void **data, } EXPORT_SYMBOL(page_pool_put_page_bulk); +static struct page *page_pool_drain_frag(struct page_pool *pool, + struct page *page) +{ + long drain_count = BIAS_MAX - pool->frag_users; + + /* Some user is still using the page frag */ + if (likely(page_pool_atomic_sub_frag_count_return(page, + drain_count))) + return NULL; + + if (page_ref_count(page) == 1 && !page_is_pfmemalloc(page)) { + if (pool->p.flags & PP_FLAG_DMA_SYNC_DEV) + page_pool_dma_sync_for_device(pool, page, -1); + + return page; + } + + page_pool_return_page(pool, page); + return NULL; +} + +static void page_pool_free_frag(struct page_pool *pool) +{ + long drain_count = BIAS_MAX - pool->frag_users; + struct page *page = pool->frag_page; + + pool->frag_page = NULL; + + if (!page || + page_pool_atomic_sub_frag_count_return(page, drain_count)) + return; + + page_pool_return_page(pool, page); +} + +struct page *page_pool_alloc_frag(struct page_pool *pool, + unsigned int *offset, + unsigned int size, gfp_t gfp) +{ + unsigned int max_size = PAGE_SIZE << pool->p.order; + struct page *page = pool->frag_page; + + if (WARN_ON(!(pool->p.flags & PP_FLAG_PAGE_FRAG) || + size > max_size)) + return NULL; + + size = ALIGN(size, dma_get_cache_alignment()); + *offset = pool->frag_offset; + + if (page && *offset + size > max_size) { + page = page_pool_drain_frag(pool, page); + if (page) + goto frag_reset; + } + + if (!page) { + page = page_pool_alloc_pages(pool, gfp); + if (unlikely(!page)) { + pool->frag_page = NULL; + return NULL; + } + + pool->frag_page = page; + +frag_reset: + pool->frag_users = 1; + *offset = 0; + pool->frag_offset = size; + page_pool_set_frag_count(page, BIAS_MAX); + return page; + } + + pool->frag_users++; + pool->frag_offset = *offset + size; + return page; +} +EXPORT_SYMBOL(page_pool_alloc_frag); + static void page_pool_empty_ring(struct page_pool *pool) { struct page *page; @@ -620,6 +705,8 @@ void page_pool_destroy(struct page_pool *pool) if (!page_pool_put(pool)) return; + page_pool_free_frag(pool); + if (!page_pool_release(pool)) return; -- 2.7.4
next prev parent reply other threads:[~2021-08-06 2:47 UTC|newest] Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top 2021-08-06 2:46 [PATCH net-next v2 0/4] add frag page support in page pool Yunsheng Lin 2021-08-06 2:46 ` [PATCH net-next v2 1/4] page_pool: keep pp info as long as page pool owns the page Yunsheng Lin 2021-08-06 2:46 ` [PATCH net-next v2 2/4] page_pool: add interface to manipulate frag count in page pool Yunsheng Lin 2021-08-10 14:58 ` Jesper Dangaard Brouer 2021-08-11 0:48 ` Yunsheng Lin 2021-08-12 15:17 ` Jesper Dangaard Brouer 2021-08-06 2:46 ` Yunsheng Lin [this message] 2021-08-06 2:46 ` [PATCH net-next v2 4/4] net: hns3: support skb's frag page recycling based on " Yunsheng Lin 2021-09-08 8:31 ` moyufeng 2021-09-08 15:08 ` Jakub Kicinski 2021-09-08 15:26 ` Ilias Apalodimas 2021-09-08 15:57 ` Jakub Kicinski 2021-09-08 16:47 ` Jesper Dangaard Brouer 2021-09-08 16:51 ` Ilias Apalodimas 2022-01-26 14:30 ` Jean-Philippe Brucker 2022-01-28 4:00 ` Yunsheng Lin 2022-01-28 9:21 ` Jean-Philippe Brucker 2022-01-29 8:44 ` Yunsheng Lin 2022-02-03 9:48 ` Jean-Philippe Brucker 2022-02-07 2:54 ` Yunsheng Lin 2022-03-24 18:09 ` Jean-Philippe Brucker 2021-08-10 14:01 ` [PATCH net-next v2 0/4] add frag page support in " Jakub Kicinski 2021-08-10 14:23 ` Jesper Dangaard Brouer 2021-08-10 14:43 ` Jakub Kicinski 2021-08-10 15:09 ` Alexander Duyck 2021-08-11 1:06 ` [Linuxarm] " Yunsheng Lin
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=1628217982-53533-4-git-send-email-linyunsheng@huawei.com \ --to=linyunsheng@huawei.com \ --cc=akpm@linux-foundation.org \ --cc=alexander.duyck@gmail.com \ --cc=alobakin@pm.me \ --cc=andrii@kernel.org \ --cc=ast@kernel.org \ --cc=bpf@vger.kernel.org \ --cc=chenhao288@hisilicon.com \ --cc=cong.wang@bytedance.com \ --cc=daniel@iogearbox.net \ --cc=davem@davemloft.net \ --cc=elver@google.com \ --cc=feng.tang@intel.com \ --cc=fenghua.yu@intel.com \ --cc=guro@fb.com \ --cc=haokexin@gmail.com \ --cc=hawk@kernel.org \ --cc=hughd@google.com \ --cc=ilias.apalodimas@linaro.org \ --cc=jgg@ziepe.ca \ --cc=john.fastabend@gmail.com \ --cc=jonathan.lemon@gmail.com \ --cc=kafai@fb.com \ --cc=kpsingh@kernel.org \ --cc=kuba@kernel.org \ --cc=linux-kernel@vger.kernel.org \ --cc=linux@armlinux.org.uk \ --cc=linuxarm@openeuler.org \ --cc=mcroce@microsoft.com \ --cc=mw@semihalf.com \ --cc=netdev@vger.kernel.org \ --cc=nogikh@google.com \ --cc=peterx@redhat.com \ --cc=peterz@infradead.org \ --cc=salil.mehta@huawei.com \ --cc=songliubraving@fb.com \ --cc=thomas.petazzoni@bootlin.com \ --cc=vbabka@suse.cz \ --cc=wenxu@ucloud.cn \ --cc=will@kernel.org \ --cc=willemb@google.com \ --cc=willy@infradead.org \ --cc=yhs@fb.com \ --cc=yisen.zhuang@huawei.com \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).