All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH net-next v8 00/11] stmmac: Add Loongson platform support
@ 2024-01-30  8:43 Yanteng Si
  2024-01-30  8:43 ` [PATCH net-next v8 01/11] net: stmmac: Add multi-channel support Yanteng Si
                   ` (12 more replies)
  0 siblings, 13 replies; 97+ messages in thread
From: Yanteng Si @ 2024-01-30  8:43 UTC (permalink / raw)
  To: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	fancer.lancer
  Cc: Yanteng Si, Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

v8:
* The biggest change is according to Serge's comment in the previous
  edition:
   Seeing the patch in the current state would overcomplicate the generic
   code and the only functions you need to update are
   dwmac_dma_interrupt()
   dwmac1000_dma_init_channel()
   you can have these methods re-defined with all the Loongson GNET
   specifics in the low-level platform driver (dwmac-loongson.c). After
   that you can just override the mac_device_info.dma pointer with a
   fixed stmmac_dma_ops descriptor. Here is what should be done for that:

   1. Keep the Patch 4/9 with my comments fixed. First it will be partly
   useful for your GNET device. Second in general it's a correct
   implementation of the normal DW GMAC v3.x multi-channels feature and
   will be useful for the DW GMACs with that feature enabled.

   2. Create the Loongson GNET-specific
   stmmac_dma_ops.dma_interrupt()
   stmmac_dma_ops.init_chan()
   methods in the dwmac-loongson.c driver. Don't forget to move all the
   Loongson-specific macros from dwmac_dma.h to dwmac-loongson.c.

   3. Create a Loongson GNET-specific platform setup method with the next
   semantics:
      + allocate stmmac_dma_ops instance and initialize it with
        dwmac1000_dma_ops.
      + override the stmmac_dma_ops.{dma_interrupt, init_chan} with
        the pointers to the methods defined in 2.
      + allocate mac_device_info instance and initialize the
        mac_device_info.dma field with a pointer to the new
        stmmac_dma_ops instance.
      + call dwmac1000_setup() or initialize mac_device_info in a way
        it's done in dwmac1000_setup() (the later might be better so you
        wouldn't need to export the dwmac1000_setup() function).
      + override stmmac_priv.synopsys_id with a correct value.

   4. Initialize plat_stmmacenet_data.setup() with the pointer to the
   method created in 3.

* Others:
  Re-split the patch.
  Passed checkpatch.pl test.

v7:
* Refer to andrew's suggestion:
  - Add DMA_INTR_ENA_NIE_RX and DMA_INTR_ENA_NIE_TX #define's, etc.

* Others:
  - Using --subject-prefix="PATCH net-next vN" to indicate that the
    patches are for the networking tree.
  - Rebase to the latest networking tree:
    <git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git>


v6:

* Refer to Serge's suggestion:
  - Add new platform feature flag:
    include/linux/stmmac.h:
    +#define STMMAC_FLAG_HAS_LGMAC			BIT(13)

  - Add the IRQs macros specific to the Loongson Multi-channels GMAC:
     drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h:
     +#define DMA_INTR_ENA_NIE_LOONGSON 0x00060000      /* ...*/
     #define DMA_INTR_ENA_NIE 0x00010000	/* Normal Summary */
     ...

  - Drop all of redundant changes that don't require the
    prototypes being converted to accepting the stmmac_priv
    pointer.

* Refer to andrew's suggestion:
  - Drop white space changes.
  - break patch up into lots of smaller parts.
     Some small patches have been put into another series as a preparation
     see <https://lore.kernel.org/loongarch/cover.1702289232.git.siyanteng@loongson.cn/T/#t>
     
     *note* : This series of patches relies on the three small patches above.
* others
  - Drop irq_flags changes.
  - Changed patch order.


v4 -> v5:

* Remove an ugly and useless patch (fix channel number).
* Remove the non-standard dma64 driver code, and also remove
  the HWIF entries, since the associated custom callbacks no
  longer exist.
* Refer to Serge's suggestion: Update the dwmac1000_dma.c to
  support the multi-DMA-channels controller setup.

See:
v4: <https://lore.kernel.org/loongarch/cover.1692696115.git.chenfeiyang@loongson.cn/>
v3: <https://lore.kernel.org/loongarch/cover.1691047285.git.chenfeiyang@loongson.cn/>
v2: <https://lore.kernel.org/loongarch/cover.1690439335.git.chenfeiyang@loongson.cn/>
v1: <https://lore.kernel.org/loongarch/cover.1689215889.git.chenfeiyang@loongson.cn/>


Yanteng Si (11):
  net: stmmac: Add multi-channel support
  net: stmmac: dwmac-loongson: Refactor code for loongson_dwmac_probe()
  net: stmmac: dwmac-loongson: Add full PCI support
  net: stmmac: dwmac-loongson: Move irq config to loongson_gmac_config
  net: stmmac: dwmac-loongson: Add Loongson-specific register
    definitions
  net: stmmac: dwmac-loongson: Add GNET support
  net: stmmac: dwmac-loongson: Add multi-channel supports for loongson
  net: stmmac: dwmac-loongson: Fix MAC speed for GNET
  net: stmmac: dwmac-loongson: Fix half duplex
  net: stmmac: dwmac-loongson: Disable flow control for GMAC
  net: stmmac: dwmac-loongson: Disable coe for some Loongson GNET

 .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 561 ++++++++++++++++--
 .../net/ethernet/stmicro/stmmac/dwmac-sun8i.c |   2 +-
 .../ethernet/stmicro/stmmac/dwmac1000_dma.c   |  36 +-
 .../net/ethernet/stmicro/stmmac/dwmac_dma.h   |  19 +-
 .../net/ethernet/stmicro/stmmac/dwmac_lib.c   |  32 +-
 drivers/net/ethernet/stmicro/stmmac/hwif.h    |   2 +-
 .../ethernet/stmicro/stmmac/stmmac_ethtool.c  |   6 +
 .../net/ethernet/stmicro/stmmac/stmmac_main.c |  15 +-
 include/linux/stmmac.h                        |   3 +
 9 files changed, 582 insertions(+), 94 deletions(-)

-- 
2.31.4


^ permalink raw reply	[flat|nested] 97+ messages in thread

* [PATCH net-next v8 01/11] net: stmmac: Add multi-channel support
  2024-01-30  8:43 [PATCH net-next v8 00/11] stmmac: Add Loongson platform support Yanteng Si
@ 2024-01-30  8:43 ` Yanteng Si
  2024-02-02 12:30   ` Simon Horman
                     ` (2 more replies)
  2024-01-30  8:43 ` [PATCH net-next v8 02/11] net: stmmac: dwmac-loongson: Refactor code for loongson_dwmac_probe() Yanteng Si
                   ` (11 subsequent siblings)
  12 siblings, 3 replies; 97+ messages in thread
From: Yanteng Si @ 2024-01-30  8:43 UTC (permalink / raw)
  To: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	fancer.lancer
  Cc: Yanteng Si, Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

DW GMAC v3.x multi-channels feature is implemented as multiple
sets of the same CSRs. Here is only preliminary support, it will
be useful for the driver further evolution and for the users
having multi-channel DWGMAC v3.x devices.

Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
---
 .../net/ethernet/stmicro/stmmac/dwmac-sun8i.c |  2 +-
 .../ethernet/stmicro/stmmac/dwmac1000_dma.c   | 36 ++++++++++---------
 .../net/ethernet/stmicro/stmmac/dwmac_dma.h   | 19 +++++++++-
 .../net/ethernet/stmicro/stmmac/dwmac_lib.c   | 32 ++++++++---------
 drivers/net/ethernet/stmicro/stmmac/hwif.h    |  2 +-
 .../net/ethernet/stmicro/stmmac/stmmac_main.c |  6 ++--
 6 files changed, 58 insertions(+), 39 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
index 137741b94122..7cdfa0bdb93a 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
@@ -395,7 +395,7 @@ static void sun8i_dwmac_dma_start_tx(struct stmmac_priv *priv,
 	writel(v, ioaddr + EMAC_TX_CTL1);
 }
 
-static void sun8i_dwmac_enable_dma_transmission(void __iomem *ioaddr)
+static void sun8i_dwmac_enable_dma_transmission(void __iomem *ioaddr, u32 chan)
 {
 	u32 v;
 
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
index daf79cdbd3ec..5f7b82ad3ec2 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
@@ -70,15 +70,18 @@ static void dwmac1000_dma_axi(void __iomem *ioaddr, struct stmmac_axi *axi)
 	writel(value, ioaddr + DMA_AXI_BUS_MODE);
 }
 
-static void dwmac1000_dma_init(void __iomem *ioaddr,
-			       struct stmmac_dma_cfg *dma_cfg, int atds)
+static void dwmac1000_dma_init_channel(struct stmmac_priv *priv,
+				       void __iomem *ioaddr,
+				       struct stmmac_dma_cfg *dma_cfg, u32 chan)
 {
-	u32 value = readl(ioaddr + DMA_BUS_MODE);
+	u32 value;
 	int txpbl = dma_cfg->txpbl ?: dma_cfg->pbl;
 	int rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl;
 
-	/*
-	 * Set the DMA PBL (Programmable Burst Length) mode.
+	/* common channel control register config */
+	value = readl(ioaddr + DMA_CHAN_BUS_MODE(chan));
+
+	/* Set the DMA PBL (Programmable Burst Length) mode.
 	 *
 	 * Note: before stmmac core 3.50 this mode bit was 4xPBL, and
 	 * post 3.5 mode bit acts as 8*PBL.
@@ -98,16 +101,15 @@ static void dwmac1000_dma_init(void __iomem *ioaddr,
 	if (dma_cfg->mixed_burst)
 		value |= DMA_BUS_MODE_MB;
 
-	if (atds)
-		value |= DMA_BUS_MODE_ATDS;
+	value |= DMA_BUS_MODE_ATDS;
 
 	if (dma_cfg->aal)
 		value |= DMA_BUS_MODE_AAL;
 
-	writel(value, ioaddr + DMA_BUS_MODE);
+	writel(value, ioaddr + DMA_CHAN_BUS_MODE(chan));
 
 	/* Mask interrupts by writing to CSR7 */
-	writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_INTR_ENA);
+	writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_CHAN_INTR_ENA(chan));
 }
 
 static void dwmac1000_dma_init_rx(struct stmmac_priv *priv,
@@ -116,7 +118,7 @@ static void dwmac1000_dma_init_rx(struct stmmac_priv *priv,
 				  dma_addr_t dma_rx_phy, u32 chan)
 {
 	/* RX descriptor base address list must be written into DMA CSR3 */
-	writel(lower_32_bits(dma_rx_phy), ioaddr + DMA_RCV_BASE_ADDR);
+	writel(lower_32_bits(dma_rx_phy), ioaddr + DMA_CHAN_RCV_BASE_ADDR(chan));
 }
 
 static void dwmac1000_dma_init_tx(struct stmmac_priv *priv,
@@ -125,7 +127,7 @@ static void dwmac1000_dma_init_tx(struct stmmac_priv *priv,
 				  dma_addr_t dma_tx_phy, u32 chan)
 {
 	/* TX descriptor base address list must be written into DMA CSR4 */
-	writel(lower_32_bits(dma_tx_phy), ioaddr + DMA_TX_BASE_ADDR);
+	writel(lower_32_bits(dma_tx_phy), ioaddr + DMA_CHAN_TX_BASE_ADDR(chan));
 }
 
 static u32 dwmac1000_configure_fc(u32 csr6, int rxfifosz)
@@ -153,7 +155,7 @@ static void dwmac1000_dma_operation_mode_rx(struct stmmac_priv *priv,
 					    void __iomem *ioaddr, int mode,
 					    u32 channel, int fifosz, u8 qmode)
 {
-	u32 csr6 = readl(ioaddr + DMA_CONTROL);
+	u32 csr6 = readl(ioaddr + DMA_CHAN_CONTROL(channel));
 
 	if (mode == SF_DMA_MODE) {
 		pr_debug("GMAC: enable RX store and forward mode\n");
@@ -175,14 +177,14 @@ static void dwmac1000_dma_operation_mode_rx(struct stmmac_priv *priv,
 	/* Configure flow control based on rx fifo size */
 	csr6 = dwmac1000_configure_fc(csr6, fifosz);
 
-	writel(csr6, ioaddr + DMA_CONTROL);
+	writel(csr6, ioaddr + DMA_CHAN_CONTROL(channel));
 }
 
 static void dwmac1000_dma_operation_mode_tx(struct stmmac_priv *priv,
 					    void __iomem *ioaddr, int mode,
 					    u32 channel, int fifosz, u8 qmode)
 {
-	u32 csr6 = readl(ioaddr + DMA_CONTROL);
+	u32 csr6 = readl(ioaddr + DMA_CHAN_CONTROL(channel));
 
 	if (mode == SF_DMA_MODE) {
 		pr_debug("GMAC: enable TX store and forward mode\n");
@@ -209,7 +211,7 @@ static void dwmac1000_dma_operation_mode_tx(struct stmmac_priv *priv,
 			csr6 |= DMA_CONTROL_TTC_256;
 	}
 
-	writel(csr6, ioaddr + DMA_CONTROL);
+	writel(csr6, ioaddr + DMA_CHAN_CONTROL(channel));
 }
 
 static void dwmac1000_dump_dma_regs(struct stmmac_priv *priv,
@@ -271,12 +273,12 @@ static int dwmac1000_get_hw_feature(void __iomem *ioaddr,
 static void dwmac1000_rx_watchdog(struct stmmac_priv *priv,
 				  void __iomem *ioaddr, u32 riwt, u32 queue)
 {
-	writel(riwt, ioaddr + DMA_RX_WATCHDOG);
+	writel(riwt, ioaddr + DMA_CHAN_RX_WATCHDOG(queue));
 }
 
 const struct stmmac_dma_ops dwmac1000_dma_ops = {
 	.reset = dwmac_dma_reset,
-	.init = dwmac1000_dma_init,
+	.init_chan = dwmac1000_dma_init_channel,
 	.init_rx_chan = dwmac1000_dma_init_rx,
 	.init_tx_chan = dwmac1000_dma_init_tx,
 	.axi = dwmac1000_dma_axi,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
index 72672391675f..593be79c46e1 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
@@ -148,11 +148,14 @@
 					 DMA_STATUS_TI | \
 					 DMA_STATUS_MSK_COMMON)
 
+/* Following DMA defines are chanels oriented */
+#define DMA_CHAN_OFFSET			0x100
+
 #define NUM_DWMAC100_DMA_REGS	9
 #define NUM_DWMAC1000_DMA_REGS	23
 #define NUM_DWMAC4_DMA_REGS	27
 
-void dwmac_enable_dma_transmission(void __iomem *ioaddr);
+void dwmac_enable_dma_transmission(void __iomem *ioaddr, u32 chan);
 void dwmac_enable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr,
 			  u32 chan, bool rx, bool tx);
 void dwmac_disable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr,
@@ -169,4 +172,18 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
 			struct stmmac_extra_stats *x, u32 chan, u32 dir);
 int dwmac_dma_reset(void __iomem *ioaddr);
 
+static inline u32 dma_chan_base_addr(u32 base, u32 chan)
+{
+	return base + chan * DMA_CHAN_OFFSET;
+}
+
+#define DMA_CHAN_XMT_POLL_DEMAND(chan)	dma_chan_base_addr(DMA_XMT_POLL_DEMAND, chan)
+#define DMA_CHAN_INTR_ENA(chan)		dma_chan_base_addr(DMA_INTR_ENA, chan)
+#define DMA_CHAN_CONTROL(chan)		dma_chan_base_addr(DMA_CONTROL, chan)
+#define DMA_CHAN_STATUS(chan)		dma_chan_base_addr(DMA_STATUS, chan)
+#define DMA_CHAN_BUS_MODE(chan)		dma_chan_base_addr(DMA_BUS_MODE, chan)
+#define DMA_CHAN_RCV_BASE_ADDR(chan)	dma_chan_base_addr(DMA_RCV_BASE_ADDR, chan)
+#define DMA_CHAN_TX_BASE_ADDR(chan)	dma_chan_base_addr(DMA_TX_BASE_ADDR, chan)
+#define DMA_CHAN_RX_WATCHDOG(chan)	dma_chan_base_addr(DMA_RX_WATCHDOG, chan)
+
 #endif /* __DWMAC_DMA_H__ */
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
index 7907d62d3437..b37368137810 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
@@ -28,65 +28,65 @@ int dwmac_dma_reset(void __iomem *ioaddr)
 }
 
 /* CSR1 enables the transmit DMA to check for new descriptor */
-void dwmac_enable_dma_transmission(void __iomem *ioaddr)
+void dwmac_enable_dma_transmission(void __iomem *ioaddr, u32 chan)
 {
-	writel(1, ioaddr + DMA_XMT_POLL_DEMAND);
+	writel(1, ioaddr + DMA_CHAN_XMT_POLL_DEMAND(chan));
 }
 
 void dwmac_enable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr,
 			  u32 chan, bool rx, bool tx)
 {
-	u32 value = readl(ioaddr + DMA_INTR_ENA);
+	u32 value = readl(ioaddr + DMA_CHAN_INTR_ENA(chan));
 
 	if (rx)
 		value |= DMA_INTR_DEFAULT_RX;
 	if (tx)
 		value |= DMA_INTR_DEFAULT_TX;
 
-	writel(value, ioaddr + DMA_INTR_ENA);
+	writel(value, ioaddr + DMA_CHAN_INTR_ENA(chan));
 }
 
 void dwmac_disable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr,
 			   u32 chan, bool rx, bool tx)
 {
-	u32 value = readl(ioaddr + DMA_INTR_ENA);
+	u32 value = readl(ioaddr + DMA_CHAN_INTR_ENA(chan));
 
 	if (rx)
 		value &= ~DMA_INTR_DEFAULT_RX;
 	if (tx)
 		value &= ~DMA_INTR_DEFAULT_TX;
 
-	writel(value, ioaddr + DMA_INTR_ENA);
+	writel(value, ioaddr + DMA_CHAN_INTR_ENA(chan));
 }
 
 void dwmac_dma_start_tx(struct stmmac_priv *priv, void __iomem *ioaddr,
 			u32 chan)
 {
-	u32 value = readl(ioaddr + DMA_CONTROL);
+	u32 value = readl(ioaddr + DMA_CHAN_CONTROL(chan));
 	value |= DMA_CONTROL_ST;
-	writel(value, ioaddr + DMA_CONTROL);
+	writel(value, ioaddr + DMA_CHAN_CONTROL(chan));
 }
 
 void dwmac_dma_stop_tx(struct stmmac_priv *priv, void __iomem *ioaddr, u32 chan)
 {
-	u32 value = readl(ioaddr + DMA_CONTROL);
+	u32 value = readl(ioaddr + DMA_CHAN_CONTROL(chan));
 	value &= ~DMA_CONTROL_ST;
-	writel(value, ioaddr + DMA_CONTROL);
+	writel(value, ioaddr + DMA_CHAN_CONTROL(chan));
 }
 
 void dwmac_dma_start_rx(struct stmmac_priv *priv, void __iomem *ioaddr,
 			u32 chan)
 {
-	u32 value = readl(ioaddr + DMA_CONTROL);
+	u32 value = readl(ioaddr + DMA_CHAN_CONTROL(chan));
 	value |= DMA_CONTROL_SR;
-	writel(value, ioaddr + DMA_CONTROL);
+	writel(value, ioaddr + DMA_CHAN_CONTROL(chan));
 }
 
 void dwmac_dma_stop_rx(struct stmmac_priv *priv, void __iomem *ioaddr, u32 chan)
 {
-	u32 value = readl(ioaddr + DMA_CONTROL);
+	u32 value = readl(ioaddr + DMA_CHAN_CONTROL(chan));
 	value &= ~DMA_CONTROL_SR;
-	writel(value, ioaddr + DMA_CONTROL);
+	writel(value, ioaddr + DMA_CHAN_CONTROL(chan));
 }
 
 #ifdef DWMAC_DMA_DEBUG
@@ -166,7 +166,7 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
 	struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[chan];
 	int ret = 0;
 	/* read the status register (CSR5) */
-	u32 intr_status = readl(ioaddr + DMA_STATUS);
+	u32 intr_status = readl(ioaddr + DMA_CHAN_STATUS(chan));
 
 #ifdef DWMAC_DMA_DEBUG
 	/* Enable it to monitor DMA rx/tx status in case of critical problems */
@@ -236,7 +236,7 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
 		pr_warn("%s: unexpected status %08x\n", __func__, intr_status);
 
 	/* Clear the interrupt by writing a logic 1 to the CSR5[15-0] */
-	writel((intr_status & 0x1ffff), ioaddr + DMA_STATUS);
+	writel((intr_status & 0x7ffff), ioaddr + DMA_CHAN_STATUS(chan));
 
 	return ret;
 }
diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h
index 7be04b54738b..b0db38396171 100644
--- a/drivers/net/ethernet/stmicro/stmmac/hwif.h
+++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h
@@ -198,7 +198,7 @@ struct stmmac_dma_ops {
 	/* To track extra statistic (if supported) */
 	void (*dma_diagnostic_fr)(struct stmmac_extra_stats *x,
 				  void __iomem *ioaddr);
-	void (*enable_dma_transmission) (void __iomem *ioaddr);
+	void (*enable_dma_transmission)(void __iomem *ioaddr, u32 chan);
 	void (*enable_dma_irq)(struct stmmac_priv *priv, void __iomem *ioaddr,
 			       u32 chan, bool rx, bool tx);
 	void (*disable_dma_irq)(struct stmmac_priv *priv, void __iomem *ioaddr,
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index b334eb16da23..5617b40abbe4 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -2558,7 +2558,7 @@ static bool stmmac_xdp_xmit_zc(struct stmmac_priv *priv, u32 queue, u32 budget)
 				       true, priv->mode, true, true,
 				       xdp_desc.len);
 
-		stmmac_enable_dma_transmission(priv, priv->ioaddr);
+		stmmac_enable_dma_transmission(priv, priv->ioaddr, queue);
 
 		xsk_tx_metadata_to_compl(meta,
 					 &tx_q->tx_skbuff_dma[entry].xsk_meta);
@@ -4706,7 +4706,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	netdev_tx_sent_queue(netdev_get_tx_queue(dev, queue), skb->len);
 
-	stmmac_enable_dma_transmission(priv, priv->ioaddr);
+	stmmac_enable_dma_transmission(priv, priv->ioaddr, queue);
 
 	stmmac_flush_tx_descriptors(priv, queue);
 	stmmac_tx_timer_arm(priv, queue);
@@ -4926,7 +4926,7 @@ static int stmmac_xdp_xmit_xdpf(struct stmmac_priv *priv, int queue,
 		u64_stats_update_end_irqrestore(&txq_stats->syncp, flags);
 	}
 
-	stmmac_enable_dma_transmission(priv, priv->ioaddr);
+	stmmac_enable_dma_transmission(priv, priv->ioaddr, queue);
 
 	entry = STMMAC_GET_ENTRY(entry, priv->dma_conf.dma_tx_size);
 	tx_q->cur_tx = entry;
-- 
2.31.4


^ permalink raw reply related	[flat|nested] 97+ messages in thread

* [PATCH net-next v8 02/11] net: stmmac: dwmac-loongson: Refactor code for loongson_dwmac_probe()
  2024-01-30  8:43 [PATCH net-next v8 00/11] stmmac: Add Loongson platform support Yanteng Si
  2024-01-30  8:43 ` [PATCH net-next v8 01/11] net: stmmac: Add multi-channel support Yanteng Si
@ 2024-01-30  8:43 ` Yanteng Si
  2024-02-02 12:33   ` Simon Horman
  2024-02-05 14:43   ` Serge Semin
  2024-01-30  8:43 ` [PATCH net-next v8 03/11] net: stmmac: dwmac-loongson: Add full PCI support Yanteng Si
                   ` (10 subsequent siblings)
  12 siblings, 2 replies; 97+ messages in thread
From: Yanteng Si @ 2024-01-30  8:43 UTC (permalink / raw)
  To: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	fancer.lancer
  Cc: Yanteng Si, Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

The driver function is not changed, but the code location is
adjusted to prepare for adding more loongson drivers.

Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
---
 .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 61 +++++++++++++------
 1 file changed, 42 insertions(+), 19 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
index 9e40c28d453a..e2dcb339b8b0 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
@@ -9,7 +9,12 @@
 #include <linux/of_irq.h>
 #include "stmmac.h"
 
-static int loongson_default_data(struct plat_stmmacenet_data *plat)
+struct stmmac_pci_info {
+	int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat);
+};
+
+static void loongson_default_data(struct pci_dev *pdev,
+				  struct plat_stmmacenet_data *plat)
 {
 	plat->clk_csr = 2;	/* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */
 	plat->has_gmac = 1;
@@ -34,23 +39,37 @@ static int loongson_default_data(struct plat_stmmacenet_data *plat)
 
 	/* Disable RX queues routing by default */
 	plat->rx_queues_cfg[0].pkt_route = 0x0;
+}
+
+static int loongson_gmac_data(struct pci_dev *pdev,
+			      struct plat_stmmacenet_data *plat)
+{
+	loongson_default_data(pdev, plat);
+
+	plat->multicast_filter_bins = 256;
+
+	plat->mdio_bus_data->phy_mask = 0;
 
-	/* Default to phy auto-detection */
 	plat->phy_addr = -1;
 
 	plat->dma_cfg->pbl = 32;
 	plat->dma_cfg->pblx8 = true;
 
-	plat->multicast_filter_bins = 256;
 	return 0;
 }
 
-static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+static struct stmmac_pci_info loongson_gmac_pci_info = {
+	.setup = loongson_gmac_data,
+};
+
+static int loongson_dwmac_probe(struct pci_dev *pdev,
+				const struct pci_device_id *id)
 {
+	int ret, i, bus_id, phy_mode;
 	struct plat_stmmacenet_data *plat;
+	struct stmmac_pci_info *info;
 	struct stmmac_resources res;
 	struct device_node *np;
-	int ret, i, phy_mode;
 
 	np = dev_of_node(&pdev->dev);
 
@@ -69,18 +88,17 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
 	if (!plat->mdio_bus_data)
 		return -ENOMEM;
 
+	plat->dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*plat->dma_cfg),
+				     GFP_KERNEL);
+	if (!plat->dma_cfg)
+		return -ENOMEM;
+
 	plat->mdio_node = of_get_child_by_name(np, "mdio");
 	if (plat->mdio_node) {
 		dev_info(&pdev->dev, "Found MDIO subnode\n");
 		plat->mdio_bus_data->needs_reset = true;
 	}
 
-	plat->dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*plat->dma_cfg), GFP_KERNEL);
-	if (!plat->dma_cfg) {
-		ret = -ENOMEM;
-		goto err_put_node;
-	}
-
 	/* Enable pci device */
 	ret = pci_enable_device(pdev);
 	if (ret) {
@@ -98,9 +116,16 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
 		break;
 	}
 
-	plat->bus_id = of_alias_get_id(np, "ethernet");
-	if (plat->bus_id < 0)
-		plat->bus_id = pci_dev_id(pdev);
+	pci_set_master(pdev);
+
+	info = (struct stmmac_pci_info *)id->driver_data;
+	ret = info->setup(pdev, plat);
+	if (ret)
+		goto err_disable_device;
+
+	bus_id = of_alias_get_id(np, "ethernet");
+	if (bus_id >= 0)
+		plat->bus_id = bus_id;
 
 	phy_mode = device_get_phy_mode(&pdev->dev);
 	if (phy_mode < 0) {
@@ -110,11 +135,7 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
 	}
 
 	plat->phy_interface = phy_mode;
-	plat->mac_interface = PHY_INTERFACE_MODE_GMII;
 
-	pci_set_master(pdev);
-
-	loongson_default_data(plat);
 	pci_enable_msi(pdev);
 	memset(&res, 0, sizeof(res));
 	res.addr = pcim_iomap_table(pdev)[0];
@@ -212,8 +233,10 @@ static int __maybe_unused loongson_dwmac_resume(struct device *dev)
 static SIMPLE_DEV_PM_OPS(loongson_dwmac_pm_ops, loongson_dwmac_suspend,
 			 loongson_dwmac_resume);
 
+#define PCI_DEVICE_ID_LOONGSON_GMAC	0x7a03
+
 static const struct pci_device_id loongson_dwmac_id_table[] = {
-	{ PCI_VDEVICE(LOONGSON, 0x7a03) },
+	{ PCI_DEVICE_DATA(LOONGSON, GMAC, &loongson_gmac_pci_info) },
 	{}
 };
 MODULE_DEVICE_TABLE(pci, loongson_dwmac_id_table);
-- 
2.31.4


^ permalink raw reply related	[flat|nested] 97+ messages in thread

* [PATCH net-next v8 03/11] net: stmmac: dwmac-loongson: Add full PCI support
  2024-01-30  8:43 [PATCH net-next v8 00/11] stmmac: Add Loongson platform support Yanteng Si
  2024-01-30  8:43 ` [PATCH net-next v8 01/11] net: stmmac: Add multi-channel support Yanteng Si
  2024-01-30  8:43 ` [PATCH net-next v8 02/11] net: stmmac: dwmac-loongson: Refactor code for loongson_dwmac_probe() Yanteng Si
@ 2024-01-30  8:43 ` Yanteng Si
  2024-02-05 16:49   ` Serge Semin
  2024-01-30  8:43 ` [PATCH net-next v8 04/11] net: stmmac: dwmac-loongson: Move irq config to loongson_gmac_config Yanteng Si
                   ` (9 subsequent siblings)
  12 siblings, 1 reply; 97+ messages in thread
From: Yanteng Si @ 2024-01-30  8:43 UTC (permalink / raw)
  To: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	fancer.lancer
  Cc: Yanteng Si, Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

Current dwmac-loongson only support LS2K in the "probed with PCI and
configured with DT" manner. Add LS7A support on which the devices are
fully PCI (non-DT).

Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
---
 .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 79 +++++++++++--------
 1 file changed, 44 insertions(+), 35 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
index e2dcb339b8b0..979c9b6dab3f 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
@@ -16,6 +16,10 @@ struct stmmac_pci_info {
 static void loongson_default_data(struct pci_dev *pdev,
 				  struct plat_stmmacenet_data *plat)
 {
+	/* Get bus_id, this can be overloaded later */
+	plat->bus_id = (pci_domain_nr(pdev->bus) << 16) |
+		       PCI_DEVID(pdev->bus->number, pdev->devfn);
+
 	plat->clk_csr = 2;	/* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */
 	plat->has_gmac = 1;
 	plat->force_sf_dma_mode = 1;
@@ -51,10 +55,14 @@ static int loongson_gmac_data(struct pci_dev *pdev,
 	plat->mdio_bus_data->phy_mask = 0;
 
 	plat->phy_addr = -1;
+	plat->phy_interface = PHY_INTERFACE_MODE_RGMII_ID;
 
 	plat->dma_cfg->pbl = 32;
 	plat->dma_cfg->pblx8 = true;
 
+	plat->clk_ref_rate = 125000000;
+	plat->clk_ptp_rate = 125000000;
+
 	return 0;
 }
 
@@ -71,13 +79,6 @@ static int loongson_dwmac_probe(struct pci_dev *pdev,
 	struct stmmac_resources res;
 	struct device_node *np;
 
-	np = dev_of_node(&pdev->dev);
-
-	if (!np) {
-		pr_info("dwmac_loongson_pci: No OF node\n");
-		return -ENODEV;
-	}
-
 	plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL);
 	if (!plat)
 		return -ENOMEM;
@@ -93,6 +94,7 @@ static int loongson_dwmac_probe(struct pci_dev *pdev,
 	if (!plat->dma_cfg)
 		return -ENOMEM;
 
+	np = dev_of_node(&pdev->dev);
 	plat->mdio_node = of_get_child_by_name(np, "mdio");
 	if (plat->mdio_node) {
 		dev_info(&pdev->dev, "Found MDIO subnode\n");
@@ -123,41 +125,48 @@ static int loongson_dwmac_probe(struct pci_dev *pdev,
 	if (ret)
 		goto err_disable_device;
 
-	bus_id = of_alias_get_id(np, "ethernet");
-	if (bus_id >= 0)
-		plat->bus_id = bus_id;
+	if (np) {
+		bus_id = of_alias_get_id(np, "ethernet");
+		if (bus_id >= 0)
+			plat->bus_id = bus_id;
 
-	phy_mode = device_get_phy_mode(&pdev->dev);
-	if (phy_mode < 0) {
-		dev_err(&pdev->dev, "phy_mode not found\n");
-		ret = phy_mode;
-		goto err_disable_device;
+		phy_mode = device_get_phy_mode(&pdev->dev);
+		if (phy_mode < 0) {
+			dev_err(&pdev->dev, "phy_mode not found\n");
+			ret = phy_mode;
+			goto err_disable_device;
+		}
+		plat->phy_interface = phy_mode;
 	}
 
-	plat->phy_interface = phy_mode;
-
 	pci_enable_msi(pdev);
 	memset(&res, 0, sizeof(res));
 	res.addr = pcim_iomap_table(pdev)[0];
 
-	res.irq = of_irq_get_byname(np, "macirq");
-	if (res.irq < 0) {
-		dev_err(&pdev->dev, "IRQ macirq not found\n");
-		ret = -ENODEV;
-		goto err_disable_msi;
-	}
-
-	res.wol_irq = of_irq_get_byname(np, "eth_wake_irq");
-	if (res.wol_irq < 0) {
-		dev_info(&pdev->dev, "IRQ eth_wake_irq not found, using macirq\n");
-		res.wol_irq = res.irq;
-	}
-
-	res.lpi_irq = of_irq_get_byname(np, "eth_lpi");
-	if (res.lpi_irq < 0) {
-		dev_err(&pdev->dev, "IRQ eth_lpi not found\n");
-		ret = -ENODEV;
-		goto err_disable_msi;
+	if (np) {
+		res.irq = of_irq_get_byname(np, "macirq");
+		if (res.irq < 0) {
+			dev_err(&pdev->dev, "IRQ macirq not found\n");
+			ret = -ENODEV;
+			goto err_disable_msi;
+		}
+
+		res.wol_irq = of_irq_get_byname(np, "eth_wake_irq");
+		if (res.wol_irq < 0) {
+			dev_info(&pdev->dev,
+				 "IRQ eth_wake_irq not found, using macirq\n");
+			res.wol_irq = res.irq;
+		}
+
+		res.lpi_irq = of_irq_get_byname(np, "eth_lpi");
+		if (res.lpi_irq < 0) {
+			dev_err(&pdev->dev, "IRQ eth_lpi not found\n");
+			ret = -ENODEV;
+			goto err_disable_msi;
+		}
+	} else {
+		res.irq = pdev->irq;
+		res.wol_irq = pdev->irq;
 	}
 
 	ret = stmmac_dvr_probe(&pdev->dev, plat, &res);
-- 
2.31.4


^ permalink raw reply related	[flat|nested] 97+ messages in thread

* [PATCH net-next v8 04/11] net: stmmac: dwmac-loongson: Move irq config to loongson_gmac_config
  2024-01-30  8:43 [PATCH net-next v8 00/11] stmmac: Add Loongson platform support Yanteng Si
                   ` (2 preceding siblings ...)
  2024-01-30  8:43 ` [PATCH net-next v8 03/11] net: stmmac: dwmac-loongson: Add full PCI support Yanteng Si
@ 2024-01-30  8:43 ` Yanteng Si
  2024-02-05 17:01   ` Serge Semin
  2024-01-30  8:48 ` [PATCH net-next v8 05/11] net: stmmac: dwmac-loongson: Add Loongson-specific register definitions Yanteng Si
                   ` (8 subsequent siblings)
  12 siblings, 1 reply; 97+ messages in thread
From: Yanteng Si @ 2024-01-30  8:43 UTC (permalink / raw)
  To: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	fancer.lancer
  Cc: Yanteng Si, Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

Add loongson_dwmac_config and moving irq config related
code to loongson_dwmac_config.

Removing MSI to prepare for adding loongson multi-channel
support later.

Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
---
 .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 85 ++++++++++++-------
 1 file changed, 55 insertions(+), 30 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
index 979c9b6dab3f..e7ce027cc14e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
@@ -11,8 +11,46 @@
 
 struct stmmac_pci_info {
 	int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat);
+	int (*config)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat,
+		      struct stmmac_resources *res, struct device_node *np);
 };
 
+static int loongson_dwmac_config_legacy(struct pci_dev *pdev,
+					struct plat_stmmacenet_data *plat,
+					struct stmmac_resources *res,
+					struct device_node *np)
+{
+	if (np) {
+		res->irq = of_irq_get_byname(np, "macirq");
+		if (res->irq < 0) {
+			dev_err(&pdev->dev, "IRQ macirq not found\n");
+			return -ENODEV;
+		}
+
+		res->wol_irq = of_irq_get_byname(np, "eth_wake_irq");
+		if (res->wol_irq < 0) {
+			dev_info(&pdev->dev,
+				 "IRQ eth_wake_irq not found, using macirq\n");
+			res->wol_irq = res->irq;
+		}
+
+		res->lpi_irq = of_irq_get_byname(np, "eth_lpi");
+		if (res->lpi_irq < 0) {
+			dev_err(&pdev->dev, "IRQ eth_lpi not found\n");
+			return -ENODEV;
+		}
+	} else {
+		res->irq = pdev->irq;
+		res->wol_irq = res->irq;
+	}
+
+	plat->flags &= ~STMMAC_FLAG_MULTI_MSI_EN;
+	dev_info(&pdev->dev, "%s: Single IRQ enablement successful\n",
+		 __func__);
+
+	return 0;
+}
+
 static void loongson_default_data(struct pci_dev *pdev,
 				  struct plat_stmmacenet_data *plat)
 {
@@ -66,8 +104,21 @@ static int loongson_gmac_data(struct pci_dev *pdev,
 	return 0;
 }
 
+static int loongson_gmac_config(struct pci_dev *pdev,
+				struct plat_stmmacenet_data *plat,
+				struct stmmac_resources *res,
+				struct device_node *np)
+{
+	int ret;
+
+	ret = loongson_dwmac_config_legacy(pdev, plat, res, np);
+
+	return ret;
+}
+
 static struct stmmac_pci_info loongson_gmac_pci_info = {
 	.setup = loongson_gmac_data,
+	.config = loongson_gmac_config,
 };
 
 static int loongson_dwmac_probe(struct pci_dev *pdev,
@@ -139,44 +190,19 @@ static int loongson_dwmac_probe(struct pci_dev *pdev,
 		plat->phy_interface = phy_mode;
 	}
 
-	pci_enable_msi(pdev);
 	memset(&res, 0, sizeof(res));
 	res.addr = pcim_iomap_table(pdev)[0];
 
-	if (np) {
-		res.irq = of_irq_get_byname(np, "macirq");
-		if (res.irq < 0) {
-			dev_err(&pdev->dev, "IRQ macirq not found\n");
-			ret = -ENODEV;
-			goto err_disable_msi;
-		}
-
-		res.wol_irq = of_irq_get_byname(np, "eth_wake_irq");
-		if (res.wol_irq < 0) {
-			dev_info(&pdev->dev,
-				 "IRQ eth_wake_irq not found, using macirq\n");
-			res.wol_irq = res.irq;
-		}
-
-		res.lpi_irq = of_irq_get_byname(np, "eth_lpi");
-		if (res.lpi_irq < 0) {
-			dev_err(&pdev->dev, "IRQ eth_lpi not found\n");
-			ret = -ENODEV;
-			goto err_disable_msi;
-		}
-	} else {
-		res.irq = pdev->irq;
-		res.wol_irq = pdev->irq;
-	}
+	ret = info->config(pdev, plat, &res, np);
+	if (ret)
+		goto err_disable_device;
 
 	ret = stmmac_dvr_probe(&pdev->dev, plat, &res);
 	if (ret)
-		goto err_disable_msi;
+		goto err_disable_device;
 
 	return ret;
 
-err_disable_msi:
-	pci_disable_msi(pdev);
 err_disable_device:
 	pci_disable_device(pdev);
 err_put_node:
@@ -200,7 +226,6 @@ static void loongson_dwmac_remove(struct pci_dev *pdev)
 		break;
 	}
 
-	pci_disable_msi(pdev);
 	pci_disable_device(pdev);
 }
 
-- 
2.31.4


^ permalink raw reply related	[flat|nested] 97+ messages in thread

* [PATCH net-next v8 05/11] net: stmmac: dwmac-loongson: Add Loongson-specific register definitions
  2024-01-30  8:43 [PATCH net-next v8 00/11] stmmac: Add Loongson platform support Yanteng Si
                   ` (3 preceding siblings ...)
  2024-01-30  8:43 ` [PATCH net-next v8 04/11] net: stmmac: dwmac-loongson: Move irq config to loongson_gmac_config Yanteng Si
@ 2024-01-30  8:48 ` Yanteng Si
  2024-02-05 18:17   ` Serge Semin
  2024-01-30  8:48 ` [PATCH net-next v8 06/11] net: stmmac: dwmac-loongson: Add GNET support Yanteng Si
                   ` (7 subsequent siblings)
  12 siblings, 1 reply; 97+ messages in thread
From: Yanteng Si @ 2024-01-30  8:48 UTC (permalink / raw)
  To: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	fancer.lancer
  Cc: Yanteng Si, Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

There are two types of Loongson DWGMAC. The first type shares the same
register definitions and has similar logic as dwmac1000. The second type
uses several different register definitions, we think it is necessary to
distinguish rx and tx, so we split these bits into two.

Simply put, we split some single bit fields into double bits fileds:

     Name              Tx          Rx

DMA_INTR_ENA_NIE = 0x00040000 | 0x00020000;
DMA_INTR_ENA_AIE = 0x00010000 | 0x00008000;
DMA_STATUS_NIS   = 0x00040000 | 0x00020000;
DMA_STATUS_AIS   = 0x00010000 | 0x00008000;
DMA_STATUS_FBI   = 0x00002000 | 0x00001000;

Therefore, when using, TX and RX must be set at the same time.

How to use them:
1. Create the Loongson GNET-specific
stmmac_dma_ops.dma_interrupt()
stmmac_dma_ops.init_chan()
methods in the dwmac-loongson.c driver. Adding all the
Loongson-specific macros

2. Create a Loongson GNET-specific platform setup method with the next
semantics:
   + allocate stmmac_dma_ops instance and initialize it with
     dwmac1000_dma_ops.
   + override the stmmac_dma_ops.{dma_interrupt, init_chan} with
     the pointers to the methods defined in 2.
   + allocate mac_device_info instance and initialize the
     mac_device_info.dma field with a pointer to the new
     stmmac_dma_ops instance.
   + initialize mac_device_info in a way it's done in
     dwmac1000_setup().

3. Initialize plat_stmmacenet_data.setup() with the pointer to the
method created in 2.

Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
---
 .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 248 ++++++++++++++++++
 1 file changed, 248 insertions(+)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
index e7ce027cc14e..3b3578318cc1 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
@@ -8,6 +8,193 @@
 #include <linux/device.h>
 #include <linux/of_irq.h>
 #include "stmmac.h"
+#include "dwmac_dma.h"
+#include "dwmac1000.h"
+
+#define DMA_INTR_ENA_NIE_TX_LOONGSON 0x00040000	/* Normal Loongson Tx Summary */
+#define DMA_INTR_ENA_NIE_RX_LOONGSON 0x00020000	/* Normal Loongson Rx Summary */
+#define DMA_INTR_NORMAL_LOONGSON	(DMA_INTR_ENA_NIE_TX_LOONGSON | \
+			 DMA_INTR_ENA_NIE_RX_LOONGSON | DMA_INTR_ENA_RIE | \
+			 DMA_INTR_ENA_TIE)
+
+#define DMA_INTR_ENA_AIE_TX_LOONGSON 0x00010000	/* Abnormal Loongson Tx Summary */
+#define DMA_INTR_ENA_AIE_RX_LOONGSON 0x00008000	/* Abnormal Loongson Rx Summary */
+
+#define DMA_INTR_ABNORMAL_LOONGSON	(DMA_INTR_ENA_AIE_TX_LOONGSON | \
+				DMA_INTR_ENA_AIE_RX_LOONGSON | DMA_INTR_ENA_FBE | \
+				DMA_INTR_ENA_UNE)
+
+#define DMA_INTR_DEFAULT_MASK_LOONGSON	(DMA_INTR_NORMAL_LOONGSON | DMA_INTR_ABNORMAL_LOONGSON)
+
+#define DMA_STATUS_NIS_TX_LOONGSON	0x00040000	/* Normal Loongson Tx Interrupt Summary */
+#define DMA_STATUS_NIS_RX_LOONGSON	0x00020000	/* Normal Loongson Rx Interrupt Summary */
+
+#define DMA_STATUS_AIS_TX_LOONGSON	0x00010000	/* Abnormal Loongson Tx Interrupt Summary */
+#define DMA_STATUS_AIS_RX_LOONGSON	0x00008000	/* Abnormal Loongson Rx Interrupt Summary */
+
+#define DMA_STATUS_FBI_TX_LOONGSON	0x00002000	/* Fatal Loongson Tx Bus Error Interrupt */
+#define DMA_STATUS_FBI_RX_LOONGSON	0x00001000	/* Fatal Loongson Rx Bus Error Interrupt */
+
+#define DMA_STATUS_MSK_COMMON_LOONGSON		(DMA_STATUS_NIS_TX_LOONGSON | \
+					 DMA_STATUS_NIS_RX_LOONGSON | DMA_STATUS_AIS_TX_LOONGSON | \
+					 DMA_STATUS_AIS_RX_LOONGSON | DMA_STATUS_FBI_TX_LOONGSON | \
+					 DMA_STATUS_FBI_RX_LOONGSON)
+
+#define DMA_STATUS_MSK_RX_LOONGSON		(DMA_STATUS_ERI | \
+					 DMA_STATUS_RWT | \
+					 DMA_STATUS_RPS | \
+					 DMA_STATUS_RU | \
+					 DMA_STATUS_RI | \
+					 DMA_STATUS_OVF | \
+					 DMA_STATUS_MSK_COMMON_LOONGSON)
+
+#define DMA_STATUS_MSK_TX_LOONGSON		(DMA_STATUS_ETI | \
+					 DMA_STATUS_UNF | \
+					 DMA_STATUS_TJT | \
+					 DMA_STATUS_TU | \
+					 DMA_STATUS_TPS | \
+					 DMA_STATUS_TI | \
+					 DMA_STATUS_MSK_COMMON_LOONGSON)
+
+struct loongson_data {
+	struct device *dev;
+	u32 lgmac_version;
+	struct stmmac_dma_ops dwlgmac_dma_ops;
+};
+
+static void dwlgmac_dma_init_channel(struct stmmac_priv *priv,
+				     void __iomem *ioaddr,
+				     struct stmmac_dma_cfg *dma_cfg, u32 chan)
+{
+	u32 value;
+	int txpbl = dma_cfg->txpbl ?: dma_cfg->pbl;
+	int rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl;
+
+	/* common channel control register config */
+	value = readl(ioaddr + DMA_CHAN_BUS_MODE(chan));
+
+	/* Set the DMA PBL (Programmable Burst Length) mode.
+	 *
+	 * Note: before stmmac core 3.50 this mode bit was 4xPBL, and
+	 * post 3.5 mode bit acts as 8*PBL.
+	 */
+	if (dma_cfg->pblx8)
+		value |= DMA_BUS_MODE_MAXPBL;
+	value |= DMA_BUS_MODE_USP;
+	value &= ~(DMA_BUS_MODE_PBL_MASK | DMA_BUS_MODE_RPBL_MASK);
+	value |= (txpbl << DMA_BUS_MODE_PBL_SHIFT);
+	value |= (rxpbl << DMA_BUS_MODE_RPBL_SHIFT);
+
+	/* Set the Fixed burst mode */
+	if (dma_cfg->fixed_burst)
+		value |= DMA_BUS_MODE_FB;
+
+	/* Mixed Burst has no effect when fb is set */
+	if (dma_cfg->mixed_burst)
+		value |= DMA_BUS_MODE_MB;
+
+	value |= DMA_BUS_MODE_ATDS;
+
+	if (dma_cfg->aal)
+		value |= DMA_BUS_MODE_AAL;
+
+	writel(value, ioaddr + DMA_BUS_MODE);
+
+	/* Mask interrupts by writing to CSR7 */
+	writel(DMA_INTR_DEFAULT_MASK_LOONGSON, ioaddr + DMA_INTR_ENA);
+}
+
+static int dwlgmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
+				 struct stmmac_extra_stats *x, u32 chan, u32 dir)
+{
+	struct stmmac_rxq_stats *rxq_stats = &priv->xstats.rxq_stats[chan];
+	struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[chan];
+	int ret = 0;
+	/* read the status register (CSR5) */
+	u32 nor_intr_status;
+	u32 abnor_intr_status;
+	u32 fb_intr_status;
+	u32 intr_status = readl(ioaddr + DMA_CHAN_STATUS(chan));
+
+#ifdef DWMAC_DMA_DEBUG
+	/* Enable it to monitor DMA rx/tx status in case of critical problems */
+	pr_debug("%s: [CSR5: 0x%08x]\n", __func__, intr_status);
+	show_tx_process_state(intr_status);
+	show_rx_process_state(intr_status);
+#endif
+
+	if (dir == DMA_DIR_RX)
+		intr_status &= DMA_STATUS_MSK_RX_LOONGSON;
+	else if (dir == DMA_DIR_TX)
+		intr_status &= DMA_STATUS_MSK_TX_LOONGSON;
+
+	nor_intr_status = intr_status & (DMA_STATUS_NIS_TX_LOONGSON |
+		DMA_STATUS_NIS_RX_LOONGSON);
+	abnor_intr_status = intr_status & (DMA_STATUS_AIS_TX_LOONGSON |
+		DMA_STATUS_AIS_RX_LOONGSON);
+	fb_intr_status = intr_status & (DMA_STATUS_FBI_TX_LOONGSON |
+		DMA_STATUS_FBI_RX_LOONGSON);
+
+	/* ABNORMAL interrupts */
+	if (unlikely(abnor_intr_status)) {
+		if (unlikely(intr_status & DMA_STATUS_UNF)) {
+			ret = tx_hard_error_bump_tc;
+			x->tx_undeflow_irq++;
+		}
+		if (unlikely(intr_status & DMA_STATUS_TJT))
+			x->tx_jabber_irq++;
+
+		if (unlikely(intr_status & DMA_STATUS_OVF))
+			x->rx_overflow_irq++;
+
+		if (unlikely(intr_status & DMA_STATUS_RU))
+			x->rx_buf_unav_irq++;
+		if (unlikely(intr_status & DMA_STATUS_RPS))
+			x->rx_process_stopped_irq++;
+		if (unlikely(intr_status & DMA_STATUS_RWT))
+			x->rx_watchdog_irq++;
+		if (unlikely(intr_status & DMA_STATUS_ETI))
+			x->tx_early_irq++;
+		if (unlikely(intr_status & DMA_STATUS_TPS)) {
+			x->tx_process_stopped_irq++;
+			ret = tx_hard_error;
+		}
+		if (unlikely(intr_status & fb_intr_status)) {
+			x->fatal_bus_error_irq++;
+			ret = tx_hard_error;
+		}
+	}
+	/* TX/RX NORMAL interrupts */
+	if (likely(nor_intr_status)) {
+		if (likely(intr_status & DMA_STATUS_RI)) {
+			u32 value = readl(ioaddr + DMA_INTR_ENA);
+			/* to schedule NAPI on real RIE event. */
+			if (likely(value & DMA_INTR_ENA_RIE)) {
+				u64_stats_update_begin(&rxq_stats->syncp);
+				rxq_stats->rx_normal_irq_n++;
+				u64_stats_update_end(&rxq_stats->syncp);
+				ret |= handle_rx;
+			}
+		}
+		if (likely(intr_status & DMA_STATUS_TI)) {
+			u64_stats_update_begin(&txq_stats->syncp);
+			txq_stats->tx_normal_irq_n++;
+			u64_stats_update_end(&txq_stats->syncp);
+			ret |= handle_tx;
+		}
+		if (unlikely(intr_status & DMA_STATUS_ERI))
+			x->rx_early_irq++;
+	}
+	/* Optional hardware blocks, interrupts should be disabled */
+	if (unlikely(intr_status &
+		     (DMA_STATUS_GPI | DMA_STATUS_GMI | DMA_STATUS_GLI)))
+		pr_warn("%s: unexpected status %08x\n", __func__, intr_status);
+
+	/* Clear the interrupt by writing a logic 1 to the CSR5[15-0] */
+	writel((intr_status & 0x7ffff), ioaddr + DMA_CHAN_STATUS(chan));
+
+	return ret;
+}
 
 struct stmmac_pci_info {
 	int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat);
@@ -121,6 +308,48 @@ static struct stmmac_pci_info loongson_gmac_pci_info = {
 	.config = loongson_gmac_config,
 };
 
+static struct mac_device_info *loongson_setup(void *apriv)
+{
+	struct stmmac_priv *priv = apriv;
+	struct mac_device_info *mac;
+	struct loongson_data *ld;
+
+	mac = devm_kzalloc(priv->device, sizeof(*mac), GFP_KERNEL);
+	if (!mac)
+		return NULL;
+
+	ld = priv->plat->bsp_priv;
+	mac->dma = &ld->dwlgmac_dma_ops;
+
+	/* Pre-initialize the respective "mac" fields as it's done in
+	 * dwmac1000_setup()
+	 */
+	priv->dev->priv_flags |= IFF_UNICAST_FLT;
+	mac->pcsr = priv->ioaddr;
+	mac->multicast_filter_bins = priv->plat->multicast_filter_bins;
+	mac->unicast_filter_entries = priv->plat->unicast_filter_entries;
+	mac->mcast_bits_log2 = 0;
+
+	if (mac->multicast_filter_bins)
+		mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins);
+
+	mac->link.duplex = GMAC_CONTROL_DM;
+	mac->link.speed10 = GMAC_CONTROL_PS;
+	mac->link.speed100 = GMAC_CONTROL_PS | GMAC_CONTROL_FES;
+	mac->link.speed1000 = 0;
+	mac->link.speed_mask = GMAC_CONTROL_PS | GMAC_CONTROL_FES;
+	mac->mii.addr = GMAC_MII_ADDR;
+	mac->mii.data = GMAC_MII_DATA;
+	mac->mii.addr_shift = 11;
+	mac->mii.addr_mask = 0x0000F800;
+	mac->mii.reg_shift = 6;
+	mac->mii.reg_mask = 0x000007C0;
+	mac->mii.clk_csr_shift = 2;
+	mac->mii.clk_csr_mask = GENMASK(5, 2);
+
+	return mac;
+}
+
 static int loongson_dwmac_probe(struct pci_dev *pdev,
 				const struct pci_device_id *id)
 {
@@ -129,6 +358,7 @@ static int loongson_dwmac_probe(struct pci_dev *pdev,
 	struct stmmac_pci_info *info;
 	struct stmmac_resources res;
 	struct device_node *np;
+	struct loongson_data *ld;
 
 	plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL);
 	if (!plat)
@@ -145,6 +375,10 @@ static int loongson_dwmac_probe(struct pci_dev *pdev,
 	if (!plat->dma_cfg)
 		return -ENOMEM;
 
+	ld = devm_kzalloc(&pdev->dev, sizeof(*ld), GFP_KERNEL);
+	if (!ld)
+		return -ENOMEM;
+
 	np = dev_of_node(&pdev->dev);
 	plat->mdio_node = of_get_child_by_name(np, "mdio");
 	if (plat->mdio_node) {
@@ -197,6 +431,20 @@ static int loongson_dwmac_probe(struct pci_dev *pdev,
 	if (ret)
 		goto err_disable_device;
 
+	ld->dev = &pdev->dev;
+	ld->lgmac_version = readl(res.addr + GMAC_VERSION) & 0xff;
+
+	/* Activate loongson custom ip */
+	if (ld->lgmac_version < DWMAC_CORE_3_50) {
+		ld->dwlgmac_dma_ops = dwmac1000_dma_ops;
+		ld->dwlgmac_dma_ops.init_chan = dwlgmac_dma_init_channel;
+		ld->dwlgmac_dma_ops.dma_interrupt = dwlgmac_dma_interrupt;
+
+		plat->setup = loongson_setup;
+	}
+
+	plat->bsp_priv = ld;
+
 	ret = stmmac_dvr_probe(&pdev->dev, plat, &res);
 	if (ret)
 		goto err_disable_device;
-- 
2.31.4


^ permalink raw reply related	[flat|nested] 97+ messages in thread

* [PATCH net-next v8 06/11] net: stmmac: dwmac-loongson: Add GNET support
  2024-01-30  8:43 [PATCH net-next v8 00/11] stmmac: Add Loongson platform support Yanteng Si
                   ` (4 preceding siblings ...)
  2024-01-30  8:48 ` [PATCH net-next v8 05/11] net: stmmac: dwmac-loongson: Add Loongson-specific register definitions Yanteng Si
@ 2024-01-30  8:48 ` Yanteng Si
  2024-02-05 20:58   ` Serge Semin
  2024-01-30  8:48 ` [PATCH net-next v8 07/11] net: stmmac: dwmac-loongson: Add multi-channel supports for loongson Yanteng Si
                   ` (6 subsequent siblings)
  12 siblings, 1 reply; 97+ messages in thread
From: Yanteng Si @ 2024-01-30  8:48 UTC (permalink / raw)
  To: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	fancer.lancer
  Cc: Yanteng Si, Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

Add Loongson GNET (GMAC with PHY) support, override
stmmac_priv.synopsys_id with 0x37.

Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
---
 .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 44 +++++++++++++++++++
 1 file changed, 44 insertions(+)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
index 3b3578318cc1..584f7322bd3e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
@@ -318,6 +318,8 @@ static struct mac_device_info *loongson_setup(void *apriv)
 	if (!mac)
 		return NULL;
 
+	priv->synopsys_id = 0x37;	/*Overwrite custom IP*/
+
 	ld = priv->plat->bsp_priv;
 	mac->dma = &ld->dwlgmac_dma_ops;
 
@@ -350,6 +352,46 @@ static struct mac_device_info *loongson_setup(void *apriv)
 	return mac;
 }
 
+static int loongson_gnet_data(struct pci_dev *pdev,
+			      struct plat_stmmacenet_data *plat)
+{
+	loongson_default_data(pdev, plat);
+
+	plat->multicast_filter_bins = 256;
+
+	plat->mdio_bus_data->phy_mask =  ~(u32)BIT(2);
+
+	plat->phy_addr = 2;
+	plat->phy_interface = PHY_INTERFACE_MODE_INTERNAL;
+
+	plat->bsp_priv = &pdev->dev;
+
+	plat->dma_cfg->pbl = 32;
+	plat->dma_cfg->pblx8 = true;
+
+	plat->clk_ref_rate = 125000000;
+	plat->clk_ptp_rate = 125000000;
+
+	return 0;
+}
+
+static int loongson_gnet_config(struct pci_dev *pdev,
+				struct plat_stmmacenet_data *plat,
+				struct stmmac_resources *res,
+				struct device_node *np)
+{
+	int ret;
+
+	ret = loongson_dwmac_config_legacy(pdev, plat, res, np);
+
+	return ret;
+}
+
+static struct stmmac_pci_info loongson_gnet_pci_info = {
+	.setup = loongson_gnet_data,
+	.config = loongson_gnet_config,
+};
+
 static int loongson_dwmac_probe(struct pci_dev *pdev,
 				const struct pci_device_id *id)
 {
@@ -516,9 +558,11 @@ static SIMPLE_DEV_PM_OPS(loongson_dwmac_pm_ops, loongson_dwmac_suspend,
 			 loongson_dwmac_resume);
 
 #define PCI_DEVICE_ID_LOONGSON_GMAC	0x7a03
+#define PCI_DEVICE_ID_LOONGSON_GNET	0x7a13
 
 static const struct pci_device_id loongson_dwmac_id_table[] = {
 	{ PCI_DEVICE_DATA(LOONGSON, GMAC, &loongson_gmac_pci_info) },
+	{ PCI_DEVICE_DATA(LOONGSON, GNET, &loongson_gnet_pci_info) },
 	{}
 };
 MODULE_DEVICE_TABLE(pci, loongson_dwmac_id_table);
-- 
2.31.4


^ permalink raw reply related	[flat|nested] 97+ messages in thread

* [PATCH net-next v8 07/11] net: stmmac: dwmac-loongson: Add multi-channel supports for loongson
  2024-01-30  8:43 [PATCH net-next v8 00/11] stmmac: Add Loongson platform support Yanteng Si
                   ` (5 preceding siblings ...)
  2024-01-30  8:48 ` [PATCH net-next v8 06/11] net: stmmac: dwmac-loongson: Add GNET support Yanteng Si
@ 2024-01-30  8:48 ` Yanteng Si
  2024-02-05 21:28   ` Serge Semin
  2024-01-30  8:48 ` [PATCH net-next v8 08/11] net: stmmac: dwmac-loongson: Fix MAC speed for GNET Yanteng Si
                   ` (5 subsequent siblings)
  12 siblings, 1 reply; 97+ messages in thread
From: Yanteng Si @ 2024-01-30  8:48 UTC (permalink / raw)
  To: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	fancer.lancer
  Cc: Yanteng Si, Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

Request allocation for MSI for specific versions.

Some features of Loongson platforms are bound to the GMAC_VERSION
register. We have to read its value in order to get the correct channel
number.

Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
---
 .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 57 +++++++++++++++----
 1 file changed, 46 insertions(+), 11 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
index 584f7322bd3e..60d0a122d7c9 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
@@ -98,10 +98,10 @@ static void dwlgmac_dma_init_channel(struct stmmac_priv *priv,
 	if (dma_cfg->aal)
 		value |= DMA_BUS_MODE_AAL;
 
-	writel(value, ioaddr + DMA_BUS_MODE);
+	writel(value, ioaddr + DMA_CHAN_BUS_MODE(chan));
 
 	/* Mask interrupts by writing to CSR7 */
-	writel(DMA_INTR_DEFAULT_MASK_LOONGSON, ioaddr + DMA_INTR_ENA);
+	writel(DMA_INTR_DEFAULT_MASK_LOONGSON, ioaddr + DMA_CHAN_INTR_ENA(chan));
 }
 
 static int dwlgmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
@@ -238,6 +238,45 @@ static int loongson_dwmac_config_legacy(struct pci_dev *pdev,
 	return 0;
 }
 
+static int loongson_dwmac_config_multi_msi(struct pci_dev *pdev,
+					   struct plat_stmmacenet_data *plat,
+					   struct stmmac_resources *res,
+					   struct device_node *np,
+					   int channel_num)
+{
+	int i, ret, vecs;
+
+	vecs = roundup_pow_of_two(channel_num * 2 + 1);
+	ret = pci_alloc_irq_vectors(pdev, vecs, vecs, PCI_IRQ_MSI);
+	if (ret < 0) {
+		dev_info(&pdev->dev,
+			 "MSI enable failed, Fallback to legacy interrupt\n");
+		return loongson_dwmac_config_legacy(pdev, plat, res, np);
+	}
+
+	plat->rx_queues_to_use = channel_num;
+	plat->tx_queues_to_use = channel_num;
+
+	res->irq = pci_irq_vector(pdev, 0);
+	res->wol_irq = res->irq;
+
+	/* INT NAME | MAC | CH7 rx | CH7 tx | ... | CH0 rx | CH0 tx |
+	 * --------- ----- -------- --------  ...  -------- --------
+	 * IRQ NUM  |  0  |   1    |   2    | ... |   15   |   16   |
+	 */
+	for (i = 0; i < channel_num; i++) {
+		res->rx_irq[channel_num - 1 - i] =
+			pci_irq_vector(pdev, 1 + i * 2);
+		res->tx_irq[channel_num - 1 - i] =
+			pci_irq_vector(pdev, 2 + i * 2);
+	}
+
+	plat->flags |= STMMAC_FLAG_MULTI_MSI_EN;
+	dev_info(&pdev->dev, "%s: multi MSI enablement successful\n", __func__);
+
+	return 0;
+}
+
 static void loongson_default_data(struct pci_dev *pdev,
 				  struct plat_stmmacenet_data *plat)
 {
@@ -296,11 +335,8 @@ static int loongson_gmac_config(struct pci_dev *pdev,
 				struct stmmac_resources *res,
 				struct device_node *np)
 {
-	int ret;
-
-	ret = loongson_dwmac_config_legacy(pdev, plat, res, np);
 
-	return ret;
+	return 0;
 }
 
 static struct stmmac_pci_info loongson_gmac_pci_info = {
@@ -380,11 +416,7 @@ static int loongson_gnet_config(struct pci_dev *pdev,
 				struct stmmac_resources *res,
 				struct device_node *np)
 {
-	int ret;
-
-	ret = loongson_dwmac_config_legacy(pdev, plat, res, np);
-
-	return ret;
+	return 0;
 }
 
 static struct stmmac_pci_info loongson_gnet_pci_info = {
@@ -483,6 +515,9 @@ static int loongson_dwmac_probe(struct pci_dev *pdev,
 		ld->dwlgmac_dma_ops.dma_interrupt = dwlgmac_dma_interrupt;
 
 		plat->setup = loongson_setup;
+		ret = loongson_dwmac_config_multi_msi(pdev, plat, &res, np, 8);
+	} else {
+		ret = loongson_dwmac_config_legacy(pdev, plat, &res, np);
 	}
 
 	plat->bsp_priv = ld;
-- 
2.31.4


^ permalink raw reply related	[flat|nested] 97+ messages in thread

* [PATCH net-next v8 08/11] net: stmmac: dwmac-loongson: Fix MAC speed for GNET
  2024-01-30  8:43 [PATCH net-next v8 00/11] stmmac: Add Loongson platform support Yanteng Si
                   ` (6 preceding siblings ...)
  2024-01-30  8:48 ` [PATCH net-next v8 07/11] net: stmmac: dwmac-loongson: Add multi-channel supports for loongson Yanteng Si
@ 2024-01-30  8:48 ` Yanteng Si
  2024-02-05 21:55   ` Serge Semin
  2024-01-30  8:49 ` [PATCH net-next v8 09/11] net: stmmac: dwmac-loongson: Fix half duplex Yanteng Si
                   ` (4 subsequent siblings)
  12 siblings, 1 reply; 97+ messages in thread
From: Yanteng Si @ 2024-01-30  8:48 UTC (permalink / raw)
  To: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	fancer.lancer
  Cc: Yanteng Si, Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

Current GNET on LS7A only supports ANE when speed is
set to 1000M.

Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
---
 .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 19 +++++++++++++++++++
 .../ethernet/stmicro/stmmac/stmmac_ethtool.c  |  6 ++++++
 include/linux/stmmac.h                        |  1 +
 3 files changed, 26 insertions(+)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
index 60d0a122d7c9..264c4c198d5a 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
@@ -344,6 +344,21 @@ static struct stmmac_pci_info loongson_gmac_pci_info = {
 	.config = loongson_gmac_config,
 };
 
+static void loongson_gnet_fix_speed(void *priv, unsigned int speed, unsigned int mode)
+{
+	struct loongson_data *ld = (struct loongson_data *)priv;
+	struct net_device *ndev = dev_get_drvdata(ld->dev);
+	struct stmmac_priv *ptr = netdev_priv(ndev);
+
+	/* The controller and PHY don't work well together.
+	 * We need to use the PS bit to check if the controller's status
+	 * is correct and reset PHY if necessary.
+	 */
+	if (speed == SPEED_1000)
+		if (readl(ptr->ioaddr + MAC_CTRL_REG) & (1 << 15) /* PS */)
+			phy_restart_aneg(ndev->phydev);
+}
+
 static struct mac_device_info *loongson_setup(void *apriv)
 {
 	struct stmmac_priv *priv = apriv;
@@ -401,6 +416,7 @@ static int loongson_gnet_data(struct pci_dev *pdev,
 	plat->phy_interface = PHY_INTERFACE_MODE_INTERNAL;
 
 	plat->bsp_priv = &pdev->dev;
+	plat->fix_mac_speed = loongson_gnet_fix_speed;
 
 	plat->dma_cfg->pbl = 32;
 	plat->dma_cfg->pblx8 = true;
@@ -416,6 +432,9 @@ static int loongson_gnet_config(struct pci_dev *pdev,
 				struct stmmac_resources *res,
 				struct device_node *np)
 {
+	if (pdev->revision == 0x00 || pdev->revision == 0x01)
+		plat->flags |= STMMAC_FLAG_DISABLE_FORCE_1000;
+
 	return 0;
 }
 
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
index 42d27b97dd1d..31068fbc23c9 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
@@ -422,6 +422,12 @@ stmmac_ethtool_set_link_ksettings(struct net_device *dev,
 		return 0;
 	}
 
+	if (FIELD_GET(STMMAC_FLAG_DISABLE_FORCE_1000, priv->plat->flags)) {
+		if (cmd->base.speed == SPEED_1000 &&
+		    cmd->base.autoneg != AUTONEG_ENABLE)
+			return -EOPNOTSUPP;
+	}
+
 	return phylink_ethtool_ksettings_set(priv->phylink, cmd);
 }
 
diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
index dee5ad6e48c5..2810361e4048 100644
--- a/include/linux/stmmac.h
+++ b/include/linux/stmmac.h
@@ -221,6 +221,7 @@ struct dwmac4_addrs {
 #define STMMAC_FLAG_RX_CLK_RUNS_IN_LPI		BIT(10)
 #define STMMAC_FLAG_EN_TX_LPI_CLOCKGATING	BIT(11)
 #define STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY	BIT(12)
+#define STMMAC_FLAG_DISABLE_FORCE_1000	BIT(13)
 
 struct plat_stmmacenet_data {
 	int bus_id;
-- 
2.31.4


^ permalink raw reply related	[flat|nested] 97+ messages in thread

* [PATCH net-next v8 09/11] net: stmmac: dwmac-loongson: Fix half duplex
  2024-01-30  8:43 [PATCH net-next v8 00/11] stmmac: Add Loongson platform support Yanteng Si
                   ` (7 preceding siblings ...)
  2024-01-30  8:48 ` [PATCH net-next v8 08/11] net: stmmac: dwmac-loongson: Fix MAC speed for GNET Yanteng Si
@ 2024-01-30  8:49 ` Yanteng Si
  2024-02-05 21:58   ` Serge Semin
  2024-01-30  8:49 ` [PATCH net-next v8 10/11] net: stmmac: dwmac-loongson: Disable flow control for GMAC Yanteng Si
                   ` (3 subsequent siblings)
  12 siblings, 1 reply; 97+ messages in thread
From: Yanteng Si @ 2024-01-30  8:49 UTC (permalink / raw)
  To: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	fancer.lancer
  Cc: Yanteng Si, Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

Current GNET does not support half duplex mode.

Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
---
 drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c | 11 ++++++++++-
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c    |  3 ++-
 include/linux/stmmac.h                               |  1 +
 3 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
index 264c4c198d5a..1753a3c46b77 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
@@ -432,8 +432,17 @@ static int loongson_gnet_config(struct pci_dev *pdev,
 				struct stmmac_resources *res,
 				struct device_node *np)
 {
-	if (pdev->revision == 0x00 || pdev->revision == 0x01)
+	switch (pdev->revision) {
+	case 0x00:
+		plat->flags |= STMMAC_FLAG_DISABLE_FORCE_1000 |
+			       STMMAC_FLAG_DISABLE_HALF_DUPLEX;
+		break;
+	case 0x01:
 		plat->flags |= STMMAC_FLAG_DISABLE_FORCE_1000;
+		break;
+	default:
+		break;
+	}
 
 	return 0;
 }
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 5617b40abbe4..3aa862269eb0 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -1201,7 +1201,8 @@ static int stmmac_init_phy(struct net_device *dev)
 static void stmmac_set_half_duplex(struct stmmac_priv *priv)
 {
 	/* Half-Duplex can only work with single tx queue */
-	if (priv->plat->tx_queues_to_use > 1)
+	if (priv->plat->tx_queues_to_use > 1 ||
+	    (STMMAC_FLAG_DISABLE_HALF_DUPLEX & priv->plat->flags))
 		priv->phylink_config.mac_capabilities &=
 			~(MAC_10HD | MAC_100HD | MAC_1000HD);
 	else
diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
index 2810361e4048..197f6f914104 100644
--- a/include/linux/stmmac.h
+++ b/include/linux/stmmac.h
@@ -222,6 +222,7 @@ struct dwmac4_addrs {
 #define STMMAC_FLAG_EN_TX_LPI_CLOCKGATING	BIT(11)
 #define STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY	BIT(12)
 #define STMMAC_FLAG_DISABLE_FORCE_1000	BIT(13)
+#define STMMAC_FLAG_DISABLE_HALF_DUPLEX	BIT(14)
 
 struct plat_stmmacenet_data {
 	int bus_id;
-- 
2.31.4


^ permalink raw reply related	[flat|nested] 97+ messages in thread

* [PATCH net-next v8 10/11] net: stmmac: dwmac-loongson: Disable flow control for GMAC
  2024-01-30  8:43 [PATCH net-next v8 00/11] stmmac: Add Loongson platform support Yanteng Si
                   ` (8 preceding siblings ...)
  2024-01-30  8:49 ` [PATCH net-next v8 09/11] net: stmmac: dwmac-loongson: Fix half duplex Yanteng Si
@ 2024-01-30  8:49 ` Yanteng Si
  2024-02-05 22:13   ` Serge Semin
  2024-01-30  8:49 ` [PATCH net-next v8 11/11] net: stmmac: dwmac-loongson: Disable coe for some Loongson GNET Yanteng Si
                   ` (2 subsequent siblings)
  12 siblings, 1 reply; 97+ messages in thread
From: Yanteng Si @ 2024-01-30  8:49 UTC (permalink / raw)
  To: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	fancer.lancer
  Cc: Yanteng Si, Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

Loongson GMAC does not support Flow Control feature. Set flags to
disable it.

Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
---
 drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c | 1 +
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c    | 6 +++---
 include/linux/stmmac.h                               | 1 +
 3 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
index 1753a3c46b77..b78a73ea748b 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
@@ -335,6 +335,7 @@ static int loongson_gmac_config(struct pci_dev *pdev,
 				struct stmmac_resources *res,
 				struct device_node *np)
 {
+	plat->flags |= STMMAC_FLAG_DISABLE_FLOW_CONTROL;
 
 	return 0;
 }
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 3aa862269eb0..8d676cbfba1e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -1237,9 +1237,9 @@ static int stmmac_phy_setup(struct stmmac_priv *priv)
 		xpcs_get_interfaces(priv->hw->xpcs,
 				    priv->phylink_config.supported_interfaces);
 
-	priv->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
-						MAC_10FD | MAC_100FD |
-						MAC_1000FD;
+	priv->phylink_config.mac_capabilities = MAC_10FD | MAC_100FD | MAC_1000FD;
+	if (!(priv->plat->flags & STMMAC_FLAG_DISABLE_FLOW_CONTROL))
+		priv->phylink_config.mac_capabilities |= MAC_ASYM_PAUSE | MAC_SYM_PAUSE;
 
 	stmmac_set_half_duplex(priv);
 
diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
index 197f6f914104..832cd8cd688f 100644
--- a/include/linux/stmmac.h
+++ b/include/linux/stmmac.h
@@ -223,6 +223,7 @@ struct dwmac4_addrs {
 #define STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY	BIT(12)
 #define STMMAC_FLAG_DISABLE_FORCE_1000	BIT(13)
 #define STMMAC_FLAG_DISABLE_HALF_DUPLEX	BIT(14)
+#define STMMAC_FLAG_DISABLE_FLOW_CONTROL	BIT(15)
 
 struct plat_stmmacenet_data {
 	int bus_id;
-- 
2.31.4


^ permalink raw reply related	[flat|nested] 97+ messages in thread

* [PATCH net-next v8 11/11] net: stmmac: dwmac-loongson: Disable coe for some Loongson GNET
  2024-01-30  8:43 [PATCH net-next v8 00/11] stmmac: Add Loongson platform support Yanteng Si
                   ` (9 preceding siblings ...)
  2024-01-30  8:49 ` [PATCH net-next v8 10/11] net: stmmac: dwmac-loongson: Disable flow control for GMAC Yanteng Si
@ 2024-01-30  8:49 ` Yanteng Si
  2024-02-05 22:18   ` Serge Semin
  2024-01-30  9:57 ` [PATCH net-next v8 00/11] stmmac: Add Loongson platform support Serge Semin
  2024-01-31  2:10 ` Jakub Kicinski
  12 siblings, 1 reply; 97+ messages in thread
From: Yanteng Si @ 2024-01-30  8:49 UTC (permalink / raw)
  To: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	fancer.lancer
  Cc: Yanteng Si, Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

Some chips of Loongson GNET does not support coe, so disable them.

Set dma_cap->tx_coe to 0 and overwrite get_hw_feature.

Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
---
 .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 46 +++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
index b78a73ea748b..8018d7d5f31b 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
@@ -196,6 +196,51 @@ static int dwlgmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
 	return ret;
 }
 
+static int dwlgmac_get_hw_feature(void __iomem *ioaddr,
+				  struct dma_features *dma_cap)
+{
+	u32 hw_cap = readl(ioaddr + DMA_HW_FEATURE);
+
+	if (!hw_cap) {
+		/* 0x00000000 is the value read on old hardware that does not
+		 * implement this register
+		 */
+		return -EOPNOTSUPP;
+	}
+
+	dma_cap->mbps_10_100 = (hw_cap & DMA_HW_FEAT_MIISEL);
+	dma_cap->mbps_1000 = (hw_cap & DMA_HW_FEAT_GMIISEL) >> 1;
+	dma_cap->half_duplex = (hw_cap & DMA_HW_FEAT_HDSEL) >> 2;
+	dma_cap->hash_filter = (hw_cap & DMA_HW_FEAT_HASHSEL) >> 4;
+	dma_cap->multi_addr = (hw_cap & DMA_HW_FEAT_ADDMAC) >> 5;
+	dma_cap->pcs = (hw_cap & DMA_HW_FEAT_PCSSEL) >> 6;
+	dma_cap->sma_mdio = (hw_cap & DMA_HW_FEAT_SMASEL) >> 8;
+	dma_cap->pmt_remote_wake_up = (hw_cap & DMA_HW_FEAT_RWKSEL) >> 9;
+	dma_cap->pmt_magic_frame = (hw_cap & DMA_HW_FEAT_MGKSEL) >> 10;
+	/* MMC */
+	dma_cap->rmon = (hw_cap & DMA_HW_FEAT_MMCSEL) >> 11;
+	/* IEEE 1588-2002 */
+	dma_cap->time_stamp =
+	    (hw_cap & DMA_HW_FEAT_TSVER1SEL) >> 12;
+	/* IEEE 1588-2008 */
+	dma_cap->atime_stamp = (hw_cap & DMA_HW_FEAT_TSVER2SEL) >> 13;
+	/* 802.3az - Energy-Efficient Ethernet (EEE) */
+	dma_cap->eee = (hw_cap & DMA_HW_FEAT_EEESEL) >> 14;
+	dma_cap->av = (hw_cap & DMA_HW_FEAT_AVSEL) >> 15;
+	/* TX and RX csum */
+	dma_cap->tx_coe = 0;
+	dma_cap->rx_coe_type1 = (hw_cap & DMA_HW_FEAT_RXTYP1COE) >> 17;
+	dma_cap->rx_coe_type2 = (hw_cap & DMA_HW_FEAT_RXTYP2COE) >> 18;
+	dma_cap->rxfifo_over_2048 = (hw_cap & DMA_HW_FEAT_RXFIFOSIZE) >> 19;
+	/* TX and RX number of channels */
+	dma_cap->number_rx_channel = (hw_cap & DMA_HW_FEAT_RXCHCNT) >> 20;
+	dma_cap->number_tx_channel = (hw_cap & DMA_HW_FEAT_TXCHCNT) >> 22;
+	/* Alternate (enhanced) DESC mode */
+	dma_cap->enh_desc = (hw_cap & DMA_HW_FEAT_ENHDESSEL) >> 24;
+
+	return 0;
+}
+
 struct stmmac_pci_info {
 	int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat);
 	int (*config)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat,
@@ -542,6 +587,7 @@ static int loongson_dwmac_probe(struct pci_dev *pdev,
 		ld->dwlgmac_dma_ops = dwmac1000_dma_ops;
 		ld->dwlgmac_dma_ops.init_chan = dwlgmac_dma_init_channel;
 		ld->dwlgmac_dma_ops.dma_interrupt = dwlgmac_dma_interrupt;
+		ld->dwlgmac_dma_ops.get_hw_feature = dwlgmac_get_hw_feature;
 
 		plat->setup = loongson_setup;
 		ret = loongson_dwmac_config_multi_msi(pdev, plat, &res, np, 8);
-- 
2.31.4


^ permalink raw reply related	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 00/11] stmmac: Add Loongson platform support
  2024-01-30  8:43 [PATCH net-next v8 00/11] stmmac: Add Loongson platform support Yanteng Si
                   ` (10 preceding siblings ...)
  2024-01-30  8:49 ` [PATCH net-next v8 11/11] net: stmmac: dwmac-loongson: Disable coe for some Loongson GNET Yanteng Si
@ 2024-01-30  9:57 ` Serge Semin
  2024-01-31  2:10 ` Jakub Kicinski
  12 siblings, 0 replies; 97+ messages in thread
From: Serge Semin @ 2024-01-30  9:57 UTC (permalink / raw)
  To: Yanteng Si
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

Hi Yanteng

On Tue, Jan 30, 2024 at 04:43:20PM +0800, Yanteng Si wrote:
> v8:
> * The biggest change is according to Serge's comment in the previous
>   edition:
>    Seeing the patch in the current state would overcomplicate the generic
>    code and the only functions you need to update are
>    dwmac_dma_interrupt()
>    dwmac1000_dma_init_channel()
>    you can have these methods re-defined with all the Loongson GNET
>    specifics in the low-level platform driver (dwmac-loongson.c). After
>    that you can just override the mac_device_info.dma pointer with a
>    fixed stmmac_dma_ops descriptor. Here is what should be done for that:
> 
>    1. Keep the Patch 4/9 with my comments fixed. First it will be partly
>    useful for your GNET device. Second in general it's a correct
>    implementation of the normal DW GMAC v3.x multi-channels feature and
>    will be useful for the DW GMACs with that feature enabled.
> 
>    2. Create the Loongson GNET-specific
>    stmmac_dma_ops.dma_interrupt()
>    stmmac_dma_ops.init_chan()
>    methods in the dwmac-loongson.c driver. Don't forget to move all the
>    Loongson-specific macros from dwmac_dma.h to dwmac-loongson.c.
> 
>    3. Create a Loongson GNET-specific platform setup method with the next
>    semantics:
>       + allocate stmmac_dma_ops instance and initialize it with
>         dwmac1000_dma_ops.
>       + override the stmmac_dma_ops.{dma_interrupt, init_chan} with
>         the pointers to the methods defined in 2.
>       + allocate mac_device_info instance and initialize the
>         mac_device_info.dma field with a pointer to the new
>         stmmac_dma_ops instance.
>       + call dwmac1000_setup() or initialize mac_device_info in a way
>         it's done in dwmac1000_setup() (the later might be better so you
>         wouldn't need to export the dwmac1000_setup() function).
>       + override stmmac_priv.synopsys_id with a correct value.
> 
>    4. Initialize plat_stmmacenet_data.setup() with the pointer to the
>    method created in 3.
> 
> * Others:
>   Re-split the patch.
>   Passed checkpatch.pl test.

Thanks for the updated series. I'll have a look at it later on this
week or early on the next one.

-Serge(y)

> 
> v7:
> * Refer to andrew's suggestion:
>   - Add DMA_INTR_ENA_NIE_RX and DMA_INTR_ENA_NIE_TX #define's, etc.
> 
> * Others:
>   - Using --subject-prefix="PATCH net-next vN" to indicate that the
>     patches are for the networking tree.
>   - Rebase to the latest networking tree:
>     <git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git>
> 
> 
> v6:
> 
> * Refer to Serge's suggestion:
>   - Add new platform feature flag:
>     include/linux/stmmac.h:
>     +#define STMMAC_FLAG_HAS_LGMAC			BIT(13)
> 
>   - Add the IRQs macros specific to the Loongson Multi-channels GMAC:
>      drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h:
>      +#define DMA_INTR_ENA_NIE_LOONGSON 0x00060000      /* ...*/
>      #define DMA_INTR_ENA_NIE 0x00010000	/* Normal Summary */
>      ...
> 
>   - Drop all of redundant changes that don't require the
>     prototypes being converted to accepting the stmmac_priv
>     pointer.
> 
> * Refer to andrew's suggestion:
>   - Drop white space changes.
>   - break patch up into lots of smaller parts.
>      Some small patches have been put into another series as a preparation
>      see <https://lore.kernel.org/loongarch/cover.1702289232.git.siyanteng@loongson.cn/T/#t>
>      
>      *note* : This series of patches relies on the three small patches above.
> * others
>   - Drop irq_flags changes.
>   - Changed patch order.
> 
> 
> v4 -> v5:
> 
> * Remove an ugly and useless patch (fix channel number).
> * Remove the non-standard dma64 driver code, and also remove
>   the HWIF entries, since the associated custom callbacks no
>   longer exist.
> * Refer to Serge's suggestion: Update the dwmac1000_dma.c to
>   support the multi-DMA-channels controller setup.
> 
> See:
> v4: <https://lore.kernel.org/loongarch/cover.1692696115.git.chenfeiyang@loongson.cn/>
> v3: <https://lore.kernel.org/loongarch/cover.1691047285.git.chenfeiyang@loongson.cn/>
> v2: <https://lore.kernel.org/loongarch/cover.1690439335.git.chenfeiyang@loongson.cn/>
> v1: <https://lore.kernel.org/loongarch/cover.1689215889.git.chenfeiyang@loongson.cn/>
> 
> 
> Yanteng Si (11):
>   net: stmmac: Add multi-channel support
>   net: stmmac: dwmac-loongson: Refactor code for loongson_dwmac_probe()
>   net: stmmac: dwmac-loongson: Add full PCI support
>   net: stmmac: dwmac-loongson: Move irq config to loongson_gmac_config
>   net: stmmac: dwmac-loongson: Add Loongson-specific register
>     definitions
>   net: stmmac: dwmac-loongson: Add GNET support
>   net: stmmac: dwmac-loongson: Add multi-channel supports for loongson
>   net: stmmac: dwmac-loongson: Fix MAC speed for GNET
>   net: stmmac: dwmac-loongson: Fix half duplex
>   net: stmmac: dwmac-loongson: Disable flow control for GMAC
>   net: stmmac: dwmac-loongson: Disable coe for some Loongson GNET
> 
>  .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 561 ++++++++++++++++--
>  .../net/ethernet/stmicro/stmmac/dwmac-sun8i.c |   2 +-
>  .../ethernet/stmicro/stmmac/dwmac1000_dma.c   |  36 +-
>  .../net/ethernet/stmicro/stmmac/dwmac_dma.h   |  19 +-
>  .../net/ethernet/stmicro/stmmac/dwmac_lib.c   |  32 +-
>  drivers/net/ethernet/stmicro/stmmac/hwif.h    |   2 +-
>  .../ethernet/stmicro/stmmac/stmmac_ethtool.c  |   6 +
>  .../net/ethernet/stmicro/stmmac/stmmac_main.c |  15 +-
>  include/linux/stmmac.h                        |   3 +
>  9 files changed, 582 insertions(+), 94 deletions(-)
> 
> -- 
> 2.31.4
> 

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 00/11] stmmac: Add Loongson platform support
  2024-01-30  8:43 [PATCH net-next v8 00/11] stmmac: Add Loongson platform support Yanteng Si
                   ` (11 preceding siblings ...)
  2024-01-30  9:57 ` [PATCH net-next v8 00/11] stmmac: Add Loongson platform support Serge Semin
@ 2024-01-31  2:10 ` Jakub Kicinski
  2024-01-31  9:20   ` Yanteng Si
  12 siblings, 1 reply; 97+ messages in thread
From: Jakub Kicinski @ 2024-01-31  2:10 UTC (permalink / raw)
  To: Yanteng Si
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	fancer.lancer, Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

On Tue, 30 Jan 2024 16:43:20 +0800 Yanteng Si wrote:
> * The biggest change is according to Serge's comment in the previous
>   edition:

Looks like there's a trivial build issue here:

ERROR: modpost: "dwmac1000_dma_ops"
[drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.ko] undefined!

Please wait for Serge's review before posting v9.
-- 
pw-bot: cr

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 00/11] stmmac: Add Loongson platform support
  2024-01-31  2:10 ` Jakub Kicinski
@ 2024-01-31  9:20   ` Yanteng Si
  0 siblings, 0 replies; 97+ messages in thread
From: Yanteng Si @ 2024-01-31  9:20 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	fancer.lancer, Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang


在 2024/1/31 10:10, Jakub Kicinski 写道:
> On Tue, 30 Jan 2024 16:43:20 +0800 Yanteng Si wrote:
>> * The biggest change is according to Serge's comment in the previous
>>    edition:
> Looks like there's a trivial build issue here:
>
> ERROR: modpost: "dwmac1000_dma_ops"
> [drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.ko] undefined!
>
> Please wait for Serge's review before posting v9.

OK!  Will fix with:

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c 
b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
index 5f7b82ad3ec2..0323f0a5049c 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
@@ -296,3 +296,4 @@ const struct stmmac_dma_ops dwmac1000_dma_ops = {
         .get_hw_feature = dwmac1000_get_hw_feature,
         .rx_watchdog = dwmac1000_rx_watchdog,
  };
+EXPORT_SYMBOL_GPL(dwmac1000_dma_ops);


Thanks,

Yanteng


^ permalink raw reply related	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 01/11] net: stmmac: Add multi-channel support
  2024-01-30  8:43 ` [PATCH net-next v8 01/11] net: stmmac: Add multi-channel support Yanteng Si
@ 2024-02-02 12:30   ` Simon Horman
  2024-02-04  8:43     ` Yanteng Si
  2024-02-04 23:28   ` Serge Semin
  2024-02-05  1:11   ` Serge Semin
  2 siblings, 1 reply; 97+ messages in thread
From: Simon Horman @ 2024-02-02 12:30 UTC (permalink / raw)
  To: Yanteng Si
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	fancer.lancer, Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

On Tue, Jan 30, 2024 at 04:43:21PM +0800, Yanteng Si wrote:
> DW GMAC v3.x multi-channels feature is implemented as multiple
> sets of the same CSRs. Here is only preliminary support, it will
> be useful for the driver further evolution and for the users
> having multi-channel DWGMAC v3.x devices.
> 
> Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
> Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
> Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>

...

> @@ -116,7 +118,7 @@ static void dwmac1000_dma_init_rx(struct stmmac_priv *priv,
>  				  dma_addr_t dma_rx_phy, u32 chan)
>  {
>  	/* RX descriptor base address list must be written into DMA CSR3 */
> -	writel(lower_32_bits(dma_rx_phy), ioaddr + DMA_RCV_BASE_ADDR);
> +	writel(lower_32_bits(dma_rx_phy), ioaddr + DMA_CHAN_RCV_BASE_ADDR(chan));

nit: Networking code (still) prefers code to be 80 columns wide or less.


Please consider running checkpatch as it is run by the CI.

https://github.com/linux-netdev/nipa/blob/main/tests/patch/checkpatch/checkpatch.sh

>  }
>  
>  static void dwmac1000_dma_init_tx(struct stmmac_priv *priv,


...

> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
> index 72672391675f..593be79c46e1 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
> @@ -148,11 +148,14 @@
>  					 DMA_STATUS_TI | \
>  					 DMA_STATUS_MSK_COMMON)
>  
> +/* Following DMA defines are chanels oriented */

nit: channels

FWIIW, checkpatch also has a --codespell option which can be used to flag
spelling errors.

...

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 02/11] net: stmmac: dwmac-loongson: Refactor code for loongson_dwmac_probe()
  2024-01-30  8:43 ` [PATCH net-next v8 02/11] net: stmmac: dwmac-loongson: Refactor code for loongson_dwmac_probe() Yanteng Si
@ 2024-02-02 12:33   ` Simon Horman
  2024-02-04  8:47     ` Yanteng Si
  2024-02-05 14:43   ` Serge Semin
  1 sibling, 1 reply; 97+ messages in thread
From: Simon Horman @ 2024-02-02 12:33 UTC (permalink / raw)
  To: Yanteng Si
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	fancer.lancer, Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

On Tue, Jan 30, 2024 at 04:43:22PM +0800, Yanteng Si wrote:
> The driver function is not changed, but the code location is
> adjusted to prepare for adding more loongson drivers.
> 
> Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
> Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
> Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>

...

> -static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id *id)
> +static struct stmmac_pci_info loongson_gmac_pci_info = {
> +	.setup = loongson_gmac_data,
> +};
> +
> +static int loongson_dwmac_probe(struct pci_dev *pdev,
> +				const struct pci_device_id *id)
>  {
> +	int ret, i, bus_id, phy_mode;
>  	struct plat_stmmacenet_data *plat;
> +	struct stmmac_pci_info *info;
>  	struct stmmac_resources res;
>  	struct device_node *np;
> -	int ret, i, phy_mode;

nit: Please consider preserving reverse xmas tree order - longest line
     to shortest - for local variable declarations in Networking code.

This tool can be helpful here:
https://github.com/ecree-solarflare/xmastree

...

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 01/11] net: stmmac: Add multi-channel support
  2024-02-02 12:30   ` Simon Horman
@ 2024-02-04  8:43     ` Yanteng Si
  0 siblings, 0 replies; 97+ messages in thread
From: Yanteng Si @ 2024-02-04  8:43 UTC (permalink / raw)
  To: Simon Horman
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	fancer.lancer, Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang


在 2024/2/2 20:30, Simon Horman 写道:
> On Tue, Jan 30, 2024 at 04:43:21PM +0800, Yanteng Si wrote:
>> DW GMAC v3.x multi-channels feature is implemented as multiple
>> sets of the same CSRs. Here is only preliminary support, it will
>> be useful for the driver further evolution and for the users
>> having multi-channel DWGMAC v3.x devices.
>>
>> Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
>> Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
>> Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
> ...
>
>> @@ -116,7 +118,7 @@ static void dwmac1000_dma_init_rx(struct stmmac_priv *priv,
>>   				  dma_addr_t dma_rx_phy, u32 chan)
>>   {
>>   	/* RX descriptor base address list must be written into DMA CSR3 */
>> -	writel(lower_32_bits(dma_rx_phy), ioaddr + DMA_RCV_BASE_ADDR);
>> +	writel(lower_32_bits(dma_rx_phy), ioaddr + DMA_CHAN_RCV_BASE_ADDR(chan));
> nit: Networking code (still) prefers code to be 80 columns wide or less.
>
>
> Please consider running checkpatch as it is run by the CI.
>
> https://github.com/linux-netdev/nipa/blob/main/tests/patch/checkpatch/checkpatch.sh
OK!
>
>>   }
>>   
>>   static void dwmac1000_dma_init_tx(struct stmmac_priv *priv,
>
> ...
>
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
>> index 72672391675f..593be79c46e1 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
>> @@ -148,11 +148,14 @@
>>   					 DMA_STATUS_TI | \
>>   					 DMA_STATUS_MSK_COMMON)
>>   
>> +/* Following DMA defines are chanels oriented */
> nit: channels
>
> FWIIW, checkpatch also has a --codespell option which can be used to flag
> spelling errors.

Sorry, I forgot to change it. This typo has already been commented in v7.


Thanks,

Yanteng


>
> ...


^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 02/11] net: stmmac: dwmac-loongson: Refactor code for loongson_dwmac_probe()
  2024-02-02 12:33   ` Simon Horman
@ 2024-02-04  8:47     ` Yanteng Si
  0 siblings, 0 replies; 97+ messages in thread
From: Yanteng Si @ 2024-02-04  8:47 UTC (permalink / raw)
  To: Simon Horman
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	fancer.lancer, Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang


在 2024/2/2 20:33, Simon Horman 写道:
> On Tue, Jan 30, 2024 at 04:43:22PM +0800, Yanteng Si wrote:
>> The driver function is not changed, but the code location is
>> adjusted to prepare for adding more loongson drivers.
>>
>> Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
>> Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
>> Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
> ...
>
>> -static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id *id)
>> +static struct stmmac_pci_info loongson_gmac_pci_info = {
>> +	.setup = loongson_gmac_data,
>> +};
>> +
>> +static int loongson_dwmac_probe(struct pci_dev *pdev,
>> +				const struct pci_device_id *id)
>>   {
>> +	int ret, i, bus_id, phy_mode;
>>   	struct plat_stmmacenet_data *plat;
>> +	struct stmmac_pci_info *info;
>>   	struct stmmac_resources res;
>>   	struct device_node *np;
>> -	int ret, i, phy_mode;
> nit: Please consider preserving reverse xmas tree order - longest line
>       to shortest - for local variable declarations in Networking code.
>
> This tool can be helpful here:
> https://github.com/ecree-solarflare/xmastree

Okey, thank you!


Thanks,

Yanteng

>
> ...


^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 01/11] net: stmmac: Add multi-channel support
  2024-01-30  8:43 ` [PATCH net-next v8 01/11] net: stmmac: Add multi-channel support Yanteng Si
  2024-02-02 12:30   ` Simon Horman
@ 2024-02-04 23:28   ` Serge Semin
  2024-02-06  9:02     ` Yanteng Si
  2024-02-19 11:02     ` Yanteng Si
  2024-02-05  1:11   ` Serge Semin
  2 siblings, 2 replies; 97+ messages in thread
From: Serge Semin @ 2024-02-04 23:28 UTC (permalink / raw)
  To: Yanteng Si
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

On Tue, Jan 30, 2024 at 04:43:21PM +0800, Yanteng Si wrote:
> DW GMAC v3.x multi-channels feature is implemented as multiple
> sets of the same CSRs. Here is only preliminary support, it will
> be useful for the driver further evolution and for the users
> having multi-channel DWGMAC v3.x devices.
> 
> Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
> Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
> Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
> ---
>  .../net/ethernet/stmicro/stmmac/dwmac-sun8i.c |  2 +-
>  .../ethernet/stmicro/stmmac/dwmac1000_dma.c   | 36 ++++++++++---------
>  .../net/ethernet/stmicro/stmmac/dwmac_dma.h   | 19 +++++++++-
>  .../net/ethernet/stmicro/stmmac/dwmac_lib.c   | 32 ++++++++---------
>  drivers/net/ethernet/stmicro/stmmac/hwif.h    |  2 +-
>  .../net/ethernet/stmicro/stmmac/stmmac_main.c |  6 ++--
>  6 files changed, 58 insertions(+), 39 deletions(-)
> 
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
> index 137741b94122..7cdfa0bdb93a 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
> @@ -395,7 +395,7 @@ static void sun8i_dwmac_dma_start_tx(struct stmmac_priv *priv,
>  	writel(v, ioaddr + EMAC_TX_CTL1);
>  }
>  
> -static void sun8i_dwmac_enable_dma_transmission(void __iomem *ioaddr)
> +static void sun8i_dwmac_enable_dma_transmission(void __iomem *ioaddr, u32 chan)
>  {
>  	u32 v;
>  
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> index daf79cdbd3ec..5f7b82ad3ec2 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> @@ -70,15 +70,18 @@ static void dwmac1000_dma_axi(void __iomem *ioaddr, struct stmmac_axi *axi)
>  	writel(value, ioaddr + DMA_AXI_BUS_MODE);
>  }
>  
> -static void dwmac1000_dma_init(void __iomem *ioaddr,
> -			       struct stmmac_dma_cfg *dma_cfg, int atds)
> +static void dwmac1000_dma_init_channel(struct stmmac_priv *priv,
> +				       void __iomem *ioaddr,
> +				       struct stmmac_dma_cfg *dma_cfg, u32 chan)
>  {

> -	u32 value = readl(ioaddr + DMA_BUS_MODE);
> +	u32 value;
>  	int txpbl = dma_cfg->txpbl ?: dma_cfg->pbl;
>  	int rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl;

Reverse xmas tree please.

>  
> -	/*
> -	 * Set the DMA PBL (Programmable Burst Length) mode.

> +	/* common channel control register config */

Redundant comment. Please drop.

> +	value = readl(ioaddr + DMA_CHAN_BUS_MODE(chan));
> +
> +	/* Set the DMA PBL (Programmable Burst Length) mode.
>  	 *
>  	 * Note: before stmmac core 3.50 this mode bit was 4xPBL, and
>  	 * post 3.5 mode bit acts as 8*PBL.
> @@ -98,16 +101,15 @@ static void dwmac1000_dma_init(void __iomem *ioaddr,
>  	if (dma_cfg->mixed_burst)
>  		value |= DMA_BUS_MODE_MB;
>  

> -	if (atds)
> -		value |= DMA_BUS_MODE_ATDS;
> +	value |= DMA_BUS_MODE_ATDS;

No, just convert the stmmac_dma_ops.dma_init_channel() to accepting
the atds flag as I suggested in v7:
https://lore.kernel.org/netdev/vxcfrxtbfu4pya56m22icnizsyjzqqha5blzb7zpexqcur56uh@uv6vsjf77npa/

In order to simplify this patch you can provide the
stmmac_dma_ops.dma_init_channel() and
stmmac_dma_ops.enable_dma_transmission() prototype updates in a
pre-requisite/preparation patch.

>  
>  	if (dma_cfg->aal)
>  		value |= DMA_BUS_MODE_AAL;
>  
> -	writel(value, ioaddr + DMA_BUS_MODE);
> +	writel(value, ioaddr + DMA_CHAN_BUS_MODE(chan));
>  
>  	/* Mask interrupts by writing to CSR7 */
> -	writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_INTR_ENA);
> +	writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_CHAN_INTR_ENA(chan));
>  }
>  
>  static void dwmac1000_dma_init_rx(struct stmmac_priv *priv,
> @@ -116,7 +118,7 @@ static void dwmac1000_dma_init_rx(struct stmmac_priv *priv,
>  				  dma_addr_t dma_rx_phy, u32 chan)
>  {
>  	/* RX descriptor base address list must be written into DMA CSR3 */
> -	writel(lower_32_bits(dma_rx_phy), ioaddr + DMA_RCV_BASE_ADDR);
> +	writel(lower_32_bits(dma_rx_phy), ioaddr + DMA_CHAN_RCV_BASE_ADDR(chan));
>  }
>  
>  static void dwmac1000_dma_init_tx(struct stmmac_priv *priv,
> @@ -125,7 +127,7 @@ static void dwmac1000_dma_init_tx(struct stmmac_priv *priv,
>  				  dma_addr_t dma_tx_phy, u32 chan)
>  {
>  	/* TX descriptor base address list must be written into DMA CSR4 */
> -	writel(lower_32_bits(dma_tx_phy), ioaddr + DMA_TX_BASE_ADDR);
> +	writel(lower_32_bits(dma_tx_phy), ioaddr + DMA_CHAN_TX_BASE_ADDR(chan));
>  }
>  
>  static u32 dwmac1000_configure_fc(u32 csr6, int rxfifosz)
> @@ -153,7 +155,7 @@ static void dwmac1000_dma_operation_mode_rx(struct stmmac_priv *priv,
>  					    void __iomem *ioaddr, int mode,
>  					    u32 channel, int fifosz, u8 qmode)
>  {
> -	u32 csr6 = readl(ioaddr + DMA_CONTROL);
> +	u32 csr6 = readl(ioaddr + DMA_CHAN_CONTROL(channel));
>  
>  	if (mode == SF_DMA_MODE) {
>  		pr_debug("GMAC: enable RX store and forward mode\n");
> @@ -175,14 +177,14 @@ static void dwmac1000_dma_operation_mode_rx(struct stmmac_priv *priv,
>  	/* Configure flow control based on rx fifo size */
>  	csr6 = dwmac1000_configure_fc(csr6, fifosz);
>  
> -	writel(csr6, ioaddr + DMA_CONTROL);
> +	writel(csr6, ioaddr + DMA_CHAN_CONTROL(channel));
>  }
>  
>  static void dwmac1000_dma_operation_mode_tx(struct stmmac_priv *priv,
>  					    void __iomem *ioaddr, int mode,
>  					    u32 channel, int fifosz, u8 qmode)
>  {
> -	u32 csr6 = readl(ioaddr + DMA_CONTROL);
> +	u32 csr6 = readl(ioaddr + DMA_CHAN_CONTROL(channel));
>  
>  	if (mode == SF_DMA_MODE) {
>  		pr_debug("GMAC: enable TX store and forward mode\n");
> @@ -209,7 +211,7 @@ static void dwmac1000_dma_operation_mode_tx(struct stmmac_priv *priv,
>  			csr6 |= DMA_CONTROL_TTC_256;
>  	}
>  
> -	writel(csr6, ioaddr + DMA_CONTROL);
> +	writel(csr6, ioaddr + DMA_CHAN_CONTROL(channel));
>  }
>  
>  static void dwmac1000_dump_dma_regs(struct stmmac_priv *priv,
> @@ -271,12 +273,12 @@ static int dwmac1000_get_hw_feature(void __iomem *ioaddr,
>  static void dwmac1000_rx_watchdog(struct stmmac_priv *priv,
>  				  void __iomem *ioaddr, u32 riwt, u32 queue)
>  {
> -	writel(riwt, ioaddr + DMA_RX_WATCHDOG);
> +	writel(riwt, ioaddr + DMA_CHAN_RX_WATCHDOG(queue));
>  }
>  
>  const struct stmmac_dma_ops dwmac1000_dma_ops = {
>  	.reset = dwmac_dma_reset,
> -	.init = dwmac1000_dma_init,
> +	.init_chan = dwmac1000_dma_init_channel,
>  	.init_rx_chan = dwmac1000_dma_init_rx,
>  	.init_tx_chan = dwmac1000_dma_init_tx,
>  	.axi = dwmac1000_dma_axi,
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
> index 72672391675f..593be79c46e1 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
> @@ -148,11 +148,14 @@
>  					 DMA_STATUS_TI | \
>  					 DMA_STATUS_MSK_COMMON)
>  

> +/* Following DMA defines are chanels oriented */    \
> +#define DMA_CHAN_OFFSET			0x100   |-------------+
> +                                                    /              |
                                                                      |
Please move all of these ---------------------------------------------+-------------------------+
to being defined just below the DMA_MISSED_FRAME_CTR macros definition.                         |
The point is to keep a coherency between dwmac_dma.h and dwmac4_dma.h.                          |
The later header file has first generic DMA-related macros defined                              |
(CSR addresses and flags) and then the channel-specific ones (CSR                               |
addresses and flags). Since in case of the DW GMAC v3.x the                                     |
multi-channels are implemented as a copy of all the DMA CSRs let's                              |
preserve the logic of having all CSR address defined first, then the                            |
CSR flags.                                                                                      |
                                                                                                |
>  #define NUM_DWMAC100_DMA_REGS	9                                                       |
>  #define NUM_DWMAC1000_DMA_REGS	23                                                      |
>  #define NUM_DWMAC4_DMA_REGS	27                                                              |
>                                                                                               |
> -void dwmac_enable_dma_transmission(void __iomem *ioaddr);                                    |
> +void dwmac_enable_dma_transmission(void __iomem *ioaddr, u32 chan);                          |
>  void dwmac_enable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr,                    |
>  			  u32 chan, bool rx, bool tx);                                          |
>  void dwmac_disable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr,                   |
> @@ -169,4 +172,18 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,  |
>  			struct stmmac_extra_stats *x, u32 chan, u32 dir);                       |
>  int dwmac_dma_reset(void __iomem *ioaddr);                                                   |
>                                                                                               |
                                                                                                |
> +static inline u32 dma_chan_base_addr(u32 base, u32 chan)                                  \  |
> +{                                                                                          | |
> +	return base + chan * DMA_CHAN_OFFSET;                                                 | |
> +}                                                                                          | |
> +                                                                                           | |
> +#define DMA_CHAN_XMT_POLL_DEMAND(chan)	dma_chan_base_addr(DMA_XMT_POLL_DEMAND, chan) | |
> +#define DMA_CHAN_INTR_ENA(chan)		dma_chan_base_addr(DMA_INTR_ENA, chan)        | |
> +#define DMA_CHAN_CONTROL(chan)		dma_chan_base_addr(DMA_CONTROL, chan)         | |
> +#define DMA_CHAN_STATUS(chan)		dma_chan_base_addr(DMA_STATUS, chan)          |-+
> +#define DMA_CHAN_BUS_MODE(chan)		dma_chan_base_addr(DMA_BUS_MODE, chan)        |
> +#define DMA_CHAN_RCV_BASE_ADDR(chan)	dma_chan_base_addr(DMA_RCV_BASE_ADDR, chan)           |
> +#define DMA_CHAN_TX_BASE_ADDR(chan)	dma_chan_base_addr(DMA_TX_BASE_ADDR, chan)            |
> +#define DMA_CHAN_RX_WATCHDOG(chan)	dma_chan_base_addr(DMA_RX_WATCHDOG, chan)             |
> +                                                                                           /

>  #endif /* __DWMAC_DMA_H__ */
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
> index 7907d62d3437..b37368137810 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
> @@ -28,65 +28,65 @@ int dwmac_dma_reset(void __iomem *ioaddr)
>  }
>  
>  /* CSR1 enables the transmit DMA to check for new descriptor */
> -void dwmac_enable_dma_transmission(void __iomem *ioaddr)
> +void dwmac_enable_dma_transmission(void __iomem *ioaddr, u32 chan)
>  {
> -	writel(1, ioaddr + DMA_XMT_POLL_DEMAND);
> +	writel(1, ioaddr + DMA_CHAN_XMT_POLL_DEMAND(chan));
>  }
>  
>  void dwmac_enable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr,
>  			  u32 chan, bool rx, bool tx)
>  {
> -	u32 value = readl(ioaddr + DMA_INTR_ENA);
> +	u32 value = readl(ioaddr + DMA_CHAN_INTR_ENA(chan));
>  
>  	if (rx)
>  		value |= DMA_INTR_DEFAULT_RX;
>  	if (tx)
>  		value |= DMA_INTR_DEFAULT_TX;
>  
> -	writel(value, ioaddr + DMA_INTR_ENA);
> +	writel(value, ioaddr + DMA_CHAN_INTR_ENA(chan));
>  }
>  
>  void dwmac_disable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr,
>  			   u32 chan, bool rx, bool tx)
>  {
> -	u32 value = readl(ioaddr + DMA_INTR_ENA);
> +	u32 value = readl(ioaddr + DMA_CHAN_INTR_ENA(chan));
>  
>  	if (rx)
>  		value &= ~DMA_INTR_DEFAULT_RX;
>  	if (tx)
>  		value &= ~DMA_INTR_DEFAULT_TX;
>  
> -	writel(value, ioaddr + DMA_INTR_ENA);
> +	writel(value, ioaddr + DMA_CHAN_INTR_ENA(chan));
>  }
>  
>  void dwmac_dma_start_tx(struct stmmac_priv *priv, void __iomem *ioaddr,
>  			u32 chan)
>  {
> -	u32 value = readl(ioaddr + DMA_CONTROL);
> +	u32 value = readl(ioaddr + DMA_CHAN_CONTROL(chan));
>  	value |= DMA_CONTROL_ST;
> -	writel(value, ioaddr + DMA_CONTROL);
> +	writel(value, ioaddr + DMA_CHAN_CONTROL(chan));
>  }
>  
>  void dwmac_dma_stop_tx(struct stmmac_priv *priv, void __iomem *ioaddr, u32 chan)
>  {
> -	u32 value = readl(ioaddr + DMA_CONTROL);
> +	u32 value = readl(ioaddr + DMA_CHAN_CONTROL(chan));
>  	value &= ~DMA_CONTROL_ST;
> -	writel(value, ioaddr + DMA_CONTROL);
> +	writel(value, ioaddr + DMA_CHAN_CONTROL(chan));
>  }
>  
>  void dwmac_dma_start_rx(struct stmmac_priv *priv, void __iomem *ioaddr,
>  			u32 chan)
>  {
> -	u32 value = readl(ioaddr + DMA_CONTROL);
> +	u32 value = readl(ioaddr + DMA_CHAN_CONTROL(chan));
>  	value |= DMA_CONTROL_SR;
> -	writel(value, ioaddr + DMA_CONTROL);
> +	writel(value, ioaddr + DMA_CHAN_CONTROL(chan));
>  }
>  
>  void dwmac_dma_stop_rx(struct stmmac_priv *priv, void __iomem *ioaddr, u32 chan)
>  {
> -	u32 value = readl(ioaddr + DMA_CONTROL);
> +	u32 value = readl(ioaddr + DMA_CHAN_CONTROL(chan));
>  	value &= ~DMA_CONTROL_SR;
> -	writel(value, ioaddr + DMA_CONTROL);
> +	writel(value, ioaddr + DMA_CHAN_CONTROL(chan));
>  }
>  
>  #ifdef DWMAC_DMA_DEBUG
> @@ -166,7 +166,7 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
>  	struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[chan];
>  	int ret = 0;
>  	/* read the status register (CSR5) */
> -	u32 intr_status = readl(ioaddr + DMA_STATUS);
> +	u32 intr_status = readl(ioaddr + DMA_CHAN_STATUS(chan));
>  
>  #ifdef DWMAC_DMA_DEBUG
>  	/* Enable it to monitor DMA rx/tx status in case of critical problems */
> @@ -236,7 +236,7 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
>  		pr_warn("%s: unexpected status %08x\n", __func__, intr_status);
>  
>  	/* Clear the interrupt by writing a logic 1 to the CSR5[15-0] */

> -	writel((intr_status & 0x1ffff), ioaddr + DMA_STATUS);
> +	writel((intr_status & 0x7ffff), ioaddr + DMA_CHAN_STATUS(chan));

Isn't the mask change going to be implemented in the framework of the
Loongson-specific DMA-interrupt handler in some of the further patches?


I'll get back to reviewing the series tomorrow (later today)...

-Serge(y)

>  
>  	return ret;
>  }
> diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h
> index 7be04b54738b..b0db38396171 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/hwif.h
> +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h
> @@ -198,7 +198,7 @@ struct stmmac_dma_ops {
>  	/* To track extra statistic (if supported) */
>  	void (*dma_diagnostic_fr)(struct stmmac_extra_stats *x,
>  				  void __iomem *ioaddr);
> -	void (*enable_dma_transmission) (void __iomem *ioaddr);
> +	void (*enable_dma_transmission)(void __iomem *ioaddr, u32 chan);
>  	void (*enable_dma_irq)(struct stmmac_priv *priv, void __iomem *ioaddr,
>  			       u32 chan, bool rx, bool tx);
>  	void (*disable_dma_irq)(struct stmmac_priv *priv, void __iomem *ioaddr,
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> index b334eb16da23..5617b40abbe4 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> @@ -2558,7 +2558,7 @@ static bool stmmac_xdp_xmit_zc(struct stmmac_priv *priv, u32 queue, u32 budget)
>  				       true, priv->mode, true, true,
>  				       xdp_desc.len);
>  
> -		stmmac_enable_dma_transmission(priv, priv->ioaddr);
> +		stmmac_enable_dma_transmission(priv, priv->ioaddr, queue);
>  
>  		xsk_tx_metadata_to_compl(meta,
>  					 &tx_q->tx_skbuff_dma[entry].xsk_meta);
> @@ -4706,7 +4706,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
>  
>  	netdev_tx_sent_queue(netdev_get_tx_queue(dev, queue), skb->len);
>  
> -	stmmac_enable_dma_transmission(priv, priv->ioaddr);
> +	stmmac_enable_dma_transmission(priv, priv->ioaddr, queue);
>  
>  	stmmac_flush_tx_descriptors(priv, queue);
>  	stmmac_tx_timer_arm(priv, queue);
> @@ -4926,7 +4926,7 @@ static int stmmac_xdp_xmit_xdpf(struct stmmac_priv *priv, int queue,
>  		u64_stats_update_end_irqrestore(&txq_stats->syncp, flags);
>  	}
>  
> -	stmmac_enable_dma_transmission(priv, priv->ioaddr);
> +	stmmac_enable_dma_transmission(priv, priv->ioaddr, queue);
>  
>  	entry = STMMAC_GET_ENTRY(entry, priv->dma_conf.dma_tx_size);
>  	tx_q->cur_tx = entry;
> -- 
> 2.31.4
> 

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 01/11] net: stmmac: Add multi-channel support
  2024-01-30  8:43 ` [PATCH net-next v8 01/11] net: stmmac: Add multi-channel support Yanteng Si
  2024-02-02 12:30   ` Simon Horman
  2024-02-04 23:28   ` Serge Semin
@ 2024-02-05  1:11   ` Serge Semin
  2 siblings, 0 replies; 97+ messages in thread
From: Serge Semin @ 2024-02-05  1:11 UTC (permalink / raw)
  To: Yanteng Si
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

On Tue, Jan 30, 2024 at 04:43:21PM +0800, Yanteng Si wrote:
> DW GMAC v3.x multi-channels feature is implemented as multiple
> sets of the same CSRs. Here is only preliminary support, it will
> be useful for the driver further evolution and for the users
> having multi-channel DWGMAC v3.x devices.
> 
> Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
> Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
> Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
> ---
>  .../net/ethernet/stmicro/stmmac/dwmac-sun8i.c |  2 +-
>  .../ethernet/stmicro/stmmac/dwmac1000_dma.c   | 36 ++++++++++---------
>  .../net/ethernet/stmicro/stmmac/dwmac_dma.h   | 19 +++++++++-
>  .../net/ethernet/stmicro/stmmac/dwmac_lib.c   | 32 ++++++++---------
>  drivers/net/ethernet/stmicro/stmmac/hwif.h    |  2 +-
>  .../net/ethernet/stmicro/stmmac/stmmac_main.c |  6 ++--
>  6 files changed, 58 insertions(+), 39 deletions(-)
> 
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
> index 137741b94122..7cdfa0bdb93a 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
> @@ -395,7 +395,7 @@ static void sun8i_dwmac_dma_start_tx(struct stmmac_priv *priv,
>  	writel(v, ioaddr + EMAC_TX_CTL1);
>  }
>  
> -static void sun8i_dwmac_enable_dma_transmission(void __iomem *ioaddr)
> +static void sun8i_dwmac_enable_dma_transmission(void __iomem *ioaddr, u32 chan)
>  {
>  	u32 v;
>  
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> index daf79cdbd3ec..5f7b82ad3ec2 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> @@ -70,15 +70,18 @@ static void dwmac1000_dma_axi(void __iomem *ioaddr, struct stmmac_axi *axi)
>  	writel(value, ioaddr + DMA_AXI_BUS_MODE);
>  }
>  
> -static void dwmac1000_dma_init(void __iomem *ioaddr,
> -			       struct stmmac_dma_cfg *dma_cfg, int atds)
> +static void dwmac1000_dma_init_channel(struct stmmac_priv *priv,
> +				       void __iomem *ioaddr,
> +				       struct stmmac_dma_cfg *dma_cfg, u32 chan)
>  {
> -	u32 value = readl(ioaddr + DMA_BUS_MODE);
> +	u32 value;
>  	int txpbl = dma_cfg->txpbl ?: dma_cfg->pbl;
>  	int rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl;
>  
> -	/*
> -	 * Set the DMA PBL (Programmable Burst Length) mode.
> +	/* common channel control register config */
> +	value = readl(ioaddr + DMA_CHAN_BUS_MODE(chan));
> +
> +	/* Set the DMA PBL (Programmable Burst Length) mode.
>  	 *
>  	 * Note: before stmmac core 3.50 this mode bit was 4xPBL, and
>  	 * post 3.5 mode bit acts as 8*PBL.
> @@ -98,16 +101,15 @@ static void dwmac1000_dma_init(void __iomem *ioaddr,
>  	if (dma_cfg->mixed_burst)
>  		value |= DMA_BUS_MODE_MB;
>  
> -	if (atds)
> -		value |= DMA_BUS_MODE_ATDS;
> +	value |= DMA_BUS_MODE_ATDS;
>  
>  	if (dma_cfg->aal)
>  		value |= DMA_BUS_MODE_AAL;
>  
> -	writel(value, ioaddr + DMA_BUS_MODE);
> +	writel(value, ioaddr + DMA_CHAN_BUS_MODE(chan));
>  
>  	/* Mask interrupts by writing to CSR7 */
> -	writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_INTR_ENA);
> +	writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_CHAN_INTR_ENA(chan));
>  }
>  
>  static void dwmac1000_dma_init_rx(struct stmmac_priv *priv,
> @@ -116,7 +118,7 @@ static void dwmac1000_dma_init_rx(struct stmmac_priv *priv,
>  				  dma_addr_t dma_rx_phy, u32 chan)
>  {
>  	/* RX descriptor base address list must be written into DMA CSR3 */
> -	writel(lower_32_bits(dma_rx_phy), ioaddr + DMA_RCV_BASE_ADDR);
> +	writel(lower_32_bits(dma_rx_phy), ioaddr + DMA_CHAN_RCV_BASE_ADDR(chan));
>  }
>  
>  static void dwmac1000_dma_init_tx(struct stmmac_priv *priv,
> @@ -125,7 +127,7 @@ static void dwmac1000_dma_init_tx(struct stmmac_priv *priv,
>  				  dma_addr_t dma_tx_phy, u32 chan)
>  {
>  	/* TX descriptor base address list must be written into DMA CSR4 */
> -	writel(lower_32_bits(dma_tx_phy), ioaddr + DMA_TX_BASE_ADDR);
> +	writel(lower_32_bits(dma_tx_phy), ioaddr + DMA_CHAN_TX_BASE_ADDR(chan));
>  }
>  
>  static u32 dwmac1000_configure_fc(u32 csr6, int rxfifosz)
> @@ -153,7 +155,7 @@ static void dwmac1000_dma_operation_mode_rx(struct stmmac_priv *priv,
>  					    void __iomem *ioaddr, int mode,
>  					    u32 channel, int fifosz, u8 qmode)
>  {
> -	u32 csr6 = readl(ioaddr + DMA_CONTROL);
> +	u32 csr6 = readl(ioaddr + DMA_CHAN_CONTROL(channel));
>  
>  	if (mode == SF_DMA_MODE) {
>  		pr_debug("GMAC: enable RX store and forward mode\n");
> @@ -175,14 +177,14 @@ static void dwmac1000_dma_operation_mode_rx(struct stmmac_priv *priv,
>  	/* Configure flow control based on rx fifo size */
>  	csr6 = dwmac1000_configure_fc(csr6, fifosz);
>  
> -	writel(csr6, ioaddr + DMA_CONTROL);
> +	writel(csr6, ioaddr + DMA_CHAN_CONTROL(channel));
>  }
>  
>  static void dwmac1000_dma_operation_mode_tx(struct stmmac_priv *priv,
>  					    void __iomem *ioaddr, int mode,
>  					    u32 channel, int fifosz, u8 qmode)
>  {
> -	u32 csr6 = readl(ioaddr + DMA_CONTROL);
> +	u32 csr6 = readl(ioaddr + DMA_CHAN_CONTROL(channel));
>  
>  	if (mode == SF_DMA_MODE) {
>  		pr_debug("GMAC: enable TX store and forward mode\n");
> @@ -209,7 +211,7 @@ static void dwmac1000_dma_operation_mode_tx(struct stmmac_priv *priv,
>  			csr6 |= DMA_CONTROL_TTC_256;
>  	}
>  
> -	writel(csr6, ioaddr + DMA_CONTROL);
> +	writel(csr6, ioaddr + DMA_CHAN_CONTROL(channel));
>  }
>  
>  static void dwmac1000_dump_dma_regs(struct stmmac_priv *priv,
> @@ -271,12 +273,12 @@ static int dwmac1000_get_hw_feature(void __iomem *ioaddr,
>  static void dwmac1000_rx_watchdog(struct stmmac_priv *priv,
>  				  void __iomem *ioaddr, u32 riwt, u32 queue)
>  {
> -	writel(riwt, ioaddr + DMA_RX_WATCHDOG);
> +	writel(riwt, ioaddr + DMA_CHAN_RX_WATCHDOG(queue));
>  }
>  
>  const struct stmmac_dma_ops dwmac1000_dma_ops = {
>  	.reset = dwmac_dma_reset,
> -	.init = dwmac1000_dma_init,
> +	.init_chan = dwmac1000_dma_init_channel,
>  	.init_rx_chan = dwmac1000_dma_init_rx,
>  	.init_tx_chan = dwmac1000_dma_init_tx,
>  	.axi = dwmac1000_dma_axi,
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
> index 72672391675f..593be79c46e1 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
> @@ -148,11 +148,14 @@
>  					 DMA_STATUS_TI | \
>  					 DMA_STATUS_MSK_COMMON)
>  

> +/* Following DMA defines are chanels oriented */

One more time:
s/chanels/channels

> +#define DMA_CHAN_OFFSET			0x100

Once again:
DMA_CHAN_BASE_OFFSET? to be looking the same as in DW QoS Eth GMAC
v4.x/v5.x (dwmac4_dma.h).

Please be more attentive to the review notes.

-Serge(y)

> +
>  #define NUM_DWMAC100_DMA_REGS	9
>  #define NUM_DWMAC1000_DMA_REGS	23
>  #define NUM_DWMAC4_DMA_REGS	27
>  
> -void dwmac_enable_dma_transmission(void __iomem *ioaddr);
> +void dwmac_enable_dma_transmission(void __iomem *ioaddr, u32 chan);
>  void dwmac_enable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr,
>  			  u32 chan, bool rx, bool tx);
>  void dwmac_disable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr,
> @@ -169,4 +172,18 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
>  			struct stmmac_extra_stats *x, u32 chan, u32 dir);
>  int dwmac_dma_reset(void __iomem *ioaddr);
>  
> +static inline u32 dma_chan_base_addr(u32 base, u32 chan)
> +{
> +	return base + chan * DMA_CHAN_OFFSET;
> +}
> +
> +#define DMA_CHAN_XMT_POLL_DEMAND(chan)	dma_chan_base_addr(DMA_XMT_POLL_DEMAND, chan)
> +#define DMA_CHAN_INTR_ENA(chan)		dma_chan_base_addr(DMA_INTR_ENA, chan)
> +#define DMA_CHAN_CONTROL(chan)		dma_chan_base_addr(DMA_CONTROL, chan)
> +#define DMA_CHAN_STATUS(chan)		dma_chan_base_addr(DMA_STATUS, chan)
> +#define DMA_CHAN_BUS_MODE(chan)		dma_chan_base_addr(DMA_BUS_MODE, chan)
> +#define DMA_CHAN_RCV_BASE_ADDR(chan)	dma_chan_base_addr(DMA_RCV_BASE_ADDR, chan)
> +#define DMA_CHAN_TX_BASE_ADDR(chan)	dma_chan_base_addr(DMA_TX_BASE_ADDR, chan)
> +#define DMA_CHAN_RX_WATCHDOG(chan)	dma_chan_base_addr(DMA_RX_WATCHDOG, chan)
> +
>  #endif /* __DWMAC_DMA_H__ */
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
> index 7907d62d3437..b37368137810 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
> @@ -28,65 +28,65 @@ int dwmac_dma_reset(void __iomem *ioaddr)
>  }
>  
>  /* CSR1 enables the transmit DMA to check for new descriptor */
> -void dwmac_enable_dma_transmission(void __iomem *ioaddr)
> +void dwmac_enable_dma_transmission(void __iomem *ioaddr, u32 chan)
>  {
> -	writel(1, ioaddr + DMA_XMT_POLL_DEMAND);
> +	writel(1, ioaddr + DMA_CHAN_XMT_POLL_DEMAND(chan));
>  }
>  
>  void dwmac_enable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr,
>  			  u32 chan, bool rx, bool tx)
>  {
> -	u32 value = readl(ioaddr + DMA_INTR_ENA);
> +	u32 value = readl(ioaddr + DMA_CHAN_INTR_ENA(chan));
>  
>  	if (rx)
>  		value |= DMA_INTR_DEFAULT_RX;
>  	if (tx)
>  		value |= DMA_INTR_DEFAULT_TX;
>  
> -	writel(value, ioaddr + DMA_INTR_ENA);
> +	writel(value, ioaddr + DMA_CHAN_INTR_ENA(chan));
>  }
>  
>  void dwmac_disable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr,
>  			   u32 chan, bool rx, bool tx)
>  {
> -	u32 value = readl(ioaddr + DMA_INTR_ENA);
> +	u32 value = readl(ioaddr + DMA_CHAN_INTR_ENA(chan));
>  
>  	if (rx)
>  		value &= ~DMA_INTR_DEFAULT_RX;
>  	if (tx)
>  		value &= ~DMA_INTR_DEFAULT_TX;
>  
> -	writel(value, ioaddr + DMA_INTR_ENA);
> +	writel(value, ioaddr + DMA_CHAN_INTR_ENA(chan));
>  }
>  
>  void dwmac_dma_start_tx(struct stmmac_priv *priv, void __iomem *ioaddr,
>  			u32 chan)
>  {
> -	u32 value = readl(ioaddr + DMA_CONTROL);
> +	u32 value = readl(ioaddr + DMA_CHAN_CONTROL(chan));
>  	value |= DMA_CONTROL_ST;
> -	writel(value, ioaddr + DMA_CONTROL);
> +	writel(value, ioaddr + DMA_CHAN_CONTROL(chan));
>  }
>  
>  void dwmac_dma_stop_tx(struct stmmac_priv *priv, void __iomem *ioaddr, u32 chan)
>  {
> -	u32 value = readl(ioaddr + DMA_CONTROL);
> +	u32 value = readl(ioaddr + DMA_CHAN_CONTROL(chan));
>  	value &= ~DMA_CONTROL_ST;
> -	writel(value, ioaddr + DMA_CONTROL);
> +	writel(value, ioaddr + DMA_CHAN_CONTROL(chan));
>  }
>  
>  void dwmac_dma_start_rx(struct stmmac_priv *priv, void __iomem *ioaddr,
>  			u32 chan)
>  {
> -	u32 value = readl(ioaddr + DMA_CONTROL);
> +	u32 value = readl(ioaddr + DMA_CHAN_CONTROL(chan));
>  	value |= DMA_CONTROL_SR;
> -	writel(value, ioaddr + DMA_CONTROL);
> +	writel(value, ioaddr + DMA_CHAN_CONTROL(chan));
>  }
>  
>  void dwmac_dma_stop_rx(struct stmmac_priv *priv, void __iomem *ioaddr, u32 chan)
>  {
> -	u32 value = readl(ioaddr + DMA_CONTROL);
> +	u32 value = readl(ioaddr + DMA_CHAN_CONTROL(chan));
>  	value &= ~DMA_CONTROL_SR;
> -	writel(value, ioaddr + DMA_CONTROL);
> +	writel(value, ioaddr + DMA_CHAN_CONTROL(chan));
>  }
>  
>  #ifdef DWMAC_DMA_DEBUG
> @@ -166,7 +166,7 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
>  	struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[chan];
>  	int ret = 0;
>  	/* read the status register (CSR5) */
> -	u32 intr_status = readl(ioaddr + DMA_STATUS);
> +	u32 intr_status = readl(ioaddr + DMA_CHAN_STATUS(chan));
>  
>  #ifdef DWMAC_DMA_DEBUG
>  	/* Enable it to monitor DMA rx/tx status in case of critical problems */
> @@ -236,7 +236,7 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
>  		pr_warn("%s: unexpected status %08x\n", __func__, intr_status);
>  
>  	/* Clear the interrupt by writing a logic 1 to the CSR5[15-0] */
> -	writel((intr_status & 0x1ffff), ioaddr + DMA_STATUS);
> +	writel((intr_status & 0x7ffff), ioaddr + DMA_CHAN_STATUS(chan));
>  
>  	return ret;
>  }
> diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h
> index 7be04b54738b..b0db38396171 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/hwif.h
> +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h
> @@ -198,7 +198,7 @@ struct stmmac_dma_ops {
>  	/* To track extra statistic (if supported) */
>  	void (*dma_diagnostic_fr)(struct stmmac_extra_stats *x,
>  				  void __iomem *ioaddr);
> -	void (*enable_dma_transmission) (void __iomem *ioaddr);
> +	void (*enable_dma_transmission)(void __iomem *ioaddr, u32 chan);
>  	void (*enable_dma_irq)(struct stmmac_priv *priv, void __iomem *ioaddr,
>  			       u32 chan, bool rx, bool tx);
>  	void (*disable_dma_irq)(struct stmmac_priv *priv, void __iomem *ioaddr,
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> index b334eb16da23..5617b40abbe4 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> @@ -2558,7 +2558,7 @@ static bool stmmac_xdp_xmit_zc(struct stmmac_priv *priv, u32 queue, u32 budget)
>  				       true, priv->mode, true, true,
>  				       xdp_desc.len);
>  
> -		stmmac_enable_dma_transmission(priv, priv->ioaddr);
> +		stmmac_enable_dma_transmission(priv, priv->ioaddr, queue);
>  
>  		xsk_tx_metadata_to_compl(meta,
>  					 &tx_q->tx_skbuff_dma[entry].xsk_meta);
> @@ -4706,7 +4706,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
>  
>  	netdev_tx_sent_queue(netdev_get_tx_queue(dev, queue), skb->len);
>  
> -	stmmac_enable_dma_transmission(priv, priv->ioaddr);
> +	stmmac_enable_dma_transmission(priv, priv->ioaddr, queue);
>  
>  	stmmac_flush_tx_descriptors(priv, queue);
>  	stmmac_tx_timer_arm(priv, queue);
> @@ -4926,7 +4926,7 @@ static int stmmac_xdp_xmit_xdpf(struct stmmac_priv *priv, int queue,
>  		u64_stats_update_end_irqrestore(&txq_stats->syncp, flags);
>  	}
>  
> -	stmmac_enable_dma_transmission(priv, priv->ioaddr);
> +	stmmac_enable_dma_transmission(priv, priv->ioaddr, queue);
>  
>  	entry = STMMAC_GET_ENTRY(entry, priv->dma_conf.dma_tx_size);
>  	tx_q->cur_tx = entry;
> -- 
> 2.31.4
> 

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 02/11] net: stmmac: dwmac-loongson: Refactor code for loongson_dwmac_probe()
  2024-01-30  8:43 ` [PATCH net-next v8 02/11] net: stmmac: dwmac-loongson: Refactor code for loongson_dwmac_probe() Yanteng Si
  2024-02-02 12:33   ` Simon Horman
@ 2024-02-05 14:43   ` Serge Semin
  2024-04-05 11:13     ` Yanteng Si
  1 sibling, 1 reply; 97+ messages in thread
From: Serge Semin @ 2024-02-05 14:43 UTC (permalink / raw)
  To: Yanteng Si
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

On Tue, Jan 30, 2024 at 04:43:22PM +0800, Yanteng Si wrote:
> The driver function is not changed, but the code location is
> adjusted to prepare for adding more loongson drivers.

Having the word "refactoring" in the subject is always suspicious
because submitters very often try to hind behind it many small
changes they didn't want to/didn't know how to unpin from a more bulky
change. Moreover if there is no detailed explanation what is done and
why, it raises too many review questions and makes the reviewers life
much harder. So it would have been much better for us if you split up
this change into the smaller patches (see my last comment for a
presumable subset of the patches) to simplify the review process and
improve the driver bisectability especially seeing there actually are
functional changes introduced here despite of what is said in the
commit log.

> 
> Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
> Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
> Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
> ---
>  .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 61 +++++++++++++------
>  1 file changed, 42 insertions(+), 19 deletions(-)
> 
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> index 9e40c28d453a..e2dcb339b8b0 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> @@ -9,7 +9,12 @@
>  #include <linux/of_irq.h>
>  #include "stmmac.h"
>  
> -static int loongson_default_data(struct plat_stmmacenet_data *plat)
> +struct stmmac_pci_info {
> +	int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat);
> +};
> +
> +static void loongson_default_data(struct pci_dev *pdev,
> +				  struct plat_stmmacenet_data *plat)
>  {
>  	plat->clk_csr = 2;	/* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */
>  	plat->has_gmac = 1;
> @@ -34,23 +39,37 @@ static int loongson_default_data(struct plat_stmmacenet_data *plat)
>  
>  	/* Disable RX queues routing by default */
>  	plat->rx_queues_cfg[0].pkt_route = 0x0;
> +}
> +
> +static int loongson_gmac_data(struct pci_dev *pdev,
> +			      struct plat_stmmacenet_data *plat)
> +{
> +	loongson_default_data(pdev, plat);
> +

> +	plat->multicast_filter_bins = 256;

Why do you need to move this here from the function tail?

> +

> +	plat->mdio_bus_data->phy_mask = 0;

This is already zero. Why do you need this?

>  

> -	/* Default to phy auto-detection */

What is wrong with this comment?

>  	plat->phy_addr = -1;
>  
>  	plat->dma_cfg->pbl = 32;
>  	plat->dma_cfg->pblx8 = true;
>  
> -	plat->multicast_filter_bins = 256;
>  	return 0;
>  }
>  
> -static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id *id)
> +static struct stmmac_pci_info loongson_gmac_pci_info = {
> +	.setup = loongson_gmac_data,
> +};
> +
> +static int loongson_dwmac_probe(struct pci_dev *pdev,
> +				const struct pci_device_id *id)
>  {

> +	int ret, i, bus_id, phy_mode;
>  	struct plat_stmmacenet_data *plat;
> +	struct stmmac_pci_info *info;
>  	struct stmmac_resources res;
>  	struct device_node *np;
> -	int ret, i, phy_mode;

Reverse xmas tree order please.

>  
>  	np = dev_of_node(&pdev->dev);
>  
> @@ -69,18 +88,17 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
>  	if (!plat->mdio_bus_data)
>  		return -ENOMEM;
>  

> +	plat->dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*plat->dma_cfg),
> +				     GFP_KERNEL);
> +	if (!plat->dma_cfg)
> +		return -ENOMEM;
> +

Why do you need this moved above the mdio_node getting procedure? They
seem independent.

>  	plat->mdio_node = of_get_child_by_name(np, "mdio");
>  	if (plat->mdio_node) {
>  		dev_info(&pdev->dev, "Found MDIO subnode\n");
>  		plat->mdio_bus_data->needs_reset = true;
>  	}
>  
> -	plat->dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*plat->dma_cfg), GFP_KERNEL);
> -	if (!plat->dma_cfg) {
> -		ret = -ENOMEM;
> -		goto err_put_node;
> -	}
> -
>  	/* Enable pci device */
>  	ret = pci_enable_device(pdev);
>  	if (ret) {
> @@ -98,9 +116,16 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
>  		break;
>  	}
>  

> -	plat->bus_id = of_alias_get_id(np, "ethernet");
> -	if (plat->bus_id < 0)
> -		plat->bus_id = pci_dev_id(pdev);

This is a functional change because further bus_id is no longer
initialized by the pci_dev_id() method as a fallback case. If you are
sure this is required please unpin to a separate patch and explain.

> +	pci_set_master(pdev);
> +
> +	info = (struct stmmac_pci_info *)id->driver_data;
> +	ret = info->setup(pdev, plat);
> +	if (ret)
> +		goto err_disable_device;
> +
> +	bus_id = of_alias_get_id(np, "ethernet");
> +	if (bus_id >= 0)
> +		plat->bus_id = bus_id;
>  
>  	phy_mode = device_get_phy_mode(&pdev->dev);
>  	if (phy_mode < 0) {
> @@ -110,11 +135,7 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
>  	}
>  
>  	plat->phy_interface = phy_mode;

> -	plat->mac_interface = PHY_INTERFACE_MODE_GMII;

This is just dropped. Are you sure that the driver will work correctly
after this change is applied? Russell already asked you about this change
here:
https://lore.kernel.org/netdev/ZZPnaziDZEcv5GGw@shell.armlinux.org.uk/

Anyway please unpin it to a separate patch and explain.

>  
> -	pci_set_master(pdev);
> -
> -	loongson_default_data(plat);
>  	pci_enable_msi(pdev);
>  	memset(&res, 0, sizeof(res));
>  	res.addr = pcim_iomap_table(pdev)[0];
> @@ -212,8 +233,10 @@ static int __maybe_unused loongson_dwmac_resume(struct device *dev)
>  static SIMPLE_DEV_PM_OPS(loongson_dwmac_pm_ops, loongson_dwmac_suspend,
>  			 loongson_dwmac_resume);
>  
> +#define PCI_DEVICE_ID_LOONGSON_GMAC	0x7a03
> +
>  static const struct pci_device_id loongson_dwmac_id_table[] = {
> -	{ PCI_VDEVICE(LOONGSON, 0x7a03) },
> +	{ PCI_DEVICE_DATA(LOONGSON, GMAC, &loongson_gmac_pci_info) },

If I were you and needed to preserve all the changes I would have
split the patch up into the next patches:
1. Use PCI_DEVICE_DATA() macro for device identification
2. Drop mac-interface initialization
3. Don't initialize MDIO bus ID with PCIe device ID
4. Introduce device-specific setup callback

-Serge(y)

>  	{}
>  };
>  MODULE_DEVICE_TABLE(pci, loongson_dwmac_id_table);
> -- 
> 2.31.4
> 

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 03/11] net: stmmac: dwmac-loongson: Add full PCI support
  2024-01-30  8:43 ` [PATCH net-next v8 03/11] net: stmmac: dwmac-loongson: Add full PCI support Yanteng Si
@ 2024-02-05 16:49   ` Serge Semin
  2024-02-21 10:08     ` Yanteng Si
  0 siblings, 1 reply; 97+ messages in thread
From: Serge Semin @ 2024-02-05 16:49 UTC (permalink / raw)
  To: Yanteng Si
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

On Tue, Jan 30, 2024 at 04:43:23PM +0800, Yanteng Si wrote:
> Current dwmac-loongson only support LS2K in the "probed with PCI and
> configured with DT" manner. Add LS7A support on which the devices are
> fully PCI (non-DT).

Please add to the commit log more details of what LS7A is like and
bind that description to the changes below like the interface
settings, ref and PTP clock settings, etc. What is the difference
between LS2K and LS7A?

> 
> Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
> Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
> Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
> ---
>  .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 79 +++++++++++--------
>  1 file changed, 44 insertions(+), 35 deletions(-)
> 
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> index e2dcb339b8b0..979c9b6dab3f 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> @@ -16,6 +16,10 @@ struct stmmac_pci_info {
>  static void loongson_default_data(struct pci_dev *pdev,
>  				  struct plat_stmmacenet_data *plat)
>  {
> +	/* Get bus_id, this can be overloaded later */
> +	plat->bus_id = (pci_domain_nr(pdev->bus) << 16) |
> +		       PCI_DEVID(pdev->bus->number, pdev->devfn);
> +
>  	plat->clk_csr = 2;	/* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */
>  	plat->has_gmac = 1;
>  	plat->force_sf_dma_mode = 1;
> @@ -51,10 +55,14 @@ static int loongson_gmac_data(struct pci_dev *pdev,
>  	plat->mdio_bus_data->phy_mask = 0;
>  
>  	plat->phy_addr = -1;
> +	plat->phy_interface = PHY_INTERFACE_MODE_RGMII_ID;
>  
>  	plat->dma_cfg->pbl = 32;
>  	plat->dma_cfg->pblx8 = true;
>  

> +	plat->clk_ref_rate = 125000000;
> +	plat->clk_ptp_rate = 125000000;
> +

Is this compatible with the LS2K GMAC?

>  	return 0;
>  }
>  
> @@ -71,13 +79,6 @@ static int loongson_dwmac_probe(struct pci_dev *pdev,
>  	struct stmmac_resources res;
>  	struct device_node *np;
>  
> -	np = dev_of_node(&pdev->dev);
> -
> -	if (!np) {
> -		pr_info("dwmac_loongson_pci: No OF node\n");
> -		return -ENODEV;
> -	}
> -
>  	plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL);
>  	if (!plat)
>  		return -ENOMEM;
> @@ -93,6 +94,7 @@ static int loongson_dwmac_probe(struct pci_dev *pdev,
>  	if (!plat->dma_cfg)
>  		return -ENOMEM;
>  
> +	np = dev_of_node(&pdev->dev);

>  	plat->mdio_node = of_get_child_by_name(np, "mdio");
>  	if (plat->mdio_node) {
>  		dev_info(&pdev->dev, "Found MDIO subnode\n");

Shouldn't mdio_node setup being done under the "if (np)" clause?

> @@ -123,41 +125,48 @@ static int loongson_dwmac_probe(struct pci_dev *pdev,
>  	if (ret)
>  		goto err_disable_device;
>  
> -	bus_id = of_alias_get_id(np, "ethernet");
> -	if (bus_id >= 0)
> -		plat->bus_id = bus_id;

> +	if (np) {
> +		bus_id = of_alias_get_id(np, "ethernet");
> +		if (bus_id >= 0)
> +			plat->bus_id = bus_id;
>  
> -	phy_mode = device_get_phy_mode(&pdev->dev);
> -	if (phy_mode < 0) {
> -		dev_err(&pdev->dev, "phy_mode not found\n");
> -		ret = phy_mode;
> -		goto err_disable_device;
> +		phy_mode = device_get_phy_mode(&pdev->dev);
> +		if (phy_mode < 0) {
> +			dev_err(&pdev->dev, "phy_mode not found\n");
> +			ret = phy_mode;
> +			goto err_disable_device;
> +		}
> +		plat->phy_interface = phy_mode;
>  	}

Please collect all OF-specific code in the same "if (np)" clause if
possible.

>  
> -	plat->phy_interface = phy_mode;
> -
>  	pci_enable_msi(pdev);
>  	memset(&res, 0, sizeof(res));
>  	res.addr = pcim_iomap_table(pdev)[0];
>  
> -	res.irq = of_irq_get_byname(np, "macirq");
> -	if (res.irq < 0) {
> -		dev_err(&pdev->dev, "IRQ macirq not found\n");
> -		ret = -ENODEV;
> -		goto err_disable_msi;
> -	}
> -
> -	res.wol_irq = of_irq_get_byname(np, "eth_wake_irq");
> -	if (res.wol_irq < 0) {
> -		dev_info(&pdev->dev, "IRQ eth_wake_irq not found, using macirq\n");
> -		res.wol_irq = res.irq;
> -	}
> -
> -	res.lpi_irq = of_irq_get_byname(np, "eth_lpi");
> -	if (res.lpi_irq < 0) {
> -		dev_err(&pdev->dev, "IRQ eth_lpi not found\n");
> -		ret = -ENODEV;
> -		goto err_disable_msi;
> +	if (np) {
> +		res.irq = of_irq_get_byname(np, "macirq");
> +		if (res.irq < 0) {
> +			dev_err(&pdev->dev, "IRQ macirq not found\n");
> +			ret = -ENODEV;
> +			goto err_disable_msi;
> +		}
> +
> +		res.wol_irq = of_irq_get_byname(np, "eth_wake_irq");
> +		if (res.wol_irq < 0) {
> +			dev_info(&pdev->dev,
> +				 "IRQ eth_wake_irq not found, using macirq\n");
> +			res.wol_irq = res.irq;
> +		}
> +
> +		res.lpi_irq = of_irq_get_byname(np, "eth_lpi");
> +		if (res.lpi_irq < 0) {
> +			dev_err(&pdev->dev, "IRQ eth_lpi not found\n");
> +			ret = -ENODEV;
> +			goto err_disable_msi;
> +		}
> +	} else {
> +		res.irq = pdev->irq;

> +		res.wol_irq = pdev->irq;

This seems redundant. If res.wol_irq matches res_irq it won't be used
(see stmmac_request_irq_multi_msi() and stmmac_request_irq_single()).
What about dropping it?

-Serge(y)

>  	}
>  
>  	ret = stmmac_dvr_probe(&pdev->dev, plat, &res);
> -- 
> 2.31.4
> 

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 04/11] net: stmmac: dwmac-loongson: Move irq config to loongson_gmac_config
  2024-01-30  8:43 ` [PATCH net-next v8 04/11] net: stmmac: dwmac-loongson: Move irq config to loongson_gmac_config Yanteng Si
@ 2024-02-05 17:01   ` Serge Semin
  2024-03-13  8:14     ` Yanteng Si
  0 siblings, 1 reply; 97+ messages in thread
From: Serge Semin @ 2024-02-05 17:01 UTC (permalink / raw)
  To: Yanteng Si
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

On Tue, Jan 30, 2024 at 04:43:24PM +0800, Yanteng Si wrote:
> Add loongson_dwmac_config and moving irq config related
> code to loongson_dwmac_config.
> 

> Removing MSI to prepare for adding loongson multi-channel
> support later.

Please detach this change into a separate patch and thoroughly explain
why it was necessary.

> 
> Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
> Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
> Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
> ---
>  .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 85 ++++++++++++-------
>  1 file changed, 55 insertions(+), 30 deletions(-)
> 
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> index 979c9b6dab3f..e7ce027cc14e 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> @@ -11,8 +11,46 @@
>  
>  struct stmmac_pci_info {
>  	int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat);
> +	int (*config)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat,
> +		      struct stmmac_resources *res, struct device_node *np);
>  };
>  
> +static int loongson_dwmac_config_legacy(struct pci_dev *pdev,
> +					struct plat_stmmacenet_data *plat,
> +					struct stmmac_resources *res,
> +					struct device_node *np)
> +{
> +	if (np) {
> +		res->irq = of_irq_get_byname(np, "macirq");
> +		if (res->irq < 0) {
> +			dev_err(&pdev->dev, "IRQ macirq not found\n");
> +			return -ENODEV;
> +		}
> +
> +		res->wol_irq = of_irq_get_byname(np, "eth_wake_irq");
> +		if (res->wol_irq < 0) {
> +			dev_info(&pdev->dev,
> +				 "IRQ eth_wake_irq not found, using macirq\n");
> +			res->wol_irq = res->irq;
> +		}
> +
> +		res->lpi_irq = of_irq_get_byname(np, "eth_lpi");
> +		if (res->lpi_irq < 0) {
> +			dev_err(&pdev->dev, "IRQ eth_lpi not found\n");
> +			return -ENODEV;
> +		}
> +	} else {
> +		res->irq = pdev->irq;
> +		res->wol_irq = res->irq;
> +	}
> +

> +	plat->flags &= ~STMMAC_FLAG_MULTI_MSI_EN;
> +	dev_info(&pdev->dev, "%s: Single IRQ enablement successful\n",
> +		 __func__);

Why is this here all of the sudden? I don't see this in the original
code. Please move it to the patch which requires the flag
setup/cleanup or drop if it isn't necessary.

> +
> +	return 0;
> +}
> +
>  static void loongson_default_data(struct pci_dev *pdev,
>  				  struct plat_stmmacenet_data *plat)
>  {
> @@ -66,8 +104,21 @@ static int loongson_gmac_data(struct pci_dev *pdev,
>  	return 0;
>  }
>  

> +static int loongson_gmac_config(struct pci_dev *pdev,
> +				struct plat_stmmacenet_data *plat,
> +				struct stmmac_resources *res,
> +				struct device_node *np)
> +{
> +	int ret;
> +
> +	ret = loongson_dwmac_config_legacy(pdev, plat, res, np);
> +
> +	return ret;
> +}
> +

You introduce the config callback here and convert to a dummy method
in
[PATCH 07/11] net: stmmac: dwmac-loongson: Add multi-channel supports for loongson
It's just pointless. What about introducing the
loongson_dwmac_config_legacy() method and call it directly?

>  static struct stmmac_pci_info loongson_gmac_pci_info = {
>  	.setup = loongson_gmac_data,
> +	.config = loongson_gmac_config,
>  };
>  
>  static int loongson_dwmac_probe(struct pci_dev *pdev,
> @@ -139,44 +190,19 @@ static int loongson_dwmac_probe(struct pci_dev *pdev,
>  		plat->phy_interface = phy_mode;
>  	}
>  

> -	pci_enable_msi(pdev);

See my first note in this message.

-Serge(y)

>  	memset(&res, 0, sizeof(res));
>  	res.addr = pcim_iomap_table(pdev)[0];
>  
> -	if (np) {
> -		res.irq = of_irq_get_byname(np, "macirq");
> -		if (res.irq < 0) {
> -			dev_err(&pdev->dev, "IRQ macirq not found\n");
> -			ret = -ENODEV;
> -			goto err_disable_msi;
> -		}
> -
> -		res.wol_irq = of_irq_get_byname(np, "eth_wake_irq");
> -		if (res.wol_irq < 0) {
> -			dev_info(&pdev->dev,
> -				 "IRQ eth_wake_irq not found, using macirq\n");
> -			res.wol_irq = res.irq;
> -		}
> -
> -		res.lpi_irq = of_irq_get_byname(np, "eth_lpi");
> -		if (res.lpi_irq < 0) {
> -			dev_err(&pdev->dev, "IRQ eth_lpi not found\n");
> -			ret = -ENODEV;
> -			goto err_disable_msi;
> -		}
> -	} else {
> -		res.irq = pdev->irq;
> -		res.wol_irq = pdev->irq;
> -	}
> +	ret = info->config(pdev, plat, &res, np);
> +	if (ret)
> +		goto err_disable_device;
>  
>  	ret = stmmac_dvr_probe(&pdev->dev, plat, &res);
>  	if (ret)
> -		goto err_disable_msi;
> +		goto err_disable_device;
>  
>  	return ret;
>  
> -err_disable_msi:
> -	pci_disable_msi(pdev);
>  err_disable_device:
>  	pci_disable_device(pdev);
>  err_put_node:
> @@ -200,7 +226,6 @@ static void loongson_dwmac_remove(struct pci_dev *pdev)
>  		break;
>  	}
>  
> -	pci_disable_msi(pdev);
>  	pci_disable_device(pdev);
>  }
>  
> -- 
> 2.31.4
> 

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 05/11] net: stmmac: dwmac-loongson: Add Loongson-specific register definitions
  2024-01-30  8:48 ` [PATCH net-next v8 05/11] net: stmmac: dwmac-loongson: Add Loongson-specific register definitions Yanteng Si
@ 2024-02-05 18:17   ` Serge Semin
  2024-02-22 13:39     ` Yanteng Si
  0 siblings, 1 reply; 97+ messages in thread
From: Serge Semin @ 2024-02-05 18:17 UTC (permalink / raw)
  To: Yanteng Si
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

On Tue, Jan 30, 2024 at 04:48:17PM +0800, Yanteng Si wrote:
> There are two types of Loongson DWGMAC. The first type shares the same
> register definitions and has similar logic as dwmac1000. The second type
> uses several different register definitions, we think it is necessary to
> distinguish rx and tx, so we split these bits into two.
> 
> Simply put, we split some single bit fields into double bits fileds:
> 
>      Name              Tx          Rx
> 
> DMA_INTR_ENA_NIE = 0x00040000 | 0x00020000;
> DMA_INTR_ENA_AIE = 0x00010000 | 0x00008000;
> DMA_STATUS_NIS   = 0x00040000 | 0x00020000;
> DMA_STATUS_AIS   = 0x00010000 | 0x00008000;
> DMA_STATUS_FBI   = 0x00002000 | 0x00001000;
> 
> Therefore, when using, TX and RX must be set at the same time.
> 
> How to use them:
> 1. Create the Loongson GNET-specific
> stmmac_dma_ops.dma_interrupt()
> stmmac_dma_ops.init_chan()
> methods in the dwmac-loongson.c driver. Adding all the
> Loongson-specific macros
> 
> 2. Create a Loongson GNET-specific platform setup method with the next
> semantics:
>    + allocate stmmac_dma_ops instance and initialize it with
>      dwmac1000_dma_ops.
>    + override the stmmac_dma_ops.{dma_interrupt, init_chan} with
>      the pointers to the methods defined in 2.
>    + allocate mac_device_info instance and initialize the
>      mac_device_info.dma field with a pointer to the new
>      stmmac_dma_ops instance.
>    + initialize mac_device_info in a way it's done in
>      dwmac1000_setup().
> 
> 3. Initialize plat_stmmacenet_data.setup() with the pointer to the
> method created in 2.
> 
> Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
> Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
> Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
> ---
>  .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 248 ++++++++++++++++++
>  1 file changed, 248 insertions(+)
> 
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> index e7ce027cc14e..3b3578318cc1 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> @@ -8,6 +8,193 @@
>  #include <linux/device.h>
>  #include <linux/of_irq.h>
>  #include "stmmac.h"
> +#include "dwmac_dma.h"
> +#include "dwmac1000.h"
> +

> +#define DMA_INTR_ENA_NIE_TX_LOONGSON 0x00040000	/* Normal Loongson Tx Summary */
> +#define DMA_INTR_ENA_NIE_RX_LOONGSON 0x00020000	/* Normal Loongson Rx Summary */
> +#define DMA_INTR_NORMAL_LOONGSON	(DMA_INTR_ENA_NIE_TX_LOONGSON | \
> +			 DMA_INTR_ENA_NIE_RX_LOONGSON | DMA_INTR_ENA_RIE | \
> +			 DMA_INTR_ENA_TIE)
> +
> +#define DMA_INTR_ENA_AIE_TX_LOONGSON 0x00010000	/* Abnormal Loongson Tx Summary */
> +#define DMA_INTR_ENA_AIE_RX_LOONGSON 0x00008000	/* Abnormal Loongson Rx Summary */
> +
> +#define DMA_INTR_ABNORMAL_LOONGSON	(DMA_INTR_ENA_AIE_TX_LOONGSON | \
> +				DMA_INTR_ENA_AIE_RX_LOONGSON | DMA_INTR_ENA_FBE | \
> +				DMA_INTR_ENA_UNE)
> +
> +#define DMA_INTR_DEFAULT_MASK_LOONGSON	(DMA_INTR_NORMAL_LOONGSON | DMA_INTR_ABNORMAL_LOONGSON)
> +
> +#define DMA_STATUS_NIS_TX_LOONGSON	0x00040000	/* Normal Loongson Tx Interrupt Summary */
> +#define DMA_STATUS_NIS_RX_LOONGSON	0x00020000	/* Normal Loongson Rx Interrupt Summary */
> +
> +#define DMA_STATUS_AIS_TX_LOONGSON	0x00010000	/* Abnormal Loongson Tx Interrupt Summary */
> +#define DMA_STATUS_AIS_RX_LOONGSON	0x00008000	/* Abnormal Loongson Rx Interrupt Summary */
> +
> +#define DMA_STATUS_FBI_TX_LOONGSON	0x00002000	/* Fatal Loongson Tx Bus Error Interrupt */
> +#define DMA_STATUS_FBI_RX_LOONGSON	0x00001000	/* Fatal Loongson Rx Bus Error Interrupt */
> +
> +#define DMA_STATUS_MSK_COMMON_LOONGSON		(DMA_STATUS_NIS_TX_LOONGSON | \
> +					 DMA_STATUS_NIS_RX_LOONGSON | DMA_STATUS_AIS_TX_LOONGSON | \
> +					 DMA_STATUS_AIS_RX_LOONGSON | DMA_STATUS_FBI_TX_LOONGSON | \
> +					 DMA_STATUS_FBI_RX_LOONGSON)

Max 80 chars per line please.

> +
> +#define DMA_STATUS_MSK_RX_LOONGSON		(DMA_STATUS_ERI | \
> +					 DMA_STATUS_RWT | \
> +					 DMA_STATUS_RPS | \
> +					 DMA_STATUS_RU | \
> +					 DMA_STATUS_RI | \
> +					 DMA_STATUS_OVF | \
> +					 DMA_STATUS_MSK_COMMON_LOONGSON)
> +
> +#define DMA_STATUS_MSK_TX_LOONGSON		(DMA_STATUS_ETI | \
> +					 DMA_STATUS_UNF | \
> +					 DMA_STATUS_TJT | \
> +					 DMA_STATUS_TU | \
> +					 DMA_STATUS_TPS | \
> +					 DMA_STATUS_TI | \
> +					 DMA_STATUS_MSK_COMMON_LOONGSON)
> +

> +struct loongson_data {
> +	struct device *dev;
> +	u32 lgmac_version;

> +	struct stmmac_dma_ops dwlgmac_dma_ops;

Just figured out we can do without this field being added to the
private data. See my note in the loongson_setup() method.

> +};
> +

> +static void dwlgmac_dma_init_channel(struct stmmac_priv *priv,

The "dwlgmac_" prefix is confusing. There is the DW XLGMAC IP-core for
which the "dwxlgmac_" is more appropriate and "x" is easy to miss
should your version of the prefix is met. Consider changing it to
something like "loongson_gnet_".

> +				     void __iomem *ioaddr,
> +				     struct stmmac_dma_cfg *dma_cfg, u32 chan)
> +{
> +	u32 value;
> +	int txpbl = dma_cfg->txpbl ?: dma_cfg->pbl;
> +	int rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl;
> +
> +	/* common channel control register config */
> +	value = readl(ioaddr + DMA_CHAN_BUS_MODE(chan));
> +
> +	/* Set the DMA PBL (Programmable Burst Length) mode.
> +	 *
> +	 * Note: before stmmac core 3.50 this mode bit was 4xPBL, and
> +	 * post 3.5 mode bit acts as 8*PBL.
> +	 */
> +	if (dma_cfg->pblx8)
> +		value |= DMA_BUS_MODE_MAXPBL;
> +	value |= DMA_BUS_MODE_USP;
> +	value &= ~(DMA_BUS_MODE_PBL_MASK | DMA_BUS_MODE_RPBL_MASK);
> +	value |= (txpbl << DMA_BUS_MODE_PBL_SHIFT);
> +	value |= (rxpbl << DMA_BUS_MODE_RPBL_SHIFT);
> +
> +	/* Set the Fixed burst mode */
> +	if (dma_cfg->fixed_burst)
> +		value |= DMA_BUS_MODE_FB;
> +
> +	/* Mixed Burst has no effect when fb is set */
> +	if (dma_cfg->mixed_burst)
> +		value |= DMA_BUS_MODE_MB;
> +
> +	value |= DMA_BUS_MODE_ATDS;
> +
> +	if (dma_cfg->aal)
> +		value |= DMA_BUS_MODE_AAL;
> +
> +	writel(value, ioaddr + DMA_BUS_MODE);
> +
> +	/* Mask interrupts by writing to CSR7 */
> +	writel(DMA_INTR_DEFAULT_MASK_LOONGSON, ioaddr + DMA_INTR_ENA);
> +}
> +

> +static int dwlgmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,

The same note as above.

> +				 struct stmmac_extra_stats *x, u32 chan, u32 dir)
> +{
> +	struct stmmac_rxq_stats *rxq_stats = &priv->xstats.rxq_stats[chan];
> +	struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[chan];
> +	int ret = 0;
> +	/* read the status register (CSR5) */
> +	u32 nor_intr_status;
> +	u32 abnor_intr_status;
> +	u32 fb_intr_status;

Reverse xmas tree please.

> +	u32 intr_status = readl(ioaddr + DMA_CHAN_STATUS(chan));

Please move the initialization into a separate statement.

> +
> +#ifdef DWMAC_DMA_DEBUG
> +	/* Enable it to monitor DMA rx/tx status in case of critical problems */
> +	pr_debug("%s: [CSR5: 0x%08x]\n", __func__, intr_status);
> +	show_tx_process_state(intr_status);
> +	show_rx_process_state(intr_status);
> +#endif

This will cause a build-error if DWMAC_DMA_DEBUG is defined. Just drop
it.

> +
> +	if (dir == DMA_DIR_RX)
> +		intr_status &= DMA_STATUS_MSK_RX_LOONGSON;
> +	else if (dir == DMA_DIR_TX)
> +		intr_status &= DMA_STATUS_MSK_TX_LOONGSON;
> +
> +	nor_intr_status = intr_status & (DMA_STATUS_NIS_TX_LOONGSON |
> +		DMA_STATUS_NIS_RX_LOONGSON);
> +	abnor_intr_status = intr_status & (DMA_STATUS_AIS_TX_LOONGSON |
> +		DMA_STATUS_AIS_RX_LOONGSON);
> +	fb_intr_status = intr_status & (DMA_STATUS_FBI_TX_LOONGSON |
> +		DMA_STATUS_FBI_RX_LOONGSON);
> +
> +	/* ABNORMAL interrupts */
> +	if (unlikely(abnor_intr_status)) {
> +		if (unlikely(intr_status & DMA_STATUS_UNF)) {
> +			ret = tx_hard_error_bump_tc;
> +			x->tx_undeflow_irq++;
> +		}
> +		if (unlikely(intr_status & DMA_STATUS_TJT))
> +			x->tx_jabber_irq++;
> +
> +		if (unlikely(intr_status & DMA_STATUS_OVF))
> +			x->rx_overflow_irq++;
> +
> +		if (unlikely(intr_status & DMA_STATUS_RU))
> +			x->rx_buf_unav_irq++;
> +		if (unlikely(intr_status & DMA_STATUS_RPS))
> +			x->rx_process_stopped_irq++;
> +		if (unlikely(intr_status & DMA_STATUS_RWT))
> +			x->rx_watchdog_irq++;
> +		if (unlikely(intr_status & DMA_STATUS_ETI))
> +			x->tx_early_irq++;
> +		if (unlikely(intr_status & DMA_STATUS_TPS)) {
> +			x->tx_process_stopped_irq++;
> +			ret = tx_hard_error;
> +		}
> +		if (unlikely(intr_status & fb_intr_status)) {
> +			x->fatal_bus_error_irq++;
> +			ret = tx_hard_error;
> +		}
> +	}
> +	/* TX/RX NORMAL interrupts */
> +	if (likely(nor_intr_status)) {
> +		if (likely(intr_status & DMA_STATUS_RI)) {
> +			u32 value = readl(ioaddr + DMA_INTR_ENA);
> +			/* to schedule NAPI on real RIE event. */
> +			if (likely(value & DMA_INTR_ENA_RIE)) {
> +				u64_stats_update_begin(&rxq_stats->syncp);
> +				rxq_stats->rx_normal_irq_n++;
> +				u64_stats_update_end(&rxq_stats->syncp);
> +				ret |= handle_rx;
> +			}
> +		}
> +		if (likely(intr_status & DMA_STATUS_TI)) {
> +			u64_stats_update_begin(&txq_stats->syncp);
> +			txq_stats->tx_normal_irq_n++;
> +			u64_stats_update_end(&txq_stats->syncp);
> +			ret |= handle_tx;
> +		}
> +		if (unlikely(intr_status & DMA_STATUS_ERI))
> +			x->rx_early_irq++;
> +	}
> +	/* Optional hardware blocks, interrupts should be disabled */
> +	if (unlikely(intr_status &
> +		     (DMA_STATUS_GPI | DMA_STATUS_GMI | DMA_STATUS_GLI)))
> +		pr_warn("%s: unexpected status %08x\n", __func__, intr_status);
> +
> +	/* Clear the interrupt by writing a logic 1 to the CSR5[15-0] */
> +	writel((intr_status & 0x7ffff), ioaddr + DMA_CHAN_STATUS(chan));
> +
> +	return ret;
> +}
>  
>  struct stmmac_pci_info {
>  	int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat);
> @@ -121,6 +308,48 @@ static struct stmmac_pci_info loongson_gmac_pci_info = {
>  	.config = loongson_gmac_config,
>  };
>  

> +static struct mac_device_info *loongson_setup(void *apriv)

Consider using the GNET-specific prefix, like "loongson_gnet_".

> +{
> +	struct stmmac_priv *priv = apriv;
> +	struct mac_device_info *mac;
> +	struct loongson_data *ld;
> +
> +	mac = devm_kzalloc(priv->device, sizeof(*mac), GFP_KERNEL);
> +	if (!mac)
> +		return NULL;

What about devm_kzalloc()-ing the stmmac_dma_ops instance here and
initializing it as it's done in the probe method? Thus ...

> +
> +	ld = priv->plat->bsp_priv;
> +	mac->dma = &ld->dwlgmac_dma_ops;

... this can be replaced with:

	mac->dma = devm_kzalloc(priv->device, sizeof(*mac->dma), GFP_KERNEL);
	if (!mac->dma)
		return -ENOMEM;

	*mac->dma = dwmac1000_dma_ops;
	mac->dma->init_chan = loongson_gnet_dma_init_channel;
	mac->dma->dma_interrupt = loongson_gnet_dma_interrupt;

> +
> +	/* Pre-initialize the respective "mac" fields as it's done in
> +	 * dwmac1000_setup()
> +	 */
> +	priv->dev->priv_flags |= IFF_UNICAST_FLT;
> +	mac->pcsr = priv->ioaddr;
> +	mac->multicast_filter_bins = priv->plat->multicast_filter_bins;
> +	mac->unicast_filter_entries = priv->plat->unicast_filter_entries;
> +	mac->mcast_bits_log2 = 0;
> +
> +	if (mac->multicast_filter_bins)
> +		mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins);
> +
> +	mac->link.duplex = GMAC_CONTROL_DM;
> +	mac->link.speed10 = GMAC_CONTROL_PS;
> +	mac->link.speed100 = GMAC_CONTROL_PS | GMAC_CONTROL_FES;
> +	mac->link.speed1000 = 0;
> +	mac->link.speed_mask = GMAC_CONTROL_PS | GMAC_CONTROL_FES;
> +	mac->mii.addr = GMAC_MII_ADDR;
> +	mac->mii.data = GMAC_MII_DATA;
> +	mac->mii.addr_shift = 11;
> +	mac->mii.addr_mask = 0x0000F800;
> +	mac->mii.reg_shift = 6;
> +	mac->mii.reg_mask = 0x000007C0;
> +	mac->mii.clk_csr_shift = 2;
> +	mac->mii.clk_csr_mask = GENMASK(5, 2);
> +
> +	return mac;
> +}
> +
>  static int loongson_dwmac_probe(struct pci_dev *pdev,
>  				const struct pci_device_id *id)
>  {
> @@ -129,6 +358,7 @@ static int loongson_dwmac_probe(struct pci_dev *pdev,
>  	struct stmmac_pci_info *info;
>  	struct stmmac_resources res;
>  	struct device_node *np;
> +	struct loongson_data *ld;

reverse xmas tree order please.

>  
>  	plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL);
>  	if (!plat)
> @@ -145,6 +375,10 @@ static int loongson_dwmac_probe(struct pci_dev *pdev,
>  	if (!plat->dma_cfg)
>  		return -ENOMEM;
>  
> +	ld = devm_kzalloc(&pdev->dev, sizeof(*ld), GFP_KERNEL);
> +	if (!ld)
> +		return -ENOMEM;
> +
>  	np = dev_of_node(&pdev->dev);
>  	plat->mdio_node = of_get_child_by_name(np, "mdio");
>  	if (plat->mdio_node) {
> @@ -197,6 +431,20 @@ static int loongson_dwmac_probe(struct pci_dev *pdev,
>  	if (ret)
>  		goto err_disable_device;
>  
> +	ld->dev = &pdev->dev;

> +	ld->lgmac_version = readl(res.addr + GMAC_VERSION) & 0xff;

AFAICS the lgmac_version is unused in out of the probe() method
context. What about locally defining it?

> +
> +	/* Activate loongson custom ip */

> +	if (ld->lgmac_version < DWMAC_CORE_3_50) {

Please define a new macro for the GNET MAC.

> +		ld->dwlgmac_dma_ops = dwmac1000_dma_ops;
> +		ld->dwlgmac_dma_ops.init_chan = dwlgmac_dma_init_channel;
> +		ld->dwlgmac_dma_ops.dma_interrupt = dwlgmac_dma_interrupt;

See my comment in the loongson_setup() method.

-Serge(y)

> +
> +		plat->setup = loongson_setup;
> +	}
> +
> +	plat->bsp_priv = ld;
> +
>  	ret = stmmac_dvr_probe(&pdev->dev, plat, &res);
>  	if (ret)
>  		goto err_disable_device;
> -- 
> 2.31.4
> 

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 06/11] net: stmmac: dwmac-loongson: Add GNET support
  2024-01-30  8:48 ` [PATCH net-next v8 06/11] net: stmmac: dwmac-loongson: Add GNET support Yanteng Si
@ 2024-02-05 20:58   ` Serge Semin
       [not found]     ` <d0e56c9b-9549-4061-8e44-2504b6b96897@loongson.cn>
  0 siblings, 1 reply; 97+ messages in thread
From: Serge Semin @ 2024-02-05 20:58 UTC (permalink / raw)
  To: Yanteng Si
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

On Tue, Jan 30, 2024 at 04:48:18PM +0800, Yanteng Si wrote:
> Add Loongson GNET (GMAC with PHY) support, override
> stmmac_priv.synopsys_id with 0x37.

Please add more details of all the device capabilities: supported
speeds, duplexness, IP-core version, DMA-descriptors type
(normal/enhanced), MTL Tx/Rx FIFO size, Perfect and Hash-based MAC
Filter tables size, L3/L4 filters availability, VLAN hash table
filter, PHY-interface (GMII, RGMII, etc), EEE support,
AV-feature/Multi-channels support, IEEE 1588 Timestamp support, Magic
Frame support, Remote Wake-up support, IP Checksum, Tx/Rx TCP/IP
Checksum, Mac Management Counters (MMC), SMA/MDIO interface, 

> 
> Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
> Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
> Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
> ---
>  .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 44 +++++++++++++++++++
>  1 file changed, 44 insertions(+)
> 
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> index 3b3578318cc1..584f7322bd3e 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> @@ -318,6 +318,8 @@ static struct mac_device_info *loongson_setup(void *apriv)
>  	if (!mac)
>  		return NULL;
>  

> +	priv->synopsys_id = 0x37;	/*Overwrite custom IP*/
> +

Please add a more descriptive comment _above_ the subjected line. In
particular note why the override is needed, what is the real DW GMAC
IP-core version and what is the original value the statement above
overrides.

>  	ld = priv->plat->bsp_priv;
>  	mac->dma = &ld->dwlgmac_dma_ops;
>  
> @@ -350,6 +352,46 @@ static struct mac_device_info *loongson_setup(void *apriv)
>  	return mac;
>  }
>  
> +static int loongson_gnet_data(struct pci_dev *pdev,
> +			      struct plat_stmmacenet_data *plat)
> +{
> +	loongson_default_data(pdev, plat);
> +
> +	plat->multicast_filter_bins = 256;
> +
> +	plat->mdio_bus_data->phy_mask =  ~(u32)BIT(2);
> +
> +	plat->phy_addr = 2;

> +	plat->phy_interface = PHY_INTERFACE_MODE_INTERNAL;

Are you sure PHY-interface is supposed to be defined as "internal"? 

> +
> +	plat->bsp_priv = &pdev->dev;
> +
> +	plat->dma_cfg->pbl = 32;
> +	plat->dma_cfg->pblx8 = true;
> +
> +	plat->clk_ref_rate = 125000000;
> +	plat->clk_ptp_rate = 125000000;
> +
> +	return 0;
> +}
> +
> +static int loongson_gnet_config(struct pci_dev *pdev,
> +				struct plat_stmmacenet_data *plat,
> +				struct stmmac_resources *res,
> +				struct device_node *np)
> +{
> +	int ret;
> +

> +	ret = loongson_dwmac_config_legacy(pdev, plat, res, np);

Again. This will be moved to the probe() method in one of the next
patches leaving loongson_gnet_config() empty. What was the problem
with doing that right away with no intermediate change?

> +
> +	return ret;
> +}
> +
> +static struct stmmac_pci_info loongson_gnet_pci_info = {
> +	.setup = loongson_gnet_data,
> +	.config = loongson_gnet_config,
> +};
> +
>  static int loongson_dwmac_probe(struct pci_dev *pdev,
>  				const struct pci_device_id *id)
>  {
> @@ -516,9 +558,11 @@ static SIMPLE_DEV_PM_OPS(loongson_dwmac_pm_ops, loongson_dwmac_suspend,
>  			 loongson_dwmac_resume);
>  
>  #define PCI_DEVICE_ID_LOONGSON_GMAC	0x7a03

> +#define PCI_DEVICE_ID_LOONGSON_GNET	0x7a13
>  
>  static const struct pci_device_id loongson_dwmac_id_table[] = {
>  	{ PCI_DEVICE_DATA(LOONGSON, GMAC, &loongson_gmac_pci_info) },
> +	{ PCI_DEVICE_DATA(LOONGSON, GNET, &loongson_gnet_pci_info) },

After this the driver is supposed to correctly handle the Loongson
GNET devices. Based on the patches introduced further it isn't.
Please consider re-arranging the changes (see my comments in the
further patches).

-Serge(y)

>  	{}
>  };
>  MODULE_DEVICE_TABLE(pci, loongson_dwmac_id_table);
> -- 
> 2.31.4
> 

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 07/11] net: stmmac: dwmac-loongson: Add multi-channel supports for loongson
  2024-01-30  8:48 ` [PATCH net-next v8 07/11] net: stmmac: dwmac-loongson: Add multi-channel supports for loongson Yanteng Si
@ 2024-02-05 21:28   ` Serge Semin
       [not found]     ` <e1c7b5fa-f3f8-4aa3-af4d-ca72b54d9c8c@loongson.cn>
  0 siblings, 1 reply; 97+ messages in thread
From: Serge Semin @ 2024-02-05 21:28 UTC (permalink / raw)
  To: Yanteng Si
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

On Tue, Jan 30, 2024 at 04:48:19PM +0800, Yanteng Si wrote:
> Request allocation for MSI for specific versions.
>

Please elaborate what is actually done in the patch. What device
version it is dedicated for (Loongson GNET?), what IRQs the patch
adds, etc.

BTW will GNET device work without this patch? If no you need to either
merge it into the patch introducing the GNET-device support or place
it before that patch (6/11).
 
> Some features of Loongson platforms are bound to the GMAC_VERSION
> register. We have to read its value in order to get the correct channel
> number.

This message seems misleading. I don't see you doing that in the patch below...

> 
> Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
> Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
> Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
> ---
>  .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 57 +++++++++++++++----
>  1 file changed, 46 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> index 584f7322bd3e..60d0a122d7c9 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> @@ -98,10 +98,10 @@ static void dwlgmac_dma_init_channel(struct stmmac_priv *priv,
>  	if (dma_cfg->aal)
>  		value |= DMA_BUS_MODE_AAL;
> 
 
> -	writel(value, ioaddr + DMA_BUS_MODE);
> +	writel(value, ioaddr + DMA_CHAN_BUS_MODE(chan));
>  
>  	/* Mask interrupts by writing to CSR7 */
> -	writel(DMA_INTR_DEFAULT_MASK_LOONGSON, ioaddr + DMA_INTR_ENA);
> +	writel(DMA_INTR_DEFAULT_MASK_LOONGSON, ioaddr + DMA_CHAN_INTR_ENA(chan));

Em, why is this here? There is a patch
[PATCH net-next v8 05/11] net: stmmac: dwmac-loongson: Add Loongson-specific register definitions
in this series which was supposed to introduce the fully functional
GNET-specific callbacks. Move this change in there.

>  }
>  
>  static int dwlgmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
> @@ -238,6 +238,45 @@ static int loongson_dwmac_config_legacy(struct pci_dev *pdev,
>  	return 0;
>  }
>  

> +static int loongson_dwmac_config_multi_msi(struct pci_dev *pdev,

This method seems like the GNET-specific one. What about using the
appropriate prefix then?

> +					   struct plat_stmmacenet_data *plat,
> +					   struct stmmac_resources *res,
> +					   struct device_node *np,

> +					   int channel_num)

Why do you need this parametrization? Since this method is
GNET-specific what about defining a macro with the channels amount and
using it here?

> +{
> +	int i, ret, vecs;
> +
> +	vecs = roundup_pow_of_two(channel_num * 2 + 1);
> +	ret = pci_alloc_irq_vectors(pdev, vecs, vecs, PCI_IRQ_MSI);

> +	if (ret < 0) {
> +		dev_info(&pdev->dev,
> +			 "MSI enable failed, Fallback to legacy interrupt\n");
> +		return loongson_dwmac_config_legacy(pdev, plat, res, np);

In what conditions is this possible? Will the
loongson_dwmac_config_legacy() method work in that case? Did you test
it out?

> +	}
> +

> +	plat->rx_queues_to_use = channel_num;
> +	plat->tx_queues_to_use = channel_num;

This is supposed to be initialized in the setup() methods. Please move
it to the dedicated patch.

> +
> +	res->irq = pci_irq_vector(pdev, 0);

> +	res->wol_irq = res->irq;

Once again. wol_irq is optional. If there is no dedicated WoL IRQ
leave the field as zero.

> +
> +	/* INT NAME | MAC | CH7 rx | CH7 tx | ... | CH0 rx | CH0 tx |
> +	 * --------- ----- -------- --------  ...  -------- --------
> +	 * IRQ NUM  |  0  |   1    |   2    | ... |   15   |   16   |
> +	 */
> +	for (i = 0; i < channel_num; i++) {
> +		res->rx_irq[channel_num - 1 - i] =
> +			pci_irq_vector(pdev, 1 + i * 2);
> +		res->tx_irq[channel_num - 1 - i] =
> +			pci_irq_vector(pdev, 2 + i * 2);
> +	}
> +
> +	plat->flags |= STMMAC_FLAG_MULTI_MSI_EN;

> +	dev_info(&pdev->dev, "%s: multi MSI enablement successful\n", __func__);

What's the point in printing this message especially with the __func__
prefix?  You'll always be able to figure out the allocated IRQs by
means of procfs. I suggest to drop it.

> +
> +	return 0;
> +}
> +

>  static void loongson_default_data(struct pci_dev *pdev,
>  				  struct plat_stmmacenet_data *plat)
>  {
> @@ -296,11 +335,8 @@ static int loongson_gmac_config(struct pci_dev *pdev,
>  				struct stmmac_resources *res,
>  				struct device_node *np)
>  {
> -	int ret;
> -
> -	ret = loongson_dwmac_config_legacy(pdev, plat, res, np);
>  
> -	return ret;
> +	return 0;
>  }
>  
>  static struct stmmac_pci_info loongson_gmac_pci_info = {
> @@ -380,11 +416,7 @@ static int loongson_gnet_config(struct pci_dev *pdev,
>  				struct stmmac_resources *res,
>  				struct device_node *np)
>  {
> -	int ret;
> -
> -	ret = loongson_dwmac_config_legacy(pdev, plat, res, np);
> -
> -	return ret;
> +	return 0;
>  }

Here you are dropping the changes you just introduced leaving the
config() methods empty... Why not to place the
loongson_dwmac_config_legacy() invocation in the probe() method right
at the patches introducing the config() functions and not to add the
config() callback in the first place?

-Serge(y)

>  
>  static struct stmmac_pci_info loongson_gnet_pci_info = {
> @@ -483,6 +515,9 @@ static int loongson_dwmac_probe(struct pci_dev *pdev,
>  		ld->dwlgmac_dma_ops.dma_interrupt = dwlgmac_dma_interrupt;
>  
>  		plat->setup = loongson_setup;
> +		ret = loongson_dwmac_config_multi_msi(pdev, plat, &res, np, 8);
> +	} else {
> +		ret = loongson_dwmac_config_legacy(pdev, plat, &res, np);
>  	}
>  
>  	plat->bsp_priv = ld;
> -- 
> 2.31.4
> 

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 08/11] net: stmmac: dwmac-loongson: Fix MAC speed for GNET
  2024-01-30  8:48 ` [PATCH net-next v8 08/11] net: stmmac: dwmac-loongson: Fix MAC speed for GNET Yanteng Si
@ 2024-02-05 21:55   ` Serge Semin
       [not found]     ` <4873ea5a-1b23-4512-b039-0a9198b53adf@loongson.cn>
  0 siblings, 1 reply; 97+ messages in thread
From: Serge Semin @ 2024-02-05 21:55 UTC (permalink / raw)
  To: Yanteng Si
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

On Tue, Jan 30, 2024 at 04:48:20PM +0800, Yanteng Si wrote:
> Current GNET on LS7A only supports ANE when speed is
> set to 1000M.

If so you need to merge it into the patch
[PATCH net-next v8 06/11] net: stmmac: dwmac-loongson: Add GNET support

> 
> Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
> Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
> Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
> ---
>  .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 19 +++++++++++++++++++
>  .../ethernet/stmicro/stmmac/stmmac_ethtool.c  |  6 ++++++
>  include/linux/stmmac.h                        |  1 +
>  3 files changed, 26 insertions(+)
> 
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> index 60d0a122d7c9..264c4c198d5a 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> @@ -344,6 +344,21 @@ static struct stmmac_pci_info loongson_gmac_pci_info = {
>  	.config = loongson_gmac_config,
>  };
>  
> +static void loongson_gnet_fix_speed(void *priv, unsigned int speed, unsigned int mode)
> +{
> +	struct loongson_data *ld = (struct loongson_data *)priv;
> +	struct net_device *ndev = dev_get_drvdata(ld->dev);
> +	struct stmmac_priv *ptr = netdev_priv(ndev);
> +

> +	/* The controller and PHY don't work well together.

So there _is_ a PHY. What is the interface between MAC and PHY then?

> +	 * We need to use the PS bit to check if the controller's status
> +	 * is correct and reset PHY if necessary.
> +	 */

> +	if (speed == SPEED_1000)
> +		if (readl(ptr->ioaddr + MAC_CTRL_REG) & (1 << 15) /* PS */)
> +			phy_restart_aneg(ndev->phydev);

1. Please add curly braces for the outer if-statement.
2. MAC_CTRL_REG.15 is defined by the GMAC_CONTROL_PS macro.
3. How is the AN-restart helps? PHY-reset is done in
stmmac_init_phy()->phylink_connect_phy()->... a bit earlier than
this is called in the framework of the stmmac_mac_link_up() callback.
Wouldn't that restart AN too?

> +}
> +
>  static struct mac_device_info *loongson_setup(void *apriv)
>  {
>  	struct stmmac_priv *priv = apriv;
> @@ -401,6 +416,7 @@ static int loongson_gnet_data(struct pci_dev *pdev,
>  	plat->phy_interface = PHY_INTERFACE_MODE_INTERNAL;
>  
>  	plat->bsp_priv = &pdev->dev;
> +	plat->fix_mac_speed = loongson_gnet_fix_speed;
>  
>  	plat->dma_cfg->pbl = 32;
>  	plat->dma_cfg->pblx8 = true;
> @@ -416,6 +432,9 @@ static int loongson_gnet_config(struct pci_dev *pdev,
>  				struct stmmac_resources *res,
>  				struct device_node *np)
>  {

> +	if (pdev->revision == 0x00 || pdev->revision == 0x01)
> +		plat->flags |= STMMAC_FLAG_DISABLE_FORCE_1000;
> +

This should be in the patch
[PATCH net-next v8 06/11] net: stmmac: dwmac-loongson: Add GNET support

>  	return 0;
>  }
>  
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> index 42d27b97dd1d..31068fbc23c9 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> @@ -422,6 +422,12 @@ stmmac_ethtool_set_link_ksettings(struct net_device *dev,
>  		return 0;
>  	}
>  

> +	if (FIELD_GET(STMMAC_FLAG_DISABLE_FORCE_1000, priv->plat->flags)) {

FIELD_GET()?

> +		if (cmd->base.speed == SPEED_1000 &&
> +		    cmd->base.autoneg != AUTONEG_ENABLE)
> +			return -EOPNOTSUPP;
> +	}
> +
>  	return phylink_ethtool_ksettings_set(priv->phylink, cmd);
>  }
>  
> diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
> index dee5ad6e48c5..2810361e4048 100644
> --- a/include/linux/stmmac.h
> +++ b/include/linux/stmmac.h
> @@ -221,6 +221,7 @@ struct dwmac4_addrs {
>  #define STMMAC_FLAG_RX_CLK_RUNS_IN_LPI		BIT(10)
>  #define STMMAC_FLAG_EN_TX_LPI_CLOCKGATING	BIT(11)
>  #define STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY	BIT(12)
> +#define STMMAC_FLAG_DISABLE_FORCE_1000	BIT(13)

Detach the change introducing the STMMAC_FLAG_DISABLE_FORCE_1000 flag
into a separate patch a place it before
[PATCH net-next v8 06/11] net: stmmac: dwmac-loongson: Add GNET support
as a pre-requisite/preparation patch.
Don't forget a _detailed_ description of why it's necessary, what is
wrong with GNET so 1G speed doesn't work without AN.

-Serge(y)

>  
>  struct plat_stmmacenet_data {
>  	int bus_id;
> -- 
> 2.31.4
> 

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 09/11] net: stmmac: dwmac-loongson: Fix half duplex
  2024-01-30  8:49 ` [PATCH net-next v8 09/11] net: stmmac: dwmac-loongson: Fix half duplex Yanteng Si
@ 2024-02-05 21:58   ` Serge Semin
  2024-02-05 22:06     ` Serge Semin
  0 siblings, 1 reply; 97+ messages in thread
From: Serge Semin @ 2024-02-05 21:58 UTC (permalink / raw)
  To: Yanteng Si
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

On Tue, Jan 30, 2024 at 04:49:14PM +0800, Yanteng Si wrote:
> Current GNET does not support half duplex mode.
> 
> Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
> Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
> Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
> ---
>  drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c | 11 ++++++++++-
>  drivers/net/ethernet/stmicro/stmmac/stmmac_main.c    |  3 ++-
>  include/linux/stmmac.h                               |  1 +
>  3 files changed, 13 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> index 264c4c198d5a..1753a3c46b77 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> @@ -432,8 +432,17 @@ static int loongson_gnet_config(struct pci_dev *pdev,
>  				struct stmmac_resources *res,
>  				struct device_node *np)
>  {

> -	if (pdev->revision == 0x00 || pdev->revision == 0x01)
> +	switch (pdev->revision) {
> +	case 0x00:
> +		plat->flags |= STMMAC_FLAG_DISABLE_FORCE_1000 |
> +			       STMMAC_FLAG_DISABLE_HALF_DUPLEX;
> +		break;
> +	case 0x01:
>  		plat->flags |= STMMAC_FLAG_DISABLE_FORCE_1000;
> +		break;
> +	default:
> +		break;
> +	}

Move this change into the patch
[PATCH net-next v8 06/11] net: stmmac: dwmac-loongson: Add GNET support

>  
>  	return 0;
>  }
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> index 5617b40abbe4..3aa862269eb0 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> @@ -1201,7 +1201,8 @@ static int stmmac_init_phy(struct net_device *dev)
>  static void stmmac_set_half_duplex(struct stmmac_priv *priv)
>  {

>  	/* Half-Duplex can only work with single tx queue */
> -	if (priv->plat->tx_queues_to_use > 1)
> +	if (priv->plat->tx_queues_to_use > 1 ||
> +	    (STMMAC_FLAG_DISABLE_HALF_DUPLEX & priv->plat->flags))
>  		priv->phylink_config.mac_capabilities &=
>  			~(MAC_10HD | MAC_100HD | MAC_1000HD);
>  	else
> diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
> index 2810361e4048..197f6f914104 100644
> --- a/include/linux/stmmac.h
> +++ b/include/linux/stmmac.h
> @@ -222,6 +222,7 @@ struct dwmac4_addrs {
>  #define STMMAC_FLAG_EN_TX_LPI_CLOCKGATING	BIT(11)
>  #define STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY	BIT(12)
>  #define STMMAC_FLAG_DISABLE_FORCE_1000	BIT(13)
> +#define STMMAC_FLAG_DISABLE_HALF_DUPLEX	BIT(14)
>  

Place the patch with this change before
[PATCH net-next v8 06/11] net: stmmac: dwmac-loongson: Add GNET support
as a pre-requisite/preparation patch. Don't forget a thorough
description of what is wrong with the GNET Half-Duplex mode.

-Serge(y)

>  struct plat_stmmacenet_data {
>  	int bus_id;
> -- 
> 2.31.4
> 

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 09/11] net: stmmac: dwmac-loongson: Fix half duplex
  2024-02-05 21:58   ` Serge Semin
@ 2024-02-05 22:06     ` Serge Semin
  2024-03-13  9:24       ` Yanteng Si
  0 siblings, 1 reply; 97+ messages in thread
From: Serge Semin @ 2024-02-05 22:06 UTC (permalink / raw)
  To: Yanteng Si
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

On Tue, Feb 06, 2024 at 12:58:17AM +0300, Serge Semin wrote:
> On Tue, Jan 30, 2024 at 04:49:14PM +0800, Yanteng Si wrote:
> > Current GNET does not support half duplex mode.
> > 
> > Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
> > Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
> > Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
> > ---
> >  drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c | 11 ++++++++++-
> >  drivers/net/ethernet/stmicro/stmmac/stmmac_main.c    |  3 ++-
> >  include/linux/stmmac.h                               |  1 +
> >  3 files changed, 13 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > index 264c4c198d5a..1753a3c46b77 100644
> > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > @@ -432,8 +432,17 @@ static int loongson_gnet_config(struct pci_dev *pdev,
> >  				struct stmmac_resources *res,
> >  				struct device_node *np)
> >  {
> 
> > -	if (pdev->revision == 0x00 || pdev->revision == 0x01)
> > +	switch (pdev->revision) {
> > +	case 0x00:
> > +		plat->flags |= STMMAC_FLAG_DISABLE_FORCE_1000 |
> > +			       STMMAC_FLAG_DISABLE_HALF_DUPLEX;
> > +		break;
> > +	case 0x01:
> >  		plat->flags |= STMMAC_FLAG_DISABLE_FORCE_1000;
> > +		break;
> > +	default:
> > +		break;
> > +	}
> 
> Move this change into the patch
> [PATCH net-next v8 06/11] net: stmmac: dwmac-loongson: Add GNET support
> 
> >  
> >  	return 0;
> >  }
> > diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> > index 5617b40abbe4..3aa862269eb0 100644
> > --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> > +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> > @@ -1201,7 +1201,8 @@ static int stmmac_init_phy(struct net_device *dev)
> >  static void stmmac_set_half_duplex(struct stmmac_priv *priv)
> >  {
> 

> >  	/* Half-Duplex can only work with single tx queue */
> > -	if (priv->plat->tx_queues_to_use > 1)
> > +	if (priv->plat->tx_queues_to_use > 1 ||
> > +	    (STMMAC_FLAG_DISABLE_HALF_DUPLEX & priv->plat->flags))
> >  		priv->phylink_config.mac_capabilities &=
> >  			~(MAC_10HD | MAC_100HD | MAC_1000HD);
> >  	else
> > diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
> > index 2810361e4048..197f6f914104 100644
> > --- a/include/linux/stmmac.h
> > +++ b/include/linux/stmmac.h
> > @@ -222,6 +222,7 @@ struct dwmac4_addrs {
> >  #define STMMAC_FLAG_EN_TX_LPI_CLOCKGATING	BIT(11)
> >  #define STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY	BIT(12)
> >  #define STMMAC_FLAG_DISABLE_FORCE_1000	BIT(13)
> > +#define STMMAC_FLAG_DISABLE_HALF_DUPLEX	BIT(14)
> >  
> 
> Place the patch with this change before
> [PATCH net-next v8 06/11] net: stmmac: dwmac-loongson: Add GNET support
> as a pre-requisite/preparation patch. Don't forget a thorough
> description of what is wrong with the GNET Half-Duplex mode.

BTW what about re-defining the stmmac_ops.phylink_get_caps() callback
instead of adding fixup flags in this patch and in the next one?

-Serge()

> 
> -Serge(y)
> 
> >  struct plat_stmmacenet_data {
> >  	int bus_id;
> > -- 
> > 2.31.4
> > 

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 10/11] net: stmmac: dwmac-loongson: Disable flow control for GMAC
  2024-01-30  8:49 ` [PATCH net-next v8 10/11] net: stmmac: dwmac-loongson: Disable flow control for GMAC Yanteng Si
@ 2024-02-05 22:13   ` Serge Semin
  2024-03-13  9:25     ` Yanteng Si
  0 siblings, 1 reply; 97+ messages in thread
From: Serge Semin @ 2024-02-05 22:13 UTC (permalink / raw)
  To: Yanteng Si
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

On Tue, Jan 30, 2024 at 04:49:15PM +0800, Yanteng Si wrote:
> Loongson GMAC does not support Flow Control feature. Set flags to
> disable it.
> 
> Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
> Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
> Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
> ---
>  drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c | 1 +
>  drivers/net/ethernet/stmicro/stmmac/stmmac_main.c    | 6 +++---
>  include/linux/stmmac.h                               | 1 +
>  3 files changed, 5 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> index 1753a3c46b77..b78a73ea748b 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> @@ -335,6 +335,7 @@ static int loongson_gmac_config(struct pci_dev *pdev,
>  				struct stmmac_resources *res,
>  				struct device_node *np)
>  {
> +	plat->flags |= STMMAC_FLAG_DISABLE_FLOW_CONTROL;
>  
>  	return 0;
>  }
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> index 3aa862269eb0..8d676cbfba1e 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> @@ -1237,9 +1237,9 @@ static int stmmac_phy_setup(struct stmmac_priv *priv)
>  		xpcs_get_interfaces(priv->hw->xpcs,
>  				    priv->phylink_config.supported_interfaces);
>  
> -	priv->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
> -						MAC_10FD | MAC_100FD |
> -						MAC_1000FD;
> +	priv->phylink_config.mac_capabilities = MAC_10FD | MAC_100FD | MAC_1000FD;
> +	if (!(priv->plat->flags & STMMAC_FLAG_DISABLE_FLOW_CONTROL))
> +		priv->phylink_config.mac_capabilities |= MAC_ASYM_PAUSE | MAC_SYM_PAUSE;
>  
>  	stmmac_set_half_duplex(priv);
>  
> diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
> index 197f6f914104..832cd8cd688f 100644
> --- a/include/linux/stmmac.h
> +++ b/include/linux/stmmac.h
> @@ -223,6 +223,7 @@ struct dwmac4_addrs {
>  #define STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY	BIT(12)
>  #define STMMAC_FLAG_DISABLE_FORCE_1000	BIT(13)
>  #define STMMAC_FLAG_DISABLE_HALF_DUPLEX	BIT(14)
> +#define STMMAC_FLAG_DISABLE_FLOW_CONTROL	BIT(15)

See my last comment in patch 9/11. This can be reached by re-defining
the stmmac_ops::phylink_get_caps() callback.

-Serge(y)

>  
>  struct plat_stmmacenet_data {
>  	int bus_id;
> -- 
> 2.31.4
> 

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 11/11] net: stmmac: dwmac-loongson: Disable coe for some Loongson GNET
  2024-01-30  8:49 ` [PATCH net-next v8 11/11] net: stmmac: dwmac-loongson: Disable coe for some Loongson GNET Yanteng Si
@ 2024-02-05 22:18   ` Serge Semin
  2024-03-13  9:52     ` Yanteng Si
  0 siblings, 1 reply; 97+ messages in thread
From: Serge Semin @ 2024-02-05 22:18 UTC (permalink / raw)
  To: Yanteng Si
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

On Tue, Jan 30, 2024 at 04:49:16PM +0800, Yanteng Si wrote:
> Some chips of Loongson GNET does not support coe, so disable them.

s/coe/Tx COE

> 
> Set dma_cap->tx_coe to 0 and overwrite get_hw_feature.
> 
> Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
> Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
> Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
> ---
>  .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 46 +++++++++++++++++++
>  1 file changed, 46 insertions(+)
> 
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> index b78a73ea748b..8018d7d5f31b 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> @@ -196,6 +196,51 @@ static int dwlgmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
>  	return ret;
>  }
>  

> +static int dwlgmac_get_hw_feature(void __iomem *ioaddr,

Please use GNET-specific prefix.

> +				  struct dma_features *dma_cap)
> +{
> +	u32 hw_cap = readl(ioaddr + DMA_HW_FEATURE);
> +

> +	if (!hw_cap) {
> +		/* 0x00000000 is the value read on old hardware that does not
> +		 * implement this register
> +		 */
> +		return -EOPNOTSUPP;
> +	}

This doesn't seems like possible. All your devices have the
HW-features register. If so please drop.

> +
> +	dma_cap->mbps_10_100 = (hw_cap & DMA_HW_FEAT_MIISEL);
> +	dma_cap->mbps_1000 = (hw_cap & DMA_HW_FEAT_GMIISEL) >> 1;
> +	dma_cap->half_duplex = (hw_cap & DMA_HW_FEAT_HDSEL) >> 2;
> +	dma_cap->hash_filter = (hw_cap & DMA_HW_FEAT_HASHSEL) >> 4;
> +	dma_cap->multi_addr = (hw_cap & DMA_HW_FEAT_ADDMAC) >> 5;
> +	dma_cap->pcs = (hw_cap & DMA_HW_FEAT_PCSSEL) >> 6;
> +	dma_cap->sma_mdio = (hw_cap & DMA_HW_FEAT_SMASEL) >> 8;
> +	dma_cap->pmt_remote_wake_up = (hw_cap & DMA_HW_FEAT_RWKSEL) >> 9;
> +	dma_cap->pmt_magic_frame = (hw_cap & DMA_HW_FEAT_MGKSEL) >> 10;
> +	/* MMC */
> +	dma_cap->rmon = (hw_cap & DMA_HW_FEAT_MMCSEL) >> 11;
> +	/* IEEE 1588-2002 */
> +	dma_cap->time_stamp =
> +	    (hw_cap & DMA_HW_FEAT_TSVER1SEL) >> 12;
> +	/* IEEE 1588-2008 */
> +	dma_cap->atime_stamp = (hw_cap & DMA_HW_FEAT_TSVER2SEL) >> 13;
> +	/* 802.3az - Energy-Efficient Ethernet (EEE) */
> +	dma_cap->eee = (hw_cap & DMA_HW_FEAT_EEESEL) >> 14;
> +	dma_cap->av = (hw_cap & DMA_HW_FEAT_AVSEL) >> 15;
> +	/* TX and RX csum */
> +	dma_cap->tx_coe = 0;
> +	dma_cap->rx_coe_type1 = (hw_cap & DMA_HW_FEAT_RXTYP1COE) >> 17;
> +	dma_cap->rx_coe_type2 = (hw_cap & DMA_HW_FEAT_RXTYP2COE) >> 18;
> +	dma_cap->rxfifo_over_2048 = (hw_cap & DMA_HW_FEAT_RXFIFOSIZE) >> 19;
> +	/* TX and RX number of channels */
> +	dma_cap->number_rx_channel = (hw_cap & DMA_HW_FEAT_RXCHCNT) >> 20;
> +	dma_cap->number_tx_channel = (hw_cap & DMA_HW_FEAT_TXCHCNT) >> 22;
> +	/* Alternate (enhanced) DESC mode */
> +	dma_cap->enh_desc = (hw_cap & DMA_HW_FEAT_ENHDESSEL) >> 24;

I am not sure whether you need to parse the capability register at all
seeing this is a GNET-specific method. For that device all the
capabilities are already known and can be just initialized in this
method.

-Serge(y)

> +
> +	return 0;
> +}
> +
>  struct stmmac_pci_info {
>  	int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat);
>  	int (*config)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat,
> @@ -542,6 +587,7 @@ static int loongson_dwmac_probe(struct pci_dev *pdev,
>  		ld->dwlgmac_dma_ops = dwmac1000_dma_ops;
>  		ld->dwlgmac_dma_ops.init_chan = dwlgmac_dma_init_channel;
>  		ld->dwlgmac_dma_ops.dma_interrupt = dwlgmac_dma_interrupt;
> +		ld->dwlgmac_dma_ops.get_hw_feature = dwlgmac_get_hw_feature;
>  
>  		plat->setup = loongson_setup;
>  		ret = loongson_dwmac_config_multi_msi(pdev, plat, &res, np, 8);
> -- 
> 2.31.4
> 

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 01/11] net: stmmac: Add multi-channel support
  2024-02-04 23:28   ` Serge Semin
@ 2024-02-06  9:02     ` Yanteng Si
  2024-02-06  9:48       ` Serge Semin
  2024-02-19 11:02     ` Yanteng Si
  1 sibling, 1 reply; 97+ messages in thread
From: Yanteng Si @ 2024-02-06  9:02 UTC (permalink / raw)
  To: Serge Semin
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang


在 2024/2/5 07:28, Serge Semin 写道:
> On Tue, Jan 30, 2024 at 04:43:21PM +0800, Yanteng Si wrote:
>> DW GMAC v3.x multi-channels feature is implemented as multiple
>> sets of the same CSRs. Here is only preliminary support, it will
>> be useful for the driver further evolution and for the users
>> having multi-channel DWGMAC v3.x devices.
>>
>> Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
>> Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
>> Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
>> ---
>>   .../net/ethernet/stmicro/stmmac/dwmac-sun8i.c |  2 +-
>>   .../ethernet/stmicro/stmmac/dwmac1000_dma.c   | 36 ++++++++++---------
>>   .../net/ethernet/stmicro/stmmac/dwmac_dma.h   | 19 +++++++++-
>>   .../net/ethernet/stmicro/stmmac/dwmac_lib.c   | 32 ++++++++---------
>>   drivers/net/ethernet/stmicro/stmmac/hwif.h    |  2 +-
>>   .../net/ethernet/stmicro/stmmac/stmmac_main.c |  6 ++--
>>   6 files changed, 58 insertions(+), 39 deletions(-)
>>
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
>> index 137741b94122..7cdfa0bdb93a 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
>> @@ -395,7 +395,7 @@ static void sun8i_dwmac_dma_start_tx(struct stmmac_priv *priv,
>>   	writel(v, ioaddr + EMAC_TX_CTL1);
>>   }
>>   
>> -static void sun8i_dwmac_enable_dma_transmission(void __iomem *ioaddr)
>> +static void sun8i_dwmac_enable_dma_transmission(void __iomem *ioaddr, u32 chan)
>>   {
>>   	u32 v;
>>   
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
>> index daf79cdbd3ec..5f7b82ad3ec2 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
>> @@ -70,15 +70,18 @@ static void dwmac1000_dma_axi(void __iomem *ioaddr, struct stmmac_axi *axi)
>>   	writel(value, ioaddr + DMA_AXI_BUS_MODE);
>>   }
>>   
>> -static void dwmac1000_dma_init(void __iomem *ioaddr,
>> -			       struct stmmac_dma_cfg *dma_cfg, int atds)
>> +static void dwmac1000_dma_init_channel(struct stmmac_priv *priv,
>> +				       void __iomem *ioaddr,
>> +				       struct stmmac_dma_cfg *dma_cfg, u32 chan)
>>   {
>> -	u32 value = readl(ioaddr + DMA_BUS_MODE);
>> +	u32 value;
>>   	int txpbl = dma_cfg->txpbl ?: dma_cfg->pbl;
>>   	int rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl;
> Reverse xmas tree please.
OK!
>
>>   
>> -	/*
>> -	 * Set the DMA PBL (Programmable Burst Length) mode.
>> +	/* common channel control register config */
> Redundant comment. Please drop.
OK!
>
>> +	value = readl(ioaddr + DMA_CHAN_BUS_MODE(chan));
>> +
>> +	/* Set the DMA PBL (Programmable Burst Length) mode.
>>   	 *
>>   	 * Note: before stmmac core 3.50 this mode bit was 4xPBL, and
>>   	 * post 3.5 mode bit acts as 8*PBL.
>> @@ -98,16 +101,15 @@ static void dwmac1000_dma_init(void __iomem *ioaddr,
>>   	if (dma_cfg->mixed_burst)
>>   		value |= DMA_BUS_MODE_MB;
>>   
>> -	if (atds)
>> -		value |= DMA_BUS_MODE_ATDS;
>> +	value |= DMA_BUS_MODE_ATDS;
> No, just convert the stmmac_dma_ops.dma_init_channel() to accepting
> the atds flag as I suggested in v7:
> https://lore.kernel.org/netdev/vxcfrxtbfu4pya56m22icnizsyjzqqha5blzb7zpexqcur56uh@uv6vsjf77npa/
>
> In order to simplify this patch you can provide the
> stmmac_dma_ops.dma_init_channel() and
> stmmac_dma_ops.enable_dma_transmission() prototype updates in a
> pre-requisite/preparation patch.
OK.
>
>>   
>>   	if (dma_cfg->aal)
>>   		value |= DMA_BUS_MODE_AAL;
>>   
>> -	writel(value, ioaddr + DMA_BUS_MODE);
>> +	writel(value, ioaddr + DMA_CHAN_BUS_MODE(chan));
>>   
>>   	/* Mask interrupts by writing to CSR7 */
>> -	writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_INTR_ENA);
>> +	writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_CHAN_INTR_ENA(chan));
>>   }
>>   
>>   static void dwmac1000_dma_init_rx(struct stmmac_priv *priv,
>> @@ -116,7 +118,7 @@ static void dwmac1000_dma_init_rx(struct stmmac_priv *priv,
>>   				  dma_addr_t dma_rx_phy, u32 chan)
>>   {
>>   	/* RX descriptor base address list must be written into DMA CSR3 */
>> -	writel(lower_32_bits(dma_rx_phy), ioaddr + DMA_RCV_BASE_ADDR);
>> +	writel(lower_32_bits(dma_rx_phy), ioaddr + DMA_CHAN_RCV_BASE_ADDR(chan));
>>   }
>>   
>>   static void dwmac1000_dma_init_tx(struct stmmac_priv *priv,
>> @@ -125,7 +127,7 @@ static void dwmac1000_dma_init_tx(struct stmmac_priv *priv,
>>   				  dma_addr_t dma_tx_phy, u32 chan)
>>   {
>>   	/* TX descriptor base address list must be written into DMA CSR4 */
>> -	writel(lower_32_bits(dma_tx_phy), ioaddr + DMA_TX_BASE_ADDR);
>> +	writel(lower_32_bits(dma_tx_phy), ioaddr + DMA_CHAN_TX_BASE_ADDR(chan));
>>   }
>>   
>>   static u32 dwmac1000_configure_fc(u32 csr6, int rxfifosz)
>> @@ -153,7 +155,7 @@ static void dwmac1000_dma_operation_mode_rx(struct stmmac_priv *priv,
>>   					    void __iomem *ioaddr, int mode,
>>   					    u32 channel, int fifosz, u8 qmode)
>>   {
>> -	u32 csr6 = readl(ioaddr + DMA_CONTROL);
>> +	u32 csr6 = readl(ioaddr + DMA_CHAN_CONTROL(channel));
>>   
>>   	if (mode == SF_DMA_MODE) {
>>   		pr_debug("GMAC: enable RX store and forward mode\n");
>> @@ -175,14 +177,14 @@ static void dwmac1000_dma_operation_mode_rx(struct stmmac_priv *priv,
>>   	/* Configure flow control based on rx fifo size */
>>   	csr6 = dwmac1000_configure_fc(csr6, fifosz);
>>   
>> -	writel(csr6, ioaddr + DMA_CONTROL);
>> +	writel(csr6, ioaddr + DMA_CHAN_CONTROL(channel));
>>   }
>>   
>>   static void dwmac1000_dma_operation_mode_tx(struct stmmac_priv *priv,
>>   					    void __iomem *ioaddr, int mode,
>>   					    u32 channel, int fifosz, u8 qmode)
>>   {
>> -	u32 csr6 = readl(ioaddr + DMA_CONTROL);
>> +	u32 csr6 = readl(ioaddr + DMA_CHAN_CONTROL(channel));
>>   
>>   	if (mode == SF_DMA_MODE) {
>>   		pr_debug("GMAC: enable TX store and forward mode\n");
>> @@ -209,7 +211,7 @@ static void dwmac1000_dma_operation_mode_tx(struct stmmac_priv *priv,
>>   			csr6 |= DMA_CONTROL_TTC_256;
>>   	}
>>   
>> -	writel(csr6, ioaddr + DMA_CONTROL);
>> +	writel(csr6, ioaddr + DMA_CHAN_CONTROL(channel));
>>   }
>>   
>>   static void dwmac1000_dump_dma_regs(struct stmmac_priv *priv,
>> @@ -271,12 +273,12 @@ static int dwmac1000_get_hw_feature(void __iomem *ioaddr,
>>   static void dwmac1000_rx_watchdog(struct stmmac_priv *priv,
>>   				  void __iomem *ioaddr, u32 riwt, u32 queue)
>>   {
>> -	writel(riwt, ioaddr + DMA_RX_WATCHDOG);
>> +	writel(riwt, ioaddr + DMA_CHAN_RX_WATCHDOG(queue));
>>   }
>>   
>>   const struct stmmac_dma_ops dwmac1000_dma_ops = {
>>   	.reset = dwmac_dma_reset,
>> -	.init = dwmac1000_dma_init,
>> +	.init_chan = dwmac1000_dma_init_channel,
>>   	.init_rx_chan = dwmac1000_dma_init_rx,
>>   	.init_tx_chan = dwmac1000_dma_init_tx,
>>   	.axi = dwmac1000_dma_axi,
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
>> index 72672391675f..593be79c46e1 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
>> @@ -148,11 +148,14 @@
>>   					 DMA_STATUS_TI | \
>>   					 DMA_STATUS_MSK_COMMON)
>>   
>> +/* Following DMA defines are chanels oriented */    \
>> +#define DMA_CHAN_OFFSET			0x100   |-------------+
>> +                                                    /              |
>                                                                        |
> Please move all of these ---------------------------------------------+-------------------------+
> to being defined just below the DMA_MISSED_FRAME_CTR macros definition.                         |
> The point is to keep a coherency between dwmac_dma.h and dwmac4_dma.h.                          |
> The later header file has first generic DMA-related macros defined                              |
> (CSR addresses and flags) and then the channel-specific ones (CSR                               |
> addresses and flags). Since in case of the DW GMAC v3.x the                                     |
> multi-channels are implemented as a copy of all the DMA CSRs let's                              |
> preserve the logic of having all CSR address defined first, then the                            |
> CSR flags.                                                                                      |
>                                                                                                  |
>>   #define NUM_DWMAC100_DMA_REGS	9                                                       |
>>   #define NUM_DWMAC1000_DMA_REGS	23                                                      |
>>   #define NUM_DWMAC4_DMA_REGS	27                                                              |
>>                                                                                                |
>> -void dwmac_enable_dma_transmission(void __iomem *ioaddr);                                    |
>> +void dwmac_enable_dma_transmission(void __iomem *ioaddr, u32 chan);                          |
>>   void dwmac_enable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr,                    |
>>   			  u32 chan, bool rx, bool tx);                                          |
>>   void dwmac_disable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr,                   |
>> @@ -169,4 +172,18 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,  |
>>   			struct stmmac_extra_stats *x, u32 chan, u32 dir);                       |
>>   int dwmac_dma_reset(void __iomem *ioaddr);                                                   |
>>                                                                                                |
>                                                                                                  |
>> +static inline u32 dma_chan_base_addr(u32 base, u32 chan)                                  \  |
>> +{                                                                                          | |
>> +	return base + chan * DMA_CHAN_OFFSET;                                                 | |
>> +}                                                                                          | |
>> +                                                                                           | |
>> +#define DMA_CHAN_XMT_POLL_DEMAND(chan)	dma_chan_base_addr(DMA_XMT_POLL_DEMAND, chan) | |
>> +#define DMA_CHAN_INTR_ENA(chan)		dma_chan_base_addr(DMA_INTR_ENA, chan)        | |
>> +#define DMA_CHAN_CONTROL(chan)		dma_chan_base_addr(DMA_CONTROL, chan)         | |
>> +#define DMA_CHAN_STATUS(chan)		dma_chan_base_addr(DMA_STATUS, chan)          |-+
>> +#define DMA_CHAN_BUS_MODE(chan)		dma_chan_base_addr(DMA_BUS_MODE, chan)        |
>> +#define DMA_CHAN_RCV_BASE_ADDR(chan)	dma_chan_base_addr(DMA_RCV_BASE_ADDR, chan)           |
>> +#define DMA_CHAN_TX_BASE_ADDR(chan)	dma_chan_base_addr(DMA_TX_BASE_ADDR, chan)            |
>> +#define DMA_CHAN_RX_WATCHDOG(chan)	dma_chan_base_addr(DMA_RX_WATCHDOG, chan)             |
>> +                                                                                           /
OK.
>>   #endif /* __DWMAC_DMA_H__ */
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
>> index 7907d62d3437..b37368137810 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
>> @@ -28,65 +28,65 @@ int dwmac_dma_reset(void __iomem *ioaddr)
>>   }
>>   
>>   /* CSR1 enables the transmit DMA to check for new descriptor */
>> -void dwmac_enable_dma_transmission(void __iomem *ioaddr)
>> +void dwmac_enable_dma_transmission(void __iomem *ioaddr, u32 chan)
>>   {
>> -	writel(1, ioaddr + DMA_XMT_POLL_DEMAND);
>> +	writel(1, ioaddr + DMA_CHAN_XMT_POLL_DEMAND(chan));
>>   }
>>   
>>   void dwmac_enable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr,
>>   			  u32 chan, bool rx, bool tx)
>>   {
>> -	u32 value = readl(ioaddr + DMA_INTR_ENA);
>> +	u32 value = readl(ioaddr + DMA_CHAN_INTR_ENA(chan));
>>   
>>   	if (rx)
>>   		value |= DMA_INTR_DEFAULT_RX;
>>   	if (tx)
>>   		value |= DMA_INTR_DEFAULT_TX;
>>   
>> -	writel(value, ioaddr + DMA_INTR_ENA);
>> +	writel(value, ioaddr + DMA_CHAN_INTR_ENA(chan));
>>   }
>>   
>>   void dwmac_disable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr,
>>   			   u32 chan, bool rx, bool tx)
>>   {
>> -	u32 value = readl(ioaddr + DMA_INTR_ENA);
>> +	u32 value = readl(ioaddr + DMA_CHAN_INTR_ENA(chan));
>>   
>>   	if (rx)
>>   		value &= ~DMA_INTR_DEFAULT_RX;
>>   	if (tx)
>>   		value &= ~DMA_INTR_DEFAULT_TX;
>>   
>> -	writel(value, ioaddr + DMA_INTR_ENA);
>> +	writel(value, ioaddr + DMA_CHAN_INTR_ENA(chan));
>>   }
>>   
>>   void dwmac_dma_start_tx(struct stmmac_priv *priv, void __iomem *ioaddr,
>>   			u32 chan)
>>   {
>> -	u32 value = readl(ioaddr + DMA_CONTROL);
>> +	u32 value = readl(ioaddr + DMA_CHAN_CONTROL(chan));
>>   	value |= DMA_CONTROL_ST;
>> -	writel(value, ioaddr + DMA_CONTROL);
>> +	writel(value, ioaddr + DMA_CHAN_CONTROL(chan));
>>   }
>>   
>>   void dwmac_dma_stop_tx(struct stmmac_priv *priv, void __iomem *ioaddr, u32 chan)
>>   {
>> -	u32 value = readl(ioaddr + DMA_CONTROL);
>> +	u32 value = readl(ioaddr + DMA_CHAN_CONTROL(chan));
>>   	value &= ~DMA_CONTROL_ST;
>> -	writel(value, ioaddr + DMA_CONTROL);
>> +	writel(value, ioaddr + DMA_CHAN_CONTROL(chan));
>>   }
>>   
>>   void dwmac_dma_start_rx(struct stmmac_priv *priv, void __iomem *ioaddr,
>>   			u32 chan)
>>   {
>> -	u32 value = readl(ioaddr + DMA_CONTROL);
>> +	u32 value = readl(ioaddr + DMA_CHAN_CONTROL(chan));
>>   	value |= DMA_CONTROL_SR;
>> -	writel(value, ioaddr + DMA_CONTROL);
>> +	writel(value, ioaddr + DMA_CHAN_CONTROL(chan));
>>   }
>>   
>>   void dwmac_dma_stop_rx(struct stmmac_priv *priv, void __iomem *ioaddr, u32 chan)
>>   {
>> -	u32 value = readl(ioaddr + DMA_CONTROL);
>> +	u32 value = readl(ioaddr + DMA_CHAN_CONTROL(chan));
>>   	value &= ~DMA_CONTROL_SR;
>> -	writel(value, ioaddr + DMA_CONTROL);
>> +	writel(value, ioaddr + DMA_CHAN_CONTROL(chan));
>>   }
>>   
>>   #ifdef DWMAC_DMA_DEBUG
>> @@ -166,7 +166,7 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
>>   	struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[chan];
>>   	int ret = 0;
>>   	/* read the status register (CSR5) */
>> -	u32 intr_status = readl(ioaddr + DMA_STATUS);
>> +	u32 intr_status = readl(ioaddr + DMA_CHAN_STATUS(chan));
>>   
>>   #ifdef DWMAC_DMA_DEBUG
>>   	/* Enable it to monitor DMA rx/tx status in case of critical problems */
>> @@ -236,7 +236,7 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
>>   		pr_warn("%s: unexpected status %08x\n", __func__, intr_status);
>>   
>>   	/* Clear the interrupt by writing a logic 1 to the CSR5[15-0] */
>> -	writel((intr_status & 0x1ffff), ioaddr + DMA_STATUS);
>> +	writel((intr_status & 0x7ffff), ioaddr + DMA_CHAN_STATUS(chan));
> Isn't the mask change going to be implemented in the framework of the
> Loongson-specific DMA-interrupt handler in some of the further patches?
Yes!
>
> I'll get back to reviewing the series tomorrow (later today)...

OK, Thanks for your review!  I have read all your comments in others patch.


I will modify the code as soon as possible according to your comments,

but in the next two weeks (Spring Festival), I will not be able to test 
on all devices.


Thanks,

Yanteng

>
> -Serge(y)
>
>>   
>>   	return ret;
>>   }
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h
>> index 7be04b54738b..b0db38396171 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/hwif.h
>> +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h
>> @@ -198,7 +198,7 @@ struct stmmac_dma_ops {
>>   	/* To track extra statistic (if supported) */
>>   	void (*dma_diagnostic_fr)(struct stmmac_extra_stats *x,
>>   				  void __iomem *ioaddr);
>> -	void (*enable_dma_transmission) (void __iomem *ioaddr);
>> +	void (*enable_dma_transmission)(void __iomem *ioaddr, u32 chan);
>>   	void (*enable_dma_irq)(struct stmmac_priv *priv, void __iomem *ioaddr,
>>   			       u32 chan, bool rx, bool tx);
>>   	void (*disable_dma_irq)(struct stmmac_priv *priv, void __iomem *ioaddr,
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>> index b334eb16da23..5617b40abbe4 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>> @@ -2558,7 +2558,7 @@ static bool stmmac_xdp_xmit_zc(struct stmmac_priv *priv, u32 queue, u32 budget)
>>   				       true, priv->mode, true, true,
>>   				       xdp_desc.len);
>>   
>> -		stmmac_enable_dma_transmission(priv, priv->ioaddr);
>> +		stmmac_enable_dma_transmission(priv, priv->ioaddr, queue);
>>   
>>   		xsk_tx_metadata_to_compl(meta,
>>   					 &tx_q->tx_skbuff_dma[entry].xsk_meta);
>> @@ -4706,7 +4706,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
>>   
>>   	netdev_tx_sent_queue(netdev_get_tx_queue(dev, queue), skb->len);
>>   
>> -	stmmac_enable_dma_transmission(priv, priv->ioaddr);
>> +	stmmac_enable_dma_transmission(priv, priv->ioaddr, queue);
>>   
>>   	stmmac_flush_tx_descriptors(priv, queue);
>>   	stmmac_tx_timer_arm(priv, queue);
>> @@ -4926,7 +4926,7 @@ static int stmmac_xdp_xmit_xdpf(struct stmmac_priv *priv, int queue,
>>   		u64_stats_update_end_irqrestore(&txq_stats->syncp, flags);
>>   	}
>>   
>> -	stmmac_enable_dma_transmission(priv, priv->ioaddr);
>> +	stmmac_enable_dma_transmission(priv, priv->ioaddr, queue);
>>   
>>   	entry = STMMAC_GET_ENTRY(entry, priv->dma_conf.dma_tx_size);
>>   	tx_q->cur_tx = entry;
>> -- 
>> 2.31.4
>>


^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 01/11] net: stmmac: Add multi-channel support
  2024-02-06  9:02     ` Yanteng Si
@ 2024-02-06  9:48       ` Serge Semin
  0 siblings, 0 replies; 97+ messages in thread
From: Serge Semin @ 2024-02-06  9:48 UTC (permalink / raw)
  To: Yanteng Si
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

On Tue, Feb 06, 2024 at 05:02:29PM +0800, Yanteng Si wrote:
> 
> 在 2024/2/5 07:28, Serge Semin 写道:
> > On Tue, Jan 30, 2024 at 04:43:21PM +0800, Yanteng Si wrote:
> > > DW GMAC v3.x multi-channels feature is implemented as multiple
> > > sets of the same CSRs. Here is only preliminary support, it will
> > > be useful for the driver further evolution and for the users
> > > having multi-channel DWGMAC v3.x devices.
> > > 
> > > Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
> > > Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
> > > Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
> > > ---
> > >   .../net/ethernet/stmicro/stmmac/dwmac-sun8i.c |  2 +-
> > >   .../ethernet/stmicro/stmmac/dwmac1000_dma.c   | 36 ++++++++++---------
> > >   .../net/ethernet/stmicro/stmmac/dwmac_dma.h   | 19 +++++++++-
> > >   .../net/ethernet/stmicro/stmmac/dwmac_lib.c   | 32 ++++++++---------
> > >   drivers/net/ethernet/stmicro/stmmac/hwif.h    |  2 +-
> > >   .../net/ethernet/stmicro/stmmac/stmmac_main.c |  6 ++--
> > >   6 files changed, 58 insertions(+), 39 deletions(-)
> > > 
> > > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
> > > index 137741b94122..7cdfa0bdb93a 100644
> > > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
> > > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
> > > @@ -395,7 +395,7 @@ static void sun8i_dwmac_dma_start_tx(struct stmmac_priv *priv,
> > >   	writel(v, ioaddr + EMAC_TX_CTL1);
> > >   }
> > > -static void sun8i_dwmac_enable_dma_transmission(void __iomem *ioaddr)
> > > +static void sun8i_dwmac_enable_dma_transmission(void __iomem *ioaddr, u32 chan)
> > >   {
> > >   	u32 v;
> > > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> > > index daf79cdbd3ec..5f7b82ad3ec2 100644
> > > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> > > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> > > @@ -70,15 +70,18 @@ static void dwmac1000_dma_axi(void __iomem *ioaddr, struct stmmac_axi *axi)
> > >   	writel(value, ioaddr + DMA_AXI_BUS_MODE);
> > >   }
> > > -static void dwmac1000_dma_init(void __iomem *ioaddr,
> > > -			       struct stmmac_dma_cfg *dma_cfg, int atds)
> > > +static void dwmac1000_dma_init_channel(struct stmmac_priv *priv,
> > > +				       void __iomem *ioaddr,
> > > +				       struct stmmac_dma_cfg *dma_cfg, u32 chan)
> > >   {
> > > -	u32 value = readl(ioaddr + DMA_BUS_MODE);
> > > +	u32 value;
> > >   	int txpbl = dma_cfg->txpbl ?: dma_cfg->pbl;
> > >   	int rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl;
> > Reverse xmas tree please.
> OK!
> > 
> > > -	/*
> > > -	 * Set the DMA PBL (Programmable Burst Length) mode.
> > > +	/* common channel control register config */
> > Redundant comment. Please drop.
> OK!
> > 
> > > +	value = readl(ioaddr + DMA_CHAN_BUS_MODE(chan));
> > > +
> > > +	/* Set the DMA PBL (Programmable Burst Length) mode.
> > >   	 *
> > >   	 * Note: before stmmac core 3.50 this mode bit was 4xPBL, and
> > >   	 * post 3.5 mode bit acts as 8*PBL.
> > > @@ -98,16 +101,15 @@ static void dwmac1000_dma_init(void __iomem *ioaddr,
> > >   	if (dma_cfg->mixed_burst)
> > >   		value |= DMA_BUS_MODE_MB;
> > > -	if (atds)
> > > -		value |= DMA_BUS_MODE_ATDS;
> > > +	value |= DMA_BUS_MODE_ATDS;
> > No, just convert the stmmac_dma_ops.dma_init_channel() to accepting
> > the atds flag as I suggested in v7:
> > https://lore.kernel.org/netdev/vxcfrxtbfu4pya56m22icnizsyjzqqha5blzb7zpexqcur56uh@uv6vsjf77npa/
> > 
> > In order to simplify this patch you can provide the
> > stmmac_dma_ops.dma_init_channel() and
> > stmmac_dma_ops.enable_dma_transmission() prototype updates in a
> > pre-requisite/preparation patch.
> OK.
> > 
> > >   	if (dma_cfg->aal)
> > >   		value |= DMA_BUS_MODE_AAL;
> > > -	writel(value, ioaddr + DMA_BUS_MODE);
> > > +	writel(value, ioaddr + DMA_CHAN_BUS_MODE(chan));
> > >   	/* Mask interrupts by writing to CSR7 */
> > > -	writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_INTR_ENA);
> > > +	writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_CHAN_INTR_ENA(chan));
> > >   }
> > >   static void dwmac1000_dma_init_rx(struct stmmac_priv *priv,
> > > @@ -116,7 +118,7 @@ static void dwmac1000_dma_init_rx(struct stmmac_priv *priv,
> > >   				  dma_addr_t dma_rx_phy, u32 chan)
> > >   {
> > >   	/* RX descriptor base address list must be written into DMA CSR3 */
> > > -	writel(lower_32_bits(dma_rx_phy), ioaddr + DMA_RCV_BASE_ADDR);
> > > +	writel(lower_32_bits(dma_rx_phy), ioaddr + DMA_CHAN_RCV_BASE_ADDR(chan));
> > >   }
> > >   static void dwmac1000_dma_init_tx(struct stmmac_priv *priv,
> > > @@ -125,7 +127,7 @@ static void dwmac1000_dma_init_tx(struct stmmac_priv *priv,
> > >   				  dma_addr_t dma_tx_phy, u32 chan)
> > >   {
> > >   	/* TX descriptor base address list must be written into DMA CSR4 */
> > > -	writel(lower_32_bits(dma_tx_phy), ioaddr + DMA_TX_BASE_ADDR);
> > > +	writel(lower_32_bits(dma_tx_phy), ioaddr + DMA_CHAN_TX_BASE_ADDR(chan));
> > >   }
> > >   static u32 dwmac1000_configure_fc(u32 csr6, int rxfifosz)
> > > @@ -153,7 +155,7 @@ static void dwmac1000_dma_operation_mode_rx(struct stmmac_priv *priv,
> > >   					    void __iomem *ioaddr, int mode,
> > >   					    u32 channel, int fifosz, u8 qmode)
> > >   {
> > > -	u32 csr6 = readl(ioaddr + DMA_CONTROL);
> > > +	u32 csr6 = readl(ioaddr + DMA_CHAN_CONTROL(channel));
> > >   	if (mode == SF_DMA_MODE) {
> > >   		pr_debug("GMAC: enable RX store and forward mode\n");
> > > @@ -175,14 +177,14 @@ static void dwmac1000_dma_operation_mode_rx(struct stmmac_priv *priv,
> > >   	/* Configure flow control based on rx fifo size */
> > >   	csr6 = dwmac1000_configure_fc(csr6, fifosz);
> > > -	writel(csr6, ioaddr + DMA_CONTROL);
> > > +	writel(csr6, ioaddr + DMA_CHAN_CONTROL(channel));
> > >   }
> > >   static void dwmac1000_dma_operation_mode_tx(struct stmmac_priv *priv,
> > >   					    void __iomem *ioaddr, int mode,
> > >   					    u32 channel, int fifosz, u8 qmode)
> > >   {
> > > -	u32 csr6 = readl(ioaddr + DMA_CONTROL);
> > > +	u32 csr6 = readl(ioaddr + DMA_CHAN_CONTROL(channel));
> > >   	if (mode == SF_DMA_MODE) {
> > >   		pr_debug("GMAC: enable TX store and forward mode\n");
> > > @@ -209,7 +211,7 @@ static void dwmac1000_dma_operation_mode_tx(struct stmmac_priv *priv,
> > >   			csr6 |= DMA_CONTROL_TTC_256;
> > >   	}
> > > -	writel(csr6, ioaddr + DMA_CONTROL);
> > > +	writel(csr6, ioaddr + DMA_CHAN_CONTROL(channel));
> > >   }
> > >   static void dwmac1000_dump_dma_regs(struct stmmac_priv *priv,
> > > @@ -271,12 +273,12 @@ static int dwmac1000_get_hw_feature(void __iomem *ioaddr,
> > >   static void dwmac1000_rx_watchdog(struct stmmac_priv *priv,
> > >   				  void __iomem *ioaddr, u32 riwt, u32 queue)
> > >   {
> > > -	writel(riwt, ioaddr + DMA_RX_WATCHDOG);
> > > +	writel(riwt, ioaddr + DMA_CHAN_RX_WATCHDOG(queue));
> > >   }
> > >   const struct stmmac_dma_ops dwmac1000_dma_ops = {
> > >   	.reset = dwmac_dma_reset,
> > > -	.init = dwmac1000_dma_init,
> > > +	.init_chan = dwmac1000_dma_init_channel,
> > >   	.init_rx_chan = dwmac1000_dma_init_rx,
> > >   	.init_tx_chan = dwmac1000_dma_init_tx,
> > >   	.axi = dwmac1000_dma_axi,
> > > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
> > > index 72672391675f..593be79c46e1 100644
> > > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
> > > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
> > > @@ -148,11 +148,14 @@
> > >   					 DMA_STATUS_TI | \
> > >   					 DMA_STATUS_MSK_COMMON)
> > > +/* Following DMA defines are chanels oriented */    \
> > > +#define DMA_CHAN_OFFSET			0x100   |-------------+
> > > +                                                    /              |
> >                                                                        |
> > Please move all of these ---------------------------------------------+-------------------------+
> > to being defined just below the DMA_MISSED_FRAME_CTR macros definition.                         |
> > The point is to keep a coherency between dwmac_dma.h and dwmac4_dma.h.                          |
> > The later header file has first generic DMA-related macros defined                              |
> > (CSR addresses and flags) and then the channel-specific ones (CSR                               |
> > addresses and flags). Since in case of the DW GMAC v3.x the                                     |
> > multi-channels are implemented as a copy of all the DMA CSRs let's                              |
> > preserve the logic of having all CSR address defined first, then the                            |
> > CSR flags.                                                                                      |
> >                                                                                                  |
> > >   #define NUM_DWMAC100_DMA_REGS	9                                                       |
> > >   #define NUM_DWMAC1000_DMA_REGS	23                                                      |
> > >   #define NUM_DWMAC4_DMA_REGS	27                                                              |
> > >                                                                                                |
> > > -void dwmac_enable_dma_transmission(void __iomem *ioaddr);                                    |
> > > +void dwmac_enable_dma_transmission(void __iomem *ioaddr, u32 chan);                          |
> > >   void dwmac_enable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr,                    |
> > >   			  u32 chan, bool rx, bool tx);                                          |
> > >   void dwmac_disable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr,                   |
> > > @@ -169,4 +172,18 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,  |
> > >   			struct stmmac_extra_stats *x, u32 chan, u32 dir);                       |
> > >   int dwmac_dma_reset(void __iomem *ioaddr);                                                   |
> > >                                                                                                |
> >                                                                                                  |
> > > +static inline u32 dma_chan_base_addr(u32 base, u32 chan)                                  \  |
> > > +{                                                                                          | |
> > > +	return base + chan * DMA_CHAN_OFFSET;                                                 | |
> > > +}                                                                                          | |
> > > +                                                                                           | |
> > > +#define DMA_CHAN_XMT_POLL_DEMAND(chan)	dma_chan_base_addr(DMA_XMT_POLL_DEMAND, chan) | |
> > > +#define DMA_CHAN_INTR_ENA(chan)		dma_chan_base_addr(DMA_INTR_ENA, chan)        | |
> > > +#define DMA_CHAN_CONTROL(chan)		dma_chan_base_addr(DMA_CONTROL, chan)         | |
> > > +#define DMA_CHAN_STATUS(chan)		dma_chan_base_addr(DMA_STATUS, chan)          |-+
> > > +#define DMA_CHAN_BUS_MODE(chan)		dma_chan_base_addr(DMA_BUS_MODE, chan)        |
> > > +#define DMA_CHAN_RCV_BASE_ADDR(chan)	dma_chan_base_addr(DMA_RCV_BASE_ADDR, chan)           |
> > > +#define DMA_CHAN_TX_BASE_ADDR(chan)	dma_chan_base_addr(DMA_TX_BASE_ADDR, chan)            |
> > > +#define DMA_CHAN_RX_WATCHDOG(chan)	dma_chan_base_addr(DMA_RX_WATCHDOG, chan)             |
> > > +                                                                                           /
> OK.
> > >   #endif /* __DWMAC_DMA_H__ */
> > > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
> > > index 7907d62d3437..b37368137810 100644
> > > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
> > > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
> > > @@ -28,65 +28,65 @@ int dwmac_dma_reset(void __iomem *ioaddr)
> > >   }
> > >   /* CSR1 enables the transmit DMA to check for new descriptor */
> > > -void dwmac_enable_dma_transmission(void __iomem *ioaddr)
> > > +void dwmac_enable_dma_transmission(void __iomem *ioaddr, u32 chan)
> > >   {
> > > -	writel(1, ioaddr + DMA_XMT_POLL_DEMAND);
> > > +	writel(1, ioaddr + DMA_CHAN_XMT_POLL_DEMAND(chan));
> > >   }
> > >   void dwmac_enable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr,
> > >   			  u32 chan, bool rx, bool tx)
> > >   {
> > > -	u32 value = readl(ioaddr + DMA_INTR_ENA);
> > > +	u32 value = readl(ioaddr + DMA_CHAN_INTR_ENA(chan));
> > >   	if (rx)
> > >   		value |= DMA_INTR_DEFAULT_RX;
> > >   	if (tx)
> > >   		value |= DMA_INTR_DEFAULT_TX;
> > > -	writel(value, ioaddr + DMA_INTR_ENA);
> > > +	writel(value, ioaddr + DMA_CHAN_INTR_ENA(chan));
> > >   }
> > >   void dwmac_disable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr,
> > >   			   u32 chan, bool rx, bool tx)
> > >   {
> > > -	u32 value = readl(ioaddr + DMA_INTR_ENA);
> > > +	u32 value = readl(ioaddr + DMA_CHAN_INTR_ENA(chan));
> > >   	if (rx)
> > >   		value &= ~DMA_INTR_DEFAULT_RX;
> > >   	if (tx)
> > >   		value &= ~DMA_INTR_DEFAULT_TX;
> > > -	writel(value, ioaddr + DMA_INTR_ENA);
> > > +	writel(value, ioaddr + DMA_CHAN_INTR_ENA(chan));
> > >   }
> > >   void dwmac_dma_start_tx(struct stmmac_priv *priv, void __iomem *ioaddr,
> > >   			u32 chan)
> > >   {
> > > -	u32 value = readl(ioaddr + DMA_CONTROL);
> > > +	u32 value = readl(ioaddr + DMA_CHAN_CONTROL(chan));
> > >   	value |= DMA_CONTROL_ST;
> > > -	writel(value, ioaddr + DMA_CONTROL);
> > > +	writel(value, ioaddr + DMA_CHAN_CONTROL(chan));
> > >   }
> > >   void dwmac_dma_stop_tx(struct stmmac_priv *priv, void __iomem *ioaddr, u32 chan)
> > >   {
> > > -	u32 value = readl(ioaddr + DMA_CONTROL);
> > > +	u32 value = readl(ioaddr + DMA_CHAN_CONTROL(chan));
> > >   	value &= ~DMA_CONTROL_ST;
> > > -	writel(value, ioaddr + DMA_CONTROL);
> > > +	writel(value, ioaddr + DMA_CHAN_CONTROL(chan));
> > >   }
> > >   void dwmac_dma_start_rx(struct stmmac_priv *priv, void __iomem *ioaddr,
> > >   			u32 chan)
> > >   {
> > > -	u32 value = readl(ioaddr + DMA_CONTROL);
> > > +	u32 value = readl(ioaddr + DMA_CHAN_CONTROL(chan));
> > >   	value |= DMA_CONTROL_SR;
> > > -	writel(value, ioaddr + DMA_CONTROL);
> > > +	writel(value, ioaddr + DMA_CHAN_CONTROL(chan));
> > >   }
> > >   void dwmac_dma_stop_rx(struct stmmac_priv *priv, void __iomem *ioaddr, u32 chan)
> > >   {
> > > -	u32 value = readl(ioaddr + DMA_CONTROL);
> > > +	u32 value = readl(ioaddr + DMA_CHAN_CONTROL(chan));
> > >   	value &= ~DMA_CONTROL_SR;
> > > -	writel(value, ioaddr + DMA_CONTROL);
> > > +	writel(value, ioaddr + DMA_CHAN_CONTROL(chan));
> > >   }
> > >   #ifdef DWMAC_DMA_DEBUG
> > > @@ -166,7 +166,7 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
> > >   	struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[chan];
> > >   	int ret = 0;
> > >   	/* read the status register (CSR5) */
> > > -	u32 intr_status = readl(ioaddr + DMA_STATUS);
> > > +	u32 intr_status = readl(ioaddr + DMA_CHAN_STATUS(chan));
> > >   #ifdef DWMAC_DMA_DEBUG
> > >   	/* Enable it to monitor DMA rx/tx status in case of critical problems */
> > > @@ -236,7 +236,7 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
> > >   		pr_warn("%s: unexpected status %08x\n", __func__, intr_status);
> > >   	/* Clear the interrupt by writing a logic 1 to the CSR5[15-0] */
> > > -	writel((intr_status & 0x1ffff), ioaddr + DMA_STATUS);
> > > +	writel((intr_status & 0x7ffff), ioaddr + DMA_CHAN_STATUS(chan));
> > Isn't the mask change going to be implemented in the framework of the
> > Loongson-specific DMA-interrupt handler in some of the further patches?
> Yes!
> > 
> > I'll get back to reviewing the series tomorrow (later today)...
> 
> OK, Thanks for your review!  I have read all your comments in others patch.
> 
> 
> I will modify the code as soon as possible according to your comments,
> 

> but in the next two weeks (Spring Festival), I will not be able to test on
> all devices.

Ok. Whenever you are ready I'll keep reviewing your series. Even at
the current state the patchset looks much much better than it was
initially. Some reordering, commit logs elaboration, a few more cycle
to polish out some details and I guess it will be ready for merging at
least from my point of view.

-Serge(y)

> 
> 
> Thanks,
> 
> Yanteng
> 
> > 
> > -Serge(y)
> > 
> > >   	return ret;
> > >   }
> > > diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h
> > > index 7be04b54738b..b0db38396171 100644
> > > --- a/drivers/net/ethernet/stmicro/stmmac/hwif.h
> > > +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h
> > > @@ -198,7 +198,7 @@ struct stmmac_dma_ops {
> > >   	/* To track extra statistic (if supported) */
> > >   	void (*dma_diagnostic_fr)(struct stmmac_extra_stats *x,
> > >   				  void __iomem *ioaddr);
> > > -	void (*enable_dma_transmission) (void __iomem *ioaddr);
> > > +	void (*enable_dma_transmission)(void __iomem *ioaddr, u32 chan);
> > >   	void (*enable_dma_irq)(struct stmmac_priv *priv, void __iomem *ioaddr,
> > >   			       u32 chan, bool rx, bool tx);
> > >   	void (*disable_dma_irq)(struct stmmac_priv *priv, void __iomem *ioaddr,
> > > diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> > > index b334eb16da23..5617b40abbe4 100644
> > > --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> > > +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> > > @@ -2558,7 +2558,7 @@ static bool stmmac_xdp_xmit_zc(struct stmmac_priv *priv, u32 queue, u32 budget)
> > >   				       true, priv->mode, true, true,
> > >   				       xdp_desc.len);
> > > -		stmmac_enable_dma_transmission(priv, priv->ioaddr);
> > > +		stmmac_enable_dma_transmission(priv, priv->ioaddr, queue);
> > >   		xsk_tx_metadata_to_compl(meta,
> > >   					 &tx_q->tx_skbuff_dma[entry].xsk_meta);
> > > @@ -4706,7 +4706,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
> > >   	netdev_tx_sent_queue(netdev_get_tx_queue(dev, queue), skb->len);
> > > -	stmmac_enable_dma_transmission(priv, priv->ioaddr);
> > > +	stmmac_enable_dma_transmission(priv, priv->ioaddr, queue);
> > >   	stmmac_flush_tx_descriptors(priv, queue);
> > >   	stmmac_tx_timer_arm(priv, queue);
> > > @@ -4926,7 +4926,7 @@ static int stmmac_xdp_xmit_xdpf(struct stmmac_priv *priv, int queue,
> > >   		u64_stats_update_end_irqrestore(&txq_stats->syncp, flags);
> > >   	}
> > > -	stmmac_enable_dma_transmission(priv, priv->ioaddr);
> > > +	stmmac_enable_dma_transmission(priv, priv->ioaddr, queue);
> > >   	entry = STMMAC_GET_ENTRY(entry, priv->dma_conf.dma_tx_size);
> > >   	tx_q->cur_tx = entry;
> > > -- 
> > > 2.31.4
> > > 
> 

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 01/11] net: stmmac: Add multi-channel support
  2024-02-04 23:28   ` Serge Semin
  2024-02-06  9:02     ` Yanteng Si
@ 2024-02-19 11:02     ` Yanteng Si
  2024-02-21 13:48       ` Serge Semin
  1 sibling, 1 reply; 97+ messages in thread
From: Yanteng Si @ 2024-02-19 11:02 UTC (permalink / raw)
  To: Serge Semin
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

Hi Serge

在 2024/2/5 07:28, Serge Semin 写道:
> On Tue, Jan 30, 2024 at 04:43:21PM +0800, Yanteng Si wrote:
>> DW GMAC v3.x multi-channels feature is implemented as multiple
>> sets of the same CSRs. Here is only preliminary support, it will
>> be useful for the driver further evolution and for the users
>> having multi-channel DWGMAC v3.x devices.
>>
>> Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
>> Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
>> Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
>> ---
>>   .../net/ethernet/stmicro/stmmac/dwmac-sun8i.c |  2 +-
>>   .../ethernet/stmicro/stmmac/dwmac1000_dma.c   | 36 ++++++++++---------
>>   .../net/ethernet/stmicro/stmmac/dwmac_dma.h   | 19 +++++++++-
>>   .../net/ethernet/stmicro/stmmac/dwmac_lib.c   | 32 ++++++++---------
>>   drivers/net/ethernet/stmicro/stmmac/hwif.h    |  2 +-
>>   .../net/ethernet/stmicro/stmmac/stmmac_main.c |  6 ++--
>>   6 files changed, 58 insertions(+), 39 deletions(-)
>>
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
>> index 137741b94122..7cdfa0bdb93a 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
>> @@ -395,7 +395,7 @@ static void sun8i_dwmac_dma_start_tx(struct stmmac_priv *priv,
>>   	writel(v, ioaddr + EMAC_TX_CTL1);
>>   }
>>   
>> -static void sun8i_dwmac_enable_dma_transmission(void __iomem *ioaddr)
>> +static void sun8i_dwmac_enable_dma_transmission(void __iomem *ioaddr, u32 chan)
>>   {
>>   	u32 v;
>>   
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
>> index daf79cdbd3ec..5f7b82ad3ec2 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
>> @@ -70,15 +70,18 @@ static void dwmac1000_dma_axi(void __iomem *ioaddr, struct stmmac_axi *axi)
>>   	writel(value, ioaddr + DMA_AXI_BUS_MODE);
>>   }
>>   
>> -static void dwmac1000_dma_init(void __iomem *ioaddr,
>> -			       struct stmmac_dma_cfg *dma_cfg, int atds)
>> +static void dwmac1000_dma_init_channel(struct stmmac_priv *priv,
>> +				       void __iomem *ioaddr,
>> +				       struct stmmac_dma_cfg *dma_cfg, u32 chan)
>>   {
>> -	u32 value = readl(ioaddr + DMA_BUS_MODE);
>> +	u32 value;
>>   	int txpbl = dma_cfg->txpbl ?: dma_cfg->pbl;
>>   	int rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl;
> Reverse xmas tree please.
>
>>   
>> -	/*
>> -	 * Set the DMA PBL (Programmable Burst Length) mode.
>> +	/* common channel control register config */
> Redundant comment. Please drop.
>
>> +	value = readl(ioaddr + DMA_CHAN_BUS_MODE(chan));
>> +
>> +	/* Set the DMA PBL (Programmable Burst Length) mode.
>>   	 *
>>   	 * Note: before stmmac core 3.50 this mode bit was 4xPBL, and
>>   	 * post 3.5 mode bit acts as 8*PBL.
>> @@ -98,16 +101,15 @@ static void dwmac1000_dma_init(void __iomem *ioaddr,
>>   	if (dma_cfg->mixed_burst)
>>   		value |= DMA_BUS_MODE_MB;
>>   
>> -	if (atds)
>> -		value |= DMA_BUS_MODE_ATDS;
>> +	value |= DMA_BUS_MODE_ATDS;
> No, just convert the stmmac_dma_ops.dma_init_channel() to accepting
> the atds flag as I suggested in v7:
> https://lore.kernel.org/netdev/vxcfrxtbfu4pya56m22icnizsyjzqqha5blzb7zpexqcur56uh@uv6vsjf77npa/
>
> In order to simplify this patch you can provide the
> stmmac_dma_ops.dma_init_channel() and
> stmmac_dma_ops.enable_dma_transmission() prototype updates in a
> pre-requisite/preparation patch.

Sorry to keep you waiting for so long, I finally got the machine again. 
Regarding atds, is this how it is implemented?

On the basis of applying PATCH v8:

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c 
b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
index 0323f0a5049c..ce99f4a1b320 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
@@ -72,7 +72,8 @@ static void dwmac1000_dma_axi(void __iomem *ioaddr, 
struct stmmac_axi *axi)

  static void dwmac1000_dma_init_channel(struct stmmac_priv *priv,
                         void __iomem *ioaddr,
-                       struct stmmac_dma_cfg *dma_cfg, u32 chan)
+                       struct stmmac_dma_cfg *dma_cfg,
+                       int atds, u32 chan)
  {
      u32 value;
      int txpbl = dma_cfg->txpbl ?: dma_cfg->pbl;
@@ -101,7 +102,8 @@ static void dwmac1000_dma_init_channel(struct 
stmmac_priv *priv,
      if (dma_cfg->mixed_burst)
          value |= DMA_BUS_MODE_MB;

-    value |= DMA_BUS_MODE_ATDS;
+    if (atds)
+        value |= DMA_BUS_MODE_ATDS;

      if (dma_cfg->aal)
          value |= DMA_BUS_MODE_AAL;
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c 
b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
index 84d3a8551b03..8a79c154b553 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
@@ -117,7 +117,8 @@ static void dwmac4_dma_init_tx_chan(struct 
stmmac_priv *priv,

  static void dwmac4_dma_init_channel(struct stmmac_priv *priv,
                      void __iomem *ioaddr,
-                    struct stmmac_dma_cfg *dma_cfg, u32 chan)
+                    struct stmmac_dma_cfg *dma_cfg,
+                                    int atds, u32 chan)
  {
      const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;
      u32 value;
@@ -135,7 +136,8 @@ static void dwmac4_dma_init_channel(struct 
stmmac_priv *priv,

  static void dwmac410_dma_init_channel(struct stmmac_priv *priv,
                        void __iomem *ioaddr,
-                      struct stmmac_dma_cfg *dma_cfg, u32 chan)
+                      struct stmmac_dma_cfg *dma_cfg,
+                                      int atds, u32 chan)
  {
      const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;
      u32 value;
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c 
b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
index dd2ab6185c40..d1627b2e50c8 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
@@ -35,7 +35,8 @@ static void dwxgmac2_dma_init(void __iomem *ioaddr,

  static void dwxgmac2_dma_init_chan(struct stmmac_priv *priv,
                     void __iomem *ioaddr,
-                   struct stmmac_dma_cfg *dma_cfg, u32 chan)
+                   struct stmmac_dma_cfg *dma_cfg,
+                                   int atds, u32 chan)
  {
      u32 value = readl(ioaddr + XGMAC_DMA_CH_CONTROL(chan));

diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h 
b/drivers/net/ethernet/stmicro/stmmac/hwif.h
index b0db38396171..fb27ad0e97e8 100644
--- a/drivers/net/ethernet/stmicro/stmmac/hwif.h
+++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h
@@ -178,7 +178,7 @@ struct stmmac_dma_ops {
      void (*init)(void __iomem *ioaddr, struct stmmac_dma_cfg *dma_cfg,
               int atds);
      void (*init_chan)(struct stmmac_priv *priv, void __iomem *ioaddr,
-              struct stmmac_dma_cfg *dma_cfg, u32 chan);
+              struct stmmac_dma_cfg *dma_cfg, int atds, u32 chan);
      void (*init_rx_chan)(struct stmmac_priv *priv, void __iomem *ioaddr,
                   struct stmmac_dma_cfg *dma_cfg,
                   dma_addr_t phy, u32 chan);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c 
b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 3eed202d1f1c..8705e04913d1 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -3039,7 +3039,7 @@ static int stmmac_init_dma_engine(struct 
stmmac_priv *priv)

      /* DMA CSR Channel configuration */
      for (chan = 0; chan < dma_csr_ch; chan++) {
-        stmmac_init_chan(priv, priv->ioaddr, priv->plat->dma_cfg, chan);
+        stmmac_init_chan(priv, priv->ioaddr, priv->plat->dma_cfg, atds, 
chan);
          stmmac_disable_dma_irq(priv, priv->ioaddr, chan, 1, 1);
      }

@@ -6963,6 +6963,7 @@ int stmmac_xdp_open(struct net_device *dev)
      u32 buf_size;
      bool sph_en;
      u32 chan;
+     int atds;
      int ret;

      ret = alloc_dma_desc_resources(priv, &priv->dma_conf);
@@ -6981,9 +6982,12 @@ int stmmac_xdp_open(struct net_device *dev)

      stmmac_reset_queues_param(priv);

+    if (priv->extend_desc && (priv->mode == STMMAC_RING_MODE))
+        atds = 1;
+
      /* DMA CSR Channel configuration */
      for (chan = 0; chan < dma_csr_ch; chan++) {
-        stmmac_init_chan(priv, priv->ioaddr, priv->plat->dma_cfg, chan);
+        stmmac_init_chan(priv, priv->ioaddr, priv->plat->dma_cfg, atds, 
chan);
          stmmac_disable_dma_irq(priv, priv->ioaddr, chan, 1, 1);
      }


Thanks,

Yanteng

>
>>   
>>   	if (dma_cfg->aal)
>>   		value |= DMA_BUS_MODE_AAL;
>>   
>> -	writel(value, ioaddr + DMA_BUS_MODE);
>> +	writel(value, ioaddr + DMA_CHAN_BUS_MODE(chan));
>>   
>>   	/* Mask interrupts by writing to CSR7 */
>> -	writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_INTR_ENA);
>> +	writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_CHAN_INTR_ENA(chan));
>>   }
>>   
>>   static void dwmac1000_dma_init_rx(struct stmmac_priv *priv,
>> @@ -116,7 +118,7 @@ static void dwmac1000_dma_init_rx(struct stmmac_priv *priv,
>>   				  dma_addr_t dma_rx_phy, u32 chan)
>>   {
>>   	/* RX descriptor base address list must be written into DMA CSR3 */
>> -	writel(lower_32_bits(dma_rx_phy), ioaddr + DMA_RCV_BASE_ADDR);
>> +	writel(lower_32_bits(dma_rx_phy), ioaddr + DMA_CHAN_RCV_BASE_ADDR(chan));
>>   }
>>   
>>   static void dwmac1000_dma_init_tx(struct stmmac_priv *priv,
>> @@ -125,7 +127,7 @@ static void dwmac1000_dma_init_tx(struct stmmac_priv *priv,
>>   				  dma_addr_t dma_tx_phy, u32 chan)
>>   {
>>   	/* TX descriptor base address list must be written into DMA CSR4 */
>> -	writel(lower_32_bits(dma_tx_phy), ioaddr + DMA_TX_BASE_ADDR);
>> +	writel(lower_32_bits(dma_tx_phy), ioaddr + DMA_CHAN_TX_BASE_ADDR(chan));
>>   }
>>   
>>   static u32 dwmac1000_configure_fc(u32 csr6, int rxfifosz)
>> @@ -153,7 +155,7 @@ static void dwmac1000_dma_operation_mode_rx(struct stmmac_priv *priv,
>>   					    void __iomem *ioaddr, int mode,
>>   					    u32 channel, int fifosz, u8 qmode)
>>   {
>> -	u32 csr6 = readl(ioaddr + DMA_CONTROL);
>> +	u32 csr6 = readl(ioaddr + DMA_CHAN_CONTROL(channel));
>>   
>>   	if (mode == SF_DMA_MODE) {
>>   		pr_debug("GMAC: enable RX store and forward mode\n");
>> @@ -175,14 +177,14 @@ static void dwmac1000_dma_operation_mode_rx(struct stmmac_priv *priv,
>>   	/* Configure flow control based on rx fifo size */
>>   	csr6 = dwmac1000_configure_fc(csr6, fifosz);
>>   
>> -	writel(csr6, ioaddr + DMA_CONTROL);
>> +	writel(csr6, ioaddr + DMA_CHAN_CONTROL(channel));
>>   }
>>   
>>   static void dwmac1000_dma_operation_mode_tx(struct stmmac_priv *priv,
>>   					    void __iomem *ioaddr, int mode,
>>   					    u32 channel, int fifosz, u8 qmode)
>>   {
>> -	u32 csr6 = readl(ioaddr + DMA_CONTROL);
>> +	u32 csr6 = readl(ioaddr + DMA_CHAN_CONTROL(channel));
>>   
>>   	if (mode == SF_DMA_MODE) {
>>   		pr_debug("GMAC: enable TX store and forward mode\n");
>> @@ -209,7 +211,7 @@ static void dwmac1000_dma_operation_mode_tx(struct stmmac_priv *priv,
>>   			csr6 |= DMA_CONTROL_TTC_256;
>>   	}
>>   
>> -	writel(csr6, ioaddr + DMA_CONTROL);
>> +	writel(csr6, ioaddr + DMA_CHAN_CONTROL(channel));
>>   }
>>   
>>   static void dwmac1000_dump_dma_regs(struct stmmac_priv *priv,
>> @@ -271,12 +273,12 @@ static int dwmac1000_get_hw_feature(void __iomem *ioaddr,
>>   static void dwmac1000_rx_watchdog(struct stmmac_priv *priv,
>>   				  void __iomem *ioaddr, u32 riwt, u32 queue)
>>   {
>> -	writel(riwt, ioaddr + DMA_RX_WATCHDOG);
>> +	writel(riwt, ioaddr + DMA_CHAN_RX_WATCHDOG(queue));
>>   }
>>   
>>   const struct stmmac_dma_ops dwmac1000_dma_ops = {
>>   	.reset = dwmac_dma_reset,
>> -	.init = dwmac1000_dma_init,
>> +	.init_chan = dwmac1000_dma_init_channel,
>>   	.init_rx_chan = dwmac1000_dma_init_rx,
>>   	.init_tx_chan = dwmac1000_dma_init_tx,
>>   	.axi = dwmac1000_dma_axi,
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
>> index 72672391675f..593be79c46e1 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
>> @@ -148,11 +148,14 @@
>>   					 DMA_STATUS_TI | \
>>   					 DMA_STATUS_MSK_COMMON)
>>   
>> +/* Following DMA defines are chanels oriented */    \
>> +#define DMA_CHAN_OFFSET			0x100   |-------------+
>> +                                                    /              |
>                                                                        |
> Please move all of these ---------------------------------------------+-------------------------+
> to being defined just below the DMA_MISSED_FRAME_CTR macros definition.                         |
> The point is to keep a coherency between dwmac_dma.h and dwmac4_dma.h.                          |
> The later header file has first generic DMA-related macros defined                              |
> (CSR addresses and flags) and then the channel-specific ones (CSR                               |
> addresses and flags). Since in case of the DW GMAC v3.x the                                     |
> multi-channels are implemented as a copy of all the DMA CSRs let's                              |
> preserve the logic of having all CSR address defined first, then the                            |
> CSR flags.                                                                                      |
>                                                                                                  |
>>   #define NUM_DWMAC100_DMA_REGS	9                                                       |
>>   #define NUM_DWMAC1000_DMA_REGS	23                                                      |
>>   #define NUM_DWMAC4_DMA_REGS	27                                                              |
>>                                                                                                |
>> -void dwmac_enable_dma_transmission(void __iomem *ioaddr);                                    |
>> +void dwmac_enable_dma_transmission(void __iomem *ioaddr, u32 chan);                          |
>>   void dwmac_enable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr,                    |
>>   			  u32 chan, bool rx, bool tx);                                          |
>>   void dwmac_disable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr,                   |
>> @@ -169,4 +172,18 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,  |
>>   			struct stmmac_extra_stats *x, u32 chan, u32 dir);                       |
>>   int dwmac_dma_reset(void __iomem *ioaddr);                                                   |
>>                                                                                                |
>                                                                                                  |
>> +static inline u32 dma_chan_base_addr(u32 base, u32 chan)                                  \  |
>> +{                                                                                          | |
>> +	return base + chan * DMA_CHAN_OFFSET;                                                 | |
>> +}                                                                                          | |
>> +                                                                                           | |
>> +#define DMA_CHAN_XMT_POLL_DEMAND(chan)	dma_chan_base_addr(DMA_XMT_POLL_DEMAND, chan) | |
>> +#define DMA_CHAN_INTR_ENA(chan)		dma_chan_base_addr(DMA_INTR_ENA, chan)        | |
>> +#define DMA_CHAN_CONTROL(chan)		dma_chan_base_addr(DMA_CONTROL, chan)         | |
>> +#define DMA_CHAN_STATUS(chan)		dma_chan_base_addr(DMA_STATUS, chan)          |-+
>> +#define DMA_CHAN_BUS_MODE(chan)		dma_chan_base_addr(DMA_BUS_MODE, chan)        |
>> +#define DMA_CHAN_RCV_BASE_ADDR(chan)	dma_chan_base_addr(DMA_RCV_BASE_ADDR, chan)           |
>> +#define DMA_CHAN_TX_BASE_ADDR(chan)	dma_chan_base_addr(DMA_TX_BASE_ADDR, chan)            |
>> +#define DMA_CHAN_RX_WATCHDOG(chan)	dma_chan_base_addr(DMA_RX_WATCHDOG, chan)             |
>> +                                                                                           /
>>   #endif /* __DWMAC_DMA_H__ */
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
>> index 7907d62d3437..b37368137810 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
>> @@ -28,65 +28,65 @@ int dwmac_dma_reset(void __iomem *ioaddr)
>>   }
>>   
>>   /* CSR1 enables the transmit DMA to check for new descriptor */
>> -void dwmac_enable_dma_transmission(void __iomem *ioaddr)
>> +void dwmac_enable_dma_transmission(void __iomem *ioaddr, u32 chan)
>>   {
>> -	writel(1, ioaddr + DMA_XMT_POLL_DEMAND);
>> +	writel(1, ioaddr + DMA_CHAN_XMT_POLL_DEMAND(chan));
>>   }
>>   
>>   void dwmac_enable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr,
>>   			  u32 chan, bool rx, bool tx)
>>   {
>> -	u32 value = readl(ioaddr + DMA_INTR_ENA);
>> +	u32 value = readl(ioaddr + DMA_CHAN_INTR_ENA(chan));
>>   
>>   	if (rx)
>>   		value |= DMA_INTR_DEFAULT_RX;
>>   	if (tx)
>>   		value |= DMA_INTR_DEFAULT_TX;
>>   
>> -	writel(value, ioaddr + DMA_INTR_ENA);
>> +	writel(value, ioaddr + DMA_CHAN_INTR_ENA(chan));
>>   }
>>   
>>   void dwmac_disable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr,
>>   			   u32 chan, bool rx, bool tx)
>>   {
>> -	u32 value = readl(ioaddr + DMA_INTR_ENA);
>> +	u32 value = readl(ioaddr + DMA_CHAN_INTR_ENA(chan));
>>   
>>   	if (rx)
>>   		value &= ~DMA_INTR_DEFAULT_RX;
>>   	if (tx)
>>   		value &= ~DMA_INTR_DEFAULT_TX;
>>   
>> -	writel(value, ioaddr + DMA_INTR_ENA);
>> +	writel(value, ioaddr + DMA_CHAN_INTR_ENA(chan));
>>   }
>>   
>>   void dwmac_dma_start_tx(struct stmmac_priv *priv, void __iomem *ioaddr,
>>   			u32 chan)
>>   {
>> -	u32 value = readl(ioaddr + DMA_CONTROL);
>> +	u32 value = readl(ioaddr + DMA_CHAN_CONTROL(chan));
>>   	value |= DMA_CONTROL_ST;
>> -	writel(value, ioaddr + DMA_CONTROL);
>> +	writel(value, ioaddr + DMA_CHAN_CONTROL(chan));
>>   }
>>   
>>   void dwmac_dma_stop_tx(struct stmmac_priv *priv, void __iomem *ioaddr, u32 chan)
>>   {
>> -	u32 value = readl(ioaddr + DMA_CONTROL);
>> +	u32 value = readl(ioaddr + DMA_CHAN_CONTROL(chan));
>>   	value &= ~DMA_CONTROL_ST;
>> -	writel(value, ioaddr + DMA_CONTROL);
>> +	writel(value, ioaddr + DMA_CHAN_CONTROL(chan));
>>   }
>>   
>>   void dwmac_dma_start_rx(struct stmmac_priv *priv, void __iomem *ioaddr,
>>   			u32 chan)
>>   {
>> -	u32 value = readl(ioaddr + DMA_CONTROL);
>> +	u32 value = readl(ioaddr + DMA_CHAN_CONTROL(chan));
>>   	value |= DMA_CONTROL_SR;
>> -	writel(value, ioaddr + DMA_CONTROL);
>> +	writel(value, ioaddr + DMA_CHAN_CONTROL(chan));
>>   }
>>   
>>   void dwmac_dma_stop_rx(struct stmmac_priv *priv, void __iomem *ioaddr, u32 chan)
>>   {
>> -	u32 value = readl(ioaddr + DMA_CONTROL);
>> +	u32 value = readl(ioaddr + DMA_CHAN_CONTROL(chan));
>>   	value &= ~DMA_CONTROL_SR;
>> -	writel(value, ioaddr + DMA_CONTROL);
>> +	writel(value, ioaddr + DMA_CHAN_CONTROL(chan));
>>   }
>>   
>>   #ifdef DWMAC_DMA_DEBUG
>> @@ -166,7 +166,7 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
>>   	struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[chan];
>>   	int ret = 0;
>>   	/* read the status register (CSR5) */
>> -	u32 intr_status = readl(ioaddr + DMA_STATUS);
>> +	u32 intr_status = readl(ioaddr + DMA_CHAN_STATUS(chan));
>>   
>>   #ifdef DWMAC_DMA_DEBUG
>>   	/* Enable it to monitor DMA rx/tx status in case of critical problems */
>> @@ -236,7 +236,7 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
>>   		pr_warn("%s: unexpected status %08x\n", __func__, intr_status);
>>   
>>   	/* Clear the interrupt by writing a logic 1 to the CSR5[15-0] */
>> -	writel((intr_status & 0x1ffff), ioaddr + DMA_STATUS);
>> +	writel((intr_status & 0x7ffff), ioaddr + DMA_CHAN_STATUS(chan));
> Isn't the mask change going to be implemented in the framework of the
> Loongson-specific DMA-interrupt handler in some of the further patches?
>
>
> I'll get back to reviewing the series tomorrow (later today)...
>
> -Serge(y)
>
>>   
>>   	return ret;
>>   }
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h
>> index 7be04b54738b..b0db38396171 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/hwif.h
>> +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h
>> @@ -198,7 +198,7 @@ struct stmmac_dma_ops {
>>   	/* To track extra statistic (if supported) */
>>   	void (*dma_diagnostic_fr)(struct stmmac_extra_stats *x,
>>   				  void __iomem *ioaddr);
>> -	void (*enable_dma_transmission) (void __iomem *ioaddr);
>> +	void (*enable_dma_transmission)(void __iomem *ioaddr, u32 chan);
>>   	void (*enable_dma_irq)(struct stmmac_priv *priv, void __iomem *ioaddr,
>>   			       u32 chan, bool rx, bool tx);
>>   	void (*disable_dma_irq)(struct stmmac_priv *priv, void __iomem *ioaddr,
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>> index b334eb16da23..5617b40abbe4 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>> @@ -2558,7 +2558,7 @@ static bool stmmac_xdp_xmit_zc(struct stmmac_priv *priv, u32 queue, u32 budget)
>>   				       true, priv->mode, true, true,
>>   				       xdp_desc.len);
>>   
>> -		stmmac_enable_dma_transmission(priv, priv->ioaddr);
>> +		stmmac_enable_dma_transmission(priv, priv->ioaddr, queue);
>>   
>>   		xsk_tx_metadata_to_compl(meta,
>>   					 &tx_q->tx_skbuff_dma[entry].xsk_meta);
>> @@ -4706,7 +4706,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
>>   
>>   	netdev_tx_sent_queue(netdev_get_tx_queue(dev, queue), skb->len);
>>   
>> -	stmmac_enable_dma_transmission(priv, priv->ioaddr);
>> +	stmmac_enable_dma_transmission(priv, priv->ioaddr, queue);
>>   
>>   	stmmac_flush_tx_descriptors(priv, queue);
>>   	stmmac_tx_timer_arm(priv, queue);
>> @@ -4926,7 +4926,7 @@ static int stmmac_xdp_xmit_xdpf(struct stmmac_priv *priv, int queue,
>>   		u64_stats_update_end_irqrestore(&txq_stats->syncp, flags);
>>   	}
>>   
>> -	stmmac_enable_dma_transmission(priv, priv->ioaddr);
>> +	stmmac_enable_dma_transmission(priv, priv->ioaddr, queue);
>>   
>>   	entry = STMMAC_GET_ENTRY(entry, priv->dma_conf.dma_tx_size);
>>   	tx_q->cur_tx = entry;
>> -- 
>> 2.31.4
>>


^ permalink raw reply related	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 03/11] net: stmmac: dwmac-loongson: Add full PCI support
  2024-02-05 16:49   ` Serge Semin
@ 2024-02-21 10:08     ` Yanteng Si
  0 siblings, 0 replies; 97+ messages in thread
From: Yanteng Si @ 2024-02-21 10:08 UTC (permalink / raw)
  To: Serge Semin
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang


在 2024/2/6 00:49, Serge Semin 写道:
> On Tue, Jan 30, 2024 at 04:43:23PM +0800, Yanteng Si wrote:
>> Current dwmac-loongson only support LS2K in the "probed with PCI and
>> configured with DT" manner. Add LS7A support on which the devices are
>> fully PCI (non-DT).
> Please add to the commit log more details of what LS7A is like and
> bind that description to the changes below like the interface
> settings, ref and PTP clock settings, etc. What is the difference
> between LS2K and LS7A?
OK,
>
>> Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
>> Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
>> Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
>> ---
>>   .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 79 +++++++++++--------
>>   1 file changed, 44 insertions(+), 35 deletions(-)
>>
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>> index e2dcb339b8b0..979c9b6dab3f 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>> @@ -16,6 +16,10 @@ struct stmmac_pci_info {
>>   static void loongson_default_data(struct pci_dev *pdev,
>>   				  struct plat_stmmacenet_data *plat)
>>   {
>> +	/* Get bus_id, this can be overloaded later */
>> +	plat->bus_id = (pci_domain_nr(pdev->bus) << 16) |
>> +		       PCI_DEVID(pdev->bus->number, pdev->devfn);
>> +
>>   	plat->clk_csr = 2;	/* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */
>>   	plat->has_gmac = 1;
>>   	plat->force_sf_dma_mode = 1;
>> @@ -51,10 +55,14 @@ static int loongson_gmac_data(struct pci_dev *pdev,
>>   	plat->mdio_bus_data->phy_mask = 0;
>>   
>>   	plat->phy_addr = -1;
>> +	plat->phy_interface = PHY_INTERFACE_MODE_RGMII_ID;
>>   
>>   	plat->dma_cfg->pbl = 32;
>>   	plat->dma_cfg->pblx8 = true;
>>   
>> +	plat->clk_ref_rate = 125000000;
>> +	plat->clk_ptp_rate = 125000000;
>> +
> Is this compatible with the LS2K GMAC?
Of course!
>
>>   	return 0;
>>   }
>>   
>> @@ -71,13 +79,6 @@ static int loongson_dwmac_probe(struct pci_dev *pdev,
>>   	struct stmmac_resources res;
>>   	struct device_node *np;
>>   
>> -	np = dev_of_node(&pdev->dev);
>> -
>> -	if (!np) {
>> -		pr_info("dwmac_loongson_pci: No OF node\n");
>> -		return -ENODEV;
>> -	}
>> -
>>   	plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL);
>>   	if (!plat)
>>   		return -ENOMEM;
>> @@ -93,6 +94,7 @@ static int loongson_dwmac_probe(struct pci_dev *pdev,
>>   	if (!plat->dma_cfg)
>>   		return -ENOMEM;
>>   
>> +	np = dev_of_node(&pdev->dev);
>>   	plat->mdio_node = of_get_child_by_name(np, "mdio");
>>   	if (plat->mdio_node) {
>>   		dev_info(&pdev->dev, "Found MDIO subnode\n");
> Shouldn't mdio_node setup being done under the "if (np)" clause?
Yes, they will be moved there.
>
>> @@ -123,41 +125,48 @@ static int loongson_dwmac_probe(struct pci_dev *pdev,
>>   	if (ret)
>>   		goto err_disable_device;
>>   
>> -	bus_id = of_alias_get_id(np, "ethernet");
>> -	if (bus_id >= 0)
>> -		plat->bus_id = bus_id;
>> +	if (np) {
>> +		bus_id = of_alias_get_id(np, "ethernet");
>> +		if (bus_id >= 0)
>> +			plat->bus_id = bus_id;
>>   
>> -	phy_mode = device_get_phy_mode(&pdev->dev);
>> -	if (phy_mode < 0) {
>> -		dev_err(&pdev->dev, "phy_mode not found\n");
>> -		ret = phy_mode;
>> -		goto err_disable_device;
>> +		phy_mode = device_get_phy_mode(&pdev->dev);
>> +		if (phy_mode < 0) {
>> +			dev_err(&pdev->dev, "phy_mode not found\n");
>> +			ret = phy_mode;
>> +			goto err_disable_device;
>> +		}
>> +		plat->phy_interface = phy_mode;
>>   	}
> Please collect all OF-specific code in the same "if (np)" clause if
> possible.
OK,
>
>>   
>> -	plat->phy_interface = phy_mode;	np = dev_of_node(&pdev->dev);
>> -
>>   	pci_enable_msi(pdev);
>>   	memset(&res, 0, sizeof(res));
>>   	res.addr = pcim_iomap_table(pdev)[0];
>>   
>> -	res.irq = of_irq_get_byname(np, "macirq");
>> -	if (res.irq < 0) {
>> -		dev_err(&pdev->dev, "IRQ macirq not found\n");
>> -		ret = -ENODEV;
>> -		goto err_disable_msi;
>> -	}
>> -
>> -	res.wol_irq = of_irq_get_byname(np, "eth_wake_irq");
>> -	if (res.wol_irq < 0) {
>> -		dev_info(&pdev->dev, "IRQ eth_wake_irq not found, using macirq\n");
>> -		res.wol_irq = res.irq;
>> -	}
>> -
>> -	res.lpi_irq = of_irq_get_byname(np, "eth_lpi");
>> -	if (res.lpi_irq < 0) {
>> -		dev_err(&pdev->dev, "IRQ eth_lpi not found\n");
>> -		ret = -ENODEV;
>> -		goto err_disable_msi;
>> +	if (np) {
>> +		res.irq = of_irq_get_byname(np, "macirq");
>> +		if (res.irq < 0) {
>> +			dev_err(&pdev->dev, "IRQ macirq not found\n");
>> +			ret = -ENODEV;
>> +			goto err_disable_msi;
>> +		}
>> +
>> +		res.wol_irq = of_irq_get_byname(np, "eth_wake_irq");
>> +		if (res.wol_irq < 0) {
>> +			dev_info(&pdev->dev,
>> +				 "IRQ eth_wake_irq not found, using macirq\n");
>> +			res.wol_irq = res.irq;
>> +		}
>> +
>> +		res.lpi_irq = of_irq_get_byname(np, "eth_lpi");
>> +		if (res.lpi_irq < 0) {
>> +			dev_err(&pdev->dev, "IRQ eth_lpi not found\n");
>> +			ret = -ENODEV;
>> +			goto err_disable_msi;
>> +		}
>> +	} else {
>> +		res.irq = pdev->irq;
>> +		res.wol_irq = pdev->irq;
> This seems redundant. If res.wol_irq matches res_irq it won't be used
> (see stmmac_request_irq_multi_msi() and stmmac_request_irq_single()).
> What about dropping it?

Okay, actually, it was removed by subsequent patches.


Thanks,

Yanteng

>
> -Serge(y)
>
>>   	}
>>   
>>   	ret = stmmac_dvr_probe(&pdev->dev, plat, &res);
>> -- 
>> 2.31.4
>>


^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 01/11] net: stmmac: Add multi-channel support
  2024-02-19 11:02     ` Yanteng Si
@ 2024-02-21 13:48       ` Serge Semin
       [not found]         ` <ee2ffb6a-fe34-47a1-9734-b0e6697a5f09@loongson.cn>
  0 siblings, 1 reply; 97+ messages in thread
From: Serge Semin @ 2024-02-21 13:48 UTC (permalink / raw)
  To: Yanteng Si
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

Hi Yanteng

On Mon, Feb 19, 2024 at 07:02:24PM +0800, Yanteng Si wrote:
> Hi Serge
> 
> 在 2024/2/5 07:28, Serge Semin 写道:
> > On Tue, Jan 30, 2024 at 04:43:21PM +0800, Yanteng Si wrote:
> > > DW GMAC v3.x multi-channels feature is implemented as multiple
> > > sets of the same CSRs. Here is only preliminary support, it will
> > > be useful for the driver further evolution and for the users
> > > having multi-channel DWGMAC v3.x devices.
> > > 
> > > Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
> > > Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
> > > Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
> > > ---
> > >   .../net/ethernet/stmicro/stmmac/dwmac-sun8i.c |  2 +-
> > >   .../ethernet/stmicro/stmmac/dwmac1000_dma.c   | 36 ++++++++++---------
> > >   .../net/ethernet/stmicro/stmmac/dwmac_dma.h   | 19 +++++++++-
> > >   .../net/ethernet/stmicro/stmmac/dwmac_lib.c   | 32 ++++++++---------
> > >   drivers/net/ethernet/stmicro/stmmac/hwif.h    |  2 +-
> > >   .../net/ethernet/stmicro/stmmac/stmmac_main.c |  6 ++--
> > >   6 files changed, 58 insertions(+), 39 deletions(-)
> > > 
> > > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
> > > index 137741b94122..7cdfa0bdb93a 100644
> > > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
> > > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
> > > @@ -395,7 +395,7 @@ static void sun8i_dwmac_dma_start_tx(struct stmmac_priv *priv,
> > >   	writel(v, ioaddr + EMAC_TX_CTL1);
> > >   }
> > > -static void sun8i_dwmac_enable_dma_transmission(void __iomem *ioaddr)
> > > +static void sun8i_dwmac_enable_dma_transmission(void __iomem *ioaddr, u32 chan)
> > >   {
> > >   	u32 v;
> > > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> > > index daf79cdbd3ec..5f7b82ad3ec2 100644
> > > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> > > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> > > @@ -70,15 +70,18 @@ static void dwmac1000_dma_axi(void __iomem *ioaddr, struct stmmac_axi *axi)
> > >   	writel(value, ioaddr + DMA_AXI_BUS_MODE);
> > >   }
> > > -static void dwmac1000_dma_init(void __iomem *ioaddr,
> > > -			       struct stmmac_dma_cfg *dma_cfg, int atds)
> > > +static void dwmac1000_dma_init_channel(struct stmmac_priv *priv,
> > > +				       void __iomem *ioaddr,
> > > +				       struct stmmac_dma_cfg *dma_cfg, u32 chan)
> > >   {
> > > -	u32 value = readl(ioaddr + DMA_BUS_MODE);
> > > +	u32 value;
> > >   	int txpbl = dma_cfg->txpbl ?: dma_cfg->pbl;
> > >   	int rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl;
> > Reverse xmas tree please.
> > 
> > > -	/*
> > > -	 * Set the DMA PBL (Programmable Burst Length) mode.
> > > +	/* common channel control register config */
> > Redundant comment. Please drop.
> > 
> > > +	value = readl(ioaddr + DMA_CHAN_BUS_MODE(chan));
> > > +
> > > +	/* Set the DMA PBL (Programmable Burst Length) mode.
> > >   	 *
> > >   	 * Note: before stmmac core 3.50 this mode bit was 4xPBL, and
> > >   	 * post 3.5 mode bit acts as 8*PBL.
> > > @@ -98,16 +101,15 @@ static void dwmac1000_dma_init(void __iomem *ioaddr,
> > >   	if (dma_cfg->mixed_burst)
> > >   		value |= DMA_BUS_MODE_MB;
> > > -	if (atds)
> > > -		value |= DMA_BUS_MODE_ATDS;
> > > +	value |= DMA_BUS_MODE_ATDS;
> > No, just convert the stmmac_dma_ops.dma_init_channel() to accepting
> > the atds flag as I suggested in v7:
> > https://lore.kernel.org/netdev/vxcfrxtbfu4pya56m22icnizsyjzqqha5blzb7zpexqcur56uh@uv6vsjf77npa/
> > 
> > In order to simplify this patch you can provide the
> > stmmac_dma_ops.dma_init_channel() and
> > stmmac_dma_ops.enable_dma_transmission() prototype updates in a
> > pre-requisite/preparation patch.
> 
> Sorry to keep you waiting for so long, I finally got the machine again.
> Regarding atds, is this how it is implemented?
> 
> On the basis of applying PATCH v8:
> 
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> index 0323f0a5049c..ce99f4a1b320 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> @@ -72,7 +72,8 @@ static void dwmac1000_dma_axi(void __iomem *ioaddr, struct
> stmmac_axi *axi)
> 
>  static void dwmac1000_dma_init_channel(struct stmmac_priv *priv,
>                         void __iomem *ioaddr,
> -                       struct stmmac_dma_cfg *dma_cfg, u32 chan)
> +                       struct stmmac_dma_cfg *dma_cfg,
> +                       int atds, u32 chan)
>  {
>      u32 value;
>      int txpbl = dma_cfg->txpbl ?: dma_cfg->pbl;
> @@ -101,7 +102,8 @@ static void dwmac1000_dma_init_channel(struct
> stmmac_priv *priv,
>      if (dma_cfg->mixed_burst)
>          value |= DMA_BUS_MODE_MB;
> 
> -    value |= DMA_BUS_MODE_ATDS;
> +    if (atds)
> +        value |= DMA_BUS_MODE_ATDS;
> 
>      if (dma_cfg->aal)
>          value |= DMA_BUS_MODE_AAL;
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
> b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
> index 84d3a8551b03..8a79c154b553 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
> @@ -117,7 +117,8 @@ static void dwmac4_dma_init_tx_chan(struct stmmac_priv
> *priv,
> 
>  static void dwmac4_dma_init_channel(struct stmmac_priv *priv,
>                      void __iomem *ioaddr,
> -                    struct stmmac_dma_cfg *dma_cfg, u32 chan)
> +                    struct stmmac_dma_cfg *dma_cfg,
> +                                    int atds, u32 chan)
>  {
>      const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;
>      u32 value;
> @@ -135,7 +136,8 @@ static void dwmac4_dma_init_channel(struct stmmac_priv
> *priv,
> 
>  static void dwmac410_dma_init_channel(struct stmmac_priv *priv,
>                        void __iomem *ioaddr,
> -                      struct stmmac_dma_cfg *dma_cfg, u32 chan)
> +                      struct stmmac_dma_cfg *dma_cfg,
> +                                      int atds, u32 chan)
>  {
>      const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;
>      u32 value;
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
> b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
> index dd2ab6185c40..d1627b2e50c8 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
> @@ -35,7 +35,8 @@ static void dwxgmac2_dma_init(void __iomem *ioaddr,
> 
>  static void dwxgmac2_dma_init_chan(struct stmmac_priv *priv,
>                     void __iomem *ioaddr,
> -                   struct stmmac_dma_cfg *dma_cfg, u32 chan)
> +                   struct stmmac_dma_cfg *dma_cfg,
> +                                   int atds, u32 chan)
>  {
>      u32 value = readl(ioaddr + XGMAC_DMA_CH_CONTROL(chan));
> 
> diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h
> b/drivers/net/ethernet/stmicro/stmmac/hwif.h
> index b0db38396171..fb27ad0e97e8 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/hwif.h
> +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h
> @@ -178,7 +178,7 @@ struct stmmac_dma_ops {
>      void (*init)(void __iomem *ioaddr, struct stmmac_dma_cfg *dma_cfg,
>               int atds);
>      void (*init_chan)(struct stmmac_priv *priv, void __iomem *ioaddr,
> -              struct stmmac_dma_cfg *dma_cfg, u32 chan);
> +              struct stmmac_dma_cfg *dma_cfg, int atds, u32 chan);
>      void (*init_rx_chan)(struct stmmac_priv *priv, void __iomem *ioaddr,
>                   struct stmmac_dma_cfg *dma_cfg,
>                   dma_addr_t phy, u32 chan);
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> index 3eed202d1f1c..8705e04913d1 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> @@ -3039,7 +3039,7 @@ static int stmmac_init_dma_engine(struct stmmac_priv
> *priv)
> 
>      /* DMA CSR Channel configuration */
>      for (chan = 0; chan < dma_csr_ch; chan++) {
> -        stmmac_init_chan(priv, priv->ioaddr, priv->plat->dma_cfg, chan);
> +        stmmac_init_chan(priv, priv->ioaddr, priv->plat->dma_cfg, atds,
> chan);
>          stmmac_disable_dma_irq(priv, priv->ioaddr, chan, 1, 1);
>      }
> 
> @@ -6963,6 +6963,7 @@ int stmmac_xdp_open(struct net_device *dev)
>      u32 buf_size;
>      bool sph_en;
>      u32 chan;
> +     int atds;
>      int ret;
> 
>      ret = alloc_dma_desc_resources(priv, &priv->dma_conf);
> @@ -6981,9 +6982,12 @@ int stmmac_xdp_open(struct net_device *dev)
> 
>      stmmac_reset_queues_param(priv);
> 
> +    if (priv->extend_desc && (priv->mode == STMMAC_RING_MODE))
> +        atds = 1;
> +
>      /* DMA CSR Channel configuration */
>      for (chan = 0; chan < dma_csr_ch; chan++) {
> -        stmmac_init_chan(priv, priv->ioaddr, priv->plat->dma_cfg, chan);
> +        stmmac_init_chan(priv, priv->ioaddr, priv->plat->dma_cfg, atds,
> chan);
>          stmmac_disable_dma_irq(priv, priv->ioaddr, chan, 1, 1);
>      }

Looking more thoroughly at this part I suggest to act a bit
differently. Let's move the atds flag to the stmmac_dma_cfg structure.
Alternate Descriptor Size (ATDS) is a part of the DMA-configs together
with the PBL, ALL, AEME, etc so the structure is the most suitable
place for it. Here is what should be done for that:
1. Add stmmac_dma_cfg::atds boolean field.
2. Drop atds argument from the stmmac_dma_ops::init() callback and use
the stmmac_dma_cfg::atds field in the callback implementations.
3. Alter stmmac_init_dma_engine() to updating the dma_cfg->atds field
instead of the local variable.

Please implement that update in a pre-requisite/preparation patch.

After that you can freely use the stmmac_dma_cfg::atds field in the
stmmac_init_chan() method too.

-Serge(y)

> 
> 
> Thanks,
> 
> Yanteng
> 
> > 
> > >   	if (dma_cfg->aal)
> > >   		value |= DMA_BUS_MODE_AAL;
> > > -	writel(value, ioaddr + DMA_BUS_MODE);
> > > +	writel(value, ioaddr + DMA_CHAN_BUS_MODE(chan));
> > >   	/* Mask interrupts by writing to CSR7 */
> > > -	writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_INTR_ENA);
> > > +	writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_CHAN_INTR_ENA(chan));
> > >   }
> > >   static void dwmac1000_dma_init_rx(struct stmmac_priv *priv,
> > > @@ -116,7 +118,7 @@ static void dwmac1000_dma_init_rx(struct stmmac_priv *priv,
> > >   				  dma_addr_t dma_rx_phy, u32 chan)
> > >   {
> > >   	/* RX descriptor base address list must be written into DMA CSR3 */
> > > -	writel(lower_32_bits(dma_rx_phy), ioaddr + DMA_RCV_BASE_ADDR);
> > > +	writel(lower_32_bits(dma_rx_phy), ioaddr + DMA_CHAN_RCV_BASE_ADDR(chan));
> > >   }
> > >   static void dwmac1000_dma_init_tx(struct stmmac_priv *priv,
> > > @@ -125,7 +127,7 @@ static void dwmac1000_dma_init_tx(struct stmmac_priv *priv,
> > >   				  dma_addr_t dma_tx_phy, u32 chan)
> > >   {
> > >   	/* TX descriptor base address list must be written into DMA CSR4 */
> > > -	writel(lower_32_bits(dma_tx_phy), ioaddr + DMA_TX_BASE_ADDR);
> > > +	writel(lower_32_bits(dma_tx_phy), ioaddr + DMA_CHAN_TX_BASE_ADDR(chan));
> > >   }
> > >   static u32 dwmac1000_configure_fc(u32 csr6, int rxfifosz)
> > > @@ -153,7 +155,7 @@ static void dwmac1000_dma_operation_mode_rx(struct stmmac_priv *priv,
> > >   					    void __iomem *ioaddr, int mode,
> > >   					    u32 channel, int fifosz, u8 qmode)
> > >   {
> > > -	u32 csr6 = readl(ioaddr + DMA_CONTROL);
> > > +	u32 csr6 = readl(ioaddr + DMA_CHAN_CONTROL(channel));
> > >   	if (mode == SF_DMA_MODE) {
> > >   		pr_debug("GMAC: enable RX store and forward mode\n");
> > > @@ -175,14 +177,14 @@ static void dwmac1000_dma_operation_mode_rx(struct stmmac_priv *priv,
> > >   	/* Configure flow control based on rx fifo size */
> > >   	csr6 = dwmac1000_configure_fc(csr6, fifosz);
> > > -	writel(csr6, ioaddr + DMA_CONTROL);
> > > +	writel(csr6, ioaddr + DMA_CHAN_CONTROL(channel));
> > >   }
> > >   static void dwmac1000_dma_operation_mode_tx(struct stmmac_priv *priv,
> > >   					    void __iomem *ioaddr, int mode,
> > >   					    u32 channel, int fifosz, u8 qmode)
> > >   {
> > > -	u32 csr6 = readl(ioaddr + DMA_CONTROL);
> > > +	u32 csr6 = readl(ioaddr + DMA_CHAN_CONTROL(channel));
> > >   	if (mode == SF_DMA_MODE) {
> > >   		pr_debug("GMAC: enable TX store and forward mode\n");
> > > @@ -209,7 +211,7 @@ static void dwmac1000_dma_operation_mode_tx(struct stmmac_priv *priv,
> > >   			csr6 |= DMA_CONTROL_TTC_256;
> > >   	}
> > > -	writel(csr6, ioaddr + DMA_CONTROL);
> > > +	writel(csr6, ioaddr + DMA_CHAN_CONTROL(channel));
> > >   }
> > >   static void dwmac1000_dump_dma_regs(struct stmmac_priv *priv,
> > > @@ -271,12 +273,12 @@ static int dwmac1000_get_hw_feature(void __iomem *ioaddr,
> > >   static void dwmac1000_rx_watchdog(struct stmmac_priv *priv,
> > >   				  void __iomem *ioaddr, u32 riwt, u32 queue)
> > >   {
> > > -	writel(riwt, ioaddr + DMA_RX_WATCHDOG);
> > > +	writel(riwt, ioaddr + DMA_CHAN_RX_WATCHDOG(queue));
> > >   }
> > >   const struct stmmac_dma_ops dwmac1000_dma_ops = {
> > >   	.reset = dwmac_dma_reset,
> > > -	.init = dwmac1000_dma_init,
> > > +	.init_chan = dwmac1000_dma_init_channel,
> > >   	.init_rx_chan = dwmac1000_dma_init_rx,
> > >   	.init_tx_chan = dwmac1000_dma_init_tx,
> > >   	.axi = dwmac1000_dma_axi,
> > > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
> > > index 72672391675f..593be79c46e1 100644
> > > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
> > > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
> > > @@ -148,11 +148,14 @@
> > >   					 DMA_STATUS_TI | \
> > >   					 DMA_STATUS_MSK_COMMON)
> > > +/* Following DMA defines are chanels oriented */    \
> > > +#define DMA_CHAN_OFFSET			0x100   |-------------+
> > > +                                                    /              |
> >                                                                        |
> > Please move all of these ---------------------------------------------+-------------------------+
> > to being defined just below the DMA_MISSED_FRAME_CTR macros definition.                         |
> > The point is to keep a coherency between dwmac_dma.h and dwmac4_dma.h.                          |
> > The later header file has first generic DMA-related macros defined                              |
> > (CSR addresses and flags) and then the channel-specific ones (CSR                               |
> > addresses and flags). Since in case of the DW GMAC v3.x the                                     |
> > multi-channels are implemented as a copy of all the DMA CSRs let's                              |
> > preserve the logic of having all CSR address defined first, then the                            |
> > CSR flags.                                                                                      |
> >                                                                                                  |
> > >   #define NUM_DWMAC100_DMA_REGS	9                                                       |
> > >   #define NUM_DWMAC1000_DMA_REGS	23                                                      |
> > >   #define NUM_DWMAC4_DMA_REGS	27                                                              |
> > >                                                                                                |
> > > -void dwmac_enable_dma_transmission(void __iomem *ioaddr);                                    |
> > > +void dwmac_enable_dma_transmission(void __iomem *ioaddr, u32 chan);                          |
> > >   void dwmac_enable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr,                    |
> > >   			  u32 chan, bool rx, bool tx);                                          |
> > >   void dwmac_disable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr,                   |
> > > @@ -169,4 +172,18 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,  |
> > >   			struct stmmac_extra_stats *x, u32 chan, u32 dir);                       |
> > >   int dwmac_dma_reset(void __iomem *ioaddr);                                                   |
> > >                                                                                                |
> >                                                                                                  |
> > > +static inline u32 dma_chan_base_addr(u32 base, u32 chan)                                  \  |
> > > +{                                                                                          | |
> > > +	return base + chan * DMA_CHAN_OFFSET;                                                 | |
> > > +}                                                                                          | |
> > > +                                                                                           | |
> > > +#define DMA_CHAN_XMT_POLL_DEMAND(chan)	dma_chan_base_addr(DMA_XMT_POLL_DEMAND, chan) | |
> > > +#define DMA_CHAN_INTR_ENA(chan)		dma_chan_base_addr(DMA_INTR_ENA, chan)        | |
> > > +#define DMA_CHAN_CONTROL(chan)		dma_chan_base_addr(DMA_CONTROL, chan)         | |
> > > +#define DMA_CHAN_STATUS(chan)		dma_chan_base_addr(DMA_STATUS, chan)          |-+
> > > +#define DMA_CHAN_BUS_MODE(chan)		dma_chan_base_addr(DMA_BUS_MODE, chan)        |
> > > +#define DMA_CHAN_RCV_BASE_ADDR(chan)	dma_chan_base_addr(DMA_RCV_BASE_ADDR, chan)           |
> > > +#define DMA_CHAN_TX_BASE_ADDR(chan)	dma_chan_base_addr(DMA_TX_BASE_ADDR, chan)            |
> > > +#define DMA_CHAN_RX_WATCHDOG(chan)	dma_chan_base_addr(DMA_RX_WATCHDOG, chan)             |
> > > +                                                                                           /
> > >   #endif /* __DWMAC_DMA_H__ */
> > > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
> > > index 7907d62d3437..b37368137810 100644
> > > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
> > > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
> > > @@ -28,65 +28,65 @@ int dwmac_dma_reset(void __iomem *ioaddr)
> > >   }
> > >   /* CSR1 enables the transmit DMA to check for new descriptor */
> > > -void dwmac_enable_dma_transmission(void __iomem *ioaddr)
> > > +void dwmac_enable_dma_transmission(void __iomem *ioaddr, u32 chan)
> > >   {
> > > -	writel(1, ioaddr + DMA_XMT_POLL_DEMAND);
> > > +	writel(1, ioaddr + DMA_CHAN_XMT_POLL_DEMAND(chan));
> > >   }
> > >   void dwmac_enable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr,
> > >   			  u32 chan, bool rx, bool tx)
> > >   {
> > > -	u32 value = readl(ioaddr + DMA_INTR_ENA);
> > > +	u32 value = readl(ioaddr + DMA_CHAN_INTR_ENA(chan));
> > >   	if (rx)
> > >   		value |= DMA_INTR_DEFAULT_RX;
> > >   	if (tx)
> > >   		value |= DMA_INTR_DEFAULT_TX;
> > > -	writel(value, ioaddr + DMA_INTR_ENA);
> > > +	writel(value, ioaddr + DMA_CHAN_INTR_ENA(chan));
> > >   }
> > >   void dwmac_disable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr,
> > >   			   u32 chan, bool rx, bool tx)
> > >   {
> > > -	u32 value = readl(ioaddr + DMA_INTR_ENA);
> > > +	u32 value = readl(ioaddr + DMA_CHAN_INTR_ENA(chan));
> > >   	if (rx)
> > >   		value &= ~DMA_INTR_DEFAULT_RX;
> > >   	if (tx)
> > >   		value &= ~DMA_INTR_DEFAULT_TX;
> > > -	writel(value, ioaddr + DMA_INTR_ENA);
> > > +	writel(value, ioaddr + DMA_CHAN_INTR_ENA(chan));
> > >   }
> > >   void dwmac_dma_start_tx(struct stmmac_priv *priv, void __iomem *ioaddr,
> > >   			u32 chan)
> > >   {
> > > -	u32 value = readl(ioaddr + DMA_CONTROL);
> > > +	u32 value = readl(ioaddr + DMA_CHAN_CONTROL(chan));
> > >   	value |= DMA_CONTROL_ST;
> > > -	writel(value, ioaddr + DMA_CONTROL);
> > > +	writel(value, ioaddr + DMA_CHAN_CONTROL(chan));
> > >   }
> > >   void dwmac_dma_stop_tx(struct stmmac_priv *priv, void __iomem *ioaddr, u32 chan)
> > >   {
> > > -	u32 value = readl(ioaddr + DMA_CONTROL);
> > > +	u32 value = readl(ioaddr + DMA_CHAN_CONTROL(chan));
> > >   	value &= ~DMA_CONTROL_ST;
> > > -	writel(value, ioaddr + DMA_CONTROL);
> > > +	writel(value, ioaddr + DMA_CHAN_CONTROL(chan));
> > >   }
> > >   void dwmac_dma_start_rx(struct stmmac_priv *priv, void __iomem *ioaddr,
> > >   			u32 chan)
> > >   {
> > > -	u32 value = readl(ioaddr + DMA_CONTROL);
> > > +	u32 value = readl(ioaddr + DMA_CHAN_CONTROL(chan));
> > >   	value |= DMA_CONTROL_SR;
> > > -	writel(value, ioaddr + DMA_CONTROL);
> > > +	writel(value, ioaddr + DMA_CHAN_CONTROL(chan));
> > >   }
> > >   void dwmac_dma_stop_rx(struct stmmac_priv *priv, void __iomem *ioaddr, u32 chan)
> > >   {
> > > -	u32 value = readl(ioaddr + DMA_CONTROL);
> > > +	u32 value = readl(ioaddr + DMA_CHAN_CONTROL(chan));
> > >   	value &= ~DMA_CONTROL_SR;
> > > -	writel(value, ioaddr + DMA_CONTROL);
> > > +	writel(value, ioaddr + DMA_CHAN_CONTROL(chan));
> > >   }
> > >   #ifdef DWMAC_DMA_DEBUG
> > > @@ -166,7 +166,7 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
> > >   	struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[chan];
> > >   	int ret = 0;
> > >   	/* read the status register (CSR5) */
> > > -	u32 intr_status = readl(ioaddr + DMA_STATUS);
> > > +	u32 intr_status = readl(ioaddr + DMA_CHAN_STATUS(chan));
> > >   #ifdef DWMAC_DMA_DEBUG
> > >   	/* Enable it to monitor DMA rx/tx status in case of critical problems */
> > > @@ -236,7 +236,7 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
> > >   		pr_warn("%s: unexpected status %08x\n", __func__, intr_status);
> > >   	/* Clear the interrupt by writing a logic 1 to the CSR5[15-0] */
> > > -	writel((intr_status & 0x1ffff), ioaddr + DMA_STATUS);
> > > +	writel((intr_status & 0x7ffff), ioaddr + DMA_CHAN_STATUS(chan));
> > Isn't the mask change going to be implemented in the framework of the
> > Loongson-specific DMA-interrupt handler in some of the further patches?
> > 
> > 
> > I'll get back to reviewing the series tomorrow (later today)...
> > 
> > -Serge(y)
> > 
> > >   	return ret;
> > >   }
> > > diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h
> > > index 7be04b54738b..b0db38396171 100644
> > > --- a/drivers/net/ethernet/stmicro/stmmac/hwif.h
> > > +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h
> > > @@ -198,7 +198,7 @@ struct stmmac_dma_ops {
> > >   	/* To track extra statistic (if supported) */
> > >   	void (*dma_diagnostic_fr)(struct stmmac_extra_stats *x,
> > >   				  void __iomem *ioaddr);
> > > -	void (*enable_dma_transmission) (void __iomem *ioaddr);
> > > +	void (*enable_dma_transmission)(void __iomem *ioaddr, u32 chan);
> > >   	void (*enable_dma_irq)(struct stmmac_priv *priv, void __iomem *ioaddr,
> > >   			       u32 chan, bool rx, bool tx);
> > >   	void (*disable_dma_irq)(struct stmmac_priv *priv, void __iomem *ioaddr,
> > > diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> > > index b334eb16da23..5617b40abbe4 100644
> > > --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> > > +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> > > @@ -2558,7 +2558,7 @@ static bool stmmac_xdp_xmit_zc(struct stmmac_priv *priv, u32 queue, u32 budget)
> > >   				       true, priv->mode, true, true,
> > >   				       xdp_desc.len);
> > > -		stmmac_enable_dma_transmission(priv, priv->ioaddr);
> > > +		stmmac_enable_dma_transmission(priv, priv->ioaddr, queue);
> > >   		xsk_tx_metadata_to_compl(meta,
> > >   					 &tx_q->tx_skbuff_dma[entry].xsk_meta);
> > > @@ -4706,7 +4706,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
> > >   	netdev_tx_sent_queue(netdev_get_tx_queue(dev, queue), skb->len);
> > > -	stmmac_enable_dma_transmission(priv, priv->ioaddr);
> > > +	stmmac_enable_dma_transmission(priv, priv->ioaddr, queue);
> > >   	stmmac_flush_tx_descriptors(priv, queue);
> > >   	stmmac_tx_timer_arm(priv, queue);
> > > @@ -4926,7 +4926,7 @@ static int stmmac_xdp_xmit_xdpf(struct stmmac_priv *priv, int queue,
> > >   		u64_stats_update_end_irqrestore(&txq_stats->syncp, flags);
> > >   	}
> > > -	stmmac_enable_dma_transmission(priv, priv->ioaddr);
> > > +	stmmac_enable_dma_transmission(priv, priv->ioaddr, queue);
> > >   	entry = STMMAC_GET_ENTRY(entry, priv->dma_conf.dma_tx_size);
> > >   	tx_q->cur_tx = entry;
> > > -- 
> > > 2.31.4
> > > 
> 

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 05/11] net: stmmac: dwmac-loongson: Add Loongson-specific register definitions
  2024-02-05 18:17   ` Serge Semin
@ 2024-02-22 13:39     ` Yanteng Si
  2024-02-22 13:59       ` Serge Semin
  0 siblings, 1 reply; 97+ messages in thread
From: Yanteng Si @ 2024-02-22 13:39 UTC (permalink / raw)
  To: Serge Semin
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang


在 2024/2/6 02:17, Serge Semin 写道:
> On Tue, Jan 30, 2024 at 04:48:17PM +0800, Yanteng Si wrote:
>> There are two types of Loongson DWGMAC. The first type shares the same
>> register definitions and has similar logic as dwmac1000. The second type
>> uses several different register definitions, we think it is necessary to
>> distinguish rx and tx, so we split these bits into two.
>>
>> Simply put, we split some single bit fields into double bits fileds:
>>
>>       Name              Tx          Rx
>>
>> DMA_INTR_ENA_NIE = 0x00040000 | 0x00020000;
>> DMA_INTR_ENA_AIE = 0x00010000 | 0x00008000;
>> DMA_STATUS_NIS   = 0x00040000 | 0x00020000;
>> DMA_STATUS_AIS   = 0x00010000 | 0x00008000;
>> DMA_STATUS_FBI   = 0x00002000 | 0x00001000;
>>
>> Therefore, when using, TX and RX must be set at the same time.
>>
>> How to use them:
>> 1. Create the Loongson GNET-specific
>> stmmac_dma_ops.dma_interrupt()
>> stmmac_dma_ops.init_chan()
>> methods in the dwmac-loongson.c driver. Adding all the
>> Loongson-specific macros
>>
>> 2. Create a Loongson GNET-specific platform setup method with the next
>> semantics:
>>     + allocate stmmac_dma_ops instance and initialize it with
>>       dwmac1000_dma_ops.
>>     + override the stmmac_dma_ops.{dma_interrupt, init_chan} with
>>       the pointers to the methods defined in 2.
>>     + allocate mac_device_info instance and initialize the
>>       mac_device_info.dma field with a pointer to the new
>>       stmmac_dma_ops instance.
>>     + initialize mac_device_info in a way it's done in
>>       dwmac1000_setup().
>>
>> 3. Initialize plat_stmmacenet_data.setup() with the pointer to the
>> method created in 2.
>>
>> Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
>> Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
>> Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
>> ---
>>   .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 248 ++++++++++++++++++
>>   1 file changed, 248 insertions(+)
>>
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>> index e7ce027cc14e..3b3578318cc1 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>> @@ -8,6 +8,193 @@
>>   #include <linux/device.h>
>>   #include <linux/of_irq.h>
>>   #include "stmmac.h"
>> +#include "dwmac_dma.h"
>> +#include "dwmac1000.h"
>> +
>> +#define DMA_INTR_ENA_NIE_TX_LOONGSON 0x00040000	/* Normal Loongson Tx Summary */
>> +#define DMA_INTR_ENA_NIE_RX_LOONGSON 0x00020000	/* Normal Loongson Rx Summary */
>> +#define DMA_INTR_NORMAL_LOONGSON	(DMA_INTR_ENA_NIE_TX_LOONGSON | \
>> +			 DMA_INTR_ENA_NIE_RX_LOONGSON | DMA_INTR_ENA_RIE | \
>> +			 DMA_INTR_ENA_TIE)
>> +
>> +#define DMA_INTR_ENA_AIE_TX_LOONGSON 0x00010000	/* Abnormal Loongson Tx Summary */
>> +#define DMA_INTR_ENA_AIE_RX_LOONGSON 0x00008000	/* Abnormal Loongson Rx Summary */
>> +
>> +#define DMA_INTR_ABNORMAL_LOONGSON	(DMA_INTR_ENA_AIE_TX_LOONGSON | \
>> +				DMA_INTR_ENA_AIE_RX_LOONGSON | DMA_INTR_ENA_FBE | \
>> +				DMA_INTR_ENA_UNE)
>> +
>> +#define DMA_INTR_DEFAULT_MASK_LOONGSON	(DMA_INTR_NORMAL_LOONGSON | DMA_INTR_ABNORMAL_LOONGSON)
>> +
>> +#define DMA_STATUS_NIS_TX_LOONGSON	0x00040000	/* Normal Loongson Tx Interrupt Summary */
>> +#define DMA_STATUS_NIS_RX_LOONGSON	0x00020000	/* Normal Loongson Rx Interrupt Summary */
>> +
>> +#define DMA_STATUS_AIS_TX_LOONGSON	0x00010000	/* Abnormal Loongson Tx Interrupt Summary */
>> +#define DMA_STATUS_AIS_RX_LOONGSON	0x00008000	/* Abnormal Loongson Rx Interrupt Summary */
>> +
>> +#define DMA_STATUS_FBI_TX_LOONGSON	0x00002000	/* Fatal Loongson Tx Bus Error Interrupt */
>> +#define DMA_STATUS_FBI_RX_LOONGSON	0x00001000	/* Fatal Loongson Rx Bus Error Interrupt */
>> +
>> +#define DMA_STATUS_MSK_COMMON_LOONGSON		(DMA_STATUS_NIS_TX_LOONGSON | \
>> +					 DMA_STATUS_NIS_RX_LOONGSON | DMA_STATUS_AIS_TX_LOONGSON | \
>> +					 DMA_STATUS_AIS_RX_LOONGSON | DMA_STATUS_FBI_TX_LOONGSON | \
>> +					 DMA_STATUS_FBI_RX_LOONGSON)
> Max 80 chars per line please.
OK,
>
>> +
>> +#define DMA_STATUS_MSK_RX_LOONGSON		(DMA_STATUS_ERI | \
>> +					 DMA_STATUS_RWT | \
>> +					 DMA_STATUS_RPS | \
>> +					 DMA_STATUS_RU | \
>> +					 DMA_STATUS_RI | \
>> +					 DMA_STATUS_OVF | \
>> +					 DMA_STATUS_MSK_COMMON_LOONGSON)
>> +
>> +#define DMA_STATUS_MSK_TX_LOONGSON		(DMA_STATUS_ETI | \
>> +					 DMA_STATUS_UNF | \
>> +					 DMA_STATUS_TJT | \
>> +					 DMA_STATUS_TU | \
>> +					 DMA_STATUS_TPS | \
>> +					 DMA_STATUS_TI | \
>> +					 DMA_STATUS_MSK_COMMON_LOONGSON)
>> +
>> +struct loongson_data {
>> +	struct device *dev;
>> +	u32 lgmac_version;
>> +	struct stmmac_dma_ops dwlgmac_dma_ops;
> Just figured out we can do without this field being added to the
> private data. See my note in the loongson_setup() method.
>
>> +};
>> +
>> +static void dwlgmac_dma_init_channel(struct stmmac_priv *priv,
> The "dwlgmac_" prefix is confusing. There is the DW XLGMAC IP-core for
> which the "dwxlgmac_" is more appropriate and "x" is easy to miss
> should your version of the prefix is met. Consider changing it to
> something like "loongson_gnet_".
OK,
>
>> +				     void __iomem *ioaddr,
>> +				     struct stmmac_dma_cfg *dma_cfg, u32 chan)
>> +{
>> +	u32 value;
>> +	int txpbl = dma_cfg->txpbl ?: dma_cfg->pbl;
>> +	int rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl;
>> +
>> +	/* common channel control register config */
>> +	value = readl(ioaddr + DMA_CHAN_BUS_MODE(chan));
>> +
>> +	/* Set the DMA PBL (Programmable Burst Length) mode.
>> +	 *
>> +	 * Note: before stmmac core 3.50 this mode bit was 4xPBL, and
>> +	 * post 3.5 mode bit acts as 8*PBL.
>> +	 */
>> +	if (dma_cfg->pblx8)
>> +		value |= DMA_BUS_MODE_MAXPBL;
>> +	value |= DMA_BUS_MODE_USP;
>> +	value &= ~(DMA_BUS_MODE_PBL_MASK | DMA_BUS_MODE_RPBL_MASK);
>> +	value |= (txpbl << DMA_BUS_MODE_PBL_SHIFT);
>> +	value |= (rxpbl << DMA_BUS_MODE_RPBL_SHIFT);
>> +
>> +	/* Set the Fixed burst mode */
>> +	if (dma_cfg->fixed_burst)
>> +		value |= DMA_BUS_MODE_FB;
>> +
>> +	/* Mixed Burst has no effect when fb is set */
>> +	if (dma_cfg->mixed_burst)
>> +		value |= DMA_BUS_MODE_MB;
>> +
>> +	value |= DMA_BUS_MODE_ATDS;
>> +
>> +	if (dma_cfg->aal)
>> +		value |= DMA_BUS_MODE_AAL;
>> +
>> +	writel(value, ioaddr + DMA_BUS_MODE);
>> +
>> +	/* Mask interrupts by writing to CSR7 */
>> +	writel(DMA_INTR_DEFAULT_MASK_LOONGSON, ioaddr + DMA_INTR_ENA);
>> +}
>> +
>> +static int dwlgmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
> The same note as above.
>
>> +				 struct stmmac_extra_stats *x, u32 chan, u32 dir)
>> +{
>> +	struct stmmac_rxq_stats *rxq_stats = &priv->xstats.rxq_stats[chan];
>> +	struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[chan];
>> +	int ret = 0;
>> +	/* read the status register (CSR5) */
>> +	u32 nor_intr_status;
>> +	u32 abnor_intr_status;
>> +	u32 fb_intr_status;
> Reverse xmas tree please.
>
>> +	u32 intr_status = readl(ioaddr + DMA_CHAN_STATUS(chan));
> Please move the initialization into a separate statement.
OK,
>
>> +
>> +#ifdef DWMAC_DMA_DEBUG
>> +	/* Enable it to monitor DMA rx/tx status in case of critical problems */
>> +	pr_debug("%s: [CSR5: 0x%08x]\n", __func__, intr_status);
>> +	show_tx_process_state(intr_status);
>> +	show_rx_process_state(intr_status);
>> +#endif
> This will cause a build-error if DWMAC_DMA_DEBUG is defined. Just drop
> it.
> OK,
>> +
>> +	if (dir == DMA_DIR_RX)
>> +		intr_status &= DMA_STATUS_MSK_RX_LOONGSON;
>> +	else if (dir == DMA_DIR_TX)
>> +		intr_status &= DMA_STATUS_MSK_TX_LOONGSON;
>> +
>> +	nor_intr_status = intr_status & (DMA_STATUS_NIS_TX_LOONGSON |
>> +		DMA_STATUS_NIS_RX_LOONGSON);
>> +	abnor_intr_status = intr_status & (DMA_STATUS_AIS_TX_LOONGSON |
>> +		DMA_STATUS_AIS_RX_LOONGSON);
>> +	fb_intr_status = intr_status & (DMA_STATUS_FBI_TX_LOONGSON |
>> +		DMA_STATUS_FBI_RX_LOONGSON);
>> +
>> +	/* ABNORMAL interrupts */
>> +	if (unlikely(abnor_intr_status)) {
>> +		if (unlikely(intr_status & DMA_STATUS_UNF)) {
>> +			ret = tx_hard_error_bump_tc;
>> +			x->tx_undeflow_irq++;
>> +		}
>> +		if (unlikely(intr_status & DMA_STATUS_TJT))
>> +			x->tx_jabber_irq++;
>> +
>> +		if (unlikely(intr_status & DMA_STATUS_OVF))
>> +			x->rx_overflow_irq++;
>> +
>> +		if (unlikely(intr_status & DMA_STATUS_RU))
>> +			x->rx_buf_unav_irq++;
>> +		if (unlikely(intr_status & DMA_STATUS_RPS))
>> +			x->rx_process_stopped_irq++;
>> +		if (unlikely(intr_status & DMA_STATUS_RWT))
>> +			x->rx_watchdog_irq++;
>> +		if (unlikely(intr_status & DMA_STATUS_ETI))
>> +			x->tx_early_irq++;
>> +		if (unlikely(intr_status & DMA_STATUS_TPS)) {
>> +			x->tx_process_stopped_irq++;
>> +			ret = tx_hard_error;
>> +		}
>> +		if (unlikely(intr_status & fb_intr_status)) {
>> +			x->fatal_bus_error_irq++;
>> +			ret = tx_hard_error;
>> +		}
>> +	}
>> +	/* TX/RX NORMAL interrupts */
>> +	if (likely(nor_intr_status)) {
>> +		if (likely(intr_status & DMA_STATUS_RI)) {
>> +			u32 value = readl(ioaddr + DMA_INTR_ENA);
>> +			/* to schedule NAPI on real RIE event. */
>> +			if (likely(value & DMA_INTR_ENA_RIE)) {
>> +				u64_stats_update_begin(&rxq_stats->syncp);
>> +				rxq_stats->rx_normal_irq_n++;
>> +				u64_stats_update_end(&rxq_stats->syncp);
>> +				ret |= handle_rx;
>> +			}
>> +		}
>> +		if (likely(intr_status & DMA_STATUS_TI)) {
>> +			u64_stats_update_begin(&txq_stats->syncp);
>> +			txq_stats->tx_normal_irq_n++;
>> +			u64_stats_update_end(&txq_stats->syncp);
>> +			ret |= handle_tx;
>> +		}
>> +		if (unlikely(intr_status & DMA_STATUS_ERI))
>> +			x->rx_early_irq++;
>> +	}
>> +	/* Optional hardware blocks, interrupts should be disabled */
>> +	if (unlikely(intr_status &
>> +		     (DMA_STATUS_GPI | DMA_STATUS_GMI | DMA_STATUS_GLI)))
>> +		pr_warn("%s: unexpected status %08x\n", __func__, intr_status);
>> +
>> +	/* Clear the interrupt by writing a logic 1 to the CSR5[15-0] */
>> +	writel((intr_status & 0x7ffff), ioaddr + DMA_CHAN_STATUS(chan));
>> +
>> +	return ret;
>> +}
>>   
>>   struct stmmac_pci_info {
>>   	int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat);
>> @@ -121,6 +308,48 @@ static struct stmmac_pci_info loongson_gmac_pci_info = {
>>   	.config = loongson_gmac_config,
>>   };
>>   
>> +static struct mac_device_info *loongson_setup(void *apriv)
> Consider using the GNET-specific prefix, like "loongson_gnet_".
>
>> +{
>> +	struct stmmac_priv *priv = apriv;
>> +	struct mac_device_info *mac;
>> +	struct loongson_data *ld;
>> +
>> +	mac = devm_kzalloc(priv->device, sizeof(*mac), GFP_KERNEL);
>> +	if (!mac)
>> +		return NULL;
> What about devm_kzalloc()-ing the stmmac_dma_ops instance here and
> initializing it as it's done in the probe method? Thus ...
>
>> +
>> +	ld = priv->plat->bsp_priv;
>> +	mac->dma = &ld->dwlgmac_dma_ops;
> ... this can be replaced with:
>
> 	mac->dma = devm_kzalloc(priv->device, sizeof(*mac->dma), GFP_KERNEL);
> 	if (!mac->dma)
> 		return -ENOMEM;
Great, but It seems that we cannot return an int value here.
>
> 	*mac->dma = dwmac1000_dma_ops;
> 	mac->dma->init_chan = loongson_gnet_dma_init_channel;
> 	mac->dma->dma_interrupt = loongson_gnet_dma_interrupt;
>
>> +
>> +	/* Pre-initialize the respective "mac" fields as it's done in
>> +	 * dwmac1000_setup()
>> +	 */
>> +	priv->dev->priv_flags |= IFF_UNICAST_FLT;
>> +	mac->pcsr = priv->ioaddr;
>> +	mac->multicast_filter_bins = priv->plat->multicast_filter_bins;
>> +	mac->unicast_filter_entries = priv->plat->unicast_filter_entries;
>> +	mac->mcast_bits_log2 = 0;
>> +
>> +	if (mac->multicast_filter_bins)
>> +		mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins);
>> +
>> +	mac->link.duplex = GMAC_CONTROL_DM;
>> +	mac->link.speed10 = GMAC_CONTROL_PS;
>> +	mac->link.speed100 = GMAC_CONTROL_PS | GMAC_CONTROL_FES;
>> +	mac->link.speed1000 = 0;
>> +	mac->link.speed_mask = GMAC_CONTROL_PS | GMAC_CONTROL_FES;
>> +	mac->mii.addr = GMAC_MII_ADDR;
>> +	mac->mii.data = GMAC_MII_DATA;
>> +	mac->mii.addr_shift = 11;
>> +	mac->mii.addr_mask = 0x0000F800;
>> +	mac->mii.reg_shift = 6;
>> +	mac->mii.reg_mask = 0x000007C0;
>> +	mac->mii.clk_csr_shift = 2;
>> +	mac->mii.clk_csr_mask = GENMASK(5, 2);
>> +
>> +	return mac;
>> +}
>> +
>>   static int loongson_dwmac_probe(struct pci_dev *pdev,
>>   				const struct pci_device_id *id)
>>   {
>> @@ -129,6 +358,7 @@ static int loongson_dwmac_probe(struct pci_dev *pdev,
>>   	struct stmmac_pci_info *info;
>>   	struct stmmac_resources res;
>>   	struct device_node *np;
>> +	struct loongson_data *ld;
> reverse xmas tree order please.
>
>>   
>>   	plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL);
>>   	if (!plat)
>> @@ -145,6 +375,10 @@ static int loongson_dwmac_probe(struct pci_dev *pdev,
>>   	if (!plat->dma_cfg)
>>   		return -ENOMEM;
>>   
>> +	ld = devm_kzalloc(&pdev->dev, sizeof(*ld), GFP_KERNEL);
>> +	if (!ld)
>> +		return -ENOMEM;
>> +
>>   	np = dev_of_node(&pdev->dev);
>>   	plat->mdio_node = of_get_child_by_name(np, "mdio");
>>   	if (plat->mdio_node) {
>> @@ -197,6 +431,20 @@ static int loongson_dwmac_probe(struct pci_dev *pdev,
>>   	if (ret)
>>   		goto err_disable_device;
>>   
>> +	ld->dev = &pdev->dev;
>> +	ld->lgmac_version = readl(res.addr + GMAC_VERSION) & 0xff;
> AFAICS the lgmac_version is unused in out of the probe() method
> context. What about locally defining it?
OK,
>
>> +
>> +	/* Activate loongson custom ip */
>> +	if (ld->lgmac_version < DWMAC_CORE_3_50) {
> Please define a new macro for the GNET MAC.
OK.
>
>> +		ld->dwlgmac_dma_ops = dwmac1000_dma_ops;
>> +		ld->dwlgmac_dma_ops.init_chan = dwlgmac_dma_init_channel;
>> +		ld->dwlgmac_dma_ops.dma_interrupt = dwlgmac_dma_interrupt;
> See my comment in the loongson_setup() method.

This will introduce a compilation warning:

warning: returning 'int' from a function with return type 'struct 
mac_device_info *' makes pointer from integer without a cast 
[-Wint-conversion]
   418 |                 return -ENOMEM;


Thanks,

Yanteng

>
> -Serge(y)
>
>> +
>> +		plat->setup = loongson_setup;
>> +	}
>> +
>> +	plat->bsp_priv = ld;
>> +
>>   	ret = stmmac_dvr_probe(&pdev->dev, plat, &res);
>>   	if (ret)
>>   		goto err_disable_device;
>> -- 
>> 2.31.4
>>


^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 05/11] net: stmmac: dwmac-loongson: Add Loongson-specific register definitions
  2024-02-22 13:39     ` Yanteng Si
@ 2024-02-22 13:59       ` Serge Semin
  2024-02-23  8:16         ` Yanteng Si
  0 siblings, 1 reply; 97+ messages in thread
From: Serge Semin @ 2024-02-22 13:59 UTC (permalink / raw)
  To: Yanteng Si
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

On Thu, Feb 22, 2024 at 09:39:49PM +0800, Yanteng Si wrote:
> 
> 在 2024/2/6 02:17, Serge Semin 写道:
> > On Tue, Jan 30, 2024 at 04:48:17PM +0800, Yanteng Si wrote:
> > > There are two types of Loongson DWGMAC. The first type shares the same
> > > register definitions and has similar logic as dwmac1000. The second type
> > > uses several different register definitions, we think it is necessary to
> > > distinguish rx and tx, so we split these bits into two.
> > > 
> > > Simply put, we split some single bit fields into double bits fileds:
> > > 
> > >       Name              Tx          Rx
> > > 
> > > DMA_INTR_ENA_NIE = 0x00040000 | 0x00020000;
> > > DMA_INTR_ENA_AIE = 0x00010000 | 0x00008000;
> > > DMA_STATUS_NIS   = 0x00040000 | 0x00020000;
> > > DMA_STATUS_AIS   = 0x00010000 | 0x00008000;
> > > DMA_STATUS_FBI   = 0x00002000 | 0x00001000;
> > > 
> > > Therefore, when using, TX and RX must be set at the same time.
> > > 
> > > How to use them:
> > > 1. Create the Loongson GNET-specific
> > > stmmac_dma_ops.dma_interrupt()
> > > stmmac_dma_ops.init_chan()
> > > methods in the dwmac-loongson.c driver. Adding all the
> > > Loongson-specific macros
> > > 
> > > 2. Create a Loongson GNET-specific platform setup method with the next
> > > semantics:
> > >     + allocate stmmac_dma_ops instance and initialize it with
> > >       dwmac1000_dma_ops.
> > >     + override the stmmac_dma_ops.{dma_interrupt, init_chan} with
> > >       the pointers to the methods defined in 2.
> > >     + allocate mac_device_info instance and initialize the
> > >       mac_device_info.dma field with a pointer to the new
> > >       stmmac_dma_ops instance.
> > >     + initialize mac_device_info in a way it's done in
> > >       dwmac1000_setup().
> > > 
> > > 3. Initialize plat_stmmacenet_data.setup() with the pointer to the
> > > method created in 2.
> > > 
> > > Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
> > > Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
> > > Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
> > > ---
> > >   .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 248 ++++++++++++++++++
> > >   1 file changed, 248 insertions(+)
> > > 
> > > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > index e7ce027cc14e..3b3578318cc1 100644
> > > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > @@ -8,6 +8,193 @@
> > >   #include <linux/device.h>
> > >   #include <linux/of_irq.h>
> > >   #include "stmmac.h"
> > > +#include "dwmac_dma.h"
> > > +#include "dwmac1000.h"
> > > +
> > > +#define DMA_INTR_ENA_NIE_TX_LOONGSON 0x00040000	/* Normal Loongson Tx Summary */
> > > +#define DMA_INTR_ENA_NIE_RX_LOONGSON 0x00020000	/* Normal Loongson Rx Summary */
> > > +#define DMA_INTR_NORMAL_LOONGSON	(DMA_INTR_ENA_NIE_TX_LOONGSON | \
> > > +			 DMA_INTR_ENA_NIE_RX_LOONGSON | DMA_INTR_ENA_RIE | \
> > > +			 DMA_INTR_ENA_TIE)
> > > +
> > > +#define DMA_INTR_ENA_AIE_TX_LOONGSON 0x00010000	/* Abnormal Loongson Tx Summary */
> > > +#define DMA_INTR_ENA_AIE_RX_LOONGSON 0x00008000	/* Abnormal Loongson Rx Summary */
> > > +
> > > +#define DMA_INTR_ABNORMAL_LOONGSON	(DMA_INTR_ENA_AIE_TX_LOONGSON | \
> > > +				DMA_INTR_ENA_AIE_RX_LOONGSON | DMA_INTR_ENA_FBE | \
> > > +				DMA_INTR_ENA_UNE)
> > > +
> > > +#define DMA_INTR_DEFAULT_MASK_LOONGSON	(DMA_INTR_NORMAL_LOONGSON | DMA_INTR_ABNORMAL_LOONGSON)
> > > +
> > > +#define DMA_STATUS_NIS_TX_LOONGSON	0x00040000	/* Normal Loongson Tx Interrupt Summary */
> > > +#define DMA_STATUS_NIS_RX_LOONGSON	0x00020000	/* Normal Loongson Rx Interrupt Summary */
> > > +
> > > +#define DMA_STATUS_AIS_TX_LOONGSON	0x00010000	/* Abnormal Loongson Tx Interrupt Summary */
> > > +#define DMA_STATUS_AIS_RX_LOONGSON	0x00008000	/* Abnormal Loongson Rx Interrupt Summary */
> > > +
> > > +#define DMA_STATUS_FBI_TX_LOONGSON	0x00002000	/* Fatal Loongson Tx Bus Error Interrupt */
> > > +#define DMA_STATUS_FBI_RX_LOONGSON	0x00001000	/* Fatal Loongson Rx Bus Error Interrupt */
> > > +
> > > +#define DMA_STATUS_MSK_COMMON_LOONGSON		(DMA_STATUS_NIS_TX_LOONGSON | \
> > > +					 DMA_STATUS_NIS_RX_LOONGSON | DMA_STATUS_AIS_TX_LOONGSON | \
> > > +					 DMA_STATUS_AIS_RX_LOONGSON | DMA_STATUS_FBI_TX_LOONGSON | \
> > > +					 DMA_STATUS_FBI_RX_LOONGSON)
> > Max 80 chars per line please.
> OK,
> > 
> > > +
> > > +#define DMA_STATUS_MSK_RX_LOONGSON		(DMA_STATUS_ERI | \
> > > +					 DMA_STATUS_RWT | \
> > > +					 DMA_STATUS_RPS | \
> > > +					 DMA_STATUS_RU | \
> > > +					 DMA_STATUS_RI | \
> > > +					 DMA_STATUS_OVF | \
> > > +					 DMA_STATUS_MSK_COMMON_LOONGSON)
> > > +
> > > +#define DMA_STATUS_MSK_TX_LOONGSON		(DMA_STATUS_ETI | \
> > > +					 DMA_STATUS_UNF | \
> > > +					 DMA_STATUS_TJT | \
> > > +					 DMA_STATUS_TU | \
> > > +					 DMA_STATUS_TPS | \
> > > +					 DMA_STATUS_TI | \
> > > +					 DMA_STATUS_MSK_COMMON_LOONGSON)
> > > +
> > > +struct loongson_data {
> > > +	struct device *dev;
> > > +	u32 lgmac_version;
> > > +	struct stmmac_dma_ops dwlgmac_dma_ops;
> > Just figured out we can do without this field being added to the
> > private data. See my note in the loongson_setup() method.
> > 
> > > +};
> > > +
> > > +static void dwlgmac_dma_init_channel(struct stmmac_priv *priv,
> > The "dwlgmac_" prefix is confusing. There is the DW XLGMAC IP-core for
> > which the "dwxlgmac_" is more appropriate and "x" is easy to miss
> > should your version of the prefix is met. Consider changing it to
> > something like "loongson_gnet_".
> OK,
> > 
> > > +				     void __iomem *ioaddr,
> > > +				     struct stmmac_dma_cfg *dma_cfg, u32 chan)
> > > +{
> > > +	u32 value;
> > > +	int txpbl = dma_cfg->txpbl ?: dma_cfg->pbl;
> > > +	int rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl;
> > > +
> > > +	/* common channel control register config */
> > > +	value = readl(ioaddr + DMA_CHAN_BUS_MODE(chan));
> > > +
> > > +	/* Set the DMA PBL (Programmable Burst Length) mode.
> > > +	 *
> > > +	 * Note: before stmmac core 3.50 this mode bit was 4xPBL, and
> > > +	 * post 3.5 mode bit acts as 8*PBL.
> > > +	 */
> > > +	if (dma_cfg->pblx8)
> > > +		value |= DMA_BUS_MODE_MAXPBL;
> > > +	value |= DMA_BUS_MODE_USP;
> > > +	value &= ~(DMA_BUS_MODE_PBL_MASK | DMA_BUS_MODE_RPBL_MASK);
> > > +	value |= (txpbl << DMA_BUS_MODE_PBL_SHIFT);
> > > +	value |= (rxpbl << DMA_BUS_MODE_RPBL_SHIFT);
> > > +
> > > +	/* Set the Fixed burst mode */
> > > +	if (dma_cfg->fixed_burst)
> > > +		value |= DMA_BUS_MODE_FB;
> > > +
> > > +	/* Mixed Burst has no effect when fb is set */
> > > +	if (dma_cfg->mixed_burst)
> > > +		value |= DMA_BUS_MODE_MB;
> > > +
> > > +	value |= DMA_BUS_MODE_ATDS;
> > > +
> > > +	if (dma_cfg->aal)
> > > +		value |= DMA_BUS_MODE_AAL;
> > > +
> > > +	writel(value, ioaddr + DMA_BUS_MODE);
> > > +
> > > +	/* Mask interrupts by writing to CSR7 */
> > > +	writel(DMA_INTR_DEFAULT_MASK_LOONGSON, ioaddr + DMA_INTR_ENA);
> > > +}
> > > +
> > > +static int dwlgmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
> > The same note as above.
> > 
> > > +				 struct stmmac_extra_stats *x, u32 chan, u32 dir)
> > > +{
> > > +	struct stmmac_rxq_stats *rxq_stats = &priv->xstats.rxq_stats[chan];
> > > +	struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[chan];
> > > +	int ret = 0;
> > > +	/* read the status register (CSR5) */
> > > +	u32 nor_intr_status;
> > > +	u32 abnor_intr_status;
> > > +	u32 fb_intr_status;
> > Reverse xmas tree please.
> > 
> > > +	u32 intr_status = readl(ioaddr + DMA_CHAN_STATUS(chan));
> > Please move the initialization into a separate statement.
> OK,
> > 
> > > +
> > > +#ifdef DWMAC_DMA_DEBUG
> > > +	/* Enable it to monitor DMA rx/tx status in case of critical problems */
> > > +	pr_debug("%s: [CSR5: 0x%08x]\n", __func__, intr_status);
> > > +	show_tx_process_state(intr_status);
> > > +	show_rx_process_state(intr_status);
> > > +#endif
> > This will cause a build-error if DWMAC_DMA_DEBUG is defined. Just drop
> > it.
> > OK,
> > > +
> > > +	if (dir == DMA_DIR_RX)
> > > +		intr_status &= DMA_STATUS_MSK_RX_LOONGSON;
> > > +	else if (dir == DMA_DIR_TX)
> > > +		intr_status &= DMA_STATUS_MSK_TX_LOONGSON;
> > > +
> > > +	nor_intr_status = intr_status & (DMA_STATUS_NIS_TX_LOONGSON |
> > > +		DMA_STATUS_NIS_RX_LOONGSON);
> > > +	abnor_intr_status = intr_status & (DMA_STATUS_AIS_TX_LOONGSON |
> > > +		DMA_STATUS_AIS_RX_LOONGSON);
> > > +	fb_intr_status = intr_status & (DMA_STATUS_FBI_TX_LOONGSON |
> > > +		DMA_STATUS_FBI_RX_LOONGSON);
> > > +
> > > +	/* ABNORMAL interrupts */
> > > +	if (unlikely(abnor_intr_status)) {
> > > +		if (unlikely(intr_status & DMA_STATUS_UNF)) {
> > > +			ret = tx_hard_error_bump_tc;
> > > +			x->tx_undeflow_irq++;
> > > +		}
> > > +		if (unlikely(intr_status & DMA_STATUS_TJT))
> > > +			x->tx_jabber_irq++;
> > > +
> > > +		if (unlikely(intr_status & DMA_STATUS_OVF))
> > > +			x->rx_overflow_irq++;
> > > +
> > > +		if (unlikely(intr_status & DMA_STATUS_RU))
> > > +			x->rx_buf_unav_irq++;
> > > +		if (unlikely(intr_status & DMA_STATUS_RPS))
> > > +			x->rx_process_stopped_irq++;
> > > +		if (unlikely(intr_status & DMA_STATUS_RWT))
> > > +			x->rx_watchdog_irq++;
> > > +		if (unlikely(intr_status & DMA_STATUS_ETI))
> > > +			x->tx_early_irq++;
> > > +		if (unlikely(intr_status & DMA_STATUS_TPS)) {
> > > +			x->tx_process_stopped_irq++;
> > > +			ret = tx_hard_error;
> > > +		}
> > > +		if (unlikely(intr_status & fb_intr_status)) {
> > > +			x->fatal_bus_error_irq++;
> > > +			ret = tx_hard_error;
> > > +		}
> > > +	}
> > > +	/* TX/RX NORMAL interrupts */
> > > +	if (likely(nor_intr_status)) {
> > > +		if (likely(intr_status & DMA_STATUS_RI)) {
> > > +			u32 value = readl(ioaddr + DMA_INTR_ENA);
> > > +			/* to schedule NAPI on real RIE event. */
> > > +			if (likely(value & DMA_INTR_ENA_RIE)) {
> > > +				u64_stats_update_begin(&rxq_stats->syncp);
> > > +				rxq_stats->rx_normal_irq_n++;
> > > +				u64_stats_update_end(&rxq_stats->syncp);
> > > +				ret |= handle_rx;
> > > +			}
> > > +		}
> > > +		if (likely(intr_status & DMA_STATUS_TI)) {
> > > +			u64_stats_update_begin(&txq_stats->syncp);
> > > +			txq_stats->tx_normal_irq_n++;
> > > +			u64_stats_update_end(&txq_stats->syncp);
> > > +			ret |= handle_tx;
> > > +		}
> > > +		if (unlikely(intr_status & DMA_STATUS_ERI))
> > > +			x->rx_early_irq++;
> > > +	}
> > > +	/* Optional hardware blocks, interrupts should be disabled */
> > > +	if (unlikely(intr_status &
> > > +		     (DMA_STATUS_GPI | DMA_STATUS_GMI | DMA_STATUS_GLI)))
> > > +		pr_warn("%s: unexpected status %08x\n", __func__, intr_status);
> > > +
> > > +	/* Clear the interrupt by writing a logic 1 to the CSR5[15-0] */
> > > +	writel((intr_status & 0x7ffff), ioaddr + DMA_CHAN_STATUS(chan));
> > > +
> > > +	return ret;
> > > +}
> > >   struct stmmac_pci_info {
> > >   	int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat);
> > > @@ -121,6 +308,48 @@ static struct stmmac_pci_info loongson_gmac_pci_info = {
> > >   	.config = loongson_gmac_config,
> > >   };
> > > +static struct mac_device_info *loongson_setup(void *apriv)
> > Consider using the GNET-specific prefix, like "loongson_gnet_".
> > 
> > > +{
> > > +	struct stmmac_priv *priv = apriv;
> > > +	struct mac_device_info *mac;
> > > +	struct loongson_data *ld;
> > > +
> > > +	mac = devm_kzalloc(priv->device, sizeof(*mac), GFP_KERNEL);
> > > +	if (!mac)
> > > +		return NULL;
> > What about devm_kzalloc()-ing the stmmac_dma_ops instance here and
> > initializing it as it's done in the probe method? Thus ...
> > 
> > > +
> > > +	ld = priv->plat->bsp_priv;
> > > +	mac->dma = &ld->dwlgmac_dma_ops;
> > ... this can be replaced with:
> > 
> > 	mac->dma = devm_kzalloc(priv->device, sizeof(*mac->dma), GFP_KERNEL);
> > 	if (!mac->dma)
> > 		return -ENOMEM;

> Great, but It seems that we cannot return an int value here.

Just
		return NULL;
then.

> > 
> > 	*mac->dma = dwmac1000_dma_ops;
> > 	mac->dma->init_chan = loongson_gnet_dma_init_channel;
> > 	mac->dma->dma_interrupt = loongson_gnet_dma_interrupt;
> > 
> > > +
> > > +	/* Pre-initialize the respective "mac" fields as it's done in
> > > +	 * dwmac1000_setup()
> > > +	 */
> > > +	priv->dev->priv_flags |= IFF_UNICAST_FLT;
> > > +	mac->pcsr = priv->ioaddr;
> > > +	mac->multicast_filter_bins = priv->plat->multicast_filter_bins;
> > > +	mac->unicast_filter_entries = priv->plat->unicast_filter_entries;
> > > +	mac->mcast_bits_log2 = 0;
> > > +
> > > +	if (mac->multicast_filter_bins)
> > > +		mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins);
> > > +
> > > +	mac->link.duplex = GMAC_CONTROL_DM;
> > > +	mac->link.speed10 = GMAC_CONTROL_PS;
> > > +	mac->link.speed100 = GMAC_CONTROL_PS | GMAC_CONTROL_FES;
> > > +	mac->link.speed1000 = 0;
> > > +	mac->link.speed_mask = GMAC_CONTROL_PS | GMAC_CONTROL_FES;
> > > +	mac->mii.addr = GMAC_MII_ADDR;
> > > +	mac->mii.data = GMAC_MII_DATA;
> > > +	mac->mii.addr_shift = 11;
> > > +	mac->mii.addr_mask = 0x0000F800;
> > > +	mac->mii.reg_shift = 6;
> > > +	mac->mii.reg_mask = 0x000007C0;
> > > +	mac->mii.clk_csr_shift = 2;
> > > +	mac->mii.clk_csr_mask = GENMASK(5, 2);
> > > +
> > > +	return mac;
> > > +}
> > > +
> > >   static int loongson_dwmac_probe(struct pci_dev *pdev,
> > >   				const struct pci_device_id *id)
> > >   {
> > > @@ -129,6 +358,7 @@ static int loongson_dwmac_probe(struct pci_dev *pdev,
> > >   	struct stmmac_pci_info *info;
> > >   	struct stmmac_resources res;
> > >   	struct device_node *np;
> > > +	struct loongson_data *ld;
> > reverse xmas tree order please.
> > 
> > >   	plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL);
> > >   	if (!plat)
> > > @@ -145,6 +375,10 @@ static int loongson_dwmac_probe(struct pci_dev *pdev,
> > >   	if (!plat->dma_cfg)
> > >   		return -ENOMEM;
> > > +	ld = devm_kzalloc(&pdev->dev, sizeof(*ld), GFP_KERNEL);
> > > +	if (!ld)
> > > +		return -ENOMEM;
> > > +
> > >   	np = dev_of_node(&pdev->dev);
> > >   	plat->mdio_node = of_get_child_by_name(np, "mdio");
> > >   	if (plat->mdio_node) {
> > > @@ -197,6 +431,20 @@ static int loongson_dwmac_probe(struct pci_dev *pdev,
> > >   	if (ret)
> > >   		goto err_disable_device;
> > > +	ld->dev = &pdev->dev;
> > > +	ld->lgmac_version = readl(res.addr + GMAC_VERSION) & 0xff;
> > AFAICS the lgmac_version is unused in out of the probe() method
> > context. What about locally defining it?
> OK,
> > 
> > > +
> > > +	/* Activate loongson custom ip */
> > > +	if (ld->lgmac_version < DWMAC_CORE_3_50) {
> > Please define a new macro for the GNET MAC.
> OK.
> > 
> > > +		ld->dwlgmac_dma_ops = dwmac1000_dma_ops;
> > > +		ld->dwlgmac_dma_ops.init_chan = dwlgmac_dma_init_channel;
> > > +		ld->dwlgmac_dma_ops.dma_interrupt = dwlgmac_dma_interrupt;
> > See my comment in the loongson_setup() method.
> 
> This will introduce a compilation warning:
> 
> warning: returning 'int' from a function with return type 'struct
> mac_device_info *' makes pointer from integer without a cast
> [-Wint-conversion]
>   418 |                 return -ENOMEM;

stmmac_hwif_init() expects priv->plat->setup(priv) returning NULL
if something wrong. As I suggested above just return NULL then if
mac_device_info couldn't be allocated.

-Serge(y)

> 
> 
> Thanks,
> 
> Yanteng
> 
> > 
> > -Serge(y)
> > 
> > > +
> > > +		plat->setup = loongson_setup;
> > > +	}
> > > +
> > > +	plat->bsp_priv = ld;
> > > +
> > >   	ret = stmmac_dvr_probe(&pdev->dev, plat, &res);
> > >   	if (ret)
> > >   		goto err_disable_device;
> > > -- 
> > > 2.31.4
> > > 
> 

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 05/11] net: stmmac: dwmac-loongson: Add Loongson-specific register definitions
  2024-02-22 13:59       ` Serge Semin
@ 2024-02-23  8:16         ` Yanteng Si
  2024-02-23 18:50           ` Serge Semin
  0 siblings, 1 reply; 97+ messages in thread
From: Yanteng Si @ 2024-02-23  8:16 UTC (permalink / raw)
  To: Serge Semin
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

Hi Serge,

在 2024/2/22 21:59, Serge Semin 写道:
> On Thu, Feb 22, 2024 at 09:39:49PM +0800, Yanteng Si wrote:
>> 在 2024/2/6 02:17, Serge Semin 写道:
>>> On Tue, Jan 30, 2024 at 04:48:17PM +0800, Yanteng Si wrote:
>>>> There are two types of Loongson DWGMAC. The first type shares the same
>>>> register definitions and has similar logic as dwmac1000. The second type
>>>> uses several different register definitions, we think it is necessary to
>>>> distinguish rx and tx, so we split these bits into two.
>>>>
>>>> Simply put, we split some single bit fields into double bits fileds:
>>>>
>>>>        Name              Tx          Rx
>>>>
>>>> DMA_INTR_ENA_NIE = 0x00040000 | 0x00020000;
>>>> DMA_INTR_ENA_AIE = 0x00010000 | 0x00008000;
>>>> DMA_STATUS_NIS   = 0x00040000 | 0x00020000;
>>>> DMA_STATUS_AIS   = 0x00010000 | 0x00008000;
>>>> DMA_STATUS_FBI   = 0x00002000 | 0x00001000;
>>>>
>>>> Therefore, when using, TX and RX must be set at the same time.
>>>>
>>>> How to use them:
>>>> 1. Create the Loongson GNET-specific
>>>> stmmac_dma_ops.dma_interrupt()
>>>> stmmac_dma_ops.init_chan()
>>>> methods in the dwmac-loongson.c driver. Adding all the
>>>> Loongson-specific macros
>>>>
>>>> 2. Create a Loongson GNET-specific platform setup method with the next
>>>> semantics:
>>>>      + allocate stmmac_dma_ops instance and initialize it with
>>>>        dwmac1000_dma_ops.
>>>>      + override the stmmac_dma_ops.{dma_interrupt, init_chan} with
>>>>        the pointers to the methods defined in 2.
>>>>      + allocate mac_device_info instance and initialize the
>>>>        mac_device_info.dma field with a pointer to the new
>>>>        stmmac_dma_ops instance.
>>>>      + initialize mac_device_info in a way it's done in
>>>>        dwmac1000_setup().
>>>>
>>>> 3. Initialize plat_stmmacenet_data.setup() with the pointer to the
>>>> method created in 2.
>>>>
>>>> Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
>>>> Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
>>>> Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
>>>> ---
>>>>    .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 248 ++++++++++++++++++
>>>>    1 file changed, 248 insertions(+)
>>>>
>>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>>> index e7ce027cc14e..3b3578318cc1 100644
>>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>>> @@ -8,6 +8,193 @@
>>>>    #include <linux/device.h>
>>>>    #include <linux/of_irq.h>
>>>>    #include "stmmac.h"
>>>> +#include "dwmac_dma.h"
>>>> +#include "dwmac1000.h"
>>>> +
>>>> +#define DMA_INTR_ENA_NIE_TX_LOONGSON 0x00040000	/* Normal Loongson Tx Summary */
>>>> +#define DMA_INTR_ENA_NIE_RX_LOONGSON 0x00020000	/* Normal Loongson Rx Summary */
>>>> +#define DMA_INTR_NORMAL_LOONGSON	(DMA_INTR_ENA_NIE_TX_LOONGSON | \
>>>> +			 DMA_INTR_ENA_NIE_RX_LOONGSON | DMA_INTR_ENA_RIE | \
>>>> +			 DMA_INTR_ENA_TIE)
>>>> +
>>>> +#define DMA_INTR_ENA_AIE_TX_LOONGSON 0x00010000	/* Abnormal Loongson Tx Summary */
>>>> +#define DMA_INTR_ENA_AIE_RX_LOONGSON 0x00008000	/* Abnormal Loongson Rx Summary */
>>>> +
>>>> +#define DMA_INTR_ABNORMAL_LOONGSON	(DMA_INTR_ENA_AIE_TX_LOONGSON | \
>>>> +				DMA_INTR_ENA_AIE_RX_LOONGSON | DMA_INTR_ENA_FBE | \
>>>> +				DMA_INTR_ENA_UNE)
>>>> +
>>>> +#define DMA_INTR_DEFAULT_MASK_LOONGSON	(DMA_INTR_NORMAL_LOONGSON | DMA_INTR_ABNORMAL_LOONGSON)
>>>> +
>>>> +#define DMA_STATUS_NIS_TX_LOONGSON	0x00040000	/* Normal Loongson Tx Interrupt Summary */
>>>> +#define DMA_STATUS_NIS_RX_LOONGSON	0x00020000	/* Normal Loongson Rx Interrupt Summary */
>>>> +
>>>> +#define DMA_STATUS_AIS_TX_LOONGSON	0x00010000	/* Abnormal Loongson Tx Interrupt Summary */
>>>> +#define DMA_STATUS_AIS_RX_LOONGSON	0x00008000	/* Abnormal Loongson Rx Interrupt Summary */
>>>> +
>>>> +#define DMA_STATUS_FBI_TX_LOONGSON	0x00002000	/* Fatal Loongson Tx Bus Error Interrupt */
>>>> +#define DMA_STATUS_FBI_RX_LOONGSON	0x00001000	/* Fatal Loongson Rx Bus Error Interrupt */
>>>> +
>>>> +#define DMA_STATUS_MSK_COMMON_LOONGSON		(DMA_STATUS_NIS_TX_LOONGSON | \
>>>> +					 DMA_STATUS_NIS_RX_LOONGSON | DMA_STATUS_AIS_TX_LOONGSON | \
>>>> +					 DMA_STATUS_AIS_RX_LOONGSON | DMA_STATUS_FBI_TX_LOONGSON | \
>>>> +					 DMA_STATUS_FBI_RX_LOONGSON)
>>> Max 80 chars per line please.
>> OK,
>>>> +
>>>> +#define DMA_STATUS_MSK_RX_LOONGSON		(DMA_STATUS_ERI | \
>>>> +					 DMA_STATUS_RWT | \
>>>> +					 DMA_STATUS_RPS | \
>>>> +					 DMA_STATUS_RU | \
>>>> +					 DMA_STATUS_RI | \
>>>> +					 DMA_STATUS_OVF | \
>>>> +					 DMA_STATUS_MSK_COMMON_LOONGSON)
>>>> +
>>>> +#define DMA_STATUS_MSK_TX_LOONGSON		(DMA_STATUS_ETI | \
>>>> +					 DMA_STATUS_UNF | \
>>>> +					 DMA_STATUS_TJT | \
>>>> +					 DMA_STATUS_TU | \
>>>> +					 DMA_STATUS_TPS | \
>>>> +					 DMA_STATUS_TI | \
>>>> +					 DMA_STATUS_MSK_COMMON_LOONGSON)
>>>> +
>>>> +struct loongson_data {
>>>> +	struct device *dev;
>>>> +	u32 lgmac_version;
>>>> +	struct stmmac_dma_ops dwlgmac_dma_ops;
>>> Just figured out we can do without this field being added to the
>>> private data. See my note in the loongson_setup() method.
>>>
>>>> +};
>>>> +
>>>> +static void dwlgmac_dma_init_channel(struct stmmac_priv *priv,
>>> The "dwlgmac_" prefix is confusing. There is the DW XLGMAC IP-core for
>>> which the "dwxlgmac_" is more appropriate and "x" is easy to miss
>>> should your version of the prefix is met. Consider changing it to
>>> something like "loongson_gnet_".
>> OK,
>>>> +				     void __iomem *ioaddr,
>>>> +				     struct stmmac_dma_cfg *dma_cfg, u32 chan)
>>>> +{
>>>> +	u32 value;
>>>> +	int txpbl = dma_cfg->txpbl ?: dma_cfg->pbl;
>>>> +	int rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl;
>>>> +
>>>> +	/* common channel control register config */
>>>> +	value = readl(ioaddr + DMA_CHAN_BUS_MODE(chan));
>>>> +
>>>> +	/* Set the DMA PBL (Programmable Burst Length) mode.
>>>> +	 *
>>>> +	 * Note: before stmmac core 3.50 this mode bit was 4xPBL, and
>>>> +	 * post 3.5 mode bit acts as 8*PBL.
>>>> +	 */
>>>> +	if (dma_cfg->pblx8)
>>>> +		value |= DMA_BUS_MODE_MAXPBL;
>>>> +	value |= DMA_BUS_MODE_USP;
>>>> +	value &= ~(DMA_BUS_MODE_PBL_MASK | DMA_BUS_MODE_RPBL_MASK);
>>>> +	value |= (txpbl << DMA_BUS_MODE_PBL_SHIFT);
>>>> +	value |= (rxpbl << DMA_BUS_MODE_RPBL_SHIFT);
>>>> +
>>>> +	/* Set the Fixed burst mode */
>>>> +	if (dma_cfg->fixed_burst)
>>>> +		value |= DMA_BUS_MODE_FB;
>>>> +
>>>> +	/* Mixed Burst has no effect when fb is set */
>>>> +	if (dma_cfg->mixed_burst)
>>>> +		value |= DMA_BUS_MODE_MB;
>>>> +
>>>> +	value |= DMA_BUS_MODE_ATDS;
>>>> +
>>>> +	if (dma_cfg->aal)
>>>> +		value |= DMA_BUS_MODE_AAL;
>>>> +
>>>> +	writel(value, ioaddr + DMA_BUS_MODE);
>>>> +
>>>> +	/* Mask interrupts by writing to CSR7 */
>>>> +	writel(DMA_INTR_DEFAULT_MASK_LOONGSON, ioaddr + DMA_INTR_ENA);
>>>> +}
>>>> +
>>>> +static int dwlgmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
>>> The same note as above.
>>>
>>>> +				 struct stmmac_extra_stats *x, u32 chan, u32 dir)
>>>> +{
>>>> +	struct stmmac_rxq_stats *rxq_stats = &priv->xstats.rxq_stats[chan];
>>>> +	struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[chan];
>>>> +	int ret = 0;
>>>> +	/* read the status register (CSR5) */
>>>> +	u32 nor_intr_status;
>>>> +	u32 abnor_intr_status;
>>>> +	u32 fb_intr_status;
>>> Reverse xmas tree please.
>>>
>>>> +	u32 intr_status = readl(ioaddr + DMA_CHAN_STATUS(chan));
>>> Please move the initialization into a separate statement.
>> OK,
>>>> +
>>>> +#ifdef DWMAC_DMA_DEBUG
>>>> +	/* Enable it to monitor DMA rx/tx status in case of critical problems */
>>>> +	pr_debug("%s: [CSR5: 0x%08x]\n", __func__, intr_status);
>>>> +	show_tx_process_state(intr_status);
>>>> +	show_rx_process_state(intr_status);
>>>> +#endif
>>> This will cause a build-error if DWMAC_DMA_DEBUG is defined. Just drop
>>> it.
>>> OK,
>>>> +
>>>> +	if (dir == DMA_DIR_RX)
>>>> +		intr_status &= DMA_STATUS_MSK_RX_LOONGSON;
>>>> +	else if (dir == DMA_DIR_TX)
>>>> +		intr_status &= DMA_STATUS_MSK_TX_LOONGSON;
>>>> +
>>>> +	nor_intr_status = intr_status & (DMA_STATUS_NIS_TX_LOONGSON |
>>>> +		DMA_STATUS_NIS_RX_LOONGSON);
>>>> +	abnor_intr_status = intr_status & (DMA_STATUS_AIS_TX_LOONGSON |
>>>> +		DMA_STATUS_AIS_RX_LOONGSON);
>>>> +	fb_intr_status = intr_status & (DMA_STATUS_FBI_TX_LOONGSON |
>>>> +		DMA_STATUS_FBI_RX_LOONGSON);
>>>> +
>>>> +	/* ABNORMAL interrupts */
>>>> +	if (unlikely(abnor_intr_status)) {
>>>> +		if (unlikely(intr_status & DMA_STATUS_UNF)) {
>>>> +			ret = tx_hard_error_bump_tc;
>>>> +			x->tx_undeflow_irq++;
>>>> +		}
>>>> +		if (unlikely(intr_status & DMA_STATUS_TJT))
>>>> +			x->tx_jabber_irq++;
>>>> +
>>>> +		if (unlikely(intr_status & DMA_STATUS_OVF))
>>>> +			x->rx_overflow_irq++;
>>>> +
>>>> +		if (unlikely(intr_status & DMA_STATUS_RU))
>>>> +			x->rx_buf_unav_irq++;
>>>> +		if (unlikely(intr_status & DMA_STATUS_RPS))
>>>> +			x->rx_process_stopped_irq++;
>>>> +		if (unlikely(intr_status & DMA_STATUS_RWT))
>>>> +			x->rx_watchdog_irq++;
>>>> +		if (unlikely(intr_status & DMA_STATUS_ETI))
>>>> +			x->tx_early_irq++;
>>>> +		if (unlikely(intr_status & DMA_STATUS_TPS)) {
>>>> +			x->tx_process_stopped_irq++;
>>>> +			ret = tx_hard_error;
>>>> +		}
>>>> +		if (unlikely(intr_status & fb_intr_status)) {
>>>> +			x->fatal_bus_error_irq++;
>>>> +			ret = tx_hard_error;
>>>> +		}
>>>> +	}
>>>> +	/* TX/RX NORMAL interrupts */
>>>> +	if (likely(nor_intr_status)) {
>>>> +		if (likely(intr_status & DMA_STATUS_RI)) {
>>>> +			u32 value = readl(ioaddr + DMA_INTR_ENA);
>>>> +			/* to schedule NAPI on real RIE event. */
>>>> +			if (likely(value & DMA_INTR_ENA_RIE)) {
>>>> +				u64_stats_update_begin(&rxq_stats->syncp);
>>>> +				rxq_stats->rx_normal_irq_n++;
>>>> +				u64_stats_update_end(&rxq_stats->syncp);
>>>> +				ret |= handle_rx;
>>>> +			}
>>>> +		}
>>>> +		if (likely(intr_status & DMA_STATUS_TI)) {
>>>> +			u64_stats_update_begin(&txq_stats->syncp);
>>>> +			txq_stats->tx_normal_irq_n++;
>>>> +			u64_stats_update_end(&txq_stats->syncp);
>>>> +			ret |= handle_tx;
>>>> +		}
>>>> +		if (unlikely(intr_status & DMA_STATUS_ERI))
>>>> +			x->rx_early_irq++;
>>>> +	}
>>>> +	/* Optional hardware blocks, interrupts should be disabled */
>>>> +	if (unlikely(intr_status &
>>>> +		     (DMA_STATUS_GPI | DMA_STATUS_GMI | DMA_STATUS_GLI)))
>>>> +		pr_warn("%s: unexpected status %08x\n", __func__, intr_status);
>>>> +
>>>> +	/* Clear the interrupt by writing a logic 1 to the CSR5[15-0] */
>>>> +	writel((intr_status & 0x7ffff), ioaddr + DMA_CHAN_STATUS(chan));
>>>> +
>>>> +	return ret;
>>>> +}
>>>>    struct stmmac_pci_info {
>>>>    	int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat);
>>>> @@ -121,6 +308,48 @@ static struct stmmac_pci_info loongson_gmac_pci_info = {
>>>>    	.config = loongson_gmac_config,
>>>>    };
>>>> +static struct mac_device_info *loongson_setup(void *apriv)
>>> Consider using the GNET-specific prefix, like "loongson_gnet_".
>>>
>>>> +{
>>>> +	struct stmmac_priv *priv = apriv;
>>>> +	struct mac_device_info *mac;
>>>> +	struct loongson_data *ld;
>>>> +
>>>> +	mac = devm_kzalloc(priv->device, sizeof(*mac), GFP_KERNEL);
>>>> +	if (!mac)
>>>> +		return NULL;
>>> What about devm_kzalloc()-ing the stmmac_dma_ops instance here and
>>> initializing it as it's done in the probe method? Thus ...
>>>
>>>> +
>>>> +	ld = priv->plat->bsp_priv;
>>>> +	mac->dma = &ld->dwlgmac_dma_ops;
>>> ... this can be replaced with:
>>>
>>> 	mac->dma = devm_kzalloc(priv->device, sizeof(*mac->dma), GFP_KERNEL);
>>> 	if (!mac->dma)
>>> 		return -ENOMEM;
>> Great, but It seems that we cannot return an int value here.
> Just
> 		return NULL;
OK,
> then.
>
>>> 	*mac->dma = dwmac1000_dma_ops;
>>> 	mac->dma->init_chan = loongson_gnet_dma_init_channel;
>>> 	mac->dma->dma_interrupt = loongson_gnet_dma_interrupt;
It seems that we still cannot do this because:
structmac_device_info{
...
conststructstmmac_mmc_ops*mmc;
...
}
some errors output:
error: assignment of read-only location '*mac->dma'
error: assignment of member 'init_chan' in read-only object
...
Thanks,
Yanteng
>>>
>>>> +
>>>> +	/* Pre-initialize the respective "mac" fields as it's done in
>>>> +	 * dwmac1000_setup()
>>>> +	 */
>>>> +	priv->dev->priv_flags |= IFF_UNICAST_FLT;
>>>> +	mac->pcsr = priv->ioaddr;
>>>> +	mac->multicast_filter_bins = priv->plat->multicast_filter_bins;
>>>> +	mac->unicast_filter_entries = priv->plat->unicast_filter_entries;
>>>> +	mac->mcast_bits_log2 = 0;
>>>> +
>>>> +	if (mac->multicast_filter_bins)
>>>> +		mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins);
>>>> +
>>>> +	mac->link.duplex = GMAC_CONTROL_DM;
>>>> +	mac->link.speed10 = GMAC_CONTROL_PS;
>>>> +	mac->link.speed100 = GMAC_CONTROL_PS | GMAC_CONTROL_FES;
>>>> +	mac->link.speed1000 = 0;
>>>> +	mac->link.speed_mask = GMAC_CONTROL_PS | GMAC_CONTROL_FES;
>>>> +	mac->mii.addr = GMAC_MII_ADDR;
>>>> +	mac->mii.data = GMAC_MII_DATA;
>>>> +	mac->mii.addr_shift = 11;
>>>> +	mac->mii.addr_mask = 0x0000F800;
>>>> +	mac->mii.reg_shift = 6;
>>>> +	mac->mii.reg_mask = 0x000007C0;
>>>> +	mac->mii.clk_csr_shift = 2;
>>>> +	mac->mii.clk_csr_mask = GENMASK(5, 2);
>>>> +
>>>> +	return mac;
>>>> +}
>>>> +
>>>>    static int loongson_dwmac_probe(struct pci_dev *pdev,
>>>>    				const struct pci_device_id *id)
>>>>    {
>>>> @@ -129,6 +358,7 @@ static int loongson_dwmac_probe(struct pci_dev *pdev,
>>>>    	struct stmmac_pci_info *info;
>>>>    	struct stmmac_resources res;
>>>>    	struct device_node *np;
>>>> +	struct loongson_data *ld;
>>> reverse xmas tree order please.
>>>
>>>>    	plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL);
>>>>    	if (!plat)
>>>> @@ -145,6 +375,10 @@ static int loongson_dwmac_probe(struct pci_dev *pdev,
>>>>    	if (!plat->dma_cfg)
>>>>    		return -ENOMEM;
>>>> +	ld = devm_kzalloc(&pdev->dev, sizeof(*ld), GFP_KERNEL);
>>>> +	if (!ld)
>>>> +		return -ENOMEM;
>>>> +
>>>>    	np = dev_of_node(&pdev->dev);
>>>>    	plat->mdio_node = of_get_child_by_name(np, "mdio");
>>>>    	if (plat->mdio_node) {
>>>> @@ -197,6 +431,20 @@ static int loongson_dwmac_probe(struct pci_dev *pdev,
>>>>    	if (ret)
>>>>    		goto err_disable_device;
>>>> +	ld->dev = &pdev->dev;
>>>> +	ld->lgmac_version = readl(res.addr + GMAC_VERSION) & 0xff;
>>> AFAICS the lgmac_version is unused in out of the probe() method
>>> context. What about locally defining it?
>> OK,
>>>> +
>>>> +	/* Activate loongson custom ip */
>>>> +	if (ld->lgmac_version < DWMAC_CORE_3_50) {
>>> Please define a new macro for the GNET MAC.
>> OK.
>>>> +		ld->dwlgmac_dma_ops = dwmac1000_dma_ops;
>>>> +		ld->dwlgmac_dma_ops.init_chan = dwlgmac_dma_init_channel;
>>>> +		ld->dwlgmac_dma_ops.dma_interrupt = dwlgmac_dma_interrupt;
>>> See my comment in the loongson_setup() method.
>> This will introduce a compilation warning:
>>
>> warning: returning 'int' from a function with return type 'struct
>> mac_device_info *' makes pointer from integer without a cast
>> [-Wint-conversion]
>>    418 |                 return -ENOMEM;
> stmmac_hwif_init() expects priv->plat->setup(priv) returning NULL
> if something wrong. As I suggested above just return NULL then if
> mac_device_info couldn't be allocated.
>
> -Serge(y)
>
>>
>> Thanks,
>>
>> Yanteng
>>
>>> -Serge(y)
>>>
>>>> +
>>>> +		plat->setup = loongson_setup;
>>>> +	}
>>>> +
>>>> +	plat->bsp_priv = ld;
>>>> +
>>>>    	ret = stmmac_dvr_probe(&pdev->dev, plat, &res);
>>>>    	if (ret)
>>>>    		goto err_disable_device;
>>>> -- 
>>>> 2.31.4
>>>>


^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 05/11] net: stmmac: dwmac-loongson: Add Loongson-specific register definitions
  2024-02-23  8:16         ` Yanteng Si
@ 2024-02-23 18:50           ` Serge Semin
  2024-03-07 13:15             ` Yanteng Si
  0 siblings, 1 reply; 97+ messages in thread
From: Serge Semin @ 2024-02-23 18:50 UTC (permalink / raw)
  To: Yanteng Si
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

On Fri, Feb 23, 2024 at 04:16:07PM +0800, Yanteng Si wrote:
> Hi Serge,
> 
> 在 2024/2/22 21:59, Serge Semin 写道:
> > On Thu, Feb 22, 2024 at 09:39:49PM +0800, Yanteng Si wrote:
> > > 在 2024/2/6 02:17, Serge Semin 写道:
> > > > On Tue, Jan 30, 2024 at 04:48:17PM +0800, Yanteng Si wrote:
> > > > > There are two types of Loongson DWGMAC. The first type shares the same
> > > > > register definitions and has similar logic as dwmac1000. The second type
> > > > > uses several different register definitions, we think it is necessary to
> > > > > distinguish rx and tx, so we split these bits into two.
> > > > > 
> > > > > Simply put, we split some single bit fields into double bits fileds:
> > > > > 
> > > > >        Name              Tx          Rx
> > > > > 
> > > > > DMA_INTR_ENA_NIE = 0x00040000 | 0x00020000;
> > > > > DMA_INTR_ENA_AIE = 0x00010000 | 0x00008000;
> > > > > DMA_STATUS_NIS   = 0x00040000 | 0x00020000;
> > > > > DMA_STATUS_AIS   = 0x00010000 | 0x00008000;
> > > > > DMA_STATUS_FBI   = 0x00002000 | 0x00001000;
> > > > > 
> > > > > Therefore, when using, TX and RX must be set at the same time.
> > > > > 
> > > > > How to use them:
> > > > > 1. Create the Loongson GNET-specific
> > > > > stmmac_dma_ops.dma_interrupt()
> > > > > stmmac_dma_ops.init_chan()
> > > > > methods in the dwmac-loongson.c driver. Adding all the
> > > > > Loongson-specific macros
> > > > > 
> > > > > 2. Create a Loongson GNET-specific platform setup method with the next
> > > > > semantics:
> > > > >      + allocate stmmac_dma_ops instance and initialize it with
> > > > >        dwmac1000_dma_ops.
> > > > >      + override the stmmac_dma_ops.{dma_interrupt, init_chan} with
> > > > >        the pointers to the methods defined in 2.
> > > > >      + allocate mac_device_info instance and initialize the
> > > > >        mac_device_info.dma field with a pointer to the new
> > > > >        stmmac_dma_ops instance.
> > > > >      + initialize mac_device_info in a way it's done in
> > > > >        dwmac1000_setup().
> > > > > 
> > > > > 3. Initialize plat_stmmacenet_data.setup() with the pointer to the
> > > > > method created in 2.
> > > > > 
> > > > > Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
> > > > > Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
> > > > > Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
> > > > > ---
> > > > >    .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 248 ++++++++++++++++++
> > > > >    1 file changed, 248 insertions(+)
> > > > > 
> > > > > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > > > index e7ce027cc14e..3b3578318cc1 100644
> > > > > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > > > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > > > @@ -8,6 +8,193 @@
> > > > >    #include <linux/device.h>
> > > > >    #include <linux/of_irq.h>
> > > > >    #include "stmmac.h"
> > > > > +#include "dwmac_dma.h"
> > > > > +#include "dwmac1000.h"
> > > > > +
> > > > > +#define DMA_INTR_ENA_NIE_TX_LOONGSON 0x00040000	/* Normal Loongson Tx Summary */
> > > > > +#define DMA_INTR_ENA_NIE_RX_LOONGSON 0x00020000	/* Normal Loongson Rx Summary */
> > > > > +#define DMA_INTR_NORMAL_LOONGSON	(DMA_INTR_ENA_NIE_TX_LOONGSON | \
> > > > > +			 DMA_INTR_ENA_NIE_RX_LOONGSON | DMA_INTR_ENA_RIE | \
> > > > > +			 DMA_INTR_ENA_TIE)
> > > > > +
> > > > > +#define DMA_INTR_ENA_AIE_TX_LOONGSON 0x00010000	/* Abnormal Loongson Tx Summary */
> > > > > +#define DMA_INTR_ENA_AIE_RX_LOONGSON 0x00008000	/* Abnormal Loongson Rx Summary */
> > > > > +
> > > > > +#define DMA_INTR_ABNORMAL_LOONGSON	(DMA_INTR_ENA_AIE_TX_LOONGSON | \
> > > > > +				DMA_INTR_ENA_AIE_RX_LOONGSON | DMA_INTR_ENA_FBE | \
> > > > > +				DMA_INTR_ENA_UNE)
> > > > > +
> > > > > +#define DMA_INTR_DEFAULT_MASK_LOONGSON	(DMA_INTR_NORMAL_LOONGSON | DMA_INTR_ABNORMAL_LOONGSON)
> > > > > +
> > > > > +#define DMA_STATUS_NIS_TX_LOONGSON	0x00040000	/* Normal Loongson Tx Interrupt Summary */
> > > > > +#define DMA_STATUS_NIS_RX_LOONGSON	0x00020000	/* Normal Loongson Rx Interrupt Summary */
> > > > > +
> > > > > +#define DMA_STATUS_AIS_TX_LOONGSON	0x00010000	/* Abnormal Loongson Tx Interrupt Summary */
> > > > > +#define DMA_STATUS_AIS_RX_LOONGSON	0x00008000	/* Abnormal Loongson Rx Interrupt Summary */
> > > > > +
> > > > > +#define DMA_STATUS_FBI_TX_LOONGSON	0x00002000	/* Fatal Loongson Tx Bus Error Interrupt */
> > > > > +#define DMA_STATUS_FBI_RX_LOONGSON	0x00001000	/* Fatal Loongson Rx Bus Error Interrupt */
> > > > > +
> > > > > +#define DMA_STATUS_MSK_COMMON_LOONGSON		(DMA_STATUS_NIS_TX_LOONGSON | \
> > > > > +					 DMA_STATUS_NIS_RX_LOONGSON | DMA_STATUS_AIS_TX_LOONGSON | \
> > > > > +					 DMA_STATUS_AIS_RX_LOONGSON | DMA_STATUS_FBI_TX_LOONGSON | \
> > > > > +					 DMA_STATUS_FBI_RX_LOONGSON)
> > > > Max 80 chars per line please.
> > > OK,
> > > > > +
> > > > > +#define DMA_STATUS_MSK_RX_LOONGSON		(DMA_STATUS_ERI | \
> > > > > +					 DMA_STATUS_RWT | \
> > > > > +					 DMA_STATUS_RPS | \
> > > > > +					 DMA_STATUS_RU | \
> > > > > +					 DMA_STATUS_RI | \
> > > > > +					 DMA_STATUS_OVF | \
> > > > > +					 DMA_STATUS_MSK_COMMON_LOONGSON)
> > > > > +
> > > > > +#define DMA_STATUS_MSK_TX_LOONGSON		(DMA_STATUS_ETI | \
> > > > > +					 DMA_STATUS_UNF | \
> > > > > +					 DMA_STATUS_TJT | \
> > > > > +					 DMA_STATUS_TU | \
> > > > > +					 DMA_STATUS_TPS | \
> > > > > +					 DMA_STATUS_TI | \
> > > > > +					 DMA_STATUS_MSK_COMMON_LOONGSON)
> > > > > +
> > > > > +struct loongson_data {
> > > > > +	struct device *dev;
> > > > > +	u32 lgmac_version;
> > > > > +	struct stmmac_dma_ops dwlgmac_dma_ops;
> > > > Just figured out we can do without this field being added to the
> > > > private data. See my note in the loongson_setup() method.
> > > > 
> > > > > +};
> > > > > +
> > > > > +static void dwlgmac_dma_init_channel(struct stmmac_priv *priv,
> > > > The "dwlgmac_" prefix is confusing. There is the DW XLGMAC IP-core for
> > > > which the "dwxlgmac_" is more appropriate and "x" is easy to miss
> > > > should your version of the prefix is met. Consider changing it to
> > > > something like "loongson_gnet_".
> > > OK,
> > > > > +				     void __iomem *ioaddr,
> > > > > +				     struct stmmac_dma_cfg *dma_cfg, u32 chan)
> > > > > +{
> > > > > +	u32 value;
> > > > > +	int txpbl = dma_cfg->txpbl ?: dma_cfg->pbl;
> > > > > +	int rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl;
> > > > > +
> > > > > +	/* common channel control register config */
> > > > > +	value = readl(ioaddr + DMA_CHAN_BUS_MODE(chan));
> > > > > +
> > > > > +	/* Set the DMA PBL (Programmable Burst Length) mode.
> > > > > +	 *
> > > > > +	 * Note: before stmmac core 3.50 this mode bit was 4xPBL, and
> > > > > +	 * post 3.5 mode bit acts as 8*PBL.
> > > > > +	 */
> > > > > +	if (dma_cfg->pblx8)
> > > > > +		value |= DMA_BUS_MODE_MAXPBL;
> > > > > +	value |= DMA_BUS_MODE_USP;
> > > > > +	value &= ~(DMA_BUS_MODE_PBL_MASK | DMA_BUS_MODE_RPBL_MASK);
> > > > > +	value |= (txpbl << DMA_BUS_MODE_PBL_SHIFT);
> > > > > +	value |= (rxpbl << DMA_BUS_MODE_RPBL_SHIFT);
> > > > > +
> > > > > +	/* Set the Fixed burst mode */
> > > > > +	if (dma_cfg->fixed_burst)
> > > > > +		value |= DMA_BUS_MODE_FB;
> > > > > +
> > > > > +	/* Mixed Burst has no effect when fb is set */
> > > > > +	if (dma_cfg->mixed_burst)
> > > > > +		value |= DMA_BUS_MODE_MB;
> > > > > +
> > > > > +	value |= DMA_BUS_MODE_ATDS;
> > > > > +
> > > > > +	if (dma_cfg->aal)
> > > > > +		value |= DMA_BUS_MODE_AAL;
> > > > > +
> > > > > +	writel(value, ioaddr + DMA_BUS_MODE);
> > > > > +
> > > > > +	/* Mask interrupts by writing to CSR7 */
> > > > > +	writel(DMA_INTR_DEFAULT_MASK_LOONGSON, ioaddr + DMA_INTR_ENA);
> > > > > +}
> > > > > +
> > > > > +static int dwlgmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
> > > > The same note as above.
> > > > 
> > > > > +				 struct stmmac_extra_stats *x, u32 chan, u32 dir)
> > > > > +{
> > > > > +	struct stmmac_rxq_stats *rxq_stats = &priv->xstats.rxq_stats[chan];
> > > > > +	struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[chan];
> > > > > +	int ret = 0;
> > > > > +	/* read the status register (CSR5) */
> > > > > +	u32 nor_intr_status;
> > > > > +	u32 abnor_intr_status;
> > > > > +	u32 fb_intr_status;
> > > > Reverse xmas tree please.
> > > > 
> > > > > +	u32 intr_status = readl(ioaddr + DMA_CHAN_STATUS(chan));
> > > > Please move the initialization into a separate statement.
> > > OK,
> > > > > +
> > > > > +#ifdef DWMAC_DMA_DEBUG
> > > > > +	/* Enable it to monitor DMA rx/tx status in case of critical problems */
> > > > > +	pr_debug("%s: [CSR5: 0x%08x]\n", __func__, intr_status);
> > > > > +	show_tx_process_state(intr_status);
> > > > > +	show_rx_process_state(intr_status);
> > > > > +#endif
> > > > This will cause a build-error if DWMAC_DMA_DEBUG is defined. Just drop
> > > > it.
> > > > OK,
> > > > > +
> > > > > +	if (dir == DMA_DIR_RX)
> > > > > +		intr_status &= DMA_STATUS_MSK_RX_LOONGSON;
> > > > > +	else if (dir == DMA_DIR_TX)
> > > > > +		intr_status &= DMA_STATUS_MSK_TX_LOONGSON;
> > > > > +
> > > > > +	nor_intr_status = intr_status & (DMA_STATUS_NIS_TX_LOONGSON |
> > > > > +		DMA_STATUS_NIS_RX_LOONGSON);
> > > > > +	abnor_intr_status = intr_status & (DMA_STATUS_AIS_TX_LOONGSON |
> > > > > +		DMA_STATUS_AIS_RX_LOONGSON);
> > > > > +	fb_intr_status = intr_status & (DMA_STATUS_FBI_TX_LOONGSON |
> > > > > +		DMA_STATUS_FBI_RX_LOONGSON);
> > > > > +
> > > > > +	/* ABNORMAL interrupts */
> > > > > +	if (unlikely(abnor_intr_status)) {
> > > > > +		if (unlikely(intr_status & DMA_STATUS_UNF)) {
> > > > > +			ret = tx_hard_error_bump_tc;
> > > > > +			x->tx_undeflow_irq++;
> > > > > +		}
> > > > > +		if (unlikely(intr_status & DMA_STATUS_TJT))
> > > > > +			x->tx_jabber_irq++;
> > > > > +
> > > > > +		if (unlikely(intr_status & DMA_STATUS_OVF))
> > > > > +			x->rx_overflow_irq++;
> > > > > +
> > > > > +		if (unlikely(intr_status & DMA_STATUS_RU))
> > > > > +			x->rx_buf_unav_irq++;
> > > > > +		if (unlikely(intr_status & DMA_STATUS_RPS))
> > > > > +			x->rx_process_stopped_irq++;
> > > > > +		if (unlikely(intr_status & DMA_STATUS_RWT))
> > > > > +			x->rx_watchdog_irq++;
> > > > > +		if (unlikely(intr_status & DMA_STATUS_ETI))
> > > > > +			x->tx_early_irq++;
> > > > > +		if (unlikely(intr_status & DMA_STATUS_TPS)) {
> > > > > +			x->tx_process_stopped_irq++;
> > > > > +			ret = tx_hard_error;
> > > > > +		}
> > > > > +		if (unlikely(intr_status & fb_intr_status)) {
> > > > > +			x->fatal_bus_error_irq++;
> > > > > +			ret = tx_hard_error;
> > > > > +		}
> > > > > +	}
> > > > > +	/* TX/RX NORMAL interrupts */
> > > > > +	if (likely(nor_intr_status)) {
> > > > > +		if (likely(intr_status & DMA_STATUS_RI)) {
> > > > > +			u32 value = readl(ioaddr + DMA_INTR_ENA);
> > > > > +			/* to schedule NAPI on real RIE event. */
> > > > > +			if (likely(value & DMA_INTR_ENA_RIE)) {
> > > > > +				u64_stats_update_begin(&rxq_stats->syncp);
> > > > > +				rxq_stats->rx_normal_irq_n++;
> > > > > +				u64_stats_update_end(&rxq_stats->syncp);
> > > > > +				ret |= handle_rx;
> > > > > +			}
> > > > > +		}
> > > > > +		if (likely(intr_status & DMA_STATUS_TI)) {
> > > > > +			u64_stats_update_begin(&txq_stats->syncp);
> > > > > +			txq_stats->tx_normal_irq_n++;
> > > > > +			u64_stats_update_end(&txq_stats->syncp);
> > > > > +			ret |= handle_tx;
> > > > > +		}
> > > > > +		if (unlikely(intr_status & DMA_STATUS_ERI))
> > > > > +			x->rx_early_irq++;
> > > > > +	}
> > > > > +	/* Optional hardware blocks, interrupts should be disabled */
> > > > > +	if (unlikely(intr_status &
> > > > > +		     (DMA_STATUS_GPI | DMA_STATUS_GMI | DMA_STATUS_GLI)))
> > > > > +		pr_warn("%s: unexpected status %08x\n", __func__, intr_status);
> > > > > +
> > > > > +	/* Clear the interrupt by writing a logic 1 to the CSR5[15-0] */
> > > > > +	writel((intr_status & 0x7ffff), ioaddr + DMA_CHAN_STATUS(chan));
> > > > > +
> > > > > +	return ret;
> > > > > +}
> > > > >    struct stmmac_pci_info {
> > > > >    	int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat);
> > > > > @@ -121,6 +308,48 @@ static struct stmmac_pci_info loongson_gmac_pci_info = {
> > > > >    	.config = loongson_gmac_config,
> > > > >    };
> > > > > +static struct mac_device_info *loongson_setup(void *apriv)
> > > > Consider using the GNET-specific prefix, like "loongson_gnet_".
> > > > 
> > > > > +{
> > > > > +	struct stmmac_priv *priv = apriv;
> > > > > +	struct mac_device_info *mac;
> > > > > +	struct loongson_data *ld;
> > > > > +
> > > > > +	mac = devm_kzalloc(priv->device, sizeof(*mac), GFP_KERNEL);
> > > > > +	if (!mac)
> > > > > +		return NULL;
> > > > What about devm_kzalloc()-ing the stmmac_dma_ops instance here and
> > > > initializing it as it's done in the probe method? Thus ...
> > > > 
> > > > > +
> > > > > +	ld = priv->plat->bsp_priv;
> > > > > +	mac->dma = &ld->dwlgmac_dma_ops;
> > > > ... this can be replaced with:
> > > > 
> > > > 	mac->dma = devm_kzalloc(priv->device, sizeof(*mac->dma), GFP_KERNEL);
> > > > 	if (!mac->dma)
> > > > 		return -ENOMEM;
> > > Great, but It seems that we cannot return an int value here.
> > Just
> > 		return NULL;
> OK,
> > then.
> > 
> > > > 	*mac->dma = dwmac1000_dma_ops;
> > > > 	mac->dma->init_chan = loongson_gnet_dma_init_channel;
> > > > 	mac->dma->dma_interrupt = loongson_gnet_dma_interrupt;
> It seems that we still cannot do this because:
> structmac_device_info{
> ...
> conststructstmmac_mmc_ops*mmc;
> ...
> }
> some errors output:
> error: assignment of read-only location '*mac->dma'
> error: assignment of member 'init_chan' in read-only object
> ...

No, we can. Just use a temporary non-const pointer to stmmac_dma_ops:

+static struct mac_device_info *loongson_gnet_setup(void *apriv)
+{
+	struct stmmac_priv *priv = apriv;
+	struct mac_device_info *mac;
+	struct stmmac_dma_ops *dma;
+	struct loongson_data *ld;
+
+	mac = devm_kzalloc(priv->device, sizeof(*mac), GFP_KERNEL);
+	if (!mac)
+		return NULL;
+
+	dma = devm_kzalloc(priv->device, sizeof(*dma), GFP_KERNEL);
+	if (!mac->dma)
+		return NULL;
+
+	*dma = dwmac1000_dma_ops;
+	dma->init_chan = loongson_gnet_dma_init_channel;
+	dma->dma_interrupt = loongson_gnet_dma_interrupt;
+	mac->dma = dma;
+
+	...

-Serge(y)

> Thanks,
> Yanteng
> > > > 
> > > > > +
> > > > > +	/* Pre-initialize the respective "mac" fields as it's done in
> > > > > +	 * dwmac1000_setup()
> > > > > +	 */
> > > > > +	priv->dev->priv_flags |= IFF_UNICAST_FLT;
> > > > > +	mac->pcsr = priv->ioaddr;
> > > > > +	mac->multicast_filter_bins = priv->plat->multicast_filter_bins;
> > > > > +	mac->unicast_filter_entries = priv->plat->unicast_filter_entries;
> > > > > +	mac->mcast_bits_log2 = 0;
> > > > > +
> > > > > +	if (mac->multicast_filter_bins)
> > > > > +		mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins);
> > > > > +
> > > > > +	mac->link.duplex = GMAC_CONTROL_DM;
> > > > > +	mac->link.speed10 = GMAC_CONTROL_PS;
> > > > > +	mac->link.speed100 = GMAC_CONTROL_PS | GMAC_CONTROL_FES;
> > > > > +	mac->link.speed1000 = 0;
> > > > > +	mac->link.speed_mask = GMAC_CONTROL_PS | GMAC_CONTROL_FES;
> > > > > +	mac->mii.addr = GMAC_MII_ADDR;
> > > > > +	mac->mii.data = GMAC_MII_DATA;
> > > > > +	mac->mii.addr_shift = 11;
> > > > > +	mac->mii.addr_mask = 0x0000F800;
> > > > > +	mac->mii.reg_shift = 6;
> > > > > +	mac->mii.reg_mask = 0x000007C0;
> > > > > +	mac->mii.clk_csr_shift = 2;
> > > > > +	mac->mii.clk_csr_mask = GENMASK(5, 2);
> > > > > +
> > > > > +	return mac;
> > > > > +}
> > > > > +
> > > > >    static int loongson_dwmac_probe(struct pci_dev *pdev,
> > > > >    				const struct pci_device_id *id)
> > > > >    {
> > > > > @@ -129,6 +358,7 @@ static int loongson_dwmac_probe(struct pci_dev *pdev,
> > > > >    	struct stmmac_pci_info *info;
> > > > >    	struct stmmac_resources res;
> > > > >    	struct device_node *np;
> > > > > +	struct loongson_data *ld;
> > > > reverse xmas tree order please.
> > > > 
> > > > >    	plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL);
> > > > >    	if (!plat)
> > > > > @@ -145,6 +375,10 @@ static int loongson_dwmac_probe(struct pci_dev *pdev,
> > > > >    	if (!plat->dma_cfg)
> > > > >    		return -ENOMEM;
> > > > > +	ld = devm_kzalloc(&pdev->dev, sizeof(*ld), GFP_KERNEL);
> > > > > +	if (!ld)
> > > > > +		return -ENOMEM;
> > > > > +
> > > > >    	np = dev_of_node(&pdev->dev);
> > > > >    	plat->mdio_node = of_get_child_by_name(np, "mdio");
> > > > >    	if (plat->mdio_node) {
> > > > > @@ -197,6 +431,20 @@ static int loongson_dwmac_probe(struct pci_dev *pdev,
> > > > >    	if (ret)
> > > > >    		goto err_disable_device;
> > > > > +	ld->dev = &pdev->dev;
> > > > > +	ld->lgmac_version = readl(res.addr + GMAC_VERSION) & 0xff;
> > > > AFAICS the lgmac_version is unused in out of the probe() method
> > > > context. What about locally defining it?
> > > OK,
> > > > > +
> > > > > +	/* Activate loongson custom ip */
> > > > > +	if (ld->lgmac_version < DWMAC_CORE_3_50) {
> > > > Please define a new macro for the GNET MAC.
> > > OK.
> > > > > +		ld->dwlgmac_dma_ops = dwmac1000_dma_ops;
> > > > > +		ld->dwlgmac_dma_ops.init_chan = dwlgmac_dma_init_channel;
> > > > > +		ld->dwlgmac_dma_ops.dma_interrupt = dwlgmac_dma_interrupt;
> > > > See my comment in the loongson_setup() method.
> > > This will introduce a compilation warning:
> > > 
> > > warning: returning 'int' from a function with return type 'struct
> > > mac_device_info *' makes pointer from integer without a cast
> > > [-Wint-conversion]
> > >    418 |                 return -ENOMEM;
> > stmmac_hwif_init() expects priv->plat->setup(priv) returning NULL
> > if something wrong. As I suggested above just return NULL then if
> > mac_device_info couldn't be allocated.
> > 
> > -Serge(y)
> > 
> > > 
> > > Thanks,
> > > 
> > > Yanteng
> > > 
> > > > -Serge(y)
> > > > 
> > > > > +
> > > > > +		plat->setup = loongson_setup;
> > > > > +	}
> > > > > +
> > > > > +	plat->bsp_priv = ld;
> > > > > +
> > > > >    	ret = stmmac_dvr_probe(&pdev->dev, plat, &res);
> > > > >    	if (ret)
> > > > >    		goto err_disable_device;
> > > > > -- 
> > > > > 2.31.4
> > > > > 
> 

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 05/11] net: stmmac: dwmac-loongson: Add Loongson-specific register definitions
  2024-02-23 18:50           ` Serge Semin
@ 2024-03-07 13:15             ` Yanteng Si
  2024-03-07 13:44               ` Serge Semin
  0 siblings, 1 reply; 97+ messages in thread
From: Yanteng Si @ 2024-03-07 13:15 UTC (permalink / raw)
  To: Serge Semin
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

Hi Serge,


Sorry for keeping you waiting for so long.

在 2024/2/24 02:50, Serge Semin 写道:
> On Fri, Feb 23, 2024 at 04:16:07PM +0800, Yanteng Si wrote:
>> Hi Serge,
>>
>> 在 2024/2/22 21:59, Serge Semin 写道:
>>> On Thu, Feb 22, 2024 at 09:39:49PM +0800, Yanteng Si wrote:
>>>> 在 2024/2/6 02:17, Serge Semin 写道:
>>>>> On Tue, Jan 30, 2024 at 04:48:17PM +0800, Yanteng Si wrote:
>>>>>> There are two types of Loongson DWGMAC. The first type shares the same
>>>>>> register definitions and has similar logic as dwmac1000. The second type
>>>>>> uses several different register definitions, we think it is necessary to
>>>>>> distinguish rx and tx, so we split these bits into two.
>>>>>>
>>>>>> Simply put, we split some single bit fields into double bits fileds:
>>>>>>
>>>>>>         Name              Tx          Rx
>>>>>>
>>>>>> DMA_INTR_ENA_NIE = 0x00040000 | 0x00020000;
>>>>>> DMA_INTR_ENA_AIE = 0x00010000 | 0x00008000;
>>>>>> DMA_STATUS_NIS   = 0x00040000 | 0x00020000;
>>>>>> DMA_STATUS_AIS   = 0x00010000 | 0x00008000;
>>>>>> DMA_STATUS_FBI   = 0x00002000 | 0x00001000;
>>>>>>
>>>>>> Therefore, when using, TX and RX must be set at the same time.
>>>>>>
>>>>>> How to use them:
>>>>>> 1. Create the Loongson GNET-specific
>>>>>> stmmac_dma_ops.dma_interrupt()
>>>>>> stmmac_dma_ops.init_chan()
>>>>>> methods in the dwmac-loongson.c driver. Adding all the
>>>>>> Loongson-specific macros
>>>>>>
>>>>>> 2. Create a Loongson GNET-specific platform setup method with the next
>>>>>> semantics:
>>>>>>       + allocate stmmac_dma_ops instance and initialize it with
>>>>>>         dwmac1000_dma_ops.
>>>>>>       + override the stmmac_dma_ops.{dma_interrupt, init_chan} with
>>>>>>         the pointers to the methods defined in 2.
>>>>>>       + allocate mac_device_info instance and initialize the
>>>>>>         mac_device_info.dma field with a pointer to the new
>>>>>>         stmmac_dma_ops instance.
>>>>>>       + initialize mac_device_info in a way it's done in
>>>>>>         dwmac1000_setup().
>>>>>>
>>>>>> 3. Initialize plat_stmmacenet_data.setup() with the pointer to the
>>>>>> method created in 2.
>>>>>>
>>>>>> Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
>>>>>> Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
>>>>>> Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
>>>>>> ---
>>>>>>     .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 248 ++++++++++++++++++
>>>>>>     1 file changed, 248 insertions(+)
>>>>>>
>>>>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>>>>> index e7ce027cc14e..3b3578318cc1 100644
>>>>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>>>>> @@ -8,6 +8,193 @@
>>>>>>     #include <linux/device.h>
>>>>>>     #include <linux/of_irq.h>
>>>>>>     #include "stmmac.h"
>>>>>> +#include "dwmac_dma.h"
>>>>>> +#include "dwmac1000.h"
>>>>>> +
>>>>>> +#define DMA_INTR_ENA_NIE_TX_LOONGSON 0x00040000	/* Normal Loongson Tx Summary */
>>>>>> +#define DMA_INTR_ENA_NIE_RX_LOONGSON 0x00020000	/* Normal Loongson Rx Summary */
>>>>>> +#define DMA_INTR_NORMAL_LOONGSON	(DMA_INTR_ENA_NIE_TX_LOONGSON | \
>>>>>> +			 DMA_INTR_ENA_NIE_RX_LOONGSON | DMA_INTR_ENA_RIE | \
>>>>>> +			 DMA_INTR_ENA_TIE)
>>>>>> +
>>>>>> +#define DMA_INTR_ENA_AIE_TX_LOONGSON 0x00010000	/* Abnormal Loongson Tx Summary */
>>>>>> +#define DMA_INTR_ENA_AIE_RX_LOONGSON 0x00008000	/* Abnormal Loongson Rx Summary */
>>>>>> +
>>>>>> +#define DMA_INTR_ABNORMAL_LOONGSON	(DMA_INTR_ENA_AIE_TX_LOONGSON | \
>>>>>> +				DMA_INTR_ENA_AIE_RX_LOONGSON | DMA_INTR_ENA_FBE | \
>>>>>> +				DMA_INTR_ENA_UNE)
>>>>>> +
>>>>>> +#define DMA_INTR_DEFAULT_MASK_LOONGSON	(DMA_INTR_NORMAL_LOONGSON | DMA_INTR_ABNORMAL_LOONGSON)
>>>>>> +
>>>>>> +#define DMA_STATUS_NIS_TX_LOONGSON	0x00040000	/* Normal Loongson Tx Interrupt Summary */
>>>>>> +#define DMA_STATUS_NIS_RX_LOONGSON	0x00020000	/* Normal Loongson Rx Interrupt Summary */
>>>>>> +
>>>>>> +#define DMA_STATUS_AIS_TX_LOONGSON	0x00010000	/* Abnormal Loongson Tx Interrupt Summary */
>>>>>> +#define DMA_STATUS_AIS_RX_LOONGSON	0x00008000	/* Abnormal Loongson Rx Interrupt Summary */
>>>>>> +
>>>>>> +#define DMA_STATUS_FBI_TX_LOONGSON	0x00002000	/* Fatal Loongson Tx Bus Error Interrupt */
>>>>>> +#define DMA_STATUS_FBI_RX_LOONGSON	0x00001000	/* Fatal Loongson Rx Bus Error Interrupt */
>>>>>> +
>>>>>> +#define DMA_STATUS_MSK_COMMON_LOONGSON		(DMA_STATUS_NIS_TX_LOONGSON | \
>>>>>> +					 DMA_STATUS_NIS_RX_LOONGSON | DMA_STATUS_AIS_TX_LOONGSON | \
>>>>>> +					 DMA_STATUS_AIS_RX_LOONGSON | DMA_STATUS_FBI_TX_LOONGSON | \
>>>>>> +					 DMA_STATUS_FBI_RX_LOONGSON)
>>>>> Max 80 chars per line please.
>>>> OK,
>>>>>> +
>>>>>> +#define DMA_STATUS_MSK_RX_LOONGSON		(DMA_STATUS_ERI | \
>>>>>> +					 DMA_STATUS_RWT | \
>>>>>> +					 DMA_STATUS_RPS | \
>>>>>> +					 DMA_STATUS_RU | \
>>>>>> +					 DMA_STATUS_RI | \
>>>>>> +					 DMA_STATUS_OVF | \
>>>>>> +					 DMA_STATUS_MSK_COMMON_LOONGSON)
>>>>>> +
>>>>>> +#define DMA_STATUS_MSK_TX_LOONGSON		(DMA_STATUS_ETI | \
>>>>>> +					 DMA_STATUS_UNF | \
>>>>>> +					 DMA_STATUS_TJT | \
>>>>>> +					 DMA_STATUS_TU | \
>>>>>> +					 DMA_STATUS_TPS | \
>>>>>> +					 DMA_STATUS_TI | \
>>>>>> +					 DMA_STATUS_MSK_COMMON_LOONGSON)
>>>>>> +
>>>>>> +struct loongson_data {
>>>>>> +	struct device *dev;
>>>>>> +	u32 lgmac_version;
>>>>>> +	struct stmmac_dma_ops dwlgmac_dma_ops;
>>>>> Just figured out we can do without this field being added to the
>>>>> private data. See my note in the loongson_setup() method.
>>>>>
>>>>>> +};
>>>>>> +
>>>>>> +static void dwlgmac_dma_init_channel(struct stmmac_priv *priv,
>>>>> The "dwlgmac_" prefix is confusing. There is the DW XLGMAC IP-core for
>>>>> which the "dwxlgmac_" is more appropriate and "x" is easy to miss
>>>>> should your version of the prefix is met. Consider changing it to
>>>>> something like "loongson_gnet_".
>>>> OK,
>>>>>> +				     void __iomem *ioaddr,
>>>>>> +				     struct stmmac_dma_cfg *dma_cfg, u32 chan)
>>>>>> +{
>>>>>> +	u32 value;
>>>>>> +	int txpbl = dma_cfg->txpbl ?: dma_cfg->pbl;
>>>>>> +	int rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl;
>>>>>> +
>>>>>> +	/* common channel control register config */
>>>>>> +	value = readl(ioaddr + DMA_CHAN_BUS_MODE(chan));
>>>>>> +
>>>>>> +	/* Set the DMA PBL (Programmable Burst Length) mode.
>>>>>> +	 *
>>>>>> +	 * Note: before stmmac core 3.50 this mode bit was 4xPBL, and
>>>>>> +	 * post 3.5 mode bit acts as 8*PBL.
>>>>>> +	 */
>>>>>> +	if (dma_cfg->pblx8)
>>>>>> +		value |= DMA_BUS_MODE_MAXPBL;
>>>>>> +	value |= DMA_BUS_MODE_USP;
>>>>>> +	value &= ~(DMA_BUS_MODE_PBL_MASK | DMA_BUS_MODE_RPBL_MASK);
>>>>>> +	value |= (txpbl << DMA_BUS_MODE_PBL_SHIFT);
>>>>>> +	value |= (rxpbl << DMA_BUS_MODE_RPBL_SHIFT);
>>>>>> +
>>>>>> +	/* Set the Fixed burst mode */
>>>>>> +	if (dma_cfg->fixed_burst)
>>>>>> +		value |= DMA_BUS_MODE_FB;
>>>>>> +
>>>>>> +	/* Mixed Burst has no effect when fb is set */
>>>>>> +	if (dma_cfg->mixed_burst)
>>>>>> +		value |= DMA_BUS_MODE_MB;
>>>>>> +
>>>>>> +	value |= DMA_BUS_MODE_ATDS;
>>>>>> +
>>>>>> +	if (dma_cfg->aal)
>>>>>> +		value |= DMA_BUS_MODE_AAL;
>>>>>> +
>>>>>> +	writel(value, ioaddr + DMA_BUS_MODE);
>>>>>> +
>>>>>> +	/* Mask interrupts by writing to CSR7 */
>>>>>> +	writel(DMA_INTR_DEFAULT_MASK_LOONGSON, ioaddr + DMA_INTR_ENA);
>>>>>> +}
>>>>>> +
>>>>>> +static int dwlgmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
>>>>> The same note as above.
>>>>>
>>>>>> +				 struct stmmac_extra_stats *x, u32 chan, u32 dir)
>>>>>> +{
>>>>>> +	struct stmmac_rxq_stats *rxq_stats = &priv->xstats.rxq_stats[chan];
>>>>>> +	struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[chan];
>>>>>> +	int ret = 0;
>>>>>> +	/* read the status register (CSR5) */
>>>>>> +	u32 nor_intr_status;
>>>>>> +	u32 abnor_intr_status;
>>>>>> +	u32 fb_intr_status;
>>>>> Reverse xmas tree please.
>>>>>
>>>>>> +	u32 intr_status = readl(ioaddr + DMA_CHAN_STATUS(chan));
>>>>> Please move the initialization into a separate statement.
>>>> OK,
>>>>>> +
>>>>>> +#ifdef DWMAC_DMA_DEBUG
>>>>>> +	/* Enable it to monitor DMA rx/tx status in case of critical problems */
>>>>>> +	pr_debug("%s: [CSR5: 0x%08x]\n", __func__, intr_status);
>>>>>> +	show_tx_process_state(intr_status);
>>>>>> +	show_rx_process_state(intr_status);
>>>>>> +#endif
>>>>> This will cause a build-error if DWMAC_DMA_DEBUG is defined. Just drop
>>>>> it.
>>>>> OK,
>>>>>> +
>>>>>> +	if (dir == DMA_DIR_RX)
>>>>>> +		intr_status &= DMA_STATUS_MSK_RX_LOONGSON;
>>>>>> +	else if (dir == DMA_DIR_TX)
>>>>>> +		intr_status &= DMA_STATUS_MSK_TX_LOONGSON;
>>>>>> +
>>>>>> +	nor_intr_status = intr_status & (DMA_STATUS_NIS_TX_LOONGSON |
>>>>>> +		DMA_STATUS_NIS_RX_LOONGSON);
>>>>>> +	abnor_intr_status = intr_status & (DMA_STATUS_AIS_TX_LOONGSON |
>>>>>> +		DMA_STATUS_AIS_RX_LOONGSON);
>>>>>> +	fb_intr_status = intr_status & (DMA_STATUS_FBI_TX_LOONGSON |
>>>>>> +		DMA_STATUS_FBI_RX_LOONGSON);
>>>>>> +
>>>>>> +	/* ABNORMAL interrupts */
>>>>>> +	if (unlikely(abnor_intr_status)) {
>>>>>> +		if (unlikely(intr_status & DMA_STATUS_UNF)) {
>>>>>> +			ret = tx_hard_error_bump_tc;
>>>>>> +			x->tx_undeflow_irq++;
>>>>>> +		}
>>>>>> +		if (unlikely(intr_status & DMA_STATUS_TJT))
>>>>>> +			x->tx_jabber_irq++;
>>>>>> +
>>>>>> +		if (unlikely(intr_status & DMA_STATUS_OVF))
>>>>>> +			x->rx_overflow_irq++;
>>>>>> +
>>>>>> +		if (unlikely(intr_status & DMA_STATUS_RU))
>>>>>> +			x->rx_buf_unav_irq++;
>>>>>> +		if (unlikely(intr_status & DMA_STATUS_RPS))
>>>>>> +			x->rx_process_stopped_irq++;
>>>>>> +		if (unlikely(intr_status & DMA_STATUS_RWT))
>>>>>> +			x->rx_watchdog_irq++;
>>>>>> +		if (unlikely(intr_status & DMA_STATUS_ETI))
>>>>>> +			x->tx_early_irq++;
>>>>>> +		if (unlikely(intr_status & DMA_STATUS_TPS)) {
>>>>>> +			x->tx_process_stopped_irq++;
>>>>>> +			ret = tx_hard_error;
>>>>>> +		}
>>>>>> +		if (unlikely(intr_status & fb_intr_status)) {
>>>>>> +			x->fatal_bus_error_irq++;
>>>>>> +			ret = tx_hard_error;
>>>>>> +		}
>>>>>> +	}
>>>>>> +	/* TX/RX NORMAL interrupts */
>>>>>> +	if (likely(nor_intr_status)) {
>>>>>> +		if (likely(intr_status & DMA_STATUS_RI)) {
>>>>>> +			u32 value = readl(ioaddr + DMA_INTR_ENA);
>>>>>> +			/* to schedule NAPI on real RIE event. */
>>>>>> +			if (likely(value & DMA_INTR_ENA_RIE)) {
>>>>>> +				u64_stats_update_begin(&rxq_stats->syncp);
>>>>>> +				rxq_stats->rx_normal_irq_n++;
>>>>>> +				u64_stats_update_end(&rxq_stats->syncp);
>>>>>> +				ret |= handle_rx;
>>>>>> +			}
>>>>>> +		}
>>>>>> +		if (likely(intr_status & DMA_STATUS_TI)) {
>>>>>> +			u64_stats_update_begin(&txq_stats->syncp);
>>>>>> +			txq_stats->tx_normal_irq_n++;
>>>>>> +			u64_stats_update_end(&txq_stats->syncp);
>>>>>> +			ret |= handle_tx;
>>>>>> +		}
>>>>>> +		if (unlikely(intr_status & DMA_STATUS_ERI))
>>>>>> +			x->rx_early_irq++;
>>>>>> +	}
>>>>>> +	/* Optional hardware blocks, interrupts should be disabled */
>>>>>> +	if (unlikely(intr_status &
>>>>>> +		     (DMA_STATUS_GPI | DMA_STATUS_GMI | DMA_STATUS_GLI)))
>>>>>> +		pr_warn("%s: unexpected status %08x\n", __func__, intr_status);
>>>>>> +
>>>>>> +	/* Clear the interrupt by writing a logic 1 to the CSR5[15-0] */
>>>>>> +	writel((intr_status & 0x7ffff), ioaddr + DMA_CHAN_STATUS(chan));
>>>>>> +
>>>>>> +	return ret;
>>>>>> +}
>>>>>>     struct stmmac_pci_info {
>>>>>>     	int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat);
>>>>>> @@ -121,6 +308,48 @@ static struct stmmac_pci_info loongson_gmac_pci_info = {
>>>>>>     	.config = loongson_gmac_config,
>>>>>>     };
>>>>>> +static struct mac_device_info *loongson_setup(void *apriv)
>>>>> Consider using the GNET-specific prefix, like "loongson_gnet_".
>>>>>
>>>>>> +{
>>>>>> +	struct stmmac_priv *priv = apriv;
>>>>>> +	struct mac_device_info *mac;
>>>>>> +	struct loongson_data *ld;
>>>>>> +
>>>>>> +	mac = devm_kzalloc(priv->device, sizeof(*mac), GFP_KERNEL);
>>>>>> +	if (!mac)
>>>>>> +		return NULL;
>>>>> What about devm_kzalloc()-ing the stmmac_dma_ops instance here and
>>>>> initializing it as it's done in the probe method? Thus ...
>>>>>
>>>>>> +
>>>>>> +	ld = priv->plat->bsp_priv;
>>>>>> +	mac->dma = &ld->dwlgmac_dma_ops;
>>>>> ... this can be replaced with:
>>>>>
>>>>> 	mac->dma = devm_kzalloc(priv->device, sizeof(*mac->dma), GFP_KERNEL);
>>>>> 	if (!mac->dma)
>>>>> 		return -ENOMEM;
>>>> Great, but It seems that we cannot return an int value here.
>>> Just
>>> 		return NULL;
>> OK,
>>> then.
>>>
>>>>> 	*mac->dma = dwmac1000_dma_ops;
>>>>> 	mac->dma->init_chan = loongson_gnet_dma_init_channel;
>>>>> 	mac->dma->dma_interrupt = loongson_gnet_dma_interrupt;
>> It seems that we still cannot do this because:
>> structmac_device_info{
>> ...
>> conststructstmmac_mmc_ops*mmc;
>> ...
>> }
>> some errors output:
>> error: assignment of read-only location '*mac->dma'
>> error: assignment of member 'init_chan' in read-only object
>> ...
> No, we can. Just use a temporary non-const pointer to stmmac_dma_ops:
>
> +static struct mac_device_info *loongson_gnet_setup(void *apriv)
> +{
> +	struct stmmac_priv *priv = apriv;
> +	struct mac_device_info *mac;
> +	struct stmmac_dma_ops *dma;
> +	struct loongson_data *ld;
> +
> +	mac = devm_kzalloc(priv->device, sizeof(*mac), GFP_KERNEL);
> +	if (!mac)
> +		return NULL;
> +
> +	dma = devm_kzalloc(priv->device, sizeof(*dma), GFP_KERNEL);
> +	if (!mac->dma)

We have already modified it according to this comment. By the way, this 
should be "if (!mac)",

otherwise the following part of the code will not work:

> +		return NULL;
> +
> +	*dma = dwmac1000_dma_ops;
> +	dma->init_chan = loongson_gnet_dma_init_channel;
> +	dma->dma_interrupt = loongson_gnet_dma_interrupt;
> +	mac->dma = dma;
> +
> +	...

Tomorrow I will continue to modify other patches based on your comment.

Thanks,

Yanteng

>
> -Serge(y)
>
>> Thanks,
>> Yanteng
>>>>>> +
>>>>>> +	/* Pre-initialize the respective "mac" fields as it's done in
>>>>>> +	 * dwmac1000_setup()
>>>>>> +	 */
>>>>>> +	priv->dev->priv_flags |= IFF_UNICAST_FLT;
>>>>>> +	mac->pcsr = priv->ioaddr;
>>>>>> +	mac->multicast_filter_bins = priv->plat->multicast_filter_bins;
>>>>>> +	mac->unicast_filter_entries = priv->plat->unicast_filter_entries;
>>>>>> +	mac->mcast_bits_log2 = 0;
>>>>>> +
>>>>>> +	if (mac->multicast_filter_bins)
>>>>>> +		mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins);
>>>>>> +
>>>>>> +	mac->link.duplex = GMAC_CONTROL_DM;
>>>>>> +	mac->link.speed10 = GMAC_CONTROL_PS;
>>>>>> +	mac->link.speed100 = GMAC_CONTROL_PS | GMAC_CONTROL_FES;
>>>>>> +	mac->link.speed1000 = 0;
>>>>>> +	mac->link.speed_mask = GMAC_CONTROL_PS | GMAC_CONTROL_FES;
>>>>>> +	mac->mii.addr = GMAC_MII_ADDR;
>>>>>> +	mac->mii.data = GMAC_MII_DATA;
>>>>>> +	mac->mii.addr_shift = 11;
>>>>>> +	mac->mii.addr_mask = 0x0000F800;
>>>>>> +	mac->mii.reg_shift = 6;
>>>>>> +	mac->mii.reg_mask = 0x000007C0;
>>>>>> +	mac->mii.clk_csr_shift = 2;
>>>>>> +	mac->mii.clk_csr_mask = GENMASK(5, 2);
>>>>>> +
>>>>>> +	return mac;
>>>>>> +}
>>>>>> +
>>>>>>     static int loongson_dwmac_probe(struct pci_dev *pdev,
>>>>>>     				const struct pci_device_id *id)
>>>>>>     {
>>>>>> @@ -129,6 +358,7 @@ static int loongson_dwmac_probe(struct pci_dev *pdev,
>>>>>>     	struct stmmac_pci_info *info;
>>>>>>     	struct stmmac_resources res;
>>>>>>     	struct device_node *np;
>>>>>> +	struct loongson_data *ld;
>>>>> reverse xmas tree order please.
>>>>>
>>>>>>     	plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL);
>>>>>>     	if (!plat)
>>>>>> @@ -145,6 +375,10 @@ static int loongson_dwmac_probe(struct pci_dev *pdev,
>>>>>>     	if (!plat->dma_cfg)
>>>>>>     		return -ENOMEM;
>>>>>> +	ld = devm_kzalloc(&pdev->dev, sizeof(*ld), GFP_KERNEL);
>>>>>> +	if (!ld)
>>>>>> +		return -ENOMEM;
>>>>>> +
>>>>>>     	np = dev_of_node(&pdev->dev);
>>>>>>     	plat->mdio_node = of_get_child_by_name(np, "mdio");
>>>>>>     	if (plat->mdio_node) {
>>>>>> @@ -197,6 +431,20 @@ static int loongson_dwmac_probe(struct pci_dev *pdev,
>>>>>>     	if (ret)
>>>>>>     		goto err_disable_device;
>>>>>> +	ld->dev = &pdev->dev;
>>>>>> +	ld->lgmac_version = readl(res.addr + GMAC_VERSION) & 0xff;
>>>>> AFAICS the lgmac_version is unused in out of the probe() method
>>>>> context. What about locally defining it?
>>>> OK,
>>>>>> +
>>>>>> +	/* Activate loongson custom ip */
>>>>>> +	if (ld->lgmac_version < DWMAC_CORE_3_50) {
>>>>> Please define a new macro for the GNET MAC.
>>>> OK.
>>>>>> +		ld->dwlgmac_dma_ops = dwmac1000_dma_ops;
>>>>>> +		ld->dwlgmac_dma_ops.init_chan = dwlgmac_dma_init_channel;
>>>>>> +		ld->dwlgmac_dma_ops.dma_interrupt = dwlgmac_dma_interrupt;
>>>>> See my comment in the loongson_setup() method.
>>>> This will introduce a compilation warning:
>>>>
>>>> warning: returning 'int' from a function with return type 'struct
>>>> mac_device_info *' makes pointer from integer without a cast
>>>> [-Wint-conversion]
>>>>     418 |                 return -ENOMEM;
>>> stmmac_hwif_init() expects priv->plat->setup(priv) returning NULL
>>> if something wrong. As I suggested above just return NULL then if
>>> mac_device_info couldn't be allocated.
>>>
>>> -Serge(y)
>>>
>>>> Thanks,
>>>>
>>>> Yanteng
>>>>
>>>>> -Serge(y)
>>>>>
>>>>>> +
>>>>>> +		plat->setup = loongson_setup;
>>>>>> +	}
>>>>>> +
>>>>>> +	plat->bsp_priv = ld;
>>>>>> +
>>>>>>     	ret = stmmac_dvr_probe(&pdev->dev, plat, &res);
>>>>>>     	if (ret)
>>>>>>     		goto err_disable_device;
>>>>>> -- 
>>>>>> 2.31.4
>>>>>>


^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 05/11] net: stmmac: dwmac-loongson: Add Loongson-specific register definitions
  2024-03-07 13:15             ` Yanteng Si
@ 2024-03-07 13:44               ` Serge Semin
  2024-03-08  4:05                 ` Yanteng Si
  0 siblings, 1 reply; 97+ messages in thread
From: Serge Semin @ 2024-03-07 13:44 UTC (permalink / raw)
  To: Yanteng Si
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

On Thu, Mar 07, 2024 at 09:15:50PM +0800, Yanteng Si wrote:
> Hi Serge,
> 
> 
> Sorry for keeping you waiting for so long.
> 
> 在 2024/2/24 02:50, Serge Semin 写道:
> > On Fri, Feb 23, 2024 at 04:16:07PM +0800, Yanteng Si wrote:
> > > Hi Serge,
> > > 
> > > 在 2024/2/22 21:59, Serge Semin 写道:
> > > > On Thu, Feb 22, 2024 at 09:39:49PM +0800, Yanteng Si wrote:
> > > > > 在 2024/2/6 02:17, Serge Semin 写道:
> > > > > > On Tue, Jan 30, 2024 at 04:48:17PM +0800, Yanteng Si wrote:
> > > > > > > There are two types of Loongson DWGMAC. The first type shares the same
> > > > > > > register definitions and has similar logic as dwmac1000. The second type
> > > > > > > uses several different register definitions, we think it is necessary to
> > > > > > > distinguish rx and tx, so we split these bits into two.
> > > > > > > 
> > > > > > > Simply put, we split some single bit fields into double bits fileds:
> > > > > > > 
> > > > > > >         Name              Tx          Rx
> > > > > > > 
> > > > > > > DMA_INTR_ENA_NIE = 0x00040000 | 0x00020000;
> > > > > > > DMA_INTR_ENA_AIE = 0x00010000 | 0x00008000;
> > > > > > > DMA_STATUS_NIS   = 0x00040000 | 0x00020000;
> > > > > > > DMA_STATUS_AIS   = 0x00010000 | 0x00008000;
> > > > > > > DMA_STATUS_FBI   = 0x00002000 | 0x00001000;
> > > > > > > 
> > > > > > > Therefore, when using, TX and RX must be set at the same time.
> > > > > > > 
> > > > > > > How to use them:
> > > > > > > 1. Create the Loongson GNET-specific
> > > > > > > stmmac_dma_ops.dma_interrupt()
> > > > > > > stmmac_dma_ops.init_chan()
> > > > > > > methods in the dwmac-loongson.c driver. Adding all the
> > > > > > > Loongson-specific macros
> > > > > > > 
> > > > > > > 2. Create a Loongson GNET-specific platform setup method with the next
> > > > > > > semantics:
> > > > > > >       + allocate stmmac_dma_ops instance and initialize it with
> > > > > > >         dwmac1000_dma_ops.
> > > > > > >       + override the stmmac_dma_ops.{dma_interrupt, init_chan} with
> > > > > > >         the pointers to the methods defined in 2.
> > > > > > >       + allocate mac_device_info instance and initialize the
> > > > > > >         mac_device_info.dma field with a pointer to the new
> > > > > > >         stmmac_dma_ops instance.
> > > > > > >       + initialize mac_device_info in a way it's done in
> > > > > > >         dwmac1000_setup().
> > > > > > > 
> > > > > > > 3. Initialize plat_stmmacenet_data.setup() with the pointer to the
> > > > > > > method created in 2.
> > > > > > > 
> > > > > > > Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
> > > > > > > Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
> > > > > > > Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
> > > > > > > ---
> > > > > > >     .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 248 ++++++++++++++++++
> > > > > > >     1 file changed, 248 insertions(+)
> > > > > > > 
> > > > > > > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > > > > > index e7ce027cc14e..3b3578318cc1 100644
> > > > > > > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > > > > > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > > > > > @@ -8,6 +8,193 @@
> > > > > > >     #include <linux/device.h>
> > > > > > >     #include <linux/of_irq.h>
> > > > > > >     #include "stmmac.h"
> > > > > > > +#include "dwmac_dma.h"
> > > > > > > +#include "dwmac1000.h"
> > > > > > > +
> > > > > > > +#define DMA_INTR_ENA_NIE_TX_LOONGSON 0x00040000	/* Normal Loongson Tx Summary */
> > > > > > > +#define DMA_INTR_ENA_NIE_RX_LOONGSON 0x00020000	/* Normal Loongson Rx Summary */
> > > > > > > +#define DMA_INTR_NORMAL_LOONGSON	(DMA_INTR_ENA_NIE_TX_LOONGSON | \
> > > > > > > +			 DMA_INTR_ENA_NIE_RX_LOONGSON | DMA_INTR_ENA_RIE | \
> > > > > > > +			 DMA_INTR_ENA_TIE)
> > > > > > > +
> > > > > > > +#define DMA_INTR_ENA_AIE_TX_LOONGSON 0x00010000	/* Abnormal Loongson Tx Summary */
> > > > > > > +#define DMA_INTR_ENA_AIE_RX_LOONGSON 0x00008000	/* Abnormal Loongson Rx Summary */
> > > > > > > +
> > > > > > > +#define DMA_INTR_ABNORMAL_LOONGSON	(DMA_INTR_ENA_AIE_TX_LOONGSON | \
> > > > > > > +				DMA_INTR_ENA_AIE_RX_LOONGSON | DMA_INTR_ENA_FBE | \
> > > > > > > +				DMA_INTR_ENA_UNE)
> > > > > > > +
> > > > > > > +#define DMA_INTR_DEFAULT_MASK_LOONGSON	(DMA_INTR_NORMAL_LOONGSON | DMA_INTR_ABNORMAL_LOONGSON)
> > > > > > > +
> > > > > > > +#define DMA_STATUS_NIS_TX_LOONGSON	0x00040000	/* Normal Loongson Tx Interrupt Summary */
> > > > > > > +#define DMA_STATUS_NIS_RX_LOONGSON	0x00020000	/* Normal Loongson Rx Interrupt Summary */
> > > > > > > +
> > > > > > > +#define DMA_STATUS_AIS_TX_LOONGSON	0x00010000	/* Abnormal Loongson Tx Interrupt Summary */
> > > > > > > +#define DMA_STATUS_AIS_RX_LOONGSON	0x00008000	/* Abnormal Loongson Rx Interrupt Summary */
> > > > > > > +
> > > > > > > +#define DMA_STATUS_FBI_TX_LOONGSON	0x00002000	/* Fatal Loongson Tx Bus Error Interrupt */
> > > > > > > +#define DMA_STATUS_FBI_RX_LOONGSON	0x00001000	/* Fatal Loongson Rx Bus Error Interrupt */
> > > > > > > +
> > > > > > > +#define DMA_STATUS_MSK_COMMON_LOONGSON		(DMA_STATUS_NIS_TX_LOONGSON | \
> > > > > > > +					 DMA_STATUS_NIS_RX_LOONGSON | DMA_STATUS_AIS_TX_LOONGSON | \
> > > > > > > +					 DMA_STATUS_AIS_RX_LOONGSON | DMA_STATUS_FBI_TX_LOONGSON | \
> > > > > > > +					 DMA_STATUS_FBI_RX_LOONGSON)
> > > > > > Max 80 chars per line please.
> > > > > OK,
> > > > > > > +
> > > > > > > +#define DMA_STATUS_MSK_RX_LOONGSON		(DMA_STATUS_ERI | \
> > > > > > > +					 DMA_STATUS_RWT | \
> > > > > > > +					 DMA_STATUS_RPS | \
> > > > > > > +					 DMA_STATUS_RU | \
> > > > > > > +					 DMA_STATUS_RI | \
> > > > > > > +					 DMA_STATUS_OVF | \
> > > > > > > +					 DMA_STATUS_MSK_COMMON_LOONGSON)
> > > > > > > +
> > > > > > > +#define DMA_STATUS_MSK_TX_LOONGSON		(DMA_STATUS_ETI | \
> > > > > > > +					 DMA_STATUS_UNF | \
> > > > > > > +					 DMA_STATUS_TJT | \
> > > > > > > +					 DMA_STATUS_TU | \
> > > > > > > +					 DMA_STATUS_TPS | \
> > > > > > > +					 DMA_STATUS_TI | \
> > > > > > > +					 DMA_STATUS_MSK_COMMON_LOONGSON)
> > > > > > > +
> > > > > > > +struct loongson_data {
> > > > > > > +	struct device *dev;
> > > > > > > +	u32 lgmac_version;
> > > > > > > +	struct stmmac_dma_ops dwlgmac_dma_ops;
> > > > > > Just figured out we can do without this field being added to the
> > > > > > private data. See my note in the loongson_setup() method.
> > > > > > 
> > > > > > > +};
> > > > > > > +
> > > > > > > +static void dwlgmac_dma_init_channel(struct stmmac_priv *priv,
> > > > > > The "dwlgmac_" prefix is confusing. There is the DW XLGMAC IP-core for
> > > > > > which the "dwxlgmac_" is more appropriate and "x" is easy to miss
> > > > > > should your version of the prefix is met. Consider changing it to
> > > > > > something like "loongson_gnet_".
> > > > > OK,
> > > > > > > +				     void __iomem *ioaddr,
> > > > > > > +				     struct stmmac_dma_cfg *dma_cfg, u32 chan)
> > > > > > > +{
> > > > > > > +	u32 value;
> > > > > > > +	int txpbl = dma_cfg->txpbl ?: dma_cfg->pbl;
> > > > > > > +	int rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl;
> > > > > > > +
> > > > > > > +	/* common channel control register config */
> > > > > > > +	value = readl(ioaddr + DMA_CHAN_BUS_MODE(chan));
> > > > > > > +
> > > > > > > +	/* Set the DMA PBL (Programmable Burst Length) mode.
> > > > > > > +	 *
> > > > > > > +	 * Note: before stmmac core 3.50 this mode bit was 4xPBL, and
> > > > > > > +	 * post 3.5 mode bit acts as 8*PBL.
> > > > > > > +	 */
> > > > > > > +	if (dma_cfg->pblx8)
> > > > > > > +		value |= DMA_BUS_MODE_MAXPBL;
> > > > > > > +	value |= DMA_BUS_MODE_USP;
> > > > > > > +	value &= ~(DMA_BUS_MODE_PBL_MASK | DMA_BUS_MODE_RPBL_MASK);
> > > > > > > +	value |= (txpbl << DMA_BUS_MODE_PBL_SHIFT);
> > > > > > > +	value |= (rxpbl << DMA_BUS_MODE_RPBL_SHIFT);
> > > > > > > +
> > > > > > > +	/* Set the Fixed burst mode */
> > > > > > > +	if (dma_cfg->fixed_burst)
> > > > > > > +		value |= DMA_BUS_MODE_FB;
> > > > > > > +
> > > > > > > +	/* Mixed Burst has no effect when fb is set */
> > > > > > > +	if (dma_cfg->mixed_burst)
> > > > > > > +		value |= DMA_BUS_MODE_MB;
> > > > > > > +
> > > > > > > +	value |= DMA_BUS_MODE_ATDS;
> > > > > > > +
> > > > > > > +	if (dma_cfg->aal)
> > > > > > > +		value |= DMA_BUS_MODE_AAL;
> > > > > > > +
> > > > > > > +	writel(value, ioaddr + DMA_BUS_MODE);
> > > > > > > +
> > > > > > > +	/* Mask interrupts by writing to CSR7 */
> > > > > > > +	writel(DMA_INTR_DEFAULT_MASK_LOONGSON, ioaddr + DMA_INTR_ENA);
> > > > > > > +}
> > > > > > > +
> > > > > > > +static int dwlgmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
> > > > > > The same note as above.
> > > > > > 
> > > > > > > +				 struct stmmac_extra_stats *x, u32 chan, u32 dir)
> > > > > > > +{
> > > > > > > +	struct stmmac_rxq_stats *rxq_stats = &priv->xstats.rxq_stats[chan];
> > > > > > > +	struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[chan];
> > > > > > > +	int ret = 0;
> > > > > > > +	/* read the status register (CSR5) */
> > > > > > > +	u32 nor_intr_status;
> > > > > > > +	u32 abnor_intr_status;
> > > > > > > +	u32 fb_intr_status;
> > > > > > Reverse xmas tree please.
> > > > > > 
> > > > > > > +	u32 intr_status = readl(ioaddr + DMA_CHAN_STATUS(chan));
> > > > > > Please move the initialization into a separate statement.
> > > > > OK,
> > > > > > > +
> > > > > > > +#ifdef DWMAC_DMA_DEBUG
> > > > > > > +	/* Enable it to monitor DMA rx/tx status in case of critical problems */
> > > > > > > +	pr_debug("%s: [CSR5: 0x%08x]\n", __func__, intr_status);
> > > > > > > +	show_tx_process_state(intr_status);
> > > > > > > +	show_rx_process_state(intr_status);
> > > > > > > +#endif
> > > > > > This will cause a build-error if DWMAC_DMA_DEBUG is defined. Just drop
> > > > > > it.
> > > > > > OK,
> > > > > > > +
> > > > > > > +	if (dir == DMA_DIR_RX)
> > > > > > > +		intr_status &= DMA_STATUS_MSK_RX_LOONGSON;
> > > > > > > +	else if (dir == DMA_DIR_TX)
> > > > > > > +		intr_status &= DMA_STATUS_MSK_TX_LOONGSON;
> > > > > > > +
> > > > > > > +	nor_intr_status = intr_status & (DMA_STATUS_NIS_TX_LOONGSON |
> > > > > > > +		DMA_STATUS_NIS_RX_LOONGSON);
> > > > > > > +	abnor_intr_status = intr_status & (DMA_STATUS_AIS_TX_LOONGSON |
> > > > > > > +		DMA_STATUS_AIS_RX_LOONGSON);
> > > > > > > +	fb_intr_status = intr_status & (DMA_STATUS_FBI_TX_LOONGSON |
> > > > > > > +		DMA_STATUS_FBI_RX_LOONGSON);
> > > > > > > +
> > > > > > > +	/* ABNORMAL interrupts */
> > > > > > > +	if (unlikely(abnor_intr_status)) {
> > > > > > > +		if (unlikely(intr_status & DMA_STATUS_UNF)) {
> > > > > > > +			ret = tx_hard_error_bump_tc;
> > > > > > > +			x->tx_undeflow_irq++;
> > > > > > > +		}
> > > > > > > +		if (unlikely(intr_status & DMA_STATUS_TJT))
> > > > > > > +			x->tx_jabber_irq++;
> > > > > > > +
> > > > > > > +		if (unlikely(intr_status & DMA_STATUS_OVF))
> > > > > > > +			x->rx_overflow_irq++;
> > > > > > > +
> > > > > > > +		if (unlikely(intr_status & DMA_STATUS_RU))
> > > > > > > +			x->rx_buf_unav_irq++;
> > > > > > > +		if (unlikely(intr_status & DMA_STATUS_RPS))
> > > > > > > +			x->rx_process_stopped_irq++;
> > > > > > > +		if (unlikely(intr_status & DMA_STATUS_RWT))
> > > > > > > +			x->rx_watchdog_irq++;
> > > > > > > +		if (unlikely(intr_status & DMA_STATUS_ETI))
> > > > > > > +			x->tx_early_irq++;
> > > > > > > +		if (unlikely(intr_status & DMA_STATUS_TPS)) {
> > > > > > > +			x->tx_process_stopped_irq++;
> > > > > > > +			ret = tx_hard_error;
> > > > > > > +		}
> > > > > > > +		if (unlikely(intr_status & fb_intr_status)) {
> > > > > > > +			x->fatal_bus_error_irq++;
> > > > > > > +			ret = tx_hard_error;
> > > > > > > +		}
> > > > > > > +	}
> > > > > > > +	/* TX/RX NORMAL interrupts */
> > > > > > > +	if (likely(nor_intr_status)) {
> > > > > > > +		if (likely(intr_status & DMA_STATUS_RI)) {
> > > > > > > +			u32 value = readl(ioaddr + DMA_INTR_ENA);
> > > > > > > +			/* to schedule NAPI on real RIE event. */
> > > > > > > +			if (likely(value & DMA_INTR_ENA_RIE)) {
> > > > > > > +				u64_stats_update_begin(&rxq_stats->syncp);
> > > > > > > +				rxq_stats->rx_normal_irq_n++;
> > > > > > > +				u64_stats_update_end(&rxq_stats->syncp);
> > > > > > > +				ret |= handle_rx;
> > > > > > > +			}
> > > > > > > +		}
> > > > > > > +		if (likely(intr_status & DMA_STATUS_TI)) {
> > > > > > > +			u64_stats_update_begin(&txq_stats->syncp);
> > > > > > > +			txq_stats->tx_normal_irq_n++;
> > > > > > > +			u64_stats_update_end(&txq_stats->syncp);
> > > > > > > +			ret |= handle_tx;
> > > > > > > +		}
> > > > > > > +		if (unlikely(intr_status & DMA_STATUS_ERI))
> > > > > > > +			x->rx_early_irq++;
> > > > > > > +	}
> > > > > > > +	/* Optional hardware blocks, interrupts should be disabled */
> > > > > > > +	if (unlikely(intr_status &
> > > > > > > +		     (DMA_STATUS_GPI | DMA_STATUS_GMI | DMA_STATUS_GLI)))
> > > > > > > +		pr_warn("%s: unexpected status %08x\n", __func__, intr_status);
> > > > > > > +
> > > > > > > +	/* Clear the interrupt by writing a logic 1 to the CSR5[15-0] */
> > > > > > > +	writel((intr_status & 0x7ffff), ioaddr + DMA_CHAN_STATUS(chan));
> > > > > > > +
> > > > > > > +	return ret;
> > > > > > > +}
> > > > > > >     struct stmmac_pci_info {
> > > > > > >     	int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat);
> > > > > > > @@ -121,6 +308,48 @@ static struct stmmac_pci_info loongson_gmac_pci_info = {
> > > > > > >     	.config = loongson_gmac_config,
> > > > > > >     };
> > > > > > > +static struct mac_device_info *loongson_setup(void *apriv)
> > > > > > Consider using the GNET-specific prefix, like "loongson_gnet_".
> > > > > > 
> > > > > > > +{
> > > > > > > +	struct stmmac_priv *priv = apriv;
> > > > > > > +	struct mac_device_info *mac;
> > > > > > > +	struct loongson_data *ld;
> > > > > > > +
> > > > > > > +	mac = devm_kzalloc(priv->device, sizeof(*mac), GFP_KERNEL);
> > > > > > > +	if (!mac)
> > > > > > > +		return NULL;
> > > > > > What about devm_kzalloc()-ing the stmmac_dma_ops instance here and
> > > > > > initializing it as it's done in the probe method? Thus ...
> > > > > > 
> > > > > > > +
> > > > > > > +	ld = priv->plat->bsp_priv;
> > > > > > > +	mac->dma = &ld->dwlgmac_dma_ops;
> > > > > > ... this can be replaced with:
> > > > > > 
> > > > > > 	mac->dma = devm_kzalloc(priv->device, sizeof(*mac->dma), GFP_KERNEL);
> > > > > > 	if (!mac->dma)
> > > > > > 		return -ENOMEM;
> > > > > Great, but It seems that we cannot return an int value here.
> > > > Just
> > > > 		return NULL;
> > > OK,
> > > > then.
> > > > 
> > > > > > 	*mac->dma = dwmac1000_dma_ops;
> > > > > > 	mac->dma->init_chan = loongson_gnet_dma_init_channel;
> > > > > > 	mac->dma->dma_interrupt = loongson_gnet_dma_interrupt;
> > > It seems that we still cannot do this because:
> > > structmac_device_info{
> > > ...
> > > conststructstmmac_mmc_ops*mmc;
> > > ...
> > > }
> > > some errors output:
> > > error: assignment of read-only location '*mac->dma'
> > > error: assignment of member 'init_chan' in read-only object
> > > ...
> > No, we can. Just use a temporary non-const pointer to stmmac_dma_ops:
> > 
> > +static struct mac_device_info *loongson_gnet_setup(void *apriv)
> > +{
> > +	struct stmmac_priv *priv = apriv;
> > +	struct mac_device_info *mac;
> > +	struct stmmac_dma_ops *dma;
> > +	struct loongson_data *ld;
> > +
> > +	mac = devm_kzalloc(priv->device, sizeof(*mac), GFP_KERNEL);
> > +	if (!mac)
> > +		return NULL;
> > +
> > +	dma = devm_kzalloc(priv->device, sizeof(*dma), GFP_KERNEL);
> > +	if (!mac->dma)
> 

> We have already modified it according to this comment. By the way, this
> should be "if (!mac)",

if (!dma)

but you were right. My hand-written code was incorrect in that part.

-Serge(y)

> 
> otherwise the following part of the code will not work:
> 
> > +		return NULL;
> > +
> > +	*dma = dwmac1000_dma_ops;
> > +	dma->init_chan = loongson_gnet_dma_init_channel;
> > +	dma->dma_interrupt = loongson_gnet_dma_interrupt;
> > +	mac->dma = dma;
> > +
> > +	...
> 
> Tomorrow I will continue to modify other patches based on your comment.
> 
> Thanks,
> 
> Yanteng
> 
> > 
> > -Serge(y)
> > 
> > > Thanks,
> > > Yanteng
> > > > > > > +
> > > > > > > +	/* Pre-initialize the respective "mac" fields as it's done in
> > > > > > > +	 * dwmac1000_setup()
> > > > > > > +	 */
> > > > > > > +	priv->dev->priv_flags |= IFF_UNICAST_FLT;
> > > > > > > +	mac->pcsr = priv->ioaddr;
> > > > > > > +	mac->multicast_filter_bins = priv->plat->multicast_filter_bins;
> > > > > > > +	mac->unicast_filter_entries = priv->plat->unicast_filter_entries;
> > > > > > > +	mac->mcast_bits_log2 = 0;
> > > > > > > +
> > > > > > > +	if (mac->multicast_filter_bins)
> > > > > > > +		mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins);
> > > > > > > +
> > > > > > > +	mac->link.duplex = GMAC_CONTROL_DM;
> > > > > > > +	mac->link.speed10 = GMAC_CONTROL_PS;
> > > > > > > +	mac->link.speed100 = GMAC_CONTROL_PS | GMAC_CONTROL_FES;
> > > > > > > +	mac->link.speed1000 = 0;
> > > > > > > +	mac->link.speed_mask = GMAC_CONTROL_PS | GMAC_CONTROL_FES;
> > > > > > > +	mac->mii.addr = GMAC_MII_ADDR;
> > > > > > > +	mac->mii.data = GMAC_MII_DATA;
> > > > > > > +	mac->mii.addr_shift = 11;
> > > > > > > +	mac->mii.addr_mask = 0x0000F800;
> > > > > > > +	mac->mii.reg_shift = 6;
> > > > > > > +	mac->mii.reg_mask = 0x000007C0;
> > > > > > > +	mac->mii.clk_csr_shift = 2;
> > > > > > > +	mac->mii.clk_csr_mask = GENMASK(5, 2);
> > > > > > > +
> > > > > > > +	return mac;
> > > > > > > +}
> > > > > > > +
> > > > > > >     static int loongson_dwmac_probe(struct pci_dev *pdev,
> > > > > > >     				const struct pci_device_id *id)
> > > > > > >     {
> > > > > > > @@ -129,6 +358,7 @@ static int loongson_dwmac_probe(struct pci_dev *pdev,
> > > > > > >     	struct stmmac_pci_info *info;
> > > > > > >     	struct stmmac_resources res;
> > > > > > >     	struct device_node *np;
> > > > > > > +	struct loongson_data *ld;
> > > > > > reverse xmas tree order please.
> > > > > > 
> > > > > > >     	plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL);
> > > > > > >     	if (!plat)
> > > > > > > @@ -145,6 +375,10 @@ static int loongson_dwmac_probe(struct pci_dev *pdev,
> > > > > > >     	if (!plat->dma_cfg)
> > > > > > >     		return -ENOMEM;
> > > > > > > +	ld = devm_kzalloc(&pdev->dev, sizeof(*ld), GFP_KERNEL);
> > > > > > > +	if (!ld)
> > > > > > > +		return -ENOMEM;
> > > > > > > +
> > > > > > >     	np = dev_of_node(&pdev->dev);
> > > > > > >     	plat->mdio_node = of_get_child_by_name(np, "mdio");
> > > > > > >     	if (plat->mdio_node) {
> > > > > > > @@ -197,6 +431,20 @@ static int loongson_dwmac_probe(struct pci_dev *pdev,
> > > > > > >     	if (ret)
> > > > > > >     		goto err_disable_device;
> > > > > > > +	ld->dev = &pdev->dev;
> > > > > > > +	ld->lgmac_version = readl(res.addr + GMAC_VERSION) & 0xff;
> > > > > > AFAICS the lgmac_version is unused in out of the probe() method
> > > > > > context. What about locally defining it?
> > > > > OK,
> > > > > > > +
> > > > > > > +	/* Activate loongson custom ip */
> > > > > > > +	if (ld->lgmac_version < DWMAC_CORE_3_50) {
> > > > > > Please define a new macro for the GNET MAC.
> > > > > OK.
> > > > > > > +		ld->dwlgmac_dma_ops = dwmac1000_dma_ops;
> > > > > > > +		ld->dwlgmac_dma_ops.init_chan = dwlgmac_dma_init_channel;
> > > > > > > +		ld->dwlgmac_dma_ops.dma_interrupt = dwlgmac_dma_interrupt;
> > > > > > See my comment in the loongson_setup() method.
> > > > > This will introduce a compilation warning:
> > > > > 
> > > > > warning: returning 'int' from a function with return type 'struct
> > > > > mac_device_info *' makes pointer from integer without a cast
> > > > > [-Wint-conversion]
> > > > >     418 |                 return -ENOMEM;
> > > > stmmac_hwif_init() expects priv->plat->setup(priv) returning NULL
> > > > if something wrong. As I suggested above just return NULL then if
> > > > mac_device_info couldn't be allocated.
> > > > 
> > > > -Serge(y)
> > > > 
> > > > > Thanks,
> > > > > 
> > > > > Yanteng
> > > > > 
> > > > > > -Serge(y)
> > > > > > 
> > > > > > > +
> > > > > > > +		plat->setup = loongson_setup;
> > > > > > > +	}
> > > > > > > +
> > > > > > > +	plat->bsp_priv = ld;
> > > > > > > +
> > > > > > >     	ret = stmmac_dvr_probe(&pdev->dev, plat, &res);
> > > > > > >     	if (ret)
> > > > > > >     		goto err_disable_device;
> > > > > > > -- 
> > > > > > > 2.31.4
> > > > > > > 
> 

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 05/11] net: stmmac: dwmac-loongson: Add Loongson-specific register definitions
  2024-03-07 13:44               ` Serge Semin
@ 2024-03-08  4:05                 ` Yanteng Si
  0 siblings, 0 replies; 97+ messages in thread
From: Yanteng Si @ 2024-03-08  4:05 UTC (permalink / raw)
  To: Serge Semin
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang


在 2024/3/7 21:44, Serge Semin 写道:
> On Thu, Mar 07, 2024 at 09:15:50PM +0800, Yanteng Si wrote:
>> Hi Serge,
>>
>>
>> Sorry for keeping you waiting for so long.
>>
>> 在 2024/2/24 02:50, Serge Semin 写道:
>>> On Fri, Feb 23, 2024 at 04:16:07PM +0800, Yanteng Si wrote:
>>>> Hi Serge,
>>>>
>>>> 在 2024/2/22 21:59, Serge Semin 写道:
>>>>> On Thu, Feb 22, 2024 at 09:39:49PM +0800, Yanteng Si wrote:
>>>>>> 在 2024/2/6 02:17, Serge Semin 写道:
>>>>>>> On Tue, Jan 30, 2024 at 04:48:17PM +0800, Yanteng Si wrote:
>>>>>>>> There are two types of Loongson DWGMAC. The first type shares the same
>>>>>>>> register definitions and has similar logic as dwmac1000. The second type
>>>>>>>> uses several different register definitions, we think it is necessary to
>>>>>>>> distinguish rx and tx, so we split these bits into two.
>>>>>>>>
>>>>>>>> Simply put, we split some single bit fields into double bits fileds:
>>>>>>>>
>>>>>>>>          Name              Tx          Rx
>>>>>>>>
>>>>>>>> DMA_INTR_ENA_NIE = 0x00040000 | 0x00020000;
>>>>>>>> DMA_INTR_ENA_AIE = 0x00010000 | 0x00008000;
>>>>>>>> DMA_STATUS_NIS   = 0x00040000 | 0x00020000;
>>>>>>>> DMA_STATUS_AIS   = 0x00010000 | 0x00008000;
>>>>>>>> DMA_STATUS_FBI   = 0x00002000 | 0x00001000;
>>>>>>>>
>>>>>>>> Therefore, when using, TX and RX must be set at the same time.
>>>>>>>>
>>>>>>>> How to use them:
>>>>>>>> 1. Create the Loongson GNET-specific
>>>>>>>> stmmac_dma_ops.dma_interrupt()
>>>>>>>> stmmac_dma_ops.init_chan()
>>>>>>>> methods in the dwmac-loongson.c driver. Adding all the
>>>>>>>> Loongson-specific macros
>>>>>>>>
>>>>>>>> 2. Create a Loongson GNET-specific platform setup method with the next
>>>>>>>> semantics:
>>>>>>>>        + allocate stmmac_dma_ops instance and initialize it with
>>>>>>>>          dwmac1000_dma_ops.
>>>>>>>>        + override the stmmac_dma_ops.{dma_interrupt, init_chan} with
>>>>>>>>          the pointers to the methods defined in 2.
>>>>>>>>        + allocate mac_device_info instance and initialize the
>>>>>>>>          mac_device_info.dma field with a pointer to the new
>>>>>>>>          stmmac_dma_ops instance.
>>>>>>>>        + initialize mac_device_info in a way it's done in
>>>>>>>>          dwmac1000_setup().
>>>>>>>>
>>>>>>>> 3. Initialize plat_stmmacenet_data.setup() with the pointer to the
>>>>>>>> method created in 2.
>>>>>>>>
>>>>>>>> Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
>>>>>>>> Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
>>>>>>>> Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
>>>>>>>> ---
>>>>>>>>      .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 248 ++++++++++++++++++
>>>>>>>>      1 file changed, 248 insertions(+)
>>>>>>>>
>>>>>>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>>>>>>> index e7ce027cc14e..3b3578318cc1 100644
>>>>>>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>>>>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>>>>>>> @@ -8,6 +8,193 @@
>>>>>>>>      #include <linux/device.h>
>>>>>>>>      #include <linux/of_irq.h>
>>>>>>>>      #include "stmmac.h"
>>>>>>>> +#include "dwmac_dma.h"
>>>>>>>> +#include "dwmac1000.h"
>>>>>>>> +
>>>>>>>> +#define DMA_INTR_ENA_NIE_TX_LOONGSON 0x00040000	/* Normal Loongson Tx Summary */
>>>>>>>> +#define DMA_INTR_ENA_NIE_RX_LOONGSON 0x00020000	/* Normal Loongson Rx Summary */
>>>>>>>> +#define DMA_INTR_NORMAL_LOONGSON	(DMA_INTR_ENA_NIE_TX_LOONGSON | \
>>>>>>>> +			 DMA_INTR_ENA_NIE_RX_LOONGSON | DMA_INTR_ENA_RIE | \
>>>>>>>> +			 DMA_INTR_ENA_TIE)
>>>>>>>> +
>>>>>>>> +#define DMA_INTR_ENA_AIE_TX_LOONGSON 0x00010000	/* Abnormal Loongson Tx Summary */
>>>>>>>> +#define DMA_INTR_ENA_AIE_RX_LOONGSON 0x00008000	/* Abnormal Loongson Rx Summary */
>>>>>>>> +
>>>>>>>> +#define DMA_INTR_ABNORMAL_LOONGSON	(DMA_INTR_ENA_AIE_TX_LOONGSON | \
>>>>>>>> +				DMA_INTR_ENA_AIE_RX_LOONGSON | DMA_INTR_ENA_FBE | \
>>>>>>>> +				DMA_INTR_ENA_UNE)
>>>>>>>> +
>>>>>>>> +#define DMA_INTR_DEFAULT_MASK_LOONGSON	(DMA_INTR_NORMAL_LOONGSON | DMA_INTR_ABNORMAL_LOONGSON)
>>>>>>>> +
>>>>>>>> +#define DMA_STATUS_NIS_TX_LOONGSON	0x00040000	/* Normal Loongson Tx Interrupt Summary */
>>>>>>>> +#define DMA_STATUS_NIS_RX_LOONGSON	0x00020000	/* Normal Loongson Rx Interrupt Summary */
>>>>>>>> +
>>>>>>>> +#define DMA_STATUS_AIS_TX_LOONGSON	0x00010000	/* Abnormal Loongson Tx Interrupt Summary */
>>>>>>>> +#define DMA_STATUS_AIS_RX_LOONGSON	0x00008000	/* Abnormal Loongson Rx Interrupt Summary */
>>>>>>>> +
>>>>>>>> +#define DMA_STATUS_FBI_TX_LOONGSON	0x00002000	/* Fatal Loongson Tx Bus Error Interrupt */
>>>>>>>> +#define DMA_STATUS_FBI_RX_LOONGSON	0x00001000	/* Fatal Loongson Rx Bus Error Interrupt */
>>>>>>>> +
>>>>>>>> +#define DMA_STATUS_MSK_COMMON_LOONGSON		(DMA_STATUS_NIS_TX_LOONGSON | \
>>>>>>>> +					 DMA_STATUS_NIS_RX_LOONGSON | DMA_STATUS_AIS_TX_LOONGSON | \
>>>>>>>> +					 DMA_STATUS_AIS_RX_LOONGSON | DMA_STATUS_FBI_TX_LOONGSON | \
>>>>>>>> +					 DMA_STATUS_FBI_RX_LOONGSON)
>>>>>>> Max 80 chars per line please.
>>>>>> OK,
>>>>>>>> +
>>>>>>>> +#define DMA_STATUS_MSK_RX_LOONGSON		(DMA_STATUS_ERI | \
>>>>>>>> +					 DMA_STATUS_RWT | \
>>>>>>>> +					 DMA_STATUS_RPS | \
>>>>>>>> +					 DMA_STATUS_RU | \
>>>>>>>> +					 DMA_STATUS_RI | \
>>>>>>>> +					 DMA_STATUS_OVF | \
>>>>>>>> +					 DMA_STATUS_MSK_COMMON_LOONGSON)
>>>>>>>> +
>>>>>>>> +#define DMA_STATUS_MSK_TX_LOONGSON		(DMA_STATUS_ETI | \
>>>>>>>> +					 DMA_STATUS_UNF | \
>>>>>>>> +					 DMA_STATUS_TJT | \
>>>>>>>> +					 DMA_STATUS_TU | \
>>>>>>>> +					 DMA_STATUS_TPS | \
>>>>>>>> +					 DMA_STATUS_TI | \
>>>>>>>> +					 DMA_STATUS_MSK_COMMON_LOONGSON)
>>>>>>>> +
>>>>>>>> +struct loongson_data {
>>>>>>>> +	struct device *dev;
>>>>>>>> +	u32 lgmac_version;
>>>>>>>> +	struct stmmac_dma_ops dwlgmac_dma_ops;
>>>>>>> Just figured out we can do without this field being added to the
>>>>>>> private data. See my note in the loongson_setup() method.
>>>>>>>
>>>>>>>> +};
>>>>>>>> +
>>>>>>>> +static void dwlgmac_dma_init_channel(struct stmmac_priv *priv,
>>>>>>> The "dwlgmac_" prefix is confusing. There is the DW XLGMAC IP-core for
>>>>>>> which the "dwxlgmac_" is more appropriate and "x" is easy to miss
>>>>>>> should your version of the prefix is met. Consider changing it to
>>>>>>> something like "loongson_gnet_".
>>>>>> OK,
>>>>>>>> +				     void __iomem *ioaddr,
>>>>>>>> +				     struct stmmac_dma_cfg *dma_cfg, u32 chan)
>>>>>>>> +{
>>>>>>>> +	u32 value;
>>>>>>>> +	int txpbl = dma_cfg->txpbl ?: dma_cfg->pbl;
>>>>>>>> +	int rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl;
>>>>>>>> +
>>>>>>>> +	/* common channel control register config */
>>>>>>>> +	value = readl(ioaddr + DMA_CHAN_BUS_MODE(chan));
>>>>>>>> +
>>>>>>>> +	/* Set the DMA PBL (Programmable Burst Length) mode.
>>>>>>>> +	 *
>>>>>>>> +	 * Note: before stmmac core 3.50 this mode bit was 4xPBL, and
>>>>>>>> +	 * post 3.5 mode bit acts as 8*PBL.
>>>>>>>> +	 */
>>>>>>>> +	if (dma_cfg->pblx8)
>>>>>>>> +		value |= DMA_BUS_MODE_MAXPBL;
>>>>>>>> +	value |= DMA_BUS_MODE_USP;
>>>>>>>> +	value &= ~(DMA_BUS_MODE_PBL_MASK | DMA_BUS_MODE_RPBL_MASK);
>>>>>>>> +	value |= (txpbl << DMA_BUS_MODE_PBL_SHIFT);
>>>>>>>> +	value |= (rxpbl << DMA_BUS_MODE_RPBL_SHIFT);
>>>>>>>> +
>>>>>>>> +	/* Set the Fixed burst mode */
>>>>>>>> +	if (dma_cfg->fixed_burst)
>>>>>>>> +		value |= DMA_BUS_MODE_FB;
>>>>>>>> +
>>>>>>>> +	/* Mixed Burst has no effect when fb is set */
>>>>>>>> +	if (dma_cfg->mixed_burst)
>>>>>>>> +		value |= DMA_BUS_MODE_MB;
>>>>>>>> +
>>>>>>>> +	value |= DMA_BUS_MODE_ATDS;
>>>>>>>> +
>>>>>>>> +	if (dma_cfg->aal)
>>>>>>>> +		value |= DMA_BUS_MODE_AAL;
>>>>>>>> +
>>>>>>>> +	writel(value, ioaddr + DMA_BUS_MODE);
>>>>>>>> +
>>>>>>>> +	/* Mask interrupts by writing to CSR7 */
>>>>>>>> +	writel(DMA_INTR_DEFAULT_MASK_LOONGSON, ioaddr + DMA_INTR_ENA);
>>>>>>>> +}
>>>>>>>> +
>>>>>>>> +static int dwlgmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
>>>>>>> The same note as above.
>>>>>>>
>>>>>>>> +				 struct stmmac_extra_stats *x, u32 chan, u32 dir)
>>>>>>>> +{
>>>>>>>> +	struct stmmac_rxq_stats *rxq_stats = &priv->xstats.rxq_stats[chan];
>>>>>>>> +	struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[chan];
>>>>>>>> +	int ret = 0;
>>>>>>>> +	/* read the status register (CSR5) */
>>>>>>>> +	u32 nor_intr_status;
>>>>>>>> +	u32 abnor_intr_status;
>>>>>>>> +	u32 fb_intr_status;
>>>>>>> Reverse xmas tree please.
>>>>>>>
>>>>>>>> +	u32 intr_status = readl(ioaddr + DMA_CHAN_STATUS(chan));
>>>>>>> Please move the initialization into a separate statement.
>>>>>> OK,
>>>>>>>> +
>>>>>>>> +#ifdef DWMAC_DMA_DEBUG
>>>>>>>> +	/* Enable it to monitor DMA rx/tx status in case of critical problems */
>>>>>>>> +	pr_debug("%s: [CSR5: 0x%08x]\n", __func__, intr_status);
>>>>>>>> +	show_tx_process_state(intr_status);
>>>>>>>> +	show_rx_process_state(intr_status);
>>>>>>>> +#endif
>>>>>>> This will cause a build-error if DWMAC_DMA_DEBUG is defined. Just drop
>>>>>>> it.
>>>>>>> OK,
>>>>>>>> +
>>>>>>>> +	if (dir == DMA_DIR_RX)
>>>>>>>> +		intr_status &= DMA_STATUS_MSK_RX_LOONGSON;
>>>>>>>> +	else if (dir == DMA_DIR_TX)
>>>>>>>> +		intr_status &= DMA_STATUS_MSK_TX_LOONGSON;
>>>>>>>> +
>>>>>>>> +	nor_intr_status = intr_status & (DMA_STATUS_NIS_TX_LOONGSON |
>>>>>>>> +		DMA_STATUS_NIS_RX_LOONGSON);
>>>>>>>> +	abnor_intr_status = intr_status & (DMA_STATUS_AIS_TX_LOONGSON |
>>>>>>>> +		DMA_STATUS_AIS_RX_LOONGSON);
>>>>>>>> +	fb_intr_status = intr_status & (DMA_STATUS_FBI_TX_LOONGSON |
>>>>>>>> +		DMA_STATUS_FBI_RX_LOONGSON);
>>>>>>>> +
>>>>>>>> +	/* ABNORMAL interrupts */
>>>>>>>> +	if (unlikely(abnor_intr_status)) {
>>>>>>>> +		if (unlikely(intr_status & DMA_STATUS_UNF)) {
>>>>>>>> +			ret = tx_hard_error_bump_tc;
>>>>>>>> +			x->tx_undeflow_irq++;
>>>>>>>> +		}
>>>>>>>> +		if (unlikely(intr_status & DMA_STATUS_TJT))
>>>>>>>> +			x->tx_jabber_irq++;
>>>>>>>> +
>>>>>>>> +		if (unlikely(intr_status & DMA_STATUS_OVF))
>>>>>>>> +			x->rx_overflow_irq++;
>>>>>>>> +
>>>>>>>> +		if (unlikely(intr_status & DMA_STATUS_RU))
>>>>>>>> +			x->rx_buf_unav_irq++;
>>>>>>>> +		if (unlikely(intr_status & DMA_STATUS_RPS))
>>>>>>>> +			x->rx_process_stopped_irq++;
>>>>>>>> +		if (unlikely(intr_status & DMA_STATUS_RWT))
>>>>>>>> +			x->rx_watchdog_irq++;
>>>>>>>> +		if (unlikely(intr_status & DMA_STATUS_ETI))
>>>>>>>> +			x->tx_early_irq++;
>>>>>>>> +		if (unlikely(intr_status & DMA_STATUS_TPS)) {
>>>>>>>> +			x->tx_process_stopped_irq++;
>>>>>>>> +			ret = tx_hard_error;
>>>>>>>> +		}
>>>>>>>> +		if (unlikely(intr_status & fb_intr_status)) {
>>>>>>>> +			x->fatal_bus_error_irq++;
>>>>>>>> +			ret = tx_hard_error;
>>>>>>>> +		}
>>>>>>>> +	}
>>>>>>>> +	/* TX/RX NORMAL interrupts */
>>>>>>>> +	if (likely(nor_intr_status)) {
>>>>>>>> +		if (likely(intr_status & DMA_STATUS_RI)) {
>>>>>>>> +			u32 value = readl(ioaddr + DMA_INTR_ENA);
>>>>>>>> +			/* to schedule NAPI on real RIE event. */
>>>>>>>> +			if (likely(value & DMA_INTR_ENA_RIE)) {
>>>>>>>> +				u64_stats_update_begin(&rxq_stats->syncp);
>>>>>>>> +				rxq_stats->rx_normal_irq_n++;
>>>>>>>> +				u64_stats_update_end(&rxq_stats->syncp);
>>>>>>>> +				ret |= handle_rx;
>>>>>>>> +			}
>>>>>>>> +		}
>>>>>>>> +		if (likely(intr_status & DMA_STATUS_TI)) {
>>>>>>>> +			u64_stats_update_begin(&txq_stats->syncp);
>>>>>>>> +			txq_stats->tx_normal_irq_n++;
>>>>>>>> +			u64_stats_update_end(&txq_stats->syncp);
>>>>>>>> +			ret |= handle_tx;
>>>>>>>> +		}
>>>>>>>> +		if (unlikely(intr_status & DMA_STATUS_ERI))
>>>>>>>> +			x->rx_early_irq++;
>>>>>>>> +	}
>>>>>>>> +	/* Optional hardware blocks, interrupts should be disabled */
>>>>>>>> +	if (unlikely(intr_status &
>>>>>>>> +		     (DMA_STATUS_GPI | DMA_STATUS_GMI | DMA_STATUS_GLI)))
>>>>>>>> +		pr_warn("%s: unexpected status %08x\n", __func__, intr_status);
>>>>>>>> +
>>>>>>>> +	/* Clear the interrupt by writing a logic 1 to the CSR5[15-0] */
>>>>>>>> +	writel((intr_status & 0x7ffff), ioaddr + DMA_CHAN_STATUS(chan));
>>>>>>>> +
>>>>>>>> +	return ret;
>>>>>>>> +}
>>>>>>>>      struct stmmac_pci_info {
>>>>>>>>      	int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat);
>>>>>>>> @@ -121,6 +308,48 @@ static struct stmmac_pci_info loongson_gmac_pci_info = {
>>>>>>>>      	.config = loongson_gmac_config,
>>>>>>>>      };
>>>>>>>> +static struct mac_device_info *loongson_setup(void *apriv)
>>>>>>> Consider using the GNET-specific prefix, like "loongson_gnet_".
>>>>>>>
>>>>>>>> +{
>>>>>>>> +	struct stmmac_priv *priv = apriv;
>>>>>>>> +	struct mac_device_info *mac;
>>>>>>>> +	struct loongson_data *ld;
>>>>>>>> +
>>>>>>>> +	mac = devm_kzalloc(priv->device, sizeof(*mac), GFP_KERNEL);
>>>>>>>> +	if (!mac)
>>>>>>>> +		return NULL;
>>>>>>> What about devm_kzalloc()-ing the stmmac_dma_ops instance here and
>>>>>>> initializing it as it's done in the probe method? Thus ...
>>>>>>>
>>>>>>>> +
>>>>>>>> +	ld = priv->plat->bsp_priv;
>>>>>>>> +	mac->dma = &ld->dwlgmac_dma_ops;
>>>>>>> ... this can be replaced with:
>>>>>>>
>>>>>>> 	mac->dma = devm_kzalloc(priv->device, sizeof(*mac->dma), GFP_KERNEL);
>>>>>>> 	if (!mac->dma)
>>>>>>> 		return -ENOMEM;
>>>>>> Great, but It seems that we cannot return an int value here.
>>>>> Just
>>>>> 		return NULL;
>>>> OK,
>>>>> then.
>>>>>
>>>>>>> 	*mac->dma = dwmac1000_dma_ops;
>>>>>>> 	mac->dma->init_chan = loongson_gnet_dma_init_channel;
>>>>>>> 	mac->dma->dma_interrupt = loongson_gnet_dma_interrupt;
>>>> It seems that we still cannot do this because:
>>>> structmac_device_info{
>>>> ...
>>>> conststructstmmac_mmc_ops*mmc;
>>>> ...
>>>> }
>>>> some errors output:
>>>> error: assignment of read-only location '*mac->dma'
>>>> error: assignment of member 'init_chan' in read-only object
>>>> ...
>>> No, we can. Just use a temporary non-const pointer to stmmac_dma_ops:
>>>
>>> +static struct mac_device_info *loongson_gnet_setup(void *apriv)
>>> +{
>>> +	struct stmmac_priv *priv = apriv;
>>> +	struct mac_device_info *mac;
>>> +	struct stmmac_dma_ops *dma;
>>> +	struct loongson_data *ld;
>>> +
>>> +	mac = devm_kzalloc(priv->device, sizeof(*mac), GFP_KERNEL);
>>> +	if (!mac)
>>> +		return NULL;
>>> +
>>> +	dma = devm_kzalloc(priv->device, sizeof(*dma), GFP_KERNEL);
>>> +	if (!mac->dma)
>> We have already modified it according to this comment. By the way, this
>> should be "if (!mac)",
> if (!dma)

Yes, you are right!

Thanks,

Yanteng

>
> -Serge(y)
>
>> otherwise the following part of the code will not work:
>>
>>> +		return NULL;
>>> +
>>> +	*dma = dwmac1000_dma_ops;
>>> +	dma->init_chan = loongson_gnet_dma_init_channel;
>>> +	dma->dma_interrupt = loongson_gnet_dma_interrupt;
>>> +	mac->dma = dma;
>>> +
>>> +	...
>> Tomorrow I will continue to modify other patches based on your comment.
>>
>> Thanks,
>>
>> Yanteng
>>
>>> -Serge(y)
>>>
>>>> Thanks,
>>>> Yanteng
>>>>>>>> +
>>>>>>>> +	/* Pre-initialize the respective "mac" fields as it's done in
>>>>>>>> +	 * dwmac1000_setup()
>>>>>>>> +	 */
>>>>>>>> +	priv->dev->priv_flags |= IFF_UNICAST_FLT;
>>>>>>>> +	mac->pcsr = priv->ioaddr;
>>>>>>>> +	mac->multicast_filter_bins = priv->plat->multicast_filter_bins;
>>>>>>>> +	mac->unicast_filter_entries = priv->plat->unicast_filter_entries;
>>>>>>>> +	mac->mcast_bits_log2 = 0;
>>>>>>>> +
>>>>>>>> +	if (mac->multicast_filter_bins)
>>>>>>>> +		mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins);
>>>>>>>> +
>>>>>>>> +	mac->link.duplex = GMAC_CONTROL_DM;
>>>>>>>> +	mac->link.speed10 = GMAC_CONTROL_PS;
>>>>>>>> +	mac->link.speed100 = GMAC_CONTROL_PS | GMAC_CONTROL_FES;
>>>>>>>> +	mac->link.speed1000 = 0;
>>>>>>>> +	mac->link.speed_mask = GMAC_CONTROL_PS | GMAC_CONTROL_FES;
>>>>>>>> +	mac->mii.addr = GMAC_MII_ADDR;
>>>>>>>> +	mac->mii.data = GMAC_MII_DATA;
>>>>>>>> +	mac->mii.addr_shift = 11;
>>>>>>>> +	mac->mii.addr_mask = 0x0000F800;
>>>>>>>> +	mac->mii.reg_shift = 6;
>>>>>>>> +	mac->mii.reg_mask = 0x000007C0;
>>>>>>>> +	mac->mii.clk_csr_shift = 2;
>>>>>>>> +	mac->mii.clk_csr_mask = GENMASK(5, 2);
>>>>>>>> +
>>>>>>>> +	return mac;
>>>>>>>> +}
>>>>>>>> +
>>>>>>>>      static int loongson_dwmac_probe(struct pci_dev *pdev,
>>>>>>>>      				const struct pci_device_id *id)
>>>>>>>>      {
>>>>>>>> @@ -129,6 +358,7 @@ static int loongson_dwmac_probe(struct pci_dev *pdev,
>>>>>>>>      	struct stmmac_pci_info *info;
>>>>>>>>      	struct stmmac_resources res;
>>>>>>>>      	struct device_node *np;
>>>>>>>> +	struct loongson_data *ld;
>>>>>>> reverse xmas tree order please.
>>>>>>>
>>>>>>>>      	plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL);
>>>>>>>>      	if (!plat)
>>>>>>>> @@ -145,6 +375,10 @@ static int loongson_dwmac_probe(struct pci_dev *pdev,
>>>>>>>>      	if (!plat->dma_cfg)
>>>>>>>>      		return -ENOMEM;
>>>>>>>> +	ld = devm_kzalloc(&pdev->dev, sizeof(*ld), GFP_KERNEL);
>>>>>>>> +	if (!ld)
>>>>>>>> +		return -ENOMEM;
>>>>>>>> +
>>>>>>>>      	np = dev_of_node(&pdev->dev);
>>>>>>>>      	plat->mdio_node = of_get_child_by_name(np, "mdio");
>>>>>>>>      	if (plat->mdio_node) {
>>>>>>>> @@ -197,6 +431,20 @@ static int loongson_dwmac_probe(struct pci_dev *pdev,
>>>>>>>>      	if (ret)
>>>>>>>>      		goto err_disable_device;
>>>>>>>> +	ld->dev = &pdev->dev;
>>>>>>>> +	ld->lgmac_version = readl(res.addr + GMAC_VERSION) & 0xff;
>>>>>>> AFAICS the lgmac_version is unused in out of the probe() method
>>>>>>> context. What about locally defining it?
>>>>>> OK,
>>>>>>>> +
>>>>>>>> +	/* Activate loongson custom ip */
>>>>>>>> +	if (ld->lgmac_version < DWMAC_CORE_3_50) {
>>>>>>> Please define a new macro for the GNET MAC.
>>>>>> OK.
>>>>>>>> +		ld->dwlgmac_dma_ops = dwmac1000_dma_ops;
>>>>>>>> +		ld->dwlgmac_dma_ops.init_chan = dwlgmac_dma_init_channel;
>>>>>>>> +		ld->dwlgmac_dma_ops.dma_interrupt = dwlgmac_dma_interrupt;
>>>>>>> See my comment in the loongson_setup() method.
>>>>>> This will introduce a compilation warning:
>>>>>>
>>>>>> warning: returning 'int' from a function with return type 'struct
>>>>>> mac_device_info *' makes pointer from integer without a cast
>>>>>> [-Wint-conversion]
>>>>>>      418 |                 return -ENOMEM;
>>>>> stmmac_hwif_init() expects priv->plat->setup(priv) returning NULL
>>>>> if something wrong. As I suggested above just return NULL then if
>>>>> mac_device_info couldn't be allocated.
>>>>>
>>>>> -Serge(y)
>>>>>
>>>>>> Thanks,
>>>>>>
>>>>>> Yanteng
>>>>>>
>>>>>>> -Serge(y)
>>>>>>>
>>>>>>>> +
>>>>>>>> +		plat->setup = loongson_setup;
>>>>>>>> +	}
>>>>>>>> +
>>>>>>>> +	plat->bsp_priv = ld;
>>>>>>>> +
>>>>>>>>      	ret = stmmac_dvr_probe(&pdev->dev, plat, &res);
>>>>>>>>      	if (ret)
>>>>>>>>      		goto err_disable_device;
>>>>>>>> -- 
>>>>>>>> 2.31.4
>>>>>>>>


^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 04/11] net: stmmac: dwmac-loongson: Move irq config to loongson_gmac_config
  2024-02-05 17:01   ` Serge Semin
@ 2024-03-13  8:14     ` Yanteng Si
  2024-03-19 13:43       ` Serge Semin
  0 siblings, 1 reply; 97+ messages in thread
From: Yanteng Si @ 2024-03-13  8:14 UTC (permalink / raw)
  To: Serge Semin
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang


在 2024/2/6 01:01, Serge Semin 写道:
> On Tue, Jan 30, 2024 at 04:43:24PM +0800, Yanteng Si wrote:
>> Add loongson_dwmac_config and moving irq config related
>> code to loongson_dwmac_config.
>>
>> Removing MSI to prepare for adding loongson multi-channel
>> support later.
> Please detach this change into a separate patch and thoroughly explain
> why it was necessary.
OK.
>
>> Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
>> Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
>> Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
>> ---
>>   .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 85 ++++++++++++-------
>>   1 file changed, 55 insertions(+), 30 deletions(-)
>>
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>> index 979c9b6dab3f..e7ce027cc14e 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>> @@ -11,8 +11,46 @@
>>   
>>   struct stmmac_pci_info {
>>   	int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat);
>> +	int (*config)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat,
>> +		      struct stmmac_resources *res, struct device_node *np);
>>   };
>>   
>> +static int loongson_dwmac_config_legacy(struct pci_dev *pdev,
>> +					struct plat_stmmacenet_data *plat,
>> +					struct stmmac_resources *res,
>> +					struct device_node *np)
>> +{
>> +	if (np) {
>> +		res->irq = of_irq_get_byname(np, "macirq");
>> +		if (res->irq < 0) {
>> +			dev_err(&pdev->dev, "IRQ macirq not found\n");
>> +			return -ENODEV;
>> +		}
>> +
>> +		res->wol_irq = of_irq_get_byname(np, "eth_wake_irq");
>> +		if (res->wol_irq < 0) {
>> +			dev_info(&pdev->dev,
>> +				 "IRQ eth_wake_irq not found, using macirq\n");
>> +			res->wol_irq = res->irq;
>> +		}
>> +
>> +		res->lpi_irq = of_irq_get_byname(np, "eth_lpi");
>> +		if (res->lpi_irq < 0) {
>> +			dev_err(&pdev->dev, "IRQ eth_lpi not found\n");
>> +			return -ENODEV;
>> +		}
>> +	} else {
>> +		res->irq = pdev->irq;
>> +		res->wol_irq = res->irq;
>> +	}
>> +
>> +	plat->flags &= ~STMMAC_FLAG_MULTI_MSI_EN;
>> +	dev_info(&pdev->dev, "%s: Single IRQ enablement successful\n",
>> +		 __func__);
> Why is this here all of the sudden? I don't see this in the original
> code. Please move it to the patch which requires the flag
> setup/cleanup or drop if it isn't necessary.

+	plat->flags &= ~STMMAC_FLAG_MULTI_MSI_EN;
This cannot be removed because it appeared in a rebase(v4 -> v5). See 
<https://lore.kernel.org/all/20230710090001.303225-9-brgl@bgdev.pl/> +	dev_info(&pdev->dev, "%s: Single IRQ enablement successful\n",
+		 __func__);

OK, drop it.

>
>> +
>> +	return 0;
>> +}
>> +
>>   static void loongson_default_data(struct pci_dev *pdev,
>>   				  struct plat_stmmacenet_data *plat)
>>   {
>> @@ -66,8 +104,21 @@ static int loongson_gmac_data(struct pci_dev *pdev,
>>   	return 0;
>>   }
>>   
>> +static int loongson_gmac_config(struct pci_dev *pdev,
>> +				struct plat_stmmacenet_data *plat,
>> +				struct stmmac_resources *res,
>> +				struct device_node *np)
>> +{
>> +	int ret;
>> +
>> +	ret = loongson_dwmac_config_legacy(pdev, plat, res, np);
>> +
>> +	return ret;
>> +}
>> +
> You introduce the config callback here and convert to a dummy method
> in
> [PATCH 07/11] net: stmmac: dwmac-loongson: Add multi-channel supports for loongson
> It's just pointless. What about introducing the
> loongson_dwmac_config_legacy() method and call it directly?
OK, I will try.
>
>>   static struct stmmac_pci_info loongson_gmac_pci_info = {
>>   	.setup = loongson_gmac_data,
>> +	.config = loongson_gmac_config,
>>   };
>>   
>>   static int loongson_dwmac_probe(struct pci_dev *pdev,
>> @@ -139,44 +190,19 @@ static int loongson_dwmac_probe(struct pci_dev *pdev,
>>   		plat->phy_interface = phy_mode;
>>   	}
>>   
>> -	pci_enable_msi(pdev);
> See my first note in this message.

OK.


Thanks,

Yanteng

>
> -Serge(y)
>
>>   	memset(&res, 0, sizeof(res));
>>   	res.addr = pcim_iomap_table(pdev)[0];
>>   
>> -	if (np) {
>> -		res.irq = of_irq_get_byname(np, "macirq");
>> -		if (res.irq < 0) {
>> -			dev_err(&pdev->dev, "IRQ macirq not found\n");
>> -			ret = -ENODEV;
>> -			goto err_disable_msi;
>> -		}
>> -
>> -		res.wol_irq = of_irq_get_byname(np, "eth_wake_irq");
>> -		if (res.wol_irq < 0) {
>> -			dev_info(&pdev->dev,
>> -				 "IRQ eth_wake_irq not found, using macirq\n");
>> -			res.wol_irq = res.irq;
>> -		}
>> -
>> -		res.lpi_irq = of_irq_get_byname(np, "eth_lpi");
>> -		if (res.lpi_irq < 0) {
>> -			dev_err(&pdev->dev, "IRQ eth_lpi not found\n");
>> -			ret = -ENODEV;
>> -			goto err_disable_msi;
>> -		}
>> -	} else {
>> -		res.irq = pdev->irq;
>> -		res.wol_irq = pdev->irq;
>> -	}
>> +	ret = info->config(pdev, plat, &res, np);
>> +	if (ret)
>> +		goto err_disable_device;
>>   
>>   	ret = stmmac_dvr_probe(&pdev->dev, plat, &res);
>>   	if (ret)
>> -		goto err_disable_msi;
>> +		goto err_disable_device;
>>   
>>   	return ret;
>>   
>> -err_disable_msi:
>> -	pci_disable_msi(pdev);
>>   err_disable_device:
>>   	pci_disable_device(pdev);
>>   err_put_node:
>> @@ -200,7 +226,6 @@ static void loongson_dwmac_remove(struct pci_dev *pdev)
>>   		break;
>>   	}
>>   
>> -	pci_disable_msi(pdev);
>>   	pci_disable_device(pdev);
>>   }
>>   
>> -- 
>> 2.31.4
>>


^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 01/11] net: stmmac: Add multi-channel support
       [not found]         ` <ee2ffb6a-fe34-47a1-9734-b0e6697a5f09@loongson.cn>
@ 2024-03-13  9:10           ` Yanteng Si
  2024-03-19 14:18             ` Serge Semin
  0 siblings, 1 reply; 97+ messages in thread
From: Yanteng Si @ 2024-03-13  9:10 UTC (permalink / raw)
  To: Serge Semin
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

Hi Serge

在 2024/3/13 15:01, Yanteng Si 写道:
> 在 2024/2/21 21:48, Serge Semin 写道:
> > Hi Yanteng
> >
> > On Mon, Feb 19, 2024 at 07:02:24PM +0800, Yanteng Si wrote:
> >> Hi Serge
> >>
> >> 在 2024/2/5 07:28, Serge Semin 写道:
> >>> On Tue, Jan 30, 2024 at 04:43:21PM +0800, Yanteng Si wrote:
> >>>> DW GMAC v3.x multi-channels feature is implemented as multiple
> >>>> sets of the same CSRs. Here is only preliminary support, it will
> >>>> be useful for the driver further evolution and for the users
> >>>> having multi-channel DWGMAC v3.x devices.
> >>>>
> >>>> Signed-off-by: Yanteng Si<siyanteng@loongson.cn>
> >>>> Signed-off-by: Feiyang Chen<chenfeiyang@loongson.cn>
> >>>> Signed-off-by: Yinggang Gu<guyinggang@loongson.cn>
> >>>> ---
> >>>>    .../net/ethernet/stmicro/stmmac/dwmac-sun8i.c |  2 +-
> >>>>    .../ethernet/stmicro/stmmac/dwmac1000_dma.c   | 36 ++++++++++---------
> >>>>    .../net/ethernet/stmicro/stmmac/dwmac_dma.h   | 19 +++++++++-
> >>>>    .../net/ethernet/stmicro/stmmac/dwmac_lib.c   | 32 ++++++++---------
> >>>>    drivers/net/ethernet/stmicro/stmmac/hwif.h    |  2 +-
> >>>>    .../net/ethernet/stmicro/stmmac/stmmac_main.c |  6 ++--
> >>>>    6 files changed, 58 insertions(+), 39 deletions(-)
> >>>>
> >>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
> >>>> index 137741b94122..7cdfa0bdb93a 100644
> >>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
> >>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
> >>>> @@ -395,7 +395,7 @@ static void sun8i_dwmac_dma_start_tx(struct stmmac_priv *priv,
> >>>>    	writel(v, ioaddr + EMAC_TX_CTL1);
> >>>>    }
> >>>> -static void sun8i_dwmac_enable_dma_transmission(void __iomem *ioaddr)
> >>>> +static void sun8i_dwmac_enable_dma_transmission(void __iomem *ioaddr, u32 chan)
> >>>>    {
> >>>>    	u32 v;
> >>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> >>>> index daf79cdbd3ec..5f7b82ad3ec2 100644
> >>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> >>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> >>>> @@ -70,15 +70,18 @@ static void dwmac1000_dma_axi(void __iomem *ioaddr, struct stmmac_axi *axi)
> >>>>    	writel(value, ioaddr + DMA_AXI_BUS_MODE);
> >>>>    }
> >>>> -static void dwmac1000_dma_init(void __iomem *ioaddr,
> >>>> -			       struct stmmac_dma_cfg *dma_cfg, int atds)
> >>>> +static void dwmac1000_dma_init_channel(struct stmmac_priv *priv,
> >>>> +				       void __iomem *ioaddr,
> >>>> +				       struct stmmac_dma_cfg *dma_cfg, u32 chan)
> >>>>    {
> >>>> -	u32 value = readl(ioaddr + DMA_BUS_MODE);
> >>>> +	u32 value;
> >>>>    	int txpbl = dma_cfg->txpbl ?: dma_cfg->pbl;
> >>>>    	int rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl;
> >>> Reverse xmas tree please.
> >>>
> >>>> -	/*
> >>>> -	 * Set the DMA PBL (Programmable Burst Length) mode.
> >>>> +	/* common channel control register config */
> >>> Redundant comment. Please drop.
> >>>
> >>>> +	value = readl(ioaddr + DMA_CHAN_BUS_MODE(chan));
> >>>> +
> >>>> +	/* Set the DMA PBL (Programmable Burst Length) mode.
> >>>>    	 *
> >>>>    	 * Note: before stmmac core 3.50 this mode bit was 4xPBL, and
> >>>>    	 * post 3.5 mode bit acts as 8*PBL.
> >>>> @@ -98,16 +101,15 @@ static void dwmac1000_dma_init(void __iomem *ioaddr,
> >>>>    	if (dma_cfg->mixed_burst)
> >>>>    		value |= DMA_BUS_MODE_MB;
> >>>> -	if (atds)
> >>>> -		value |= DMA_BUS_MODE_ATDS;
> >>>> +	value |= DMA_BUS_MODE_ATDS;
> >>> No, just convert the stmmac_dma_ops.dma_init_channel() to accepting
> >>> the atds flag as I suggested in v7:
> >>> https://lore.kernel.org/netdev/vxcfrxtbfu4pya56m22icnizsyjzqqha5blzb7zpexqcur56uh@uv6vsjf77npa/
> >>>
> >>> In order to simplify this patch you can provide the
> >>> stmmac_dma_ops.dma_init_channel() and
> >>> stmmac_dma_ops.enable_dma_transmission() prototype updates in a
> >>> pre-requisite/preparation patch.
> >> Sorry to keep you waiting for so long, I finally got the machine again.
> >> Regarding atds, is this how it is implemented?
> >>
> >> On the basis of applying PATCH v8:
> >>
> >> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> >> b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> >> index 0323f0a5049c..ce99f4a1b320 100644
> >> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> >> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> >> @@ -72,7 +72,8 @@ static void dwmac1000_dma_axi(void __iomem *ioaddr, struct
> >> stmmac_axi *axi)
> >>
> >>   static void dwmac1000_dma_init_channel(struct stmmac_priv *priv,
> >>                          void __iomem *ioaddr,
> >> -                       struct stmmac_dma_cfg *dma_cfg, u32 chan)
> >> +                       struct stmmac_dma_cfg *dma_cfg,
> >> +                       int atds, u32 chan)
> >>   {
> >>       u32 value;
> >>       int txpbl = dma_cfg->txpbl ?: dma_cfg->pbl;
> >> @@ -101,7 +102,8 @@ static void dwmac1000_dma_init_channel(struct
> >> stmmac_priv *priv,
> >>       if (dma_cfg->mixed_burst)
> >>           value |= DMA_BUS_MODE_MB;
> >>
> >> -    value |= DMA_BUS_MODE_ATDS;
> >> +    if (atds)
> >> +        value |= DMA_BUS_MODE_ATDS;
> >>
> >>       if (dma_cfg->aal)
> >>           value |= DMA_BUS_MODE_AAL;
> >> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
> >> b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
> >> index 84d3a8551b03..8a79c154b553 100644
> >> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
> >> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
> >> @@ -117,7 +117,8 @@ static void dwmac4_dma_init_tx_chan(struct stmmac_priv
> >> *priv,
> >>
> >>   static void dwmac4_dma_init_channel(struct stmmac_priv *priv,
> >>                       void __iomem *ioaddr,
> >> -                    struct stmmac_dma_cfg *dma_cfg, u32 chan)
> >> +                    struct stmmac_dma_cfg *dma_cfg,
> >> +                                    int atds, u32 chan)
> >>   {
> >>       const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;
> >>       u32 value;
> >> @@ -135,7 +136,8 @@ static void dwmac4_dma_init_channel(struct stmmac_priv
> >> *priv,
> >>
> >>   static void dwmac410_dma_init_channel(struct stmmac_priv *priv,
> >>                         void __iomem *ioaddr,
> >> -                      struct stmmac_dma_cfg *dma_cfg, u32 chan)
> >> +                      struct stmmac_dma_cfg *dma_cfg,
> >> +                                      int atds, u32 chan)
> >>   {
> >>       const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;
> >>       u32 value;
> >> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
> >> b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
> >> index dd2ab6185c40..d1627b2e50c8 100644
> >> --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
> >> +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
> >> @@ -35,7 +35,8 @@ static void dwxgmac2_dma_init(void __iomem *ioaddr,
> >>
> >>   static void dwxgmac2_dma_init_chan(struct stmmac_priv *priv,
> >>                      void __iomem *ioaddr,
> >> -                   struct stmmac_dma_cfg *dma_cfg, u32 chan)
> >> +                   struct stmmac_dma_cfg *dma_cfg,
> >> +                                   int atds, u32 chan)
> >>   {
> >>       u32 value = readl(ioaddr + XGMAC_DMA_CH_CONTROL(chan));
> >>
> >> diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h
> >> b/drivers/net/ethernet/stmicro/stmmac/hwif.h
> >> index b0db38396171..fb27ad0e97e8 100644
> >> --- a/drivers/net/ethernet/stmicro/stmmac/hwif.h
> >> +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h
> >> @@ -178,7 +178,7 @@ struct stmmac_dma_ops {
> >>       void (*init)(void __iomem *ioaddr, struct stmmac_dma_cfg *dma_cfg,
> >>                int atds);
> >>       void (*init_chan)(struct stmmac_priv *priv, void __iomem *ioaddr,
> >> -              struct stmmac_dma_cfg *dma_cfg, u32 chan);
> >> +              struct stmmac_dma_cfg *dma_cfg, int atds, u32 chan);
> >>       void (*init_rx_chan)(struct stmmac_priv *priv, void __iomem *ioaddr,
> >>                    struct stmmac_dma_cfg *dma_cfg,
> >>                    dma_addr_t phy, u32 chan);
> >> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> >> b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> >> index 3eed202d1f1c..8705e04913d1 100644
> >> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> >> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> >> @@ -3039,7 +3039,7 @@ static int stmmac_init_dma_engine(struct stmmac_priv
> >> *priv)
> >>
> >>       /* DMA CSR Channel configuration */
> >>       for (chan = 0; chan < dma_csr_ch; chan++) {
> >> -        stmmac_init_chan(priv, priv->ioaddr, priv->plat->dma_cfg, chan);
> >> +        stmmac_init_chan(priv, priv->ioaddr, priv->plat->dma_cfg, atds,
> >> chan);
> >>           stmmac_disable_dma_irq(priv, priv->ioaddr, chan, 1, 1);
> >>       }
> >>
> >> @@ -6963,6 +6963,7 @@ int stmmac_xdp_open(struct net_device *dev)
> >>       u32 buf_size;
> >>       bool sph_en;
> >>       u32 chan;
> >> +     int atds;
> >>       int ret;
> >>
> >>       ret = alloc_dma_desc_resources(priv, &priv->dma_conf);
> >> @@ -6981,9 +6982,12 @@ int stmmac_xdp_open(struct net_device *dev)
> >>
> >>       stmmac_reset_queues_param(priv);
> >>
> >> +    if (priv->extend_desc && (priv->mode == STMMAC_RING_MODE))
> >> +        atds = 1;
> >> +
> >>       /* DMA CSR Channel configuration */
> >>       for (chan = 0; chan < dma_csr_ch; chan++) {
> >> -        stmmac_init_chan(priv, priv->ioaddr, priv->plat->dma_cfg, chan);
> >> +        stmmac_init_chan(priv, priv->ioaddr, priv->plat->dma_cfg, atds,
> >> chan);
> >>           stmmac_disable_dma_irq(priv, priv->ioaddr, chan, 1, 1);
> >>       }
> > Looking more thoroughly at this part I suggest to act a bit
> > differently. Let's move the atds flag to the stmmac_dma_cfg structure.
> > Alternate Descriptor Size (ATDS) is a part of the DMA-configs together
> > with the PBL, ALL, AEME, etc so the structure is the most suitable
> > place for it. Here is what should be done for that:
> > 1. Add stmmac_dma_cfg::atds boolean field.
> > 2. Drop atds argument from the stmmac_dma_ops::init() callback and use
> > the stmmac_dma_cfg::atds field in the callback implementations.
> > 3. Alter stmmac_init_dma_engine() to updating the dma_cfg->atds field
> > instead of the local variable.
> >
> > Please implement that update in a pre-requisite/preparation patch.
> >
> > After that you can freely use the stmmac_dma_cfg::atds field in the
> > stmmac_init_chan() method too.
>
> OK.
>
>
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> index b57e1325ce62..dabd6a3772f2 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> @@ -66,8 +66,7 @@ struct loongson_data {
>
>    static void loongson_gnet_dma_init_channel(struct stmmac_priv *priv,
>                         void __iomem *ioaddr,
> -                     struct stmmac_dma_cfg *dma_cfg,
> -                                     int atds, u32 chan)
> +                     struct stmmac_dma_cfg *dma_cfg, u32 chan)
>    {
>        int txpbl = dma_cfg->txpbl ?: dma_cfg->pbl;
>        int rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl;
> @@ -96,7 +95,7 @@ static void loongson_gnet_dma_init_channel(struct stmmac_priv
> *priv,
>        if (dma_cfg->mixed_burst)
>            value |= DMA_BUS_MODE_MB;
>
> -    if (atds)
> +    if (dma_cfg->atds)
>            value |= DMA_BUS_MODE_ATDS;
>
>        if (dma_cfg->aal)
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
> b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
> index 7001a86425ea..ae9240736e64 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
> @@ -299,7 +299,7 @@ static int sun8i_dwmac_dma_reset(void __iomem *ioaddr)
>     * Called from stmmac via stmmac_dma_ops->init
>     */
>    static void sun8i_dwmac_dma_init(void __iomem *ioaddr,
> -                 struct stmmac_dma_cfg *dma_cfg, int atds)
> +                 struct stmmac_dma_cfg *dma_cfg)
>    {
>        writel(EMAC_RX_INT | EMAC_TX_INT, ioaddr + EMAC_INT_EN);
>        writel(0x1FFFFFF, ioaddr + EMAC_INT_STA);
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> index fd5ecc043251..66c0c22908b1 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> @@ -72,8 +72,7 @@ static void dwmac1000_dma_axi(void __iomem *ioaddr, struct
> stmmac_axi *axi)
>
>    static void dwmac1000_dma_init_channel(struct stmmac_priv *priv,
>                           void __iomem *ioaddr,
> -                       struct stmmac_dma_cfg *dma_cfg,
> -                       int atds, u32 chan)
> +                       struct stmmac_dma_cfg *dma_cfg, u32 chan)
>    {
>        int txpbl = dma_cfg->txpbl ?: dma_cfg->pbl;
>        int rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl;
> @@ -101,7 +100,7 @@ static void dwmac1000_dma_init_channel(struct stmmac_priv *priv,
>        if (dma_cfg->mixed_burst)
>            value |= DMA_BUS_MODE_MB;
>
> -    if (atds)
> +    if (dma_cfg->atds)
>            value |= DMA_BUS_MODE_ATDS;
>
>        if (dma_cfg->aal)
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
> b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
> index dea270f60cc3..f861babc06f9 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
> @@ -19,7 +19,7 @@
>    #include "dwmac_dma.h"
>
>    static void dwmac100_dma_init(void __iomem *ioaddr,
> -                  struct stmmac_dma_cfg *dma_cfg, int atds)
> +                  struct stmmac_dma_cfg *dma_cfg)
>    {
>        /* Enable Application Access by writing to DMA CSR0 */
>        writel(DMA_BUS_MODE_DEFAULT | (dma_cfg->pbl << DMA_BUS_MODE_PBL_SHIFT),
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
> b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
> index 8a79c154b553..e0165358c4ac 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
> @@ -117,8 +117,7 @@ static void dwmac4_dma_init_tx_chan(struct stmmac_priv *priv,
>
>    static void dwmac4_dma_init_channel(struct stmmac_priv *priv,
>                        void __iomem *ioaddr,
> -                    struct stmmac_dma_cfg *dma_cfg,
> -                                    int atds, u32 chan)
> +                    struct stmmac_dma_cfg *dma_cfg, u32 chan)
>    {
>        const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;
>        u32 value;
> @@ -136,8 +135,7 @@ static void dwmac4_dma_init_channel(struct stmmac_priv *priv,
>
>    static void dwmac410_dma_init_channel(struct stmmac_priv *priv,
>                          void __iomem *ioaddr,
> -                      struct stmmac_dma_cfg *dma_cfg,
> -                                      int atds, u32 chan)
> +                      struct stmmac_dma_cfg *dma_cfg, u32 chan)
>    {
>        const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;
>        u32 value;
> @@ -155,7 +153,7 @@ static void dwmac410_dma_init_channel(struct stmmac_priv *priv,
>    }
>
>    static void dwmac4_dma_init(void __iomem *ioaddr,
> -                struct stmmac_dma_cfg *dma_cfg, int atds)
> +                struct stmmac_dma_cfg *dma_cfg)
>    {
>        u32 value = readl(ioaddr + DMA_SYS_BUS_MODE);
>
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
> b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
> index d1627b2e50c8..7840bc403788 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
> @@ -20,7 +20,7 @@ static int dwxgmac2_dma_reset(void __iomem *ioaddr)
>    }
>
>    static void dwxgmac2_dma_init(void __iomem *ioaddr,
> -                  struct stmmac_dma_cfg *dma_cfg, int atds)
> +                  struct stmmac_dma_cfg *dma_cfg)
>    {
>        u32 value = readl(ioaddr + XGMAC_DMA_SYSBUS_MODE);
>
> @@ -35,8 +35,7 @@ static void dwxgmac2_dma_init(void __iomem *ioaddr,
>
>    static void dwxgmac2_dma_init_chan(struct stmmac_priv *priv,
>                       void __iomem *ioaddr,
> -                   struct stmmac_dma_cfg *dma_cfg,
> -                                   int atds, u32 chan)
> +                   struct stmmac_dma_cfg *dma_cfg, u32 chan)
>    {
>        u32 value = readl(ioaddr + XGMAC_DMA_CH_CONTROL(chan));
>
> diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h
> b/drivers/net/ethernet/stmicro/stmmac/hwif.h
> index fb27ad0e97e8..3b20fb7f3a61 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/hwif.h
> +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h
> @@ -175,10 +175,9 @@ struct dma_features;
>    struct stmmac_dma_ops {
>        /* DMA core initialization */
>        int (*reset)(void __iomem *ioaddr);
> -    void (*init)(void __iomem *ioaddr, struct stmmac_dma_cfg *dma_cfg,
> -             int atds);
> +    void (*init)(void __iomem *ioaddr, struct stmmac_dma_cfg *dma_cfg);
>        void (*init_chan)(struct stmmac_priv *priv, void __iomem *ioaddr,
> -              struct stmmac_dma_cfg *dma_cfg, int atds, u32 chan);
> +              struct stmmac_dma_cfg *dma_cfg, u32 chan);
>        void (*init_rx_chan)(struct stmmac_priv *priv, void __iomem *ioaddr,
>                     struct stmmac_dma_cfg *dma_cfg,
>                     dma_addr_t phy, u32 chan);
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> index 7c656f970575..957dfabc663d 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> @@ -3013,7 +3013,6 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv)
>        struct stmmac_rx_queue *rx_q;
>        struct stmmac_tx_queue *tx_q;
>        u32 chan = 0;
> -    int atds = 0;
>        int ret = 0;
>
>        if (!priv->plat->dma_cfg || !priv->plat->dma_cfg->pbl) {
> @@ -3022,7 +3021,7 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv)
>        }
>
>        if (priv->extend_desc && (priv->mode == STMMAC_RING_MODE))
> -        atds = 1;
> +        priv->plat->dma_cfg->atds = 1;
>
>        ret = stmmac_reset(priv, priv->ioaddr);
>        if (ret) {
> @@ -3031,14 +3030,14 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv)
>        }
>
>        /* DMA Configuration */
> -    stmmac_dma_init(priv, priv->ioaddr, priv->plat->dma_cfg, atds);
> +    stmmac_dma_init(priv, priv->ioaddr, priv->plat->dma_cfg);
>
>        if (priv->plat->axi)
>            stmmac_axi(priv, priv->ioaddr, priv->plat->axi);
>
>        /* DMA CSR Channel configuration */
>        for (chan = 0; chan < dma_csr_ch; chan++) {
> -        stmmac_init_chan(priv, priv->ioaddr, priv->plat->dma_cfg, atds, chan);
> +        stmmac_init_chan(priv, priv->ioaddr, priv->plat->dma_cfg, chan);
>            stmmac_disable_dma_irq(priv, priv->ioaddr, chan, 1, 1);
>        }
>
> @@ -6962,7 +6961,6 @@ int stmmac_xdp_open(struct net_device *dev)
>        u32 buf_size;
>        bool sph_en;
>        u32 chan;
> -        int atds;
>        int ret;
>
>        ret = alloc_dma_desc_resources(priv, &priv->dma_conf);
> @@ -6981,12 +6979,9 @@ int stmmac_xdp_open(struct net_device *dev)
>
>        stmmac_reset_queues_param(priv);
>
> -    if (priv->extend_desc && (priv->mode == STMMAC_RING_MODE))
> -        atds = 1;
> -
>        /* DMA CSR Channel configuration */
>        for (chan = 0; chan < dma_csr_ch; chan++) {
> -        stmmac_init_chan(priv, priv->ioaddr, priv->plat->dma_cfg, atds, chan);
> +        stmmac_init_chan(priv, priv->ioaddr, priv->plat->dma_cfg, chan);
>            stmmac_disable_dma_irq(priv, priv->ioaddr, chan, 1, 1);
>        }
>
> diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
> index 23bfe3c1465f..c827dc1213b9 100644
> --- a/include/linux/stmmac.h
> +++ b/include/linux/stmmac.h
> @@ -100,6 +100,7 @@ struct stmmac_dma_cfg {
>        bool eame;
>        bool multi_msi_en;
>        bool dche;
> +    bool atds;
>    };
>
>    #define AXI_BLEN    7
>
>
> Thanks,
>
> Yanteng
>
> >
> > -Serge(y)
> >
> >>
> >> Thanks,
> >>
> >> Yanteng
> >>
> >>>>    	if (dma_cfg->aal)
> >>>>    		value |= DMA_BUS_MODE_AAL;
> >>>> -	writel(value, ioaddr + DMA_BUS_MODE);
> >>>> +	writel(value, ioaddr + DMA_CHAN_BUS_MODE(chan));
> >>>>    	/* Mask interrupts by writing to CSR7 */
> >>>> -	writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_INTR_ENA);
> >>>> +	writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_CHAN_INTR_ENA(chan));
> >>>>    }
> >>>>    static void dwmac1000_dma_init_rx(struct stmmac_priv *priv,
> >>>> @@ -116,7 +118,7 @@ static void dwmac1000_dma_init_rx(struct stmmac_priv *priv,
> >>>>    				  dma_addr_t dma_rx_phy, u32 chan)
> >>>>    {
> >>>>    	/* RX descriptor base address list must be written into DMA CSR3 */
> >>>> -	writel(lower_32_bits(dma_rx_phy), ioaddr + DMA_RCV_BASE_ADDR);
> >>>> +	writel(lower_32_bits(dma_rx_phy), ioaddr + DMA_CHAN_RCV_BASE_ADDR(chan));
> >>>>    }
> >>>>    static void dwmac1000_dma_init_tx(struct stmmac_priv *priv,
> >>>> @@ -125,7 +127,7 @@ static void dwmac1000_dma_init_tx(struct stmmac_priv *priv,
> >>>>    				  dma_addr_t dma_tx_phy, u32 chan)
> >>>>    {
> >>>>    	/* TX descriptor base address list must be written into DMA CSR4 */
> >>>> -	writel(lower_32_bits(dma_tx_phy), ioaddr + DMA_TX_BASE_ADDR);
> >>>> +	writel(lower_32_bits(dma_tx_phy), ioaddr + DMA_CHAN_TX_BASE_ADDR(chan));
> >>>>    }
> >>>>    static u32 dwmac1000_configure_fc(u32 csr6, int rxfifosz)
> >>>> @@ -153,7 +155,7 @@ static void dwmac1000_dma_operation_mode_rx(struct stmmac_priv *priv,
> >>>>    					    void __iomem *ioaddr, int mode,
> >>>>    					    u32 channel, int fifosz, u8 qmode)
> >>>>    {
> >>>> -	u32 csr6 = readl(ioaddr + DMA_CONTROL);
> >>>> +	u32 csr6 = readl(ioaddr + DMA_CHAN_CONTROL(channel));
> >>>>    	if (mode == SF_DMA_MODE) {
> >>>>    		pr_debug("GMAC: enable RX store and forward mode\n");
> >>>> @@ -175,14 +177,14 @@ static void dwmac1000_dma_operation_mode_rx(struct stmmac_priv *priv,
> >>>>    	/* Configure flow control based on rx fifo size */
> >>>>    	csr6 = dwmac1000_configure_fc(csr6, fifosz);
> >>>> -	writel(csr6, ioaddr + DMA_CONTROL);
> >>>> +	writel(csr6, ioaddr + DMA_CHAN_CONTROL(channel));
> >>>>    }
> >>>>    static void dwmac1000_dma_operation_mode_tx(struct stmmac_priv *priv,
> >>>>    					    void __iomem *ioaddr, int mode,
> >>>>    					    u32 channel, int fifosz, u8 qmode)
> >>>>    {
> >>>> -	u32 csr6 = readl(ioaddr + DMA_CONTROL);
> >>>> +	u32 csr6 = readl(ioaddr + DMA_CHAN_CONTROL(channel));
> >>>>    	if (mode == SF_DMA_MODE) {
> >>>>    		pr_debug("GMAC: enable TX store and forward mode\n");
> >>>> @@ -209,7 +211,7 @@ static void dwmac1000_dma_operation_mode_tx(struct stmmac_priv *priv,
> >>>>    			csr6 |= DMA_CONTROL_TTC_256;
> >>>>    	}
> >>>> -	writel(csr6, ioaddr + DMA_CONTROL);
> >>>> +	writel(csr6, ioaddr + DMA_CHAN_CONTROL(channel));
> >>>>    }
> >>>>    static void dwmac1000_dump_dma_regs(struct stmmac_priv *priv,
> >>>> @@ -271,12 +273,12 @@ static int dwmac1000_get_hw_feature(void __iomem *ioaddr,
> >>>>    static void dwmac1000_rx_watchdog(struct stmmac_priv *priv,
> >>>>    				  void __iomem *ioaddr, u32 riwt, u32 queue)
> >>>>    {
> >>>> -	writel(riwt, ioaddr + DMA_RX_WATCHDOG);
> >>>> +	writel(riwt, ioaddr + DMA_CHAN_RX_WATCHDOG(queue));
> >>>>    }
> >>>>    const struct stmmac_dma_ops dwmac1000_dma_ops = {
> >>>>    	.reset = dwmac_dma_reset,
> >>>> -	.init = dwmac1000_dma_init,
> >>>> +	.init_chan = dwmac1000_dma_init_channel,
> >>>>    	.init_rx_chan = dwmac1000_dma_init_rx,
> >>>>    	.init_tx_chan = dwmac1000_dma_init_tx,
> >>>>    	.axi = dwmac1000_dma_axi,
> >>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
> >>>> index 72672391675f..593be79c46e1 100644
> >>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
> >>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
> >>>> @@ -148,11 +148,14 @@
> >>>>    					 DMA_STATUS_TI | \
> >>>>    					 DMA_STATUS_MSK_COMMON)
> >>>> +/* Following DMA defines are chanels oriented */    \
> >>>> +#define DMA_CHAN_OFFSET			0x100   |-------------+
> >>>> +                                                    /              |
> >>>                                                                         |
> >>> Please move all of these ---------------------------------------------+-------------------------+
> >>> to being defined just below the DMA_MISSED_FRAME_CTR macros definition.                         |
> >>> The point is to keep a coherency between dwmac_dma.h and dwmac4_dma.h.                          |
> >>> The later header file has first generic DMA-related macros defined                              |
> >>> (CSR addresses and flags) and then the channel-specific ones (CSR                               |
> >>> addresses and flags). Since in case of the DW GMAC v3.x the                                     |
> >>> multi-channels are implemented as a copy of all the DMA CSRs let's                              |
> >>> preserve the logic of having all CSR address defined first, then the                            |
> >>> CSR flags.                                                                                      |
> >>>                                                                                                   |
> >>>>    #define NUM_DWMAC100_DMA_REGS	9                                                       |
> >>>>    #define NUM_DWMAC1000_DMA_REGS	23                                                      |
> >>>>    #define NUM_DWMAC4_DMA_REGS	27                                                              |
> >>>>                                                                                                 |
> >>>> -void dwmac_enable_dma_transmission(void __iomem *ioaddr);                                    |
> >>>> +void dwmac_enable_dma_transmission(void __iomem *ioaddr, u32 chan);                          |
> >>>>    void dwmac_enable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr,                    |
> >>>>    			  u32 chan, bool rx, bool tx);                                          |
> >>>>    void dwmac_disable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr,                   |
> >>>> @@ -169,4 +172,18 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,  |
> >>>>    			struct stmmac_extra_stats *x, u32 chan, u32 dir);                       |
> >>>>    int dwmac_dma_reset(void __iomem *ioaddr);                                                   |
> >>>>                                                                                                 |
> >>>                                                                                                   |
> >>>> +static inline u32 dma_chan_base_addr(u32 base, u32 chan)                                  \  |
> >>>> +{                                                                                          | |
> >>>> +	return base + chan * DMA_CHAN_OFFSET;                                                 | |
> >>>> +}                                                                                          | |
> >>>> +                                                                                           | |
> >>>> +#define DMA_CHAN_XMT_POLL_DEMAND(chan)	dma_chan_base_addr(DMA_XMT_POLL_DEMAND, chan) | |
> >>>> +#define DMA_CHAN_INTR_ENA(chan)		dma_chan_base_addr(DMA_INTR_ENA, chan)        | |
> >>>> +#define DMA_CHAN_CONTROL(chan)		dma_chan_base_addr(DMA_CONTROL, chan)         | |
> >>>> +#define DMA_CHAN_STATUS(chan)		dma_chan_base_addr(DMA_STATUS, chan)          |-+
> >>>> +#define DMA_CHAN_BUS_MODE(chan)		dma_chan_base_addr(DMA_BUS_MODE, chan)        |
> >>>> +#define DMA_CHAN_RCV_BASE_ADDR(chan)	dma_chan_base_addr(DMA_RCV_BASE_ADDR, chan)           |
> >>>> +#define DMA_CHAN_TX_BASE_ADDR(chan)	dma_chan_base_addr(DMA_TX_BASE_ADDR, chan)            |
> >>>> +#define DMA_CHAN_RX_WATCHDOG(chan)	dma_chan_base_addr(DMA_RX_WATCHDOG, chan)             |
> >>>> +                                                                                           /
> >>>>    #endif /* __DWMAC_DMA_H__ */
> >>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
> >>>> index 7907d62d3437..b37368137810 100644
> >>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
> >>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
> >>>> @@ -28,65 +28,65 @@ int dwmac_dma_reset(void __iomem *ioaddr)
> >>>>    }
> >>>>    /* CSR1 enables the transmit DMA to check for new descriptor */
> >>>> -void dwmac_enable_dma_transmission(void __iomem *ioaddr)
> >>>> +void dwmac_enable_dma_transmission(void __iomem *ioaddr, u32 chan)
> >>>>    {
> >>>> -	writel(1, ioaddr + DMA_XMT_POLL_DEMAND);
> >>>> +	writel(1, ioaddr + DMA_CHAN_XMT_POLL_DEMAND(chan));
> >>>>    }
> >>>>    void dwmac_enable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr,
> >>>>    			  u32 chan, bool rx, bool tx)
> >>>>    {
> >>>> -	u32 value = readl(ioaddr + DMA_INTR_ENA);
> >>>> +	u32 value = readl(ioaddr + DMA_CHAN_INTR_ENA(chan));
> >>>>    	if (rx)
> >>>>    		value |= DMA_INTR_DEFAULT_RX;
> >>>>    	if (tx)
> >>>>    		value |= DMA_INTR_DEFAULT_TX;
> >>>> -	writel(value, ioaddr + DMA_INTR_ENA);
> >>>> +	writel(value, ioaddr + DMA_CHAN_INTR_ENA(chan));
> >>>>    }
> >>>>    void dwmac_disable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr,
> >>>>    			   u32 chan, bool rx, bool tx)
> >>>>    {
> >>>> -	u32 value = readl(ioaddr + DMA_INTR_ENA);
> >>>> +	u32 value = readl(ioaddr + DMA_CHAN_INTR_ENA(chan));
> >>>>    	if (rx)
> >>>>    		value &= ~DMA_INTR_DEFAULT_RX;
> >>>>    	if (tx)
> >>>>    		value &= ~DMA_INTR_DEFAULT_TX;
> >>>> -	writel(value, ioaddr + DMA_INTR_ENA);
> >>>> +	writel(value, ioaddr + DMA_CHAN_INTR_ENA(chan));
> >>>>    }
> >>>>    void dwmac_dma_start_tx(struct stmmac_priv *priv, void __iomem *ioaddr,
> >>>>    			u32 chan)
> >>>>    {
> >>>> -	u32 value = readl(ioaddr + DMA_CONTROL);
> >>>> +	u32 value = readl(ioaddr + DMA_CHAN_CONTROL(chan));
> >>>>    	value |= DMA_CONTROL_ST;
> >>>> -	writel(value, ioaddr + DMA_CONTROL);
> >>>> +	writel(value, ioaddr + DMA_CHAN_CONTROL(chan));
> >>>>    }
> >>>>    void dwmac_dma_stop_tx(struct stmmac_priv *priv, void __iomem *ioaddr, u32 chan)
> >>>>    {
> >>>> -	u32 value = readl(ioaddr + DMA_CONTROL);
> >>>> +	u32 value = readl(ioaddr + DMA_CHAN_CONTROL(chan));
> >>>>    	value &= ~DMA_CONTROL_ST;
> >>>> -	writel(value, ioaddr + DMA_CONTROL);
> >>>> +	writel(value, ioaddr + DMA_CHAN_CONTROL(chan));
> >>>>    }
> >>>>    void dwmac_dma_start_rx(struct stmmac_priv *priv, void __iomem *ioaddr,
> >>>>    			u32 chan)
> >>>>    {
> >>>> -	u32 value = readl(ioaddr + DMA_CONTROL);
> >>>> +	u32 value = readl(ioaddr + DMA_CHAN_CONTROL(chan));
> >>>>    	value |= DMA_CONTROL_SR;
> >>>> -	writel(value, ioaddr + DMA_CONTROL);
> >>>> +	writel(value, ioaddr + DMA_CHAN_CONTROL(chan));
> >>>>    }
> >>>>    void dwmac_dma_stop_rx(struct stmmac_priv *priv, void __iomem *ioaddr, u32 chan)
> >>>>    {
> >>>> -	u32 value = readl(ioaddr + DMA_CONTROL);
> >>>> +	u32 value = readl(ioaddr + DMA_CHAN_CONTROL(chan));
> >>>>    	value &= ~DMA_CONTROL_SR;
> >>>> -	writel(value, ioaddr + DMA_CONTROL);
> >>>> +	writel(value, ioaddr + DMA_CHAN_CONTROL(chan));
> >>>>    }
> >>>>    #ifdef DWMAC_DMA_DEBUG
> >>>> @@ -166,7 +166,7 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
> >>>>    	struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[chan];
> >>>>    	int ret = 0;
> >>>>    	/* read the status register (CSR5) */
> >>>> -	u32 intr_status = readl(ioaddr + DMA_STATUS);
> >>>> +	u32 intr_status = readl(ioaddr + DMA_CHAN_STATUS(chan));
> >>>>    #ifdef DWMAC_DMA_DEBUG
> >>>>    	/* Enable it to monitor DMA rx/tx status in case of critical problems */
> >>>> @@ -236,7 +236,7 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
> >>>>    		pr_warn("%s: unexpected status %08x\n", __func__, intr_status);
> >>>>    	/* Clear the interrupt by writing a logic 1 to the CSR5[15-0] */
> >>>> -	writel((intr_status & 0x1ffff), ioaddr + DMA_STATUS);
> >>>> +	writel((intr_status & 0x7ffff), ioaddr + DMA_CHAN_STATUS(chan));
> >>> Isn't the mask change going to be implemented in the framework of the
> >>> Loongson-specific DMA-interrupt handler in some of the further patches?
> >>>
> >>>
> >>> I'll get back to reviewing the series tomorrow (later today)...
> >>>
> >>> -Serge(y)
> >>>
> >>>>    	return ret;
> >>>>    }
> >>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h
> >>>> index 7be04b54738b..b0db38396171 100644
> >>>> --- a/drivers/net/ethernet/stmicro/stmmac/hwif.h
> >>>> +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h
> >>>> @@ -198,7 +198,7 @@ struct stmmac_dma_ops {
> >>>>    	/* To track extra statistic (if supported) */
> >>>>    	void (*dma_diagnostic_fr)(struct stmmac_extra_stats *x,
> >>>>    				  void __iomem *ioaddr);
> >>>> -	void (*enable_dma_transmission) (void __iomem *ioaddr);
> >>>> +	void (*enable_dma_transmission)(void __iomem *ioaddr, u32 chan);
> >>>>    	void (*enable_dma_irq)(struct stmmac_priv *priv, void __iomem *ioaddr,
> >>>>    			       u32 chan, bool rx, bool tx);
> >>>>    	void (*disable_dma_irq)(struct stmmac_priv *priv, void __iomem *ioaddr,
> >>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> >>>> index b334eb16da23..5617b40abbe4 100644
> >>>> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> >>>> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> >>>> @@ -2558,7 +2558,7 @@ static bool stmmac_xdp_xmit_zc(struct stmmac_priv *priv, u32 queue, u32 budget)
> >>>>    				       true, priv->mode, true, true,
> >>>>    				       xdp_desc.len);
> >>>> -		stmmac_enable_dma_transmission(priv, priv->ioaddr);
> >>>> +		stmmac_enable_dma_transmission(priv, priv->ioaddr, queue);
> >>>>    		xsk_tx_metadata_to_compl(meta,
> >>>>    					 &tx_q->tx_skbuff_dma[entry].xsk_meta);
> >>>> @@ -4706,7 +4706,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
> >>>>    	netdev_tx_sent_queue(netdev_get_tx_queue(dev, queue), skb->len);
> >>>> -	stmmac_enable_dma_transmission(priv, priv->ioaddr);
> >>>> +	stmmac_enable_dma_transmission(priv, priv->ioaddr, queue);
> >>>>    	stmmac_flush_tx_descriptors(priv, queue);
> >>>>    	stmmac_tx_timer_arm(priv, queue);
> >>>> @@ -4926,7 +4926,7 @@ static int stmmac_xdp_xmit_xdpf(struct stmmac_priv *priv, int queue,
> >>>>    		u64_stats_update_end_irqrestore(&txq_stats->syncp, flags);
> >>>>    	}
> >>>> -	stmmac_enable_dma_transmission(priv, priv->ioaddr);
> >>>> +	stmmac_enable_dma_transmission(priv, priv->ioaddr, queue);
> >>>>    	entry = STMMAC_GET_ENTRY(entry, priv->dma_conf.dma_tx_size);
> >>>>    	tx_q->cur_tx = entry;
> >>>> -- 
> >>>> 2.31.4
> >>>>


^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 09/11] net: stmmac: dwmac-loongson: Fix half duplex
  2024-02-05 22:06     ` Serge Semin
@ 2024-03-13  9:24       ` Yanteng Si
  2024-03-13 10:21         ` Russell King (Oracle)
  0 siblings, 1 reply; 97+ messages in thread
From: Yanteng Si @ 2024-03-13  9:24 UTC (permalink / raw)
  To: Serge Semin
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang


在 2024/2/6 06:06, Serge Semin 写道:
> On Tue, Feb 06, 2024 at 12:58:17AM +0300, Serge Semin wrote:
>> On Tue, Jan 30, 2024 at 04:49:14PM +0800, Yanteng Si wrote:
>>> Current GNET does not support half duplex mode.
>>>
>>> Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
>>> Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
>>> Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
>>> ---
>>>   drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c | 11 ++++++++++-
>>>   drivers/net/ethernet/stmicro/stmmac/stmmac_main.c    |  3 ++-
>>>   include/linux/stmmac.h                               |  1 +
>>>   3 files changed, 13 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>> index 264c4c198d5a..1753a3c46b77 100644
>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>> @@ -432,8 +432,17 @@ static int loongson_gnet_config(struct pci_dev *pdev,
>>>   				struct stmmac_resources *res,
>>>   				struct device_node *np)
>>>   {
>>> -	if (pdev->revision == 0x00 || pdev->revision == 0x01)
>>> +	switch (pdev->revision) {
>>> +	case 0x00:
>>> +		plat->flags |= STMMAC_FLAG_DISABLE_FORCE_1000 |
>>> +			       STMMAC_FLAG_DISABLE_HALF_DUPLEX;
>>> +		break;
>>> +	case 0x01:
>>>   		plat->flags |= STMMAC_FLAG_DISABLE_FORCE_1000;
>>> +		break;
>>> +	default:
>>> +		break;
>>> +	}
>> Move this change into the patch
>> [PATCH net-next v8 06/11] net: stmmac: dwmac-loongson: Add GNET support
>>
>>>   
>>>   	return 0;
>>>   }
>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>>> index 5617b40abbe4..3aa862269eb0 100644
>>> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>>> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>>> @@ -1201,7 +1201,8 @@ static int stmmac_init_phy(struct net_device *dev)
>>>   static void stmmac_set_half_duplex(struct stmmac_priv *priv)
>>>   {
>>>   	/* Half-Duplex can only work with single tx queue */
>>> -	if (priv->plat->tx_queues_to_use > 1)
>>> +	if (priv->plat->tx_queues_to_use > 1 ||
>>> +	    (STMMAC_FLAG_DISABLE_HALF_DUPLEX & priv->plat->flags))
>>>   		priv->phylink_config.mac_capabilities &=
>>>   			~(MAC_10HD | MAC_100HD | MAC_1000HD);
>>>   	else
>>> diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
>>> index 2810361e4048..197f6f914104 100644
>>> --- a/include/linux/stmmac.h
>>> +++ b/include/linux/stmmac.h
>>> @@ -222,6 +222,7 @@ struct dwmac4_addrs {
>>>   #define STMMAC_FLAG_EN_TX_LPI_CLOCKGATING	BIT(11)
>>>   #define STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY	BIT(12)
>>>   #define STMMAC_FLAG_DISABLE_FORCE_1000	BIT(13)
>>> +#define STMMAC_FLAG_DISABLE_HALF_DUPLEX	BIT(14)
>>>   
>> Place the patch with this change before
>> [PATCH net-next v8 06/11] net: stmmac: dwmac-loongson: Add GNET support
>> as a pre-requisite/preparation patch. Don't forget a thorough
>> description of what is wrong with the GNET Half-Duplex mode.
> BTW what about re-defining the stmmac_ops.phylink_get_caps() callback
> instead of adding fixup flags in this patch and in the next one?

ok.

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c 
b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
index ac1b48ff7199..b57e1325ce62 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
@@ -238,6 +234,13 @@ static int loongson_gnet_get_hw_feature(void 
__iomem *ioaddr,
      return 0;
  }

+static void loongson_phylink_get_caps(struct stmmac_priv *priv)
+{
+    priv->phylink_config.mac_capabilities = (MAC_10FD |
+        MAC_100FD | MAC_1000FD) & ~(MAC_10HD | MAC_100HD | MAC_1000HD);
+
+}
+
  struct stmmac_pci_info {
      int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat);
      int (*config)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat,
@@ -403,10 +405,15 @@ static void loongson_gnet_fix_speed(void *priv, 
unsigned int speed, unsigned int

  static struct mac_device_info *loongson_setup(void *apriv)
  {
+    struct stmmac_ops *loongson_dwmac_ops;
      struct stmmac_priv *priv = apriv;
      struct mac_device_info *mac;
      struct stmmac_dma_ops *dma;

+    loongson_dwmac_ops = devm_kzalloc(priv->device, 
sizeof(*loongson_dwmac_ops), GFP_KERNEL);
+    if (!loongson_dwmac_ops)
+        return NULL;
+
      mac = devm_kzalloc(priv->device, sizeof(*mac), GFP_KERNEL);
      if (!mac)
          return NULL;
@@ -417,6 +424,10 @@ static struct mac_device_info *loongson_setup(void 
*apriv)

      priv->synopsys_id = 0x37;    /*Overwrite custom IP*/

+    *loongson_dwmac_ops = dwmac1000_ops;
+    loongson_dwmac_ops->phylink_get_caps = loongson_phylink_get_caps;
+    mac->mac = loongson_dwmac_ops;
+
      *dma = dwmac1000_dma_ops;
      dma->init_chan = loongson_gnet_dma_init_channel;
      dma->dma_interrupt = loongson_gnet_dma_interrupt;
@@ -375,8 +375,6 @@ static int loongson_gmac_config(struct pci_dev *pdev,
                                 struct stmmac_resources *res,
                                 struct device_node *np)
  {
-       plat->flags |= STMMAC_FLAG_DISABLE_FLOW_CONTROL;
-
         return 0;
  }

@@ -489,17 +487,7 @@ static int loongson_gnet_config(struct pci_dev *pdev,
                                 struct stmmac_resources *res,
                                 struct device_node *np)
  {
-       switch (pdev->revision) {
-       case 0x00:
-               plat->flags |= STMMAC_FLAG_DISABLE_FORCE_1000 |
-                              STMMAC_FLAG_DISABLE_HALF_DUPLEX;
-               break;
-       case 0x01:
-               plat->flags |= STMMAC_FLAG_DISABLE_FORCE_1000;
-               break;
-       default:
-               break;
-       }
+       plat->flags |= STMMAC_FLAG_DISABLE_FORCE_1000;

         return 0;
  }
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c 
b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 8705e04913d1..7c656f970575 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -1201,8 +1201,7 @@ static int stmmac_init_phy(struct net_device *dev)
  static void stmmac_set_half_duplex(struct stmmac_priv *priv)
  {
      /* Half-Duplex can only work with single tx queue */
-    if (priv->plat->tx_queues_to_use > 1 ||
-        (STMMAC_FLAG_DISABLE_HALF_DUPLEX & priv->plat->flags))
+    if (priv->plat->tx_queues_to_use > 1)
          priv->phylink_config.mac_capabilities &=
              ~(MAC_10HD | MAC_100HD | MAC_1000HD);
      else
@@ -1237,9 +1236,9 @@ static int stmmac_phy_setup(struct stmmac_priv *priv)
          xpcs_get_interfaces(priv->hw->xpcs,
priv->phylink_config.supported_interfaces);

-    priv->phylink_config.mac_capabilities = MAC_10FD | MAC_100FD | 
MAC_1000FD;
-    if (!(priv->plat->flags & STMMAC_FLAG_DISABLE_FLOW_CONTROL))
-        priv->phylink_config.mac_capabilities |= MAC_ASYM_PAUSE | 
MAC_SYM_PAUSE;
+    priv->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | 
MAC_SYM_PAUSE |
+                        MAC_10FD | MAC_100FD |
+                        MAC_1000FD;

      stmmac_set_half_duplex(priv);
  -----


loongson_gmac/gnet_config()

I will try to remove these two functions according to your comment in 
another patch。


Thanks,

Yanteng

>
> -Serge()
>
>> -Serge(y)
>>
>>>   struct plat_stmmacenet_data {
>>>   	int bus_id;
>>> -- 
>>> 2.31.4
>>>


^ permalink raw reply related	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 10/11] net: stmmac: dwmac-loongson: Disable flow control for GMAC
  2024-02-05 22:13   ` Serge Semin
@ 2024-03-13  9:25     ` Yanteng Si
  0 siblings, 0 replies; 97+ messages in thread
From: Yanteng Si @ 2024-03-13  9:25 UTC (permalink / raw)
  To: Serge Semin
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang


在 2024/2/6 06:13, Serge Semin 写道:
> On Tue, Jan 30, 2024 at 04:49:15PM +0800, Yanteng Si wrote:
>> Loongson GMAC does not support Flow Control feature. Set flags to
>> disable it.
>>
>> Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
>> Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
>> Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
>> ---
>>   drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c | 1 +
>>   drivers/net/ethernet/stmicro/stmmac/stmmac_main.c    | 6 +++---
>>   include/linux/stmmac.h                               | 1 +
>>   3 files changed, 5 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>> index 1753a3c46b77..b78a73ea748b 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>> @@ -335,6 +335,7 @@ static int loongson_gmac_config(struct pci_dev *pdev,
>>   				struct stmmac_resources *res,
>>   				struct device_node *np)
>>   {
>> +	plat->flags |= STMMAC_FLAG_DISABLE_FLOW_CONTROL;
>>   
>>   	return 0;
>>   }
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>> index 3aa862269eb0..8d676cbfba1e 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>> @@ -1237,9 +1237,9 @@ static int stmmac_phy_setup(struct stmmac_priv *priv)
>>   		xpcs_get_interfaces(priv->hw->xpcs,
>>   				    priv->phylink_config.supported_interfaces);
>>   
>> -	priv->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
>> -						MAC_10FD | MAC_100FD |
>> -						MAC_1000FD;
>> +	priv->phylink_config.mac_capabilities = MAC_10FD | MAC_100FD | MAC_1000FD;
>> +	if (!(priv->plat->flags & STMMAC_FLAG_DISABLE_FLOW_CONTROL))
>> +		priv->phylink_config.mac_capabilities |= MAC_ASYM_PAUSE | MAC_SYM_PAUSE;
>>   
>>   	stmmac_set_half_duplex(priv);
>>   
>> diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
>> index 197f6f914104..832cd8cd688f 100644
>> --- a/include/linux/stmmac.h
>> +++ b/include/linux/stmmac.h
>> @@ -223,6 +223,7 @@ struct dwmac4_addrs {
>>   #define STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY	BIT(12)
>>   #define STMMAC_FLAG_DISABLE_FORCE_1000	BIT(13)
>>   #define STMMAC_FLAG_DISABLE_HALF_DUPLEX	BIT(14)
>> +#define STMMAC_FLAG_DISABLE_FLOW_CONTROL	BIT(15)
> See my last comment in patch 9/11. This can be reached by re-defining
> the stmmac_ops::phylink_get_caps() callback.

OK.


Thanks,

Yanteng

>
> -Serge(y)
>
>>   
>>   struct plat_stmmacenet_data {
>>   	int bus_id;
>> -- 
>> 2.31.4
>>


^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 11/11] net: stmmac: dwmac-loongson: Disable coe for some Loongson GNET
  2024-02-05 22:18   ` Serge Semin
@ 2024-03-13  9:52     ` Yanteng Si
  2024-03-13 10:19       ` Yanteng Si
  0 siblings, 1 reply; 97+ messages in thread
From: Yanteng Si @ 2024-03-13  9:52 UTC (permalink / raw)
  To: Serge Semin
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang


在 2024/2/6 06:18, Serge Semin 写道:
> On Tue, Jan 30, 2024 at 04:49:16PM +0800, Yanteng Si wrote:
>> Some chips of Loongson GNET does not support coe, so disable them.
> s/coe/Tx COE
OK.
>
>> Set dma_cap->tx_coe to 0 and overwrite get_hw_feature.
>>
>> Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
>> Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
>> Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
>> ---
>>   .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 46 +++++++++++++++++++
>>   1 file changed, 46 insertions(+)
>>
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>> index b78a73ea748b..8018d7d5f31b 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>> @@ -196,6 +196,51 @@ static int dwlgmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
>>   	return ret;
>>   }
>>   
>> +static int dwlgmac_get_hw_feature(void __iomem *ioaddr,
> Please use GNET-specific prefix.
OK. loongson_gnet_get_hw_feature()
>
>> +				  struct dma_features *dma_cap)
>> +{
>> +	u32 hw_cap = readl(ioaddr + DMA_HW_FEATURE);
>> +
>> +	if (!hw_cap) {
>> +		/* 0x00000000 is the value read on old hardware that does not
>> +		 * implement this register
>> +		 */
>> +		return -EOPNOTSUPP;
>> +	}
> This doesn't seems like possible. All your devices have the
> HW-features register. If so please drop.
OK, drop it.
>
>> +
>> +	dma_cap->mbps_10_100 = (hw_cap & DMA_HW_FEAT_MIISEL);
>> +	dma_cap->mbps_1000 = (hw_cap & DMA_HW_FEAT_GMIISEL) >> 1;
>> +	dma_cap->half_duplex = (hw_cap & DMA_HW_FEAT_HDSEL) >> 2;
>> +	dma_cap->hash_filter = (hw_cap & DMA_HW_FEAT_HASHSEL) >> 4;
>> +	dma_cap->multi_addr = (hw_cap & DMA_HW_FEAT_ADDMAC) >> 5;
>> +	dma_cap->pcs = (hw_cap & DMA_HW_FEAT_PCSSEL) >> 6;
>> +	dma_cap->sma_mdio = (hw_cap & DMA_HW_FEAT_SMASEL) >> 8;
>> +	dma_cap->pmt_remote_wake_up = (hw_cap & DMA_HW_FEAT_RWKSEL) >> 9;
>> +	dma_cap->pmt_magic_frame = (hw_cap & DMA_HW_FEAT_MGKSEL) >> 10;
>> +	/* MMC */
>> +	dma_cap->rmon = (hw_cap & DMA_HW_FEAT_MMCSEL) >> 11;
>> +	/* IEEE 1588-2002 */
>> +	dma_cap->time_stamp =
>> +	    (hw_cap & DMA_HW_FEAT_TSVER1SEL) >> 12;
>> +	/* IEEE 1588-2008 */
>> +	dma_cap->atime_stamp = (hw_cap & DMA_HW_FEAT_TSVER2SEL) >> 13;
>> +	/* 802.3az - Energy-Efficient Ethernet (EEE) */
>> +	dma_cap->eee = (hw_cap & DMA_HW_FEAT_EEESEL) >> 14;
>> +	dma_cap->av = (hw_cap & DMA_HW_FEAT_AVSEL) >> 15;
>> +	/* TX and RX csum */
>> +	dma_cap->tx_coe = 0;
>> +	dma_cap->rx_coe_type1 = (hw_cap & DMA_HW_FEAT_RXTYP1COE) >> 17;
>> +	dma_cap->rx_coe_type2 = (hw_cap & DMA_HW_FEAT_RXTYP2COE) >> 18;
>> +	dma_cap->rxfifo_over_2048 = (hw_cap & DMA_HW_FEAT_RXFIFOSIZE) >> 19;
>> +	/* TX and RX number of channels */
>> +	dma_cap->number_rx_channel = (hw_cap & DMA_HW_FEAT_RXCHCNT) >> 20;
>> +	dma_cap->number_tx_channel = (hw_cap & DMA_HW_FEAT_TXCHCNT) >> 22;
>> +	/* Alternate (enhanced) DESC mode */
>> +	dma_cap->enh_desc = (hw_cap & DMA_HW_FEAT_ENHDESSEL) >> 24;
> I am not sure whether you need to parse the capability register at all
> seeing this is a GNET-specific method. For that device all the
> capabilities are already known and can be just initialized in this
> method.
-dma_cap->tx_coe = (hw_cap & DMA_HW_FEAT_TXCOESEL) >> 16;

+dma_cap->tx_coe = 0;

I'm a little confused. Actually, I only modified this line, which is 
used to fix the checksum.

2k2000  of Loongson GNET does not support coe.


Thanks,
Yanteng

>
> -Serge(y)
>
>> +
>> +	return 0;
>> +}
>> +
>>   struct stmmac_pci_info {
>>   	int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat);
>>   	int (*config)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat,
>> @@ -542,6 +587,7 @@ static int loongson_dwmac_probe(struct pci_dev *pdev,
>>   		ld->dwlgmac_dma_ops = dwmac1000_dma_ops;
>>   		ld->dwlgmac_dma_ops.init_chan = dwlgmac_dma_init_channel;
>>   		ld->dwlgmac_dma_ops.dma_interrupt = dwlgmac_dma_interrupt;
>> +		ld->dwlgmac_dma_ops.get_hw_feature = dwlgmac_get_hw_feature;
>>   
>>   		plat->setup = loongson_setup;
>>   		ret = loongson_dwmac_config_multi_msi(pdev, plat, &res, np, 8);
>> -- 
>> 2.31.4
>>


^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 11/11] net: stmmac: dwmac-loongson: Disable coe for some Loongson GNET
  2024-03-13  9:52     ` Yanteng Si
@ 2024-03-13 10:19       ` Yanteng Si
  2024-03-20 11:24         ` Serge Semin
  0 siblings, 1 reply; 97+ messages in thread
From: Yanteng Si @ 2024-03-13 10:19 UTC (permalink / raw)
  To: Serge Semin
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang


在 2024/3/13 17:52, Yanteng Si 写道:
>
> 在 2024/2/6 06:18, Serge Semin 写道:
>> On Tue, Jan 30, 2024 at 04:49:16PM +0800, Yanteng Si wrote:
>>> Some chips of Loongson GNET does not support coe, so disable them.
>> s/coe/Tx COE
> OK.
>>
>>> Set dma_cap->tx_coe to 0 and overwrite get_hw_feature.
>>>
>>> Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
>>> Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
>>> Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
>>> ---
>>>   .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 46 
>>> +++++++++++++++++++
>>>   1 file changed, 46 insertions(+)
>>>
>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c 
>>> b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>> index b78a73ea748b..8018d7d5f31b 100644
>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>> @@ -196,6 +196,51 @@ static int dwlgmac_dma_interrupt(struct 
>>> stmmac_priv *priv, void __iomem *ioaddr,
>>>       return ret;
>>>   }
>>>   +static int dwlgmac_get_hw_feature(void __iomem *ioaddr,
>> Please use GNET-specific prefix.
> OK. loongson_gnet_get_hw_feature()
>>
>>> +                  struct dma_features *dma_cap)
>>> +{
>>> +    u32 hw_cap = readl(ioaddr + DMA_HW_FEATURE);
>>> +
>>> +    if (!hw_cap) {
>>> +        /* 0x00000000 is the value read on old hardware that does not
>>> +         * implement this register
>>> +         */
>>> +        return -EOPNOTSUPP;
>>> +    }
>> This doesn't seems like possible. All your devices have the
>> HW-features register. If so please drop.
> OK, drop it.
>>
>>> +
>>> +    dma_cap->mbps_10_100 = (hw_cap & DMA_HW_FEAT_MIISEL);
>>> +    dma_cap->mbps_1000 = (hw_cap & DMA_HW_FEAT_GMIISEL) >> 1;
>>> +    dma_cap->half_duplex = (hw_cap & DMA_HW_FEAT_HDSEL) >> 2;
>>> +    dma_cap->hash_filter = (hw_cap & DMA_HW_FEAT_HASHSEL) >> 4;
>>> +    dma_cap->multi_addr = (hw_cap & DMA_HW_FEAT_ADDMAC) >> 5;
>>> +    dma_cap->pcs = (hw_cap & DMA_HW_FEAT_PCSSEL) >> 6;
>>> +    dma_cap->sma_mdio = (hw_cap & DMA_HW_FEAT_SMASEL) >> 8;
>>> +    dma_cap->pmt_remote_wake_up = (hw_cap & DMA_HW_FEAT_RWKSEL) >> 9;
>>> +    dma_cap->pmt_magic_frame = (hw_cap & DMA_HW_FEAT_MGKSEL) >> 10;
>>> +    /* MMC */
>>> +    dma_cap->rmon = (hw_cap & DMA_HW_FEAT_MMCSEL) >> 11;
>>> +    /* IEEE 1588-2002 */
>>> +    dma_cap->time_stamp =
>>> +        (hw_cap & DMA_HW_FEAT_TSVER1SEL) >> 12;
>>> +    /* IEEE 1588-2008 */
>>> +    dma_cap->atime_stamp = (hw_cap & DMA_HW_FEAT_TSVER2SEL) >> 13;
>>> +    /* 802.3az - Energy-Efficient Ethernet (EEE) */
>>> +    dma_cap->eee = (hw_cap & DMA_HW_FEAT_EEESEL) >> 14;
>>> +    dma_cap->av = (hw_cap & DMA_HW_FEAT_AVSEL) >> 15;
>>> +    /* TX and RX csum */
>>> +    dma_cap->tx_coe = 0;
>>> +    dma_cap->rx_coe_type1 = (hw_cap & DMA_HW_FEAT_RXTYP1COE) >> 17;
>>> +    dma_cap->rx_coe_type2 = (hw_cap & DMA_HW_FEAT_RXTYP2COE) >> 18;
>>> +    dma_cap->rxfifo_over_2048 = (hw_cap & DMA_HW_FEAT_RXFIFOSIZE) 
>>> >> 19;
>>> +    /* TX and RX number of channels */
>>> +    dma_cap->number_rx_channel = (hw_cap & DMA_HW_FEAT_RXCHCNT) >> 20;
>>> +    dma_cap->number_tx_channel = (hw_cap & DMA_HW_FEAT_TXCHCNT) >> 22;
>>> +    /* Alternate (enhanced) DESC mode */
>>> +    dma_cap->enh_desc = (hw_cap & DMA_HW_FEAT_ENHDESSEL) >> 24;
>> I am not sure whether you need to parse the capability register at all
>> seeing this is a GNET-specific method. For that device all the
>> capabilities are already known and can be just initialized in this
>> method.
> -dma_cap->tx_coe = (hw_cap & DMA_HW_FEAT_TXCOESEL) >> 16;
>
> +dma_cap->tx_coe = 0;
>
> I'm a little confused. Actually, I only modified this line, which is 
> used to fix the checksum.
>
> 2k2000  of Loongson GNET does not support coe.

Specifically, it is to ensure the normal operation of multiple channels, 
as other channels except for channel 0 cannot perform checksum.

Thanks,

Yanteng


>
>
> Thanks,
> Yanteng
>
>>
>> -Serge(y)
>>
>>> +
>>> +    return 0;
>>> +}
>>> +
>>>   struct stmmac_pci_info {
>>>       int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data 
>>> *plat);
>>>       int (*config)(struct pci_dev *pdev, struct 
>>> plat_stmmacenet_data *plat,
>>> @@ -542,6 +587,7 @@ static int loongson_dwmac_probe(struct pci_dev 
>>> *pdev,
>>>           ld->dwlgmac_dma_ops = dwmac1000_dma_ops;
>>>           ld->dwlgmac_dma_ops.init_chan = dwlgmac_dma_init_channel;
>>>           ld->dwlgmac_dma_ops.dma_interrupt = dwlgmac_dma_interrupt;
>>> +        ld->dwlgmac_dma_ops.get_hw_feature = dwlgmac_get_hw_feature;
>>>             plat->setup = loongson_setup;
>>>           ret = loongson_dwmac_config_multi_msi(pdev, plat, &res, 
>>> np, 8);
>>> -- 
>>> 2.31.4
>>>


^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 09/11] net: stmmac: dwmac-loongson: Fix half duplex
  2024-03-13  9:24       ` Yanteng Si
@ 2024-03-13 10:21         ` Russell King (Oracle)
  2024-03-14 13:08           ` Yanteng Si
  0 siblings, 1 reply; 97+ messages in thread
From: Russell King (Oracle) @ 2024-03-13 10:21 UTC (permalink / raw)
  To: Yanteng Si
  Cc: Serge Semin, andrew, hkallweit1, peppe.cavallaro,
	alexandre.torgue, joabreu, Jose.Abreu, chenhuacai, guyinggang,
	netdev, chris.chenfeiyang

On Wed, Mar 13, 2024 at 05:24:52PM +0800, Yanteng Si wrote:
> 在 2024/2/6 06:06, Serge Semin 写道:
> > On Tue, Feb 06, 2024 at 12:58:17AM +0300, Serge Semin wrote:
> > > On Tue, Jan 30, 2024 at 04:49:14PM +0800, Yanteng Si wrote:
> > > > Current GNET does not support half duplex mode.
> > > > 
> > > > Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
> > > > Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
> > > > Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
> > > > ---
> > > >   drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c | 11 ++++++++++-
> > > >   drivers/net/ethernet/stmicro/stmmac/stmmac_main.c    |  3 ++-
> > > >   include/linux/stmmac.h                               |  1 +
> > > >   3 files changed, 13 insertions(+), 2 deletions(-)
> > > > 
> > > > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > > index 264c4c198d5a..1753a3c46b77 100644
> > > > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > > @@ -432,8 +432,17 @@ static int loongson_gnet_config(struct pci_dev *pdev,
> > > >   				struct stmmac_resources *res,
> > > >   				struct device_node *np)
> > > >   {
> > > > -	if (pdev->revision == 0x00 || pdev->revision == 0x01)
> > > > +	switch (pdev->revision) {
> > > > +	case 0x00:
> > > > +		plat->flags |= STMMAC_FLAG_DISABLE_FORCE_1000 |
> > > > +			       STMMAC_FLAG_DISABLE_HALF_DUPLEX;
> > > > +		break;
> > > > +	case 0x01:
> > > >   		plat->flags |= STMMAC_FLAG_DISABLE_FORCE_1000;
> > > > +		break;
> > > > +	default:
> > > > +		break;
> > > > +	}
> > > Move this change into the patch
> > > [PATCH net-next v8 06/11] net: stmmac: dwmac-loongson: Add GNET support
> > > 
> > > >   	return 0;
> > > >   }
> > > > diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> > > > index 5617b40abbe4..3aa862269eb0 100644
> > > > --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> > > > +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> > > > @@ -1201,7 +1201,8 @@ static int stmmac_init_phy(struct net_device *dev)
> > > >   static void stmmac_set_half_duplex(struct stmmac_priv *priv)
> > > >   {
> > > >   	/* Half-Duplex can only work with single tx queue */
> > > > -	if (priv->plat->tx_queues_to_use > 1)
> > > > +	if (priv->plat->tx_queues_to_use > 1 ||
> > > > +	    (STMMAC_FLAG_DISABLE_HALF_DUPLEX & priv->plat->flags))
> > > >   		priv->phylink_config.mac_capabilities &=
> > > >   			~(MAC_10HD | MAC_100HD | MAC_1000HD);
> > > >   	else
> > > > diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
> > > > index 2810361e4048..197f6f914104 100644
> > > > --- a/include/linux/stmmac.h
> > > > +++ b/include/linux/stmmac.h
> > > > @@ -222,6 +222,7 @@ struct dwmac4_addrs {
> > > >   #define STMMAC_FLAG_EN_TX_LPI_CLOCKGATING	BIT(11)
> > > >   #define STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY	BIT(12)
> > > >   #define STMMAC_FLAG_DISABLE_FORCE_1000	BIT(13)
> > > > +#define STMMAC_FLAG_DISABLE_HALF_DUPLEX	BIT(14)
> > > Place the patch with this change before
> > > [PATCH net-next v8 06/11] net: stmmac: dwmac-loongson: Add GNET support
> > > as a pre-requisite/preparation patch. Don't forget a thorough
> > > description of what is wrong with the GNET Half-Duplex mode.
> > BTW what about re-defining the stmmac_ops.phylink_get_caps() callback
> > instead of adding fixup flags in this patch and in the next one?
> 
> ok.
> 
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> index ac1b48ff7199..b57e1325ce62 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> @@ -238,6 +234,13 @@ static int loongson_gnet_get_hw_feature(void __iomem
> *ioaddr,
>      return 0;
>  }
> 
> +static void loongson_phylink_get_caps(struct stmmac_priv *priv)
> +{
> +    priv->phylink_config.mac_capabilities = (MAC_10FD |
> +        MAC_100FD | MAC_1000FD) & ~(MAC_10HD | MAC_100HD | MAC_1000HD);

Why is this so complicated? It would be silly if the _full duplex_
definitions also defined the _half duplex_ bits. This should be just:

	priv->phylink_config.mac_capabilities = MAC_10FD | MAC_100FD |
						MAC_1000FD;

if that is all you support. Do you not support any pause modes (they
would need to be included as well here.)

As to this approach, I don't think it's a good model to override the
stmmac MAC operations. Instead, I would suggest that a better approach
would be for the platform to provide its capabilities to the stmmac
core code (maybe a new member in stmmac_priv) which, when set, is used
to reduce the capabilities provided to phylink via
priv->phylink_config.mac_capabilities.

Why? The driver has several components that are involved in the
overall capabilities, and the capabilities of the system is the
logical subset of all these capabilities. One component should not
be setting capabilities that a different component doesn't support.

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 09/11] net: stmmac: dwmac-loongson: Fix half duplex
  2024-03-13 10:21         ` Russell King (Oracle)
@ 2024-03-14 13:08           ` Yanteng Si
  2024-03-20 10:10             ` Serge Semin
  0 siblings, 1 reply; 97+ messages in thread
From: Yanteng Si @ 2024-03-14 13:08 UTC (permalink / raw)
  To: Russell King (Oracle), Serge Semin
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, guyinggang, netdev, chris.chenfeiyang


在 2024/3/13 18:21, Russell King (Oracle) 写道:
> On Wed, Mar 13, 2024 at 05:24:52PM +0800, Yanteng Si wrote:
>> 在 2024/2/6 06:06, Serge Semin 写道:
>>> On Tue, Feb 06, 2024 at 12:58:17AM +0300, Serge Semin wrote:
>>>> On Tue, Jan 30, 2024 at 04:49:14PM +0800, Yanteng Si wrote:
>>>>> Current GNET does not support half duplex mode.
>>>>>
>>>>> Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
>>>>> Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
>>>>> Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
>>>>> ---
>>>>>    drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c | 11 ++++++++++-
>>>>>    drivers/net/ethernet/stmicro/stmmac/stmmac_main.c    |  3 ++-
>>>>>    include/linux/stmmac.h                               |  1 +
>>>>>    3 files changed, 13 insertions(+), 2 deletions(-)
>>>>>
>>>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>>>> index 264c4c198d5a..1753a3c46b77 100644
>>>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>>>> @@ -432,8 +432,17 @@ static int loongson_gnet_config(struct pci_dev *pdev,
>>>>>    				struct stmmac_resources *res,
>>>>>    				struct device_node *np)
>>>>>    {
>>>>> -	if (pdev->revision == 0x00 || pdev->revision == 0x01)
>>>>> +	switch (pdev->revision) {
>>>>> +	case 0x00:
>>>>> +		plat->flags |= STMMAC_FLAG_DISABLE_FORCE_1000 |
>>>>> +			       STMMAC_FLAG_DISABLE_HALF_DUPLEX;
>>>>> +		break;
>>>>> +	case 0x01:
>>>>>    		plat->flags |= STMMAC_FLAG_DISABLE_FORCE_1000;
>>>>> +		break;
>>>>> +	default:
>>>>> +		break;
>>>>> +	}
>>>> Move this change into the patch
>>>> [PATCH net-next v8 06/11] net: stmmac: dwmac-loongson: Add GNET support
>>>>
>>>>>    	return 0;
>>>>>    }
>>>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>>>>> index 5617b40abbe4..3aa862269eb0 100644
>>>>> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>>>>> @@ -1201,7 +1201,8 @@ static int stmmac_init_phy(struct net_device *dev)
>>>>>    static void stmmac_set_half_duplex(struct stmmac_priv *priv)
>>>>>    {
>>>>>    	/* Half-Duplex can only work with single tx queue */
>>>>> -	if (priv->plat->tx_queues_to_use > 1)
>>>>> +	if (priv->plat->tx_queues_to_use > 1 ||
>>>>> +	    (STMMAC_FLAG_DISABLE_HALF_DUPLEX & priv->plat->flags))
>>>>>    		priv->phylink_config.mac_capabilities &=
>>>>>    			~(MAC_10HD | MAC_100HD | MAC_1000HD);
>>>>>    	else
>>>>> diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
>>>>> index 2810361e4048..197f6f914104 100644
>>>>> --- a/include/linux/stmmac.h
>>>>> +++ b/include/linux/stmmac.h
>>>>> @@ -222,6 +222,7 @@ struct dwmac4_addrs {
>>>>>    #define STMMAC_FLAG_EN_TX_LPI_CLOCKGATING	BIT(11)
>>>>>    #define STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY	BIT(12)
>>>>>    #define STMMAC_FLAG_DISABLE_FORCE_1000	BIT(13)
>>>>> +#define STMMAC_FLAG_DISABLE_HALF_DUPLEX	BIT(14)
>>>> Place the patch with this change before
>>>> [PATCH net-next v8 06/11] net: stmmac: dwmac-loongson: Add GNET support
>>>> as a pre-requisite/preparation patch. Don't forget a thorough
>>>> description of what is wrong with the GNET Half-Duplex mode.
>>> BTW what about re-defining the stmmac_ops.phylink_get_caps() callback
>>> instead of adding fixup flags in this patch and in the next one?
>> ok.
>>
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>> b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>> index ac1b48ff7199..b57e1325ce62 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>> @@ -238,6 +234,13 @@ static int loongson_gnet_get_hw_feature(void __iomem
>> *ioaddr,
>>       return 0;
>>   }

Hi Russell,

>> +static void loongson_phylink_get_caps(struct stmmac_priv *priv)
>> +{
>> +    priv->phylink_config.mac_capabilities = (MAC_10FD |
>> +        MAC_100FD | MAC_1000FD) & ~(MAC_10HD | MAC_100HD | MAC_1000HD);
> Why is this so complicated? It would be silly if the _full duplex_
> definitions also defined the _half duplex_ bits. This should be just:
>
> 	priv->phylink_config.mac_capabilities = MAC_10FD | MAC_100FD |
> 						MAC_1000FD;

Yes, you are right. Our gnet device (7a2000) does not support 
half-duplex, while the gnet device (2k2000) does.

I plan to use PCI IDand IP CORE as the condition to separate full-duplex 
and half-duplex.

>
> if that is all you support. Do you not support any pause modes (they
> would need to be included as well here.)

I have tested it and our gnet device supports MAC_ASYM_PAUSE and 
MAC_SYM_PAUSE, but gmac does not. I will fix this in the patch v9.

This is also easy to do because all GMAC devices have the same PCI ID.

>
> As to this approach, I don't think it's a good model to override the
> stmmac MAC operations. Instead, I would suggest that a better approach
> would be for the platform to provide its capabilities to the stmmac
> core code (maybe a new member in stmmac_priv) which, when set, is used
> to reduce the capabilities provided to phylink via
> priv->phylink_config.mac_capabilities.
>
> Why? The driver has several components that are involved in the
> overall capabilities, and the capabilities of the system is the
> logical subset of all these capabilities. One component should not
> be setting capabilities that a different component doesn't support.

Hi Serge,

It seems to be going back again, what do you think?

Thanks,

Yanteng

>


^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 06/11] net: stmmac: dwmac-loongson: Add GNET support
       [not found]     ` <d0e56c9b-9549-4061-8e44-2504b6b96897@loongson.cn>
@ 2024-03-14 13:12       ` Yanteng Si
  2024-03-19 15:03         ` Serge Semin
  0 siblings, 1 reply; 97+ messages in thread
From: Yanteng Si @ 2024-03-14 13:12 UTC (permalink / raw)
  To: Serge Semin
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang


在 2024/3/14 16:27, Yanteng Si 写道:
> 在 2024/2/6 04:58, Serge Semin 写道:
> > On Tue, Jan 30, 2024 at 04:48:18PM +0800, Yanteng Si wrote:
> >> Add Loongson GNET (GMAC with PHY) support, override
> >> stmmac_priv.synopsys_id with 0x37.
> > Please add more details of all the device capabilities: supported
> > speeds, duplexness, IP-core version, DMA-descriptors type
> > (normal/enhanced), MTL Tx/Rx FIFO size, Perfect and Hash-based MAC
> > Filter tables size, L3/L4 filters availability, VLAN hash table
> > filter, PHY-interface (GMII, RGMII, etc), EEE support,
> > AV-feature/Multi-channels support, IEEE 1588 Timestamp support, Magic
> > Frame support, Remote Wake-up support, IP Checksum, Tx/Rx TCP/IP
> > Checksum, Mac Management Counters (MMC), SMA/MDIO interface,
> The gnet (2k2000) of 0x10 supports full-duplex and half-duplex at 1000/100/10M.
> The gnet of 0x37 (i.e. the gnet of 7a2000) supports 1000/100/10M full duplex.
>
> The gnet with 0x10 has 8 DMA channels, except for channel 0, which does not
> support sending hardware checksums.
>
> Supported AV features are Qav, Qat, and Qas, and other features should be
> consistent with the 3.73 IP.
>
> >
> >> Signed-off-by: Yanteng Si<siyanteng@loongson.cn>
> >> Signed-off-by: Feiyang Chen<chenfeiyang@loongson.cn>
> >> Signed-off-by: Yinggang Gu<guyinggang@loongson.cn>
> >> ---
> >>   .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 44 +++++++++++++++++++
> >>   1 file changed, 44 insertions(+)
> >>
> >> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> >> index 3b3578318cc1..584f7322bd3e 100644
> >> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> >> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> >> @@ -318,6 +318,8 @@ static struct mac_device_info *loongson_setup(void *apriv)
> >>   	if (!mac)
> >>   		return NULL;
> >>   
> >> +	priv->synopsys_id = 0x37;	/*Overwrite custom IP*/
> >> +
> > Please add a more descriptive comment _above_ the subjected line. In
> > particular note why the override is needed, what is the real DW GMAC
> > IP-core version and what is the original value the statement above
> > overrides.
>
> The IP-core version of the gnet device on the loongson 2k2000 is 0x10, which is
> a custom IP.
>
> Compared to 0x37, we have split some of the dma registers into two (tx and rx).
> After overwriting stmmac_dma_ops.dma_interrupt() and stmmac_dma_ops.init_chan(),
> the logic is consistent with 0x37,
>
> so we overwrite synopsys_id to 0x37.
>
> >>   	ld = priv->plat->bsp_priv;
> >>   	mac->dma = &ld->dwlgmac_dma_ops;
> >>   
> >> @@ -350,6 +352,46 @@ static struct mac_device_info *loongson_setup(void *apriv)
> >>   	return mac;
> >>   }
> >>   
> >> +static int loongson_gnet_data(struct pci_dev *pdev,
> >> +			      struct plat_stmmacenet_data *plat)
> >> +{
> >> +	loongson_default_data(pdev, plat);
> >> +
> >> +	plat->multicast_filter_bins = 256;
> >> +
> >> +	plat->mdio_bus_data->phy_mask =  ~(u32)BIT(2);
> >> +
> >> +	plat->phy_addr = 2;
> >> +	plat->phy_interface = PHY_INTERFACE_MODE_INTERNAL;
> > Are you sure PHY-interface is supposed to be defined as "internal"?
>
> Yes, because the gnet hardware has a integrated PHY, so we set it to internal,
>
> Correspondingly, our gmac hardware PHY is external.
>
> >> +
> >> +	plat->bsp_priv = &pdev->dev;
> >> +
> >> +	plat->dma_cfg->pbl = 32;
> >> +	plat->dma_cfg->pblx8 = true;
> >> +
> >> +	plat->clk_ref_rate = 125000000;
> >> +	plat->clk_ptp_rate = 125000000;
> >> +
> >> +	return 0;
> >> +}
> >> +
> >> +static int loongson_gnet_config(struct pci_dev *pdev,
> >> +				struct plat_stmmacenet_data *plat,
> >> +				struct stmmac_resources *res,
> >> +				struct device_node *np)
> >> +{
> >> +	int ret;
> >> +
> >> +	ret = loongson_dwmac_config_legacy(pdev, plat, res, np);
> > Again. This will be moved to the probe() method in one of the next
> > patches leaving loongson_gnet_config() empty. What was the problem
> > with doing that right away with no intermediate change?
>
> No problem. My original intention is to break the patches down into smaller pieces.
>
> In the next version, I will try to re-break them based on your comments.
>
> >
> >> +
> >> +	return ret;
> >> +}
> >> +
> >> +static struct stmmac_pci_info loongson_gnet_pci_info = {
> >> +	.setup = loongson_gnet_data,
> >> +	.config = loongson_gnet_config,
> >> +};
> >> +
> >>   static int loongson_dwmac_probe(struct pci_dev *pdev,
> >>   				const struct pci_device_id *id)
> >>   {
> >> @@ -516,9 +558,11 @@ static SIMPLE_DEV_PM_OPS(loongson_dwmac_pm_ops, loongson_dwmac_suspend,
> >>   			 loongson_dwmac_resume);
> >>   
> >>   #define PCI_DEVICE_ID_LOONGSON_GMAC	0x7a03
> >> +#define PCI_DEVICE_ID_LOONGSON_GNET	0x7a13
> >>   
> >>   static const struct pci_device_id loongson_dwmac_id_table[] = {
> >>   	{ PCI_DEVICE_DATA(LOONGSON, GMAC, &loongson_gmac_pci_info) },
> >> +	{ PCI_DEVICE_DATA(LOONGSON, GNET, &loongson_gnet_pci_info) },
> > After this the driver is supposed to correctly handle the Loongson
> > GNET devices. Based on the patches introduced further it isn't.
> > Please consider re-arranging the changes (see my comments in the
> > further patches).
>
> OK.
>
>
> Thanks,
>
> Yanteng
>
>
> >
> > -Serge(y)
> >
> >>   	{}
> >>   };
> >>   MODULE_DEVICE_TABLE(pci, loongson_dwmac_id_table);
> >> -- 
> >> 2.31.4
> >>


^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 07/11] net: stmmac: dwmac-loongson: Add multi-channel supports for loongson
       [not found]     ` <e1c7b5fa-f3f8-4aa3-af4d-ca72b54d9c8c@loongson.cn>
@ 2024-03-14 13:13       ` Yanteng Si
  2024-03-19 15:53         ` Serge Semin
  0 siblings, 1 reply; 97+ messages in thread
From: Yanteng Si @ 2024-03-14 13:13 UTC (permalink / raw)
  To: Serge Semin
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang


在 2024/3/14 17:33, Yanteng Si 写道:
> 在 2024/2/6 05:28, Serge Semin 写道:
> > On Tue, Jan 30, 2024 at 04:48:19PM +0800, Yanteng Si wrote:
> >> Request allocation for MSI for specific versions.
> >>
> > Please elaborate what is actually done in the patch. What device
> > version it is dedicated for (Loongson GNET?), what IRQs the patch
> > adds, etc.
> gnet_device   core IP    IRQ
> 7a2000        0x37    legacy
> 2k2000        0x10    multi_msi
> >
> > BTW will GNET device work without this patch? If no you need to either
> > merge it into the patch introducing the GNET-device support or place
> > it before that patch (6/11).
> OK, GNET device work need this patch.
> >   
> >> Some features of Loongson platforms are bound to the GMAC_VERSION
> >> register. We have to read its value in order to get the correct channel
> >> number.
> > This message seems misleading. I don't see you doing that in the patch below...
> Because part of our gnet hardware (7a2000) core IP is 0x37
> >
> >> Signed-off-by: Yanteng Si<siyanteng@loongson.cn>
> >> Signed-off-by: Feiyang Chen<chenfeiyang@loongson.cn>
> >> Signed-off-by: Yinggang Gu<guyinggang@loongson.cn>
> >> ---
> >>   .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 57 +++++++++++++++----
> >>   1 file changed, 46 insertions(+), 11 deletions(-)
> >>
> >> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> >> index 584f7322bd3e..60d0a122d7c9 100644
> >> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> >> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> >> @@ -98,10 +98,10 @@ static void dwlgmac_dma_init_channel(struct stmmac_priv *priv,
> >>   	if (dma_cfg->aal)
> >>   		value |= DMA_BUS_MODE_AAL;
> >>
> >   
> >> -	writel(value, ioaddr + DMA_BUS_MODE);
> >> +	writel(value, ioaddr + DMA_CHAN_BUS_MODE(chan));
> >>   
> >>   	/* Mask interrupts by writing to CSR7 */
> >> -	writel(DMA_INTR_DEFAULT_MASK_LOONGSON, ioaddr + DMA_INTR_ENA);
> >> +	writel(DMA_INTR_DEFAULT_MASK_LOONGSON, ioaddr + DMA_CHAN_INTR_ENA(chan));
> > Em, why is this here? There is a patch
> > [PATCH net-next v8 05/11] net: stmmac: dwmac-loongson: Add Loongson-specific register definitions
> > in this series which was supposed to introduce the fully functional
> > GNET-specific callbacks. Move this change in there.
> OK.
> >
> >>   }
> >>   
> >>   static int dwlgmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
> >> @@ -238,6 +238,45 @@ static int loongson_dwmac_config_legacy(struct pci_dev *pdev,
> >>   	return 0;
> >>   }
> >>   
> >> +static int loongson_dwmac_config_multi_msi(struct pci_dev *pdev,
> > This method seems like the GNET-specific one. What about using the
> > appropriate prefix then?
> OK. loongson_gnet_config_multi_msi()
>
> >
> >> +					   struct plat_stmmacenet_data *plat,
> >> +					   struct stmmac_resources *res,
> >> +					   struct device_node *np,
> >> +					   int channel_num)
> > Why do you need this parametrization? Since this method is
> > GNET-specific what about defining a macro with the channels amount and
> > using it here?
>
> OK.
>
> #define CHANNEL_NUM    8
>
> >
> >> +{
> >> +	int i, ret, vecs;
> >> +
> >> +	vecs = roundup_pow_of_two(channel_num * 2 + 1);
> >> +	ret = pci_alloc_irq_vectors(pdev, vecs, vecs, PCI_IRQ_MSI);
> >> +	if (ret < 0) {
> >> +		dev_info(&pdev->dev,
> >> +			 "MSI enable failed, Fallback to legacy interrupt\n");
> >> +		return loongson_dwmac_config_legacy(pdev, plat, res, np);
> > In what conditions is this possible? Will the
> > loongson_dwmac_config_legacy() method work in that case? Did you test
> > it out?
> Failed to apply for msi interrupt when the interrupt number is not enough,For
> example, there are a large number of devices。
> >> +	}
> >> +
> >> +	plat->rx_queues_to_use = channel_num;
> >> +	plat->tx_queues_to_use = channel_num;
> > This is supposed to be initialized in the setup() methods. Please move
> > it to the dedicated patch.
> No, referring to my previous reply, only the 0x10 gnet device has 8 channels,
> and the 0x37 device has a single channel.
> >
> >> +
> >> +	res->irq = pci_irq_vector(pdev, 0);
> >> +	res->wol_irq = res->irq;
> > Once again. wol_irq is optional. If there is no dedicated WoL IRQ
> > leave the field as zero.
> OK.
>
> res->wol_irq = 0;
>
> >
> >> +
> >> +	/* INT NAME | MAC | CH7 rx | CH7 tx | ... | CH0 rx | CH0 tx |
> >> +	 * --------- ----- -------- --------  ...  -------- --------
> >> +	 * IRQ NUM  |  0  |   1    |   2    | ... |   15   |   16   |
> >> +	 */
> >> +	for (i = 0; i < channel_num; i++) {
> >> +		res->rx_irq[channel_num - 1 - i] =
> >> +			pci_irq_vector(pdev, 1 + i * 2);
> >> +		res->tx_irq[channel_num - 1 - i] =
> >> +			pci_irq_vector(pdev, 2 + i * 2);
> >> +	}
> >> +
> >> +	plat->flags |= STMMAC_FLAG_MULTI_MSI_EN;
> >> +	dev_info(&pdev->dev, "%s: multi MSI enablement successful\n", __func__);
> > What's the point in printing this message especially with the __func__
> > prefix?  You'll always be able to figure out the allocated IRQs by
> > means of procfs. I suggest to drop it.
>
> OK.
>
> >
> >> +
> >> +	return 0;
> >> +}
> >> +
> >>   static void loongson_default_data(struct pci_dev *pdev,
> >>   				  struct plat_stmmacenet_data *plat)
> >>   {
> >> @@ -296,11 +335,8 @@ static int loongson_gmac_config(struct pci_dev *pdev,
> >>   				struct stmmac_resources *res,
> >>   				struct device_node *np)
> >>   {
> >> -	int ret;
> >> -
> >> -	ret = loongson_dwmac_config_legacy(pdev, plat, res, np);
> >>   
> >> -	return ret;
> >> +	return 0;
> >>   }
> >>   
> >>   static struct stmmac_pci_info loongson_gmac_pci_info = {
> >> @@ -380,11 +416,7 @@ static int loongson_gnet_config(struct pci_dev *pdev,
> >>   				struct stmmac_resources *res,
> >>   				struct device_node *np)
> >>   {
> >> -	int ret;
> >> -
> >> -	ret = loongson_dwmac_config_legacy(pdev, plat, res, np);
> >> -
> >> -	return ret;
> >> +	return 0;
> >>   }
> > Here you are dropping the changes you just introduced leaving the
> > config() methods empty... Why not to place the
> > loongson_dwmac_config_legacy() invocation in the probe() method right
> > at the patches introducing the config() functions and not to add the
> > config() callback in the first place?
> OK, I will try.
>
> Thanks,
>
> Yanteng
>
> >
> > -Serge(y)
> >
> >>   
> >>   static struct stmmac_pci_info loongson_gnet_pci_info = {
> >> @@ -483,6 +515,9 @@ static int loongson_dwmac_probe(struct pci_dev *pdev,
> >>   		ld->dwlgmac_dma_ops.dma_interrupt = dwlgmac_dma_interrupt;
> >>   
> >>   		plat->setup = loongson_setup;
> >> +		ret = loongson_dwmac_config_multi_msi(pdev, plat, &res, np, 8);
> >> +	} else {
> >> +		ret = loongson_dwmac_config_legacy(pdev, plat, &res, np);
> >>   	}
> >>   
> >>   	plat->bsp_priv = ld;
> >> -- 
> >> 2.31.4
> >>


^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 08/11] net: stmmac: dwmac-loongson: Fix MAC speed for GNET
       [not found]     ` <4873ea5a-1b23-4512-b039-0a9198b53adf@loongson.cn>
@ 2024-03-14 13:18       ` Yanteng Si
  2024-03-19 17:02         ` Serge Semin
  0 siblings, 1 reply; 97+ messages in thread
From: Yanteng Si @ 2024-03-14 13:18 UTC (permalink / raw)
  To: Serge Semin
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang


在 2024/3/14 17:43, Yanteng Si 写道:
> 在 2024/2/6 05:55, Serge Semin 写道:
> > On Tue, Jan 30, 2024 at 04:48:20PM +0800, Yanteng Si wrote:
> >> Current GNET on LS7A only supports ANE when speed is
> >> set to 1000M.
> > If so you need to merge it into the patch
> > [PATCH net-next v8 06/11] net: stmmac: dwmac-loongson: Add GNET support

>> Current GNET on LS7A only supports ANE when speed is
>> set to 1000M.

>If so you need to merge it into the patch
>[PATCH net-next v8 06/11] net: stmmac: dwmac-loongson: Add GNET support

OK.

> >
> >> Signed-off-by: Yanteng Si<siyanteng@loongson.cn>
> >> Signed-off-by: Feiyang Chen<chenfeiyang@loongson.cn>
> >> Signed-off-by: Yinggang Gu<guyinggang@loongson.cn>
> >> ---
> >>   .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 19 +++++++++++++++++++
> >>   .../ethernet/stmicro/stmmac/stmmac_ethtool.c  |  6 ++++++
> >>   include/linux/stmmac.h                        |  1 +
> >>   3 files changed, 26 insertions(+)
> >>
> >> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> >> index 60d0a122d7c9..264c4c198d5a 100644
> >> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> >> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> >> @@ -344,6 +344,21 @@ static struct stmmac_pci_info loongson_gmac_pci_info = {
> >>   	.config = loongson_gmac_config,
> >>   };
> >>   
> >> +static void loongson_gnet_fix_speed(void *priv, unsigned int speed, unsigned int mode)
> >> +{
> >> +	struct loongson_data *ld = (struct loongson_data *)priv;
> >> +	struct net_device *ndev = dev_get_drvdata(ld->dev);
> >> +	struct stmmac_priv *ptr = netdev_priv(ndev);
> >> +
> >> +	/* The controller and PHY don't work well together.
> > So there _is_ a PHY. What is the interface between MAC and PHY then?
> >
> > GMAC only has a MAC chip inside the chip and needs an external PHY chip; GNET 
> > has the PHY chip inside the chip.
> >> +	 * We need to use the PS bit to check if the controller's status
> >> +	 * is correct and reset PHY if necessary.
> >> +	 */
> >> +	if (speed == SPEED_1000)
> >> +		if (readl(ptr->ioaddr + MAC_CTRL_REG) & (1 << 15) /* PS */)
> >> +			phy_restart_aneg(ndev->phydev);
> > 1. Please add curly braces for the outer if-statement.
> OK,
> > 2. MAC_CTRL_REG.15 is defined by the GMAC_CONTROL_PS macro.
>
> OK.
>
> if(speed==SPEED_1000){
> /*MAC_CTRL_REG.15 is defined by the GMAC_CONTROL_PS macro.*/
> if(readl(ptr->ioaddr+MAC_CTRL_REG) &(1<<15))
> phy_restart_aneg(ndev->phydev);
> }
>
> > 3. How is the AN-restart helps? PHY-reset is done in
> > stmmac_init_phy()->phylink_connect_phy()->... a bit earlier than
> > this is called in the framework of the stmmac_mac_link_up() callback.
> > Wouldn't that restart AN too?
>
> Due to a bug in the chip's internal PHY, the network is still not working after
> the first self-negotiation, and it needs to be self-negotiated again.
>
> >
> >> +}
> >> +
> >>   static struct mac_device_info *loongson_setup(void *apriv)
> >>   {
> >>   	struct stmmac_priv *priv = apriv;
> >> @@ -401,6 +416,7 @@ static int loongson_gnet_data(struct pci_dev *pdev,
> >>   	plat->phy_interface = PHY_INTERFACE_MODE_INTERNAL;
> >>   
> >>   	plat->bsp_priv = &pdev->dev;
> >> +	plat->fix_mac_speed = loongson_gnet_fix_speed;
> >>   
> >>   	plat->dma_cfg->pbl = 32;
> >>   	plat->dma_cfg->pblx8 = true;
> >> @@ -416,6 +432,9 @@ static int loongson_gnet_config(struct pci_dev *pdev,
> >>   				struct stmmac_resources *res,
> >>   				struct device_node *np)
> >>   {
> >> +	if (pdev->revision == 0x00 || pdev->revision == 0x01)
> >> +		plat->flags |= STMMAC_FLAG_DISABLE_FORCE_1000;
> >> +
> > This should be in the patch
> > [PATCH net-next v8 06/11] net: stmmac: dwmac-loongson: Add GNET support
> OK.
> >
> >>   	return 0;
> >>   }
> >>   
> >> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> >> index 42d27b97dd1d..31068fbc23c9 100644
> >> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> >> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> >> @@ -422,6 +422,12 @@ stmmac_ethtool_set_link_ksettings(struct net_device *dev,
> >>   		return 0;
> >>   	}
> >>   
> >> +	if (FIELD_GET(STMMAC_FLAG_DISABLE_FORCE_1000, priv->plat->flags)) {
> > FIELD_GET()?
>
> OK,
>
> if (STMMAC_FLAG_DISABLE_FORCE_1000 & priv->plat->flags) {
>
> >
> >> +		if (cmd->base.speed == SPEED_1000 &&
> >> +		    cmd->base.autoneg != AUTONEG_ENABLE)
> >> +			return -EOPNOTSUPP;
> >> +	}
> >> +
> >>   	return phylink_ethtool_ksettings_set(priv->phylink, cmd);
> >>   }
> >>   
> >> diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
> >> index dee5ad6e48c5..2810361e4048 100644
> >> --- a/include/linux/stmmac.h
> >> +++ b/include/linux/stmmac.h
> >> @@ -221,6 +221,7 @@ struct dwmac4_addrs {
> >>   #define STMMAC_FLAG_RX_CLK_RUNS_IN_LPI		BIT(10)
> >>   #define STMMAC_FLAG_EN_TX_LPI_CLOCKGATING	BIT(11)
> >>   #define STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY	BIT(12)
> >> +#define STMMAC_FLAG_DISABLE_FORCE_1000	BIT(13)
> > Detach the change introducing the STMMAC_FLAG_DISABLE_FORCE_1000 flag
> > into a separate patch a place it before
> > [PATCH net-next v8 06/11] net: stmmac: dwmac-loongson: Add GNET support
> > as a pre-requisite/preparation patch.
> > Don't forget a _detailed_ description of why it's necessary, what is
> > wrong with GNET so 1G speed doesn't work without AN.
>
> OK.
>
>
> Thanks,
>
> Yanteng
>
> >
> > -Serge(y)
> >
> >>   
> >>   struct plat_stmmacenet_data {
> >>   	int bus_id;
> >> -- 
> >> 2.31.4
> >>


^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 04/11] net: stmmac: dwmac-loongson: Move irq config to loongson_gmac_config
  2024-03-13  8:14     ` Yanteng Si
@ 2024-03-19 13:43       ` Serge Semin
  2024-03-20 10:12         ` Yanteng Si
  0 siblings, 1 reply; 97+ messages in thread
From: Serge Semin @ 2024-03-19 13:43 UTC (permalink / raw)
  To: Yanteng Si
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

On Wed, Mar 13, 2024 at 04:14:28PM +0800, Yanteng Si wrote:
> 
> 在 2024/2/6 01:01, Serge Semin 写道:
> > On Tue, Jan 30, 2024 at 04:43:24PM +0800, Yanteng Si wrote:
> > > Add loongson_dwmac_config and moving irq config related
> > > code to loongson_dwmac_config.
> > > 
> > > Removing MSI to prepare for adding loongson multi-channel
> > > support later.
> > Please detach this change into a separate patch and thoroughly explain
> > why it was necessary.
> OK.
> > 
> > > Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
> > > Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
> > > Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
> > > ---
> > >   .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 85 ++++++++++++-------
> > >   1 file changed, 55 insertions(+), 30 deletions(-)
> > > 
> > > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > index 979c9b6dab3f..e7ce027cc14e 100644
> > > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > @@ -11,8 +11,46 @@
> > >   struct stmmac_pci_info {
> > >   	int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat);
> > > +	int (*config)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat,
> > > +		      struct stmmac_resources *res, struct device_node *np);
> > >   };
> > > +static int loongson_dwmac_config_legacy(struct pci_dev *pdev,
> > > +					struct plat_stmmacenet_data *plat,
> > > +					struct stmmac_resources *res,
> > > +					struct device_node *np)
> > > +{
> > > +	if (np) {
> > > +		res->irq = of_irq_get_byname(np, "macirq");
> > > +		if (res->irq < 0) {
> > > +			dev_err(&pdev->dev, "IRQ macirq not found\n");
> > > +			return -ENODEV;
> > > +		}
> > > +
> > > +		res->wol_irq = of_irq_get_byname(np, "eth_wake_irq");
> > > +		if (res->wol_irq < 0) {
> > > +			dev_info(&pdev->dev,
> > > +				 "IRQ eth_wake_irq not found, using macirq\n");
> > > +			res->wol_irq = res->irq;
> > > +		}
> > > +
> > > +		res->lpi_irq = of_irq_get_byname(np, "eth_lpi");
> > > +		if (res->lpi_irq < 0) {
> > > +			dev_err(&pdev->dev, "IRQ eth_lpi not found\n");
> > > +			return -ENODEV;
> > > +		}
> > > +	} else {
> > > +		res->irq = pdev->irq;
> > > +		res->wol_irq = res->irq;
> > > +	}
> > > +
> > > +	plat->flags &= ~STMMAC_FLAG_MULTI_MSI_EN;
> > > +	dev_info(&pdev->dev, "%s: Single IRQ enablement successful\n",
> > > +		 __func__);
> > Why is this here all of the sudden? I don't see this in the original
> > code. Please move it to the patch which requires the flag
> > setup/cleanup or drop if it isn't necessary.
> 

> +	plat->flags &= ~STMMAC_FLAG_MULTI_MSI_EN;
> This cannot be removed because it appeared in a rebase(v4 -> v5). See
> <https://lore.kernel.org/all/20230710090001.303225-9-brgl@bgdev.pl/>

AFAICS it _can_ be removed. The patch you referred to is a formal
conversion of
-	plat->multi_msi_en = 0;
to
+	plat->flags &= ~STMMAC_FLAG_MULTI_MSI_EN;
First of all the "multi_msi_en" field clearance had been
redundant there since the code setting the flag was executed after the
code which may cause the field clearance performed. Second AFAICS the
"multi_msi_en" field clearance was originally added to emphasize the
functions semantics:
intel_eth_config_multi_msi() - config multi IRQ device,
intel_eth_config_single_msi() - config single IRQ device.

So in your case there is no any reason of clearing the
STMMAC_FLAG_MULTI_MSI_EN flag. Please, either drop it or move the
change into a separate patch.

-Serge(y)

> +	dev_info(&pdev->dev, "%s: Single IRQ enablement successful\n",
> +		 __func__);
> 
> OK, drop it.
> 
> > 
> > > +
> > > +	return 0;
> > > +}
> > > +
> > >   static void loongson_default_data(struct pci_dev *pdev,
> > >   				  struct plat_stmmacenet_data *plat)
> > >   {
> > > @@ -66,8 +104,21 @@ static int loongson_gmac_data(struct pci_dev *pdev,
> > >   	return 0;
> > >   }
> > > +static int loongson_gmac_config(struct pci_dev *pdev,
> > > +				struct plat_stmmacenet_data *plat,
> > > +				struct stmmac_resources *res,
> > > +				struct device_node *np)
> > > +{
> > > +	int ret;
> > > +
> > > +	ret = loongson_dwmac_config_legacy(pdev, plat, res, np);
> > > +
> > > +	return ret;
> > > +}
> > > +
> > You introduce the config callback here and convert to a dummy method
> > in
> > [PATCH 07/11] net: stmmac: dwmac-loongson: Add multi-channel supports for loongson
> > It's just pointless. What about introducing the
> > loongson_dwmac_config_legacy() method and call it directly?
> OK, I will try.
> > 
> > >   static struct stmmac_pci_info loongson_gmac_pci_info = {
> > >   	.setup = loongson_gmac_data,
> > > +	.config = loongson_gmac_config,
> > >   };
> > >   static int loongson_dwmac_probe(struct pci_dev *pdev,
> > > @@ -139,44 +190,19 @@ static int loongson_dwmac_probe(struct pci_dev *pdev,
> > >   		plat->phy_interface = phy_mode;
> > >   	}
> > > -	pci_enable_msi(pdev);
> > See my first note in this message.
> 
> OK.
> 
> 
> Thanks,
> 
> Yanteng
> 
> > 
> > -Serge(y)
> > 
> > >   	memset(&res, 0, sizeof(res));
> > >   	res.addr = pcim_iomap_table(pdev)[0];
> > > -	if (np) {
> > > -		res.irq = of_irq_get_byname(np, "macirq");
> > > -		if (res.irq < 0) {
> > > -			dev_err(&pdev->dev, "IRQ macirq not found\n");
> > > -			ret = -ENODEV;
> > > -			goto err_disable_msi;
> > > -		}
> > > -
> > > -		res.wol_irq = of_irq_get_byname(np, "eth_wake_irq");
> > > -		if (res.wol_irq < 0) {
> > > -			dev_info(&pdev->dev,
> > > -				 "IRQ eth_wake_irq not found, using macirq\n");
> > > -			res.wol_irq = res.irq;
> > > -		}
> > > -
> > > -		res.lpi_irq = of_irq_get_byname(np, "eth_lpi");
> > > -		if (res.lpi_irq < 0) {
> > > -			dev_err(&pdev->dev, "IRQ eth_lpi not found\n");
> > > -			ret = -ENODEV;
> > > -			goto err_disable_msi;
> > > -		}
> > > -	} else {
> > > -		res.irq = pdev->irq;
> > > -		res.wol_irq = pdev->irq;
> > > -	}
> > > +	ret = info->config(pdev, plat, &res, np);
> > > +	if (ret)
> > > +		goto err_disable_device;
> > >   	ret = stmmac_dvr_probe(&pdev->dev, plat, &res);
> > >   	if (ret)
> > > -		goto err_disable_msi;
> > > +		goto err_disable_device;
> > >   	return ret;
> > > -err_disable_msi:
> > > -	pci_disable_msi(pdev);
> > >   err_disable_device:
> > >   	pci_disable_device(pdev);
> > >   err_put_node:
> > > @@ -200,7 +226,6 @@ static void loongson_dwmac_remove(struct pci_dev *pdev)
> > >   		break;
> > >   	}
> > > -	pci_disable_msi(pdev);
> > >   	pci_disable_device(pdev);
> > >   }
> > > -- 
> > > 2.31.4
> > > 
> 

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 01/11] net: stmmac: Add multi-channel support
  2024-03-13  9:10           ` Yanteng Si
@ 2024-03-19 14:18             ` Serge Semin
  2024-03-20  9:47               ` Yanteng Si
  2024-03-20  9:55               ` Russell King (Oracle)
  0 siblings, 2 replies; 97+ messages in thread
From: Serge Semin @ 2024-03-19 14:18 UTC (permalink / raw)
  To: Yanteng Si
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

On Wed, Mar 13, 2024 at 05:10:54PM +0800, Yanteng Si wrote:
> Hi Serge

How come almost all of yours recent replies have been formatted as if
with no inline messages? See
https://lore.kernel.org/netdev/034d1f08-a110-4e68-abf5-35e7714ea5ae@loongson.cn/
It's very-very-very hard to read. Please never do that.

> 
> 在 2024/3/13 15:01, Yanteng Si 写道:
> > 在 2024/2/21 21:48, Serge Semin 写道:
> > > Hi Yanteng
> > >
> > > On Mon, Feb 19, 2024 at 07:02:24PM +0800, Yanteng Si wrote:
> > >> Hi Serge
> > >>
> > >> 在 2024/2/5 07:28, Serge Semin 写道:
> > >>> On Tue, Jan 30, 2024 at 04:43:21PM +0800, Yanteng Si wrote:
> > >>>> DW GMAC v3.x multi-channels feature is implemented as multiple
> > >>>> sets of the same CSRs. Here is only preliminary support, it will
> > >>>> be useful for the driver further evolution and for the users
> > >>>> having multi-channel DWGMAC v3.x devices.
> > >>>>
> > >>>> Signed-off-by: Yanteng Si<siyanteng@loongson.cn>
> > >>>> Signed-off-by: Feiyang Chen<chenfeiyang@loongson.cn>
> > >>>> Signed-off-by: Yinggang Gu<guyinggang@loongson.cn>
> > >>>> ---
> > >>>>    .../net/ethernet/stmicro/stmmac/dwmac-sun8i.c |  2 +-
> > >>>>    .../ethernet/stmicro/stmmac/dwmac1000_dma.c   | 36 ++++++++++---------
> > >>>>    .../net/ethernet/stmicro/stmmac/dwmac_dma.h   | 19 +++++++++-
> > >>>>    .../net/ethernet/stmicro/stmmac/dwmac_lib.c   | 32 ++++++++---------
> > >>>>    drivers/net/ethernet/stmicro/stmmac/hwif.h    |  2 +-
> > >>>>    .../net/ethernet/stmicro/stmmac/stmmac_main.c |  6 ++--
> > >>>>    6 files changed, 58 insertions(+), 39 deletions(-)
> > >>>>
> > >>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
> > >>>> index 137741b94122..7cdfa0bdb93a 100644
> > >>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
> > >>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
> > >>>> @@ -395,7 +395,7 @@ static void sun8i_dwmac_dma_start_tx(struct stmmac_priv *priv,
> > >>>>    	writel(v, ioaddr + EMAC_TX_CTL1);
> > >>>>    }
> > >>>> -static void sun8i_dwmac_enable_dma_transmission(void __iomem *ioaddr)
> > >>>> +static void sun8i_dwmac_enable_dma_transmission(void __iomem *ioaddr, u32 chan)
> > >>>>    {
> > >>>>    	u32 v;
> > >>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> > >>>> index daf79cdbd3ec..5f7b82ad3ec2 100644
> > >>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> > >>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> > >>>> @@ -70,15 +70,18 @@ static void dwmac1000_dma_axi(void __iomem *ioaddr, struct stmmac_axi *axi)
> > >>>>    	writel(value, ioaddr + DMA_AXI_BUS_MODE);
> > >>>>    }
> > >>>> -static void dwmac1000_dma_init(void __iomem *ioaddr,
> > >>>> -			       struct stmmac_dma_cfg *dma_cfg, int atds)
> > >>>> +static void dwmac1000_dma_init_channel(struct stmmac_priv *priv,
> > >>>> +				       void __iomem *ioaddr,
> > >>>> +				       struct stmmac_dma_cfg *dma_cfg, u32 chan)
> > >>>>    {
> > >>>> -	u32 value = readl(ioaddr + DMA_BUS_MODE);
> > >>>> +	u32 value;
> > >>>>    	int txpbl = dma_cfg->txpbl ?: dma_cfg->pbl;
> > >>>>    	int rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl;
> > >>> Reverse xmas tree please.
> > >>>
> > >>>> -	/*
> > >>>> -	 * Set the DMA PBL (Programmable Burst Length) mode.
> > >>>> +	/* common channel control register config */
> > >>> Redundant comment. Please drop.
> > >>>
> > >>>> +	value = readl(ioaddr + DMA_CHAN_BUS_MODE(chan));
> > >>>> +
> > >>>> +	/* Set the DMA PBL (Programmable Burst Length) mode.
> > >>>>    	 *
> > >>>>    	 * Note: before stmmac core 3.50 this mode bit was 4xPBL, and
> > >>>>    	 * post 3.5 mode bit acts as 8*PBL.
> > >>>> @@ -98,16 +101,15 @@ static void dwmac1000_dma_init(void __iomem *ioaddr,
> > >>>>    	if (dma_cfg->mixed_burst)
> > >>>>    		value |= DMA_BUS_MODE_MB;
> > >>>> -	if (atds)
> > >>>> -		value |= DMA_BUS_MODE_ATDS;
> > >>>> +	value |= DMA_BUS_MODE_ATDS;
> > >>> No, just convert the stmmac_dma_ops.dma_init_channel() to accepting
> > >>> the atds flag as I suggested in v7:
> > >>> https://lore.kernel.org/netdev/vxcfrxtbfu4pya56m22icnizsyjzqqha5blzb7zpexqcur56uh@uv6vsjf77npa/
> > >>>
> > >>> In order to simplify this patch you can provide the
> > >>> stmmac_dma_ops.dma_init_channel() and
> > >>> stmmac_dma_ops.enable_dma_transmission() prototype updates in a
> > >>> pre-requisite/preparation patch.
> > >> Sorry to keep you waiting for so long, I finally got the machine again.
> > >> Regarding atds, is this how it is implemented?
> > >>
> > >> On the basis of applying PATCH v8:
> > >>
> > >> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> > >> b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> > >> index 0323f0a5049c..ce99f4a1b320 100644
> > >> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> > >> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> > >> @@ -72,7 +72,8 @@ static void dwmac1000_dma_axi(void __iomem *ioaddr, struct
> > >> stmmac_axi *axi)
> > >>
> > >>   static void dwmac1000_dma_init_channel(struct stmmac_priv *priv,
> > >>                          void __iomem *ioaddr,
> > >> -                       struct stmmac_dma_cfg *dma_cfg, u32 chan)
> > >> +                       struct stmmac_dma_cfg *dma_cfg,
> > >> +                       int atds, u32 chan)
> > >>   {
> > >>       u32 value;
> > >>       int txpbl = dma_cfg->txpbl ?: dma_cfg->pbl;
> > >> @@ -101,7 +102,8 @@ static void dwmac1000_dma_init_channel(struct
> > >> stmmac_priv *priv,
> > >>       if (dma_cfg->mixed_burst)
> > >>           value |= DMA_BUS_MODE_MB;
> > >>
> > >> -    value |= DMA_BUS_MODE_ATDS;
> > >> +    if (atds)
> > >> +        value |= DMA_BUS_MODE_ATDS;
> > >>
> > >>       if (dma_cfg->aal)
> > >>           value |= DMA_BUS_MODE_AAL;
> > >> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
> > >> b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
> > >> index 84d3a8551b03..8a79c154b553 100644
> > >> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
> > >> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
> > >> @@ -117,7 +117,8 @@ static void dwmac4_dma_init_tx_chan(struct stmmac_priv
> > >> *priv,
> > >>
> > >>   static void dwmac4_dma_init_channel(struct stmmac_priv *priv,
> > >>                       void __iomem *ioaddr,
> > >> -                    struct stmmac_dma_cfg *dma_cfg, u32 chan)
> > >> +                    struct stmmac_dma_cfg *dma_cfg,
> > >> +                                    int atds, u32 chan)
> > >>   {
> > >>       const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;
> > >>       u32 value;
> > >> @@ -135,7 +136,8 @@ static void dwmac4_dma_init_channel(struct stmmac_priv
> > >> *priv,
> > >>
> > >>   static void dwmac410_dma_init_channel(struct stmmac_priv *priv,
> > >>                         void __iomem *ioaddr,
> > >> -                      struct stmmac_dma_cfg *dma_cfg, u32 chan)
> > >> +                      struct stmmac_dma_cfg *dma_cfg,
> > >> +                                      int atds, u32 chan)
> > >>   {
> > >>       const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;
> > >>       u32 value;
> > >> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
> > >> b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
> > >> index dd2ab6185c40..d1627b2e50c8 100644
> > >> --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
> > >> +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
> > >> @@ -35,7 +35,8 @@ static void dwxgmac2_dma_init(void __iomem *ioaddr,
> > >>
> > >>   static void dwxgmac2_dma_init_chan(struct stmmac_priv *priv,
> > >>                      void __iomem *ioaddr,
> > >> -                   struct stmmac_dma_cfg *dma_cfg, u32 chan)
> > >> +                   struct stmmac_dma_cfg *dma_cfg,
> > >> +                                   int atds, u32 chan)
> > >>   {
> > >>       u32 value = readl(ioaddr + XGMAC_DMA_CH_CONTROL(chan));
> > >>
> > >> diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h
> > >> b/drivers/net/ethernet/stmicro/stmmac/hwif.h
> > >> index b0db38396171..fb27ad0e97e8 100644
> > >> --- a/drivers/net/ethernet/stmicro/stmmac/hwif.h
> > >> +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h
> > >> @@ -178,7 +178,7 @@ struct stmmac_dma_ops {
> > >>       void (*init)(void __iomem *ioaddr, struct stmmac_dma_cfg *dma_cfg,
> > >>                int atds);
> > >>       void (*init_chan)(struct stmmac_priv *priv, void __iomem *ioaddr,
> > >> -              struct stmmac_dma_cfg *dma_cfg, u32 chan);
> > >> +              struct stmmac_dma_cfg *dma_cfg, int atds, u32 chan);
> > >>       void (*init_rx_chan)(struct stmmac_priv *priv, void __iomem *ioaddr,
> > >>                    struct stmmac_dma_cfg *dma_cfg,
> > >>                    dma_addr_t phy, u32 chan);
> > >> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> > >> b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> > >> index 3eed202d1f1c..8705e04913d1 100644
> > >> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> > >> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> > >> @@ -3039,7 +3039,7 @@ static int stmmac_init_dma_engine(struct stmmac_priv
> > >> *priv)
> > >>
> > >>       /* DMA CSR Channel configuration */
> > >>       for (chan = 0; chan < dma_csr_ch; chan++) {
> > >> -        stmmac_init_chan(priv, priv->ioaddr, priv->plat->dma_cfg, chan);
> > >> +        stmmac_init_chan(priv, priv->ioaddr, priv->plat->dma_cfg, atds,
> > >> chan);
> > >>           stmmac_disable_dma_irq(priv, priv->ioaddr, chan, 1, 1);
> > >>       }
> > >>
> > >> @@ -6963,6 +6963,7 @@ int stmmac_xdp_open(struct net_device *dev)
> > >>       u32 buf_size;
> > >>       bool sph_en;
> > >>       u32 chan;
> > >> +     int atds;
> > >>       int ret;
> > >>
> > >>       ret = alloc_dma_desc_resources(priv, &priv->dma_conf);
> > >> @@ -6981,9 +6982,12 @@ int stmmac_xdp_open(struct net_device *dev)
> > >>
> > >>       stmmac_reset_queues_param(priv);
> > >>
> > >> +    if (priv->extend_desc && (priv->mode == STMMAC_RING_MODE))
> > >> +        atds = 1;
> > >> +
> > >>       /* DMA CSR Channel configuration */
> > >>       for (chan = 0; chan < dma_csr_ch; chan++) {
> > >> -        stmmac_init_chan(priv, priv->ioaddr, priv->plat->dma_cfg, chan);
> > >> +        stmmac_init_chan(priv, priv->ioaddr, priv->plat->dma_cfg, atds,
> > >> chan);
> > >>           stmmac_disable_dma_irq(priv, priv->ioaddr, chan, 1, 1);
> > >>       }
> > > Looking more thoroughly at this part I suggest to act a bit
> > > differently. Let's move the atds flag to the stmmac_dma_cfg structure.
> > > Alternate Descriptor Size (ATDS) is a part of the DMA-configs together
> > > with the PBL, ALL, AEME, etc so the structure is the most suitable
> > > place for it. Here is what should be done for that:
> > > 1. Add stmmac_dma_cfg::atds boolean field.
> > > 2. Drop atds argument from the stmmac_dma_ops::init() callback and use
> > > the stmmac_dma_cfg::atds field in the callback implementations.
> > > 3. Alter stmmac_init_dma_engine() to updating the dma_cfg->atds field
> > > instead of the local variable.
> > >
> > > Please implement that update in a pre-requisite/preparation patch.
> > >
> > > After that you can freely use the stmmac_dma_cfg::atds field in the
> > > stmmac_init_chan() method too.
> > 
> > OK.
> > 
> > 
> > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > index b57e1325ce62..dabd6a3772f2 100644
> > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > @@ -66,8 +66,7 @@ struct loongson_data {
> > 
> >    static void loongson_gnet_dma_init_channel(struct stmmac_priv *priv,
> >                         void __iomem *ioaddr,
> > -                     struct stmmac_dma_cfg *dma_cfg,
> > -                                     int atds, u32 chan)
> > +                     struct stmmac_dma_cfg *dma_cfg, u32 chan)
> >    {
> >        int txpbl = dma_cfg->txpbl ?: dma_cfg->pbl;
> >        int rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl;
> > @@ -96,7 +95,7 @@ static void loongson_gnet_dma_init_channel(struct stmmac_priv
> > *priv,
> >        if (dma_cfg->mixed_burst)
> >            value |= DMA_BUS_MODE_MB;
> > 
> > -    if (atds)
> > +    if (dma_cfg->atds)
> >            value |= DMA_BUS_MODE_ATDS;
> > 
> >        if (dma_cfg->aal)
> > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
> > b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
> > index 7001a86425ea..ae9240736e64 100644
> > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
> > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
> > @@ -299,7 +299,7 @@ static int sun8i_dwmac_dma_reset(void __iomem *ioaddr)
> >     * Called from stmmac via stmmac_dma_ops->init
> >     */
> >    static void sun8i_dwmac_dma_init(void __iomem *ioaddr,
> > -                 struct stmmac_dma_cfg *dma_cfg, int atds)
> > +                 struct stmmac_dma_cfg *dma_cfg)
> >    {
> >        writel(EMAC_RX_INT | EMAC_TX_INT, ioaddr + EMAC_INT_EN);
> >        writel(0x1FFFFFF, ioaddr + EMAC_INT_STA);
> > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> > b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> > index fd5ecc043251..66c0c22908b1 100644
> > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> > @@ -72,8 +72,7 @@ static void dwmac1000_dma_axi(void __iomem *ioaddr, struct
> > stmmac_axi *axi)
> > 
> >    static void dwmac1000_dma_init_channel(struct stmmac_priv *priv,
> >                           void __iomem *ioaddr,
> > -                       struct stmmac_dma_cfg *dma_cfg,
> > -                       int atds, u32 chan)
> > +                       struct stmmac_dma_cfg *dma_cfg, u32 chan)
> >    {
> >        int txpbl = dma_cfg->txpbl ?: dma_cfg->pbl;
> >        int rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl;
> > @@ -101,7 +100,7 @@ static void dwmac1000_dma_init_channel(struct stmmac_priv *priv,
> >        if (dma_cfg->mixed_burst)
> >            value |= DMA_BUS_MODE_MB;
> > 
> > -    if (atds)
> > +    if (dma_cfg->atds)
> >            value |= DMA_BUS_MODE_ATDS;
> > 
> >        if (dma_cfg->aal)
> > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
> > b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
> > index dea270f60cc3..f861babc06f9 100644
> > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
> > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
> > @@ -19,7 +19,7 @@
> >    #include "dwmac_dma.h"
> > 
> >    static void dwmac100_dma_init(void __iomem *ioaddr,
> > -                  struct stmmac_dma_cfg *dma_cfg, int atds)
> > +                  struct stmmac_dma_cfg *dma_cfg)
> >    {
> >        /* Enable Application Access by writing to DMA CSR0 */
> >        writel(DMA_BUS_MODE_DEFAULT | (dma_cfg->pbl << DMA_BUS_MODE_PBL_SHIFT),
> > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
> > b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
> > index 8a79c154b553..e0165358c4ac 100644
> > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
> > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
> > @@ -117,8 +117,7 @@ static void dwmac4_dma_init_tx_chan(struct stmmac_priv *priv,
> > 
> >    static void dwmac4_dma_init_channel(struct stmmac_priv *priv,
> >                        void __iomem *ioaddr,
> > -                    struct stmmac_dma_cfg *dma_cfg,
> > -                                    int atds, u32 chan)
> > +                    struct stmmac_dma_cfg *dma_cfg, u32 chan)
> >    {
> >        const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;
> >        u32 value;
> > @@ -136,8 +135,7 @@ static void dwmac4_dma_init_channel(struct stmmac_priv *priv,
> > 
> >    static void dwmac410_dma_init_channel(struct stmmac_priv *priv,
> >                          void __iomem *ioaddr,
> > -                      struct stmmac_dma_cfg *dma_cfg,
> > -                                      int atds, u32 chan)
> > +                      struct stmmac_dma_cfg *dma_cfg, u32 chan)
> >    {
> >        const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;
> >        u32 value;
> > @@ -155,7 +153,7 @@ static void dwmac410_dma_init_channel(struct stmmac_priv *priv,
> >    }
> > 
> >    static void dwmac4_dma_init(void __iomem *ioaddr,
> > -                struct stmmac_dma_cfg *dma_cfg, int atds)
> > +                struct stmmac_dma_cfg *dma_cfg)
> >    {
> >        u32 value = readl(ioaddr + DMA_SYS_BUS_MODE);
> > 
> > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
> > b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
> > index d1627b2e50c8..7840bc403788 100644
> > --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
> > +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
> > @@ -20,7 +20,7 @@ static int dwxgmac2_dma_reset(void __iomem *ioaddr)
> >    }
> > 
> >    static void dwxgmac2_dma_init(void __iomem *ioaddr,
> > -                  struct stmmac_dma_cfg *dma_cfg, int atds)
> > +                  struct stmmac_dma_cfg *dma_cfg)
> >    {
> >        u32 value = readl(ioaddr + XGMAC_DMA_SYSBUS_MODE);
> > 
> > @@ -35,8 +35,7 @@ static void dwxgmac2_dma_init(void __iomem *ioaddr,
> > 
> >    static void dwxgmac2_dma_init_chan(struct stmmac_priv *priv,
> >                       void __iomem *ioaddr,
> > -                   struct stmmac_dma_cfg *dma_cfg,
> > -                                   int atds, u32 chan)
> > +                   struct stmmac_dma_cfg *dma_cfg, u32 chan)
> >    {
> >        u32 value = readl(ioaddr + XGMAC_DMA_CH_CONTROL(chan));
> > 
> > diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h
> > b/drivers/net/ethernet/stmicro/stmmac/hwif.h
> > index fb27ad0e97e8..3b20fb7f3a61 100644
> > --- a/drivers/net/ethernet/stmicro/stmmac/hwif.h
> > +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h
> > @@ -175,10 +175,9 @@ struct dma_features;
> >    struct stmmac_dma_ops {
> >        /* DMA core initialization */
> >        int (*reset)(void __iomem *ioaddr);
> > -    void (*init)(void __iomem *ioaddr, struct stmmac_dma_cfg *dma_cfg,
> > -             int atds);
> > +    void (*init)(void __iomem *ioaddr, struct stmmac_dma_cfg *dma_cfg);
> >        void (*init_chan)(struct stmmac_priv *priv, void __iomem *ioaddr,
> > -              struct stmmac_dma_cfg *dma_cfg, int atds, u32 chan);
> > +              struct stmmac_dma_cfg *dma_cfg, u32 chan);
> >        void (*init_rx_chan)(struct stmmac_priv *priv, void __iomem *ioaddr,
> >                     struct stmmac_dma_cfg *dma_cfg,
> >                     dma_addr_t phy, u32 chan);
> > diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> > b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> > index 7c656f970575..957dfabc663d 100644
> > --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> > +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> > @@ -3013,7 +3013,6 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv)
> >        struct stmmac_rx_queue *rx_q;
> >        struct stmmac_tx_queue *tx_q;
> >        u32 chan = 0;
> > -    int atds = 0;
> >        int ret = 0;
> > 
> >        if (!priv->plat->dma_cfg || !priv->plat->dma_cfg->pbl) {
> > @@ -3022,7 +3021,7 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv)
> >        }
> > 
> >        if (priv->extend_desc && (priv->mode == STMMAC_RING_MODE))
> > -        atds = 1;
> > +        priv->plat->dma_cfg->atds = 1;
> > 
> >        ret = stmmac_reset(priv, priv->ioaddr);
> >        if (ret) {
> > @@ -3031,14 +3030,14 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv)
> >        }
> > 
> >        /* DMA Configuration */
> > -    stmmac_dma_init(priv, priv->ioaddr, priv->plat->dma_cfg, atds);
> > +    stmmac_dma_init(priv, priv->ioaddr, priv->plat->dma_cfg);
> > 
> >        if (priv->plat->axi)
> >            stmmac_axi(priv, priv->ioaddr, priv->plat->axi);
> > 
> >        /* DMA CSR Channel configuration */
> >        for (chan = 0; chan < dma_csr_ch; chan++) {
> > -        stmmac_init_chan(priv, priv->ioaddr, priv->plat->dma_cfg, atds, chan);
> > +        stmmac_init_chan(priv, priv->ioaddr, priv->plat->dma_cfg, chan);
> >            stmmac_disable_dma_irq(priv, priv->ioaddr, chan, 1, 1);
> >        }
> > 
> > @@ -6962,7 +6961,6 @@ int stmmac_xdp_open(struct net_device *dev)
> >        u32 buf_size;
> >        bool sph_en;
> >        u32 chan;
> > -        int atds;
> >        int ret;
> > 
> >        ret = alloc_dma_desc_resources(priv, &priv->dma_conf);
> > @@ -6981,12 +6979,9 @@ int stmmac_xdp_open(struct net_device *dev)
> > 
> >        stmmac_reset_queues_param(priv);
> > 
> > -    if (priv->extend_desc && (priv->mode == STMMAC_RING_MODE))
> > -        atds = 1;
> > -
> >        /* DMA CSR Channel configuration */
> >        for (chan = 0; chan < dma_csr_ch; chan++) {
> > -        stmmac_init_chan(priv, priv->ioaddr, priv->plat->dma_cfg, atds, chan);
> > +        stmmac_init_chan(priv, priv->ioaddr, priv->plat->dma_cfg, chan);
> >            stmmac_disable_dma_irq(priv, priv->ioaddr, chan, 1, 1);
> >        }
> > 
> > diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
> > index 23bfe3c1465f..c827dc1213b9 100644
> > --- a/include/linux/stmmac.h
> > +++ b/include/linux/stmmac.h
> > @@ -100,6 +100,7 @@ struct stmmac_dma_cfg {
> >        bool eame;
> >        bool multi_msi_en;
> >        bool dche;
> > +    bool atds;
> >    };
> > 
> >    #define AXI_BLEN    7
> > 

Ok. Let's see how it looks in a separate patch of the v9 series.

-Serge(y)

> > 
> > Thanks,
> > 
> > Yanteng
> > 
> > >
> > > -Serge(y)
> > >
> > >>
> > >> Thanks,
> > >>
> > >> Yanteng
> > >>
> > >>>>    	if (dma_cfg->aal)
> > >>>>    		value |= DMA_BUS_MODE_AAL;
> > >>>> -	writel(value, ioaddr + DMA_BUS_MODE);
> > >>>> +	writel(value, ioaddr + DMA_CHAN_BUS_MODE(chan));
> > >>>>    	/* Mask interrupts by writing to CSR7 */
> > >>>> -	writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_INTR_ENA);
> > >>>> +	writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_CHAN_INTR_ENA(chan));
> > >>>>    }
> > >>>>    static void dwmac1000_dma_init_rx(struct stmmac_priv *priv,
> > >>>> @@ -116,7 +118,7 @@ static void dwmac1000_dma_init_rx(struct stmmac_priv *priv,
> > >>>>    				  dma_addr_t dma_rx_phy, u32 chan)
> > >>>>    {
> > >>>>    	/* RX descriptor base address list must be written into DMA CSR3 */
> > >>>> -	writel(lower_32_bits(dma_rx_phy), ioaddr + DMA_RCV_BASE_ADDR);
> > >>>> +	writel(lower_32_bits(dma_rx_phy), ioaddr + DMA_CHAN_RCV_BASE_ADDR(chan));
> > >>>>    }
> > >>>>    static void dwmac1000_dma_init_tx(struct stmmac_priv *priv,
> > >>>> @@ -125,7 +127,7 @@ static void dwmac1000_dma_init_tx(struct stmmac_priv *priv,
> > >>>>    				  dma_addr_t dma_tx_phy, u32 chan)
> > >>>>    {
> > >>>>    	/* TX descriptor base address list must be written into DMA CSR4 */
> > >>>> -	writel(lower_32_bits(dma_tx_phy), ioaddr + DMA_TX_BASE_ADDR);
> > >>>> +	writel(lower_32_bits(dma_tx_phy), ioaddr + DMA_CHAN_TX_BASE_ADDR(chan));
> > >>>>    }
> > >>>>    static u32 dwmac1000_configure_fc(u32 csr6, int rxfifosz)
> > >>>> @@ -153,7 +155,7 @@ static void dwmac1000_dma_operation_mode_rx(struct stmmac_priv *priv,
> > >>>>    					    void __iomem *ioaddr, int mode,
> > >>>>    					    u32 channel, int fifosz, u8 qmode)
> > >>>>    {
> > >>>> -	u32 csr6 = readl(ioaddr + DMA_CONTROL);
> > >>>> +	u32 csr6 = readl(ioaddr + DMA_CHAN_CONTROL(channel));
> > >>>>    	if (mode == SF_DMA_MODE) {
> > >>>>    		pr_debug("GMAC: enable RX store and forward mode\n");
> > >>>> @@ -175,14 +177,14 @@ static void dwmac1000_dma_operation_mode_rx(struct stmmac_priv *priv,
> > >>>>    	/* Configure flow control based on rx fifo size */
> > >>>>    	csr6 = dwmac1000_configure_fc(csr6, fifosz);
> > >>>> -	writel(csr6, ioaddr + DMA_CONTROL);
> > >>>> +	writel(csr6, ioaddr + DMA_CHAN_CONTROL(channel));
> > >>>>    }
> > >>>>    static void dwmac1000_dma_operation_mode_tx(struct stmmac_priv *priv,
> > >>>>    					    void __iomem *ioaddr, int mode,
> > >>>>    					    u32 channel, int fifosz, u8 qmode)
> > >>>>    {
> > >>>> -	u32 csr6 = readl(ioaddr + DMA_CONTROL);
> > >>>> +	u32 csr6 = readl(ioaddr + DMA_CHAN_CONTROL(channel));
> > >>>>    	if (mode == SF_DMA_MODE) {
> > >>>>    		pr_debug("GMAC: enable TX store and forward mode\n");
> > >>>> @@ -209,7 +211,7 @@ static void dwmac1000_dma_operation_mode_tx(struct stmmac_priv *priv,
> > >>>>    			csr6 |= DMA_CONTROL_TTC_256;
> > >>>>    	}
> > >>>> -	writel(csr6, ioaddr + DMA_CONTROL);
> > >>>> +	writel(csr6, ioaddr + DMA_CHAN_CONTROL(channel));
> > >>>>    }
> > >>>>    static void dwmac1000_dump_dma_regs(struct stmmac_priv *priv,
> > >>>> @@ -271,12 +273,12 @@ static int dwmac1000_get_hw_feature(void __iomem *ioaddr,
> > >>>>    static void dwmac1000_rx_watchdog(struct stmmac_priv *priv,
> > >>>>    				  void __iomem *ioaddr, u32 riwt, u32 queue)
> > >>>>    {
> > >>>> -	writel(riwt, ioaddr + DMA_RX_WATCHDOG);
> > >>>> +	writel(riwt, ioaddr + DMA_CHAN_RX_WATCHDOG(queue));
> > >>>>    }
> > >>>>    const struct stmmac_dma_ops dwmac1000_dma_ops = {
> > >>>>    	.reset = dwmac_dma_reset,
> > >>>> -	.init = dwmac1000_dma_init,
> > >>>> +	.init_chan = dwmac1000_dma_init_channel,
> > >>>>    	.init_rx_chan = dwmac1000_dma_init_rx,
> > >>>>    	.init_tx_chan = dwmac1000_dma_init_tx,
> > >>>>    	.axi = dwmac1000_dma_axi,
> > >>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
> > >>>> index 72672391675f..593be79c46e1 100644
> > >>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
> > >>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
> > >>>> @@ -148,11 +148,14 @@
> > >>>>    					 DMA_STATUS_TI | \
> > >>>>    					 DMA_STATUS_MSK_COMMON)
> > >>>> +/* Following DMA defines are chanels oriented */    \
> > >>>> +#define DMA_CHAN_OFFSET			0x100   |-------------+
> > >>>> +                                                    /              |
> > >>>                                                                         |
> > >>> Please move all of these ---------------------------------------------+-------------------------+
> > >>> to being defined just below the DMA_MISSED_FRAME_CTR macros definition.                         |
> > >>> The point is to keep a coherency between dwmac_dma.h and dwmac4_dma.h.                          |
> > >>> The later header file has first generic DMA-related macros defined                              |
> > >>> (CSR addresses and flags) and then the channel-specific ones (CSR                               |
> > >>> addresses and flags). Since in case of the DW GMAC v3.x the                                     |
> > >>> multi-channels are implemented as a copy of all the DMA CSRs let's                              |
> > >>> preserve the logic of having all CSR address defined first, then the                            |
> > >>> CSR flags.                                                                                      |
> > >>>                                                                                                   |
> > >>>>    #define NUM_DWMAC100_DMA_REGS	9                                                       |
> > >>>>    #define NUM_DWMAC1000_DMA_REGS	23                                                      |
> > >>>>    #define NUM_DWMAC4_DMA_REGS	27                                                              |
> > >>>>                                                                                                 |
> > >>>> -void dwmac_enable_dma_transmission(void __iomem *ioaddr);                                    |
> > >>>> +void dwmac_enable_dma_transmission(void __iomem *ioaddr, u32 chan);                          |
> > >>>>    void dwmac_enable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr,                    |
> > >>>>    			  u32 chan, bool rx, bool tx);                                          |
> > >>>>    void dwmac_disable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr,                   |
> > >>>> @@ -169,4 +172,18 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,  |
> > >>>>    			struct stmmac_extra_stats *x, u32 chan, u32 dir);                       |
> > >>>>    int dwmac_dma_reset(void __iomem *ioaddr);                                                   |
> > >>>>                                                                                                 |
> > >>>                                                                                                   |
> > >>>> +static inline u32 dma_chan_base_addr(u32 base, u32 chan)                                  \  |
> > >>>> +{                                                                                          | |
> > >>>> +	return base + chan * DMA_CHAN_OFFSET;                                                 | |
> > >>>> +}                                                                                          | |
> > >>>> +                                                                                           | |
> > >>>> +#define DMA_CHAN_XMT_POLL_DEMAND(chan)	dma_chan_base_addr(DMA_XMT_POLL_DEMAND, chan) | |
> > >>>> +#define DMA_CHAN_INTR_ENA(chan)		dma_chan_base_addr(DMA_INTR_ENA, chan)        | |
> > >>>> +#define DMA_CHAN_CONTROL(chan)		dma_chan_base_addr(DMA_CONTROL, chan)         | |
> > >>>> +#define DMA_CHAN_STATUS(chan)		dma_chan_base_addr(DMA_STATUS, chan)          |-+
> > >>>> +#define DMA_CHAN_BUS_MODE(chan)		dma_chan_base_addr(DMA_BUS_MODE, chan)        |
> > >>>> +#define DMA_CHAN_RCV_BASE_ADDR(chan)	dma_chan_base_addr(DMA_RCV_BASE_ADDR, chan)           |
> > >>>> +#define DMA_CHAN_TX_BASE_ADDR(chan)	dma_chan_base_addr(DMA_TX_BASE_ADDR, chan)            |
> > >>>> +#define DMA_CHAN_RX_WATCHDOG(chan)	dma_chan_base_addr(DMA_RX_WATCHDOG, chan)             |
> > >>>> +                                                                                           /
> > >>>>    #endif /* __DWMAC_DMA_H__ */
> > >>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
> > >>>> index 7907d62d3437..b37368137810 100644
> > >>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
> > >>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
> > >>>> @@ -28,65 +28,65 @@ int dwmac_dma_reset(void __iomem *ioaddr)
> > >>>>    }
> > >>>>    /* CSR1 enables the transmit DMA to check for new descriptor */
> > >>>> -void dwmac_enable_dma_transmission(void __iomem *ioaddr)
> > >>>> +void dwmac_enable_dma_transmission(void __iomem *ioaddr, u32 chan)
> > >>>>    {
> > >>>> -	writel(1, ioaddr + DMA_XMT_POLL_DEMAND);
> > >>>> +	writel(1, ioaddr + DMA_CHAN_XMT_POLL_DEMAND(chan));
> > >>>>    }
> > >>>>    void dwmac_enable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr,
> > >>>>    			  u32 chan, bool rx, bool tx)
> > >>>>    {
> > >>>> -	u32 value = readl(ioaddr + DMA_INTR_ENA);
> > >>>> +	u32 value = readl(ioaddr + DMA_CHAN_INTR_ENA(chan));
> > >>>>    	if (rx)
> > >>>>    		value |= DMA_INTR_DEFAULT_RX;
> > >>>>    	if (tx)
> > >>>>    		value |= DMA_INTR_DEFAULT_TX;
> > >>>> -	writel(value, ioaddr + DMA_INTR_ENA);
> > >>>> +	writel(value, ioaddr + DMA_CHAN_INTR_ENA(chan));
> > >>>>    }
> > >>>>    void dwmac_disable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr,
> > >>>>    			   u32 chan, bool rx, bool tx)
> > >>>>    {
> > >>>> -	u32 value = readl(ioaddr + DMA_INTR_ENA);
> > >>>> +	u32 value = readl(ioaddr + DMA_CHAN_INTR_ENA(chan));
> > >>>>    	if (rx)
> > >>>>    		value &= ~DMA_INTR_DEFAULT_RX;
> > >>>>    	if (tx)
> > >>>>    		value &= ~DMA_INTR_DEFAULT_TX;
> > >>>> -	writel(value, ioaddr + DMA_INTR_ENA);
> > >>>> +	writel(value, ioaddr + DMA_CHAN_INTR_ENA(chan));
> > >>>>    }
> > >>>>    void dwmac_dma_start_tx(struct stmmac_priv *priv, void __iomem *ioaddr,
> > >>>>    			u32 chan)
> > >>>>    {
> > >>>> -	u32 value = readl(ioaddr + DMA_CONTROL);
> > >>>> +	u32 value = readl(ioaddr + DMA_CHAN_CONTROL(chan));
> > >>>>    	value |= DMA_CONTROL_ST;
> > >>>> -	writel(value, ioaddr + DMA_CONTROL);
> > >>>> +	writel(value, ioaddr + DMA_CHAN_CONTROL(chan));
> > >>>>    }
> > >>>>    void dwmac_dma_stop_tx(struct stmmac_priv *priv, void __iomem *ioaddr, u32 chan)
> > >>>>    {
> > >>>> -	u32 value = readl(ioaddr + DMA_CONTROL);
> > >>>> +	u32 value = readl(ioaddr + DMA_CHAN_CONTROL(chan));
> > >>>>    	value &= ~DMA_CONTROL_ST;
> > >>>> -	writel(value, ioaddr + DMA_CONTROL);
> > >>>> +	writel(value, ioaddr + DMA_CHAN_CONTROL(chan));
> > >>>>    }
> > >>>>    void dwmac_dma_start_rx(struct stmmac_priv *priv, void __iomem *ioaddr,
> > >>>>    			u32 chan)
> > >>>>    {
> > >>>> -	u32 value = readl(ioaddr + DMA_CONTROL);
> > >>>> +	u32 value = readl(ioaddr + DMA_CHAN_CONTROL(chan));
> > >>>>    	value |= DMA_CONTROL_SR;
> > >>>> -	writel(value, ioaddr + DMA_CONTROL);
> > >>>> +	writel(value, ioaddr + DMA_CHAN_CONTROL(chan));
> > >>>>    }
> > >>>>    void dwmac_dma_stop_rx(struct stmmac_priv *priv, void __iomem *ioaddr, u32 chan)
> > >>>>    {
> > >>>> -	u32 value = readl(ioaddr + DMA_CONTROL);
> > >>>> +	u32 value = readl(ioaddr + DMA_CHAN_CONTROL(chan));
> > >>>>    	value &= ~DMA_CONTROL_SR;
> > >>>> -	writel(value, ioaddr + DMA_CONTROL);
> > >>>> +	writel(value, ioaddr + DMA_CHAN_CONTROL(chan));
> > >>>>    }
> > >>>>    #ifdef DWMAC_DMA_DEBUG
> > >>>> @@ -166,7 +166,7 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
> > >>>>    	struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[chan];
> > >>>>    	int ret = 0;
> > >>>>    	/* read the status register (CSR5) */
> > >>>> -	u32 intr_status = readl(ioaddr + DMA_STATUS);
> > >>>> +	u32 intr_status = readl(ioaddr + DMA_CHAN_STATUS(chan));
> > >>>>    #ifdef DWMAC_DMA_DEBUG
> > >>>>    	/* Enable it to monitor DMA rx/tx status in case of critical problems */
> > >>>> @@ -236,7 +236,7 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
> > >>>>    		pr_warn("%s: unexpected status %08x\n", __func__, intr_status);
> > >>>>    	/* Clear the interrupt by writing a logic 1 to the CSR5[15-0] */
> > >>>> -	writel((intr_status & 0x1ffff), ioaddr + DMA_STATUS);
> > >>>> +	writel((intr_status & 0x7ffff), ioaddr + DMA_CHAN_STATUS(chan));
> > >>> Isn't the mask change going to be implemented in the framework of the
> > >>> Loongson-specific DMA-interrupt handler in some of the further patches?
> > >>>
> > >>>
> > >>> I'll get back to reviewing the series tomorrow (later today)...
> > >>>
> > >>> -Serge(y)
> > >>>
> > >>>>    	return ret;
> > >>>>    }
> > >>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h
> > >>>> index 7be04b54738b..b0db38396171 100644
> > >>>> --- a/drivers/net/ethernet/stmicro/stmmac/hwif.h
> > >>>> +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h
> > >>>> @@ -198,7 +198,7 @@ struct stmmac_dma_ops {
> > >>>>    	/* To track extra statistic (if supported) */
> > >>>>    	void (*dma_diagnostic_fr)(struct stmmac_extra_stats *x,
> > >>>>    				  void __iomem *ioaddr);
> > >>>> -	void (*enable_dma_transmission) (void __iomem *ioaddr);
> > >>>> +	void (*enable_dma_transmission)(void __iomem *ioaddr, u32 chan);
> > >>>>    	void (*enable_dma_irq)(struct stmmac_priv *priv, void __iomem *ioaddr,
> > >>>>    			       u32 chan, bool rx, bool tx);
> > >>>>    	void (*disable_dma_irq)(struct stmmac_priv *priv, void __iomem *ioaddr,
> > >>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> > >>>> index b334eb16da23..5617b40abbe4 100644
> > >>>> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> > >>>> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> > >>>> @@ -2558,7 +2558,7 @@ static bool stmmac_xdp_xmit_zc(struct stmmac_priv *priv, u32 queue, u32 budget)
> > >>>>    				       true, priv->mode, true, true,
> > >>>>    				       xdp_desc.len);
> > >>>> -		stmmac_enable_dma_transmission(priv, priv->ioaddr);
> > >>>> +		stmmac_enable_dma_transmission(priv, priv->ioaddr, queue);
> > >>>>    		xsk_tx_metadata_to_compl(meta,
> > >>>>    					 &tx_q->tx_skbuff_dma[entry].xsk_meta);
> > >>>> @@ -4706,7 +4706,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
> > >>>>    	netdev_tx_sent_queue(netdev_get_tx_queue(dev, queue), skb->len);
> > >>>> -	stmmac_enable_dma_transmission(priv, priv->ioaddr);
> > >>>> +	stmmac_enable_dma_transmission(priv, priv->ioaddr, queue);
> > >>>>    	stmmac_flush_tx_descriptors(priv, queue);
> > >>>>    	stmmac_tx_timer_arm(priv, queue);
> > >>>> @@ -4926,7 +4926,7 @@ static int stmmac_xdp_xmit_xdpf(struct stmmac_priv *priv, int queue,
> > >>>>    		u64_stats_update_end_irqrestore(&txq_stats->syncp, flags);
> > >>>>    	}
> > >>>> -	stmmac_enable_dma_transmission(priv, priv->ioaddr);
> > >>>> +	stmmac_enable_dma_transmission(priv, priv->ioaddr, queue);
> > >>>>    	entry = STMMAC_GET_ENTRY(entry, priv->dma_conf.dma_tx_size);
> > >>>>    	tx_q->cur_tx = entry;
> > >>>> -- >>>> 2.31.4
> > >>>>
> 

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 06/11] net: stmmac: dwmac-loongson: Add GNET support
  2024-03-14 13:12       ` Yanteng Si
@ 2024-03-19 15:03         ` Serge Semin
  2024-03-20 10:23           ` Yanteng Si
  2024-03-21  9:13           ` Yanteng Si
  0 siblings, 2 replies; 97+ messages in thread
From: Serge Semin @ 2024-03-19 15:03 UTC (permalink / raw)
  To: Yanteng Si
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

On Thu, Mar 14, 2024 at 09:12:49PM +0800, Yanteng Si wrote:
> 
> 在 2024/3/14 16:27, Yanteng Si 写道:
> > 在 2024/2/6 04:58, Serge Semin 写道:
> > > On Tue, Jan 30, 2024 at 04:48:18PM +0800, Yanteng Si wrote:
> > >> Add Loongson GNET (GMAC with PHY) support, override
> > >> stmmac_priv.synopsys_id with 0x37.
> > > Please add more details of all the device capabilities: supported
> > > speeds, duplexness, IP-core version, DMA-descriptors type
> > > (normal/enhanced), MTL Tx/Rx FIFO size, Perfect and Hash-based MAC
> > > Filter tables size, L3/L4 filters availability, VLAN hash table
> > > filter, PHY-interface (GMII, RGMII, etc), EEE support,
> > > AV-feature/Multi-channels support, IEEE 1588 Timestamp support, Magic
> > > Frame support, Remote Wake-up support, IP Checksum, Tx/Rx TCP/IP
> > > Checksum, Mac Management Counters (MMC), SMA/MDIO interface,

> > The gnet (2k2000) of 0x10 supports full-duplex and half-duplex at 1000/100/10M.
> > The gnet of 0x37 (i.e. the gnet of 7a2000) supports 1000/100/10M full duplex.
> > 
> > The gnet with 0x10 has 8 DMA channels, except for channel 0, which does not
> > support sending hardware checksums.
> > 
> > Supported AV features are Qav, Qat, and Qas, and other features should be
> > consistent with the 3.73 IP.

Just list all of these features in the commit message referring to the
respective controller. Like this:
"There are two types of them Loongson GNET controllers:
Loongson 2k2000 GNET and the rest of the Loongson GNETs (like
presented on the 7a2000 SoC). All of them of the DW GMAC 3.73a
IP-core with the next features:
Speeds, DMA-descriptors type (normal/enhanced), MTL Tx/Rx FIFO size,
Perfect and Hash-based MAC Filter tables size, L3/L4 filters availability,
VLAN hash table filter, PHY-interface (GMII, RGMII, etc), EEE support,
IEEE 1588 Timestamp support, Magic Frame support, Remote Wake-up support,
IP Checksum, Tx/Rx TCP/IP Checksum, Mac Management Counters (MMC),
SMA/MDIO interface. 

The difference is that the Loongson 2k2000 GNET controller supports 8
DMA-channels, AV features (Qav, Qat, and Qas) and half-duplex link,
meanwhile the rest of the GNETs don't have these capabilities
available."

> > 
> > >
> > >> Signed-off-by: Yanteng Si<siyanteng@loongson.cn>
> > >> Signed-off-by: Feiyang Chen<chenfeiyang@loongson.cn>
> > >> Signed-off-by: Yinggang Gu<guyinggang@loongson.cn>
> > >> ---
> > >>   .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 44 +++++++++++++++++++
> > >>   1 file changed, 44 insertions(+)
> > >>
> > >> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > >> index 3b3578318cc1..584f7322bd3e 100644
> > >> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > >> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > >> @@ -318,6 +318,8 @@ static struct mac_device_info *loongson_setup(void *apriv)
> > >>   	if (!mac)
> > >>   		return NULL;
> > >>   >> +	priv->synopsys_id = 0x37;	/*Overwrite custom IP*/
> > >> +
> > > Please add a more descriptive comment _above_ the subjected line. In
> > > particular note why the override is needed, what is the real DW GMAC
> > > IP-core version and what is the original value the statement above
> > > overrides.
> > 

> > The IP-core version of the gnet device on the loongson 2k2000 is 0x10, which is
> > a custom IP.
> > 
> > Compared to 0x37, we have split some of the dma registers into two (tx and rx).
> > After overwriting stmmac_dma_ops.dma_interrupt() and stmmac_dma_ops.init_chan(),
> > the logic is consistent with 0x37,
> > 
> > so we overwrite synopsys_id to 0x37.

Yeah, something like that:
	/* The original IP-core version is 0x37 in all Loongson GNET
	 * (2k2000 and 7a2000), but the GNET HW designers have changed the
	 * GMAC_VERSION.SNPSVER field to the custom 0x10 value on the Loongson
	 * 2k2000 MAC to emphasize the differences: multiple DMA-channels, AV
	 * feature and GMAC_INT_STATUS CSR flags layout. Get back the
	 * original value so the correct HW-interface would be
	 * selected.
	 */

> > 
> > >>   	ld = priv->plat->bsp_priv;
> > >>   	mac->dma = &ld->dwlgmac_dma_ops;
> > >>   >> @@ -350,6 +352,46 @@ static struct mac_device_info
> > *loongson_setup(void *apriv)
> > >>   	return mac;
> > >>   }
> > >>   >> +static int loongson_gnet_data(struct pci_dev *pdev,
> > >> +			      struct plat_stmmacenet_data *plat)
> > >> +{
> > >> +	loongson_default_data(pdev, plat);
> > >> +
> > >> +	plat->multicast_filter_bins = 256;
> > >> +
> > >> +	plat->mdio_bus_data->phy_mask =  ~(u32)BIT(2);
> > >> +
> > >> +	plat->phy_addr = 2;
> > >> +	plat->phy_interface = PHY_INTERFACE_MODE_INTERNAL;
> > > Are you sure PHY-interface is supposed to be defined as "internal"?
> > 

> > Yes, because the gnet hardware has a integrated PHY, so we set it to internal,
> > 

Why do you need the phy_addr set to 2 then? Is PHY still discoverable
on the subordinate MDIO-bus?

kdoc in "include/linux/phy.h" defines the PHY_INTERFACE_MODE_INTERNAL
mode as for a case of the MAC and PHY being combined. IIUC it's
reserved for a case when you can't determine actual interface between
the MAC and PHY. Is it your case? Are you sure the interface between
MAC and PHY isn't something like GMII/RGMII/etc?

-Serge(y)

> > Correspondingly, our gmac hardware PHY is external.
> > 
> > >> +
> > >> +	plat->bsp_priv = &pdev->dev;
> > >> +
> > >> +	plat->dma_cfg->pbl = 32;
> > >> +	plat->dma_cfg->pblx8 = true;
> > >> +
> > >> +	plat->clk_ref_rate = 125000000;
> > >> +	plat->clk_ptp_rate = 125000000;
> > >> +
> > >> +	return 0;
> > >> +}
> > >> +
> > >> +static int loongson_gnet_config(struct pci_dev *pdev,
> > >> +				struct plat_stmmacenet_data *plat,
> > >> +				struct stmmac_resources *res,
> > >> +				struct device_node *np)
> > >> +{
> > >> +	int ret;
> > >> +
> > >> +	ret = loongson_dwmac_config_legacy(pdev, plat, res, np);
> > > Again. This will be moved to the probe() method in one of the next
> > > patches leaving loongson_gnet_config() empty. What was the problem
> > > with doing that right away with no intermediate change?
> > 
> > No problem. My original intention is to break the patches down into smaller pieces.
> > 
> > In the next version, I will try to re-break them based on your comments.
> > 
> > >
> > >> +
> > >> +	return ret;
> > >> +}
> > >> +
> > >> +static struct stmmac_pci_info loongson_gnet_pci_info = {
> > >> +	.setup = loongson_gnet_data,
> > >> +	.config = loongson_gnet_config,
> > >> +};
> > >> +
> > >>   static int loongson_dwmac_probe(struct pci_dev *pdev,
> > >>   				const struct pci_device_id *id)
> > >>   {
> > >> @@ -516,9 +558,11 @@ static SIMPLE_DEV_PM_OPS(loongson_dwmac_pm_ops, loongson_dwmac_suspend,
> > >>   			 loongson_dwmac_resume);
> > >>   >>   #define PCI_DEVICE_ID_LOONGSON_GMAC	0x7a03
> > >> +#define PCI_DEVICE_ID_LOONGSON_GNET	0x7a13
> > >>   >>   static const struct pci_device_id loongson_dwmac_id_table[] =
> > {
> > >>   	{ PCI_DEVICE_DATA(LOONGSON, GMAC, &loongson_gmac_pci_info) },
> > >> +	{ PCI_DEVICE_DATA(LOONGSON, GNET, &loongson_gnet_pci_info) },
> > > After this the driver is supposed to correctly handle the Loongson
> > > GNET devices. Based on the patches introduced further it isn't.
> > > Please consider re-arranging the changes (see my comments in the
> > > further patches).
> > 
> > OK.
> > 
> > 
> > Thanks,
> > 
> > Yanteng
> > 
> > 
> > >
> > > -Serge(y)
> > >
> > >>   	{}
> > >>   };
> > >>   MODULE_DEVICE_TABLE(pci, loongson_dwmac_id_table);
> > >> -- >> 2.31.4
> > >>
> 

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 07/11] net: stmmac: dwmac-loongson: Add multi-channel supports for loongson
  2024-03-14 13:13       ` Yanteng Si
@ 2024-03-19 15:53         ` Serge Semin
  2024-03-22 10:36           ` Yanteng Si
  2024-04-03  8:23           ` Yanteng Si
  0 siblings, 2 replies; 97+ messages in thread
From: Serge Semin @ 2024-03-19 15:53 UTC (permalink / raw)
  To: Yanteng Si
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

On Thu, Mar 14, 2024 at 09:13:58PM +0800, Yanteng Si wrote:
> 
> 在 2024/3/14 17:33, Yanteng Si 写道:
> > 在 2024/2/6 05:28, Serge Semin 写道:
> > > On Tue, Jan 30, 2024 at 04:48:19PM +0800, Yanteng Si wrote:
> > >> Request allocation for MSI for specific versions.
> > >>
> > > Please elaborate what is actually done in the patch. What device
> > > version it is dedicated for (Loongson GNET?), what IRQs the patch
> > > adds, etc.
> > gnet_device   core IP    IRQ
> > 7a2000        0x37    legacy
> > 2k2000        0x10    multi_msi
> > >
> > > BTW will GNET device work without this patch? If no you need to either
> > > merge it into the patch introducing the GNET-device support or place
> > > it before that patch (6/11).
> > OK, GNET device work need this patch.
> > >   >> Some features of Loongson platforms are bound to the GMAC_VERSION
> > >> register. We have to read its value in order to get the correct channel
> > >> number.
> > > This message seems misleading. I don't see you doing that in the patch below...
> > Because part of our gnet hardware (7a2000) core IP is 0x37
> > >
> > >> Signed-off-by: Yanteng Si<siyanteng@loongson.cn>
> > >> Signed-off-by: Feiyang Chen<chenfeiyang@loongson.cn>
> > >> Signed-off-by: Yinggang Gu<guyinggang@loongson.cn>
> > >> ---
> > >>   .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 57 +++++++++++++++----
> > >>   1 file changed, 46 insertions(+), 11 deletions(-)
> > >>
> > >> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > >> index 584f7322bd3e..60d0a122d7c9 100644
> > >> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > >> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > >> @@ -98,10 +98,10 @@ static void dwlgmac_dma_init_channel(struct stmmac_priv *priv,
> > >>   	if (dma_cfg->aal)
> > >>   		value |= DMA_BUS_MODE_AAL;
> > >>
> > >   >> -	writel(value, ioaddr + DMA_BUS_MODE);
> > >> +	writel(value, ioaddr + DMA_CHAN_BUS_MODE(chan));
> > >>   >>   	/* Mask interrupts by writing to CSR7 */
> > >> -	writel(DMA_INTR_DEFAULT_MASK_LOONGSON, ioaddr + DMA_INTR_ENA);
> > >> +	writel(DMA_INTR_DEFAULT_MASK_LOONGSON, ioaddr + DMA_CHAN_INTR_ENA(chan));
> > > Em, why is this here? There is a patch
> > > [PATCH net-next v8 05/11] net: stmmac: dwmac-loongson: Add Loongson-specific register definitions
> > > in this series which was supposed to introduce the fully functional
> > > GNET-specific callbacks. Move this change in there.
> > OK.
> > >
> > >>   }
> > >>   >>   static int dwlgmac_dma_interrupt(struct stmmac_priv *priv,
> > void __iomem *ioaddr,
> > >> @@ -238,6 +238,45 @@ static int loongson_dwmac_config_legacy(struct pci_dev *pdev,
> > >>   	return 0;
> > >>   }
> > >>   >> +static int loongson_dwmac_config_multi_msi(struct pci_dev
> > *pdev,
> > > This method seems like the GNET-specific one. What about using the
> > > appropriate prefix then?
> > OK. loongson_gnet_config_multi_msi()
> > 
> > >
> > >> +					   struct plat_stmmacenet_data *plat,
> > >> +					   struct stmmac_resources *res,
> > >> +					   struct device_node *np,
> > >> +					   int channel_num)
> > > Why do you need this parametrization? Since this method is
> > > GNET-specific what about defining a macro with the channels amount and
> > > using it here?
> > 
> > OK.
> > 
> > #define CHANNEL_NUM    8
> > 
> > >
> > >> +{
> > >> +	int i, ret, vecs;
> > >> +
> > >> +	vecs = roundup_pow_of_two(channel_num * 2 + 1);
> > >> +	ret = pci_alloc_irq_vectors(pdev, vecs, vecs, PCI_IRQ_MSI);
> > >> +	if (ret < 0) {
> > >> +		dev_info(&pdev->dev,
> > >> +			 "MSI enable failed, Fallback to legacy interrupt\n");
> > >> +		return loongson_dwmac_config_legacy(pdev, plat, res, np);
> > > In what conditions is this possible? Will the
> > > loongson_dwmac_config_legacy() method work in that case? Did you test
> > > it out?

> > Failed to apply for msi interrupt when the interrupt number is not enough,For
> > example, there are a large number of devices。

Then those platforms will _require_ to have the DT-node specified. This
will define the DT-bindings which I doubt you imply here. Am I wrong?

Once again have you tested the loongson_dwmac_config_legacy() method
working in the case of the pci_alloc_irq_vectors() failure?
	

> > >> +	}
> > >> +
> > >> +	plat->rx_queues_to_use = channel_num;
> > >> +	plat->tx_queues_to_use = channel_num;
> > > This is supposed to be initialized in the setup() methods. Please move
> > > it to the dedicated patch.

> > No, referring to my previous reply, only the 0x10 gnet device has 8 channels,
> > and the 0x37 device has a single channel.

Yes. You have a perfectly suitable method for it. It's
loongson_gnet_data(). Init the number of channels there based on the
value read from the GMAC_VERSION.SNPSVER field. Thus the
loongson_gnet_config_multi_msi() will get to be more coherent setting
up the MSI IRQs only.

Am I missing something in the last two notes chunks regard? If yes,
let's submit v9 as you see it. We'll get back to this part there then.

-Serge(y)

> > >
> > >> +
> > >> +	res->irq = pci_irq_vector(pdev, 0);
> > >> +	res->wol_irq = res->irq;
> > > Once again. wol_irq is optional. If there is no dedicated WoL IRQ
> > > leave the field as zero.
> > OK.
> > 
> > res->wol_irq = 0;
> > 
> > >
> > >> +
> > >> +	/* INT NAME | MAC | CH7 rx | CH7 tx | ... | CH0 rx | CH0 tx |
> > >> +	 * --------- ----- -------- --------  ...  -------- --------
> > >> +	 * IRQ NUM  |  0  |   1    |   2    | ... |   15   |   16   |
> > >> +	 */
> > >> +	for (i = 0; i < channel_num; i++) {
> > >> +		res->rx_irq[channel_num - 1 - i] =
> > >> +			pci_irq_vector(pdev, 1 + i * 2);
> > >> +		res->tx_irq[channel_num - 1 - i] =
> > >> +			pci_irq_vector(pdev, 2 + i * 2);
> > >> +	}
> > >> +
> > >> +	plat->flags |= STMMAC_FLAG_MULTI_MSI_EN;
> > >> +	dev_info(&pdev->dev, "%s: multi MSI enablement successful\n", __func__);
> > > What's the point in printing this message especially with the __func__
> > > prefix?  You'll always be able to figure out the allocated IRQs by
> > > means of procfs. I suggest to drop it.
> > 
> > OK.
> > 
> > >
> > >> +
> > >> +	return 0;
> > >> +}
> > >> +
> > >>   static void loongson_default_data(struct pci_dev *pdev,
> > >>   				  struct plat_stmmacenet_data *plat)
> > >>   {
> > >> @@ -296,11 +335,8 @@ static int loongson_gmac_config(struct pci_dev *pdev,
> > >>   				struct stmmac_resources *res,
> > >>   				struct device_node *np)
> > >>   {
> > >> -	int ret;
> > >> -
> > >> -	ret = loongson_dwmac_config_legacy(pdev, plat, res, np);
> > >>   >> -	return ret;
> > >> +	return 0;
> > >>   }
> > >>   >>   static struct stmmac_pci_info loongson_gmac_pci_info = {
> > >> @@ -380,11 +416,7 @@ static int loongson_gnet_config(struct pci_dev *pdev,
> > >>   				struct stmmac_resources *res,
> > >>   				struct device_node *np)
> > >>   {
> > >> -	int ret;
> > >> -
> > >> -	ret = loongson_dwmac_config_legacy(pdev, plat, res, np);
> > >> -
> > >> -	return ret;
> > >> +	return 0;
> > >>   }
> > > Here you are dropping the changes you just introduced leaving the
> > > config() methods empty... Why not to place the
> > > loongson_dwmac_config_legacy() invocation in the probe() method right
> > > at the patches introducing the config() functions and not to add the
> > > config() callback in the first place?
> > OK, I will try.
> > 
> > Thanks,
> > 
> > Yanteng
> > 
> > >
> > > -Serge(y)
> > >
> > >>   >>   static struct stmmac_pci_info loongson_gnet_pci_info = {
> > >> @@ -483,6 +515,9 @@ static int loongson_dwmac_probe(struct pci_dev *pdev,
> > >>   		ld->dwlgmac_dma_ops.dma_interrupt = dwlgmac_dma_interrupt;
> > >>   >>   		plat->setup = loongson_setup;
> > >> +		ret = loongson_dwmac_config_multi_msi(pdev, plat, &res, np, 8);
> > >> +	} else {
> > >> +		ret = loongson_dwmac_config_legacy(pdev, plat, &res, np);
> > >>   	}
> > >>   >>   	plat->bsp_priv = ld;
> > >> -- >> 2.31.4
> > >>
> 

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 08/11] net: stmmac: dwmac-loongson: Fix MAC speed for GNET
  2024-03-14 13:18       ` Yanteng Si
@ 2024-03-19 17:02         ` Serge Semin
  2024-03-20 10:42           ` Yanteng Si
  2024-03-21  9:29           ` Yanteng Si
  0 siblings, 2 replies; 97+ messages in thread
From: Serge Semin @ 2024-03-19 17:02 UTC (permalink / raw)
  To: Yanteng Si
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

On Thu, Mar 14, 2024 at 09:18:15PM +0800, Yanteng Si wrote:
> 
> 在 2024/3/14 17:43, Yanteng Si 写道:
> > 在 2024/2/6 05:55, Serge Semin 写道:
> > > On Tue, Jan 30, 2024 at 04:48:20PM +0800, Yanteng Si wrote:
> > >> Current GNET on LS7A only supports ANE when speed is
> > >> set to 1000M.
> > > If so you need to merge it into the patch
> > > [PATCH net-next v8 06/11] net: stmmac: dwmac-loongson: Add GNET support
> 
> > > Current GNET on LS7A only supports ANE when speed is
> > > set to 1000M.
> 
> > If so you need to merge it into the patch
> > [PATCH net-next v8 06/11] net: stmmac: dwmac-loongson: Add GNET support
> 
> OK.
> 
> > >
> > >> Signed-off-by: Yanteng Si<siyanteng@loongson.cn>
> > >> Signed-off-by: Feiyang Chen<chenfeiyang@loongson.cn>
> > >> Signed-off-by: Yinggang Gu<guyinggang@loongson.cn>
> > >> ---
> > >>   .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 19 +++++++++++++++++++
> > >>   .../ethernet/stmicro/stmmac/stmmac_ethtool.c  |  6 ++++++
> > >>   include/linux/stmmac.h                        |  1 +
> > >>   3 files changed, 26 insertions(+)
> > >>
> > >> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > >> index 60d0a122d7c9..264c4c198d5a 100644
> > >> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > >> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > >> @@ -344,6 +344,21 @@ static struct stmmac_pci_info loongson_gmac_pci_info = {
> > >>   	.config = loongson_gmac_config,
> > >>   };
> > >>   >> +static void loongson_gnet_fix_speed(void *priv, unsigned int
> > speed, unsigned int mode)
> > >> +{
> > >> +	struct loongson_data *ld = (struct loongson_data *)priv;
> > >> +	struct net_device *ndev = dev_get_drvdata(ld->dev);
> > >> +	struct stmmac_priv *ptr = netdev_priv(ndev);
> > >> +
> > >> +	/* The controller and PHY don't work well together.
> > > So there _is_ a PHY. What is the interface between MAC and PHY then?
> > >
> > > GMAC only has a MAC chip inside the chip and needs an external PHY
> > chip; GNET > has the PHY chip inside the chip.

We are talking about GNETs in this method since it has the
loongson_gnet_ prefix. You are referring to GMAC. I am getting
confused about all of these. Based on the patch 06/11 of this series
you call "Loongson GNET" of all the devices placed on the PCI devices
with PCI ID 0x7a13. PCIe device with ID 0x7a03 is called "Loongson
GMAC". Right?

Anyway no matter whether the PHY is placed externally or inside the
chip. AFAIU as long as you know the interface type between MAC and PHY
it would be better to have it specified.

> > >> +	 * We need to use the PS bit to check if the controller's status
> > >> +	 * is correct and reset PHY if necessary.
> > >> +	 */
> > >> +	if (speed == SPEED_1000)
> > >> +		if (readl(ptr->ioaddr + MAC_CTRL_REG) & (1 << 15) /* PS */)
> > >> +			phy_restart_aneg(ndev->phydev);
> > > 1. Please add curly braces for the outer if-statement.
> > OK,
> > > 2. MAC_CTRL_REG.15 is defined by the GMAC_CONTROL_PS macro.
> > 
> > OK.
> > 
> > if(speed==SPEED_1000){
> > /*MAC_CTRL_REG.15 is defined by the GMAC_CONTROL_PS macro.*/
> > if(readl(ptr->ioaddr+MAC_CTRL_REG) &(1<<15))
> > phy_restart_aneg(ndev->phydev);
> > }
> > 
> > > 3. How is the AN-restart helps? PHY-reset is done in
> > > stmmac_init_phy()->phylink_connect_phy()->... a bit earlier than
> > > this is called in the framework of the stmmac_mac_link_up() callback.
> > > Wouldn't that restart AN too?
> > 

> > Due to a bug in the chip's internal PHY, the network is still not working after
> > the first self-negotiation, and it needs to be self-negotiated again.

Then please describe the bug in more details then.

Getting back to the code you implemented here. In the in-situ comment
you say: "We need to use the PS bit to check if the controller's
status is correct and reset PHY if necessary." By calling
phy_restart_aneg() you don't reset the PHY.

Moreover if "PS" flag is set, then the MAC has been pre-configured to
work in the 10/100Mbps mode. Since 1000Mbps speed is requested, the
MAC_CTRL_REG.PS flag will be cleared later in the
stmmac_mac_link_up() method and then phylink_start() shall cause the
link speed re-auto-negotiation. Why do you need the auto-negotiation
started for the default MAC config which will be changed just in a
moment later? All of that seems weird.

Most importantly I have doubts the networking subsystem maintainers
will permit you calling the phy_restart_aneg() method from the MAC
driver code.

> > 
> > >
> > >> +}
> > >> +
> > >>   static struct mac_device_info *loongson_setup(void *apriv)
> > >>   {
> > >>   	struct stmmac_priv *priv = apriv;
> > >> @@ -401,6 +416,7 @@ static int loongson_gnet_data(struct pci_dev *pdev,
> > >>   	plat->phy_interface = PHY_INTERFACE_MODE_INTERNAL;
> > >>   >>   	plat->bsp_priv = &pdev->dev;
> > >> +	plat->fix_mac_speed = loongson_gnet_fix_speed;
> > >>   >>   	plat->dma_cfg->pbl = 32;
> > >>   	plat->dma_cfg->pblx8 = true;
> > >> @@ -416,6 +432,9 @@ static int loongson_gnet_config(struct pci_dev *pdev,
> > >>   				struct stmmac_resources *res,
> > >>   				struct device_node *np)
> > >>   {
> > >> +	if (pdev->revision == 0x00 || pdev->revision == 0x01)
> > >> +		plat->flags |= STMMAC_FLAG_DISABLE_FORCE_1000;
> > >> +
> > > This should be in the patch
> > > [PATCH net-next v8 06/11] net: stmmac: dwmac-loongson: Add GNET support
> > OK.
> > >
> > >>   	return 0;
> > >>   }
> > >>   >> diff --git
> > a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> > b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> > >> index 42d27b97dd1d..31068fbc23c9 100644
> > >> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> > >> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> > >> @@ -422,6 +422,12 @@ stmmac_ethtool_set_link_ksettings(struct net_device *dev,
> > >>   		return 0;
> > >>   	}
> > >>   >> +	if (FIELD_GET(STMMAC_FLAG_DISABLE_FORCE_1000,
> > priv->plat->flags)) {
> > > FIELD_GET()?
> > 
> > OK,
> > 

> > if (STMMAC_FLAG_DISABLE_FORCE_1000 & priv->plat->flags) {

it's better to change the order of the operands:
	if (priv->plat->flags & STMMAC_FLAG_DISABLE_FORCE_1000) {

-Serge(y)

> > 
> > >
> > >> +		if (cmd->base.speed == SPEED_1000 &&
> > >> +		    cmd->base.autoneg != AUTONEG_ENABLE)
> > >> +			return -EOPNOTSUPP;
> > >> +	}
> > >> +
> > >>   	return phylink_ethtool_ksettings_set(priv->phylink, cmd);
> > >>   }
> > >>   >> diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
> > >> index dee5ad6e48c5..2810361e4048 100644
> > >> --- a/include/linux/stmmac.h
> > >> +++ b/include/linux/stmmac.h
> > >> @@ -221,6 +221,7 @@ struct dwmac4_addrs {
> > >>   #define STMMAC_FLAG_RX_CLK_RUNS_IN_LPI		BIT(10)
> > >>   #define STMMAC_FLAG_EN_TX_LPI_CLOCKGATING	BIT(11)
> > >>   #define STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY	BIT(12)
> > >> +#define STMMAC_FLAG_DISABLE_FORCE_1000	BIT(13)
> > > Detach the change introducing the STMMAC_FLAG_DISABLE_FORCE_1000 flag
> > > into a separate patch a place it before
> > > [PATCH net-next v8 06/11] net: stmmac: dwmac-loongson: Add GNET support
> > > as a pre-requisite/preparation patch.
> > > Don't forget a _detailed_ description of why it's necessary, what is
> > > wrong with GNET so 1G speed doesn't work without AN.
> > 
> > OK.
> > 
> > 
> > Thanks,
> > 
> > Yanteng
> > 
> > >
> > > -Serge(y)
> > >
> > >>   >>   struct plat_stmmacenet_data {
> > >>   	int bus_id;
> > >> -- >> 2.31.4
> > >>
> 

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 01/11] net: stmmac: Add multi-channel support
  2024-03-19 14:18             ` Serge Semin
@ 2024-03-20  9:47               ` Yanteng Si
  2024-03-20  9:55               ` Russell King (Oracle)
  1 sibling, 0 replies; 97+ messages in thread
From: Yanteng Si @ 2024-03-20  9:47 UTC (permalink / raw)
  To: Serge Semin
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang


在 2024/3/19 22:18, Serge Semin 写道:
> On Wed, Mar 13, 2024 at 05:10:54PM +0800, Yanteng Si wrote:
>> Hi Serge
> How come almost all of yours recent replies have been formatted as if
> with no inline messages? See
> https://lore.kernel.org/netdev/034d1f08-a110-4e68-abf5-35e7714ea5ae@loongson.cn/
> It's very-very-very hard to read. Please never do that.

Sorry, maybe I made a mistake in the email client.


Thanks,

Yanteng

>
>> 在 2024/3/13 15:01, Yanteng Si 写道:
>>> 在 2024/2/21 21:48, Serge Semin 写道:
>>>> Hi Yanteng
>>>>
>>>> On Mon, Feb 19, 2024 at 07:02:24PM +0800, Yanteng Si wrote:
>>>>> Hi Serge
>>>>>
>>>>> 在 2024/2/5 07:28, Serge Semin 写道:
>>>>>> On Tue, Jan 30, 2024 at 04:43:21PM +0800, Yanteng Si wrote:
>>>>>>> DW GMAC v3.x multi-channels feature is implemented as multiple
>>>>>>> sets of the same CSRs. Here is only preliminary support, it will
>>>>>>> be useful for the driver further evolution and for the users
>>>>>>> having multi-channel DWGMAC v3.x devices.
>>>>>>>
>>>>>>> Signed-off-by: Yanteng Si<siyanteng@loongson.cn>
>>>>>>> Signed-off-by: Feiyang Chen<chenfeiyang@loongson.cn>
>>>>>>> Signed-off-by: Yinggang Gu<guyinggang@loongson.cn>
>>>>>>> ---
>>>>>>>     .../net/ethernet/stmicro/stmmac/dwmac-sun8i.c |  2 +-
>>>>>>>     .../ethernet/stmicro/stmmac/dwmac1000_dma.c   | 36 ++++++++++---------
>>>>>>>     .../net/ethernet/stmicro/stmmac/dwmac_dma.h   | 19 +++++++++-
>>>>>>>     .../net/ethernet/stmicro/stmmac/dwmac_lib.c   | 32 ++++++++---------
>>>>>>>     drivers/net/ethernet/stmicro/stmmac/hwif.h    |  2 +-
>>>>>>>     .../net/ethernet/stmicro/stmmac/stmmac_main.c |  6 ++--
>>>>>>>     6 files changed, 58 insertions(+), 39 deletions(-)
>>>>>>>
>>>>>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
>>>>>>> index 137741b94122..7cdfa0bdb93a 100644
>>>>>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
>>>>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
>>>>>>> @@ -395,7 +395,7 @@ static void sun8i_dwmac_dma_start_tx(struct stmmac_priv *priv,
>>>>>>>     	writel(v, ioaddr + EMAC_TX_CTL1);
>>>>>>>     }
>>>>>>> -static void sun8i_dwmac_enable_dma_transmission(void __iomem *ioaddr)
>>>>>>> +static void sun8i_dwmac_enable_dma_transmission(void __iomem *ioaddr, u32 chan)
>>>>>>>     {
>>>>>>>     	u32 v;
>>>>>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
>>>>>>> index daf79cdbd3ec..5f7b82ad3ec2 100644
>>>>>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
>>>>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
>>>>>>> @@ -70,15 +70,18 @@ static void dwmac1000_dma_axi(void __iomem *ioaddr, struct stmmac_axi *axi)
>>>>>>>     	writel(value, ioaddr + DMA_AXI_BUS_MODE);
>>>>>>>     }
>>>>>>> -static void dwmac1000_dma_init(void __iomem *ioaddr,
>>>>>>> -			       struct stmmac_dma_cfg *dma_cfg, int atds)
>>>>>>> +static void dwmac1000_dma_init_channel(struct stmmac_priv *priv,
>>>>>>> +				       void __iomem *ioaddr,
>>>>>>> +				       struct stmmac_dma_cfg *dma_cfg, u32 chan)
>>>>>>>     {
>>>>>>> -	u32 value = readl(ioaddr + DMA_BUS_MODE);
>>>>>>> +	u32 value;
>>>>>>>     	int txpbl = dma_cfg->txpbl ?: dma_cfg->pbl;
>>>>>>>     	int rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl;
>>>>>> Reverse xmas tree please.
>>>>>>
>>>>>>> -	/*
>>>>>>> -	 * Set the DMA PBL (Programmable Burst Length) mode.
>>>>>>> +	/* common channel control register config */
>>>>>> Redundant comment. Please drop.
>>>>>>
>>>>>>> +	value = readl(ioaddr + DMA_CHAN_BUS_MODE(chan));
>>>>>>> +
>>>>>>> +	/* Set the DMA PBL (Programmable Burst Length) mode.
>>>>>>>     	 *
>>>>>>>     	 * Note: before stmmac core 3.50 this mode bit was 4xPBL, and
>>>>>>>     	 * post 3.5 mode bit acts as 8*PBL.
>>>>>>> @@ -98,16 +101,15 @@ static void dwmac1000_dma_init(void __iomem *ioaddr,
>>>>>>>     	if (dma_cfg->mixed_burst)
>>>>>>>     		value |= DMA_BUS_MODE_MB;
>>>>>>> -	if (atds)
>>>>>>> -		value |= DMA_BUS_MODE_ATDS;
>>>>>>> +	value |= DMA_BUS_MODE_ATDS;
>>>>>> No, just convert the stmmac_dma_ops.dma_init_channel() to accepting
>>>>>> the atds flag as I suggested in v7:
>>>>>> https://lore.kernel.org/netdev/vxcfrxtbfu4pya56m22icnizsyjzqqha5blzb7zpexqcur56uh@uv6vsjf77npa/
>>>>>>
>>>>>> In order to simplify this patch you can provide the
>>>>>> stmmac_dma_ops.dma_init_channel() and
>>>>>> stmmac_dma_ops.enable_dma_transmission() prototype updates in a
>>>>>> pre-requisite/preparation patch.
>>>>> Sorry to keep you waiting for so long, I finally got the machine again.
>>>>> Regarding atds, is this how it is implemented?
>>>>>
>>>>> On the basis of applying PATCH v8:
>>>>>
>>>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
>>>>> b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
>>>>> index 0323f0a5049c..ce99f4a1b320 100644
>>>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
>>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
>>>>> @@ -72,7 +72,8 @@ static void dwmac1000_dma_axi(void __iomem *ioaddr, struct
>>>>> stmmac_axi *axi)
>>>>>
>>>>>    static void dwmac1000_dma_init_channel(struct stmmac_priv *priv,
>>>>>                           void __iomem *ioaddr,
>>>>> -                       struct stmmac_dma_cfg *dma_cfg, u32 chan)
>>>>> +                       struct stmmac_dma_cfg *dma_cfg,
>>>>> +                       int atds, u32 chan)
>>>>>    {
>>>>>        u32 value;
>>>>>        int txpbl = dma_cfg->txpbl ?: dma_cfg->pbl;
>>>>> @@ -101,7 +102,8 @@ static void dwmac1000_dma_init_channel(struct
>>>>> stmmac_priv *priv,
>>>>>        if (dma_cfg->mixed_burst)
>>>>>            value |= DMA_BUS_MODE_MB;
>>>>>
>>>>> -    value |= DMA_BUS_MODE_ATDS;
>>>>> +    if (atds)
>>>>> +        value |= DMA_BUS_MODE_ATDS;
>>>>>
>>>>>        if (dma_cfg->aal)
>>>>>            value |= DMA_BUS_MODE_AAL;
>>>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
>>>>> b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
>>>>> index 84d3a8551b03..8a79c154b553 100644
>>>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
>>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
>>>>> @@ -117,7 +117,8 @@ static void dwmac4_dma_init_tx_chan(struct stmmac_priv
>>>>> *priv,
>>>>>
>>>>>    static void dwmac4_dma_init_channel(struct stmmac_priv *priv,
>>>>>                        void __iomem *ioaddr,
>>>>> -                    struct stmmac_dma_cfg *dma_cfg, u32 chan)
>>>>> +                    struct stmmac_dma_cfg *dma_cfg,
>>>>> +                                    int atds, u32 chan)
>>>>>    {
>>>>>        const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;
>>>>>        u32 value;
>>>>> @@ -135,7 +136,8 @@ static void dwmac4_dma_init_channel(struct stmmac_priv
>>>>> *priv,
>>>>>
>>>>>    static void dwmac410_dma_init_channel(struct stmmac_priv *priv,
>>>>>                          void __iomem *ioaddr,
>>>>> -                      struct stmmac_dma_cfg *dma_cfg, u32 chan)
>>>>> +                      struct stmmac_dma_cfg *dma_cfg,
>>>>> +                                      int atds, u32 chan)
>>>>>    {
>>>>>        const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;
>>>>>        u32 value;
>>>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
>>>>> b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
>>>>> index dd2ab6185c40..d1627b2e50c8 100644
>>>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
>>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
>>>>> @@ -35,7 +35,8 @@ static void dwxgmac2_dma_init(void __iomem *ioaddr,
>>>>>
>>>>>    static void dwxgmac2_dma_init_chan(struct stmmac_priv *priv,
>>>>>                       void __iomem *ioaddr,
>>>>> -                   struct stmmac_dma_cfg *dma_cfg, u32 chan)
>>>>> +                   struct stmmac_dma_cfg *dma_cfg,
>>>>> +                                   int atds, u32 chan)
>>>>>    {
>>>>>        u32 value = readl(ioaddr + XGMAC_DMA_CH_CONTROL(chan));
>>>>>
>>>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h
>>>>> b/drivers/net/ethernet/stmicro/stmmac/hwif.h
>>>>> index b0db38396171..fb27ad0e97e8 100644
>>>>> --- a/drivers/net/ethernet/stmicro/stmmac/hwif.h
>>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h
>>>>> @@ -178,7 +178,7 @@ struct stmmac_dma_ops {
>>>>>        void (*init)(void __iomem *ioaddr, struct stmmac_dma_cfg *dma_cfg,
>>>>>                 int atds);
>>>>>        void (*init_chan)(struct stmmac_priv *priv, void __iomem *ioaddr,
>>>>> -              struct stmmac_dma_cfg *dma_cfg, u32 chan);
>>>>> +              struct stmmac_dma_cfg *dma_cfg, int atds, u32 chan);
>>>>>        void (*init_rx_chan)(struct stmmac_priv *priv, void __iomem *ioaddr,
>>>>>                     struct stmmac_dma_cfg *dma_cfg,
>>>>>                     dma_addr_t phy, u32 chan);
>>>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>>>>> b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>>>>> index 3eed202d1f1c..8705e04913d1 100644
>>>>> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>>>>> @@ -3039,7 +3039,7 @@ static int stmmac_init_dma_engine(struct stmmac_priv
>>>>> *priv)
>>>>>
>>>>>        /* DMA CSR Channel configuration */
>>>>>        for (chan = 0; chan < dma_csr_ch; chan++) {
>>>>> -        stmmac_init_chan(priv, priv->ioaddr, priv->plat->dma_cfg, chan);
>>>>> +        stmmac_init_chan(priv, priv->ioaddr, priv->plat->dma_cfg, atds,
>>>>> chan);
>>>>>            stmmac_disable_dma_irq(priv, priv->ioaddr, chan, 1, 1);
>>>>>        }
>>>>>
>>>>> @@ -6963,6 +6963,7 @@ int stmmac_xdp_open(struct net_device *dev)
>>>>>        u32 buf_size;
>>>>>        bool sph_en;
>>>>>        u32 chan;
>>>>> +     int atds;
>>>>>        int ret;
>>>>>
>>>>>        ret = alloc_dma_desc_resources(priv, &priv->dma_conf);
>>>>> @@ -6981,9 +6982,12 @@ int stmmac_xdp_open(struct net_device *dev)
>>>>>
>>>>>        stmmac_reset_queues_param(priv);
>>>>>
>>>>> +    if (priv->extend_desc && (priv->mode == STMMAC_RING_MODE))
>>>>> +        atds = 1;
>>>>> +
>>>>>        /* DMA CSR Channel configuration */
>>>>>        for (chan = 0; chan < dma_csr_ch; chan++) {
>>>>> -        stmmac_init_chan(priv, priv->ioaddr, priv->plat->dma_cfg, chan);
>>>>> +        stmmac_init_chan(priv, priv->ioaddr, priv->plat->dma_cfg, atds,
>>>>> chan);
>>>>>            stmmac_disable_dma_irq(priv, priv->ioaddr, chan, 1, 1);
>>>>>        }
>>>> Looking more thoroughly at this part I suggest to act a bit
>>>> differently. Let's move the atds flag to the stmmac_dma_cfg structure.
>>>> Alternate Descriptor Size (ATDS) is a part of the DMA-configs together
>>>> with the PBL, ALL, AEME, etc so the structure is the most suitable
>>>> place for it. Here is what should be done for that:
>>>> 1. Add stmmac_dma_cfg::atds boolean field.
>>>> 2. Drop atds argument from the stmmac_dma_ops::init() callback and use
>>>> the stmmac_dma_cfg::atds field in the callback implementations.
>>>> 3. Alter stmmac_init_dma_engine() to updating the dma_cfg->atds field
>>>> instead of the local variable.
>>>>
>>>> Please implement that update in a pre-requisite/preparation patch.
>>>>
>>>> After that you can freely use the stmmac_dma_cfg::atds field in the
>>>> stmmac_init_chan() method too.
>>> OK.
>>>
>>>
>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>> b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>> index b57e1325ce62..dabd6a3772f2 100644
>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>> @@ -66,8 +66,7 @@ struct loongson_data {
>>>
>>>     static void loongson_gnet_dma_init_channel(struct stmmac_priv *priv,
>>>                          void __iomem *ioaddr,
>>> -                     struct stmmac_dma_cfg *dma_cfg,
>>> -                                     int atds, u32 chan)
>>> +                     struct stmmac_dma_cfg *dma_cfg, u32 chan)
>>>     {
>>>         int txpbl = dma_cfg->txpbl ?: dma_cfg->pbl;
>>>         int rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl;
>>> @@ -96,7 +95,7 @@ static void loongson_gnet_dma_init_channel(struct stmmac_priv
>>> *priv,
>>>         if (dma_cfg->mixed_burst)
>>>             value |= DMA_BUS_MODE_MB;
>>>
>>> -    if (atds)
>>> +    if (dma_cfg->atds)
>>>             value |= DMA_BUS_MODE_ATDS;
>>>
>>>         if (dma_cfg->aal)
>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
>>> b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
>>> index 7001a86425ea..ae9240736e64 100644
>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
>>> @@ -299,7 +299,7 @@ static int sun8i_dwmac_dma_reset(void __iomem *ioaddr)
>>>      * Called from stmmac via stmmac_dma_ops->init
>>>      */
>>>     static void sun8i_dwmac_dma_init(void __iomem *ioaddr,
>>> -                 struct stmmac_dma_cfg *dma_cfg, int atds)
>>> +                 struct stmmac_dma_cfg *dma_cfg)
>>>     {
>>>         writel(EMAC_RX_INT | EMAC_TX_INT, ioaddr + EMAC_INT_EN);
>>>         writel(0x1FFFFFF, ioaddr + EMAC_INT_STA);
>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
>>> b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
>>> index fd5ecc043251..66c0c22908b1 100644
>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
>>> @@ -72,8 +72,7 @@ static void dwmac1000_dma_axi(void __iomem *ioaddr, struct
>>> stmmac_axi *axi)
>>>
>>>     static void dwmac1000_dma_init_channel(struct stmmac_priv *priv,
>>>                            void __iomem *ioaddr,
>>> -                       struct stmmac_dma_cfg *dma_cfg,
>>> -                       int atds, u32 chan)
>>> +                       struct stmmac_dma_cfg *dma_cfg, u32 chan)
>>>     {
>>>         int txpbl = dma_cfg->txpbl ?: dma_cfg->pbl;
>>>         int rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl;
>>> @@ -101,7 +100,7 @@ static void dwmac1000_dma_init_channel(struct stmmac_priv *priv,
>>>         if (dma_cfg->mixed_burst)
>>>             value |= DMA_BUS_MODE_MB;
>>>
>>> -    if (atds)
>>> +    if (dma_cfg->atds)
>>>             value |= DMA_BUS_MODE_ATDS;
>>>
>>>         if (dma_cfg->aal)
>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
>>> b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
>>> index dea270f60cc3..f861babc06f9 100644
>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
>>> @@ -19,7 +19,7 @@
>>>     #include "dwmac_dma.h"
>>>
>>>     static void dwmac100_dma_init(void __iomem *ioaddr,
>>> -                  struct stmmac_dma_cfg *dma_cfg, int atds)
>>> +                  struct stmmac_dma_cfg *dma_cfg)
>>>     {
>>>         /* Enable Application Access by writing to DMA CSR0 */
>>>         writel(DMA_BUS_MODE_DEFAULT | (dma_cfg->pbl << DMA_BUS_MODE_PBL_SHIFT),
>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
>>> b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
>>> index 8a79c154b553..e0165358c4ac 100644
>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
>>> @@ -117,8 +117,7 @@ static void dwmac4_dma_init_tx_chan(struct stmmac_priv *priv,
>>>
>>>     static void dwmac4_dma_init_channel(struct stmmac_priv *priv,
>>>                         void __iomem *ioaddr,
>>> -                    struct stmmac_dma_cfg *dma_cfg,
>>> -                                    int atds, u32 chan)
>>> +                    struct stmmac_dma_cfg *dma_cfg, u32 chan)
>>>     {
>>>         const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;
>>>         u32 value;
>>> @@ -136,8 +135,7 @@ static void dwmac4_dma_init_channel(struct stmmac_priv *priv,
>>>
>>>     static void dwmac410_dma_init_channel(struct stmmac_priv *priv,
>>>                           void __iomem *ioaddr,
>>> -                      struct stmmac_dma_cfg *dma_cfg,
>>> -                                      int atds, u32 chan)
>>> +                      struct stmmac_dma_cfg *dma_cfg, u32 chan)
>>>     {
>>>         const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;
>>>         u32 value;
>>> @@ -155,7 +153,7 @@ static void dwmac410_dma_init_channel(struct stmmac_priv *priv,
>>>     }
>>>
>>>     static void dwmac4_dma_init(void __iomem *ioaddr,
>>> -                struct stmmac_dma_cfg *dma_cfg, int atds)
>>> +                struct stmmac_dma_cfg *dma_cfg)
>>>     {
>>>         u32 value = readl(ioaddr + DMA_SYS_BUS_MODE);
>>>
>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
>>> b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
>>> index d1627b2e50c8..7840bc403788 100644
>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
>>> @@ -20,7 +20,7 @@ static int dwxgmac2_dma_reset(void __iomem *ioaddr)
>>>     }
>>>
>>>     static void dwxgmac2_dma_init(void __iomem *ioaddr,
>>> -                  struct stmmac_dma_cfg *dma_cfg, int atds)
>>> +                  struct stmmac_dma_cfg *dma_cfg)
>>>     {
>>>         u32 value = readl(ioaddr + XGMAC_DMA_SYSBUS_MODE);
>>>
>>> @@ -35,8 +35,7 @@ static void dwxgmac2_dma_init(void __iomem *ioaddr,
>>>
>>>     static void dwxgmac2_dma_init_chan(struct stmmac_priv *priv,
>>>                        void __iomem *ioaddr,
>>> -                   struct stmmac_dma_cfg *dma_cfg,
>>> -                                   int atds, u32 chan)
>>> +                   struct stmmac_dma_cfg *dma_cfg, u32 chan)
>>>     {
>>>         u32 value = readl(ioaddr + XGMAC_DMA_CH_CONTROL(chan));
>>>
>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h
>>> b/drivers/net/ethernet/stmicro/stmmac/hwif.h
>>> index fb27ad0e97e8..3b20fb7f3a61 100644
>>> --- a/drivers/net/ethernet/stmicro/stmmac/hwif.h
>>> +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h
>>> @@ -175,10 +175,9 @@ struct dma_features;
>>>     struct stmmac_dma_ops {
>>>         /* DMA core initialization */
>>>         int (*reset)(void __iomem *ioaddr);
>>> -    void (*init)(void __iomem *ioaddr, struct stmmac_dma_cfg *dma_cfg,
>>> -             int atds);
>>> +    void (*init)(void __iomem *ioaddr, struct stmmac_dma_cfg *dma_cfg);
>>>         void (*init_chan)(struct stmmac_priv *priv, void __iomem *ioaddr,
>>> -              struct stmmac_dma_cfg *dma_cfg, int atds, u32 chan);
>>> +              struct stmmac_dma_cfg *dma_cfg, u32 chan);
>>>         void (*init_rx_chan)(struct stmmac_priv *priv, void __iomem *ioaddr,
>>>                      struct stmmac_dma_cfg *dma_cfg,
>>>                      dma_addr_t phy, u32 chan);
>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>>> b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>>> index 7c656f970575..957dfabc663d 100644
>>> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>>> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>>> @@ -3013,7 +3013,6 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv)
>>>         struct stmmac_rx_queue *rx_q;
>>>         struct stmmac_tx_queue *tx_q;
>>>         u32 chan = 0;
>>> -    int atds = 0;
>>>         int ret = 0;
>>>
>>>         if (!priv->plat->dma_cfg || !priv->plat->dma_cfg->pbl) {
>>> @@ -3022,7 +3021,7 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv)
>>>         }
>>>
>>>         if (priv->extend_desc && (priv->mode == STMMAC_RING_MODE))
>>> -        atds = 1;
>>> +        priv->plat->dma_cfg->atds = 1;
>>>
>>>         ret = stmmac_reset(priv, priv->ioaddr);
>>>         if (ret) {
>>> @@ -3031,14 +3030,14 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv)
>>>         }
>>>
>>>         /* DMA Configuration */
>>> -    stmmac_dma_init(priv, priv->ioaddr, priv->plat->dma_cfg, atds);
>>> +    stmmac_dma_init(priv, priv->ioaddr, priv->plat->dma_cfg);
>>>
>>>         if (priv->plat->axi)
>>>             stmmac_axi(priv, priv->ioaddr, priv->plat->axi);
>>>
>>>         /* DMA CSR Channel configuration */
>>>         for (chan = 0; chan < dma_csr_ch; chan++) {
>>> -        stmmac_init_chan(priv, priv->ioaddr, priv->plat->dma_cfg, atds, chan);
>>> +        stmmac_init_chan(priv, priv->ioaddr, priv->plat->dma_cfg, chan);
>>>             stmmac_disable_dma_irq(priv, priv->ioaddr, chan, 1, 1);
>>>         }
>>>
>>> @@ -6962,7 +6961,6 @@ int stmmac_xdp_open(struct net_device *dev)
>>>         u32 buf_size;
>>>         bool sph_en;
>>>         u32 chan;
>>> -        int atds;
>>>         int ret;
>>>
>>>         ret = alloc_dma_desc_resources(priv, &priv->dma_conf);
>>> @@ -6981,12 +6979,9 @@ int stmmac_xdp_open(struct net_device *dev)
>>>
>>>         stmmac_reset_queues_param(priv);
>>>
>>> -    if (priv->extend_desc && (priv->mode == STMMAC_RING_MODE))
>>> -        atds = 1;
>>> -
>>>         /* DMA CSR Channel configuration */
>>>         for (chan = 0; chan < dma_csr_ch; chan++) {
>>> -        stmmac_init_chan(priv, priv->ioaddr, priv->plat->dma_cfg, atds, chan);
>>> +        stmmac_init_chan(priv, priv->ioaddr, priv->plat->dma_cfg, chan);
>>>             stmmac_disable_dma_irq(priv, priv->ioaddr, chan, 1, 1);
>>>         }
>>>
>>> diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
>>> index 23bfe3c1465f..c827dc1213b9 100644
>>> --- a/include/linux/stmmac.h
>>> +++ b/include/linux/stmmac.h
>>> @@ -100,6 +100,7 @@ struct stmmac_dma_cfg {
>>>         bool eame;
>>>         bool multi_msi_en;
>>>         bool dche;
>>> +    bool atds;
>>>     };
>>>
>>>     #define AXI_BLEN    7
>>>
> Ok. Let's see how it looks in a separate patch of the v9 series.
>
> -Serge(y)
>
>>> Thanks,
>>>
>>> Yanteng
>>>
>>>> -Serge(y)
>>>>
>>>>> Thanks,
>>>>>
>>>>> Yanteng
>>>>>
>>>>>>>     	if (dma_cfg->aal)
>>>>>>>     		value |= DMA_BUS_MODE_AAL;
>>>>>>> -	writel(value, ioaddr + DMA_BUS_MODE);
>>>>>>> +	writel(value, ioaddr + DMA_CHAN_BUS_MODE(chan));
>>>>>>>     	/* Mask interrupts by writing to CSR7 */
>>>>>>> -	writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_INTR_ENA);
>>>>>>> +	writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_CHAN_INTR_ENA(chan));
>>>>>>>     }
>>>>>>>     static void dwmac1000_dma_init_rx(struct stmmac_priv *priv,
>>>>>>> @@ -116,7 +118,7 @@ static void dwmac1000_dma_init_rx(struct stmmac_priv *priv,
>>>>>>>     				  dma_addr_t dma_rx_phy, u32 chan)
>>>>>>>     {
>>>>>>>     	/* RX descriptor base address list must be written into DMA CSR3 */
>>>>>>> -	writel(lower_32_bits(dma_rx_phy), ioaddr + DMA_RCV_BASE_ADDR);
>>>>>>> +	writel(lower_32_bits(dma_rx_phy), ioaddr + DMA_CHAN_RCV_BASE_ADDR(chan));
>>>>>>>     }
>>>>>>>     static void dwmac1000_dma_init_tx(struct stmmac_priv *priv,
>>>>>>> @@ -125,7 +127,7 @@ static void dwmac1000_dma_init_tx(struct stmmac_priv *priv,
>>>>>>>     				  dma_addr_t dma_tx_phy, u32 chan)
>>>>>>>     {
>>>>>>>     	/* TX descriptor base address list must be written into DMA CSR4 */
>>>>>>> -	writel(lower_32_bits(dma_tx_phy), ioaddr + DMA_TX_BASE_ADDR);
>>>>>>> +	writel(lower_32_bits(dma_tx_phy), ioaddr + DMA_CHAN_TX_BASE_ADDR(chan));
>>>>>>>     }
>>>>>>>     static u32 dwmac1000_configure_fc(u32 csr6, int rxfifosz)
>>>>>>> @@ -153,7 +155,7 @@ static void dwmac1000_dma_operation_mode_rx(struct stmmac_priv *priv,
>>>>>>>     					    void __iomem *ioaddr, int mode,
>>>>>>>     					    u32 channel, int fifosz, u8 qmode)
>>>>>>>     {
>>>>>>> -	u32 csr6 = readl(ioaddr + DMA_CONTROL);
>>>>>>> +	u32 csr6 = readl(ioaddr + DMA_CHAN_CONTROL(channel));
>>>>>>>     	if (mode == SF_DMA_MODE) {
>>>>>>>     		pr_debug("GMAC: enable RX store and forward mode\n");
>>>>>>> @@ -175,14 +177,14 @@ static void dwmac1000_dma_operation_mode_rx(struct stmmac_priv *priv,
>>>>>>>     	/* Configure flow control based on rx fifo size */
>>>>>>>     	csr6 = dwmac1000_configure_fc(csr6, fifosz);
>>>>>>> -	writel(csr6, ioaddr + DMA_CONTROL);
>>>>>>> +	writel(csr6, ioaddr + DMA_CHAN_CONTROL(channel));
>>>>>>>     }
>>>>>>>     static void dwmac1000_dma_operation_mode_tx(struct stmmac_priv *priv,
>>>>>>>     					    void __iomem *ioaddr, int mode,
>>>>>>>     					    u32 channel, int fifosz, u8 qmode)
>>>>>>>     {
>>>>>>> -	u32 csr6 = readl(ioaddr + DMA_CONTROL);
>>>>>>> +	u32 csr6 = readl(ioaddr + DMA_CHAN_CONTROL(channel));
>>>>>>>     	if (mode == SF_DMA_MODE) {
>>>>>>>     		pr_debug("GMAC: enable TX store and forward mode\n");
>>>>>>> @@ -209,7 +211,7 @@ static void dwmac1000_dma_operation_mode_tx(struct stmmac_priv *priv,
>>>>>>>     			csr6 |= DMA_CONTROL_TTC_256;
>>>>>>>     	}
>>>>>>> -	writel(csr6, ioaddr + DMA_CONTROL);
>>>>>>> +	writel(csr6, ioaddr + DMA_CHAN_CONTROL(channel));
>>>>>>>     }
>>>>>>>     static void dwmac1000_dump_dma_regs(struct stmmac_priv *priv,
>>>>>>> @@ -271,12 +273,12 @@ static int dwmac1000_get_hw_feature(void __iomem *ioaddr,
>>>>>>>     static void dwmac1000_rx_watchdog(struct stmmac_priv *priv,
>>>>>>>     				  void __iomem *ioaddr, u32 riwt, u32 queue)
>>>>>>>     {
>>>>>>> -	writel(riwt, ioaddr + DMA_RX_WATCHDOG);
>>>>>>> +	writel(riwt, ioaddr + DMA_CHAN_RX_WATCHDOG(queue));
>>>>>>>     }
>>>>>>>     const struct stmmac_dma_ops dwmac1000_dma_ops = {
>>>>>>>     	.reset = dwmac_dma_reset,
>>>>>>> -	.init = dwmac1000_dma_init,
>>>>>>> +	.init_chan = dwmac1000_dma_init_channel,
>>>>>>>     	.init_rx_chan = dwmac1000_dma_init_rx,
>>>>>>>     	.init_tx_chan = dwmac1000_dma_init_tx,
>>>>>>>     	.axi = dwmac1000_dma_axi,
>>>>>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
>>>>>>> index 72672391675f..593be79c46e1 100644
>>>>>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
>>>>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
>>>>>>> @@ -148,11 +148,14 @@
>>>>>>>     					 DMA_STATUS_TI | \
>>>>>>>     					 DMA_STATUS_MSK_COMMON)
>>>>>>> +/* Following DMA defines are chanels oriented */    \
>>>>>>> +#define DMA_CHAN_OFFSET			0x100   |-------------+
>>>>>>> +                                                    /              |
>>>>>>                                                                          |
>>>>>> Please move all of these ---------------------------------------------+-------------------------+
>>>>>> to being defined just below the DMA_MISSED_FRAME_CTR macros definition.                         |
>>>>>> The point is to keep a coherency between dwmac_dma.h and dwmac4_dma.h.                          |
>>>>>> The later header file has first generic DMA-related macros defined                              |
>>>>>> (CSR addresses and flags) and then the channel-specific ones (CSR                               |
>>>>>> addresses and flags). Since in case of the DW GMAC v3.x the                                     |
>>>>>> multi-channels are implemented as a copy of all the DMA CSRs let's                              |
>>>>>> preserve the logic of having all CSR address defined first, then the                            |
>>>>>> CSR flags.                                                                                      |
>>>>>>                                                                                                    |
>>>>>>>     #define NUM_DWMAC100_DMA_REGS	9                                                       |
>>>>>>>     #define NUM_DWMAC1000_DMA_REGS	23                                                      |
>>>>>>>     #define NUM_DWMAC4_DMA_REGS	27                                                              |
>>>>>>>                                                                                                  |
>>>>>>> -void dwmac_enable_dma_transmission(void __iomem *ioaddr);                                    |
>>>>>>> +void dwmac_enable_dma_transmission(void __iomem *ioaddr, u32 chan);                          |
>>>>>>>     void dwmac_enable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr,                    |
>>>>>>>     			  u32 chan, bool rx, bool tx);                                          |
>>>>>>>     void dwmac_disable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr,                   |
>>>>>>> @@ -169,4 +172,18 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,  |
>>>>>>>     			struct stmmac_extra_stats *x, u32 chan, u32 dir);                       |
>>>>>>>     int dwmac_dma_reset(void __iomem *ioaddr);                                                   |
>>>>>>>                                                                                                  |
>>>>>>                                                                                                    |
>>>>>>> +static inline u32 dma_chan_base_addr(u32 base, u32 chan)                                  \  |
>>>>>>> +{                                                                                          | |
>>>>>>> +	return base + chan * DMA_CHAN_OFFSET;                                                 | |
>>>>>>> +}                                                                                          | |
>>>>>>> +                                                                                           | |
>>>>>>> +#define DMA_CHAN_XMT_POLL_DEMAND(chan)	dma_chan_base_addr(DMA_XMT_POLL_DEMAND, chan) | |
>>>>>>> +#define DMA_CHAN_INTR_ENA(chan)		dma_chan_base_addr(DMA_INTR_ENA, chan)        | |
>>>>>>> +#define DMA_CHAN_CONTROL(chan)		dma_chan_base_addr(DMA_CONTROL, chan)         | |
>>>>>>> +#define DMA_CHAN_STATUS(chan)		dma_chan_base_addr(DMA_STATUS, chan)          |-+
>>>>>>> +#define DMA_CHAN_BUS_MODE(chan)		dma_chan_base_addr(DMA_BUS_MODE, chan)        |
>>>>>>> +#define DMA_CHAN_RCV_BASE_ADDR(chan)	dma_chan_base_addr(DMA_RCV_BASE_ADDR, chan)           |
>>>>>>> +#define DMA_CHAN_TX_BASE_ADDR(chan)	dma_chan_base_addr(DMA_TX_BASE_ADDR, chan)            |
>>>>>>> +#define DMA_CHAN_RX_WATCHDOG(chan)	dma_chan_base_addr(DMA_RX_WATCHDOG, chan)             |
>>>>>>> +                                                                                           /
>>>>>>>     #endif /* __DWMAC_DMA_H__ */
>>>>>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
>>>>>>> index 7907d62d3437..b37368137810 100644
>>>>>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
>>>>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
>>>>>>> @@ -28,65 +28,65 @@ int dwmac_dma_reset(void __iomem *ioaddr)
>>>>>>>     }
>>>>>>>     /* CSR1 enables the transmit DMA to check for new descriptor */
>>>>>>> -void dwmac_enable_dma_transmission(void __iomem *ioaddr)
>>>>>>> +void dwmac_enable_dma_transmission(void __iomem *ioaddr, u32 chan)
>>>>>>>     {
>>>>>>> -	writel(1, ioaddr + DMA_XMT_POLL_DEMAND);
>>>>>>> +	writel(1, ioaddr + DMA_CHAN_XMT_POLL_DEMAND(chan));
>>>>>>>     }
>>>>>>>     void dwmac_enable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr,
>>>>>>>     			  u32 chan, bool rx, bool tx)
>>>>>>>     {
>>>>>>> -	u32 value = readl(ioaddr + DMA_INTR_ENA);
>>>>>>> +	u32 value = readl(ioaddr + DMA_CHAN_INTR_ENA(chan));
>>>>>>>     	if (rx)
>>>>>>>     		value |= DMA_INTR_DEFAULT_RX;
>>>>>>>     	if (tx)
>>>>>>>     		value |= DMA_INTR_DEFAULT_TX;
>>>>>>> -	writel(value, ioaddr + DMA_INTR_ENA);
>>>>>>> +	writel(value, ioaddr + DMA_CHAN_INTR_ENA(chan));
>>>>>>>     }
>>>>>>>     void dwmac_disable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr,
>>>>>>>     			   u32 chan, bool rx, bool tx)
>>>>>>>     {
>>>>>>> -	u32 value = readl(ioaddr + DMA_INTR_ENA);
>>>>>>> +	u32 value = readl(ioaddr + DMA_CHAN_INTR_ENA(chan));
>>>>>>>     	if (rx)
>>>>>>>     		value &= ~DMA_INTR_DEFAULT_RX;
>>>>>>>     	if (tx)
>>>>>>>     		value &= ~DMA_INTR_DEFAULT_TX;
>>>>>>> -	writel(value, ioaddr + DMA_INTR_ENA);
>>>>>>> +	writel(value, ioaddr + DMA_CHAN_INTR_ENA(chan));
>>>>>>>     }
>>>>>>>     void dwmac_dma_start_tx(struct stmmac_priv *priv, void __iomem *ioaddr,
>>>>>>>     			u32 chan)
>>>>>>>     {
>>>>>>> -	u32 value = readl(ioaddr + DMA_CONTROL);
>>>>>>> +	u32 value = readl(ioaddr + DMA_CHAN_CONTROL(chan));
>>>>>>>     	value |= DMA_CONTROL_ST;
>>>>>>> -	writel(value, ioaddr + DMA_CONTROL);
>>>>>>> +	writel(value, ioaddr + DMA_CHAN_CONTROL(chan));
>>>>>>>     }
>>>>>>>     void dwmac_dma_stop_tx(struct stmmac_priv *priv, void __iomem *ioaddr, u32 chan)
>>>>>>>     {
>>>>>>> -	u32 value = readl(ioaddr + DMA_CONTROL);
>>>>>>> +	u32 value = readl(ioaddr + DMA_CHAN_CONTROL(chan));
>>>>>>>     	value &= ~DMA_CONTROL_ST;
>>>>>>> -	writel(value, ioaddr + DMA_CONTROL);
>>>>>>> +	writel(value, ioaddr + DMA_CHAN_CONTROL(chan));
>>>>>>>     }
>>>>>>>     void dwmac_dma_start_rx(struct stmmac_priv *priv, void __iomem *ioaddr,
>>>>>>>     			u32 chan)
>>>>>>>     {
>>>>>>> -	u32 value = readl(ioaddr + DMA_CONTROL);
>>>>>>> +	u32 value = readl(ioaddr + DMA_CHAN_CONTROL(chan));
>>>>>>>     	value |= DMA_CONTROL_SR;
>>>>>>> -	writel(value, ioaddr + DMA_CONTROL);
>>>>>>> +	writel(value, ioaddr + DMA_CHAN_CONTROL(chan));
>>>>>>>     }
>>>>>>>     void dwmac_dma_stop_rx(struct stmmac_priv *priv, void __iomem *ioaddr, u32 chan)
>>>>>>>     {
>>>>>>> -	u32 value = readl(ioaddr + DMA_CONTROL);
>>>>>>> +	u32 value = readl(ioaddr + DMA_CHAN_CONTROL(chan));
>>>>>>>     	value &= ~DMA_CONTROL_SR;
>>>>>>> -	writel(value, ioaddr + DMA_CONTROL);
>>>>>>> +	writel(value, ioaddr + DMA_CHAN_CONTROL(chan));
>>>>>>>     }
>>>>>>>     #ifdef DWMAC_DMA_DEBUG
>>>>>>> @@ -166,7 +166,7 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
>>>>>>>     	struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[chan];
>>>>>>>     	int ret = 0;
>>>>>>>     	/* read the status register (CSR5) */
>>>>>>> -	u32 intr_status = readl(ioaddr + DMA_STATUS);
>>>>>>> +	u32 intr_status = readl(ioaddr + DMA_CHAN_STATUS(chan));
>>>>>>>     #ifdef DWMAC_DMA_DEBUG
>>>>>>>     	/* Enable it to monitor DMA rx/tx status in case of critical problems */
>>>>>>> @@ -236,7 +236,7 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
>>>>>>>     		pr_warn("%s: unexpected status %08x\n", __func__, intr_status);
>>>>>>>     	/* Clear the interrupt by writing a logic 1 to the CSR5[15-0] */
>>>>>>> -	writel((intr_status & 0x1ffff), ioaddr + DMA_STATUS);
>>>>>>> +	writel((intr_status & 0x7ffff), ioaddr + DMA_CHAN_STATUS(chan));
>>>>>> Isn't the mask change going to be implemented in the framework of the
>>>>>> Loongson-specific DMA-interrupt handler in some of the further patches?
>>>>>>
>>>>>>
>>>>>> I'll get back to reviewing the series tomorrow (later today)...
>>>>>>
>>>>>> -Serge(y)
>>>>>>
>>>>>>>     	return ret;
>>>>>>>     }
>>>>>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h
>>>>>>> index 7be04b54738b..b0db38396171 100644
>>>>>>> --- a/drivers/net/ethernet/stmicro/stmmac/hwif.h
>>>>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h
>>>>>>> @@ -198,7 +198,7 @@ struct stmmac_dma_ops {
>>>>>>>     	/* To track extra statistic (if supported) */
>>>>>>>     	void (*dma_diagnostic_fr)(struct stmmac_extra_stats *x,
>>>>>>>     				  void __iomem *ioaddr);
>>>>>>> -	void (*enable_dma_transmission) (void __iomem *ioaddr);
>>>>>>> +	void (*enable_dma_transmission)(void __iomem *ioaddr, u32 chan);
>>>>>>>     	void (*enable_dma_irq)(struct stmmac_priv *priv, void __iomem *ioaddr,
>>>>>>>     			       u32 chan, bool rx, bool tx);
>>>>>>>     	void (*disable_dma_irq)(struct stmmac_priv *priv, void __iomem *ioaddr,
>>>>>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>>>>>>> index b334eb16da23..5617b40abbe4 100644
>>>>>>> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>>>>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>>>>>>> @@ -2558,7 +2558,7 @@ static bool stmmac_xdp_xmit_zc(struct stmmac_priv *priv, u32 queue, u32 budget)
>>>>>>>     				       true, priv->mode, true, true,
>>>>>>>     				       xdp_desc.len);
>>>>>>> -		stmmac_enable_dma_transmission(priv, priv->ioaddr);
>>>>>>> +		stmmac_enable_dma_transmission(priv, priv->ioaddr, queue);
>>>>>>>     		xsk_tx_metadata_to_compl(meta,
>>>>>>>     					 &tx_q->tx_skbuff_dma[entry].xsk_meta);
>>>>>>> @@ -4706,7 +4706,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
>>>>>>>     	netdev_tx_sent_queue(netdev_get_tx_queue(dev, queue), skb->len);
>>>>>>> -	stmmac_enable_dma_transmission(priv, priv->ioaddr);
>>>>>>> +	stmmac_enable_dma_transmission(priv, priv->ioaddr, queue);
>>>>>>>     	stmmac_flush_tx_descriptors(priv, queue);
>>>>>>>     	stmmac_tx_timer_arm(priv, queue);
>>>>>>> @@ -4926,7 +4926,7 @@ static int stmmac_xdp_xmit_xdpf(struct stmmac_priv *priv, int queue,
>>>>>>>     		u64_stats_update_end_irqrestore(&txq_stats->syncp, flags);
>>>>>>>     	}
>>>>>>> -	stmmac_enable_dma_transmission(priv, priv->ioaddr);
>>>>>>> +	stmmac_enable_dma_transmission(priv, priv->ioaddr, queue);
>>>>>>>     	entry = STMMAC_GET_ENTRY(entry, priv->dma_conf.dma_tx_size);
>>>>>>>     	tx_q->cur_tx = entry;
>>>>>>> -- >>>> 2.31.4
>>>>>>>


^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 01/11] net: stmmac: Add multi-channel support
  2024-03-19 14:18             ` Serge Semin
  2024-03-20  9:47               ` Yanteng Si
@ 2024-03-20  9:55               ` Russell King (Oracle)
  2024-03-20 10:51                 ` Yanteng Si
  1 sibling, 1 reply; 97+ messages in thread
From: Russell King (Oracle) @ 2024-03-20  9:55 UTC (permalink / raw)
  To: Serge Semin
  Cc: Yanteng Si, andrew, hkallweit1, peppe.cavallaro,
	alexandre.torgue, joabreu, Jose.Abreu, chenhuacai, guyinggang,
	netdev, chris.chenfeiyang

On Tue, Mar 19, 2024 at 05:18:14PM +0300, Serge Semin wrote:
> How come almost all of yours recent replies have been formatted as if
> with no inline messages? See
> https://lore.kernel.org/netdev/034d1f08-a110-4e68-abf5-35e7714ea5ae@loongson.cn/
> It's very-very-very hard to read. Please never do that.

Please also trim appropriately your replies (that goes for both of you.)
I tried to work out whether you'd provided any content apart from the
above, but I really couldn't be bothered to page through the message.

https://subspace.kernel.org/etiquette.html#trim-your-quotes-when-replying

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 09/11] net: stmmac: dwmac-loongson: Fix half duplex
  2024-03-14 13:08           ` Yanteng Si
@ 2024-03-20 10:10             ` Serge Semin
  2024-03-20 10:37               ` Russell King (Oracle)
  0 siblings, 1 reply; 97+ messages in thread
From: Serge Semin @ 2024-03-20 10:10 UTC (permalink / raw)
  To: Russell King (Oracle)
  Cc: Yanteng Si, andrew, hkallweit1, peppe.cavallaro,
	alexandre.torgue, joabreu, Jose.Abreu, chenhuacai, guyinggang,
	netdev, chris.chenfeiyang

On Thu, Mar 14, 2024 at 09:08:41PM +0800, Yanteng Si wrote:
> 
> 在 2024/3/13 18:21, Russell King (Oracle) 写道:
> > On Wed, Mar 13, 2024 at 05:24:52PM +0800, Yanteng Si wrote:
> > > 在 2024/2/6 06:06, Serge Semin 写道:
> > > > On Tue, Feb 06, 2024 at 12:58:17AM +0300, Serge Semin wrote:
> > > > > On Tue, Jan 30, 2024 at 04:49:14PM +0800, Yanteng Si wrote:
> > > > > > Current GNET does not support half duplex mode.
> > > > > > 
> > > > > > Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
> > > > > > Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
> > > > > > Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
> > > > > > ---
> > > > > >    drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c | 11 ++++++++++-
> > > > > >    drivers/net/ethernet/stmicro/stmmac/stmmac_main.c    |  3 ++-
> > > > > >    include/linux/stmmac.h                               |  1 +
> > > > > >    3 files changed, 13 insertions(+), 2 deletions(-)
> > > > > > 
> > > > > > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > > > > index 264c4c198d5a..1753a3c46b77 100644
> > > > > > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > > > > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > > > > @@ -432,8 +432,17 @@ static int loongson_gnet_config(struct pci_dev *pdev,
> > > > > >    				struct stmmac_resources *res,
> > > > > >    				struct device_node *np)
> > > > > >    {
> > > > > > -	if (pdev->revision == 0x00 || pdev->revision == 0x01)
> > > > > > +	switch (pdev->revision) {
> > > > > > +	case 0x00:
> > > > > > +		plat->flags |= STMMAC_FLAG_DISABLE_FORCE_1000 |
> > > > > > +			       STMMAC_FLAG_DISABLE_HALF_DUPLEX;
> > > > > > +		break;
> > > > > > +	case 0x01:
> > > > > >    		plat->flags |= STMMAC_FLAG_DISABLE_FORCE_1000;
> > > > > > +		break;
> > > > > > +	default:
> > > > > > +		break;
> > > > > > +	}
> > > > > Move this change into the patch
> > > > > [PATCH net-next v8 06/11] net: stmmac: dwmac-loongson: Add GNET support
> > > > > 
> > > > > >    	return 0;
> > > > > >    }
> > > > > > diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> > > > > > index 5617b40abbe4..3aa862269eb0 100644
> > > > > > --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> > > > > > +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> > > > > > @@ -1201,7 +1201,8 @@ static int stmmac_init_phy(struct net_device *dev)
> > > > > >    static void stmmac_set_half_duplex(struct stmmac_priv *priv)
> > > > > >    {
> > > > > >    	/* Half-Duplex can only work with single tx queue */
> > > > > > -	if (priv->plat->tx_queues_to_use > 1)
> > > > > > +	if (priv->plat->tx_queues_to_use > 1 ||
> > > > > > +	    (STMMAC_FLAG_DISABLE_HALF_DUPLEX & priv->plat->flags))
> > > > > >    		priv->phylink_config.mac_capabilities &=
> > > > > >    			~(MAC_10HD | MAC_100HD | MAC_1000HD);
> > > > > >    	else
> > > > > > diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
> > > > > > index 2810361e4048..197f6f914104 100644
> > > > > > --- a/include/linux/stmmac.h
> > > > > > +++ b/include/linux/stmmac.h
> > > > > > @@ -222,6 +222,7 @@ struct dwmac4_addrs {
> > > > > >    #define STMMAC_FLAG_EN_TX_LPI_CLOCKGATING	BIT(11)
> > > > > >    #define STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY	BIT(12)
> > > > > >    #define STMMAC_FLAG_DISABLE_FORCE_1000	BIT(13)
> > > > > > +#define STMMAC_FLAG_DISABLE_HALF_DUPLEX	BIT(14)
> > > > > Place the patch with this change before
> > > > > [PATCH net-next v8 06/11] net: stmmac: dwmac-loongson: Add GNET support
> > > > > as a pre-requisite/preparation patch. Don't forget a thorough
> > > > > description of what is wrong with the GNET Half-Duplex mode.
> > > > BTW what about re-defining the stmmac_ops.phylink_get_caps() callback
> > > > instead of adding fixup flags in this patch and in the next one?
> > > ok.
> > > 
> > > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > index ac1b48ff7199..b57e1325ce62 100644
> > > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > @@ -238,6 +234,13 @@ static int loongson_gnet_get_hw_feature(void __iomem
> > > *ioaddr,
> > >       return 0;
> > >   }
> 
> Hi Russell,
> 
> > > +static void loongson_phylink_get_caps(struct stmmac_priv *priv)
> > > +{
> > > +    priv->phylink_config.mac_capabilities = (MAC_10FD |
> > > +        MAC_100FD | MAC_1000FD) & ~(MAC_10HD | MAC_100HD | MAC_1000HD);
> > Why is this so complicated? It would be silly if the _full duplex_
> > definitions also defined the _half duplex_ bits. This should be just:
> > 
> > 	priv->phylink_config.mac_capabilities = MAC_10FD | MAC_100FD |
> > 						MAC_1000FD;
> 
> Yes, you are right. Our gnet device (7a2000) does not support half-duplex,
> while the gnet device (2k2000) does.
> 
> I plan to use PCI IDand IP CORE as the condition to separate full-duplex and
> half-duplex.
> 
> > 
> > if that is all you support. Do you not support any pause modes (they
> > would need to be included as well here.)
> 
> I have tested it and our gnet device supports MAC_ASYM_PAUSE and
> MAC_SYM_PAUSE, but gmac does not. I will fix this in the patch v9.
> 
> This is also easy to do because all GMAC devices have the same PCI ID.
> 
> > 

> > As to this approach, I don't think it's a good model to override the
> > stmmac MAC operations. Instead, I would suggest that a better approach
> > would be for the platform to provide its capabilities to the stmmac
> > core code (maybe a new member in stmmac_priv) which, when set, is used
> > to reduce the capabilities provided to phylink via
> > priv->phylink_config.mac_capabilities.
> > 
> > Why? The driver has several components that are involved in the
> > overall capabilities, and the capabilities of the system is the
> > logical subset of all these capabilities. One component should not
> > be setting capabilities that a different component doesn't support.

In general you are right for sure - it's better to avoid one part
setting capabilities and another part unsetting them at least from the
readability and maintainability point of view. But in this case we've
already got implemented a ready-to-use internal interface
stmmac_ops::phylink_get_caps() which can be used to extend/reduce the
capabilities field based on the particular MAC abilities. Moreover
it's called right from the component setting the capabilities. Are you
saying that the callback is supposed to be utilized for extending the
capabilities only?

If you insist on not overriding the stmmac_ops::phylink_get_caps()
anyway then please explain what is the principal difference
between the next two code snippets:
	/* Get the MAC specific capabilities */
        stmmac_mac_phylink_get_caps(priv);
and
	priv->phylink_config.mac_capabilities &= ~priv->plat->mac_caps_mask;
in the MAC-capabilities update implementation? Do you think the later
approach would be more descriptive? If so then would the
callback-based approach almost equally descriptive if the callback
name was, suppose, stmmac_mac_phylink_set_caps() or similar?

In anyway I am sure the approach suggested in the initial patch of
this thread isn't good since it motivates the developers to implement
more-and-more DW MAC-specific platform capabilities flags fixing
another flags, which makes the generic code even more complicated
than it already is with endless if-else-plat-flags statements.

-Serge(y)

> 
> Hi Serge,
> 
> It seems to be going back again, what do you think?
> 
> Thanks,
> 
> Yanteng
> 
> > 
> 
> 

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 04/11] net: stmmac: dwmac-loongson: Move irq config to loongson_gmac_config
  2024-03-19 13:43       ` Serge Semin
@ 2024-03-20 10:12         ` Yanteng Si
  0 siblings, 0 replies; 97+ messages in thread
From: Yanteng Si @ 2024-03-20 10:12 UTC (permalink / raw)
  To: Serge Semin
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang


在 2024/3/19 21:43, Serge Semin 写道:
> On Wed, Mar 13, 2024 at 04:14:28PM +0800, Yanteng Si wrote:
>> 在 2024/2/6 01:01, Serge Semin 写道:
>>> On Tue, Jan 30, 2024 at 04:43:24PM +0800, Yanteng Si wrote:
>>>> Add loongson_dwmac_config and moving irq config related
>>>> code to loongson_dwmac_config.
>>>>
>>>> Removing MSI to prepare for adding loongson multi-channel
>>>> support later.
>>> Please detach this change into a separate patch and thoroughly explain
>>> why it was necessary.
>> OK.
>>>> Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
>>>> Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
>>>> Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
>>>> ---
>>>>    .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 85 ++++++++++++-------
>>>>    1 file changed, 55 insertions(+), 30 deletions(-)
>>>>
>>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>>> index 979c9b6dab3f..e7ce027cc14e 100644
>>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>>> @@ -11,8 +11,46 @@
>>>>    struct stmmac_pci_info {
>>>>    	int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat);
>>>> +	int (*config)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat,
>>>> +		      struct stmmac_resources *res, struct device_node *np);
>>>>    };
>>>> +static int loongson_dwmac_config_legacy(struct pci_dev *pdev,
>>>> +					struct plat_stmmacenet_data *plat,
>>>> +					struct stmmac_resources *res,
>>>> +					struct device_node *np)
>>>> +{
>>>> +	if (np) {
>>>> +		res->irq = of_irq_get_byname(np, "macirq");
>>>> +		if (res->irq < 0) {
>>>> +			dev_err(&pdev->dev, "IRQ macirq not found\n");
>>>> +			return -ENODEV;
>>>> +		}
>>>> +
>>>> +		res->wol_irq = of_irq_get_byname(np, "eth_wake_irq");
>>>> +		if (res->wol_irq < 0) {
>>>> +			dev_info(&pdev->dev,
>>>> +				 "IRQ eth_wake_irq not found, using macirq\n");
>>>> +			res->wol_irq = res->irq;
>>>> +		}
>>>> +
>>>> +		res->lpi_irq = of_irq_get_byname(np, "eth_lpi");
>>>> +		if (res->lpi_irq < 0) {
>>>> +			dev_err(&pdev->dev, "IRQ eth_lpi not found\n");
>>>> +			return -ENODEV;
>>>> +		}
>>>> +	} else {
>>>> +		res->irq = pdev->irq;
>>>> +		res->wol_irq = res->irq;
>>>> +	}
>>>> +
>>>> +	plat->flags &= ~STMMAC_FLAG_MULTI_MSI_EN;
>>>> +	dev_info(&pdev->dev, "%s: Single IRQ enablement successful\n",
>>>> +		 __func__);
>>> Why is this here all of the sudden? I don't see this in the original
>>> code. Please move it to the patch which requires the flag
>>> setup/cleanup or drop if it isn't necessary.
>> +	plat->flags &= ~STMMAC_FLAG_MULTI_MSI_EN;
>> This cannot be removed because it appeared in a rebase(v4 -> v5). See
>> <https://lore.kernel.org/all/20230710090001.303225-9-brgl@bgdev.pl/>
> AFAICS it _can_ be removed. The patch you referred to is a formal
> conversion of
> -	plat->multi_msi_en = 0;
> to
> +	plat->flags &= ~STMMAC_FLAG_MULTI_MSI_EN;
> First of all the "multi_msi_en" field clearance had been
> redundant there since the code setting the flag was executed after the
> code which may cause the field clearance performed. Second AFAICS the
> "multi_msi_en" field clearance was originally added to emphasize the
> functions semantics:
> intel_eth_config_multi_msi() - config multi IRQ device,
> intel_eth_config_single_msi() - config single IRQ device.
>
> So in your case there is no any reason of clearing the
> STMMAC_FLAG_MULTI_MSI_EN flag. Please, either drop it or move the
> change into a separate patch.

OK, you are right. drop it.


Thanks,

Yanteng

>
> -Serge(y)
>
>> +	dev_info(&pdev->dev, "%s: Single IRQ enablement successful\n",
>> +		 __func__);
>>
>> OK, drop it.
>>
>>>> +
>>>> +	return 0;
>>>> +}
>>>> +
>>>>    static void loongson_default_data(struct pci_dev *pdev,
>>>>    				  struct plat_stmmacenet_data *plat)
>>>>    {
>>>> @@ -66,8 +104,21 @@ static int loongson_gmac_data(struct pci_dev *pdev,
>>>>    	return 0;
>>>>    }
>>>> +static int loongson_gmac_config(struct pci_dev *pdev,
>>>> +				struct plat_stmmacenet_data *plat,
>>>> +				struct stmmac_resources *res,
>>>> +				struct device_node *np)
>>>> +{
>>>> +	int ret;
>>>> +
>>>> +	ret = loongson_dwmac_config_legacy(pdev, plat, res, np);
>>>> +
>>>> +	return ret;
>>>> +}
>>>> +
>>> You introduce the config callback here and convert to a dummy method
>>> in
>>> [PATCH 07/11] net: stmmac: dwmac-loongson: Add multi-channel supports for loongson
>>> It's just pointless. What about introducing the
>>> loongson_dwmac_config_legacy() method and call it directly?
>> OK, I will try.
>>>>    static struct stmmac_pci_info loongson_gmac_pci_info = {
>>>>    	.setup = loongson_gmac_data,
>>>> +	.config = loongson_gmac_config,
>>>>    };
>>>>    static int loongson_dwmac_probe(struct pci_dev *pdev,
>>>> @@ -139,44 +190,19 @@ static int loongson_dwmac_probe(struct pci_dev *pdev,
>>>>    		plat->phy_interface = phy_mode;
>>>>    	}
>>>> -	pci_enable_msi(pdev);
>>> See my first note in this message.
>> OK.
>>
>>
>> Thanks,
>>
>> Yanteng
>>
>>> -Serge(y)
>>>
>>>>    	memset(&res, 0, sizeof(res));
>>>>    	res.addr = pcim_iomap_table(pdev)[0];
>>>> -	if (np) {
>>>> -		res.irq = of_irq_get_byname(np, "macirq");
>>>> -		if (res.irq < 0) {
>>>> -			dev_err(&pdev->dev, "IRQ macirq not found\n");
>>>> -			ret = -ENODEV;
>>>> -			goto err_disable_msi;
>>>> -		}
>>>> -
>>>> -		res.wol_irq = of_irq_get_byname(np, "eth_wake_irq");
>>>> -		if (res.wol_irq < 0) {
>>>> -			dev_info(&pdev->dev,
>>>> -				 "IRQ eth_wake_irq not found, using macirq\n");
>>>> -			res.wol_irq = res.irq;
>>>> -		}
>>>> -
>>>> -		res.lpi_irq = of_irq_get_byname(np, "eth_lpi");
>>>> -		if (res.lpi_irq < 0) {
>>>> -			dev_err(&pdev->dev, "IRQ eth_lpi not found\n");
>>>> -			ret = -ENODEV;
>>>> -			goto err_disable_msi;
>>>> -		}
>>>> -	} else {
>>>> -		res.irq = pdev->irq;
>>>> -		res.wol_irq = pdev->irq;
>>>> -	}
>>>> +	ret = info->config(pdev, plat, &res, np);
>>>> +	if (ret)
>>>> +		goto err_disable_device;
>>>>    	ret = stmmac_dvr_probe(&pdev->dev, plat, &res);
>>>>    	if (ret)
>>>> -		goto err_disable_msi;
>>>> +		goto err_disable_device;
>>>>    	return ret;
>>>> -err_disable_msi:
>>>> -	pci_disable_msi(pdev);
>>>>    err_disable_device:
>>>>    	pci_disable_device(pdev);
>>>>    err_put_node:
>>>> @@ -200,7 +226,6 @@ static void loongson_dwmac_remove(struct pci_dev *pdev)
>>>>    		break;
>>>>    	}
>>>> -	pci_disable_msi(pdev);
>>>>    	pci_disable_device(pdev);
>>>>    }
>>>> -- 
>>>> 2.31.4
>>>>


^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 06/11] net: stmmac: dwmac-loongson: Add GNET support
  2024-03-19 15:03         ` Serge Semin
@ 2024-03-20 10:23           ` Yanteng Si
  2024-03-20 12:18             ` Serge Semin
  2024-03-21  9:13           ` Yanteng Si
  1 sibling, 1 reply; 97+ messages in thread
From: Yanteng Si @ 2024-03-20 10:23 UTC (permalink / raw)
  To: Serge Semin
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang


在 2024/3/19 23:03, Serge Semin 写道:
> On Thu, Mar 14, 2024 at 09:12:49PM +0800, Yanteng Si wrote:
>> 在 2024/3/14 16:27, Yanteng Si 写道:
>>> 在 2024/2/6 04:58, Serge Semin 写道:
>>>> On Tue, Jan 30, 2024 at 04:48:18PM +0800, Yanteng Si wrote:
>>>>> Add Loongson GNET (GMAC with PHY) support, override
>>>>> stmmac_priv.synopsys_id with 0x37.
>>>> Please add more details of all the device capabilities: supported
>>>> speeds, duplexness, IP-core version, DMA-descriptors type
>>>> (normal/enhanced), MTL Tx/Rx FIFO size, Perfect and Hash-based MAC
>>>> Filter tables size, L3/L4 filters availability, VLAN hash table
>>>> filter, PHY-interface (GMII, RGMII, etc), EEE support,
>>>> AV-feature/Multi-channels support, IEEE 1588 Timestamp support, Magic
>>>> Frame support, Remote Wake-up support, IP Checksum, Tx/Rx TCP/IP
>>>> Checksum, Mac Management Counters (MMC), SMA/MDIO interface,
>>> The gnet (2k2000) of 0x10 supports full-duplex and half-duplex at 1000/100/10M.
>>> The gnet of 0x37 (i.e. the gnet of 7a2000) supports 1000/100/10M full duplex.
>>>
>>> The gnet with 0x10 has 8 DMA channels, except for channel 0, which does not
>>> support sending hardware checksums.
>>>
>>> Supported AV features are Qav, Qat, and Qas, and other features should be
>>> consistent with the 3.73 IP.
> Just list all of these features in the commit message referring to the
> respective controller. Like this:
> "There are two types of them Loongson GNET controllers:
> Loongson 2k2000 GNET and the rest of the Loongson GNETs (like
> presented on the 7a2000 SoC). All of them of the DW GMAC 3.73a
> IP-core with the next features:
> Speeds, DMA-descriptors type (normal/enhanced), MTL Tx/Rx FIFO size,
> Perfect and Hash-based MAC Filter tables size, L3/L4 filters availability,
> VLAN hash table filter, PHY-interface (GMII, RGMII, etc), EEE support,
> IEEE 1588 Timestamp support, Magic Frame support, Remote Wake-up support,
> IP Checksum, Tx/Rx TCP/IP Checksum, Mac Management Counters (MMC),
> SMA/MDIO interface.
>
> The difference is that the Loongson 2k2000 GNET controller supports 8
> DMA-channels, AV features (Qav, Qat, and Qas) and half-duplex link,
> meanwhile the rest of the GNETs don't have these capabilities
> available."
OK, Thanks!
>
>>>>> Signed-off-by: Yanteng Si<siyanteng@loongson.cn>
>>>>> Signed-off-by: Feiyang Chen<chenfeiyang@loongson.cn>
>>>>> Signed-off-by: Yinggang Gu<guyinggang@loongson.cn>
>>>>> ---
>>>>>    .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 44 +++++++++++++++++++
>>>>>    1 file changed, 44 insertions(+)
>>>>>
>>>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>>>> index 3b3578318cc1..584f7322bd3e 100644
>>>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>>>> @@ -318,6 +318,8 @@ static struct mac_device_info *loongson_setup(void *apriv)
>>>>>    	if (!mac)
>>>>>    		return NULL;
>>>>>    >> +	priv->synopsys_id = 0x37;	/*Overwrite custom IP*/
>>>>> +
>>>> Please add a more descriptive comment _above_ the subjected line. In
>>>> particular note why the override is needed, what is the real DW GMAC
>>>> IP-core version and what is the original value the statement above
>>>> overrides.
>>> The IP-core version of the gnet device on the loongson 2k2000 is 0x10, which is
>>> a custom IP.
>>>
>>> Compared to 0x37, we have split some of the dma registers into two (tx and rx).
>>> After overwriting stmmac_dma_ops.dma_interrupt() and stmmac_dma_ops.init_chan(),
>>> the logic is consistent with 0x37,
>>>
>>> so we overwrite synopsys_id to 0x37.
> Yeah, something like that:
> 	/* The original IP-core version is 0x37 in all Loongson GNET
> 	 * (2k2000 and 7a2000), but the GNET HW designers have changed the
> 	 * GMAC_VERSION.SNPSVER field to the custom 0x10 value on the Loongson
> 	 * 2k2000 MAC to emphasize the differences: multiple DMA-channels, AV
> 	 * feature and GMAC_INT_STATUS CSR flags layout. Get back the
> 	 * original value so the correct HW-interface would be
> 	 * selected.
> 	 */
OK, Thanks!
>>>>>    	ld = priv->plat->bsp_priv;
>>>>>    	mac->dma = &ld->dwlgmac_dma_ops;
>>>>>    >> @@ -350,6 +352,46 @@ static struct mac_device_info
>>> *loongson_setup(void *apriv)
>>>>>    	return mac;
>>>>>    }
>>>>>    >> +static int loongson_gnet_data(struct pci_dev *pdev,
>>>>> +			      struct plat_stmmacenet_data *plat)
>>>>> +{
>>>>> +	loongson_default_data(pdev, plat);
>>>>> +
>>>>> +	plat->multicast_filter_bins = 256;
>>>>> +
>>>>> +	plat->mdio_bus_data->phy_mask =  ~(u32)BIT(2);
>>>>> +
>>>>> +	plat->phy_addr = 2;
>>>>> +	plat->phy_interface = PHY_INTERFACE_MODE_INTERNAL;
>>>> Are you sure PHY-interface is supposed to be defined as "internal"?
>>> Yes, because the gnet hardware has a integrated PHY, so we set it to internal,
>>>
> Why do you need the phy_addr set to 2 then? Is PHY still discoverable
> on the subordinate MDIO-bus?
>
> kdoc in "include/linux/phy.h" defines the PHY_INTERFACE_MODE_INTERNAL
> mode as for a case of the MAC and PHY being combined. IIUC it's
> reserved for a case when you can't determine actual interface between
> the MAC and PHY. Is it your case? Are you sure the interface between
> MAC and PHY isn't something like GMII/RGMII/etc?

Please allow me to consult with our hardware engineers before replying 
to you. :)


Thanks,

Yanteng

>
> -Serge(y)
>
>>> Correspondingly, our gmac hardware PHY is external.
>>>
>>>>> +
>>>>> +	plat->bsp_priv = &pdev->dev;
>>>>> +
>>>>> +	plat->dma_cfg->pbl = 32;
>>>>> +	plat->dma_cfg->pblx8 = true;
>>>>> +
>>>>> +	plat->clk_ref_rate = 125000000;
>>>>> +	plat->clk_ptp_rate = 125000000;
>>>>> +
>>>>> +	return 0;
>>>>> +}
>>>>> +
>>>>> +static int loongson_gnet_config(struct pci_dev *pdev,
>>>>> +				struct plat_stmmacenet_data *plat,
>>>>> +				struct stmmac_resources *res,
>>>>> +				struct device_node *np)
>>>>> +{
>>>>> +	int ret;
>>>>> +
>>>>> +	ret = loongson_dwmac_config_legacy(pdev, plat, res, np);
>>>> Again. This will be moved to the probe() method in one of the next
>>>> patches leaving loongson_gnet_config() empty. What was the problem
>>>> with doing that right away with no intermediate change?
>>> No problem. My original intention is to break the patches down into smaller pieces.
>>>
>>> In the next version, I will try to re-break them based on your comments.
>>>
>>>>> +
>>>>> +	return ret;
>>>>> +}
>>>>> +
>>>>> +static struct stmmac_pci_info loongson_gnet_pci_info = {
>>>>> +	.setup = loongson_gnet_data,
>>>>> +	.config = loongson_gnet_config,
>>>>> +};
>>>>> +
>>>>>    static int loongson_dwmac_probe(struct pci_dev *pdev,
>>>>>    				const struct pci_device_id *id)
>>>>>    {
>>>>> @@ -516,9 +558,11 @@ static SIMPLE_DEV_PM_OPS(loongson_dwmac_pm_ops, loongson_dwmac_suspend,
>>>>>    			 loongson_dwmac_resume);
>>>>>    >>   #define PCI_DEVICE_ID_LOONGSON_GMAC	0x7a03
>>>>> +#define PCI_DEVICE_ID_LOONGSON_GNET	0x7a13
>>>>>    >>   static const struct pci_device_id loongson_dwmac_id_table[] =
>>> {
>>>>>    	{ PCI_DEVICE_DATA(LOONGSON, GMAC, &loongson_gmac_pci_info) },
>>>>> +	{ PCI_DEVICE_DATA(LOONGSON, GNET, &loongson_gnet_pci_info) },
>>>> After this the driver is supposed to correctly handle the Loongson
>>>> GNET devices. Based on the patches introduced further it isn't.
>>>> Please consider re-arranging the changes (see my comments in the
>>>> further patches).
>>> OK.
>>>
>>>
>>> Thanks,
>>>
>>> Yanteng
>>>
>>>
>>>> -Serge(y)
>>>>
>>>>>    	{}
>>>>>    };
>>>>>    MODULE_DEVICE_TABLE(pci, loongson_dwmac_id_table);
>>>>> -- >> 2.31.4
>>>>>


^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 09/11] net: stmmac: dwmac-loongson: Fix half duplex
  2024-03-20 10:10             ` Serge Semin
@ 2024-03-20 10:37               ` Russell King (Oracle)
  2024-03-20 12:50                 ` Russell King (Oracle)
  2024-03-22 18:07                 ` Serge Semin
  0 siblings, 2 replies; 97+ messages in thread
From: Russell King (Oracle) @ 2024-03-20 10:37 UTC (permalink / raw)
  To: Serge Semin
  Cc: Yanteng Si, andrew, hkallweit1, peppe.cavallaro,
	alexandre.torgue, joabreu, Jose.Abreu, chenhuacai, guyinggang,
	netdev, chris.chenfeiyang

Serge,

Again, please learn to trim your replies.

On Wed, Mar 20, 2024 at 01:10:04PM +0300, Serge Semin wrote:
> > > As to this approach, I don't think it's a good model to override the
> > > stmmac MAC operations. Instead, I would suggest that a better approach
> > > would be for the platform to provide its capabilities to the stmmac
> > > core code (maybe a new member in stmmac_priv) which, when set, is used
> > > to reduce the capabilities provided to phylink via
> > > priv->phylink_config.mac_capabilities.
> > > 
> > > Why? The driver has several components that are involved in the
> > > overall capabilities, and the capabilities of the system is the
> > > logical subset of all these capabilities. One component should not
> > > be setting capabilities that a different component doesn't support.
> 
> In general you are right for sure - it's better to avoid one part
> setting capabilities and another part unsetting them at least from the
> readability and maintainability point of view. But in this case we've
> already got implemented a ready-to-use internal interface
> stmmac_ops::phylink_get_caps() which can be used to extend/reduce the
> capabilities field based on the particular MAC abilities. Moreover
> it's called right from the component setting the capabilities. Are you
> saying that the callback is supposed to be utilized for extending the
> capabilities only?

What concerns me is that the proposed code _overwrites_ the
capabilities from the MAC layer, so from a maintanability point of
view it's a nightmare, because you will now have the situation where
MACs provide their capabilities, and then platform code may overwrite
it - which means it's like a spiders web trying to work out what
capabilities are provided.

The reality is surely that the MAC dictates what it can do, but there
may be further restrictions by other components in the platform, so
the capabilities provided to phylink should be:

	mac_capabilities & platform_capabilities

And what I'm proposing is that _that_ should be done in a way that
makes it _easy_ for the platform code to get right. Overriding
stmmac_ops::phylink_get_caps() doesn't do that - as can be seen in
the proposed patch.

Help your users write correct code by adopting a structure that makes
it easy for them to do the right thing.

> If you insist on not overriding the stmmac_ops::phylink_get_caps()
> anyway then please explain what is the principal difference
> between the next two code snippets:
> 	/* Get the MAC specific capabilities */
>         stmmac_mac_phylink_get_caps(priv);
> and
> 	priv->phylink_config.mac_capabilities &= ~priv->plat->mac_caps_mask;


I was thinking:

	stmmac_mac_phylink_get_caps(priv);

	if (priv->plat->mac_capabilities)
		priv->phylink_config.mac_capabilities &=
			priv->plat->mac_capabilities;

In other words, if a platform sets plat->mac_capabilities, then it is
providing the capabilities that it supports, and those need to reduce
the capabilities provided by the MAC.

This will _also_ allow stmmac_set_half_duplex() to do the right thing.
Consider something in the platform side that doesn't allow half-duplex,
but allows tx_queues_to_use == 1. That'll set the half-duplex modes
when stmmac_set_half_duplex() is called, overriding what the platform
supports.

Now that I look at the stmmac implementation, there's even more that
is wrong. Consider plat->max_speed = 100, like
arch/arc/boot/dts/axs10x_mb.dtsi sets. If stmmac_set_half_duplex()
is called as it can be from stmmac_reinit_queues(), it'll enable
1000 half-duplex, despite the plat->max_speed = 100.

> in the MAC-capabilities update implementation? Do you think the later
> approach would be more descriptive? If so then would the
> callback-based approach almost equally descriptive if the callback
> name was, suppose, stmmac_mac_phylink_set_caps() or similar?

From what I can see of the existing stmmac MAC phylink_get_caps
implementations, there seem to be two - xgmac_phylink_get_caps()
and dwmac4_phylink_get_caps(). Both of these merely set additional
modes in priv->phylink_config.mac_capabilities. Is there a reason
to have this as an instruction stream, rather than providing data
to the core stmmac code from the MAC about its capabilities? Is
there a reason why it would be necessary for the code in a MAC backend
to make a decision about what capabilities to enable based on some
condition?

> In anyway I am sure the approach suggested in the initial patch of
> this thread isn't good since it motivates the developers to implement
> more-and-more DW MAC-specific platform capabilities flags fixing
> another flags, which makes the generic code even more complicated
> than it already is with endless if-else-plat-flags statements.

Yes, I do agree with that.

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 08/11] net: stmmac: dwmac-loongson: Fix MAC speed for GNET
  2024-03-19 17:02         ` Serge Semin
@ 2024-03-20 10:42           ` Yanteng Si
  2024-03-21  9:29           ` Yanteng Si
  1 sibling, 0 replies; 97+ messages in thread
From: Yanteng Si @ 2024-03-20 10:42 UTC (permalink / raw)
  To: Serge Semin
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang


在 2024/3/20 01:02, Serge Semin 写道:
> On Thu, Mar 14, 2024 at 09:18:15PM +0800, Yanteng Si wrote:
>> 在 2024/3/14 17:43, Yanteng Si 写道:
>>> 在 2024/2/6 05:55, Serge Semin 写道:
>>>> On Tue, Jan 30, 2024 at 04:48:20PM +0800, Yanteng Si wrote:
>>>>> Current GNET on LS7A only supports ANE when speed is
>>>>> set to 1000M.
>>>> If so you need to merge it into the patch
>>>> [PATCH net-next v8 06/11] net: stmmac: dwmac-loongson: Add GNET support
>>>> Current GNET on LS7A only supports ANE when speed is
>>>> set to 1000M.
>>> If so you need to merge it into the patch
>>> [PATCH net-next v8 06/11] net: stmmac: dwmac-loongson: Add GNET support
>> OK.
>>
>>>>> Signed-off-by: Yanteng Si<siyanteng@loongson.cn>
>>>>> Signed-off-by: Feiyang Chen<chenfeiyang@loongson.cn>
>>>>> Signed-off-by: Yinggang Gu<guyinggang@loongson.cn>
>>>>> ---
>>>>>    .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 19 +++++++++++++++++++
>>>>>    .../ethernet/stmicro/stmmac/stmmac_ethtool.c  |  6 ++++++
>>>>>    include/linux/stmmac.h                        |  1 +
>>>>>    3 files changed, 26 insertions(+)
>>>>>
>>>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>>>> index 60d0a122d7c9..264c4c198d5a 100644
>>>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>>>> @@ -344,6 +344,21 @@ static struct stmmac_pci_info loongson_gmac_pci_info = {
>>>>>    	.config = loongson_gmac_config,
>>>>>    };
>>>>>    >> +static void loongson_gnet_fix_speed(void *priv, unsigned int
>>> speed, unsigned int mode)
>>>>> +{
>>>>> +	struct loongson_data *ld = (struct loongson_data *)priv;
>>>>> +	struct net_device *ndev = dev_get_drvdata(ld->dev);
>>>>> +	struct stmmac_priv *ptr = netdev_priv(ndev);
>>>>> +
>>>>> +	/* The controller and PHY don't work well together.
>>>> So there _is_ a PHY. What is the interface between MAC and PHY then?
>>>>
>>>> GMAC only has a MAC chip inside the chip and needs an external PHY
>>> chip; GNET > has the PHY chip inside the chip.
> We are talking about GNETs in this method since it has the
> loongson_gnet_ prefix. You are referring to GMAC. I am getting
> confused about all of these. Based on the patch 06/11 of this series
> you call "Loongson GNET" of all the devices placed on the PCI devices
> with PCI ID 0x7a13. PCIe device with ID 0x7a03 is called "Loongson
> GMAC". Right?

ls2k is SOC, ls7a ls bridge:


device    type    pci_id    gmac_version
ls7a1000  gmac    7a03      0x37
ls2k1000  gmac    7a03      0x37
ls7a2000  gnet    7a13      0x37
ls2k2000  gnet    7a13      0x10
>
> Anyway no matter whether the PHY is placed externally or inside the
> chip. AFAIU as long as you know the interface type between MAC and PHY
> it would be better to have it specified.
>
>>>>> +	 * We need to use the PS bit to check if the controller's status
>>>>> +	 * is correct and reset PHY if necessary.
>>>>> +	 */
>>>>> +	if (speed == SPEED_1000)
>>>>> +		if (readl(ptr->ioaddr + MAC_CTRL_REG) & (1 << 15) /* PS */)
>>>>> +			phy_restart_aneg(ndev->phydev);
>>>> 1. Please add curly braces for the outer if-statement.
>>> OK,
>>>> 2. MAC_CTRL_REG.15 is defined by the GMAC_CONTROL_PS macro.
>>> OK.
>>>
>>> if(speed==SPEED_1000){
>>> /*MAC_CTRL_REG.15 is defined by the GMAC_CONTROL_PS macro.*/
>>> if(readl(ptr->ioaddr+MAC_CTRL_REG) &(1<<15))
>>> phy_restart_aneg(ndev->phydev);
>>> }
>>>
>>>> 3. How is the AN-restart helps? PHY-reset is done in
>>>> stmmac_init_phy()->phylink_connect_phy()->... a bit earlier than
>>>> this is called in the framework of the stmmac_mac_link_up() callback.
>>>> Wouldn't that restart AN too?
>>> Due to a bug in the chip's internal PHY, the network is still not working after
>>> the first self-negotiation, and it needs to be self-negotiated again.
> Then please describe the bug in more details then.
>
> Getting back to the code you implemented here. In the in-situ comment
> you say: "We need to use the PS bit to check if the controller's
> status is correct and reset PHY if necessary." By calling
> phy_restart_aneg() you don't reset the PHY.
>
> Moreover if "PS" flag is set, then the MAC has been pre-configured to
> work in the 10/100Mbps mode. Since 1000Mbps speed is requested, the
> MAC_CTRL_REG.PS flag will be cleared later in the
> stmmac_mac_link_up() method and then phylink_start() shall cause the
> link speed re-auto-negotiation. Why do you need the auto-negotiation
> started for the default MAC config which will be changed just in a
> moment later? All of that seems weird.
>
> Most importantly I have doubts the networking subsystem maintainers
> will permit you calling the phy_restart_aneg() method from the MAC
> driver code.

I will reply to you tomorrow.


>
>>>>> +}
>>>>> +
>>>>>    static struct mac_device_info *loongson_setup(void *apriv)
>>>>>    {
>>>>>    	struct stmmac_priv *priv = apriv;
>>>>> @@ -401,6 +416,7 @@ static int loongson_gnet_data(struct pci_dev *pdev,
>>>>>    	plat->phy_interface = PHY_INTERFACE_MODE_INTERNAL;
>>>>>    >>   	plat->bsp_priv = &pdev->dev;
>>>>> +	plat->fix_mac_speed = loongson_gnet_fix_speed;
>>>>>    >>   	plat->dma_cfg->pbl = 32;
>>>>>    	plat->dma_cfg->pblx8 = true;
>>>>> @@ -416,6 +432,9 @@ static int loongson_gnet_config(struct pci_dev *pdev,
>>>>>    				struct stmmac_resources *res,
>>>>>    				struct device_node *np)
>>>>>    {
>>>>> +	if (pdev->revision == 0x00 || pdev->revision == 0x01)
>>>>> +		plat->flags |= STMMAC_FLAG_DISABLE_FORCE_1000;
>>>>> +
>>>> This should be in the patch
>>>> [PATCH net-next v8 06/11] net: stmmac: dwmac-loongson: Add GNET support
>>> OK.
>>>>>    	return 0;
>>>>>    }
>>>>>    >> diff --git
>>> a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
>>> b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
>>>>> index 42d27b97dd1d..31068fbc23c9 100644
>>>>> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
>>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
>>>>> @@ -422,6 +422,12 @@ stmmac_ethtool_set_link_ksettings(struct net_device *dev,
>>>>>    		return 0;
>>>>>    	}
>>>>>    >> +	if (FIELD_GET(STMMAC_FLAG_DISABLE_FORCE_1000,
>>> priv->plat->flags)) {
>>>> FIELD_GET()?
>>> OK,
>>>
>>> if (STMMAC_FLAG_DISABLE_FORCE_1000 & priv->plat->flags) {
> it's better to change the order of the operands:
> 	if (priv->plat->flags & STMMAC_FLAG_DISABLE_FORCE_1000) {

OK,


Thanks,

Yanteng

>
> -Serge(y)
>
>>>>> +		if (cmd->base.speed == SPEED_1000 &&
>>>>> +		    cmd->base.autoneg != AUTONEG_ENABLE)
>>>>> +			return -EOPNOTSUPP;
>>>>> +	}
>>>>> +
>>>>>    	return phylink_ethtool_ksettings_set(priv->phylink, cmd);
>>>>>    }
>>>>>    >> diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
>>>>> index dee5ad6e48c5..2810361e4048 100644
>>>>> --- a/include/linux/stmmac.h
>>>>> +++ b/include/linux/stmmac.h
>>>>> @@ -221,6 +221,7 @@ struct dwmac4_addrs {
>>>>>    #define STMMAC_FLAG_RX_CLK_RUNS_IN_LPI		BIT(10)
>>>>>    #define STMMAC_FLAG_EN_TX_LPI_CLOCKGATING	BIT(11)
>>>>>    #define STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY	BIT(12)
>>>>> +#define STMMAC_FLAG_DISABLE_FORCE_1000	BIT(13)
>>>> Detach the change introducing the STMMAC_FLAG_DISABLE_FORCE_1000 flag
>>>> into a separate patch a place it before
>>>> [PATCH net-next v8 06/11] net: stmmac: dwmac-loongson: Add GNET support
>>>> as a pre-requisite/preparation patch.
>>>> Don't forget a _detailed_ description of why it's necessary, what is
>>>> wrong with GNET so 1G speed doesn't work without AN.
>>> OK.
>>>
>>>
>>> Thanks,
>>>
>>> Yanteng
>>>
>>>> -Serge(y)
>>>>
>>>>>    >>   struct plat_stmmacenet_data {
>>>>>    	int bus_id;
>>>>> -- >> 2.31.4
>>>>>


^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 01/11] net: stmmac: Add multi-channel support
  2024-03-20  9:55               ` Russell King (Oracle)
@ 2024-03-20 10:51                 ` Yanteng Si
  0 siblings, 0 replies; 97+ messages in thread
From: Yanteng Si @ 2024-03-20 10:51 UTC (permalink / raw)
  To: Russell King (Oracle), Serge Semin
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, guyinggang, netdev, chris.chenfeiyang


在 2024/3/20 17:55, Russell King (Oracle) 写道:
> Please also trim appropriately your replies (that goes for both of you.)
> I tried to work out whether you'd provided any content apart from the
> above, but I really couldn't be bothered to page through the message.

Sorry, I will.  I'm sorry to have caused you trouble.  I just saw this 
comment.


Thanks,

Yanteng


^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 11/11] net: stmmac: dwmac-loongson: Disable coe for some Loongson GNET
  2024-03-13 10:19       ` Yanteng Si
@ 2024-03-20 11:24         ` Serge Semin
  0 siblings, 0 replies; 97+ messages in thread
From: Serge Semin @ 2024-03-20 11:24 UTC (permalink / raw)
  To: Yanteng Si
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

Hi Yanteng

On Wed, Mar 13, 2024 at 06:19:47PM +0800, Yanteng Si wrote:
> 
> 在 2024/3/13 17:52, Yanteng Si 写道:
> > 
> > 在 2024/2/6 06:18, Serge Semin 写道:
> > > On Tue, Jan 30, 2024 at 04:49:16PM +0800, Yanteng Si wrote:
> > > > Some chips of Loongson GNET does not support coe, so disable them.
> > > s/coe/Tx COE
> > OK.
> > > 
> > > > Set dma_cap->tx_coe to 0 and overwrite get_hw_feature.
> > > > 
> > > > Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
> > > > Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
> > > > Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
> > > > ---
> > > >   .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 46
> > > > +++++++++++++++++++
> > > >   1 file changed, 46 insertions(+)
> > > > 
> > > > diff --git
> > > > a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > > b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > > index b78a73ea748b..8018d7d5f31b 100644
> > > > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > > @@ -196,6 +196,51 @@ static int dwlgmac_dma_interrupt(struct
> > > > stmmac_priv *priv, void __iomem *ioaddr,
> > > >       return ret;
> > > >   }
> > > >   +static int dwlgmac_get_hw_feature(void __iomem *ioaddr,
> > > Please use GNET-specific prefix.
> > OK. loongson_gnet_get_hw_feature()
> > > 
> > > > +                  struct dma_features *dma_cap)
> > > > +{
> > > > +    u32 hw_cap = readl(ioaddr + DMA_HW_FEATURE);
> > > > +
> > > > +    if (!hw_cap) {
> > > > +        /* 0x00000000 is the value read on old hardware that does not
> > > > +         * implement this register
> > > > +         */
> > > > +        return -EOPNOTSUPP;
> > > > +    }
> > > This doesn't seems like possible. All your devices have the
> > > HW-features register. If so please drop.
> > OK, drop it.
> > > 
> > > > +
> > > > +    dma_cap->mbps_10_100 = (hw_cap & DMA_HW_FEAT_MIISEL);
> > > > +    dma_cap->mbps_1000 = (hw_cap & DMA_HW_FEAT_GMIISEL) >> 1;
> > > > +    dma_cap->half_duplex = (hw_cap & DMA_HW_FEAT_HDSEL) >> 2;
> > > > +    dma_cap->hash_filter = (hw_cap & DMA_HW_FEAT_HASHSEL) >> 4;
> > > > +    dma_cap->multi_addr = (hw_cap & DMA_HW_FEAT_ADDMAC) >> 5;
> > > > +    dma_cap->pcs = (hw_cap & DMA_HW_FEAT_PCSSEL) >> 6;
> > > > +    dma_cap->sma_mdio = (hw_cap & DMA_HW_FEAT_SMASEL) >> 8;
> > > > +    dma_cap->pmt_remote_wake_up = (hw_cap & DMA_HW_FEAT_RWKSEL) >> 9;
> > > > +    dma_cap->pmt_magic_frame = (hw_cap & DMA_HW_FEAT_MGKSEL) >> 10;
> > > > +    /* MMC */
> > > > +    dma_cap->rmon = (hw_cap & DMA_HW_FEAT_MMCSEL) >> 11;
> > > > +    /* IEEE 1588-2002 */
> > > > +    dma_cap->time_stamp =
> > > > +        (hw_cap & DMA_HW_FEAT_TSVER1SEL) >> 12;
> > > > +    /* IEEE 1588-2008 */
> > > > +    dma_cap->atime_stamp = (hw_cap & DMA_HW_FEAT_TSVER2SEL) >> 13;
> > > > +    /* 802.3az - Energy-Efficient Ethernet (EEE) */
> > > > +    dma_cap->eee = (hw_cap & DMA_HW_FEAT_EEESEL) >> 14;
> > > > +    dma_cap->av = (hw_cap & DMA_HW_FEAT_AVSEL) >> 15;
> > > > +    /* TX and RX csum */
> > > > +    dma_cap->tx_coe = 0;
> > > > +    dma_cap->rx_coe_type1 = (hw_cap & DMA_HW_FEAT_RXTYP1COE) >> 17;
> > > > +    dma_cap->rx_coe_type2 = (hw_cap & DMA_HW_FEAT_RXTYP2COE) >> 18;
> > > > +    dma_cap->rxfifo_over_2048 = (hw_cap &
> > > > DMA_HW_FEAT_RXFIFOSIZE) >> 19;
> > > > +    /* TX and RX number of channels */
> > > > +    dma_cap->number_rx_channel = (hw_cap & DMA_HW_FEAT_RXCHCNT) >> 20;
> > > > +    dma_cap->number_tx_channel = (hw_cap & DMA_HW_FEAT_TXCHCNT) >> 22;
> > > > +    /* Alternate (enhanced) DESC mode */
> > > > +    dma_cap->enh_desc = (hw_cap & DMA_HW_FEAT_ENHDESSEL) >> 24;
> > > I am not sure whether you need to parse the capability register at all
> > > seeing this is a GNET-specific method. For that device all the
> > > capabilities are already known and can be just initialized in this
> > > method.
> > -dma_cap->tx_coe = (hw_cap & DMA_HW_FEAT_TXCOESEL) >> 16;
> > 
> > +dma_cap->tx_coe = 0;
> > 
> > I'm a little confused. Actually, I only modified this line, which is
> > used to fix the checksum.
> > 
> > 2k2000  of Loongson GNET does not support coe.
> 
> Specifically, it is to ensure the normal operation of multiple channels, as
> other channels except for channel 0 cannot perform checksum.

Originally I thought that Tx-COE was fully broken, but seeing it works
for channel 0 changes the situation. While we kept discussing your
series a useful patch was merged into the driver:
https://lore.kernel.org/netdev/20230916063312.7011-3-rohan.g.thomas@intel.com/
The stmmac_txq_cfg::coe_unsupported flag can be used to disable Tx COE
for the particular channels. You can just set the coe_unsupported flag
for the channels greater than zero and the skb_checksum_help() helper
will be utilized for them to calculate the packets control sum. This
will be the most optimal solution since channel zero will still be
serviced by the Tx Checksum Offload Engine and you won't need the
stmmac_dma_ops::get_hw_feature() callback redefinition.

-Serge(y)

> 
> Thanks,
> 
> Yanteng
> 
> 
> > 
> > 
> > Thanks,
> > Yanteng
> > 
> > > 
> > > -Serge(y)
> > > 
> > > > +
> > > > +    return 0;
> > > > +}
> > > > +
> > > >   struct stmmac_pci_info {
> > > >       int (*setup)(struct pci_dev *pdev, struct
> > > > plat_stmmacenet_data *plat);
> > > >       int (*config)(struct pci_dev *pdev, struct
> > > > plat_stmmacenet_data *plat,
> > > > @@ -542,6 +587,7 @@ static int loongson_dwmac_probe(struct
> > > > pci_dev *pdev,
> > > >           ld->dwlgmac_dma_ops = dwmac1000_dma_ops;
> > > >           ld->dwlgmac_dma_ops.init_chan = dwlgmac_dma_init_channel;
> > > >           ld->dwlgmac_dma_ops.dma_interrupt = dwlgmac_dma_interrupt;
> > > > +        ld->dwlgmac_dma_ops.get_hw_feature = dwlgmac_get_hw_feature;
> > > >             plat->setup = loongson_setup;
> > > >           ret = loongson_dwmac_config_multi_msi(pdev, plat,
> > > > &res, np, 8);
> > > > -- 
> > > > 2.31.4
> > > > 
> 

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 06/11] net: stmmac: dwmac-loongson: Add GNET support
  2024-03-20 10:23           ` Yanteng Si
@ 2024-03-20 12:18             ` Serge Semin
  0 siblings, 0 replies; 97+ messages in thread
From: Serge Semin @ 2024-03-20 12:18 UTC (permalink / raw)
  To: Yanteng Si
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

On Wed, Mar 20, 2024 at 06:23:14PM +0800, Yanteng Si wrote:
> 
> 在 2024/3/19 23:03, Serge Semin 写道:
> > On Thu, Mar 14, 2024 at 09:12:49PM +0800, Yanteng Si wrote:
> > > 在 2024/3/14 16:27, Yanteng Si 写道:
> > > > 在 2024/2/6 04:58, Serge Semin 写道:
> > > > > On Tue, Jan 30, 2024 at 04:48:18PM +0800, Yanteng Si wrote:
> > > > > > Add Loongson GNET (GMAC with PHY) support, override
> > > > > > stmmac_priv.synopsys_id with 0x37.
> > > > > Please add more details of all the device capabilities: supported
> > > > > speeds, duplexness, IP-core version, DMA-descriptors type
> > > > > (normal/enhanced), MTL Tx/Rx FIFO size, Perfect and Hash-based MAC
> > > > > Filter tables size, L3/L4 filters availability, VLAN hash table
> > > > > filter, PHY-interface (GMII, RGMII, etc), EEE support,
> > > > > AV-feature/Multi-channels support, IEEE 1588 Timestamp support, Magic
> > > > > Frame support, Remote Wake-up support, IP Checksum, Tx/Rx TCP/IP
> > > > > Checksum, Mac Management Counters (MMC), SMA/MDIO interface,
> > > > The gnet (2k2000) of 0x10 supports full-duplex and half-duplex at 1000/100/10M.
> > > > The gnet of 0x37 (i.e. the gnet of 7a2000) supports 1000/100/10M full duplex.
> > > > 
> > > > The gnet with 0x10 has 8 DMA channels, except for channel 0, which does not
> > > > support sending hardware checksums.
> > > > 
> > > > Supported AV features are Qav, Qat, and Qas, and other features should be
> > > > consistent with the 3.73 IP.
> > Just list all of these features in the commit message referring to the
> > respective controller. Like this:
> > "There are two types of them Loongson GNET controllers:
> > Loongson 2k2000 GNET and the rest of the Loongson GNETs (like
> > presented on the 7a2000 SoC). All of them of the DW GMAC 3.73a
> > IP-core with the next features:
> > Speeds, DMA-descriptors type (normal/enhanced), MTL Tx/Rx FIFO size,
> > Perfect and Hash-based MAC Filter tables size, L3/L4 filters availability,
> > VLAN hash table filter, PHY-interface (GMII, RGMII, etc), EEE support,
> > IEEE 1588 Timestamp support, Magic Frame support, Remote Wake-up support,
> > IP Checksum, Tx/Rx TCP/IP Checksum, Mac Management Counters (MMC),
> > SMA/MDIO interface.
> > 
> > The difference is that the Loongson 2k2000 GNET controller supports 8
> > DMA-channels, AV features (Qav, Qat, and Qas) and half-duplex link,
> > meanwhile the rest of the GNETs don't have these capabilities
> > available."

> OK, Thanks!

Please don't forget to replace the next text:

"... Speeds, DMA-descriptors type (normal/enhanced), MTL Tx/Rx FIFO size,
Perfect and Hash-based MAC Filter tables size, L3/L4 filters availability,
VLAN hash table filter, PHY-interface (GMII, RGMII, etc), EEE support,
IEEE 1588 Timestamp support, Magic Frame support, Remote Wake-up support,
IP Checksum, Tx/Rx TCP/IP Checksum, Mac Management Counters (MMC),
SMA/MDIO interface."

with the actual device capabilities, like:
Speeds - 10/100/1000Mbps,
DMA-descriptors type - Normal DMA descriptors or Enhanced DMA descriptors,
MTL Tx/Rx FIFO size -  X Kb MTL Tx FIFO, Y Kb MTL Rx FIFO,
Perfect and Hash-based MAC Filter tables size - X MAC addresses,
X-entries hash address filter,
etc

-Serge(y)

> > 
> > > > > > Signed-off-by: Yanteng Si<siyanteng@loongson.cn>
> > > > > > Signed-off-by: Feiyang Chen<chenfeiyang@loongson.cn>
> > > > > > Signed-off-by: Yinggang Gu<guyinggang@loongson.cn>
> > > > > > ---
> > > > > >    .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 44 +++++++++++++++++++
> > > > > >    1 file changed, 44 insertions(+)
> > > > > > 
> > > > > > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > > > > index 3b3578318cc1..584f7322bd3e 100644
> > > > > > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > > > > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > > > > @@ -318,6 +318,8 @@ static struct mac_device_info *loongson_setup(void *apriv)
> > > > > >    	if (!mac)
> > > > > >    		return NULL;
> > > > > >    >> +	priv->synopsys_id = 0x37;	/*Overwrite custom IP*/
> > > > > > +
> > > > > Please add a more descriptive comment _above_ the subjected line. In
> > > > > particular note why the override is needed, what is the real DW GMAC
> > > > > IP-core version and what is the original value the statement above
> > > > > overrides.
> > > > The IP-core version of the gnet device on the loongson 2k2000 is 0x10, which is
> > > > a custom IP.
> > > > 
> > > > Compared to 0x37, we have split some of the dma registers into two (tx and rx).
> > > > After overwriting stmmac_dma_ops.dma_interrupt() and stmmac_dma_ops.init_chan(),
> > > > the logic is consistent with 0x37,
> > > > 
> > > > so we overwrite synopsys_id to 0x37.
> > Yeah, something like that:
> > 	/* The original IP-core version is 0x37 in all Loongson GNET
> > 	 * (2k2000 and 7a2000), but the GNET HW designers have changed the
> > 	 * GMAC_VERSION.SNPSVER field to the custom 0x10 value on the Loongson
> > 	 * 2k2000 MAC to emphasize the differences: multiple DMA-channels, AV
> > 	 * feature and GMAC_INT_STATUS CSR flags layout. Get back the
> > 	 * original value so the correct HW-interface would be
> > 	 * selected.
> > 	 */
> OK, Thanks!
> > > > > >    	ld = priv->plat->bsp_priv;
> > > > > >    	mac->dma = &ld->dwlgmac_dma_ops;
> > > > > >    >> @@ -350,6 +352,46 @@ static struct mac_device_info
> > > > *loongson_setup(void *apriv)
> > > > > >    	return mac;
> > > > > >    }
> > > > > >    >> +static int loongson_gnet_data(struct pci_dev *pdev,
> > > > > > +			      struct plat_stmmacenet_data *plat)
> > > > > > +{
> > > > > > +	loongson_default_data(pdev, plat);
> > > > > > +
> > > > > > +	plat->multicast_filter_bins = 256;
> > > > > > +
> > > > > > +	plat->mdio_bus_data->phy_mask =  ~(u32)BIT(2);
> > > > > > +
> > > > > > +	plat->phy_addr = 2;
> > > > > > +	plat->phy_interface = PHY_INTERFACE_MODE_INTERNAL;
> > > > > Are you sure PHY-interface is supposed to be defined as "internal"?
> > > > Yes, because the gnet hardware has a integrated PHY, so we set it to internal,
> > > > 
> > Why do you need the phy_addr set to 2 then? Is PHY still discoverable
> > on the subordinate MDIO-bus?
> > 
> > kdoc in "include/linux/phy.h" defines the PHY_INTERFACE_MODE_INTERNAL
> > mode as for a case of the MAC and PHY being combined. IIUC it's
> > reserved for a case when you can't determine actual interface between
> > the MAC and PHY. Is it your case? Are you sure the interface between
> > MAC and PHY isn't something like GMII/RGMII/etc?
> 
> Please allow me to consult with our hardware engineers before replying to
> you. :)
> 
> 
> Thanks,
> 
> Yanteng
> 
> > 
> > -Serge(y)
> > 
> > > > Correspondingly, our gmac hardware PHY is external.
> > > > 
> > > > > > +
> > > > > > +	plat->bsp_priv = &pdev->dev;
> > > > > > +
> > > > > > +	plat->dma_cfg->pbl = 32;
> > > > > > +	plat->dma_cfg->pblx8 = true;
> > > > > > +
> > > > > > +	plat->clk_ref_rate = 125000000;
> > > > > > +	plat->clk_ptp_rate = 125000000;
> > > > > > +
> > > > > > +	return 0;
> > > > > > +}
> > > > > > +
> > > > > > +static int loongson_gnet_config(struct pci_dev *pdev,
> > > > > > +				struct plat_stmmacenet_data *plat,
> > > > > > +				struct stmmac_resources *res,
> > > > > > +				struct device_node *np)
> > > > > > +{
> > > > > > +	int ret;
> > > > > > +
> > > > > > +	ret = loongson_dwmac_config_legacy(pdev, plat, res, np);
> > > > > Again. This will be moved to the probe() method in one of the next
> > > > > patches leaving loongson_gnet_config() empty. What was the problem
> > > > > with doing that right away with no intermediate change?
> > > > No problem. My original intention is to break the patches down into smaller pieces.
> > > > 
> > > > In the next version, I will try to re-break them based on your comments.
> > > > 
> > > > > > +
> > > > > > +	return ret;
> > > > > > +}
> > > > > > +
> > > > > > +static struct stmmac_pci_info loongson_gnet_pci_info = {
> > > > > > +	.setup = loongson_gnet_data,
> > > > > > +	.config = loongson_gnet_config,
> > > > > > +};
> > > > > > +
> > > > > >    static int loongson_dwmac_probe(struct pci_dev *pdev,
> > > > > >    				const struct pci_device_id *id)
> > > > > >    {
> > > > > > @@ -516,9 +558,11 @@ static SIMPLE_DEV_PM_OPS(loongson_dwmac_pm_ops, loongson_dwmac_suspend,
> > > > > >    			 loongson_dwmac_resume);
> > > > > >    >>   #define PCI_DEVICE_ID_LOONGSON_GMAC	0x7a03
> > > > > > +#define PCI_DEVICE_ID_LOONGSON_GNET	0x7a13
> > > > > >    >>   static const struct pci_device_id loongson_dwmac_id_table[] =
> > > > {
> > > > > >    	{ PCI_DEVICE_DATA(LOONGSON, GMAC, &loongson_gmac_pci_info) },
> > > > > > +	{ PCI_DEVICE_DATA(LOONGSON, GNET, &loongson_gnet_pci_info) },
> > > > > After this the driver is supposed to correctly handle the Loongson
> > > > > GNET devices. Based on the patches introduced further it isn't.
> > > > > Please consider re-arranging the changes (see my comments in the
> > > > > further patches).
> > > > OK.
> > > > 
> > > > 
> > > > Thanks,
> > > > 
> > > > Yanteng
> > > > 
> > > > 
> > > > > -Serge(y)
> > > > > 
> > > > > >    	{}
> > > > > >    };
> > > > > >    MODULE_DEVICE_TABLE(pci, loongson_dwmac_id_table);
> > > > > > -- >> 2.31.4
> > > > > > 
> 

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 09/11] net: stmmac: dwmac-loongson: Fix half duplex
  2024-03-20 10:37               ` Russell King (Oracle)
@ 2024-03-20 12:50                 ` Russell King (Oracle)
  2024-03-20 14:22                   ` Russell King (Oracle)
  2024-03-22 18:07                 ` Serge Semin
  1 sibling, 1 reply; 97+ messages in thread
From: Russell King (Oracle) @ 2024-03-20 12:50 UTC (permalink / raw)
  To: Serge Semin
  Cc: Yanteng Si, andrew, hkallweit1, peppe.cavallaro,
	alexandre.torgue, joabreu, Jose.Abreu, chenhuacai, guyinggang,
	netdev, chris.chenfeiyang

On Wed, Mar 20, 2024 at 10:37:00AM +0000, Russell King (Oracle) wrote:
> I was thinking:
> 
> 	stmmac_mac_phylink_get_caps(priv);
> 
> 	if (priv->plat->mac_capabilities)
> 		priv->phylink_config.mac_capabilities &=
> 			priv->plat->mac_capabilities;
> 
> In other words, if a platform sets plat->mac_capabilities, then it is
> providing the capabilities that it supports, and those need to reduce
> the capabilities provided by the MAC.

To further expand on this given the additional discussion, here's a
patch that amagamates the ideas so far - however, it doesn't
implement everything.

I think an additional step would be to provide a function that does all
the mac capability calculations, something like:

static void stmmac_calculate_mac_capabilities(struct stmmac_priv *priv)
{
	struct phylink_config cfg;

	/* do everything with cfg.mac_capabilities that is currently in
	 * stmmac_phy_setup()
	 */

	/* this must be done with rtnl held if the device is open */
	priv->phylink_config.mac_capabilities = cfg.mac_capabilities;
}

and that needs to be called from both stmmac_reinit_queues() and
stmmac_phy_setup().

diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index a6fefe675ef1..a1e144b99213 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -605,6 +605,7 @@ struct mac_device_info {
 	unsigned int pmt;
 	unsigned int ps;
 	unsigned int xlgmac;
+	u32 phylink_mac_capabilities;
 	unsigned int num_vlan;
 	u32 vlan_filter[32];
 	bool vlan_fail_q_en;
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
index 6b6d0de09619..2e4da6ac5173 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
@@ -68,11 +68,6 @@ static void dwmac4_core_init(struct mac_device_info *hw,
 		init_waitqueue_head(&priv->tstamp_busy_wait);
 }
 
-static void dwmac4_phylink_get_caps(struct stmmac_priv *priv)
-{
-	priv->phylink_config.mac_capabilities |= MAC_2500FD;
-}
-
 static void dwmac4_rx_queue_enable(struct mac_device_info *hw,
 				   u8 mode, u32 queue)
 {
@@ -1165,7 +1160,6 @@ static void dwmac4_set_hw_vlan_mode(struct mac_device_info *hw)
 
 const struct stmmac_ops dwmac4_ops = {
 	.core_init = dwmac4_core_init,
-	.phylink_get_caps = dwmac4_phylink_get_caps,
 	.set_mac = stmmac_set_mac,
 	.rx_ipc = dwmac4_rx_ipc_enable,
 	.rx_queue_enable = dwmac4_rx_queue_enable,
@@ -1210,7 +1204,6 @@ const struct stmmac_ops dwmac4_ops = {
 
 const struct stmmac_ops dwmac410_ops = {
 	.core_init = dwmac4_core_init,
-	.phylink_get_caps = dwmac4_phylink_get_caps,
 	.set_mac = stmmac_dwmac4_set_mac,
 	.rx_ipc = dwmac4_rx_ipc_enable,
 	.rx_queue_enable = dwmac4_rx_queue_enable,
@@ -1259,7 +1252,6 @@ const struct stmmac_ops dwmac410_ops = {
 
 const struct stmmac_ops dwmac510_ops = {
 	.core_init = dwmac4_core_init,
-	.phylink_get_caps = dwmac4_phylink_get_caps,
 	.set_mac = stmmac_dwmac4_set_mac,
 	.rx_ipc = dwmac4_rx_ipc_enable,
 	.rx_queue_enable = dwmac4_rx_queue_enable,
@@ -1372,5 +1364,7 @@ int dwmac4_setup(struct stmmac_priv *priv)
 	mac->mii.clk_csr_mask = GENMASK(11, 8);
 	mac->num_vlan = dwmac4_get_num_vlan(priv->ioaddr);
 
+	mac->phylink_mac_capabilities |= MAC_2500FD;
+
 	return 0;
 }
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
index 1af2f89a0504..f3daa284012b 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
@@ -47,14 +47,6 @@ static void dwxgmac2_core_init(struct mac_device_info *hw,
 	writel(XGMAC_INT_DEFAULT_EN, ioaddr + XGMAC_INT_EN);
 }
 
-static void xgmac_phylink_get_caps(struct stmmac_priv *priv)
-{
-	priv->phylink_config.mac_capabilities |= MAC_2500FD | MAC_5000FD |
-						 MAC_10000FD | MAC_25000FD |
-						 MAC_40000FD | MAC_50000FD |
-						 MAC_100000FD;
-}
-
 static void dwxgmac2_set_mac(void __iomem *ioaddr, bool enable)
 {
 	u32 tx = readl(ioaddr + XGMAC_TX_CONFIG);
@@ -1516,7 +1508,6 @@ static void dwxgmac3_fpe_configure(void __iomem *ioaddr, struct stmmac_fpe_cfg *
 
 const struct stmmac_ops dwxgmac210_ops = {
 	.core_init = dwxgmac2_core_init,
-	.phylink_get_caps = xgmac_phylink_get_caps,
 	.set_mac = dwxgmac2_set_mac,
 	.rx_ipc = dwxgmac2_rx_ipc,
 	.rx_queue_enable = dwxgmac2_rx_queue_enable,
@@ -1577,7 +1568,6 @@ static void dwxlgmac2_rx_queue_enable(struct mac_device_info *hw, u8 mode,
 
 const struct stmmac_ops dwxlgmac2_ops = {
 	.core_init = dwxgmac2_core_init,
-	.phylink_get_caps = xgmac_phylink_get_caps,
 	.set_mac = dwxgmac2_set_mac,
 	.rx_ipc = dwxgmac2_rx_ipc,
 	.rx_queue_enable = dwxlgmac2_rx_queue_enable,
@@ -1656,6 +1646,11 @@ int dwxgmac2_setup(struct stmmac_priv *priv)
 	mac->mii.clk_csr_shift = 19;
 	mac->mii.clk_csr_mask = GENMASK(21, 19);
 
+	mac->phylink_mac_capabilities = MAC_2500FD | MAC_5000FD |
+					MAC_10000FD | MAC_25000FD |
+					MAC_40000FD | MAC_50000FD |
+					MAC_100000FD;
+
 	return 0;
 }
 
@@ -1693,5 +1688,10 @@ int dwxlgmac2_setup(struct stmmac_priv *priv)
 	mac->mii.clk_csr_shift = 19;
 	mac->mii.clk_csr_mask = GENMASK(21, 19);
 
+	mac->phylink_mac_capabilities = MAC_2500FD | MAC_5000FD |
+					MAC_10000FD | MAC_25000FD |
+					MAC_40000FD | MAC_50000FD |
+					MAC_100000FD;
+
 	return 0;
 }
diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h
index 7be04b54738b..7370cd963569 100644
--- a/drivers/net/ethernet/stmicro/stmmac/hwif.h
+++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h
@@ -308,8 +308,6 @@ struct stmmac_est;
 struct stmmac_ops {
 	/* MAC core initialization */
 	void (*core_init)(struct mac_device_info *hw, struct net_device *dev);
-	/* Get phylink capabilities */
-	void (*phylink_get_caps)(struct stmmac_priv *priv);
 	/* Enable the MAC RX/TX */
 	void (*set_mac)(void __iomem *ioaddr, bool enable);
 	/* Enable and verify that the IPC module is supported */
@@ -430,8 +428,6 @@ struct stmmac_ops {
 
 #define stmmac_core_init(__priv, __args...) \
 	stmmac_do_void_callback(__priv, mac, core_init, __args)
-#define stmmac_mac_phylink_get_caps(__priv) \
-	stmmac_do_void_callback(__priv, mac, phylink_get_caps, __priv)
 #define stmmac_mac_set(__priv, __args...) \
 	stmmac_do_void_callback(__priv, mac, set_mac, __args)
 #define stmmac_rx_ipc(__priv, __args...) \
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 24cd80490d19..5e8cffc49f1f 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -1240,15 +1240,25 @@ static int stmmac_phy_setup(struct stmmac_priv *priv)
 						MAC_10FD | MAC_100FD |
 						MAC_1000FD;
 
-	stmmac_set_half_duplex(priv);
+	/* Merge in the MAC capabilities */
+	priv->phylink_config.mac_capabilities |=
+					priv->hw->phylink_mac_capabilities;
 
-	/* Get the MAC specific capabilities */
-	stmmac_mac_phylink_get_caps(priv);
+	stmmac_set_half_duplex(priv);
 
 	max_speed = priv->plat->max_speed;
 	if (max_speed)
 		phylink_limit_mac_speed(&priv->phylink_config, max_speed);
 
+	/* If the platform supplies MAC capabilities, calculate the union
+	 * of the MAC and platform capabilities to give the whole-system
+	 * capabilities. This intetionally can not add additional capabilities
+	 * so if this is populated, it must list everything that is supported.
+	 */
+	if (priv->plat->phylink_mac_capabilities)
+		priv->phylink_config.mac_capabilities &=
+					priv->plat->phylink_mac_capabilities;
+
 	fwnode = priv->plat->port_node;
 	if (!fwnode)
 		fwnode = dev_fwnode(priv->device);
diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
index dfa1828cd756..fe3f64df17ac 100644
--- a/include/linux/stmmac.h
+++ b/include/linux/stmmac.h
@@ -272,6 +272,7 @@ struct plat_stmmacenet_data {
 	u8 tx_sched_algorithm;
 	struct stmmac_rxq_cfg rx_queues_cfg[MTL_MAX_RX_QUEUES];
 	struct stmmac_txq_cfg tx_queues_cfg[MTL_MAX_TX_QUEUES];
+	u32 phylink_mac_capabilities;
 	void (*fix_mac_speed)(void *priv, unsigned int speed, unsigned int mode);
 	int (*fix_soc_reset)(void *priv, void __iomem *ioaddr);
 	int (*serdes_powerup)(struct net_device *ndev, void *priv);

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!

^ permalink raw reply related	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 09/11] net: stmmac: dwmac-loongson: Fix half duplex
  2024-03-20 12:50                 ` Russell King (Oracle)
@ 2024-03-20 14:22                   ` Russell King (Oracle)
  0 siblings, 0 replies; 97+ messages in thread
From: Russell King (Oracle) @ 2024-03-20 14:22 UTC (permalink / raw)
  To: Serge Semin
  Cc: Yanteng Si, andrew, hkallweit1, peppe.cavallaro,
	alexandre.torgue, joabreu, Jose.Abreu, chenhuacai, guyinggang,
	netdev, chris.chenfeiyang

On Wed, Mar 20, 2024 at 12:50:28PM +0000, Russell King (Oracle) wrote:
> On Wed, Mar 20, 2024 at 10:37:00AM +0000, Russell King (Oracle) wrote:
> > I was thinking:
> > 
> > 	stmmac_mac_phylink_get_caps(priv);
> > 
> > 	if (priv->plat->mac_capabilities)
> > 		priv->phylink_config.mac_capabilities &=
> > 			priv->plat->mac_capabilities;
> > 
> > In other words, if a platform sets plat->mac_capabilities, then it is
> > providing the capabilities that it supports, and those need to reduce
> > the capabilities provided by the MAC.
> 
> To further expand on this given the additional discussion, here's a
> patch that amagamates the ideas so far - however, it doesn't
> implement everything.
> 
> I think an additional step would be to provide a function that does all
> the mac capability calculations, something like:

Here's the complete patch:

diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index a6fefe675ef1..a1e144b99213 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -605,6 +605,7 @@ struct mac_device_info {
 	unsigned int pmt;
 	unsigned int ps;
 	unsigned int xlgmac;
+	u32 phylink_mac_capabilities;
 	unsigned int num_vlan;
 	u32 vlan_filter[32];
 	bool vlan_fail_q_en;
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
index 6b6d0de09619..2e4da6ac5173 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
@@ -68,11 +68,6 @@ static void dwmac4_core_init(struct mac_device_info *hw,
 		init_waitqueue_head(&priv->tstamp_busy_wait);
 }
 
-static void dwmac4_phylink_get_caps(struct stmmac_priv *priv)
-{
-	priv->phylink_config.mac_capabilities |= MAC_2500FD;
-}
-
 static void dwmac4_rx_queue_enable(struct mac_device_info *hw,
 				   u8 mode, u32 queue)
 {
@@ -1165,7 +1160,6 @@ static void dwmac4_set_hw_vlan_mode(struct mac_device_info *hw)
 
 const struct stmmac_ops dwmac4_ops = {
 	.core_init = dwmac4_core_init,
-	.phylink_get_caps = dwmac4_phylink_get_caps,
 	.set_mac = stmmac_set_mac,
 	.rx_ipc = dwmac4_rx_ipc_enable,
 	.rx_queue_enable = dwmac4_rx_queue_enable,
@@ -1210,7 +1204,6 @@ const struct stmmac_ops dwmac4_ops = {
 
 const struct stmmac_ops dwmac410_ops = {
 	.core_init = dwmac4_core_init,
-	.phylink_get_caps = dwmac4_phylink_get_caps,
 	.set_mac = stmmac_dwmac4_set_mac,
 	.rx_ipc = dwmac4_rx_ipc_enable,
 	.rx_queue_enable = dwmac4_rx_queue_enable,
@@ -1259,7 +1252,6 @@ const struct stmmac_ops dwmac410_ops = {
 
 const struct stmmac_ops dwmac510_ops = {
 	.core_init = dwmac4_core_init,
-	.phylink_get_caps = dwmac4_phylink_get_caps,
 	.set_mac = stmmac_dwmac4_set_mac,
 	.rx_ipc = dwmac4_rx_ipc_enable,
 	.rx_queue_enable = dwmac4_rx_queue_enable,
@@ -1372,5 +1364,7 @@ int dwmac4_setup(struct stmmac_priv *priv)
 	mac->mii.clk_csr_mask = GENMASK(11, 8);
 	mac->num_vlan = dwmac4_get_num_vlan(priv->ioaddr);
 
+	mac->phylink_mac_capabilities |= MAC_2500FD;
+
 	return 0;
 }
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
index 1af2f89a0504..f3daa284012b 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
@@ -47,14 +47,6 @@ static void dwxgmac2_core_init(struct mac_device_info *hw,
 	writel(XGMAC_INT_DEFAULT_EN, ioaddr + XGMAC_INT_EN);
 }
 
-static void xgmac_phylink_get_caps(struct stmmac_priv *priv)
-{
-	priv->phylink_config.mac_capabilities |= MAC_2500FD | MAC_5000FD |
-						 MAC_10000FD | MAC_25000FD |
-						 MAC_40000FD | MAC_50000FD |
-						 MAC_100000FD;
-}
-
 static void dwxgmac2_set_mac(void __iomem *ioaddr, bool enable)
 {
 	u32 tx = readl(ioaddr + XGMAC_TX_CONFIG);
@@ -1516,7 +1508,6 @@ static void dwxgmac3_fpe_configure(void __iomem *ioaddr, struct stmmac_fpe_cfg *
 
 const struct stmmac_ops dwxgmac210_ops = {
 	.core_init = dwxgmac2_core_init,
-	.phylink_get_caps = xgmac_phylink_get_caps,
 	.set_mac = dwxgmac2_set_mac,
 	.rx_ipc = dwxgmac2_rx_ipc,
 	.rx_queue_enable = dwxgmac2_rx_queue_enable,
@@ -1577,7 +1568,6 @@ static void dwxlgmac2_rx_queue_enable(struct mac_device_info *hw, u8 mode,
 
 const struct stmmac_ops dwxlgmac2_ops = {
 	.core_init = dwxgmac2_core_init,
-	.phylink_get_caps = xgmac_phylink_get_caps,
 	.set_mac = dwxgmac2_set_mac,
 	.rx_ipc = dwxgmac2_rx_ipc,
 	.rx_queue_enable = dwxlgmac2_rx_queue_enable,
@@ -1656,6 +1646,11 @@ int dwxgmac2_setup(struct stmmac_priv *priv)
 	mac->mii.clk_csr_shift = 19;
 	mac->mii.clk_csr_mask = GENMASK(21, 19);
 
+	mac->phylink_mac_capabilities = MAC_2500FD | MAC_5000FD |
+					MAC_10000FD | MAC_25000FD |
+					MAC_40000FD | MAC_50000FD |
+					MAC_100000FD;
+
 	return 0;
 }
 
@@ -1693,5 +1688,10 @@ int dwxlgmac2_setup(struct stmmac_priv *priv)
 	mac->mii.clk_csr_shift = 19;
 	mac->mii.clk_csr_mask = GENMASK(21, 19);
 
+	mac->phylink_mac_capabilities = MAC_2500FD | MAC_5000FD |
+					MAC_10000FD | MAC_25000FD |
+					MAC_40000FD | MAC_50000FD |
+					MAC_100000FD;
+
 	return 0;
 }
diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h
index 7be04b54738b..7370cd963569 100644
--- a/drivers/net/ethernet/stmicro/stmmac/hwif.h
+++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h
@@ -308,8 +308,6 @@ struct stmmac_est;
 struct stmmac_ops {
 	/* MAC core initialization */
 	void (*core_init)(struct mac_device_info *hw, struct net_device *dev);
-	/* Get phylink capabilities */
-	void (*phylink_get_caps)(struct stmmac_priv *priv);
 	/* Enable the MAC RX/TX */
 	void (*set_mac)(void __iomem *ioaddr, bool enable);
 	/* Enable and verify that the IPC module is supported */
@@ -430,8 +428,6 @@ struct stmmac_ops {
 
 #define stmmac_core_init(__priv, __args...) \
 	stmmac_do_void_callback(__priv, mac, core_init, __args)
-#define stmmac_mac_phylink_get_caps(__priv) \
-	stmmac_do_void_callback(__priv, mac, phylink_get_caps, __priv)
 #define stmmac_mac_set(__priv, __args...) \
 	stmmac_do_void_callback(__priv, mac, set_mac, __args)
 #define stmmac_rx_ipc(__priv, __args...) \
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 24cd80490d19..278532290f0c 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -1198,15 +1198,33 @@ static int stmmac_init_phy(struct net_device *dev)
 	return ret;
 }
 
-static void stmmac_set_half_duplex(struct stmmac_priv *priv)
+static void stmmac_set_mac_capabilties(struct stmmac_priv *priv)
 {
+	struct phylink_config cfg;
+
+	cfg.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
+			       MAC_10FD | MAC_100FD | MAC_1000FD |
+			       priv->hw->phylink_mac_capabilities;
+
 	/* Half-Duplex can only work with single tx queue */
 	if (priv->plat->tx_queues_to_use > 1)
-		priv->phylink_config.mac_capabilities &=
-			~(MAC_10HD | MAC_100HD | MAC_1000HD);
+		cfg.mac_capabilities &= ~(MAC_10HD | MAC_100HD | MAC_1000HD);
 	else
-		priv->phylink_config.mac_capabilities |=
-			(MAC_10HD | MAC_100HD | MAC_1000HD);
+		cfg.mac_capabilities |= MAC_10HD | MAC_100HD | MAC_1000HD;
+
+	max_speed = priv->plat->max_speed;
+	if (max_speed)
+		phylink_limit_mac_speed(&cfg, max_speed);
+
+	/* If the platform supplies MAC capabilities, calculate the union
+	 * of the MAC and platform capabilities to give the whole-system
+	 * capabilities. This intetionally can not add additional capabilities
+	 * so if this is populated, it must list everything that is supported.
+	 */
+	if (priv->plat->phylink_mac_capabilities)
+		cfg.mac_capabilities &= priv->plat->phylink_mac_capabilities;
+
+	priv->phylink_config.mac_capabilities = cfg.mac_capabilities;
 }
 
 static int stmmac_phy_setup(struct stmmac_priv *priv)
@@ -1236,18 +1254,7 @@ static int stmmac_phy_setup(struct stmmac_priv *priv)
 		xpcs_get_interfaces(priv->hw->xpcs,
 				    priv->phylink_config.supported_interfaces);
 
-	priv->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
-						MAC_10FD | MAC_100FD |
-						MAC_1000FD;
-
-	stmmac_set_half_duplex(priv);
-
-	/* Get the MAC specific capabilities */
-	stmmac_mac_phylink_get_caps(priv);
-
-	max_speed = priv->plat->max_speed;
-	if (max_speed)
-		phylink_limit_mac_speed(&priv->phylink_config, max_speed);
+	stmmac_set_mac_capabilties(priv);
 
 	fwnode = priv->plat->port_node;
 	if (!fwnode)
@@ -7355,7 +7362,7 @@ int stmmac_reinit_queues(struct net_device *dev, u32 rx_cnt, u32 tx_cnt)
 			priv->rss.table[i] = ethtool_rxfh_indir_default(i,
 									rx_cnt);
 
-	stmmac_set_half_duplex(priv);
+	stmmac_set_mac_capabilties(priv);
 	stmmac_napi_add(dev);
 
 	if (netif_running(dev))
diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
index dfa1828cd756..fe3f64df17ac 100644
--- a/include/linux/stmmac.h
+++ b/include/linux/stmmac.h
@@ -272,6 +272,7 @@ struct plat_stmmacenet_data {
 	u8 tx_sched_algorithm;
 	struct stmmac_rxq_cfg rx_queues_cfg[MTL_MAX_RX_QUEUES];
 	struct stmmac_txq_cfg tx_queues_cfg[MTL_MAX_TX_QUEUES];
+	u32 phylink_mac_capabilities;
 	void (*fix_mac_speed)(void *priv, unsigned int speed, unsigned int mode);
 	int (*fix_soc_reset)(void *priv, void __iomem *ioaddr);
 	int (*serdes_powerup)(struct net_device *ndev, void *priv);
-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!

^ permalink raw reply related	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 06/11] net: stmmac: dwmac-loongson: Add GNET support
  2024-03-19 15:03         ` Serge Semin
  2024-03-20 10:23           ` Yanteng Si
@ 2024-03-21  9:13           ` Yanteng Si
  2024-03-21 14:55             ` Andrew Lunn
  2024-03-22 19:09             ` Serge Semin
  1 sibling, 2 replies; 97+ messages in thread
From: Yanteng Si @ 2024-03-21  9:13 UTC (permalink / raw)
  To: Serge Semin
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang


在 2024/3/19 23:03, Serge Semin 写道:
>>>>>   >> +static int loongson_gnet_data(struct pci_dev *pdev,
>>>>> +			      struct plat_stmmacenet_data *plat)
>>>>> +{
>>>>> +	loongson_default_data(pdev, plat);
>>>>> +
>>>>> +	plat->multicast_filter_bins = 256;
>>>>> +
>>>>> +	plat->mdio_bus_data->phy_mask =  ~(u32)BIT(2);
>>>>> +
>>>>> +	plat->phy_addr = 2;
>>>>> +	plat->phy_interface = PHY_INTERFACE_MODE_INTERNAL;
>>>> Are you sure PHY-interface is supposed to be defined as "internal"?
>>> Yes, because the gnet hardware has a integrated PHY, so we set it to internal,
>>>
> Why do you need the phy_addr set to 2 then? Is PHY still discoverable
> on the subordinate MDIO-bus?

Because the default return value of gnet's mdio is 0xffff, when scanning 
for phy,

if the return value is not 0, it will be assumed that the phy for that 
address exists.

  Not specifying an address will cause all addresses' phy to be 
detected, and the

lowest address' phy will be selected by default. so then, the network is 
unavailable.

>
> kdoc in "include/linux/phy.h" defines the PHY_INTERFACE_MODE_INTERNAL
> mode as for a case of the MAC and PHY being combined. IIUC it's
> reserved for a case when you can't determine actual interface between
> the MAC and PHY. Is it your case? Are you sure the interface between
> MAC and PHY isn't something like GMII/RGMII/etc?
Hmmm. the interface between MAC and PHY is GMII, so let's use

PHY_INTERFACE_MODE_GMII?


Thanks,

Yanteng


^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 08/11] net: stmmac: dwmac-loongson: Fix MAC speed for GNET
  2024-03-19 17:02         ` Serge Semin
  2024-03-20 10:42           ` Yanteng Si
@ 2024-03-21  9:29           ` Yanteng Si
  2024-03-21 15:02             ` Andrew Lunn
  1 sibling, 1 reply; 97+ messages in thread
From: Yanteng Si @ 2024-03-21  9:29 UTC (permalink / raw)
  To: Serge Semin
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang


在 2024/3/20 01:02, Serge Semin 写道:
>>> Due to a bug in the chip's internal PHY, the network is still not working after
>>> the first self-negotiation, and it needs to be self-negotiated again.
> Then please describe the bug in more details then.
>
> Getting back to the code you implemented here. In the in-situ comment
> you say: "We need to use the PS bit to check if the controller's
> status is correct and reset PHY if necessary." By calling
> phy_restart_aneg() you don't reset the PHY.
>
> Moreover if "PS" flag is set, then the MAC has been pre-configured to
> work in the 10/100Mbps mode. Since 1000Mbps speed is requested, the
> MAC_CTRL_REG.PS flag will be cleared later in the
> stmmac_mac_link_up() method and then phylink_start() shall cause the
> link speed re-auto-negotiation. Why do you need the auto-negotiation
> started for the default MAC config which will be changed just in a
> moment later? All of that seems weird.

When switching speeds (from 100M to 1000M), the phy cannot output clocks,

resulting in the unavailability of the network card.  At this time, a 
reset of the

phy is required.


BTW, This bug has been fixed in gnet of 2k2000 (0x10, 7a13).

>
> Most importantly I have doubts the networking subsystem maintainers
> will permit you calling the phy_restart_aneg() method from the MAC
> driver code.

We are happy to accept the opinions of the community.


Thanks,

Yanteng

>


^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 06/11] net: stmmac: dwmac-loongson: Add GNET support
  2024-03-21  9:13           ` Yanteng Si
@ 2024-03-21 14:55             ` Andrew Lunn
  2024-03-28 11:41               ` Yanteng Si
  2024-03-22 19:09             ` Serge Semin
  1 sibling, 1 reply; 97+ messages in thread
From: Andrew Lunn @ 2024-03-21 14:55 UTC (permalink / raw)
  To: Yanteng Si
  Cc: Serge Semin, hkallweit1, peppe.cavallaro, alexandre.torgue,
	joabreu, Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

> Because the default return value of gnet's mdio is 0xffff, when scanning for
> phy,
> 
> if the return value is not 0, it will be assumed that the phy for that
> address exists.

That is not correct. The MDIO bus has a pull up on the data line. If
there is no device at a given address, that pull up results in 0xffff
being read. phylib understands this, it knows that a read with the
value of 0xffff probably means there is no device at that address. So
it will not create a device.

>  Not specifying an address will cause all addresses' phy to be detected, and
> the
> 
> lowest address' phy will be selected by default. so then, the network is
> unavailable.

Do you have multiple PHYs on the bus? If there is only one PHY the
first PHY should be the PHY you want, and phy_find_first() will do
what you need. However, if there are multiple PHYs on the bus, you
really should use a phandle in DT to point to the correct PHY.

       Andrew

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 08/11] net: stmmac: dwmac-loongson: Fix MAC speed for GNET
  2024-03-21  9:29           ` Yanteng Si
@ 2024-03-21 15:02             ` Andrew Lunn
  2024-03-21 15:19               ` Russell King (Oracle)
  2024-03-26 12:02               ` Yanteng Si
  0 siblings, 2 replies; 97+ messages in thread
From: Andrew Lunn @ 2024-03-21 15:02 UTC (permalink / raw)
  To: Yanteng Si
  Cc: Serge Semin, hkallweit1, peppe.cavallaro, alexandre.torgue,
	joabreu, Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

On Thu, Mar 21, 2024 at 05:29:55PM +0800, Yanteng Si wrote:
> 
> 在 2024/3/20 01:02, Serge Semin 写道:
> > > > Due to a bug in the chip's internal PHY, the network is still not working after
> > > > the first self-negotiation, and it needs to be self-negotiated again.
> > Then please describe the bug in more details then.
> > 
> > Getting back to the code you implemented here. In the in-situ comment
> > you say: "We need to use the PS bit to check if the controller's
> > status is correct and reset PHY if necessary." By calling
> > phy_restart_aneg() you don't reset the PHY.
> > 
> > Moreover if "PS" flag is set, then the MAC has been pre-configured to
> > work in the 10/100Mbps mode. Since 1000Mbps speed is requested, the
> > MAC_CTRL_REG.PS flag will be cleared later in the
> > stmmac_mac_link_up() method and then phylink_start() shall cause the
> > link speed re-auto-negotiation. Why do you need the auto-negotiation
> > started for the default MAC config which will be changed just in a
> > moment later? All of that seems weird.
> 
> When switching speeds (from 100M to 1000M), the phy cannot output clocks,
> 
> resulting in the unavailability of the network card.  At this time, a reset
> of the
> 
> phy is required.

reset, or restart of autoneg?

> BTW, This bug has been fixed in gnet of 2k2000 (0x10, 7a13).
> 
> > 
> > Most importantly I have doubts the networking subsystem maintainers
> > will permit you calling the phy_restart_aneg() method from the MAC
> > driver code.

That is O.K. It should have a comment explaining that it is working
around a hardware bug. And you need to take care of locking. But a MAC
driver can call this, e.g. if it implements ethtool nway_reset, it
needs to do exactly this. See phy_ethtool_nway_reset().

      Andrew

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 08/11] net: stmmac: dwmac-loongson: Fix MAC speed for GNET
  2024-03-21 15:02             ` Andrew Lunn
@ 2024-03-21 15:19               ` Russell King (Oracle)
  2024-03-21 15:38                 ` Andrew Lunn
  2024-03-26 12:02               ` Yanteng Si
  1 sibling, 1 reply; 97+ messages in thread
From: Russell King (Oracle) @ 2024-03-21 15:19 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Yanteng Si, Serge Semin, hkallweit1, peppe.cavallaro,
	alexandre.torgue, joabreu, Jose.Abreu, chenhuacai, guyinggang,
	netdev, chris.chenfeiyang

On Thu, Mar 21, 2024 at 04:02:54PM +0100, Andrew Lunn wrote:
> On Thu, Mar 21, 2024 at 05:29:55PM +0800, Yanteng Si wrote:
> > 
> > 在 2024/3/20 01:02, Serge Semin 写道:
> > > > > Due to a bug in the chip's internal PHY, the network is still not working after
> > > > > the first self-negotiation, and it needs to be self-negotiated again.
> > > Then please describe the bug in more details then.
> > > 
> > > Getting back to the code you implemented here. In the in-situ comment
> > > you say: "We need to use the PS bit to check if the controller's
> > > status is correct and reset PHY if necessary." By calling
> > > phy_restart_aneg() you don't reset the PHY.
> > > 
> > > Moreover if "PS" flag is set, then the MAC has been pre-configured to
> > > work in the 10/100Mbps mode. Since 1000Mbps speed is requested, the
> > > MAC_CTRL_REG.PS flag will be cleared later in the
> > > stmmac_mac_link_up() method and then phylink_start() shall cause the
> > > link speed re-auto-negotiation. Why do you need the auto-negotiation
> > > started for the default MAC config which will be changed just in a
> > > moment later? All of that seems weird.
> > 
> > When switching speeds (from 100M to 1000M), the phy cannot output clocks,
> > 
> > resulting in the unavailability of the network card.  At this time, a reset
> > of the
> > 
> > phy is required.
> 
> reset, or restart of autoneg?
> 
> > BTW, This bug has been fixed in gnet of 2k2000 (0x10, 7a13).
> > 
> > > 
> > > Most importantly I have doubts the networking subsystem maintainers
> > > will permit you calling the phy_restart_aneg() method from the MAC
> > > driver code.
> 
> That is O.K. It should have a comment explaining that it is working
> around a hardware bug. And you need to take care of locking. But a MAC
> driver can call this, e.g. if it implements ethtool nway_reset, it
> needs to do exactly this. See phy_ethtool_nway_reset().

However, because stmmac uses phylink, we should be adding phylink
interfaces that forward to phylib to avoid the layering violation.

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 08/11] net: stmmac: dwmac-loongson: Fix MAC speed for GNET
  2024-03-21 15:19               ` Russell King (Oracle)
@ 2024-03-21 15:38                 ` Andrew Lunn
  2024-03-26 12:32                   ` Yanteng Si
  0 siblings, 1 reply; 97+ messages in thread
From: Andrew Lunn @ 2024-03-21 15:38 UTC (permalink / raw)
  To: Russell King (Oracle)
  Cc: Yanteng Si, Serge Semin, hkallweit1, peppe.cavallaro,
	alexandre.torgue, joabreu, Jose.Abreu, chenhuacai, guyinggang,
	netdev, chris.chenfeiyang

> However, because stmmac uses phylink, we should be adding phylink
> interfaces that forward to phylib to avoid the layering violation.

Yes.

Maybe just call phylink_ethtool_nway_reset()?  Just depends if the
additional phylink_pcs_an_restart(pl) will mess things up for this
device.

      Andrew

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 07/11] net: stmmac: dwmac-loongson: Add multi-channel supports for loongson
  2024-03-19 15:53         ` Serge Semin
@ 2024-03-22 10:36           ` Yanteng Si
  2024-03-22 18:47             ` Serge Semin
  2024-04-03  8:23           ` Yanteng Si
  1 sibling, 1 reply; 97+ messages in thread
From: Yanteng Si @ 2024-03-22 10:36 UTC (permalink / raw)
  To: Serge Semin
  Cc: hkallweit1, andrew, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

>>>>> +{
>>>>> +	int i, ret, vecs;
>>>>> +
>>>>> +	vecs = roundup_pow_of_two(channel_num * 2 + 1);
>>>>> +	ret = pci_alloc_irq_vectors(pdev, vecs, vecs, PCI_IRQ_MSI);
>>>>> +	if (ret < 0) {
>>>>> +		dev_info(&pdev->dev,
>>>>> +			 "MSI enable failed, Fallback to legacy interrupt\n");
>>>>> +		return loongson_dwmac_config_legacy(pdev, plat, res, np);
>>>> In what conditions is this possible? Will the
>>>> loongson_dwmac_config_legacy() method work in that case? Did you test
>>>> it out?
I need to wait for special hardware and PMON for this.  Please give me 
some time.

> Then those platforms will _require_ to have the DT-node specified. This
> will define the DT-bindings which I doubt you imply here. Am I wrong?
>
> Once again have you tested the loongson_dwmac_config_legacy() method
> working in the case of the pci_alloc_irq_vectors() failure?

Yes!  I have tested it, it works in single channel mode.

dmesg:

[    3.935203] mdio_bus stmmac-18:02: attached PHY driver [unbound]
(mii_bus:phy_addr=stmmac-18:02, irq=POLL)
[    3.945625] dwmac-loongson-pci 0000:00:03.1: MSI enable failed, Fallback to
legacy interrupt
[    3.954175] dwmac-loongson-pci 0000:00:03.1: User ID: 0xd1, Synopsys ID: 0x10
[    3.973676] dwmac-loongson-pci 0000:00:03.1: DMA HW capability register supported
[    3.981135] dwmac-loongson-pci 0000:00:03.1: RX Checksum Offload Engine supported

cat /proc/interrupt:

43:          0          0   PCH PIC  16  ahci[0000:00:08.0]
   44:          0          0   PCH PIC  12  enp0s3f0
   45:          0          0   PCH PIC  14  enp0s3f1
   46:      16233          0   PCH PIC  17  enp0s3f2
   47:      12698          0   PCH PIC  48  xhci-hcd:usb1


the irq number 46 is the falkback legacy irq.

> 	
>
>>>>> +	}
>>>>> +
>>>>> +	plat->rx_queues_to_use = channel_num;
>>>>> +	plat->tx_queues_to_use = channel_num;
>>>> This is supposed to be initialized in the setup() methods. Please move
>>>> it to the dedicated patch.
>>> No, referring to my previous reply, only the 0x10 gnet device has 8 channels,
>>> and the 0x37 device has a single channel.
> Yes. You have a perfectly suitable method for it. It's
> loongson_gnet_data(). Init the number of channels there based on the
> value read from the GMAC_VERSION.SNPSVER field. Thus the
> loongson_gnet_config_multi_msi() will get to be more coherent setting
> up the MSI IRQs only.
You are right!  it works well.


Thanks,

Yanteng



^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 09/11] net: stmmac: dwmac-loongson: Fix half duplex
  2024-03-20 10:37               ` Russell King (Oracle)
  2024-03-20 12:50                 ` Russell King (Oracle)
@ 2024-03-22 18:07                 ` Serge Semin
  2024-03-22 19:56                   ` Russell King (Oracle)
  1 sibling, 1 reply; 97+ messages in thread
From: Serge Semin @ 2024-03-22 18:07 UTC (permalink / raw)
  To: Russell King (Oracle)
  Cc: Yanteng Si, andrew, hkallweit1, peppe.cavallaro,
	alexandre.torgue, joabreu, Jose.Abreu, chenhuacai, guyinggang,
	netdev, chris.chenfeiyang

On Wed, Mar 20, 2024 at 10:37:00AM +0000, Russell King (Oracle) wrote:
> Serge,
> 
> Again, please learn to trim your replies.

Ok, got it.

> 
> On Wed, Mar 20, 2024 at 01:10:04PM +0300, Serge Semin wrote:
> ...
> > 
> > In general you are right for sure - it's better to avoid one part
> > setting capabilities and another part unsetting them at least from the
> > readability and maintainability point of view. But in this case we've
> > already got implemented a ready-to-use internal interface
> > stmmac_ops::phylink_get_caps() which can be used to extend/reduce the
> > capabilities field based on the particular MAC abilities. Moreover
> > it's called right from the component setting the capabilities. Are you
> > saying that the callback is supposed to be utilized for extending the
> > capabilities only?
> 
> What concerns me is that the proposed code _overwrites_ the
> capabilities from the MAC layer, so from a maintanability point of
> view it's a nightmare, because you will now have the situation where
> MACs provide their capabilities, and then platform code may overwrite
> it - which means it's like a spiders web trying to work out what
> capabilities are provided.
> 
> The reality is surely that the MAC dictates what it can do, but there
> may be further restrictions by other components in the platform, so
> the capabilities provided to phylink should be:
> 
> 	mac_capabilities & platform_capabilities
> 
> And what I'm proposing is that _that_ should be done in a way that
> makes it _easy_ for the platform code to get right. Overriding
> stmmac_ops::phylink_get_caps() doesn't do that - as can be seen in
> the proposed patch.
> 
> Help your users write correct code by adopting a structure that makes
> it easy for them to do the right thing.

Got it. Thanks for the detailed explanation. So you prefer not to
provide too much freedom in the interface to refrain the users from
unwillingly doing something wrong. Sounds very reasonable.

> 
> > If you insist on not overriding the stmmac_ops::phylink_get_caps()
> > anyway then please explain what is the principal difference
> > between the next two code snippets:
> > 	/* Get the MAC specific capabilities */
> >         stmmac_mac_phylink_get_caps(priv);
> > and
> > 	priv->phylink_config.mac_capabilities &= ~priv->plat->mac_caps_mask;
> 
> 
> I was thinking:
> 
> 	stmmac_mac_phylink_get_caps(priv);
> 
> 	if (priv->plat->mac_capabilities)
> 		priv->phylink_config.mac_capabilities &=
> 			priv->plat->mac_capabilities;
> 
> In other words, if a platform sets plat->mac_capabilities, then it is
> providing the capabilities that it supports, and those need to reduce
> the capabilities provided by the MAC.
> 
> This will _also_ allow stmmac_set_half_duplex() to do the right thing.
> Consider something in the platform side that doesn't allow half-duplex,
> but allows tx_queues_to_use == 1. That'll set the half-duplex modes
> when stmmac_set_half_duplex() is called, overriding what the platform
> supports.
> 
> Now that I look at the stmmac implementation, there's even more that
> is wrong. Consider plat->max_speed = 100, like
> arch/arc/boot/dts/axs10x_mb.dtsi sets. If stmmac_set_half_duplex()
> is called as it can be from stmmac_reinit_queues(), it'll enable
> 1000 half-duplex, despite the plat->max_speed = 100.

Right. Plus to that I found three more issues in the MAC-capabilities
detection code:
1. There is DW MAC100 (see dwmac100_core.c, dwmac100_dma.c), which
doesn't seem like supporting 1G speed, but stmmac_phy_setup() and
stmmac_set_half_duplex() enable the MAC_1000* capabilities anyway.
2. DW XGMAC doesn't support 10/100Mbps speed and half-duplex, but the
stmmac_phy_setup() and stmmac_set_half_duplex() methods set them up
anyway.
3. It seems that the Tx-queues-based constraint of the
half-duplex-ness is only specific for DW QoS Eth (DW GMAC v4/v5).
The databook explicitly says about that:
"In multi queue/channel configurations, enable only Q0/CH0 on Tx and
Rx for half-duplex operation. If you want to enable single
queue/channel in full-duplex operation, any queue/channel can be
enabled."
There is no such note in the DW GMAC v3.x databook.

At least first two problems look as bugs. The last note will be
interesting for Yanteng who has the multi-channel DW GMAC _v3_ device
with the half-duplex mode working for all channels. Therefore the
statement
        if (priv->plat->tx_queues_to_use > 1)
                priv->phylink_config.mac_capabilities &=
                        ~(MAC_10HD | MAC_100HD | MAC_1000HD);
        else
                priv->phylink_config.mac_capabilities |=
                        (MAC_10HD | MAC_100HD | MAC_1000HD);
won't be acceptable for his device.

> 
> > in the MAC-capabilities update implementation? Do you think the later
> > approach would be more descriptive? If so then would the
> > callback-based approach almost equally descriptive if the callback
> > name was, suppose, stmmac_mac_phylink_set_caps() or similar?
> 

> From what I can see of the existing stmmac MAC phylink_get_caps
> implementations, there seem to be two - xgmac_phylink_get_caps()
> and dwmac4_phylink_get_caps(). Both of these merely set additional
> modes in priv->phylink_config.mac_capabilities. Is there a reason
> to have this as an instruction stream, rather than providing data
> to the core stmmac code from the MAC about its capabilities? Is
> there a reason why it would be necessary for the code in a MAC backend
> to make a decision about what capabilities to enable based on some
> condition?

Seeing the Tx-queues-based constraint is DW QoS Eth-specific there is
such reason. It might be better to move the selective Half-duplex
mode disabling to the MAC-specific callback.

But based on what you already demonstrated in the following up email
messages there is a better option to implement the MAC capabilities
detection procedure. Let's see what MAC-capabilities can be currently
specified based on the DW MAC IP-core versions:

DW MAC100: MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
	   MAC_10 | MAC_100

DW GMAC: MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
         MAC_10 | MAC_100 | MAC_1000

DW QoS Eth: MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
            MAC_10 | MAC_100 | MAC_1000 | MAC_2500FD
but if the amount of the active Tx queues is > 1, then:
	   MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
           MAC_10FD | MAC_100FD | MAC_1000FD | MAC_2500FD 

DW XGMAC: MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
          MAC_1000FD | MAC_2500FD | MAC_5000FD |
          MAC_10000FD | MAC_25000FD |
          MAC_40000FD | MAC_50000FD |
          MAC_100000FD

As you can see there are only two common capabilities:
MAC_ASYM_PAUSE | MAC_SYM_PAUSE. Seeing the flow-control is implemented
as a callback for each MAC IP-core (see dwmac100_flow_ctrl(),
dwmac1000_flow_ctrl(), sun8i_dwmac_flow_ctrl(), etc) we can freely
move all the PHYLINK MAC capabilities initializations to the
MAC-specific setup methods (similarly to what you already did in your
patch but specifying the full MAC capabilities list).

After that the only IP-core which requires the capabilities update will
be DW QoS Eth. So the Tx-queue-based capabilities update can be moved
there and the rest of the xgmac_phylink_get_caps() callback can be
dropped.

We can go further. Instead of calling the
stmmac_set_half_duplex()/stmmac_set_mac_capabilties() methods on the
device init and queues reinit stages, we can move their bodies into
the phylink:mac_get_caps() callback.

Here is what the described changes will look like:

diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index 721c1f8e892f..2339af32ac77 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -525,6 +525,7 @@ extern const struct stmmac_hwtimestamp stmmac_ptp;
 extern const struct stmmac_mode_ops dwmac4_ring_mode_ops;
 
 struct mac_link {
+	u32 caps;
 	u32 speed_mask;
 	u32 speed10;
 	u32 speed100;
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
index 137741b94122..6bc18d4c4da9 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
@@ -1097,6 +1097,8 @@ static struct mac_device_info *sun8i_dwmac_setup(void *ppriv)
 
 	priv->dev->priv_flags |= IFF_UNICAST_FLT;
 
+	mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
+			 MAC_10 | MAC_100 | MAC_1000;
 	/* The loopback bit seems to be re-set when link change
 	 * Simply mask it each time
 	 * Speed 10/100/1000 are set in BIT(2)/BIT(3)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
index 3927609abc44..8555299443f4 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
@@ -539,6 +539,8 @@ int dwmac1000_setup(struct stmmac_priv *priv)
 	if (mac->multicast_filter_bins)
 		mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins);
 
+	mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
+			 MAC_10 | MAC_100 | MAC_1000;
 	mac->link.duplex = GMAC_CONTROL_DM;
 	mac->link.speed10 = GMAC_CONTROL_PS;
 	mac->link.speed100 = GMAC_CONTROL_PS | GMAC_CONTROL_FES;
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
index a6e8d7bd9588..7667d103cd0e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
@@ -175,6 +175,8 @@ int dwmac100_setup(struct stmmac_priv *priv)
 	dev_info(priv->device, "\tDWMAC100\n");
 
 	mac->pcsr = priv->ioaddr;
+	mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
+			 MAC_10 | MAC_100;
 	mac->link.duplex = MAC_CONTROL_F;
 	mac->link.speed10 = 0;
 	mac->link.speed100 = 0;
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
index 6b6d0de09619..c51dc946e8ef 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
@@ -70,7 +70,11 @@ static void dwmac4_core_init(struct mac_device_info *hw,
 
 static void dwmac4_phylink_get_caps(struct stmmac_priv *priv)
 {
-	priv->phylink_config.mac_capabilities |= MAC_2500FD;
+	/* Half-Duplex can only work with single tx queue */
+	if (priv->plat->tx_queues_to_use > 1)
+		priv->hw->link.caps &= ~(MAC_10HD | MAC_100HD | MAC_1000HD);
+	else
+		priv->hw->link.caps |= (MAC_10HD | MAC_100HD | MAC_1000HD);
 }
 
 static void dwmac4_rx_queue_enable(struct mac_device_info *hw,
@@ -1356,6 +1360,8 @@ int dwmac4_setup(struct stmmac_priv *priv)
 	if (mac->multicast_filter_bins)
 		mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins);
 
+	mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
+			 MAC_10 | MAC_100 | MAC_1000 | MAC_2500FD;
 	mac->link.duplex = GMAC_CONFIG_DM;
 	mac->link.speed10 = GMAC_CONFIG_PS;
 	mac->link.speed100 = GMAC_CONFIG_FES | GMAC_CONFIG_PS;
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
index eb48211d9b0e..79ea8329ead5 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
@@ -47,14 +47,6 @@ static void dwxgmac2_core_init(struct mac_device_info *hw,
 	writel(XGMAC_INT_DEFAULT_EN, ioaddr + XGMAC_INT_EN);
 }
 
-static void xgmac_phylink_get_caps(struct stmmac_priv *priv)
-{
-	priv->phylink_config.mac_capabilities |= MAC_2500FD | MAC_5000FD |
-						 MAC_10000FD | MAC_25000FD |
-						 MAC_40000FD | MAC_50000FD |
-						 MAC_100000FD;
-}
-
 static void dwxgmac2_set_mac(void __iomem *ioaddr, bool enable)
 {
 	u32 tx = readl(ioaddr + XGMAC_TX_CONFIG);
@@ -1618,6 +1610,11 @@ int dwxlgmac2_setup(struct stmmac_priv *priv)
 	if (mac->multicast_filter_bins)
 		mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins);
 
+	mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
+			 MAC_1000FD | MAC_2500FD | MAC_5000FD |
+			 MAC_10000FD | MAC_25000FD |
+			 MAC_40000FD | MAC_50000FD |
+			 MAC_100000FD;
 	mac->link.duplex = 0;
 	mac->link.speed1000 = XLGMAC_CONFIG_SS_1000;
 	mac->link.speed2500 = XLGMAC_CONFIG_SS_2500;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 25519952f754..24ff5d1eb963 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -936,6 +936,22 @@ static void stmmac_mac_flow_ctrl(struct stmmac_priv *priv, u32 duplex)
 			priv->pause, tx_cnt);
 }
 
+static unsigned long stmmac_mac_get_caps(struct phylink_config *config,
+					 phy_interface_t interface)
+{
+	struct stmmac_priv *priv = netdev_priv(to_net_dev(config->dev));
+
+	/* Get the MAC-specific capabilities */
+	stmmac_mac_phylink_get_caps(priv);
+
+	config->mac_capabilities = priv->hw->link.caps;
+
+	if (priv->plat->max_speed)
+		phylink_limit_mac_speed(config, priv->plat->max_speed);
+
+	return config->mac_capabilities;
+}
+
 static struct phylink_pcs *stmmac_mac_select_pcs(struct phylink_config *config,
 						 phy_interface_t interface)
 {
@@ -1105,6 +1121,7 @@ static void stmmac_mac_link_up(struct phylink_config *config,
 }
 
 static const struct phylink_mac_ops stmmac_phylink_mac_ops = {
+	.mac_get_caps = stmmac_mac_get_caps,
 	.mac_select_pcs = stmmac_mac_select_pcs,
 	.mac_config = stmmac_mac_config,
 	.mac_link_down = stmmac_mac_link_down,
@@ -1198,24 +1215,12 @@ static int stmmac_init_phy(struct net_device *dev)
 	return ret;
 }
 
-static void stmmac_set_half_duplex(struct stmmac_priv *priv)
-{
-	/* Half-Duplex can only work with single tx queue */
-	if (priv->plat->tx_queues_to_use > 1)
-		priv->phylink_config.mac_capabilities &=
-			~(MAC_10HD | MAC_100HD | MAC_1000HD);
-	else
-		priv->phylink_config.mac_capabilities |=
-			(MAC_10HD | MAC_100HD | MAC_1000HD);
-}
-
 static int stmmac_phy_setup(struct stmmac_priv *priv)
 {
 	struct stmmac_mdio_bus_data *mdio_bus_data;
 	int mode = priv->plat->phy_interface;
 	struct fwnode_handle *fwnode;
 	struct phylink *phylink;
-	int max_speed;
 
 	priv->phylink_config.dev = &priv->dev->dev;
 	priv->phylink_config.type = PHYLINK_NETDEV;
@@ -1236,19 +1241,6 @@ static int stmmac_phy_setup(struct stmmac_priv *priv)
 		xpcs_get_interfaces(priv->hw->xpcs,
 				    priv->phylink_config.supported_interfaces);
 
-	priv->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
-						MAC_10FD | MAC_100FD |
-						MAC_1000FD;
-
-	stmmac_set_half_duplex(priv);
-
-	/* Get the MAC specific capabilities */
-	stmmac_mac_phylink_get_caps(priv);
-
-	max_speed = priv->plat->max_speed;
-	if (max_speed)
-		phylink_limit_mac_speed(&priv->phylink_config, max_speed);
-
 	fwnode = priv->plat->port_node;
 	if (!fwnode)
 		fwnode = dev_fwnode(priv->device);

---

Note I intentionally omitted the part with the platform-specific MAC
capabilities filtering because AFAICS it won't be necessary for
Yanteng. He'll have the plat_stmmacenet_data::setup() callback defined
anyway, in which he'll be able to initialize the MAC capabilities as
required by his platform.

-Serge(y)

> 
> > In anyway I am sure the approach suggested in the initial patch of
> > this thread isn't good since it motivates the developers to implement
> > more-and-more DW MAC-specific platform capabilities flags fixing
> > another flags, which makes the generic code even more complicated
> > than it already is with endless if-else-plat-flags statements.
> 
> Yes, I do agree with that.
> 
> -- 
> RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
> FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!

^ permalink raw reply related	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 07/11] net: stmmac: dwmac-loongson: Add multi-channel supports for loongson
  2024-03-22 10:36           ` Yanteng Si
@ 2024-03-22 18:47             ` Serge Semin
  2024-04-03  8:09               ` Yanteng Si
  0 siblings, 1 reply; 97+ messages in thread
From: Serge Semin @ 2024-03-22 18:47 UTC (permalink / raw)
  To: Yanteng Si
  Cc: hkallweit1, andrew, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

On Fri, Mar 22, 2024 at 06:36:20PM +0800, Yanteng Si wrote:
> > > > > > +{
> > > > > > +	int i, ret, vecs;
> > > > > > +
> > > > > > +	vecs = roundup_pow_of_two(channel_num * 2 + 1);
> > > > > > +	ret = pci_alloc_irq_vectors(pdev, vecs, vecs, PCI_IRQ_MSI);
> > > > > > +	if (ret < 0) {
> > > > > > +		dev_info(&pdev->dev,
> > > > > > +			 "MSI enable failed, Fallback to legacy interrupt\n");
> > > > > > +		return loongson_dwmac_config_legacy(pdev, plat, res, np);
> > > > > In what conditions is this possible? Will the
> > > > > loongson_dwmac_config_legacy() method work in that case? Did you test
> > > > > it out?
> I need to wait for special hardware and PMON for this.  Please give me some
> time.
> 
> > Then those platforms will _require_ to have the DT-node specified. This
> > will define the DT-bindings which I doubt you imply here. Am I wrong?
> > 
> > Once again have you tested the loongson_dwmac_config_legacy() method
> > working in the case of the pci_alloc_irq_vectors() failure?
> 
> Yes!  I have tested it, it works in single channel mode.
> 
> dmesg:
> 
> [    3.935203] mdio_bus stmmac-18:02: attached PHY driver [unbound]
> (mii_bus:phy_addr=stmmac-18:02, irq=POLL)
> [    3.945625] dwmac-loongson-pci 0000:00:03.1: MSI enable failed, Fallback to
> legacy interrupt
> [    3.954175] dwmac-loongson-pci 0000:00:03.1: User ID: 0xd1, Synopsys ID: 0x10
> [    3.973676] dwmac-loongson-pci 0000:00:03.1: DMA HW capability register supported
> [    3.981135] dwmac-loongson-pci 0000:00:03.1: RX Checksum Offload Engine supported
> 
> cat /proc/interrupt:
> 
> 43:          0          0   PCH PIC  16  ahci[0000:00:08.0]
>   44:          0          0   PCH PIC  12  enp0s3f0
>   45:          0          0   PCH PIC  14  enp0s3f1
>   46:      16233          0   PCH PIC  17  enp0s3f2
>   47:      12698          0   PCH PIC  48  xhci-hcd:usb1
> 
> 
> the irq number 46 is the falkback legacy irq.

Ok. Thanks. You can do that in a bit more clever manner. Like this:

+static int loongson_dwmac_config_multi_msi(struct pci_dev *pdev,
+					   struct plat_stmmacenet_data *plat,
+					   struct stmmac_resources *res)
+{
+	int i, ret, vecs;
+
+	/* INT NAME | MAC | CH7 rx | CH7 tx | ... | CH0 rx | CH0 tx |
+	 * --------- ----- -------- --------  ...  -------- --------
+	 * IRQ NUM  |  0  |   1    |   2    | ... |   15   |   16   |
+	 */
+	vecs = plat->rx_queues_to_use + plat->tx_queues_to_use + 1;
+	ret = pci_alloc_irq_vectors(pdev, 1, vecs, PCI_IRQ_MSI | PCI_IRQ_LEGACY);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Failed to allocate PCI IRQs\n");
+		return ret;
+	} else if (ret >= vecs) {
+		for (i = 0; i < plat->rx_queues_to_use; i++) {
+			res->rx_irq[CHANNELS_NUM - 1 - i] =
+				pci_irq_vector(pdev, 1 + i * 2);
+		}
+		for (i = 0; i < plat->tx_queues_to_use; i++) {
+			res->tx_irq[CHANNELS_NUM - 1 - i] =
+				pci_irq_vector(pdev, 2 + i * 2);
+		}
+
+		plat->flags |= STMMAC_FLAG_MULTI_MSI_EN;
+	}
+
+	res->irq = pci_irq_vector(pdev, 0);
+
+	return 0;
+}

Thus in case if for some reason you were able to allocate less MSI
IRQs than required you'll still be able to use them. The legacy IRQ
will be also available in case if MSI failed to be allocated.

-Serge(y)

> 
> > 	
> > 
> > > > > > +	}
> > > > > > +
> > > > > > +	plat->rx_queues_to_use = channel_num;
> > > > > > +	plat->tx_queues_to_use = channel_num;
> > > > > This is supposed to be initialized in the setup() methods. Please move
> > > > > it to the dedicated patch.
> > > > No, referring to my previous reply, only the 0x10 gnet device has 8 channels,
> > > > and the 0x37 device has a single channel.
> > Yes. You have a perfectly suitable method for it. It's
> > loongson_gnet_data(). Init the number of channels there based on the
> > value read from the GMAC_VERSION.SNPSVER field. Thus the
> > loongson_gnet_config_multi_msi() will get to be more coherent setting
> > up the MSI IRQs only.
> You are right!  it works well.
> 
> 
> Thanks,
> 
> Yanteng
> 
> 

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 06/11] net: stmmac: dwmac-loongson: Add GNET support
  2024-03-21  9:13           ` Yanteng Si
  2024-03-21 14:55             ` Andrew Lunn
@ 2024-03-22 19:09             ` Serge Semin
  1 sibling, 0 replies; 97+ messages in thread
From: Serge Semin @ 2024-03-22 19:09 UTC (permalink / raw)
  To: Yanteng Si
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

On Thu, Mar 21, 2024 at 05:13:45PM +0800, Yanteng Si wrote:
> 
> 在 2024/3/19 23:03, Serge Semin 写道:
> > > > > >   >> +static int loongson_gnet_data(struct pci_dev *pdev,
> > > > > > +			      struct plat_stmmacenet_data *plat)
> > > > > > +{
> > > > > > +	loongson_default_data(pdev, plat);
> > > > > > +
> > > > > > +	plat->multicast_filter_bins = 256;
> > > > > > +
> > > > > > +	plat->mdio_bus_data->phy_mask =  ~(u32)BIT(2);
> > > > > > +
> > > > > > +	plat->phy_addr = 2;
> > > > > > +	plat->phy_interface = PHY_INTERFACE_MODE_INTERNAL;
> > > > > Are you sure PHY-interface is supposed to be defined as "internal"?
> > > > Yes, because the gnet hardware has a integrated PHY, so we set it to internal,
> > > > 
> ...
> > kdoc in "include/linux/phy.h" defines the PHY_INTERFACE_MODE_INTERNAL
> > mode as for a case of the MAC and PHY being combined. IIUC it's
> > reserved for a case when you can't determine actual interface between
> > the MAC and PHY. Is it your case? Are you sure the interface between
> > MAC and PHY isn't something like GMII/RGMII/etc?
> Hmmm. the interface between MAC and PHY is GMII, so let's use
> 

> PHY_INTERFACE_MODE_GMII?

If MAC<->PHY interface is GMII, then PHY_INTERFACE_MODE_GMII should be
used to indicate that.

-Serge(y)

> 
> 
> Thanks,
> 
> Yanteng
> 

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 09/11] net: stmmac: dwmac-loongson: Fix half duplex
  2024-03-22 18:07                 ` Serge Semin
@ 2024-03-22 19:56                   ` Russell King (Oracle)
  2024-04-03 12:37                     ` Serge Semin
  0 siblings, 1 reply; 97+ messages in thread
From: Russell King (Oracle) @ 2024-03-22 19:56 UTC (permalink / raw)
  To: Serge Semin
  Cc: Yanteng Si, andrew, hkallweit1, peppe.cavallaro,
	alexandre.torgue, joabreu, Jose.Abreu, chenhuacai, guyinggang,
	netdev, chris.chenfeiyang

On Fri, Mar 22, 2024 at 09:07:19PM +0300, Serge Semin wrote:
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> index 25519952f754..24ff5d1eb963 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> @@ -936,6 +936,22 @@ static void stmmac_mac_flow_ctrl(struct stmmac_priv *priv, u32 duplex)
>  			priv->pause, tx_cnt);
>  }
>  
> +static unsigned long stmmac_mac_get_caps(struct phylink_config *config,
> +					 phy_interface_t interface)
> +{
> +	struct stmmac_priv *priv = netdev_priv(to_net_dev(config->dev));
> +
> +	/* Get the MAC-specific capabilities */
> +	stmmac_mac_phylink_get_caps(priv);
> +
> +	config->mac_capabilities = priv->hw->link.caps;
> +
> +	if (priv->plat->max_speed)
> +		phylink_limit_mac_speed(config, priv->plat->max_speed);
> +
> +	return config->mac_capabilities;

Yes, I think your approach is better - and it still allows for the
platform's capabilities to be masked in towards the end of this
function.

Thanks.

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 08/11] net: stmmac: dwmac-loongson: Fix MAC speed for GNET
  2024-03-21 15:02             ` Andrew Lunn
  2024-03-21 15:19               ` Russell King (Oracle)
@ 2024-03-26 12:02               ` Yanteng Si
  2024-03-26 12:21                 ` Andrew Lunn
  1 sibling, 1 reply; 97+ messages in thread
From: Yanteng Si @ 2024-03-26 12:02 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Serge Semin, hkallweit1, peppe.cavallaro, alexandre.torgue,
	joabreu, Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang


在 2024/3/21 23:02, Andrew Lunn 写道:
>> When switching speeds (from 100M to 1000M), the phy cannot output clocks,
>>
>> resulting in the unavailability of the network card.  At this time, a reset
>> of the
>>
>> phy is required.
> reset, or restart of autoneg?

reset.


Thanks,

Yanteng


^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 08/11] net: stmmac: dwmac-loongson: Fix MAC speed for GNET
  2024-03-26 12:02               ` Yanteng Si
@ 2024-03-26 12:21                 ` Andrew Lunn
  2024-03-27  2:41                   ` Yanteng Si
  0 siblings, 1 reply; 97+ messages in thread
From: Andrew Lunn @ 2024-03-26 12:21 UTC (permalink / raw)
  To: Yanteng Si
  Cc: Serge Semin, hkallweit1, peppe.cavallaro, alexandre.torgue,
	joabreu, Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

On Tue, Mar 26, 2024 at 08:02:55PM +0800, Yanteng Si wrote:
> 
> 在 2024/3/21 23:02, Andrew Lunn 写道:
> > > When switching speeds (from 100M to 1000M), the phy cannot output clocks,
> > > 
> > > resulting in the unavailability of the network card.  At this time, a reset
> > > of the
> > > 
> > > phy is required.
> > reset, or restart of autoneg?
> 
> reset.

If you need a reset, why are you asking it to restart auto-neg?

	Andrew

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 08/11] net: stmmac: dwmac-loongson: Fix MAC speed for GNET
  2024-03-21 15:38                 ` Andrew Lunn
@ 2024-03-26 12:32                   ` Yanteng Si
  0 siblings, 0 replies; 97+ messages in thread
From: Yanteng Si @ 2024-03-26 12:32 UTC (permalink / raw)
  To: Andrew Lunn, Russell King (Oracle)
  Cc: Serge Semin, hkallweit1, peppe.cavallaro, alexandre.torgue,
	joabreu, Jose.Abreu, chenhuacai, guyinggang, netdev,
	chris.chenfeiyang

Hi Andrew, Serge and Russell,

在 2024/3/21 23:38, Andrew Lunn 写道:
>> However, because stmmac uses phylink, we should be adding phylink
>> interfaces that forward to phylib to avoid the layering violation.
> Yes.
>
> Maybe just call phylink_ethtool_nway_reset()?  Just depends if the

Nice! It works.


In fact, after repeated testing, my previous code did not fix all 
issues, such

as network unavailability when switching from 1000M to 100M(physical).


But your method is perfect!



Thanks,

Yanteng

> additional phylink_pcs_an_restart(pl) will mess things up for this
> device.
>
>        Andrew


^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 08/11] net: stmmac: dwmac-loongson: Fix MAC speed for GNET
  2024-03-26 12:21                 ` Andrew Lunn
@ 2024-03-27  2:41                   ` Yanteng Si
  2024-03-27 12:47                     ` Andrew Lunn
  0 siblings, 1 reply; 97+ messages in thread
From: Yanteng Si @ 2024-03-27  2:41 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Serge Semin, hkallweit1, peppe.cavallaro, alexandre.torgue,
	joabreu, Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang


在 2024/3/26 20:21, Andrew Lunn 写道:
> On Tue, Mar 26, 2024 at 08:02:55PM +0800, Yanteng Si wrote:
>> 在 2024/3/21 23:02, Andrew Lunn 写道:
>>>> When switching speeds (from 100M to 1000M), the phy cannot output clocks,
>>>>
>>>> resulting in the unavailability of the network card.  At this time, a reset
>>>> of the
>>>>
>>>> phy is required.
>>> reset, or restart of autoneg?
>> reset.
> If you need a reset, why are you asking it to restart auto-neg?
Autoneg was discussed in patch v1, but we may have misunderstood the 
description from our hardware engineers at the time. The root cause is 
that there is an error in the connection between the MAC and PHY. After 
repeated tests, we have found that

auto-negcannot solve all problems and can only be reset. Thanks, Yanteng


^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 08/11] net: stmmac: dwmac-loongson: Fix MAC speed for GNET
  2024-03-27  2:41                   ` Yanteng Si
@ 2024-03-27 12:47                     ` Andrew Lunn
  2024-03-28 10:08                       ` Yanteng Si
  0 siblings, 1 reply; 97+ messages in thread
From: Andrew Lunn @ 2024-03-27 12:47 UTC (permalink / raw)
  To: Yanteng Si
  Cc: Serge Semin, hkallweit1, peppe.cavallaro, alexandre.torgue,
	joabreu, Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

On Wed, Mar 27, 2024 at 10:41:57AM +0800, Yanteng Si wrote:
> 
> 在 2024/3/26 20:21, Andrew Lunn 写道:
> > On Tue, Mar 26, 2024 at 08:02:55PM +0800, Yanteng Si wrote:
> > > 在 2024/3/21 23:02, Andrew Lunn 写道:
> > > > > When switching speeds (from 100M to 1000M), the phy cannot output clocks,
> > > > > 
> > > > > resulting in the unavailability of the network card.  At this time, a reset
> > > > > of the
> > > > > 
> > > > > phy is required.
> > > > reset, or restart of autoneg?
> > > reset.
> > If you need a reset, why are you asking it to restart auto-neg?
> Autoneg was discussed in patch v1, but we may have misunderstood the
> description from our hardware engineers at the time. The root cause is that
> there is an error in the connection between the MAC and PHY. After repeated
> tests, we have found that
> 
> auto-negcannot solve all problems and can only be reset. Thanks, Yanteng
 
So calling phylink_ethtool_nway_reset() does not fix your problem, and
you need some other fix.

    Andrew

---
pw-bot: cr

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 08/11] net: stmmac: dwmac-loongson: Fix MAC speed for GNET
  2024-03-27 12:47                     ` Andrew Lunn
@ 2024-03-28 10:08                       ` Yanteng Si
  0 siblings, 0 replies; 97+ messages in thread
From: Yanteng Si @ 2024-03-28 10:08 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Serge Semin, hkallweit1, peppe.cavallaro, alexandre.torgue,
	joabreu, Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang


在 2024/3/27 20:47, Andrew Lunn 写道:
> On Wed, Mar 27, 2024 at 10:41:57AM +0800, Yanteng Si wrote:
>> 在 2024/3/26 20:21, Andrew Lunn 写道:
>>> On Tue, Mar 26, 2024 at 08:02:55PM +0800, Yanteng Si wrote:
>>>> 在 2024/3/21 23:02, Andrew Lunn 写道:
>>>>>> When switching speeds (from 100M to 1000M), the phy cannot output clocks,
>>>>>>
>>>>>> resulting in the unavailability of the network card.  At this time, a reset
>>>>>> of the
>>>>>>
>>>>>> phy is required.
>>>>> reset, or restart of autoneg?
>>>> reset.
>>> If you need a reset, why are you asking it to restart auto-neg?
>> Autoneg was discussed in patch v1, but we may have misunderstood the
>> description from our hardware engineers at the time. The root cause is that
>> there is an error in the connection between the MAC and PHY. After repeated
>> tests, we have found that
>>
>> auto-negcannot solve all problems and can only be reset. Thanks, Yanteng
>   
> So calling phylink_ethtool_nway_reset() does not fix your problem, and
> you need some other fix.
>
Sorry, it's my fault.  I was stupid. Let me explain the whole story:

First, here is the original code we got:

  if (speed == SPEED_1000) {
   if (readl(ptr->ioaddr + MAC_CTRL_REG) & (1 << 15) /* PS */) {
    /* reset phy */
    phy_set_bits(ndev->phydev, 0 /*MII_BMCR*/, 0x200 /*BMCR_ANRESTART*/);

Although the comment in the code is **reset phy**, the actual operation
is to modify the autoneg bit. This method fixes all problems.

V1:
if (phydev->speed == SPEED_1000)
  phydev->autoneg = AUTONEG_ENABLE

After discussing with you, see:
<https://lore.kernel.org/loongarch/be1874e517f4f4cc50906f18689a0add3594c2e0.1689215889.git.chenfeiyang@loongson.cn/>

v2 -> v8:
if (speed == SPEED_1000)
  if (readl(ptr->ioaddr + MAC_CTRL_REG) & (1 << 15) /* PS */)
   phy_restart_aneg(ndev->phydev);

Subsequent versions have been using this method. In recent days, I 
accidentally
conducted an erroneous test, possibly due to the network cable not being
firmly connected, leading me to mistakenly believe that this did not fix all
problems. After conducting sufficient testing today, I found that I was 
mistaken
and that calling phy_restart_aneg() directly fixed all problems.

At your suggestion, calling phylink_et Athletic_nway_reset() also works 
well, but
it will report an assertion failed at drivers/net/phy/phylink.c in the 
dmesg.
So let's continue to call phy_restart_aneg()?

Finally, why did I reply you with reset?  It's because I first checked 
the original
code, and the comment in the original code was /* reset phy */.  I 
thought it was
reset, but today I found out that it was actually autoneg. I apologize 
for my

carelessness.


Thanks,

Yanteng


^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 06/11] net: stmmac: dwmac-loongson: Add GNET support
  2024-03-21 14:55             ` Andrew Lunn
@ 2024-03-28 11:41               ` Yanteng Si
  0 siblings, 0 replies; 97+ messages in thread
From: Yanteng Si @ 2024-03-28 11:41 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Serge Semin, hkallweit1, peppe.cavallaro, alexandre.torgue,
	joabreu, Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang


在 2024/3/21 22:55, Andrew Lunn 写道:
>> Because the default return value of gnet's mdio is 0xffff, when scanning for
>> phy,
>>
>> if the return value is not 0, it will be assumed that the phy for that
>> address exists.
> That is not correct. The MDIO bus has a pull up on the data line. If
> there is no device at a given address, that pull up results in 0xffff
> being read. phylib understands this, it knows that a read with the
> value of 0xffff probably means there is no device at that address. So
> it will not create a device.
OK. I've got it.
>
>>   Not specifying an address will cause all addresses' phy to be detected, and
>> the
>>
>> lowest address' phy will be selected by default. so then, the network is
>> unavailable.
> Do you have multiple PHYs on the bus? If there is only one PHY the
Only one.
> first PHY should be the PHY you want, and phy_find_first() will do

static int loongson_gnet_data(struct pci_dev *pdev,
                   struct plat_stmmacenet_data *plat)
{
     struct net_device *ndev = dev_get_drvdata(&pdev->dev);
     struct stmmac_priv *priv = netdev_priv(ndev);
     struct phy_device *phydev;

     phydev = phy_find_first(priv->mii);
     plat->phy_addr = phydev->mdio.addr;

If I understand your comment correctly, this doesn't seem to work

because the mii hasn't been initialized at this point.


So, how about plat->phy_addr = -1;  ?


Thanks,

Yanteng



^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 07/11] net: stmmac: dwmac-loongson: Add multi-channel supports for loongson
  2024-03-22 18:47             ` Serge Semin
@ 2024-04-03  8:09               ` Yanteng Si
  2024-04-03 12:03                 ` Serge Semin
  0 siblings, 1 reply; 97+ messages in thread
From: Yanteng Si @ 2024-04-03  8:09 UTC (permalink / raw)
  To: Serge Semin
  Cc: hkallweit1, andrew, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang


在 2024/3/23 02:47, Serge Semin 写道:
> +static int loongson_dwmac_config_multi_msi(struct pci_dev *pdev,
> +					   struct plat_stmmacenet_data *plat,
> +					   struct stmmac_resources *res)
> +{
> +	int i, ret, vecs;
> +
> +	/* INT NAME | MAC | CH7 rx | CH7 tx | ... | CH0 rx | CH0 tx |
> +	 * --------- ----- -------- --------  ...  -------- --------
> +	 * IRQ NUM  |  0  |   1    |   2    | ... |   15   |   16   |
> +	 */
> +	vecs = plat->rx_queues_to_use + plat->tx_queues_to_use + 1;
> +	ret = pci_alloc_irq_vectors(pdev, 1, vecs, PCI_IRQ_MSI | PCI_IRQ_LEGACY);
> +	if (ret < 0) {
> +		dev_err(&pdev->dev, "Failed to allocate PCI IRQs\n");
> +		return ret;
> +	} else if (ret >= vecs) {
> +		for (i = 0; i < plat->rx_queues_to_use; i++) {
> +			res->rx_irq[CHANNELS_NUM - 1 - i] =
> +				pci_irq_vector(pdev, 1 + i * 2);
> +		}
> +		for (i = 0; i < plat->tx_queues_to_use; i++) {
> +			res->tx_irq[CHANNELS_NUM - 1 - i] =
> +				pci_irq_vector(pdev, 2 + i * 2);
> +		}
> +
> +		plat->flags |= STMMAC_FLAG_MULTI_MSI_EN;
> +	}
> +
> +	res->irq = pci_irq_vector(pdev, 0);
> +
> +	return 0;
> +}
>
> Thus in case if for some reason you were able to allocate less MSI
> IRQs than required you'll still be able to use them. The legacy IRQ
> will be also available in case if MSI failed to be allocated.

Great, we will consider doing this in the future, but at this stage, we 
don't want to add too much complexity.


Thanks,

Yanteng


^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 07/11] net: stmmac: dwmac-loongson: Add multi-channel supports for loongson
  2024-03-19 15:53         ` Serge Semin
  2024-03-22 10:36           ` Yanteng Si
@ 2024-04-03  8:23           ` Yanteng Si
  1 sibling, 0 replies; 97+ messages in thread
From: Yanteng Si @ 2024-04-03  8:23 UTC (permalink / raw)
  To: Serge Semin
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang


在 2024/3/19 23:53, Serge Semin 写道:
> Then those platforms will_require_  to have the DT-node specified. This
> will define the DT-bindings which I doubt you imply here. Am I wrong?

yes,dt-node has specified irq information,and this driver also work with ACPI
configuration.

Thanks,
Yanteng


^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 07/11] net: stmmac: dwmac-loongson: Add multi-channel supports for loongson
  2024-04-03  8:09               ` Yanteng Si
@ 2024-04-03 12:03                 ` Serge Semin
  2024-04-05 10:17                   ` Yanteng Si
  0 siblings, 1 reply; 97+ messages in thread
From: Serge Semin @ 2024-04-03 12:03 UTC (permalink / raw)
  To: Yanteng Si
  Cc: hkallweit1, andrew, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

On Wed, Apr 03, 2024 at 04:09:21PM +0800, Yanteng Si wrote:
> 
> 在 2024/3/23 02:47, Serge Semin 写道:
> > +static int loongson_dwmac_config_multi_msi(struct pci_dev *pdev,
> > +					   struct plat_stmmacenet_data *plat,
> > +					   struct stmmac_resources *res)
> > +{
> > +	int i, ret, vecs;
> > +
> > +	/* INT NAME | MAC | CH7 rx | CH7 tx | ... | CH0 rx | CH0 tx |
> > +	 * --------- ----- -------- --------  ...  -------- --------
> > +	 * IRQ NUM  |  0  |   1    |   2    | ... |   15   |   16   |
> > +	 */
> > +	vecs = plat->rx_queues_to_use + plat->tx_queues_to_use + 1;
> > +	ret = pci_alloc_irq_vectors(pdev, 1, vecs, PCI_IRQ_MSI | PCI_IRQ_LEGACY);
> > +	if (ret < 0) {
> > +		dev_err(&pdev->dev, "Failed to allocate PCI IRQs\n");
> > +		return ret;
> > +	} else if (ret >= vecs) {
> > +		for (i = 0; i < plat->rx_queues_to_use; i++) {
> > +			res->rx_irq[CHANNELS_NUM - 1 - i] =
> > +				pci_irq_vector(pdev, 1 + i * 2);
> > +		}
> > +		for (i = 0; i < plat->tx_queues_to_use; i++) {
> > +			res->tx_irq[CHANNELS_NUM - 1 - i] =
> > +				pci_irq_vector(pdev, 2 + i * 2);
> > +		}
> > +
> > +		plat->flags |= STMMAC_FLAG_MULTI_MSI_EN;
> > +	}
> > +
> > +	res->irq = pci_irq_vector(pdev, 0);
> > +
> > +	return 0;
> > +}
> > 
> > Thus in case if for some reason you were able to allocate less MSI
> > IRQs than required you'll still be able to use them. The legacy IRQ
> > will be also available in case if MSI failed to be allocated.
> 
> Great, we will consider doing this in the future, but at this stage, we
> don't want to add too much complexity.

This comment isn't about complexity. Moreover the code in my comment
is simpler since the function is more coherent and doesn't have the
redundant dependencies from the node-pointer and the
loongson_dwmac_config_legacy() function. In addition it provides more
flexible solution in case if there were less MSI vectors allocated
then required.

-Serge(y)

> 
> 
> Thanks,
> 
> Yanteng
> 

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 09/11] net: stmmac: dwmac-loongson: Fix half duplex
  2024-03-22 19:56                   ` Russell King (Oracle)
@ 2024-04-03 12:37                     ` Serge Semin
  2024-04-05 10:48                       ` Yanteng Si
  0 siblings, 1 reply; 97+ messages in thread
From: Serge Semin @ 2024-04-03 12:37 UTC (permalink / raw)
  To: Russell King (Oracle)
  Cc: Yanteng Si, andrew, hkallweit1, peppe.cavallaro,
	alexandre.torgue, joabreu, Jose.Abreu, chenhuacai, guyinggang,
	netdev, chris.chenfeiyang

On Fri, Mar 22, 2024 at 07:56:44PM +0000, Russell King (Oracle) wrote:
> On Fri, Mar 22, 2024 at 09:07:19PM +0300, Serge Semin wrote:
> > diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> > index 25519952f754..24ff5d1eb963 100644
> > --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> > +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> > @@ -936,6 +936,22 @@ static void stmmac_mac_flow_ctrl(struct stmmac_priv *priv, u32 duplex)
> >  			priv->pause, tx_cnt);
> >  }
> >  
> > +static unsigned long stmmac_mac_get_caps(struct phylink_config *config,
> > +					 phy_interface_t interface)
> > +{
> > +	struct stmmac_priv *priv = netdev_priv(to_net_dev(config->dev));
> > +
> > +	/* Get the MAC-specific capabilities */
> > +	stmmac_mac_phylink_get_caps(priv);
> > +
> > +	config->mac_capabilities = priv->hw->link.caps;
> > +
> > +	if (priv->plat->max_speed)
> > +		phylink_limit_mac_speed(config, priv->plat->max_speed);
> > +
> > +	return config->mac_capabilities;
> 
> Yes, I think your approach is better - and it still allows for the
> platform's capabilities to be masked in towards the end of this
> function.

Sorry for the long-term response. Thanks for your comment. Seeing
Yanteng is struggling much with this series review I'll convert the
suggested change into a patchset (taking into account that the change
implies some fixes) and submit it for review later on this week. After
finishing the review stage, the series could be either merged in right
away or Yanteng will be able to pick it up and add it into his patchset.

-Serge(y)

> 
> Thanks.
> 
> -- 
> RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
> FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 07/11] net: stmmac: dwmac-loongson: Add multi-channel supports for loongson
  2024-04-03 12:03                 ` Serge Semin
@ 2024-04-05 10:17                   ` Yanteng Si
  0 siblings, 0 replies; 97+ messages in thread
From: Yanteng Si @ 2024-04-05 10:17 UTC (permalink / raw)
  To: Serge Semin
  Cc: hkallweit1, andrew, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang


在 2024/4/3 20:03, Serge Semin 写道:
> On Wed, Apr 03, 2024 at 04:09:21PM +0800, Yanteng Si wrote:
>> 在 2024/3/23 02:47, Serge Semin 写道:
>>> +static int loongson_dwmac_config_multi_msi(struct pci_dev *pdev,
>>> +					   struct plat_stmmacenet_data *plat,
>>> +					   struct stmmac_resources *res)
>>> +{
>>> +	int i, ret, vecs;
>>> +
>>> +	/* INT NAME | MAC | CH7 rx | CH7 tx | ... | CH0 rx | CH0 tx |
>>> +	 * --------- ----- -------- --------  ...  -------- --------
>>> +	 * IRQ NUM  |  0  |   1    |   2    | ... |   15   |   16   |
>>> +	 */
>>> +	vecs = plat->rx_queues_to_use + plat->tx_queues_to_use + 1;
>>> +	ret = pci_alloc_irq_vectors(pdev, 1, vecs, PCI_IRQ_MSI | PCI_IRQ_LEGACY);
>>> +	if (ret < 0) {
>>> +		dev_err(&pdev->dev, "Failed to allocate PCI IRQs\n");
>>> +		return ret;
>>> +	} else if (ret >= vecs) {
>>> +		for (i = 0; i < plat->rx_queues_to_use; i++) {
>>> +			res->rx_irq[CHANNELS_NUM - 1 - i] =
>>> +				pci_irq_vector(pdev, 1 + i * 2);
>>> +		}
>>> +		for (i = 0; i < plat->tx_queues_to_use; i++) {
>>> +			res->tx_irq[CHANNELS_NUM - 1 - i] =
>>> +				pci_irq_vector(pdev, 2 + i * 2);
>>> +		}
>>> +
>>> +		plat->flags |= STMMAC_FLAG_MULTI_MSI_EN;
>>> +	}
>>> +
>>> +	res->irq = pci_irq_vector(pdev, 0);
>>> +
>>> +	return 0;
>>> +}
>>>
>>> Thus in case if for some reason you were able to allocate less MSI
>>> IRQs than required you'll still be able to use them. The legacy IRQ
>>> will be also available in case if MSI failed to be allocated.
>> Great, we will consider doing this in the future, but at this stage, we
>> don't want to add too much complexity.
> This comment isn't about complexity. Moreover the code in my comment
> is simpler since the function is more coherent and doesn't have the
> redundant dependencies from the node-pointer and the
> loongson_dwmac_config_legacy() function. In addition it provides more
> flexible solution in case if there were less MSI vectors allocated
> then required.

I just tried it, the network card doesn't work, the reason is not clear.

Considering that the overall change is a little big, I want to send the 
current

working state as the patch v9.


However, I will continue to analyze the reasons for the failure and 
submit them

as a separate patch in the future. Is that OK?


Thanks,

Yanteng


^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 09/11] net: stmmac: dwmac-loongson: Fix half duplex
  2024-04-03 12:37                     ` Serge Semin
@ 2024-04-05 10:48                       ` Yanteng Si
  0 siblings, 0 replies; 97+ messages in thread
From: Yanteng Si @ 2024-04-05 10:48 UTC (permalink / raw)
  To: Serge Semin, Russell King (Oracle)
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, guyinggang, netdev, chris.chenfeiyang


在 2024/4/3 20:37, Serge Semin 写道:
> On Fri, Mar 22, 2024 at 07:56:44PM +0000, Russell King (Oracle) wrote:
>> On Fri, Mar 22, 2024 at 09:07:19PM +0300, Serge Semin wrote:
>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>>> index 25519952f754..24ff5d1eb963 100644
>>> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>>> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>>> @@ -936,6 +936,22 @@ static void stmmac_mac_flow_ctrl(struct stmmac_priv *priv, u32 duplex)
>>>   			priv->pause, tx_cnt);
>>>   }
>>>   
>>> +static unsigned long stmmac_mac_get_caps(struct phylink_config *config,
>>> +					 phy_interface_t interface)
>>> +{
>>> +	struct stmmac_priv *priv = netdev_priv(to_net_dev(config->dev));
>>> +
>>> +	/* Get the MAC-specific capabilities */
>>> +	stmmac_mac_phylink_get_caps(priv);
>>> +
>>> +	config->mac_capabilities = priv->hw->link.caps;
>>> +
>>> +	if (priv->plat->max_speed)
>>> +		phylink_limit_mac_speed(config, priv->plat->max_speed);
>>> +
>>> +	return config->mac_capabilities;
>> Yes, I think your approach is better - and it still allows for the
>> platform's capabilities to be masked in towards the end of this
>> function.
> Sorry for the long-term response. Thanks for your comment. Seeing
> Yanteng is struggling much with this series review I'll convert the
> suggested change into a patchset (taking into account that the change
> implies some fixes) and submit it for review later on this week. After
> finishing the review stage, the series could be either merged in right
> away or Yanteng will be able to pick it up and add it into his patchset.
>
Couldn't be better! I have already started to re-split the patches, and 
then a series

of tests are needed. There are some network card parameters that I need 
to confirm

with the hardware engineer. Of course, I will pay attention to the email 
list before

sending it out. If I don't see your patch set, I will pick it up.


Thanks,

Yanteng



^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH net-next v8 02/11] net: stmmac: dwmac-loongson: Refactor code for loongson_dwmac_probe()
  2024-02-05 14:43   ` Serge Semin
@ 2024-04-05 11:13     ` Yanteng Si
  0 siblings, 0 replies; 97+ messages in thread
From: Yanteng Si @ 2024-04-05 11:13 UTC (permalink / raw)
  To: Serge Semin
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

Hi Serge,


Sorry, I seem to have forgotten to reply to the comments on this patch.

在 2024/2/5 22:43, Serge Semin 写道:
> On Tue, Jan 30, 2024 at 04:43:22PM +0800, Yanteng Si wrote:
>> The driver function is not changed, but the code location is
>> adjusted to prepare for adding more loongson drivers.
> Having the word "refactoring" in the subject is always suspicious
> because submitters very often try to hind behind it many small
> changes they didn't want to/didn't know how to unpin from a more bulky
> change. Moreover if there is no detailed explanation what is done and
> why, it raises too many review questions and makes the reviewers life
> much harder. So it would have been much better for us if you split up
> this change into the smaller patches (see my last comment for a
> presumable subset of the patches) to simplify the review process and
> improve the driver bisectability especially seeing there actually are
> functional changes introduced here despite of what is said in the
> commit log.
OK. I will resplit it.
>> Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
>> Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
>> Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
>> ---
>>   .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 61 +++++++++++++------
>>   1 file changed, 42 insertions(+), 19 deletions(-)
>>
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>> index 9e40c28d453a..e2dcb339b8b0 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>> @@ -9,7 +9,12 @@
>>   #include <linux/of_irq.h>
>>   #include "stmmac.h"
>>   
>> -static int loongson_default_data(struct plat_stmmacenet_data *plat)
>> +struct stmmac_pci_info {
>> +	int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat);
>> +};
>> +
>> +static void loongson_default_data(struct pci_dev *pdev,
>> +				  struct plat_stmmacenet_data *plat)
>>   {
>>   	plat->clk_csr = 2;	/* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */
>>   	plat->has_gmac = 1;
>> @@ -34,23 +39,37 @@ static int loongson_default_data(struct plat_stmmacenet_data *plat)
>>   
>>   	/* Disable RX queues routing by default */
>>   	plat->rx_queues_cfg[0].pkt_route = 0x0;
>> +}
>> +
>> +static int loongson_gmac_data(struct pci_dev *pdev,
>> +			      struct plat_stmmacenet_data *plat)
>> +{
>> +	loongson_default_data(pdev, plat);
>> +
>> +	plat->multicast_filter_bins = 256;
> Why do you need to move this here from the function tail?
OK, restore it.
>
>> +
>> +	plat->mdio_bus_data->phy_mask = 0;
> This is already zero. Why do you need this?
OK, drop it.
>
>>   
>> -	/* Default to phy auto-detection */
> What is wrong with this comment?
Sorry, restore it.
>
>>   	plat->phy_addr = -1;
>>   
>>   	plat->dma_cfg->pbl = 32;
>>   	plat->dma_cfg->pblx8 = true;
>>   
>> -	plat->multicast_filter_bins = 256;
>>   	return 0;
>>   }
>>   
>> -static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id *id)
>> +static struct stmmac_pci_info loongson_gmac_pci_info = {
>> +	.setup = loongson_gmac_data,
>> +};
>> +
>> +static int loongson_dwmac_probe(struct pci_dev *pdev,
>> +				const struct pci_device_id *id)
>>   {
>> +	int ret, i, bus_id, phy_mode;
>>   	struct plat_stmmacenet_data *plat;
>> +	struct stmmac_pci_info *info;
>>   	struct stmmac_resources res;
>>   	struct device_node *np;
>> -	int ret, i, phy_mode;
> Reverse xmas tree order please.
OK.
>
>>   
>>   	np = dev_of_node(&pdev->dev);
>>   
>> @@ -69,18 +88,17 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
>>   	if (!plat->mdio_bus_data)
>>   		return -ENOMEM;
>>   
>> +	plat->dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*plat->dma_cfg),
>> +				     GFP_KERNEL);
>> +	if (!plat->dma_cfg)
>> +		return -ENOMEM;
>> +
> Why do you need this moved above the mdio_node getting procedure? They
> seem independent.
Sorry, restore it.
>
>>   	plat->mdio_node = of_get_child_by_name(np, "mdio");
>>   	if (plat->mdio_node) {
>>   		dev_info(&pdev->dev, "Found MDIO subnode\n");
>>   		plat->mdio_bus_data->needs_reset = true;
>>   	}
>>   
>> -	plat->dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*plat->dma_cfg), GFP_KERNEL);
>> -	if (!plat->dma_cfg) {
>> -		ret = -ENOMEM;
>> -		goto err_put_node;
>> -	}
>> -
>>   	/* Enable pci device */
>>   	ret = pci_enable_device(pdev);
>>   	if (ret) {
>> @@ -98,9 +116,16 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
>>   		break;
>>   	}
>>   
>> -	plat->bus_id = of_alias_get_id(np, "ethernet");
>> -	if (plat->bus_id < 0)
>> -		plat->bus_id = pci_dev_id(pdev);
> This is a functional change because further bus_id is no longer
> initialized by the pci_dev_id() method as a fallback case. If you are
> sure this is required please unpin to a separate patch and explain.
Hmm, I will merge it into  [PATCH net-next 03/11] .
>
>> +	pci_set_master(pdev);
>> +
>> +	info = (struct stmmac_pci_info *)id->driver_data;
>> +	ret = info->setup(pdev, plat);
>> +	if (ret)
>> +		goto err_disable_device;
>> +
>> +	bus_id = of_alias_get_id(np, "ethernet");
>> +	if (bus_id >= 0)
>> +		plat->bus_id = bus_id;
>>   
>>   	phy_mode = device_get_phy_mode(&pdev->dev);
>>   	if (phy_mode < 0) {
>> @@ -110,11 +135,7 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
>>   	}
>>   
>>   	plat->phy_interface = phy_mode;
>> -	plat->mac_interface = PHY_INTERFACE_MODE_GMII;
> This is just dropped. Are you sure that the driver will work correctly
Yes, We only need to set phy_interface.
> after this change is applied? Russell already asked you about this change
> here:
> https://lore.kernel.org/netdev/ZZPnaziDZEcv5GGw@shell.armlinux.org.uk/
>
> Anyway please unpin it to a separate patch and explain.
OK.
>
>>   
>> -	pci_set_master(pdev);
>> -
>> -	loongson_default_data(plat);
>>   	pci_enable_msi(pdev);
>>   	memset(&res, 0, sizeof(res));
>>   	res.addr = pcim_iomap_table(pdev)[0];
>> @@ -212,8 +233,10 @@ static int __maybe_unused loongson_dwmac_resume(struct device *dev)
>>   static SIMPLE_DEV_PM_OPS(loongson_dwmac_pm_ops, loongson_dwmac_suspend,
>>   			 loongson_dwmac_resume);
>>   
>> +#define PCI_DEVICE_ID_LOONGSON_GMAC	0x7a03
>> +
>>   static const struct pci_device_id loongson_dwmac_id_table[] = {
>> -	{ PCI_VDEVICE(LOONGSON, 0x7a03) },
>> +	{ PCI_DEVICE_DATA(LOONGSON, GMAC, &loongson_gmac_pci_info) },
> If I were you and needed to preserve all the changes I would have
> split the patch up into the next patches:
> 1. Use PCI_DEVICE_DATA() macro for device identification
> 2. Drop mac-interface initialization
> 3. Don't initialize MDIO bus ID with PCIe device ID
> 4. Introduce device-specific setup callback

OK, I will.


Thanks,

Yanteng



^ permalink raw reply	[flat|nested] 97+ messages in thread

end of thread, other threads:[~2024-04-05 11:13 UTC | newest]

Thread overview: 97+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-01-30  8:43 [PATCH net-next v8 00/11] stmmac: Add Loongson platform support Yanteng Si
2024-01-30  8:43 ` [PATCH net-next v8 01/11] net: stmmac: Add multi-channel support Yanteng Si
2024-02-02 12:30   ` Simon Horman
2024-02-04  8:43     ` Yanteng Si
2024-02-04 23:28   ` Serge Semin
2024-02-06  9:02     ` Yanteng Si
2024-02-06  9:48       ` Serge Semin
2024-02-19 11:02     ` Yanteng Si
2024-02-21 13:48       ` Serge Semin
     [not found]         ` <ee2ffb6a-fe34-47a1-9734-b0e6697a5f09@loongson.cn>
2024-03-13  9:10           ` Yanteng Si
2024-03-19 14:18             ` Serge Semin
2024-03-20  9:47               ` Yanteng Si
2024-03-20  9:55               ` Russell King (Oracle)
2024-03-20 10:51                 ` Yanteng Si
2024-02-05  1:11   ` Serge Semin
2024-01-30  8:43 ` [PATCH net-next v8 02/11] net: stmmac: dwmac-loongson: Refactor code for loongson_dwmac_probe() Yanteng Si
2024-02-02 12:33   ` Simon Horman
2024-02-04  8:47     ` Yanteng Si
2024-02-05 14:43   ` Serge Semin
2024-04-05 11:13     ` Yanteng Si
2024-01-30  8:43 ` [PATCH net-next v8 03/11] net: stmmac: dwmac-loongson: Add full PCI support Yanteng Si
2024-02-05 16:49   ` Serge Semin
2024-02-21 10:08     ` Yanteng Si
2024-01-30  8:43 ` [PATCH net-next v8 04/11] net: stmmac: dwmac-loongson: Move irq config to loongson_gmac_config Yanteng Si
2024-02-05 17:01   ` Serge Semin
2024-03-13  8:14     ` Yanteng Si
2024-03-19 13:43       ` Serge Semin
2024-03-20 10:12         ` Yanteng Si
2024-01-30  8:48 ` [PATCH net-next v8 05/11] net: stmmac: dwmac-loongson: Add Loongson-specific register definitions Yanteng Si
2024-02-05 18:17   ` Serge Semin
2024-02-22 13:39     ` Yanteng Si
2024-02-22 13:59       ` Serge Semin
2024-02-23  8:16         ` Yanteng Si
2024-02-23 18:50           ` Serge Semin
2024-03-07 13:15             ` Yanteng Si
2024-03-07 13:44               ` Serge Semin
2024-03-08  4:05                 ` Yanteng Si
2024-01-30  8:48 ` [PATCH net-next v8 06/11] net: stmmac: dwmac-loongson: Add GNET support Yanteng Si
2024-02-05 20:58   ` Serge Semin
     [not found]     ` <d0e56c9b-9549-4061-8e44-2504b6b96897@loongson.cn>
2024-03-14 13:12       ` Yanteng Si
2024-03-19 15:03         ` Serge Semin
2024-03-20 10:23           ` Yanteng Si
2024-03-20 12:18             ` Serge Semin
2024-03-21  9:13           ` Yanteng Si
2024-03-21 14:55             ` Andrew Lunn
2024-03-28 11:41               ` Yanteng Si
2024-03-22 19:09             ` Serge Semin
2024-01-30  8:48 ` [PATCH net-next v8 07/11] net: stmmac: dwmac-loongson: Add multi-channel supports for loongson Yanteng Si
2024-02-05 21:28   ` Serge Semin
     [not found]     ` <e1c7b5fa-f3f8-4aa3-af4d-ca72b54d9c8c@loongson.cn>
2024-03-14 13:13       ` Yanteng Si
2024-03-19 15:53         ` Serge Semin
2024-03-22 10:36           ` Yanteng Si
2024-03-22 18:47             ` Serge Semin
2024-04-03  8:09               ` Yanteng Si
2024-04-03 12:03                 ` Serge Semin
2024-04-05 10:17                   ` Yanteng Si
2024-04-03  8:23           ` Yanteng Si
2024-01-30  8:48 ` [PATCH net-next v8 08/11] net: stmmac: dwmac-loongson: Fix MAC speed for GNET Yanteng Si
2024-02-05 21:55   ` Serge Semin
     [not found]     ` <4873ea5a-1b23-4512-b039-0a9198b53adf@loongson.cn>
2024-03-14 13:18       ` Yanteng Si
2024-03-19 17:02         ` Serge Semin
2024-03-20 10:42           ` Yanteng Si
2024-03-21  9:29           ` Yanteng Si
2024-03-21 15:02             ` Andrew Lunn
2024-03-21 15:19               ` Russell King (Oracle)
2024-03-21 15:38                 ` Andrew Lunn
2024-03-26 12:32                   ` Yanteng Si
2024-03-26 12:02               ` Yanteng Si
2024-03-26 12:21                 ` Andrew Lunn
2024-03-27  2:41                   ` Yanteng Si
2024-03-27 12:47                     ` Andrew Lunn
2024-03-28 10:08                       ` Yanteng Si
2024-01-30  8:49 ` [PATCH net-next v8 09/11] net: stmmac: dwmac-loongson: Fix half duplex Yanteng Si
2024-02-05 21:58   ` Serge Semin
2024-02-05 22:06     ` Serge Semin
2024-03-13  9:24       ` Yanteng Si
2024-03-13 10:21         ` Russell King (Oracle)
2024-03-14 13:08           ` Yanteng Si
2024-03-20 10:10             ` Serge Semin
2024-03-20 10:37               ` Russell King (Oracle)
2024-03-20 12:50                 ` Russell King (Oracle)
2024-03-20 14:22                   ` Russell King (Oracle)
2024-03-22 18:07                 ` Serge Semin
2024-03-22 19:56                   ` Russell King (Oracle)
2024-04-03 12:37                     ` Serge Semin
2024-04-05 10:48                       ` Yanteng Si
2024-01-30  8:49 ` [PATCH net-next v8 10/11] net: stmmac: dwmac-loongson: Disable flow control for GMAC Yanteng Si
2024-02-05 22:13   ` Serge Semin
2024-03-13  9:25     ` Yanteng Si
2024-01-30  8:49 ` [PATCH net-next v8 11/11] net: stmmac: dwmac-loongson: Disable coe for some Loongson GNET Yanteng Si
2024-02-05 22:18   ` Serge Semin
2024-03-13  9:52     ` Yanteng Si
2024-03-13 10:19       ` Yanteng Si
2024-03-20 11:24         ` Serge Semin
2024-01-30  9:57 ` [PATCH net-next v8 00/11] stmmac: Add Loongson platform support Serge Semin
2024-01-31  2:10 ` Jakub Kicinski
2024-01-31  9:20   ` Yanteng Si

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.