| From 69cf32f63b80b5e74681799a05e7ed0e00d274bf Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Mon, 9 Feb 2026 17:50:32 -0500 |
| Subject: net: stmmac: fix oops when split header is enabled |
| |
| From: Jie Zhang <jzhang918@gmail.com> |
| |
| [ Upstream commit babab1b42ed68877ef669a08384becf281ad2582 ] |
| |
| For GMAC4, when split header is enabled, in some rare cases, the |
| hardware does not fill buf2 of the first descriptor with payload. |
| Thus we cannot assume buf2 is always fully filled if it is not |
| the last descriptor. Otherwise, the length of buf2 of the second |
| descriptor will be calculated wrong and cause an oops: |
| |
| Unable to handle kernel paging request at virtual address ffff00019246bfc0 |
| ... |
| x2 : 0000000000000040 x1 : ffff00019246bfc0 x0 : ffff00009246c000 |
| Call trace: |
| dcache_inval_poc+0x28/0x58 (P) |
| dma_direct_sync_single_for_cpu+0x38/0x6c |
| __dma_sync_single_for_cpu+0x34/0x6c |
| stmmac_napi_poll_rx+0x8f0/0xb60 |
| __napi_poll.constprop.0+0x30/0x144 |
| net_rx_action+0x160/0x274 |
| handle_softirqs+0x1b8/0x1fc |
| ... |
| |
| To fix this, the PL bit-field in RDES3 register is used for all |
| descriptors, whether it is the last descriptor or not. |
| |
| Fixes: ec222003bd94 ("net: stmmac: Prepare to add Split Header support") |
| Reviewed-by: Jacob Keller <jacob.e.keller@intel.com> |
| Signed-off-by: Jie Zhang <jie.zhang@analog.com> |
| Link: https://patch.msgid.link/20260209225037.589130-1-jie.zhang@analog.com |
| Signed-off-by: Jakub Kicinski <kuba@kernel.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| .../net/ethernet/stmicro/stmmac/stmmac_main.c | 20 ++++++++++++++++--- |
| 1 file changed, 17 insertions(+), 3 deletions(-) |
| |
| diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c |
| index a379221b96a34..f98fd254315f6 100644 |
| --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c |
| +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c |
| @@ -5023,13 +5023,27 @@ static unsigned int stmmac_rx_buf2_len(struct stmmac_priv *priv, |
| if (!priv->sph_active) |
| return 0; |
| |
| - /* Not last descriptor */ |
| - if (status & rx_not_ls) |
| + /* For GMAC4, when split header is enabled, in some rare cases, the |
| + * hardware does not fill buf2 of the first descriptor with payload. |
| + * Thus we cannot assume buf2 is always fully filled if it is not |
| + * the last descriptor. Otherwise, the length of buf2 of the second |
| + * descriptor will be calculated wrong and cause an oops. |
| + * |
| + * If this is the last descriptor, 'plen' is the length of the |
| + * received packet that was transferred to system memory. |
| + * Otherwise, it is the accumulated number of bytes that have been |
| + * transferred for the current packet. |
| + * |
| + * Thus 'plen - len' always gives the correct length of buf2. |
| + */ |
| + |
| + /* Not GMAC4 and not last descriptor */ |
| + if (priv->plat->core_type != DWMAC_CORE_GMAC4 && (status & rx_not_ls)) |
| return priv->dma_conf.dma_buf_sz; |
| |
| + /* GMAC4 or last descriptor */ |
| plen = stmmac_get_rx_frame_len(priv, p, coe); |
| |
| - /* Last descriptor */ |
| return plen - len; |
| } |
| |
| -- |
| 2.51.0 |
| |