<div dir="ltr">On Tue, Aug 6, 2024 at 2:56 PM Serge Semin <<a href="mailto:fancer.lancer@gmail.com">fancer.lancer@gmail.com</a>> wrote:<br>><br>> On Thu, Aug 01, 2024 at 08:18:20PM -0700, <a href="mailto:jitendra.vegiraju@broadcom.com">jitendra.vegiraju@broadcom.com</a> wrote:<br>> > From: Jitendra Vegiraju <<a href="mailto:jitendra.vegiraju@broadcom.com">jitendra.vegiraju@broadcom.com</a>><br>> ><br>> > Adds support for DWC_xgmac version 4.00a in stmmac core module.<br>> > This version adds enhancements to DMA architecture for virtualization<br>> > scalability. This is realized by decoupling physical DMA channels (PDMA)<br>> > from Virtual DMA channels (VDMA). The  VDMAs are software abastractions<br>> > that map to PDMAs for frame transmission and reception.<br>> ><br>> > The virtualization enhancements are currently not being used and hence<br>> > a fixed mapping of VDMA to PDMA is configured in the init functions.<br>> > Because of the new init functions, a new instance of struct stmmac_dma_ops<br>> > dwxgmac400_dma_ops is added.<br>> > Most of the other dma operation functions in existing dwxgamc2_dma.c file<br>> > can be reused.<br>><br>> As we figured out (didn't we?) that it's actually the DW 25GMAC, then<br>> it should be taken into account across the entire series.<br>><br>Yes, indeed.<br>Its confirmed by the design team that we received an early adopter version of 25GMAC IP.<br>It is also confirmed that 25GMAC always comes with HDMA .<br>The revision id is 4.xx and device id is 0x55.<br>With that in mind, we will change naming to 25GMAC throughout the patch .<br>> ><br>> > Signed-off-by: Jitendra Vegiraju <<a href="mailto:jitendra.vegiraju@broadcom.com">jitendra.vegiraju@broadcom.com</a>><br>> > ---<br>> >  drivers/net/ethernet/stmicro/stmmac/Makefile  |   2 +-<br>> >  .../ethernet/stmicro/stmmac/dwxgmac2_dma.c    |  31 ++++<br>> >  .../net/ethernet/stmicro/stmmac/dwxgmac4.c    | 142 ++++++++++++++++++<br>> >  .../net/ethernet/stmicro/stmmac/dwxgmac4.h    |  84 +++++++++++<br>> >  4 files changed, 258 insertions(+), 1 deletion(-)<br>> >  create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwxgmac4.c<br>> >  create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwxgmac4.h<br>> ><br>> > diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile<br>> > index c2f0e91f6bf8..2f637612513d 100644<br>> > --- a/drivers/net/ethernet/stmicro/stmmac/Makefile<br>> > +++ b/drivers/net/ethernet/stmicro/stmmac/Makefile<br>> > @@ -6,7 +6,7 @@ stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o ring_mode.o        \<br>> >             mmc_core.o stmmac_hwtstamp.o stmmac_ptp.o dwmac4_descs.o  \<br>> >             dwmac4_dma.o dwmac4_lib.o dwmac4_core.o dwmac5.o hwif.o \<br>> >             stmmac_tc.o dwxgmac2_core.o dwxgmac2_dma.o dwxgmac2_descs.o \<br>> > -           stmmac_xdp.o stmmac_est.o \<br>><br>> > +           stmmac_xdp.o stmmac_est.o dwxgmac4.o \<br>><br>> dw25gmac.o?<br>><br>> >             $(stmmac-y)<br>> ><br>> >  stmmac-$(CONFIG_STMMAC_SELFTESTS) += stmmac_selftests.o<br>> > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c<br>> > index dd2ab6185c40..c15f5247aaa8 100644<br>> > --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c<br>> > +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c<br>> > @@ -7,6 +7,7 @@<br>> >  #include <linux/iopoll.h><br>> >  #include "stmmac.h"<br>> >  #include "dwxgmac2.h"<br>><br>> > +#include "dwxgmac4.h"<br>><br>> "dw25gmac.h"?<br>><br>> ><br>> >  static int dwxgmac2_dma_reset(void __iomem *ioaddr)<br>> >  {<br>> > @@ -641,3 +642,33 @@ const struct stmmac_dma_ops dwxgmac210_dma_ops = {<br>> >       .enable_sph = dwxgmac2_enable_sph,<br>> >       .enable_tbs = dwxgmac2_enable_tbs,<br>> >  };<br>> > +<br>><br>> > +const struct stmmac_dma_ops dwxgmac400_dma_ops = {<br>><br>> dw25gmac_dma_ops?<br>><br>> > +     .reset = dwxgmac2_dma_reset,<br>><br>> > +     .init = dwxgmac4_dma_init,<br>> > +     .init_chan = dwxgmac2_dma_init_chan,<br>> > +     .init_rx_chan = dwxgmac4_dma_init_rx_chan,<br>> > +     .init_tx_chan = dwxgmac4_dma_init_tx_chan,<br>><br>> dw25gmac_dma_init, dw25gmac_dma_init_rx_chan, dw25gmac_dma_init_tx_chan?<br>><br>> > +     .axi = dwxgmac2_dma_axi,<br>> > +     .dump_regs = dwxgmac2_dma_dump_regs,<br>> > +     .dma_rx_mode = dwxgmac2_dma_rx_mode,<br>> > +     .dma_tx_mode = dwxgmac2_dma_tx_mode,<br>> > +     .enable_dma_irq = dwxgmac2_enable_dma_irq,<br>> > +     .disable_dma_irq = dwxgmac2_disable_dma_irq,<br>> > +     .start_tx = dwxgmac2_dma_start_tx,<br>> > +     .stop_tx = dwxgmac2_dma_stop_tx,<br>> > +     .start_rx = dwxgmac2_dma_start_rx,<br>> > +     .stop_rx = dwxgmac2_dma_stop_rx,<br>> > +     .dma_interrupt = dwxgmac2_dma_interrupt,<br>> > +     .get_hw_feature = dwxgmac2_get_hw_feature,<br>> > +     .rx_watchdog = dwxgmac2_rx_watchdog,<br>> > +     .set_rx_ring_len = dwxgmac2_set_rx_ring_len,<br>> > +     .set_tx_ring_len = dwxgmac2_set_tx_ring_len,<br>> > +     .set_rx_tail_ptr = dwxgmac2_set_rx_tail_ptr,<br>> > +     .set_tx_tail_ptr = dwxgmac2_set_tx_tail_ptr,<br>> > +     .enable_tso = dwxgmac2_enable_tso,<br>> > +     .qmode = dwxgmac2_qmode,<br>> > +     .set_bfsize = dwxgmac2_set_bfsize,<br>> > +     .enable_sph = dwxgmac2_enable_sph,<br>> > +     .enable_tbs = dwxgmac2_enable_tbs,<br>> > +};<br>><br>> > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac4.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac4.c<br>> > new file mode 100644<br>> > index 000000000000..9c8748122dc6<br>> > --- /dev/null<br>> > +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac4.c<br>><br>> dw25gmac.c?<br>><br>> > @@ -0,0 +1,142 @@<br>> > +// SPDX-License-Identifier: GPL-2.0-only<br>> > +/*<br>> > + * Copyright (c) 2024 Broadcom Corporation<br>> > + */<br>> > +#include "dwxgmac2.h"<br>><br>> > +#include "dwxgmac4.h"<br>><br>> dw25gmac.h?<br>><br>> > +<br>> > +static int rd_dma_ch_ind(void __iomem *ioaddr, u8 mode, u32 channel)<br>> > +{<br>> > +     u32 reg_val = 0;<br>> > +     u32 val = 0;<br>> > +<br>> > +     reg_val |= mode << XGMAC4_MSEL_SHIFT & XGMAC4_MODE_SELECT;<br>> > +     reg_val |= channel << XGMAC4_AOFF_SHIFT & XGMAC4_ADDR_OFFSET;<br>> > +     reg_val |= XGMAC4_CMD_TYPE | XGMAC4_OB;<br>> > +     writel(reg_val, ioaddr + XGMAC4_DMA_CH_IND_CONTROL);<br>> > +     val = readl(ioaddr + XGMAC4_DMA_CH_IND_DATA);<br>> > +     return val;<br>> > +}<br>> > +<br>> > +static void wr_dma_ch_ind(void __iomem *ioaddr, u8 mode, u32 channel, u32 val)<br>> > +{<br>> > +     u32 reg_val = 0;<br>> > +<br>> > +     writel(val, ioaddr + XGMAC4_DMA_CH_IND_DATA);<br>> > +     reg_val |= mode << XGMAC4_MSEL_SHIFT & XGMAC4_MODE_SELECT;<br>> > +     reg_val |= channel << XGMAC4_AOFF_SHIFT & XGMAC4_ADDR_OFFSET;<br>> > +     reg_val |= XGMAC_OB;<br>> > +     writel(reg_val, ioaddr + XGMAC4_DMA_CH_IND_CONTROL);<br>> > +}<br>> > +<br>><br>> > +static void xgmac4_tp2tc_map(void __iomem *ioaddr, u8 pdma_ch, u32 tc_num)<br>> > +{<br>> > +     u32 val = 0;<br>> > +<br>> > +     val = rd_dma_ch_ind(ioaddr, MODE_TXEXTCFG, pdma_ch);<br>> > +     val &= ~XGMAC4_TP2TCMP;<br>> > +     val |= tc_num << XGMAC4_TP2TCMP_SHIFT & XGMAC4_TP2TCMP;<br>> > +     wr_dma_ch_ind(ioaddr, MODE_TXEXTCFG, pdma_ch, val);<br>> > +}<br>> > +<br>> > +static void xgmac4_rp2tc_map(void __iomem *ioaddr, u8 pdma_ch, u32 tc_num)<br>> > +{<br>> > +     u32 val = 0;<br>> > +<br>> > +     val = rd_dma_ch_ind(ioaddr, MODE_RXEXTCFG, pdma_ch);<br>> > +     val &= ~XGMAC4_RP2TCMP;<br>> > +     val |= tc_num << XGMAC4_RP2TCMP_SHIFT & XGMAC4_RP2TCMP;<br>> > +     wr_dma_ch_ind(ioaddr, MODE_RXEXTCFG, pdma_ch, val);<br>> > +}<br>><br>> What does "tc" stand for? Traffic control? If it's a kind of queue<br>> then what about implementing the stmmac_ops::map_mtl_to_dma interface<br>> method?<br>"TC" stands for traffic class. Its is mechanism to classify and schedule traffic<div>to DMA channels between VDMAs and PDMAs.<br><div> An example VDMA to PDMA mapping shown below<br>TX and RX.<br><font face="monospace">         VDMAs            Traffic Class      PDMA<br>         +--------+          +------+         +-----------+<br>         |VDMA0   |--------->| TC0  |-------->|PDMA0/TXQ0 |<br>  TX     +--------+   |----->+------+         +-----------+<br> Host => +--------+   |      +------+         +-----------+  => to MAC<br>  SW     |VDMA1   |---+      | TC1  |    +--->|PDMA1/TXQ1 |<br>         +--------+          +------+    |    +-----------+<br>         +--------+          +------+----+    +-----------+<br>         |VDMA2   |--------->| TC2  |-------->|PDMA2/TXQ1 |<br>         +--------+          +------+         +-----------+<br>         +--------+          +------+         +-----------+<br>         |VDMAn-1 |--------->| TCx-1|-------->|PDMAm/TXQm |<br>         +--------+          +------+         +-----------+<br></font><br><div><font face="monospace">        PDMAs            Traffic Class      VDMAs<br>         +------+          +------+         +------+<br>         |PDMA0 |--------->| TC0  |-------->|VDMA0 |<br>         +------+   |----->+------+         +------+<br> MAC =>  +------+   |      +------+         +------+<br>  RXQs   |PDMA1 |---+      | TC1  |    +--->|VDMA1 |  => Host<br>         +------+          +------+    |    +------+   Software<br>         +------+          +------+----+    +------+<br>         |PDMA2 |--------->| TC2  |-------->|VDMA2 |<br>         +------+          +------+         +------+<br>         +-------+         +------+        +--------+<br>         |PDMAn-1|-------->| TCx-1|------->|VDMAm-1 |<br>         +-------+         +------+        +--------+<br><br></font>> > +<br>> > +void dwxgmac4_dma_init(void __iomem *ioaddr,<br>> > +                    struct stmmac_dma_cfg *dma_cfg, int atds)<br>> > +{<br>> > +     u32 value;<br>> > +     u32 i;<br>> > +<br>> > +     value = readl(ioaddr + XGMAC_DMA_SYSBUS_MODE);<br>> > +<br>> > +     if (dma_cfg->aal)<br>> > +             value |= XGMAC_AAL;<br>> > +<br>> > +     if (dma_cfg->eame)<br>> > +             value |= XGMAC_EAME;<br>> > +<br>> > +     writel(value, ioaddr + XGMAC_DMA_SYSBUS_MODE);<br>> > +<br>> > +     for (i = 0; i < VDMA_TOTAL_CH_COUNT; i++) {<br>><br>> > +             value = rd_dma_ch_ind(ioaddr, MODE_TXDESCCTRL, i);<br>> > +             value &= ~XGMAC4_TXDCSZ;<br>> > +             value |= 0x3;<br>> > +             value &= ~XGMAC4_TDPS;<br>> > +             value |= (3 << XGMAC4_TDPS_SHIFT) & XGMAC4_TDPS;<br>> > +             wr_dma_ch_ind(ioaddr, MODE_TXDESCCTRL, i, value);<br>> > +<br>> > +             value = rd_dma_ch_ind(ioaddr, MODE_RXDESCCTRL, i);<br>> > +             value &= ~XGMAC4_RXDCSZ;<br>> > +             value |= 0x3;<br>> > +             value &= ~XGMAC4_RDPS;<br>> > +             value |= (3 << XGMAC4_RDPS_SHIFT) & XGMAC4_RDPS;<br>> > +             wr_dma_ch_ind(ioaddr, MODE_RXDESCCTRL, i, value);<br>><br>> I know that the TDPS/RDPS means Tx/Rx Descriptor Pre-fetch threshold<br>> Size. What does the TXDCSZ/RXDCSZ config mean?<br>><br>> Most importantly why are these parameters hardcoded to 3? It<br>> doesn't seem right.</div><div>TXDCSZ/RXDCSZ specify the per channel DMA descriptor cache size </div><div>I missed defining macro for the valid values, for example 3 indicates 256 bytes.</div><div>Will fix it in next patch update.<br>><br>> > +     }<br>> > +<br>><br>> > +     for (i = 0; i < PDMA_TX_CH_COUNT; i++) {<br>> > +             value = rd_dma_ch_ind(ioaddr, MODE_TXEXTCFG, i);<br>> > +             value &= ~(XGMAC4_TXPBL | XGMAC4_TPBLX8_MODE);<br>> > +             if (dma_cfg->pblx8)<br>> > +                     value |= XGMAC4_TPBLX8_MODE;<br>> > +             value |= (dma_cfg->pbl << XGMAC4_TXPBL_SHIFT) & XGMAC4_TXPBL;<br>> > +             wr_dma_ch_ind(ioaddr, MODE_TXEXTCFG, i, value);<br>> > +             xgmac4_tp2tc_map(ioaddr, i, i);<br>> > +     }<br>> > +<br>> > +     for (i = 0; i < PDMA_RX_CH_COUNT; i++) {<br>> > +             value = rd_dma_ch_ind(ioaddr, MODE_RXEXTCFG, i);<br>> > +             value &= ~(XGMAC4_RXPBL | XGMAC4_RPBLX8_MODE);<br>> > +             if (dma_cfg->pblx8)<br>> > +                     value |= XGMAC4_RPBLX8_MODE;<br>> > +             value |= (dma_cfg->pbl << XGMAC4_RXPBL_SHIFT) & XGMAC4_RXPBL;<br>> > +             wr_dma_ch_ind(ioaddr, MODE_RXEXTCFG, i, value);<br>> > +             if (i < PDMA_MAX_TC_COUNT)<br>> > +                     xgmac4_rp2tc_map(ioaddr, i, i);<br>> > +             else<br>> > +                     xgmac4_rp2tc_map(ioaddr, i, PDMA_MAX_TC_COUNT - 1);<br>> > +     }<br>><br>> Shouldn't these initialization be done on the per-channel basis only<br>> for only activated queues<br>> plat_stmmacenet_data::{rx_queues_to_use,tx_queues_to_use} (the STMMAC<br>> driver one-on-one maps queues and DMA-channels if no custom mapping<br>> was specified)?<br>></div><div>This is a mapping between VDMA and PDMA channels. We are starting with a default any to any mapping.</div><div><br>> > +}<br>> > +<br>> > +void dwxgmac4_dma_init_tx_chan(struct stmmac_priv *priv,<br>> > +                            void __iomem *ioaddr,<br>> > +                            struct stmmac_dma_cfg *dma_cfg,<br>> > +                            dma_addr_t dma_addr, u32 chan)<br>> > +{<br>> > +     u32 value;<br>> > +<br>> > +     value = readl(ioaddr + XGMAC_DMA_CH_TX_CONTROL(chan));<br>> > +     value &= ~XGMAC4_TVDMA2TCMP;<br>> > +     value |= (chan << XGMAC4_TVDMA2TCMP_SHIFT) & XGMAC4_TVDMA2TCMP;<br>> > +     writel(value, ioaddr + XGMAC_DMA_CH_TX_CONTROL(chan));<br>> > +<br>> > +     writel(upper_32_bits(dma_addr),<br>> > +            ioaddr + XGMAC_DMA_CH_TxDESC_HADDR(chan));<br>> > +     writel(lower_32_bits(dma_addr),<br>> > +            ioaddr + XGMAC_DMA_CH_TxDESC_LADDR(chan));<br>> > +}<br>> > +<br>> > +void dwxgmac4_dma_init_rx_chan(struct stmmac_priv *priv,<br>> > +                            void __iomem *ioaddr,<br>> > +                            struct stmmac_dma_cfg *dma_cfg,<br>> > +                            dma_addr_t dma_addr, u32 chan)<br>> > +{<br>> > +     u32 value;<br>> > +<br>> > +     value = readl(ioaddr + XGMAC_DMA_CH_RX_CONTROL(chan));<br>> > +     value &= ~XGMAC4_RVDMA2TCMP;<br>> > +     value |= (chan << XGMAC4_RVDMA2TCMP_SHIFT) & XGMAC4_RVDMA2TCMP;<br>> > +     writel(value, ioaddr + XGMAC_DMA_CH_RX_CONTROL(chan));<br>> > +<br>> > +     writel(upper_32_bits(dma_addr),<br>> > +            ioaddr + XGMAC_DMA_CH_RxDESC_HADDR(chan));<br>> > +     writel(lower_32_bits(dma_addr),<br>> > +            ioaddr + XGMAC_DMA_CH_RxDESC_LADDR(chan));<br>> > +}<br>> > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac4.h b/drivers/net/ethernet/stmicro/stmmac/dwxgmac4.h<br>> > new file mode 100644<br>> > index 000000000000..0ce1856b0b34<br>> > --- /dev/null<br>><br>> > +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac4.h<br>><br>> dw25gmac.h?<br>><br>> > @@ -0,0 +1,84 @@<br>> > +/* SPDX-License-Identifier: GPL-2.0-only */<br>> > +/* Copyright (c) 2024 Broadcom Corporation<br>> > + * XGMAC4 definitions.<br>> > + */<br>> > +#ifndef __STMMAC_DWXGMAC4_H__<br>> > +#define __STMMAC_DWXGMAC4_H__<br>> > +<br>> > +/* DMA Indirect Registers*/<br>><br>> > +#define XGMAC4_DMA_CH_IND_CONTROL    0X00003080<br>><br>> XXVGMAC_*?<br>><br>> > +#define XGMAC4_MODE_SELECT           GENMASK(27, 24)<br>> > +#define XGMAC4_MSEL_SHIFT            24<br>> > +enum dma_ch_ind_modes {<br>> > +     MODE_TXEXTCFG    = 0x0,   /* Tx Extended Config */<br>> > +     MODE_RXEXTCFG    = 0x1,   /* Rx Extended Config */<br>> > +     MODE_TXDBGSTS    = 0x2,   /* Tx Debug Status */<br>> > +     MODE_RXDBGSTS    = 0x3,   /* Rx Debug Status */<br>> > +     MODE_TXDESCCTRL  = 0x4,   /* Tx Descriptor control */<br>> > +     MODE_RXDESCCTRL  = 0x5,   /* Rx Descriptor control */<br>> > +};<br>> > +<br>> > +#define XGMAC4_ADDR_OFFSET           GENMASK(14, 8)<br>> > +#define XGMAC4_AOFF_SHIFT            8<br>> > +#define XGMAC4_AUTO_INCR             GENMASK(5, 4)<br>> > +#define XGMAC4_AUTO_SHIFT            4<br>> > +#define XGMAC4_CMD_TYPE                      BIT(1)<br>> > +#define XGMAC4_OB                    BIT(0)<br>> > +#define XGMAC4_DMA_CH_IND_DATA               0X00003084<br>> > +<br>> > +/* TX Config definitions */<br>> > +#define XGMAC4_TXPBL                 GENMASK(29, 24)<br>> > +#define XGMAC4_TXPBL_SHIFT           24<br>> > +#define XGMAC4_TPBLX8_MODE           BIT(19)<br>> > +#define XGMAC4_TP2TCMP                       GENMASK(18, 16)<br>> > +#define XGMAC4_TP2TCMP_SHIFT         16<br>> > +#define XGMAC4_ORRQ                  GENMASK(13, 8)<br>> > +/* RX Config definitions */<br>> > +#define XGMAC4_RXPBL                 GENMASK(29, 24)<br>> > +#define XGMAC4_RXPBL_SHIFT           24<br>> > +#define XGMAC4_RPBLX8_MODE           BIT(19)<br>> > +#define XGMAC4_RP2TCMP                       GENMASK(18, 16)<br>> > +#define XGMAC4_RP2TCMP_SHIFT         16<br>> > +#define XGMAC4_OWRQ                  GENMASK(13, 8)<br>> > +/* Tx Descriptor control */<br>> > +#define XGMAC4_TXDCSZ                        GENMASK(2, 0)<br>> > +#define XGMAC4_TDPS                  GENMASK(5, 3)<br>> > +#define XGMAC4_TDPS_SHIFT            3<br>> > +/* Rx Descriptor control */<br>> > +#define XGMAC4_RXDCSZ                        GENMASK(2, 0)<br>> > +#define XGMAC4_RDPS                  GENMASK(5, 3)<br>> > +#define XGMAC4_RDPS_SHIFT            3<br>> > +<br>> > +/* DWCXG_DMA_CH(#i) Registers*/<br>> > +#define XGMAC4_DSL                   GENMASK(20, 18)<br>> > +#define XGMAC4_MSS                   GENMASK(13, 0)<br>> > +#define XGMAC4_TFSEL                 GENMASK(30, 29)<br>> > +#define XGMAC4_TQOS                  GENMASK(27, 24)<br>> > +#define XGMAC4_IPBL                  BIT(15)<br>> > +#define XGMAC4_TVDMA2TCMP            GENMASK(6, 4)<br>> > +#define XGMAC4_TVDMA2TCMP_SHIFT              4<br>> > +#define XGMAC4_RPF                   BIT(31)<br>> > +#define XGMAC4_RVDMA2TCMP            GENMASK(30, 28)<br>> > +#define XGMAC4_RVDMA2TCMP_SHIFT              28<br>> > +#define XGMAC4_RQOS                  GENMASK(27, 24)<br>> > +<br>><br>> > +/* PDMA Channel count */<br>> > +#define PDMA_TX_CH_COUNT             8<br>> > +#define PDMA_RX_CH_COUNT             10<br>> > +#define PDMA_MAX_TC_COUNT            8<br>> > +<br>> > +/* VDMA channel count */<br>> > +#define VDMA_TOTAL_CH_COUNT          32<br>><br>> These seems like the vendor-specific constant. What are the actual DW<br>> 25GMAC constraints?<br>></div><div>These are the constraints in this device. We can read from the hardware, we will fix it in the next patch.</div><div><br>> -Serge(y)<br>><br>> > +<br>> > +void dwxgmac4_dma_init(void __iomem *ioaddr,<br>> > +                    struct stmmac_dma_cfg *dma_cfg, int atds);<br>> > +<br>> > +void dwxgmac4_dma_init_tx_chan(struct stmmac_priv *priv,<br>> > +                            void __iomem *ioaddr,<br>> > +                            struct stmmac_dma_cfg *dma_cfg,<br>> > +                            dma_addr_t dma_addr, u32 chan);<br>> > +void dwxgmac4_dma_init_rx_chan(struct stmmac_priv *priv,<br>> > +                            void __iomem *ioaddr,<br>> > +                            struct stmmac_dma_cfg *dma_cfg,<br>> > +                            dma_addr_t dma_addr, u32 chan);<br>> > +#endif /* __STMMAC_DWXGMAC4_H__ */<br>> > --<br>> > 2.34.1<br>> ><br>> ></div></div></div></div>