drivers/net/ethernet/mediatek/mtk_eth_soc.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-)
When rx_flag == MTK_RX_FLAGS_HWLRO,
rx_data_len = MTK_MAX_LRO_RX_LENGTH(4096 * 3) > PAGE_SIZE.
netdev_alloc_frag is for alloction of page fragment only.
Reference to other drivers and Documentation/vm/page_frags.rst
Branch to use __get_free_pages when ring->frag_size > PAGE_SIZE.
Signed-off-by: Chen Lin <chen45464546@163.com>
---
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 21 +++++++++++++++++++--
1 file changed, 19 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index b3b3c07..3da162e 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -899,6 +899,17 @@ static bool mtk_rx_get_desc(struct mtk_eth *eth, struct mtk_rx_dma_v2 *rxd,
return true;
}
+static inline void *mtk_max_lro_buf_alloc(gfp_t gfp_mask)
+{
+ void *data;
+
+ data = (void *)__get_free_pages(gfp_mask |
+ __GFP_COMP | __GFP_NOWARN,
+ get_order(mtk_max_frag_size(MTK_MAX_LRO_RX_LENGTH)));
+
+ return data;
+}
+
/* the qdma core needs scratch memory to be setup */
static int mtk_init_fq_dma(struct mtk_eth *eth)
{
@@ -1467,7 +1478,10 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
goto release_desc;
/* alloc new buffer */
- new_data = napi_alloc_frag(ring->frag_size);
+ if (ring->frag_size <= PAGE_SIZE)
+ new_data = napi_alloc_frag(ring->frag_size);
+ else
+ new_data = mtk_max_lro_buf_alloc(GFP_ATOMIC);
if (unlikely(!new_data)) {
netdev->stats.rx_dropped++;
goto release_desc;
@@ -1914,7 +1928,10 @@ static int mtk_rx_alloc(struct mtk_eth *eth, int ring_no, int rx_flag)
return -ENOMEM;
for (i = 0; i < rx_dma_size; i++) {
- ring->data[i] = netdev_alloc_frag(ring->frag_size);
+ if (ring->frag_size <= PAGE_SIZE)
+ ring->data[i] = netdev_alloc_frag(ring->frag_size);
+ else
+ ring->data[i] = mtk_max_lro_buf_alloc(GFP_KERNEL);
if (!ring->data[i])
return -ENOMEM;
}
--
1.7.9.5
On Tue, 7 Jun 2022 07:39:11 +0800 Chen Lin wrote: > +static inline void *mtk_max_lro_buf_alloc(gfp_t gfp_mask) No need for inline, compiler will inline this anyway. > +{ > + void *data; unsigned long data; then you can move the cast from the long line to the return statement, saving us from the strange indentation. > + data = (void *)__get_free_pages(gfp_mask | > + __GFP_COMP | __GFP_NOWARN, > + get_order(mtk_max_frag_size(MTK_MAX_LRO_RX_LENGTH))); > + > + return data; > +}
At 2022-06-08 07:14:13, "Jakub Kicinski" <kuba@kernel.org> wrote: >On Tue, 7 Jun 2022 07:39:11 +0800 Chen Lin wrote: >> +static inline void *mtk_max_lro_buf_alloc(gfp_t gfp_mask) > >No need for inline, compiler will inline this anyway. > >> +{ >> + void *data; > >unsigned long data; then you can move the cast from the long line to >the return statement, saving us from the strange indentation. > >> + data = (void *)__get_free_pages(gfp_mask | >> + __GFP_COMP | __GFP_NOWARN, >> + get_order(mtk_max_frag_size(MTK_MAX_LRO_RX_LENGTH))); >> + >> + return data; >> +} I'll do it like below : +static void *mtk_max_lro_buf_alloc(gfp_t gfp_mask) +{ + unsigned long data; + unsigned int size = mtk_max_frag_size(MTK_MAX_LRO_RX_LENGTH); + + data = __get_free_pages(gfp_mask | __GFP_COMP | __GFP_NOWARN, + get_order(size)); + + return (void *)data; +} Through analysis of the ASM code from objdump, I confirmed that the inline is not necessary. Thanks for your tips. Also, I confirmed that create a new local variable 'size' will not affect the generation of a constant 'order' parameter at compile time. ASM code of calling 'mtk_max_lro_buf_alloc': 'mtk_max_lro_buf_alloc' inlined and 'order'(w1) is a constant 0x2 0000000000004530 <mtk_napi_rx>: ... 4a98: 52854400 mov w0, #0x2a20 // #10784 4a9c: 52800041 mov w1, #0x2 // #2 4aa0: 72a00080 movk w0, #0x4, lsl #16 4aa4: 94000000 bl 0 <__get_free_pages> 4aa8: f90033e0 str x0, [sp, #96] 0000000000000730 <mtk_rx_alloc>: ... 7fc: 2a1703e0 mov w0, w23 800: 52800041 mov w1, #0x2 // #2 804: 7140047f cmp w3, #0x1, lsl #12 808: 54fffe49 b.ls 7d0 <mtk_rx_alloc+0xa0> // b.plast 80c: 94000000 bl 0 <__get_free_pages> The compiler is smart.
When rx_flag == MTK_RX_FLAGS_HWLRO,
rx_data_len = MTK_MAX_LRO_RX_LENGTH(4096 * 3) > PAGE_SIZE.
netdev_alloc_frag is for alloction of page fragment only.
Reference to other drivers and Documentation/vm/page_frags.rst
Branch to use __get_free_pages when ring->frag_size > PAGE_SIZE.
Signed-off-by: Chen Lin <chen45464546@163.com>
---
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 21 +++++++++++++++++++--
1 file changed, 19 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index b3b3c07..aba0d84 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -899,6 +899,17 @@ static bool mtk_rx_get_desc(struct mtk_eth *eth, struct mtk_rx_dma_v2 *rxd,
return true;
}
+static void *mtk_max_lro_buf_alloc(gfp_t gfp_mask)
+{
+ unsigned long data;
+ unsigned int size = mtk_max_frag_size(MTK_MAX_LRO_RX_LENGTH);
+
+ data = __get_free_pages(gfp_mask | __GFP_COMP | __GFP_NOWARN,
+ get_order(size));
+
+ return (void *)data;
+}
+
/* the qdma core needs scratch memory to be setup */
static int mtk_init_fq_dma(struct mtk_eth *eth)
{
@@ -1467,7 +1478,10 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
goto release_desc;
/* alloc new buffer */
- new_data = napi_alloc_frag(ring->frag_size);
+ if (ring->frag_size <= PAGE_SIZE)
+ new_data = napi_alloc_frag(ring->frag_size);
+ else
+ new_data = mtk_max_lro_buf_alloc(GFP_ATOMIC);
if (unlikely(!new_data)) {
netdev->stats.rx_dropped++;
goto release_desc;
@@ -1914,7 +1928,10 @@ static int mtk_rx_alloc(struct mtk_eth *eth, int ring_no, int rx_flag)
return -ENOMEM;
for (i = 0; i < rx_dma_size; i++) {
- ring->data[i] = netdev_alloc_frag(ring->frag_size);
+ if (ring->frag_size <= PAGE_SIZE)
+ ring->data[i] = netdev_alloc_frag(ring->frag_size);
+ else
+ ring->data[i] = mtk_max_lro_buf_alloc(GFP_KERNEL);
if (!ring->data[i])
return -ENOMEM;
}
--
1.7.9.5
Hello: This patch was applied to netdev/net.git (master) by Jakub Kicinski <kuba@kernel.org>: On Wed, 8 Jun 2022 20:46:53 +0800 you wrote: > When rx_flag == MTK_RX_FLAGS_HWLRO, > rx_data_len = MTK_MAX_LRO_RX_LENGTH(4096 * 3) > PAGE_SIZE. > netdev_alloc_frag is for alloction of page fragment only. > Reference to other drivers and Documentation/vm/page_frags.rst > > Branch to use __get_free_pages when ring->frag_size > PAGE_SIZE. > > [...] Here is the summary with links: - [v5] net: ethernet: mtk_eth_soc: fix misuse of mem alloc interface netdev[napi]_alloc_frag https://git.kernel.org/netdev/net/c/2f2c0d2919a1 You are awesome, thank you! -- Deet-doot-dot, I am a bot. https://korg.docs.kernel.org/patchwork/pwbot.html
© 2016 - 2024 Red Hat, Inc.