net: stmmac: RX performance improvement
Subsystems (6)
v3 cover net: stmmac: RX performance improvement
This series improves RX performance a lot, ~40% TCP RX throughput boost has been observed with DWXGMAC CORE 3.20a running on Cortex-A65 CPUs:
from 2.18 Gbits/sec increased to 3.06 Gbits/sec.
---
Changes in v3:
1. Convert prefetch() to net_prefetch() to get better performance (Joe Damato)
v2: https://patchwork.kernel.org/project/netdevbpf/list/?series=924912&state=%2A&archive=both
Changes in v2:
1. No cache prefetch for frags (Alexander Lobakin)
2. Fix code style warning reported by netdev CI on Patchwork
v1: https://patchwork.kernel.org/project/netdevbpf/list/?series=924103&state=%2A&archive=both
---
Furong Xu (4):
net: stmmac: Switch to zero-copy in non-XDP RX path
net: stmmac: Set page_pool_params.max_len to a precise size
net: stmmac: Optimize cache prefetch in RX path
net: stmmac: Convert prefetch() to net_prefetch() for received frames
drivers/net/ethernet/stmicro/stmmac/stmmac.h | 1 + .../net/ethernet/stmicro/stmmac/stmmac_main.c | 34 +++++++++++-------- .../net/ethernet/stmicro/stmmac/stmmac_xdp.h | 1 - 3 files changed, 21 insertions(+), 15 deletions(-)
Signature · 1 line
2.34.1
PATCH v3 1/4 net: stmmac: Switch to zero-copy in non-XDP RX path
Avoid memcpy in non-XDP RX path by marking all allocated SKBs to be recycled in the upper network stack.
This patch brings ~11.5% driver performance improvement in a TCP RX throughput test with iPerf tool on a single isolated Cortex-A65 CPU core, from 2.18 Gbits/sec increased to 2.43 Gbits/sec.
--- drivers/net/ethernet/stmicro/stmmac/stmmac.h | 1 + .../net/ethernet/stmicro/stmmac/stmmac_main.c | 26 ++++++++++++------- 2 files changed, 18 insertions(+), 9 deletions(-)
drivers/net/ethernet/stmicro/stmmac/stmmac.h +1 -0
@@ -126,6 +126,7 @@ struct stmmac_rx_queue {unsigned int cur_rx;unsigned int dirty_rx;unsigned int buf_alloc_num; +unsigned int napi_skb_frag_size;dma_addr_t dma_rx_phy;u32 rx_tail_addr;unsigned int state_saved;
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +17 -9
@@ -1341,7 +1341,7 @@ static unsigned int stmmac_rx_offset(struct stmmac_priv *priv)if (stmmac_xdp_is_enabled (priv))return XDP_PACKET_HEADROOM ; -return 0 ; +return NET_SKB_PAD ; }static int stmmac_set_bfsize (int mtu,int bufsize)
@@ -2040,17 +2040,21 @@ static int __alloc_dma_rx_desc_resources(struct stmmac_priv *priv,struct stmmac_channel *ch = &priv->channel[queue];bool xdp_prog =stmmac_xdp_is_enabled (priv);struct page_pool_params pp_params = {0 }; -unsigned int num_pages; +unsigned int dma_buf_sz_pad, num_pages;unsigned int napi_id;int ret; + dma_buf_sz_pad =stmmac_rx_offset (priv) + dma_conf->dma_buf_sz + +SKB_DATA_ALIGN (sizeof (struct skb_shared_info )); + num_pages =DIV_ROUND_UP (dma_buf_sz_pad,PAGE_SIZE ); + rx_q->queue_index = queue; rx_q->priv_data = priv; + rx_q->napi_skb_frag_size = num_pages *PAGE_SIZE ; pp_params.flags =PP_FLAG_DMA_MAP |PP_FLAG_DMA_SYNC_DEV ; pp_params.pool_size = dma_conf->dma_rx_size; - num_pages =DIV_ROUND_UP (dma_conf->dma_buf_sz,PAGE_SIZE ); - pp_params.order =ilog2 (num_pages); + pp_params.order =order_base_2 (num_pages); pp_params.nid =dev_to_node (priv->device); pp_params.dev = priv->device; pp_params.dma_dir = xdp_prog ?DMA_BIDIRECTIONAL :DMA_FROM_DEVICE ;
@@ -5582,22 +5586,26 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue) }if (!skb) { +unsigned int head_pad_len; +/* XDP program may expand or reduce tail */ buf1_len = ctx.xdp.data_end - ctx.xdp.data; - skb =napi_alloc_skb (&ch->rx_napi, buf1_len); + skb =napi_build_skb (page_address (buf->page), + rx_q->napi_skb_frag_size);if (!skb) { +page_pool_recycle_direct (rx_q->page_pool, + buf->page); rx_dropped++; count++; goto drain_data; }/* XDP program may adjust header */ -skb_copy_to_linear_data (skb, ctx.xdp.data, buf1_len); + head_pad_len = ctx.xdp.data - ctx.xdp.data_hard_start; +skb_reserve (skb, head_pad_len);skb_put (skb, buf1_len); - -/* Data payload copied into SKB, page ready for recycle */ -page_pool_recycle_direct (rx_q->page_pool, buf->page); +skb_mark_for_recycle (skb); buf->page =NULL ; }else if (buf1_len) { dma_sync_single_for_cpu(priv->device, buf->addr,
Signature · 1 line
2.34.1
Re: [PATCH net-next v3 1/4] net: stmmac: Switch to zero-copy in non-XDP RX path
Quoted 9 lines · Furong Xu
Avoid memcpy in non-XDP RX path by marking all allocated SKBs to be recycled in the upper network stack.
This patch brings ~11.5% driver performance improvement in a TCP RX throughput test with iPerf tool on a single isolated Cortex-A65 CPU core, from 2.18 Gbits/sec increased to 2.43 Gbits/sec.
Signed-off-by Furong Xu <[email protected]>Reviewed-by Alexander Lobakin <[email protected]>
Quoted 91 lines
--- drivers/net/ethernet/stmicro/stmmac/stmmac.h | 1 + .../net/ethernet/stmicro/stmmac/stmmac_main.c | 26 ++++++++++++------- 2 files changed, 18 insertions(+), 9 deletions(-)drivers/net/ethernet/stmicro/stmmac/stmmac.h +1
-0@@ -126,6 +126,7 @@ struct stmmac_rx_queue {unsigned int cur_rx;unsigned int dirty_rx;unsigned int buf_alloc_num; +unsigned int napi_skb_frag_size;dma_addr_t dma_rx_phy;u32 rx_tail_addr;unsigned int state_saved;drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +17
-9@@ -1341,7 +1341,7 @@ static unsigned int stmmac_rx_offset(struct stmmac_priv *priv)if (stmmac_xdp_is_enabled (priv))return XDP_PACKET_HEADROOM ; -return 0 ; +return NET_SKB_PAD ; }static int stmmac_set_bfsize (int mtu,int bufsize)@@ -2040,17 +2040,21 @@ static int __alloc_dma_rx_desc_resources(struct stmmac_priv *priv,struct stmmac_channel *ch = &priv->channel[queue];bool xdp_prog =stmmac_xdp_is_enabled (priv);struct page_pool_params pp_params = {0 }; -unsigned int num_pages; +unsigned int dma_buf_sz_pad, num_pages;unsigned int napi_id;int ret; + dma_buf_sz_pad =stmmac_rx_offset (priv) + dma_conf->dma_buf_sz + +SKB_DATA_ALIGN (sizeof (struct skb_shared_info )); + num_pages =DIV_ROUND_UP (dma_buf_sz_pad,PAGE_SIZE ); + rx_q->queue_index = queue; rx_q->priv_data = priv; + rx_q->napi_skb_frag_size = num_pages *PAGE_SIZE ; pp_params.flags =PP_FLAG_DMA_MAP |PP_FLAG_DMA_SYNC_DEV ; pp_params.pool_size = dma_conf->dma_rx_size; - num_pages =DIV_ROUND_UP (dma_conf->dma_buf_sz,PAGE_SIZE ); - pp_params.order =ilog2 (num_pages); + pp_params.order =order_base_2 (num_pages); pp_params.nid =dev_to_node (priv->device); pp_params.dev = priv->device; pp_params.dma_dir = xdp_prog ?DMA_BIDIRECTIONAL :DMA_FROM_DEVICE ;@@ -5582,22 +5586,26 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue) }if (!skb) { +unsigned int head_pad_len; +/* XDP program may expand or reduce tail */ buf1_len = ctx.xdp.data_end - ctx.xdp.data; - skb =napi_alloc_skb (&ch->rx_napi, buf1_len); + skb =napi_build_skb (page_address (buf->page), + rx_q->napi_skb_frag_size);if (!skb) { +page_pool_recycle_direct (rx_q->page_pool, + buf->page); rx_dropped++; count++; goto drain_data; }/* XDP program may adjust header */ -skb_copy_to_linear_data (skb, ctx.xdp.data, buf1_len); + head_pad_len = ctx.xdp.data - ctx.xdp.data_hard_start; +skb_reserve (skb, head_pad_len);skb_put (skb, buf1_len); - -/* Data payload copied into SKB, page ready for recycle */ -page_pool_recycle_direct (rx_q->page_pool, buf->page); +skb_mark_for_recycle (skb); buf->page =NULL ; }else if (buf1_len) { dma_sync_single_for_cpu(priv->device, buf->addr,Signature · 1 line
2.34.1
Re: [PATCH net-next v3 1/4] net: stmmac: Switch to zero-copy in non-XDP RX path
In reply to Furong XuQuoted 9 lines · Furong Xu
Avoid memcpy in non-XDP RX path by marking all allocated SKBs to be recycled in the upper network stack.
This patch brings ~11.5% driver performance improvement in a TCP RX throughput test with iPerf tool on a single isolated Cortex-A65 CPU core, from 2.18 Gbits/sec increased to 2.43 Gbits/sec.
Signed-off-by Furong Xu <[email protected]>Reviewed-by Alexander Lobakin <[email protected]>
Thanks,
Yanteng
Quoted 87 lines
--- drivers/net/ethernet/stmicro/stmmac/stmmac.h | 1 + .../net/ethernet/stmicro/stmmac/stmmac_main.c | 26 ++++++++++++------- 2 files changed, 18 insertions(+), 9 deletions(-)drivers/net/ethernet/stmicro/stmmac/stmmac.h +1
-0@@ -126,6 +126,7 @@ struct stmmac_rx_queue {unsigned int cur_rx;unsigned int dirty_rx;unsigned int buf_alloc_num; +unsigned int napi_skb_frag_size;dma_addr_t dma_rx_phy;u32 rx_tail_addr;unsigned int state_saved;drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +17
-9@@ -1341,7 +1341,7 @@ static unsigned int stmmac_rx_offset(struct stmmac_priv *priv)if (stmmac_xdp_is_enabled (priv))return XDP_PACKET_HEADROOM ; -return 0 ; +return NET_SKB_PAD ; }static int stmmac_set_bfsize (int mtu,int bufsize)@@ -2040,17 +2040,21 @@ static int __alloc_dma_rx_desc_resources(struct stmmac_priv *priv,struct stmmac_channel *ch = &priv->channel[queue];bool xdp_prog =stmmac_xdp_is_enabled (priv);struct page_pool_params pp_params = {0 }; -unsigned int num_pages; +unsigned int dma_buf_sz_pad, num_pages;unsigned int napi_id;int ret; + dma_buf_sz_pad =stmmac_rx_offset (priv) + dma_conf->dma_buf_sz + +SKB_DATA_ALIGN (sizeof (struct skb_shared_info )); + num_pages =DIV_ROUND_UP (dma_buf_sz_pad,PAGE_SIZE ); + rx_q->queue_index = queue; rx_q->priv_data = priv; + rx_q->napi_skb_frag_size = num_pages *PAGE_SIZE ; pp_params.flags =PP_FLAG_DMA_MAP |PP_FLAG_DMA_SYNC_DEV ; pp_params.pool_size = dma_conf->dma_rx_size; - num_pages =DIV_ROUND_UP (dma_conf->dma_buf_sz,PAGE_SIZE ); - pp_params.order =ilog2 (num_pages); + pp_params.order =order_base_2 (num_pages); pp_params.nid =dev_to_node (priv->device); pp_params.dev = priv->device; pp_params.dma_dir = xdp_prog ?DMA_BIDIRECTIONAL :DMA_FROM_DEVICE ;@@ -5582,22 +5586,26 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue) }if (!skb) { +unsigned int head_pad_len; +/* XDP program may expand or reduce tail */ buf1_len = ctx.xdp.data_end - ctx.xdp.data; - skb =napi_alloc_skb (&ch->rx_napi, buf1_len); + skb =napi_build_skb (page_address (buf->page), + rx_q->napi_skb_frag_size);if (!skb) { +page_pool_recycle_direct (rx_q->page_pool, + buf->page); rx_dropped++; count++; goto drain_data; }/* XDP program may adjust header */ -skb_copy_to_linear_data (skb, ctx.xdp.data, buf1_len); + head_pad_len = ctx.xdp.data - ctx.xdp.data_hard_start; +skb_reserve (skb, head_pad_len);skb_put (skb, buf1_len); - -/* Data payload copied into SKB, page ready for recycle */ -page_pool_recycle_direct (rx_q->page_pool, buf->page); +skb_mark_for_recycle (skb); buf->page =NULL ; }else if (buf1_len) { dma_sync_single_for_cpu(priv->device, buf->addr,
Jon Hunter
maintainerRe: [PATCH net-next v3 1/4] net: stmmac: Switch to zero-copy in non-XDP RX path
In reply to Furong XuHi Furong,
Quoted 86 lines · Furong Xu
Avoid memcpy in non-XDP RX path by marking all allocated SKBs to be recycled in the upper network stack.
This patch brings ~11.5% driver performance improvement in a TCP RX throughput test with iPerf tool on a single isolated Cortex-A65 CPU core, from 2.18 Gbits/sec increased to 2.43 Gbits/sec.
Signed-off-by Furong Xu <[email protected]>Reviewed-by Alexander Lobakin <[email protected]>--- drivers/net/ethernet/stmicro/stmmac/stmmac.h | 1 + .../net/ethernet/stmicro/stmmac/stmmac_main.c | 26 ++++++++++++------- 2 files changed, 18 insertions(+), 9 deletions(-)drivers/net/ethernet/stmicro/stmmac/stmmac.h +1
-0@@ -126,6 +126,7 @@ struct stmmac_rx_queue {unsigned int cur_rx;unsigned int dirty_rx;unsigned int buf_alloc_num; +unsigned int napi_skb_frag_size;dma_addr_t dma_rx_phy;u32 rx_tail_addr;unsigned int state_saved;drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +14
-6@@ -1341,7 +1341,7 @@ static unsigned int stmmac_rx_offset(struct stmmac_priv *priv)if (stmmac_xdp_is_enabled (priv))return XDP_PACKET_HEADROOM ; -return 0 ; +return NET_SKB_PAD ; }static int stmmac_set_bfsize (int mtu,int bufsize)@@ -2040,17 +2040,21 @@ static int __alloc_dma_rx_desc_resources(struct stmmac_priv *priv,struct stmmac_channel *ch = &priv->channel[queue];bool xdp_prog =stmmac_xdp_is_enabled (priv);struct page_pool_params pp_params = {0 }; -unsigned int num_pages; +unsigned int dma_buf_sz_pad, num_pages;unsigned int napi_id;int ret; + dma_buf_sz_pad =stmmac_rx_offset (priv) + dma_conf->dma_buf_sz + +SKB_DATA_ALIGN (sizeof (struct skb_shared_info )); + num_pages =DIV_ROUND_UP (dma_buf_sz_pad,PAGE_SIZE ); + rx_q->queue_index = queue; rx_q->priv_data = priv; + rx_q->napi_skb_frag_size = num_pages *PAGE_SIZE ; pp_params.flags =PP_FLAG_DMA_MAP |PP_FLAG_DMA_SYNC_DEV ; pp_params.pool_size = dma_conf->dma_rx_size; - num_pages =DIV_ROUND_UP (dma_conf->dma_buf_sz,PAGE_SIZE ); - pp_params.order =ilog2 (num_pages); + pp_params.order =order_base_2 (num_pages); pp_params.nid =dev_to_node (priv->device); pp_params.dev = priv->device; pp_params.dma_dir = xdp_prog ?DMA_BIDIRECTIONAL :DMA_FROM_DEVICE ;@@ -5582,22 +5586,26 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue) }if (!skb) { +unsigned int head_pad_len; +/* XDP program may expand or reduce tail */ buf1_len = ctx.xdp.data_end - ctx.xdp.data; - skb =napi_alloc_skb (&ch->rx_napi, buf1_len); + skb =napi_build_skb (page_address (buf->page), + rx_q->napi_skb_frag_size);if (!skb) { +page_pool_recycle_direct (rx_q->page_pool, + buf->page); rx_dropped++; count++; goto drain_data; }/* XDP program may adjust header */ -skb_copy_to_linear_data (skb, ctx.xdp.data, buf1_len);
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue) · line 5611
Quoted 10 lines
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +3
-3+ head_pad_len = ctx.xdp.data - ctx.xdp.data_hard_start; +skb_reserve (skb, head_pad_len);skb_put (skb, buf1_len); - -/* Data payload copied into SKB, page ready for recycle */ -page_pool_recycle_direct (rx_q->page_pool, buf->page); +skb_mark_for_recycle (skb); buf->page =NULL ; }else if (buf1_len) { dma_sync_single_for_cpu(priv->device, buf->addr,
We have noticed a boot regression on -next when booting with NFS. Bisect is pointing to this commit and reverting this on top of -next does fix the problem.
I only see this on Tegra234 which uses the drivers/net/ethernet/stmicro/stmmac/dwmac-tegra.c driver. Tegra194 which uses the drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c driver appears to be fine.
I tried booting without NFS and the network interface seems to come up fine. It only seems to be a problem when booting with NFS. However, I guess I have also not stressed the network interface when booting without NFS. Have you tried booting with NFS?
Thanks
Jon
Signature · 1 line
nvpublic
Re: [PATCH net-next v3 1/4] net: stmmac: Switch to zero-copy in non-XDP RX path
Hi Jon,
Quoted 9 lines · Jon Hunter
We have noticed a boot regression on -next when booting with NFS. Bisect is pointing to this commit and reverting this on top of -next does fix the problem.
I only see this on Tegra234 which uses the
drivers/net/ethernet/stmicro/stmmac/dwmac-tegra.cdriver. Tegra194 which uses thedrivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.cdriver appears to be fine.
What is the MTU of Tegra234 and NFS server? Are they both 1500?
Could you please try attached patch to confirm if this regression is fixed?
If the attached patch fixes this regression, and so it seems to be a cache coherence issue specific to Tegra234, since this patch avoid memcpy and the page buffers may be modified by upper network stack of course, then cache lines of page buffers may become dirty. But by reverting this patch, cache lines of page buffers never become dirty, this is the core difference.
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +1 -1
@@ -5442,7 +5442,7 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)struct stmmac_rx_queue *rx_q = &priv->dma_conf.rx_queue[queue];struct stmmac_channel *ch = &priv->channel[queue];unsigned int count =0 , error =0 , len =0 ; -int status =0 , coe = priv->hw->rx_csum; +int status =0 , coe =0 ;unsigned int next_entry = rx_q->cur_rx;enum dma_data_direction dma_dir;unsigned int desc_size;
Re: [PATCH net-next v3 1/4] net: stmmac: Switch to zero-copy in non-XDP RX path
Quoted 1 line · Furong Xu
What is the MTU of Tegra234 and NFS server? Are they both 1500?
I see the same issue. Yes, both are 1500.
Quoted 2 lines
Could you please try attached patch to confirm if this regression is fixed?
Patch fixes the issue.
Quoted 6 lines
If the attached patch fixes this regression, and so it seems to be a cache coherence issue specific to Tegra234, since this patch avoid memcpy and the page buffers may be modified by upper network stack of course, then cache lines of page buffers may become dirty. But by reverting this patch, cache lines of page buffers never become dirty, this is the core difference.
Thanks for these insights. I don't have specific experience in this driver, but I see we have dma-coherent turned on for this driver in our downstream device tree files (i.e. dtbs that coincide with our out-of-tree implementation of this driver). I went back to the original code and verified that the issue was there. I did a new test where I added dma-coherent to this ethernet node in the dtb and retested. It worked!
Just to clarify, the patch that you had us try was not intended as an actual fix, correct? It was only for diagnostic purposes, i.e. to see if there is some kind of cache coherence issue, which seems to be the case?
So perhaps the only fix needed is to add dma-coherent to our device tree?
Re: [PATCH net-next v3 1/4] net: stmmac: Switch to zero-copy in non-XDP RX path
Quoted 4 lines
Just to clarify, the patch that you had us try was not intended as an actual fix, correct? It was only for diagnostic purposes, i.e. to see if there is some kind of cache coherence issue, which seems to be the case? So perhaps the only fix needed is to add dma-coherent to our device tree?
That sounds quite error prone. How many other DT blobs are missing the property? If the memory should be coherent, i would expect the driver to allocate coherent memory. Or the driver needs to handle non-coherent memory and add the necessary flush/invalidates etc.
Andrew
Re: [PATCH net-next v3 1/4] net: stmmac: Switch to zero-copy in non-XDP RX path
Quoted 9 lines · Andrew Lunn
Quoted 4 lines
Just to clarify, the patch that you had us try was not intended as an actual fix, correct? It was only for diagnostic purposes, i.e. to see if there is some kind of cache coherence issue, which seems to be the case? So perhaps the only fix needed is to add dma-coherent to our device tree?
That sounds quite error prone. How many other DT blobs are missing the property? If the memory should be coherent, i would expect the driver to allocate coherent memory. Or the driver needs to handle non-coherent memory and add the necessary flush/invalidates etc.
stmmac driver does the necessary cache flush/invalidates to maintain cache lines explicitly.
See dma_sync_single_for_cpu():
https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git/tree/include/linux/dma-mapping.h#n297
dma_dev_need_sync() is supposed to return false for Tegra234, since the ethernet controller on Tegra234 is dma coherent by SoC design as Brad said their downstream device tree has dma-coherent turned on by default, and after add dma-coherent to mainline ethernet node, stmmac driver works fine. But dma-coherent property is missing in mainline Tegra234 ethernet device tree node, dma_dev_need_sync() returns true and this is not the expected behavior.
The dma-coherent property in device tree node is SoC specific, so only the vendors know if their stmmac ethernet controller is dma coherent and whether their device tree are missing the critical dma-coherent property.
Re: [PATCH net-next v3 1/4] net: stmmac: Switch to zero-copy in non-XDP RX path
Quoted 18 lines · Furong Xu
Quoted 9 lines · Andrew Lunn
Quoted 4 lines
Just to clarify, the patch that you had us try was not intended as an actual fix, correct? It was only for diagnostic purposes, i.e. to see if there is some kind of cache coherence issue, which seems to be the case? So perhaps the only fix needed is to add dma-coherent to our device tree?
That sounds quite error prone. How many other DT blobs are missing the property? If the memory should be coherent, i would expect the driver to allocate coherent memory. Or the driver needs to handle non-coherent memory and add the necessary flush/invalidates etc.
stmmac driver does the necessary cache flush/invalidates to maintain cache lines explicitly.
See
dma_sync_single_for_cpu():
https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git/tree/include/linux/dma-mapping.h#n297
Quoted 6 lines
dma_dev_need_sync()is supposed to return false for Tegra234, since the ethernet controller on Tegra234 is dma coherent by SoC design as Brad said their downstream device tree has dma-coherent turned on by default, and after add dma-coherent to mainline ethernet node, stmmac driver works fine. But dma-coherent property is missing in mainline Tegra234 ethernet device tree node,dma_dev_need_sync()returns true and this is not the expected behavior.
My understanding is that the Ethernet controller itself is not DMA coherent. Instead, it is by accessing memory through the IOMMU that the accesses become coherent. It's technically possible for the IOMMU to be disabled via command-line, or simply compile out the driver for it, and the devices are supposed to keep working with it (though it's not a recommended configuration), so exclusively relying on the presence of an IOMMU node or even a dma-coherent property is bound to fail in these corner cases. We don't currently have a good way of describing this in device tree, but a discussion with the DT maintainers is probably warranted.
Quoted 3 lines
The dma-coherent property in device tree node is SoC specific, so only the vendors know if their stmmac ethernet controller is dma coherent and whether their device tree are missing the critical dma-coherent property.
What I fail to understand is how dma-coherent can make a difference in this case. If it's not present, then the driver is supposed to maintain caches explicitly. But it seems like explicit cache maintenance actually causes things to break. So do we need to assume that DMA coherent devices in generally won't work if the driver manages caches explicitly?
I always figured dma-coherent was more of an optimization, but this seems to indicate it isn't.
Thierry
Re: [PATCH net-next v3 1/4] net: stmmac: Switch to zero-copy in non-XDP RX path
Am Freitag, dem 24.01.2025 um 14:15 +0100 schrieb Thierry Reding:
Quoted 1 line
[...]
Quoted 4 lines
Quoted 3 lines
The dma-coherent property in device tree node is SoC specific, so only the vendors know if their stmmac ethernet controller is dma coherent and whether their device tree are missing the critical dma-coherent property.
Quoted 8 lines
What I fail to understand is how dma-coherent can make a difference in this case. If it's not present, then the driver is supposed to maintain caches explicitly. But it seems like explicit cache maintenance actually causes things to break. So do we need to assume that DMA coherent devices in generally won't work if the driver manages caches explicitly?
I always figured dma-coherent was more of an optimization, but this seems to indicate it isn't.
There is a real failure scenario when the device is actually dma- coherent, but the DT claims it isn't: If a location from e.g. a receive buffer is already allocated in the cache, the write from the device will update the cache line and not go out to memory. If you then do the usual non-coherent cache maintenance, i.e. invalidate the RX buffer area after the device indicated the reception of the buffer, you will destroy the updated data in the cache and read stale data from memory.
Regards,
Lucas
Re: [PATCH net-next v3 1/4] net: stmmac: Switch to zero-copy in non-XDP RX path
In reply to Furong XuQuoted 7 lines · Furong Xu
Quoted 5 lines · Andrew Lunn
Quoted 4 lines
Just to clarify, the patch that you had us try was not intended as an actual fix, correct? It was only for diagnostic purposes, i.e. to see if there is some kind of cache coherence issue, which seems to be the case? So perhaps the only fix needed is to add dma-coherent to our device tree?
Quoted 7 lines
Quoted 4 lines
That sounds quite error prone. How many other DT blobs are missing the property? If the memory should be coherent, i would expect the driver to allocate coherent memory. Or the driver needs to handle non-coherent memory and add the necessary flush/invalidates etc.
stmmac driver does the necessary cache flush/invalidates to maintain cache lines explicitly.
Given the problem happens when the kernel performs syncing, is it possible that there is a problem with how the syncing is performed?
I am not familiar with this driver, but it seems to allocate multiple buffers per packet when split header is enabled and these buffers are allocated from the same page pool (see stmmac_init_rx_buffers()). Despite that, the driver is creating the page pool with a non-zero offset (see __alloc_dma_rx_desc_resources()) to avoid syncing the headroom, which is only present in the head buffer.
I asked Thierry to test the following patch [1] and initial testing seems OK. He also confirmed that "SPH feature enabled" shows up in the kernel log.
BTW, the commit that added split header support (67afd6d1cfdf0) says that it "reduces CPU usage because without the feature all the entire packet is memcpy'ed, while that with the feature only the header is". This is no longer correct after your patch, so is there still value in the split header feature? With two large buffers being allocated from the same page pool for each packet (headers + data), the end result is an inflated skb->truesize, no?
[1]
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +2 -2
@@ -2091,8 +2091,8 @@ static int __alloc_dma_rx_desc_resources(struct stmmac_priv *priv, pp_params.nid =dev_to_node (priv->device); pp_params.dev = priv->device; pp_params.dma_dir = xdp_prog ?DMA_BIDIRECTIONAL :DMA_FROM_DEVICE ; - pp_params.offset =stmmac_rx_offset (priv); - pp_params.max_len = dma_conf->dma_buf_sz; + pp_params.offset =0 ; + pp_params.max_len = num_pages *PAGE_SIZE ; rx_q->page_pool =page_pool_create (&pp_params);if (IS_ERR (rx_q->page_pool)) {
Re: [PATCH net-next v3 1/4] net: stmmac: Switch to zero-copy in non-XDP RX path
Hi Ido
Quoted 28 lines · Ido Schimmel
Quoted 8 lines · Furong Xu
Quoted 6 lines · Andrew Lunn
Quoted 5 lines
Just to clarify, the patch that you had us try was not intended as an actual fix, correct? It was only for diagnostic purposes, i.e. to see if there is some kind of cache coherence issue, which seems to be the case? So perhaps the only fix needed is to add dma-coherent to our device tree?
Quoted 8 lines
Quoted 5 lines
That sounds quite error prone. How many other DT blobs are missing the property? If the memory should be coherent, i would expect the driver to allocate coherent memory. Or the driver needs to handle non-coherent memory and add the necessary flush/invalidates etc.
stmmac driver does the necessary cache flush/invalidates to maintain cache lines explicitly.
Given the problem happens when the kernel performs syncing, is it possible that there is a problem with how the syncing is performed?
I am not familiar with this driver, but it seems to allocate multiple buffers per packet when split header is enabled and these buffers are allocated from the same page pool (see
stmmac_init_rx_buffers()). Despite that, the driver is creating the page pool with a non-zero offset (see__alloc_dma_rx_desc_resources()) to avoid syncing the headroom, which is only present in the head buffer.
Quoted 8 lines
I asked Thierry to test the following patch [1] and initial testing seems OK. He also confirmed that "SPH feature enabled" shows up in the kernel log.
BTW, the commit that added split header support (67afd6d1cfdf0) says that it "reduces CPU usage because without the feature all the entire packet is memcpy'ed, while that with the feature only the header is". This is no longer correct after your patch, so is there still value in the split header feature? With two large buffers being allocated from
Thanks for these great insights!
Yes, when "SPH feature enabled", it is not correct after my patch, pp_params.offset should be updated to match the offset of split payload.
But I would like to let pp_params.max_len remains to dma_conf->dma_buf_sz since the sizes of both header and payload are limited to dma_conf->dma_buf_sz by DMA engine, no more than dma_conf->dma_buf_sz bytes will be written into a page buffer. So my patch would be like [2]:
BTW, the split header feature will be very useful on some certain cases, stmmac driver should support this feature always.
[2]
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +1 -1
@@ -2091,7 +2091,7 @@ static int __alloc_dma_rx_desc_resources(struct stmmac_priv *priv, pp_params.nid =dev_to_node (priv->device); pp_params.dev = priv->device; pp_params.dma_dir = xdp_prog ?DMA_BIDIRECTIONAL :DMA_FROM_DEVICE ; - pp_params.offset =stmmac_rx_offset (priv); + pp_params.offset = priv->sph ?0 :stmmac_rx_offset (priv); pp_params.max_len = dma_conf->dma_buf_sz; rx_q->page_pool =page_pool_create (&pp_params);
Re: [PATCH net-next v3 1/4] net: stmmac: Switch to zero-copy in non-XDP RX path
Hi,
Quoted 61 lines · Furong Xu
Hi Ido
Quoted 28 lines · Ido Schimmel
Quoted 8 lines · Furong Xu
Quoted 6 lines · Andrew Lunn
Quoted 5 lines
Just to clarify, the patch that you had us try was not intended as an actual fix, correct? It was only for diagnostic purposes, i.e. to see if there is some kind of cache coherence issue, which seems to be the case? So perhaps the only fix needed is to add dma-coherent to our device tree?
Quoted 8 lines
Quoted 5 lines
That sounds quite error prone. How many other DT blobs are missing the property? If the memory should be coherent, i would expect the driver to allocate coherent memory. Or the driver needs to handle non-coherent memory and add the necessary flush/invalidates etc.
stmmac driver does the necessary cache flush/invalidates to maintain cache lines explicitly.
Given the problem happens when the kernel performs syncing, is it possible that there is a problem with how the syncing is performed?
I am not familiar with this driver, but it seems to allocate multiple buffers per packet when split header is enabled and these buffers are allocated from the same page pool (see
stmmac_init_rx_buffers()). Despite that, the driver is creating the page pool with a non-zero offset (see__alloc_dma_rx_desc_resources()) to avoid syncing the headroom, which is only present in the head buffer.Quoted 8 lines
I asked Thierry to test the following patch [1] and initial testing seems OK. He also confirmed that "SPH feature enabled" shows up in the kernel log.
BTW, the commit that added split header support (67afd6d1cfdf0) says that it "reduces CPU usage because without the feature all the entire packet is memcpy'ed, while that with the feature only the header is". This is no longer correct after your patch, so is there still value in the split header feature? With two large buffers being allocated fromThanks for these great insights!
Yes, when "SPH feature enabled", it is not correct after my patch, pp_params.offset should be updated to match the offset of split payload.
But I would like to let pp_params.max_len remains to
dma_conf->dma_buf_szsince the sizes of both header and payload are limited todma_conf->dma_buf_szby DMA engine, no more thandma_conf->dma_buf_szbytes will be written into a page buffer. So my patch would be like [2]:BTW, the split header feature will be very useful on some certain cases, stmmac driver should support this feature always.
[2]
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +0
-0
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c static int __alloc_dma_rx_desc_resources(struct stmmac_priv *priv, · line 2094
Quoted 5 lines
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +1
-1@@ -2091,7 +2091,7 @@ static int __alloc_dma_rx_desc_resources(struct stmmac_priv *priv, pp_params.nid =dev_to_node (priv->device); pp_params.dev = priv->device; pp_params.dma_dir = xdp_prog ?DMA_BIDIRECTIONAL :DMA_FROM_DEVICE ; - pp_params.offset =stmmac_rx_offset (priv); + pp_params.offset = priv->sph ?0 :stmmac_rx_offset (priv);
SPH is the only scenario in which the driver uses multiple buffers per packet?
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c static int __alloc_dma_rx_desc_resources(struct stmmac_priv *priv, · line 2095
Quoted 1 line
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +0
-0pp_params.max_len = dma_conf->dma_buf_sz;
Are you sure this is correct? Page pool documentation says that "For pages recycled on the XDP xmit and skb paths the page pool will use the max_len member of struct page_pool_params to decide how much of the page needs to be synced (starting at offset)" [1].
While "no more than dma_conf->dma_buf_sz bytes will be written into a page buffer", for the head buffer they will be written starting at a non-zero offset unlike buffers used for the data, no?
[1] https://docs.kernel.org/networking/page_pool.html#dma-sync
Re: [PATCH net-next v3 1/4] net: stmmac: Switch to zero-copy in non-XDP RX path
Quoted 2 lines · Ido Schimmel
SPH is the only scenario in which the driver uses multiple buffers per packet?
Yes.
Jumbo mode may use multiple buffers per packet too, but they are high order pages, just like a single page in a page pool when using a standard MTU.
Quoted 6 lines
Quoted 1 line
pp_params.max_len = dma_conf->dma_buf_sz;Are you sure this is correct? Page pool documentation says that "For pages recycled on the XDP xmit and skb paths the page pool will use the
max_lenmember of structpage_pool_paramsto decide how much of the page needs to be synced (starting at offset)" [1].
Page pool must sync an area of the buffer because both DMA and CPU may touch this area, other areas are CPU exclusive, so no sync for them seems better.
Quoted 3 lines
While "no more than
dma_conf->dma_buf_szbytes will be written into a page buffer", for the head buffer they will be written starting at a non-zero offset unlike buffers used for the data, no?
Correct, they have different offsets.
The "SPH feature" splits header into buf->page (non-zero offset) and splits payload into buf->sec_page (zero offset).
For buf->page, pp_params.max_len should be the size of L3/L4 header, and with a offset of NET_SKB_PAD.
For buf->sec_page, pp_params.max_len should be dma_conf->dma_buf_sz, and with a offset of 0.
This is always true:
sizeof(L3/L4 header) + NET_SKB_PAD < dma_conf->dma_buf_sz + 0
pp_params.max_len = dma_conf->dma_buf_sz;
make things simpler :)
Re: [PATCH net-next v3 1/4] net: stmmac: Switch to zero-copy in non-XDP RX path
Quoted 11 lines · Furong Xu
The "SPH feature" splits header into
buf->page(non-zero offset) and splits payload intobuf->sec_page(zero offset).For
buf->page, pp_params.max_len should be the size of L3/L4 header, and with a offset ofNET_SKB_PAD.For
buf->sec_page, pp_params.max_len should bedma_conf->dma_buf_sz, and with a offset of 0.This is always true:
sizeof(L3/L4 header) +NET_SKB_PAD<dma_conf->dma_buf_sz+ 0
Thanks, understood, but are there situations where the device is unable to split a packet? For example, a large L2 packet. I am trying to understand if there are situations where the device will write more than "dma_conf->dma_buf_sz - NET_SKB_PAD" to the head buffer.
Re: [PATCH net-next v3 1/4] net: stmmac: Switch to zero-copy in non-XDP RX path
Quoted 10 lines · Ido Schimmel
Quoted 9 lines · Furong Xu
The "SPH feature" splits header into
buf->page(non-zero offset) and splits payload intobuf->sec_page(zero offset).For
buf->page, pp_params.max_len should be the size of L3/L4 header, and with a offset ofNET_SKB_PAD.For
buf->sec_page, pp_params.max_len should bedma_conf->dma_buf_sz, and with a offset of 0.
Quoted 7 lines
Quoted 2 lines
This is always true:
sizeof(L3/L4 header) +NET_SKB_PAD<dma_conf->dma_buf_sz+ 0Thanks, understood, but are there situations where the device is unable to split a packet? For example, a large L2 packet. I am trying to understand if there are situations where the device will write more than "
dma_conf->dma_buf_sz-NET_SKB_PAD" to the head buffer.
Nice catch!
When receiving a large L2/non-IP packet, more than "dma_conf->dma_buf_sz
- NET_SKB_PAD" will be written.
So we should:
pp_params.max_len = dma_conf->dma_buf_sz + stmmac_rx_offset(priv);
Thanks a lot, Ido
Have a nice weekend :)
Re: [PATCH net-next v3 1/4] net: stmmac: Switch to zero-copy in non-XDP RX path
In reply to Ido SchimmelHi Thierry
Quoted 28 lines · Ido Schimmel
Quoted 8 lines · Furong Xu
Quoted 6 lines · Andrew Lunn
Quoted 5 lines
Just to clarify, the patch that you had us try was not intended as an actual fix, correct? It was only for diagnostic purposes, i.e. to see if there is some kind of cache coherence issue, which seems to be the case? So perhaps the only fix needed is to add dma-coherent to our device tree?
Quoted 8 lines
Quoted 5 lines
That sounds quite error prone. How many other DT blobs are missing the property? If the memory should be coherent, i would expect the driver to allocate coherent memory. Or the driver needs to handle non-coherent memory and add the necessary flush/invalidates etc.
stmmac driver does the necessary cache flush/invalidates to maintain cache lines explicitly.
Given the problem happens when the kernel performs syncing, is it possible that there is a problem with how the syncing is performed?
I am not familiar with this driver, but it seems to allocate multiple buffers per packet when split header is enabled and these buffers are allocated from the same page pool (see
stmmac_init_rx_buffers()). Despite that, the driver is creating the page pool with a non-zero offset (see__alloc_dma_rx_desc_resources()) to avoid syncing the headroom, which is only present in the head buffer.
Quoted 3 lines
I asked Thierry to test the following patch [1] and initial testing seems OK. He also confirmed that "SPH feature enabled" shows up in the kernel log.
It is recommended to disable the "SPH feature" by default unless some certain cases depend on it. Like Ido said, two large buffers being allocated from the same page pool for each packet, this is a huge waste of memory, and brings performance drops for most of general cases.
Our downstream driver and two mainline drivers disable SPH by default:
https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git/tree/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c#n357
https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git/tree/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c#n471
Re: [PATCH net-next v3 1/4] net: stmmac: Switch to zero-copy in non-XDP RX path
Quoted 4 lines
It is recommended to disable the "SPH feature" by default unless some certain cases depend on it. Like Ido said, two large buffers being allocated from the same page pool for each packet, this is a huge waste of memory, and brings performance drops for most of general cases.
I don't know this driver, but it looks like SPH is required for NETIF_F_GRO? Can you add this flag to hw_features, but not wanted_features and leave SPH disabled until ethtool is used to enable GRO?
Are there other use cases where SPH is needed?
Andrew
Re: [PATCH net-next v3 1/4] net: stmmac: Switch to zero-copy in non-XDP RX path
Quoted 10 lines · Andrew Lunn
Quoted 5 lines
It is recommended to disable the "SPH feature" by default unless some certain cases depend on it. Like Ido said, two large buffers being allocated from the same page pool for each packet, this is a huge waste of memory, and brings performance drops for most of general cases.
I don't know this driver, but it looks like SPH is required for
NETIF_F_GRO? Can you add this flag tohw_features, but notwanted_featuresand leave SPH disabled until ethtool is used to enable GRO?
SPH has its own ethtool command, stmmac driver does not implement yet. see:
https://patchwork.kernel.org/project/netdevbpf/cover/[email protected]/
Quoted 1 line
Are there other use cases where SPH is needed?
https://patchwork.kernel.org/project/netdevbpf/cover/[email protected]/
https://patchwork.kernel.org/project/netdevbpf/cover/[email protected]/
The stmmac driver does not support both of them, but it will someday :)
Re: [PATCH net-next v3 1/4] net: stmmac: Switch to zero-copy in non-XDP RX path
In reply to Furong XuQuoted 36 lines · Furong Xu
Hi Thierry
Quoted 28 lines · Ido Schimmel
Quoted 8 lines · Furong Xu
Quoted 6 lines · Andrew Lunn
Quoted 5 lines
Just to clarify, the patch that you had us try was not intended as an actual fix, correct? It was only for diagnostic purposes, i.e. to see if there is some kind of cache coherence issue, which seems to be the case? So perhaps the only fix needed is to add dma-coherent to our device tree?
Quoted 8 lines
Quoted 5 lines
That sounds quite error prone. How many other DT blobs are missing the property? If the memory should be coherent, i would expect the driver to allocate coherent memory. Or the driver needs to handle non-coherent memory and add the necessary flush/invalidates etc.
stmmac driver does the necessary cache flush/invalidates to maintain cache lines explicitly.
Given the problem happens when the kernel performs syncing, is it possible that there is a problem with how the syncing is performed?
I am not familiar with this driver, but it seems to allocate multiple buffers per packet when split header is enabled and these buffers are allocated from the same page pool (see
stmmac_init_rx_buffers()). Despite that, the driver is creating the page pool with a non-zero offset (see__alloc_dma_rx_desc_resources()) to avoid syncing the headroom, which is only present in the head buffer.Quoted 3 lines
I asked Thierry to test the following patch [1] and initial testing seems OK. He also confirmed that "SPH feature enabled" shows up in the kernel log.
Quoted 8 lines
It is recommended to disable the "SPH feature" by default unless some certain cases depend on it. Like Ido said, two large buffers being allocated from the same page pool for each packet, this is a huge waste of memory, and brings performance drops for most of general cases.
Our downstream driver and two mainline drivers disable SPH by default:
https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git/tree/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c#n357
https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git/tree/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c#n471
Okay, that's something we can look into changing. What would be an example of a use-case depending on SPH? Also, isn't this something that should be a policy that users can configure?
Irrespective of that we should fix the problems we are seeing with SPH enabled.
Thierry
Jon Hunter
maintainerRe: [PATCH net-next v3 1/4] net: stmmac: Switch to zero-copy in non-XDP RX path
Hi Furong,
Quoted 46 lines · Thierry Reding
Quoted 36 lines · Furong Xu
Hi Thierry
Quoted 28 lines · Ido Schimmel
Quoted 8 lines · Furong Xu
Quoted 6 lines · Andrew Lunn
Quoted 5 lines
Just to clarify, the patch that you had us try was not intended as an actual fix, correct? It was only for diagnostic purposes, i.e. to see if there is some kind of cache coherence issue, which seems to be the case? So perhaps the only fix needed is to add dma-coherent to our device tree?
Quoted 8 lines
Quoted 5 lines
That sounds quite error prone. How many other DT blobs are missing the property? If the memory should be coherent, i would expect the driver to allocate coherent memory. Or the driver needs to handle non-coherent memory and add the necessary flush/invalidates etc.
stmmac driver does the necessary cache flush/invalidates to maintain cache lines explicitly.
Given the problem happens when the kernel performs syncing, is it possible that there is a problem with how the syncing is performed?
I am not familiar with this driver, but it seems to allocate multiple buffers per packet when split header is enabled and these buffers are allocated from the same page pool (see
stmmac_init_rx_buffers()). Despite that, the driver is creating the page pool with a non-zero offset (see__alloc_dma_rx_desc_resources()) to avoid syncing the headroom, which is only present in the head buffer.Quoted 3 lines
I asked Thierry to test the following patch [1] and initial testing seems OK. He also confirmed that "SPH feature enabled" shows up in the kernel log.
Quoted 8 lines
It is recommended to disable the "SPH feature" by default unless some certain cases depend on it. Like Ido said, two large buffers being allocated from the same page pool for each packet, this is a huge waste of memory, and brings performance drops for most of general cases.
Our downstream driver and two mainline drivers disable SPH by default:
https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git/tree/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c#n357
https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git/tree/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c#n471
Quoted 6 lines
Okay, that's something we can look into changing. What would be an example of a use-case depending on SPH? Also, isn't this something that should be a policy that users can configure?
Irrespective of that we should fix the problems we are seeing with SPH enabled.
Any update on this?
Thanks
Jon
Signature · 1 line
nvpublic
Re: [PATCH net-next v3 1/4] net: stmmac: Switch to zero-copy in non-XDP RX path
Hi Jon,
Quoted 53 lines · Jon Hunter
Hi Furong,
Quoted 50 lines · Thierry Reding
Quoted 36 lines · Furong Xu
Hi Thierry
Quoted 28 lines · Ido Schimmel
Quoted 8 lines · Furong Xu
Quoted 6 lines · Andrew Lunn
Quoted 5 lines
Just to clarify, the patch that you had us try was not intended as an actual fix, correct? It was only for diagnostic purposes, i.e. to see if there is some kind of cache coherence issue, which seems to be the case? So perhaps the only fix needed is to add dma-coherent to our device tree?
Quoted 8 lines
Quoted 5 lines
That sounds quite error prone. How many other DT blobs are missing the property? If the memory should be coherent, i would expect the driver to allocate coherent memory. Or the driver needs to handle non-coherent memory and add the necessary flush/invalidates etc.
stmmac driver does the necessary cache flush/invalidates to maintain cache lines explicitly.
Given the problem happens when the kernel performs syncing, is it possible that there is a problem with how the syncing is performed?
I am not familiar with this driver, but it seems to allocate multiple buffers per packet when split header is enabled and these buffers are allocated from the same page pool (see
stmmac_init_rx_buffers()). Despite that, the driver is creating the page pool with a non-zero offset (see__alloc_dma_rx_desc_resources()) to avoid syncing the headroom, which is only present in the head buffer.Quoted 3 lines
I asked Thierry to test the following patch [1] and initial testing seems OK. He also confirmed that "SPH feature enabled" shows up in the kernel log.
Quoted 8 lines
It is recommended to disable the "SPH feature" by default unless some certain cases depend on it. Like Ido said, two large buffers being allocated from the same page pool for each packet, this is a huge waste of memory, and brings performance drops for most of general cases.
Our downstream driver and two mainline drivers disable SPH by default:
https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git/tree/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c#n357
https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git/tree/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c#n471Okay, that's something we can look into changing. What would be an example of a use-case depending on SPH? Also, isn't this something that should be a policy that users can configure?
Quoted 5 lines
Quoted 2 lines
Irrespective of that we should fix the problems we are seeing with SPH enabled.
Any update on this?
Sorry for my late response, I was on Chinese New Year holiday.
The fix is sent, and it will be so nice to have your Tested-by: tag there:
https://lore.kernel.org/all/[email protected]/
Jon Hunter
maintainerRe: [PATCH net-next v3 1/4] net: stmmac: Switch to zero-copy in non-XDP RX path
Quoted 56 lines · Furong Xu
Hi Jon,
Quoted 53 lines · Jon Hunter
Hi Furong,
Quoted 50 lines · Thierry Reding
Quoted 36 lines · Furong Xu
Hi Thierry
Quoted 28 lines · Ido Schimmel
Quoted 8 lines · Furong Xu
Quoted 6 lines · Andrew Lunn
Quoted 5 lines
Just to clarify, the patch that you had us try was not intended as an actual fix, correct? It was only for diagnostic purposes, i.e. to see if there is some kind of cache coherence issue, which seems to be the case? So perhaps the only fix needed is to add dma-coherent to our device tree?
Quoted 8 lines
Quoted 5 lines
That sounds quite error prone. How many other DT blobs are missing the property? If the memory should be coherent, i would expect the driver to allocate coherent memory. Or the driver needs to handle non-coherent memory and add the necessary flush/invalidates etc.
stmmac driver does the necessary cache flush/invalidates to maintain cache lines explicitly.
Given the problem happens when the kernel performs syncing, is it possible that there is a problem with how the syncing is performed?
I am not familiar with this driver, but it seems to allocate multiple buffers per packet when split header is enabled and these buffers are allocated from the same page pool (see
stmmac_init_rx_buffers()). Despite that, the driver is creating the page pool with a non-zero offset (see__alloc_dma_rx_desc_resources()) to avoid syncing the headroom, which is only present in the head buffer.Quoted 3 lines
I asked Thierry to test the following patch [1] and initial testing seems OK. He also confirmed that "SPH feature enabled" shows up in the kernel log.
Quoted 8 lines
It is recommended to disable the "SPH feature" by default unless some certain cases depend on it. Like Ido said, two large buffers being allocated from the same page pool for each packet, this is a huge waste of memory, and brings performance drops for most of general cases.
Our downstream driver and two mainline drivers disable SPH by default:
https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git/tree/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c#n357
https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git/tree/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c#n471Okay, that's something we can look into changing. What would be an example of a use-case depending on SPH? Also, isn't this something that should be a policy that users can configure?
Quoted 7 lines
Quoted 5 lines
Quoted 2 lines
Irrespective of that we should fix the problems we are seeing with SPH enabled.
Any update on this?
Sorry for my late response, I was on Chinese New Year holiday.
No problem! Happy new year!
Quoted 2 lines
The fix is sent, and it will be so nice to have your Tested-by: tag there:
https://lore.kernel.org/all/[email protected]/
Thanks, I have tested and responded. All looking good!
Jon
Signature · 1 line
nvpublic
Re: [PATCH net-next v3 1/4] net: stmmac: Switch to zero-copy in non-XDP RX path
In reply to Brad GriffisQuoted 24 lines · Brad Griffis
Quoted 1 line · Furong Xu
What is the MTU of Tegra234 and NFS server? Are they both 1500?
I see the same issue. Yes, both are 1500.
Quoted 2 lines
Could you please try attached patch to confirm if this regression is fixed?
Patch fixes the issue.
Quoted 6 lines
If the attached patch fixes this regression, and so it seems to be a cache coherence issue specific to Tegra234, since this patch avoid memcpy and the page buffers may be modified by upper network stack of course, then cache lines of page buffers may become dirty. But by reverting this patch, cache lines of page buffers never become dirty, this is the core difference.
Thanks for these insights. I don't have specific experience in this driver, but I see we have dma-coherent turned on for this driver in our downstream device tree files (i.e. dtbs that coincide with our out-of-tree implementation of this driver). I went back to the original code and verified that the issue was there. I did a new test where I added dma-coherent to this ethernet node in the dtb and retested. It worked!
Quoted 3 lines
Just to clarify, the patch that you had us try was not intended as an actual fix, correct? It was only for diagnostic purposes, i.e. to see if there is some kind of cache coherence issue, which seems to be the case?
It is not an actual fix, it is only for diagnostic purposes.
Quoted 1 line
So perhaps the only fix needed is to add dma-coherent to our device tree?
Yes, add dma-coherent to ethernet node is the correct fix.
Re: [PATCH net-next v3 1/4] net: stmmac: Switch to zero-copy in non-XDP RX path
Quoted 5 lines
It is not an actual fix, it is only for diagnostic purposes.
Quoted 1 line
So perhaps the only fix needed is to add dma-coherent to our device tree?
Yes, add dma-coherent to ethernet node is the correct fix.
What do you think about the comment i made?
Andrew
PATCH v3 2/4 net: stmmac: Set page_pool_params.max_len to a precise size
In reply to Furong XuDMA engine will always write no more than dma_buf_sz bytes of a received frame into a page buffer, the remaining spaces are unused or used by CPU exclusively.
Setting page_pool_params.max_len to almost the full size of page(s) helps nothing more, but wastes more CPU cycles on cache maintenance.
For a standard MTU of 1500, then dma_buf_sz is assigned to 1536, and this patch brings ~16.9% driver performance improvement in a TCP RX throughput test with iPerf tool on a single isolated Cortex-A65 CPU core, from 2.43 Gbits/sec increased to 2.84 Gbits/sec.
--- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 2 +- drivers/net/ethernet/stmicro/stmmac/stmmac_xdp.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-)
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +1 -1
@@ -2059,7 +2059,7 @@ static int __alloc_dma_rx_desc_resources(struct stmmac_priv *priv, pp_params.dev = priv->device; pp_params.dma_dir = xdp_prog ?DMA_BIDIRECTIONAL :DMA_FROM_DEVICE ; pp_params.offset =stmmac_rx_offset (priv); - pp_params.max_len =STMMAC_MAX_RX_BUF_SIZE (num_pages); + pp_params.max_len = dma_conf->dma_buf_sz; rx_q->page_pool =page_pool_create (&pp_params);if (IS_ERR (rx_q->page_pool)) {
drivers/net/ethernet/stmicro/stmmac/stmmac_xdp.h +0 -1
@@ -4,7 +4,6 @@#ifndef _STMMAC_XDP_H_#define _STMMAC_XDP_H_ -#define STMMAC_MAX_RX_BUF_SIZE (num) (((num) * PAGE_SIZE) - XDP_PACKET_HEADROOM)#define STMMAC_RX_DMA_ATTR (DMA_ATTR_SKIP_CPU_SYNC | DMA_ATTR_WEAK_ORDERING) int stmmac_xdp_setup_pool(struct stmmac_priv *priv, struct xsk_buff_pool *pool,
Signature · 1 line
2.34.1
Re: [PATCH net-next v3 2/4] net: stmmac: Set page_pool_params.max_len to a precise size
Quoted 6 lines · Furong Xu
DMA engine will always write no more than
dma_buf_szbytes of a received frame into a page buffer, the remaining spaces are unused or used by CPU exclusively.
Setting page_pool_params.max_len to almost the full size of page(s) helps nothing more, but wastes more CPU cycles on cache maintenance.
Quoted 7 lines
For a standard MTU of 1500, then
dma_buf_szis assigned to 1536, and this patch brings ~16.9% driver performance improvement in a TCP RX throughput test with iPerf tool on a single isolated Cortex-A65 CPU core, from 2.43 Gbits/sec increased to 2.84 Gbits/sec.Signed-off-by Furong Xu <[email protected]>Reviewed-by Alexander Lobakin <[email protected]>
Thanks,
Yanteng
Quoted 4 lines
--- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 2 +- drivers/net/ethernet/stmicro/stmmac/stmmac_xdp.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-)
PATCH v3 3/4 net: stmmac: Optimize cache prefetch in RX path
In reply to Furong XuCurrent code prefetches cache lines for the received frame first, and then dma_sync_single_for_cpu() against this frame, this is wrong. Cache prefetch should be triggered after dma_sync_single_for_cpu().
This patch brings ~2.8% driver performance improvement in a TCP RX throughput test with iPerf tool on a single isolated Cortex-A65 CPU core, 2.84 Gbits/sec increased to 2.92 Gbits/sec.
--- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +1 -4
@@ -5508,10 +5508,6 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)/* Buffer is good. Go on. */ -prefetch (page_address (buf->page) + buf->page_offset); -if (buf->sec_page) -prefetch (page_address (buf->sec_page)); - buf1_len =stmmac_rx_buf1_len (priv, p, status, len); len += buf1_len; buf2_len =stmmac_rx_buf2_len (priv, p, status, len);
@@ -5533,6 +5529,7 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)dma_sync_single_for_cpu (priv->device, buf->addr, buf1_len, dma_dir); +prefetch (page_address (buf->page) + buf->page_offset);xdp_init_buff (&ctx.xdp, buf_sz, &rx_q->xdp_rxq); xdp_prepare_buff(&ctx.xdp, page_address(buf->page),
Signature · 1 line
2.34.1
Re: [PATCH net-next v3 3/4] net: stmmac: Optimize cache prefetch in RX path
Quoted 10 lines · Furong Xu
Current code prefetches cache lines for the received frame first, and then
dma_sync_single_for_cpu()against this frame, this is wrong. Cache prefetch should be triggered afterdma_sync_single_for_cpu().This patch brings ~2.8% driver performance improvement in a TCP RX throughput test with iPerf tool on a single isolated Cortex-A65 CPU core, 2.84 Gbits/sec increased to 2.92 Gbits/sec.
Signed-off-by Furong Xu <[email protected]>Reviewed-by Alexander Lobakin <[email protected]>
Thanks,
Yanteng
Quoted 27 lines
--- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +1
-4@@ -5508,10 +5508,6 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)/* Buffer is good. Go on. */ -prefetch (page_address (buf->page) + buf->page_offset); -if (buf->sec_page) -prefetch (page_address (buf->sec_page)); - buf1_len =stmmac_rx_buf1_len (priv, p, status, len); len += buf1_len; buf2_len =stmmac_rx_buf2_len (priv, p, status, len);@@ -5533,6 +5529,7 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)dma_sync_single_for_cpu (priv->device, buf->addr, buf1_len, dma_dir); +prefetch (page_address (buf->page) + buf->page_offset);xdp_init_buff (&ctx.xdp, buf_sz, &rx_q->xdp_rxq); xdp_prepare_buff(&ctx.xdp, page_address(buf->page),
PATCH v3 4/4 net: stmmac: Convert prefetch() to net_prefetch() for received frames
In reply to Furong XuThe size of DMA descriptors is 32 bytes at most. net_prefetch() for received frames, and keep prefetch() for descriptors.
This patch brings ~4.8% driver performance improvement in a TCP RX throughput test with iPerf tool on a single isolated Cortex-A65 CPU core, 2.92 Gbits/sec increased to 3.06 Gbits/sec.
--- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +2 -1
@@ -5529,7 +5529,8 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)dma_sync_single_for_cpu (priv->device, buf->addr, buf1_len, dma_dir); -prefetch (page_address (buf->page) + buf->page_offset); +net_prefetch (page_address (buf->page) + + buf->page_offset);xdp_init_buff (&ctx.xdp, buf_sz, &rx_q->xdp_rxq); xdp_prepare_buff(&ctx.xdp, page_address(buf->page),
Signature · 1 line
2.34.1
Re: [PATCH net-next v3 4/4] net: stmmac: Convert prefetch() to net_prefetch() for received frames
Quoted 9 lines · Furong Xu
The size of DMA descriptors is 32 bytes at most.
net_prefetch()for received frames, and keepprefetch()for descriptors.This patch brings ~4.8% driver performance improvement in a TCP RX throughput test with iPerf tool on a single isolated Cortex-A65 CPU core, 2.92 Gbits/sec increased to 3.06 Gbits/sec.
Suggested-by Joe Damato <[email protected]>Signed-off-by Furong Xu <[email protected]>
Thanks,
Yanteng
Quoted 18 lines
--- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +2
-1@@ -5529,7 +5529,8 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)dma_sync_single_for_cpu (priv->device, buf->addr, buf1_len, dma_dir); -prefetch (page_address (buf->page) + buf->page_offset); +net_prefetch (page_address (buf->page) + + buf->page_offset);xdp_init_buff (&ctx.xdp, buf_sz, &rx_q->xdp_rxq); xdp_prepare_buff(&ctx.xdp, page_address(buf->page),
Re: [PATCH net-next v3 4/4] net: stmmac: Convert prefetch() to net_prefetch() for received frames
In reply to Furong XuQuoted 9 lines · Furong Xu
The size of DMA descriptors is 32 bytes at most.
net_prefetch()for received frames, and keepprefetch()for descriptors.This patch brings ~4.8% driver performance improvement in a TCP RX throughput test with iPerf tool on a single isolated Cortex-A65 CPU core, 2.92 Gbits/sec increased to 3.06 Gbits/sec.
Suggested-by Joe Damato <[email protected]>Signed-off-by Furong Xu <[email protected]>
Quoted 22 lines
--- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +2
-1@@ -5529,7 +5529,8 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)dma_sync_single_for_cpu (priv->device, buf->addr, buf1_len, dma_dir); -prefetch (page_address (buf->page) + buf->page_offset); +net_prefetch (page_address (buf->page) + + buf->page_offset);xdp_init_buff (&ctx.xdp, buf_sz, &rx_q->xdp_rxq); xdp_prepare_buff(&ctx.xdp, page_address(buf->page),Signature · 1 line
2.34.1
Re: [PATCH net-next v3 4/4] net: stmmac: Convert prefetch() to net_prefetch() for received frames
In reply to Furong XuQuoted 7 lines · Furong Xu
The size of DMA descriptors is 32 bytes at most.
net_prefetch()for received frames, and keepprefetch()for descriptors.This patch brings ~4.8% driver performance improvement in a TCP RX throughput test with iPerf tool on a single isolated Cortex-A65 CPU core, 2.92 Gbits/sec increased to 3.06 Gbits/sec.
Quoted 5 lines
Suggested-by Joe Damato <[email protected]>Signed-off-by Furong Xu <[email protected]>--- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
This series was applied to netdev/net-next.git (main) by Paolo Abeni <[email protected]>:
Hello:
This series was applied to netdev/net-next.git (main) by Paolo Abeni <[email protected]>:
Quoted 9 lines · On Wed, 15 Jan 2025 11:27:01 +0800 you wrote:
This series improves RX performance a lot, ~40% TCP RX throughput boost has been observed with DWXGMAC CORE 3.20a running on Cortex-A65 CPUs:
from 2.18 Gbits/sec increased to 3.06 Gbits/sec.---
Changes in v3:
1. Convertprefetch()tonet_prefetch()to get better performance (Joe Damato)[...]
Here is the summary with links:
- [net-next,v3,1/4] net: stmmac: Switch to zero-copy in non-XDP RX path
https://git.kernel.org/netdev/net-next/c/df542f669307 - [net-next,v3,2/4] net: stmmac: Set page_pool_params.max_len to a precise size https://git.kernel.org/netdev/net-next/c/2324c78a75c5 - [net-next,v3,3/4] net: stmmac: Optimize cache prefetch in RX path https://git.kernel.org/netdev/net-next/c/2a2931517c9a - [net-next,v3,4/4] net: stmmac: Convert prefetch() to net_prefetch() for received frames https://git.kernel.org/netdev/net-next/c/204182edb310
You are awesome, thank you!
Signature · 2 lines
Deet-doot-dot, I am a bot. https://korg.docs.kernel.org/patchwork/pwbot.html