diff options
| author | Serge Semin <fancer.lancer@gmail.com> | 2025-07-22 15:31:51 +0300 |
|---|---|---|
| committer | Serge Semin <fancer.lancer@gmail.com> | 2026-08-13 20:31:43 +0300 |
| commit | 7cec342ce65a02484b130e49e1903623ff6ac83a (patch) | |
| tree | 3488af756734016eca5643719f024545fef9fe99 | |
| parent | 6f83bbb0e2136423511b8ffd22e765ddf4937ce9 (diff) | |
| download | linux-7cec342ce65a02484b130e49e1903623ff6ac83a.tar.gz linux-7cec342ce65a02484b130e49e1903623ff6ac83a.zip | |
net: stmmac: dwmac1000: Fix long-broken Rx Jumbo-frames support
As soon as the Jumbo frames with MTU over 2K/4K (for the Normal
descriptors) and over 8K (for the chained Enhanced descriptors) enabled
the frames exceeding these limits won't be delivered to the networking
core and will be just discarded. This happens due to the driver not
supporting the cross-descriptors data reception (see the
stmmac_desc_ops::rx_status() callbacks handling the non-last segment
descriptors).
DW GMAC layer of the STMMAC driver currently supports the two types of the
Rx DMA-descriptors which besides the different layout differ by the
maximum buffers size:
Normal Rx descriptor: 2K (chain), 2x2K (ring)
Enhanced Rx descriptor: 8K (chain), 2x8K (ring)
Since the cross-descriptor data reception is basically disabled the ringed
Enhanced Rx-descriptors will only work for the 9K jumbo frames retrieval.
The rest of the modes will cause the over the buffer-size frames dropping.
This is definitely wrong seeing the driver unconditionally setups max 9K
MTU constraint for any DW GMAC devices. Moreover the older non-GMAC
IP-cores are supposed to work with the SKB_MAX_HEAD() MTUs which implies
up to Page-sized frames reception. In that case depending on the
system-wide page size the Jumbo frames reception won't properly work
either.
Let's fix the problem described above. In fact the driver code has already
been prepared for that by the preceding fixes and the only what left to be
done is to just return the "rx_not_ls" status from the DW GMAC-specific
stmmac_desc_ops::rx_status() callback. The STMMAC core driver will handle
the rest as is.
Fixes: 286a83721720 ("stmmac: add CHAINED descriptor mode support (V4)")
Fixes: 47dd7a540b8a ("net: add support for STMicroelectronics Ethernet controllers.")
Signed-off-by: Serge Semin <fancer.lancer@gmail.com>
---
Note the patch used to fix the stmmac_rx_buf1_len(). It must take into
account that it's possible to have two buffers initialized in the Rx
DMA-descriptors. So the very first buffer of the last segment could be not
containing the tail of the Rx frame. It's specific for the DW GMAC4/XGMAC
IP-cores supporting the split-headers and failing to split the retrieved
frame for some reason.
| -rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/enh_desc.c | 6 | ||||
| -rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/norm_desc.c | 6 |
2 files changed, 4 insertions, 8 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c index c11a06af7dbf..24ac1d2ff164 100644 --- a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c +++ b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c @@ -166,10 +166,8 @@ static int enh_desc_get_rx_basic_status(unsigned int rdes0, if (unlikely(rdes0 & RDES0_OWN)) return dma_own; - if (unlikely(!(rdes0 & RDES0_LAST_DESCRIPTOR))) { - x->rx_length++; - return discard_frame; - } + if (unlikely(!(rdes0 & RDES0_LAST_DESCRIPTOR))) + return rx_not_ls; if (unlikely(!(rdes0 & RDES0_FRAME_TYPE))) ret = llc_snap; diff --git a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c index e90184f3f136..389e07f35c6a 100644 --- a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c +++ b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c @@ -67,10 +67,8 @@ static int ndesc_get_rx_basic_status(unsigned int rdes0, if (unlikely(rdes0 & RDES0_OWN)) return dma_own; - if (unlikely(!(rdes0 & RDES0_LAST_DESCRIPTOR))) { - x->rx_length++; - return discard_frame; - } + if (unlikely(!(rdes0 & RDES0_LAST_DESCRIPTOR))) + return rx_not_ls; if (unlikely(!(rdes0 & RDES0_FRAME_TYPE))) ret = llc_snap; |
