diff options
| author | Serge Semin <fancer.lancer@gmail.com> | 2025-07-21 21:53:20 +0300 |
|---|---|---|
| committer | Serge Semin <fancer.lancer@gmail.com> | 2026-08-13 20:31:43 +0300 |
| commit | afa311d89ad518321d4b1a738f31ca6996fbc3ad (patch) | |
| tree | a6898a9e2f86808cb27981e4fe6e7321bfc22610 | |
| parent | f5e4e87c3c9c9c1de2a2cd17ce9ecc03d63b1775 (diff) | |
| download | linux-afa311d89ad518321d4b1a738f31ca6996fbc3ad.tar.gz linux-afa311d89ad518321d4b1a738f31ca6996fbc3ad.zip | |
net: stmmac: dwmac1000: Fix invalid Rx descriptor mode setup
Currently the Rx DMA-descriptors mode setup is partly broken. First of all
the ring mode works for the Enhanced descriptors only. As long as the
Normal descriptors support is detected enabling the ring descriptors mode
will cause malfunctioned over 2K frames reception. This happens due to the
ring-mode init procedure originally being developed for the 8KB buffers
specific for the Enhanced descriptors. But since the commit 286a83721720
("stmmac: add CHAINED descriptor mode support (V4)") it has been converted
to be available for both Normal and Enhanced descriptor types without
taking into account that the former descriptors type has the buffer of 2KB
size.
Secondly the commit e3ad57c96715 ("stmmac: review RX/TX ring management")
has broken the Rx-descriptors chain and extended ring pointers
re-initialization in case of IEEE 1833-2002 Timestamp-ing. The
Rx-descriptor refill procedures used to rely on the
stmmac_rx_queue::dirty_rx field state to re-init the pointers, but since
the blamed commit the field state has no longer being advanced in sync
with the descriptors cleanups. It's set only after all the pending Rx
DMA-descriptors have been cleaned up. So the intermediate descriptors will
have the chain broken, meanwhile the first dirty one will point to the
first non-dirty. This is definitely wrong.
Let's fix the problems denoted above at once since both of them concern
the same part of driver code. The solution is simple - just move the chain
and ring mode initialization procedure to the dedicated
stmmac_desc_ops::prepare_rx_desc() methods and make sure they are called
at the moments where the Rx DMA-descriptors initialization and
re-initialization is required.
Note as a side-effect of the this change another problem is fixed. The
commit bba2556efad6 ("net: stmmac: Enable RX via AF_XDP zero-copy") has
missed the chain and ring mode pointers initialization on zero-copy
Rx-buffers allocation. Now by calling the stmmac_prepare_rx_desc() method
it has that done.
Moreover as a result of the denoted conversion there is no longer need in
the stmmac_mode_ops-related infrastructure. So it has been fully dropped.
Fixes: 286a83721720 ("stmmac: add CHAINED descriptor mode support (V4)")
Fixes: e3ad57c96715 ("stmmac: review RX/TX ring management")
Fixes: bba2556efad6 ("net: stmmac: Enable RX via AF_XDP zero-copy")
Signed-off-by: Serge Semin <fancer.lancer@gmail.com>
| -rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/Makefile | 4 | ||||
| -rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/chain_mode.c | 65 | ||||
| -rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/common.h | 1 | ||||
| -rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/descs_com.h | 40 | ||||
| -rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/enh_desc.c | 12 | ||||
| -rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/hwif.c | 28 | ||||
| -rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/hwif.h | 23 | ||||
| -rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/norm_desc.c | 11 | ||||
| -rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/ring_mode.c | 35 | ||||
| -rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 85 |
10 files changed, 119 insertions, 185 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile index c9263987ef8d..9f24db4cf7a8 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Makefile +++ b/drivers/net/ethernet/stmicro/stmmac/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_STMMAC_ETH) += stmmac.o -stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o ring_mode.o \ - chain_mode.o dwmac_lib.o dwmac1000_core.o dwmac1000_dma.o \ +stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o \ + dwmac_lib.o dwmac1000_core.o dwmac1000_dma.o \ dwmac100_core.o dwmac100_dma.o enh_desc.o norm_desc.o \ mmc_core.o stmmac_hwtstamp.o stmmac_ptp.o dwmac4_descs.o \ dwmac4_dma.o dwmac4_lib.o dwmac4_core.o dwmac5.o hwif.o \ diff --git a/drivers/net/ethernet/stmicro/stmmac/chain_mode.c b/drivers/net/ethernet/stmicro/stmmac/chain_mode.c deleted file mode 100644 index fb5749bfb348..000000000000 --- a/drivers/net/ethernet/stmicro/stmmac/chain_mode.c +++ /dev/null @@ -1,65 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/******************************************************************************* - Specialised functions for managing Chained mode - - Copyright(C) 2011 STMicroelectronics Ltd - - It defines all the functions used to handle the normal/enhanced - descriptors in case of the DMA is configured to work in chained or - in ring mode. - - - Author: Giuseppe Cavallaro <peppe.cavallaro@st.com> -*******************************************************************************/ - -#include "stmmac.h" - -static void init_dma_chain(void *des, dma_addr_t phy_addr, - unsigned int size, unsigned int extend_desc) -{ - /* - * In chained mode the des3 points to the next element in the ring. - * The latest element has to point to the head. - */ - int i; - dma_addr_t dma_phy = phy_addr; - - if (extend_desc) { - struct dma_extended_desc *p = (struct dma_extended_desc *)des; - for (i = 0; i < (size - 1); i++) { - dma_phy += sizeof(struct dma_extended_desc); - p->basic.des3 = cpu_to_le32((unsigned int)dma_phy); - p++; - } - p->basic.des3 = cpu_to_le32((unsigned int)phy_addr); - - } else { - struct dma_desc *p = (struct dma_desc *)des; - for (i = 0; i < (size - 1); i++) { - dma_phy += sizeof(struct dma_desc); - p->des3 = cpu_to_le32((unsigned int)dma_phy); - p++; - } - p->des3 = cpu_to_le32((unsigned int)phy_addr); - } -} - -static void refill_desc3(struct stmmac_rx_queue *rx_q, struct dma_desc *p) -{ - struct stmmac_priv *priv = rx_q->priv_data; - - if (priv->hwts_rx_en && !priv->extend_desc) - /* NOTE: Device will overwrite des3 with timestamp value if - * 1588-2002 time stamping is enabled, hence reinitialize it - * to keep explicit chaining in the descriptor. - */ - p->des3 = cpu_to_le32((unsigned int)(rx_q->dma_rx_phy + - (((rx_q->dirty_rx) + 1) % - priv->dma_conf.dma_rx_size) * - sizeof(struct dma_desc))); -} - -const struct stmmac_mode_ops chain_mode_ops = { - .init = init_dma_chain, - .refill_desc3 = refill_desc3, -}; diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h index c41e15124472..27665c7c5c25 100644 --- a/drivers/net/ethernet/stmicro/stmmac/common.h +++ b/drivers/net/ethernet/stmicro/stmmac/common.h @@ -639,7 +639,6 @@ struct mac_device_info { const struct stmmac_ops *mac; const struct stmmac_desc_ops *desc; const struct stmmac_dma_ops *dma; - const struct stmmac_mode_ops *mode; const struct stmmac_hwtimestamp *ptp; const struct stmmac_tc_ops *tc; const struct stmmac_mmc_ops *mmc; diff --git a/drivers/net/ethernet/stmicro/stmmac/descs_com.h b/drivers/net/ethernet/stmicro/stmmac/descs_com.h index 6e71832f5a90..5eba3182b7a9 100644 --- a/drivers/net/ethernet/stmicro/stmmac/descs_com.h +++ b/drivers/net/ethernet/stmicro/stmmac/descs_com.h @@ -36,6 +36,18 @@ static inline void enh_desc_rx_set_on_ring(struct dma_desc *p, int end, p->des1 |= cpu_to_le32(ERDES1_END_RING); } +static inline void enh_desc_rx_set_buf_on_ring(struct dma_desc *p, int bfsize) +{ + if (bfsize > STMMAC_RX_BUF_ALIGN(ERDES1_BUFFER1_SIZE_MASK)) { + u32 buf1_len = STMMAC_RX_BUF_ALIGN(ERDES1_BUFFER1_SIZE_MASK); + + /* Note DMA will ignore the data-bus unaligned offset of the + * non-first Rx buffers. + */ + p->des3 = cpu_to_le32(le32_to_cpu(p->des2) + buf1_len); + } +} + static inline unsigned int enh_desc_rx_desc_len_on_ring(void) { return STMMAC_RX_BUF_ALIGN(FIELD_MAX(ERDES1_BUFFER1_SIZE_MASK)) + @@ -85,6 +97,18 @@ static inline void ndesc_rx_set_on_ring(struct dma_desc *p, int end, int bfsize) p->des1 |= cpu_to_le32(RDES1_END_RING); } +static inline void ndesc_rx_set_buf_on_ring(struct dma_desc *p, int bfsize) +{ + if (bfsize > STMMAC_RX_BUF_ALIGN(RDES1_BUFFER1_SIZE_MASK)) { + u32 buf1_len = STMMAC_RX_BUF_ALIGN(RDES1_BUFFER1_SIZE_MASK); + + /* Note DMA will ignore the data-bus unaligned offset of the + * non-first Rx buffers. + */ + p->des3 = cpu_to_le32(le32_to_cpu(p->des2) + buf1_len); + } +} + static inline unsigned int ndesc_rx_desc_len_on_ring(void) { return STMMAC_RX_BUF_ALIGN(FIELD_MAX(RDES1_BUFFER1_SIZE_MASK)) + @@ -128,6 +152,14 @@ static inline void enh_desc_rx_set_on_chain(struct dma_desc *p, int bfsize) ERDES1_SECOND_ADDRESS_CHAINED); } +static inline void enh_desc_rx_set_buf_on_chain(struct dma_desc *p, dma_addr_t np, + bool hwts_rx_en) +{ + /* des3 is overwritten with timestamp in case of IEEE 1588-2002 */ + if (hwts_rx_en) + p->des3 = cpu_to_le32(lower_32_bits(np)); +} + static inline unsigned int enh_desc_rx_desc_len_on_chain(void) { return STMMAC_RX_BUF_ALIGN(FIELD_MAX(ERDES1_BUFFER1_SIZE_MASK)); @@ -160,6 +192,14 @@ static inline void ndesc_rx_set_on_chain(struct dma_desc *p, int bfsize) RDES1_SECOND_ADDRESS_CHAINED); } +static inline void ndesc_rx_set_buf_on_chain(struct dma_desc *p, dma_addr_t np, + bool hwts_rx_en) +{ + /* des3 is overwritten with timestamp in case of IEEE 1588-2002 */ + if (hwts_rx_en) + p->des3 = cpu_to_le32(lower_32_bits(np)); +} + static inline unsigned int ndesc_rx_desc_len_on_chain(void) { return STMMAC_RX_BUF_ALIGN(FIELD_MAX(RDES1_BUFFER1_SIZE_MASK)); diff --git a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c index 0781700a554d..91d63659f108 100644 --- a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c +++ b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c @@ -327,6 +327,15 @@ static unsigned int enh_desc_get_rx_len(int mode) return enh_desc_rx_desc_len_on_ring(); } +static void enh_desc_prepare_rx_desc(struct dma_desc *p, int mode, + dma_addr_t np, bool hwts_rx, int bfsize) +{ + if (mode == STMMAC_CHAIN_MODE) + enh_desc_rx_set_buf_on_chain(p, np, hwts_rx); + else + enh_desc_rx_set_buf_on_ring(p, bfsize); +} + static int enh_desc_get_tx_ls(struct dma_desc *p) { return (le32_to_cpu(p->des0) & ETDES0_LAST_SEGMENT) >> 29; @@ -484,6 +493,7 @@ const struct stmmac_desc_ops enh_desc_ops = { .init_rx_desc = enh_desc_init_rx_desc, .init_tx_desc = enh_desc_init_tx_desc, .get_tx_owner = enh_desc_get_tx_owner, + .prepare_rx_desc = enh_desc_prepare_rx_desc, .release_tx_desc = enh_desc_release_tx_desc, .prepare_tx_desc = enh_desc_prepare_tx_desc, .set_tx_ic = enh_desc_set_tx_ic, @@ -508,6 +518,7 @@ const struct stmmac_desc_ops enh_desc_noext_ops = { .init_rx_desc = enh_desc_init_rx_desc, .init_tx_desc = enh_desc_init_tx_desc, .get_tx_owner = enh_desc_get_tx_owner, + .prepare_rx_desc = enh_desc_prepare_rx_desc, .release_tx_desc = enh_desc_release_tx_desc, .prepare_tx_desc = enh_desc_prepare_tx_desc, .set_tx_ic = enh_desc_set_tx_ic, @@ -532,6 +543,7 @@ const struct stmmac_desc_ops enh_desc_ext_ops = { .init_rx_desc = enh_desc_init_rx_desc, .init_tx_desc = enh_desc_init_tx_desc, .get_tx_owner = enh_desc_get_tx_owner, + .prepare_rx_desc = enh_desc_prepare_rx_desc, .release_tx_desc = enh_desc_release_tx_desc, .prepare_tx_desc = enh_desc_prepare_tx_desc, .set_tx_ic = enh_desc_set_tx_ic, diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.c b/drivers/net/ethernet/stmicro/stmmac/hwif.c index 35d9f058cea2..fa8b0bf5bdad 100644 --- a/drivers/net/ethernet/stmicro/stmmac/hwif.c +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.c @@ -51,21 +51,6 @@ static void stmmac_get_version(struct stmmac_priv *priv, ver->dev_id = FIELD_GET(DWMAC_USERVER, version); } -static void stmmac_dwmac_mode_quirk(struct stmmac_priv *priv) -{ - struct mac_device_info *mac = priv->hw; - - if (priv->chain_mode) { - dev_info(priv->device, "Chain mode enabled\n"); - priv->mode = STMMAC_CHAIN_MODE; - mac->mode = &chain_mode_ops; - } else { - dev_info(priv->device, "Ring mode enabled\n"); - priv->mode = STMMAC_RING_MODE; - mac->mode = &ring_mode_ops; - } -} - static int stmmac_dwmac1_quirks(struct stmmac_priv *priv) { struct mac_device_info *mac = priv->hw; @@ -92,13 +77,6 @@ static int stmmac_dwmac1_quirks(struct stmmac_priv *priv) mac->desc = priv->plat->rx_coe ? &ndesc_rxcoe2_ops : &ndesc_ops; } - stmmac_dwmac_mode_quirk(priv); - return 0; -} - -static int stmmac_dwmac4_quirks(struct stmmac_priv *priv) -{ - stmmac_dwmac_mode_quirk(priv); return 0; } @@ -129,7 +107,6 @@ static const struct stmmac_hwif_entry { const void *mac; const void *hwtimestamp; const void *ptp; - const void *mode; const void *tc; const void *mmc; const void *est; @@ -150,7 +127,6 @@ static const struct stmmac_hwif_entry { .mac = &dwmac100_ops, .hwtimestamp = &dwmac1000_ptp, .ptp = &dwmac1000_ptp_clock_ops, - .mode = NULL, .tc = NULL, .mmc = &dwmac_mmc_ops, .setup = dwmac100_setup, @@ -167,7 +143,6 @@ static const struct stmmac_hwif_entry { .mac = &dwmac1000_ops, .hwtimestamp = &dwmac1000_ptp, .ptp = &dwmac1000_ptp_clock_ops, - .mode = NULL, .tc = NULL, .mmc = &dwmac_mmc_ops, .setup = dwmac1000_setup, @@ -186,12 +161,10 @@ static const struct stmmac_hwif_entry { .vlan = &dwmac_vlan_ops, .hwtimestamp = &stmmac_ptp, .ptp = &stmmac_ptp_clock_ops, - .mode = NULL, .tc = &dwmac4_tc_ops, .mmc = &dwmac_mmc_ops, .est = &dwmac510_est_ops, .setup = dwmac4_setup, - .quirks = stmmac_dwmac4_quirks, }, { .core_type = DWMAC_CORE_GMAC4, .min_id = DWMAC_CORE_4_00, @@ -380,7 +353,6 @@ int stmmac_hwif_init(struct stmmac_priv *priv) mac->dma = mac->dma ? : entry->dma; mac->mac = mac->mac ? : entry->mac; mac->ptp = mac->ptp ? : entry->hwtimestamp; - mac->mode = mac->mode ? : entry->mode; mac->tc = mac->tc ? : entry->tc; mac->mmc = mac->mmc ? : entry->mmc; mac->est = mac->est ? : entry->est; diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h index 2216c25abc66..2eb1e03375f1 100644 --- a/drivers/net/ethernet/stmicro/stmmac/hwif.h +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h @@ -42,6 +42,9 @@ struct stmmac_desc_ops { int end, int bfsize); /* DMA TX descriptor ring initialization */ void (*init_tx_desc)(struct dma_desc *p, int mode, int end); + /* Invoked by the refill function to prepare the rx descriptor */ + void (*prepare_rx_desc)(struct dma_desc *p, int mode, + dma_addr_t np, bool hwts_rx, int bfsize); /* Invoked by the xmit function to prepare the tx descriptor */ void (*prepare_tx_desc)(struct dma_desc *p, int is_fs, int len, bool csum_flag, int mode, bool tx_own, bool ls, @@ -109,6 +112,8 @@ struct stmmac_desc_ops { stmmac_do_void_callback(__priv, desc, init_rx_desc, __args) #define stmmac_init_tx_desc(__priv, __args...) \ stmmac_do_void_callback(__priv, desc, init_tx_desc, __args) +#define stmmac_prepare_rx_desc(__priv, __args...) \ + stmmac_do_void_callback(__priv, desc, prepare_rx_desc, __args) #define stmmac_prepare_tx_desc(__priv, __args...) \ stmmac_do_void_callback(__priv, desc, prepare_tx_desc, __args) #define stmmac_prepare_tso_tx_desc(__priv, __args...) \ @@ -547,21 +552,6 @@ struct stmmac_hwtimestamp { struct stmmac_tx_queue; struct stmmac_rx_queue; -/* Helpers to manage the descriptors for chain and ring modes */ -struct stmmac_mode_ops { - void (*init) (void *des, dma_addr_t phy_addr, unsigned int size, - unsigned int extend_desc); - void (*init_desc3)(struct dma_desc *p); - void (*refill_desc3)(struct stmmac_rx_queue *rx_q, struct dma_desc *p); -}; - -#define stmmac_mode_init(__priv, __args...) \ - stmmac_do_void_callback(__priv, mode, init, __args) -#define stmmac_init_desc3(__priv, __args...) \ - stmmac_do_void_callback(__priv, mode, init_desc3, __args) -#define stmmac_refill_desc3(__priv, __args...) \ - stmmac_do_void_callback(__priv, mode, refill_desc3, __args) - struct tc_cls_u32_offload; struct tc_cbs_qopt_offload; struct flow_cls_offload; @@ -680,9 +670,6 @@ extern const struct stmmac_desc_ops ndesc_rxcoe2_ops; extern const struct stmmac_hwtimestamp stmmac_ptp; extern const struct stmmac_hwtimestamp dwmac1000_ptp; -extern const struct stmmac_mode_ops ring_mode_ops; -extern const struct stmmac_mode_ops chain_mode_ops; - extern const struct stmmac_ops dwmac100_ops; extern const struct stmmac_dma_ops dwmac100_dma_ops; extern const struct stmmac_ops dwmac1000_ops; diff --git a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c index 95d3031f4ab9..d24324bd2058 100644 --- a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c +++ b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c @@ -201,6 +201,15 @@ static unsigned int ndesc_get_rx_len(int mode) return ndesc_rx_desc_len_on_ring(); } +static void ndesc_prepare_rx_desc(struct dma_desc *p, int mode, + dma_addr_t np, bool hwts_rx, int bfsize) +{ + if (mode == STMMAC_CHAIN_MODE) + ndesc_rx_set_buf_on_chain(p, np, hwts_rx); + else + ndesc_rx_set_buf_on_ring(p, bfsize); +} + static int ndesc_get_tx_ls(struct dma_desc *p) { return (le32_to_cpu(p->des1) & TDES1_LAST_SEGMENT) >> 30; @@ -339,6 +348,7 @@ const struct stmmac_desc_ops ndesc_ops = { .init_rx_desc = ndesc_init_rx_desc, .init_tx_desc = ndesc_init_tx_desc, .get_tx_owner = ndesc_get_tx_owner, + .prepare_rx_desc = ndesc_prepare_rx_desc, .release_tx_desc = ndesc_release_tx_desc, .prepare_tx_desc = ndesc_prepare_tx_desc, .set_tx_ic = ndesc_set_tx_ic, @@ -363,6 +373,7 @@ const struct stmmac_desc_ops ndesc_rxcoe2_ops = { .init_rx_desc = ndesc_init_rx_desc, .init_tx_desc = ndesc_init_tx_desc, .get_tx_owner = ndesc_get_tx_owner, + .prepare_rx_desc = ndesc_prepare_rx_desc, .release_tx_desc = ndesc_release_tx_desc, .prepare_tx_desc = ndesc_prepare_tx_desc, .set_tx_ic = ndesc_set_tx_ic, diff --git a/drivers/net/ethernet/stmicro/stmmac/ring_mode.c b/drivers/net/ethernet/stmicro/stmmac/ring_mode.c deleted file mode 100644 index 916396cb59b8..000000000000 --- a/drivers/net/ethernet/stmicro/stmmac/ring_mode.c +++ /dev/null @@ -1,35 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/******************************************************************************* - Specialised functions for managing Ring mode - - Copyright(C) 2011 STMicroelectronics Ltd - - It defines all the functions used to handle the normal/enhanced - descriptors in case of the DMA is configured to work in chained or - in ring mode. - - - Author: Giuseppe Cavallaro <peppe.cavallaro@st.com> -*******************************************************************************/ - -#include "stmmac.h" - -static void refill_desc3(struct stmmac_rx_queue *rx_q, struct dma_desc *p) -{ - struct stmmac_priv *priv = rx_q->priv_data; - - /* Fill DES3 in case of RING mode */ - if (priv->dma_conf.dma_buf_sz == BUF_SIZE_16KiB) - p->des3 = cpu_to_le32(le32_to_cpu(p->des2) + BUF_SIZE_8KiB); -} - -/* In ring mode we need to fill the desc3 because it is used as buffer */ -static void init_desc3(struct dma_desc *p) -{ - p->des3 = cpu_to_le32(le32_to_cpu(p->des2) + BUF_SIZE_8KiB); -} - -const struct stmmac_mode_ops ring_mode_ops = { - .refill_desc3 = refill_desc3, - .init_desc3 = init_desc3, -}; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 44f3ef3ff361..5fbafd8e53ce 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1711,7 +1711,7 @@ static void stmmac_clear_descriptors(struct stmmac_priv *priv, */ static int stmmac_init_rx_buffers(struct stmmac_priv *priv, struct stmmac_dma_conf *dma_conf, - struct dma_desc *p, + struct dma_desc *p, dma_addr_t np, int i, gfp_t flags, u32 queue) { struct stmmac_rx_queue *rx_q = &dma_conf->rx_queue[queue]; @@ -1751,8 +1751,8 @@ static int stmmac_init_rx_buffers(struct stmmac_priv *priv, } stmmac_set_desc_addr(priv, p, buf->addr); - if (dma_conf->dma_buf_sz == BUF_SIZE_16KiB) - stmmac_init_desc3(priv, p); + stmmac_prepare_rx_desc(priv, p, priv->mode, np, true, + dma_conf->dma_buf_sz); return 0; } @@ -1861,14 +1861,19 @@ static int stmmac_alloc_rx_buffers(struct stmmac_priv *priv, for (i = 0; i < dma_conf->dma_rx_size; i++) { struct dma_desc *p; + dma_addr_t np; int ret; - if (priv->extend_desc) - p = &((rx_q->dma_erx + i)->basic); - else - p = rx_q->dma_rx + i; + np = STMMAC_GET_ENTRY(i, dma_conf->dma_rx_size); + if (priv->extend_desc) { + p = &rx_q->dma_erx[i].basic; + np = rx_q->dma_rx_phy + np * sizeof(struct dma_extended_desc); + } else { + p = &rx_q->dma_rx[i]; + np = rx_q->dma_rx_phy + np * sizeof(struct dma_desc); + } - ret = stmmac_init_rx_buffers(priv, dma_conf, p, i, flags, + ret = stmmac_init_rx_buffers(priv, dma_conf, p, np, i, flags, queue); if (ret) return ret; @@ -1924,13 +1929,17 @@ static int stmmac_alloc_rx_buffers_zc(struct stmmac_priv *priv, for (i = 0; i < dma_conf->dma_rx_size; i++) { struct stmmac_rx_buffer *buf; - dma_addr_t dma_addr; + dma_addr_t dma_addr, np; struct dma_desc *p; - if (priv->extend_desc) - p = (struct dma_desc *)(rx_q->dma_erx + i); - else - p = rx_q->dma_rx + i; + np = STMMAC_GET_ENTRY(i, dma_conf->dma_rx_size); + if (priv->extend_desc) { + p = &rx_q->dma_erx[i].basic; + np = rx_q->dma_rx_phy + np * sizeof(struct dma_extended_desc); + } else { + p = &rx_q->dma_rx[i]; + np = rx_q->dma_rx_phy + np * sizeof(struct dma_desc); + } buf = &rx_q->buf_pool[i]; @@ -1940,6 +1949,9 @@ static int stmmac_alloc_rx_buffers_zc(struct stmmac_priv *priv, dma_addr = xsk_buff_xdp_get_dma(buf->xdp); stmmac_set_desc_addr(priv, p, dma_addr); + stmmac_prepare_rx_desc(priv, p, priv->mode, np, true, + dma_conf->dma_buf_sz); + rx_q->buf_alloc_num++; } @@ -2010,18 +2022,6 @@ static int __init_dma_rx_desc_rings(struct stmmac_priv *priv, return -ENOMEM; } - /* Setup the chained descriptor addresses */ - if (priv->mode == STMMAC_CHAIN_MODE) { - if (priv->extend_desc) - stmmac_mode_init(priv, rx_q->dma_erx, - rx_q->dma_rx_phy, - dma_conf->dma_rx_size, 1); - else - stmmac_mode_init(priv, rx_q->dma_rx, - rx_q->dma_rx_phy, - dma_conf->dma_rx_size, 0); - } - return 0; } @@ -5148,11 +5148,16 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv, u32 queue) struct stmmac_rx_buffer *buf = &rx_q->buf_pool[entry]; struct dma_desc *p; bool use_rx_wd; + dma_addr_t np; - if (priv->extend_desc) - p = (struct dma_desc *)(rx_q->dma_erx + entry); - else - p = rx_q->dma_rx + entry; + np = STMMAC_GET_ENTRY(entry, priv->dma_conf.dma_rx_size); + if (priv->extend_desc) { + p = &rx_q->dma_erx[entry].basic; + np = rx_q->dma_rx_phy + np * sizeof(struct dma_extended_desc); + } else { + p = &rx_q->dma_rx[entry]; + np = rx_q->dma_rx_phy + np * sizeof(struct dma_desc); + } if (!buf->page) { size = rx_q->napi_skb_frag_size; @@ -5180,8 +5185,8 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv, u32 queue) stmmac_set_desc_addr(priv, p, buf->addr); stmmac_set_desc_sec_addr(priv, p, buf->sec_addr, priv->sph_active); - - stmmac_refill_desc3(priv, rx_q, p); + stmmac_prepare_rx_desc(priv, p, priv->mode, np, + priv->hwts_rx_en, priv->dma_conf.dma_buf_sz); rx_q->rx_count_frames++; if (rx_q->rx_count_frames > priv->rx_coal_frames[queue]) @@ -5573,6 +5578,7 @@ static bool stmmac_rx_refill_zc(struct stmmac_priv *priv, u32 queue, u32 budget) struct stmmac_rx_queue *rx_q = &priv->dma_conf.rx_queue[queue]; unsigned int entry = rx_q->dirty_rx; struct dma_desc *rx_desc = NULL; + dma_addr_t rx_next; bool ret = true; budget = min(budget, stmmac_rx_dirty(priv, queue)); @@ -5590,15 +5596,22 @@ static bool stmmac_rx_refill_zc(struct stmmac_priv *priv, u32 queue, u32 budget) } } - if (priv->extend_desc) - rx_desc = (struct dma_desc *)(rx_q->dma_erx + entry); - else - rx_desc = rx_q->dma_rx + entry; + rx_next = STMMAC_GET_ENTRY(entry, priv->dma_conf.dma_rx_size); + if (priv->extend_desc) { + rx_desc = &rx_q->dma_erx[entry].basic; + rx_next = rx_q->dma_rx_phy + + rx_next * sizeof(struct dma_extended_desc); + } else { + rx_desc = &rx_q->dma_rx[entry]; + rx_next = rx_q->dma_rx_phy + + rx_next * sizeof(struct dma_desc); + } dma_addr = xsk_buff_xdp_get_dma(buf->xdp); stmmac_set_desc_addr(priv, rx_desc, dma_addr); stmmac_set_desc_sec_addr(priv, rx_desc, 0, false); - stmmac_refill_desc3(priv, rx_q, rx_desc); + stmmac_prepare_rx_desc(priv, rx_desc, priv->mode, rx_next, + priv->hwts_rx_en, priv->dma_conf.dma_buf_sz); rx_q->rx_count_frames++; if (rx_q->rx_count_frames > priv->rx_coal_frames[queue]) |
