netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net-next v7 0/9] stmmac: Add Loongson platform support
@ 2023-12-19 14:17 Yanteng Si
  2023-12-19 14:17 ` [PATCH net-next v7 1/9] net: stmmac: Pass stmmac_priv and chan in some callbacks Yanteng Si
                   ` (8 more replies)
  0 siblings, 9 replies; 48+ messages in thread
From: Yanteng Si @ 2023-12-19 14:17 UTC (permalink / raw)
  To: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu
  Cc: Yanteng Si, fancer.lancer, Jose.Abreu, chenhuacai, linux,
	guyinggang, netdev, chris.chenfeiyang

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	/* Normal Loongson Tx/Rx Summary */
     #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 (9):
  net: stmmac: Pass stmmac_priv and chan in some callbacks
  net: stmmac: dwmac-loongson: Refactor code for loongson_dwmac_probe()
  net: stmmac: dwmac-loongson: Add full PCI support
  net: stmmac: Add multi-channel supports
  net: stmmac: Add Loongson-specific register definitions
  net: stmmac: dwmac-loongson: Add MSI support
  net: stmmac: dwmac-loongson: Add GNET support
  net: stmmac: dwmac-loongson: Disable flow control for GMAC
  net: stmmac: Disable coe for some Loongson GNET

 drivers/net/ethernet/stmicro/stmmac/common.h  |   1 +
 .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 296 ++++++++++++++----
 .../net/ethernet/stmicro/stmmac/dwmac-sun8i.c |   2 +-
 .../ethernet/stmicro/stmmac/dwmac1000_dma.c   |  61 +++-
 .../ethernet/stmicro/stmmac/dwmac100_dma.c    |   2 +-
 .../net/ethernet/stmicro/stmmac/dwmac4_dma.c  |   2 +-
 .../net/ethernet/stmicro/stmmac/dwmac_dma.h   |  55 +++-
 .../net/ethernet/stmicro/stmmac/dwmac_lib.c   |  68 ++--
 .../ethernet/stmicro/stmmac/dwxgmac2_dma.c    |   2 +-
 drivers/net/ethernet/stmicro/stmmac/hwif.c    |   8 +-
 drivers/net/ethernet/stmicro/stmmac/hwif.h    |  11 +-
 .../ethernet/stmicro/stmmac/stmmac_ethtool.c  |   6 +
 .../net/ethernet/stmicro/stmmac/stmmac_main.c |  13 +-
 include/linux/stmmac.h                        |   4 +
 14 files changed, 424 insertions(+), 107 deletions(-)

-- 
2.31.4


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

* [PATCH net-next v7 1/9] net: stmmac: Pass stmmac_priv and chan in some callbacks
  2023-12-19 14:17 [PATCH net-next v7 0/9] stmmac: Add Loongson platform support Yanteng Si
@ 2023-12-19 14:17 ` Yanteng Si
  2023-12-20 15:08   ` Simon Horman
  2023-12-20 18:18   ` Serge Semin
  2023-12-19 14:17 ` [PATCH net-next v7 2/9] net: stmmac: dwmac-loongson: Refactor code for loongson_dwmac_probe() Yanteng Si
                   ` (7 subsequent siblings)
  8 siblings, 2 replies; 48+ messages in thread
From: Yanteng Si @ 2023-12-19 14:17 UTC (permalink / raw)
  To: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu
  Cc: Yanteng Si, fancer.lancer, Jose.Abreu, chenhuacai, linux,
	guyinggang, netdev, chris.chenfeiyang

Loongson GMAC and GNET have some special features. To prepare for that,
pass stmmac_priv and chan to more callbacks, and adjust the callbacks
accordingly.

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-sun8i.c   |  2 +-
 drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c |  2 +-
 drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c  |  2 +-
 drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c    |  2 +-
 drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h     |  3 ++-
 drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c     |  3 ++-
 drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c  |  2 +-
 drivers/net/ethernet/stmicro/stmmac/hwif.h          | 11 ++++++-----
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c   |  6 +++---
 9 files changed, 18 insertions(+), 15 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..5e80d3eec9db 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
@@ -70,7 +70,7 @@ 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,
+static void dwmac1000_dma_init(struct stmmac_priv *priv, void __iomem *ioaddr,
 			       struct stmmac_dma_cfg *dma_cfg, int atds)
 {
 	u32 value = readl(ioaddr + DMA_BUS_MODE);
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
index dea270f60cc3..105e7d4d798f 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
@@ -18,7 +18,7 @@
 #include "dwmac100.h"
 #include "dwmac_dma.h"
 
-static void dwmac100_dma_init(void __iomem *ioaddr,
+static void dwmac100_dma_init(struct stmmac_priv *priv, void __iomem *ioaddr,
 			      struct stmmac_dma_cfg *dma_cfg, int atds)
 {
 	/* Enable Application Access by writing to DMA CSR0 */
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
index 84d3a8551b03..dc54c4e793fd 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
@@ -152,7 +152,7 @@ static void dwmac410_dma_init_channel(struct stmmac_priv *priv,
 	       ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
 }
 
-static void dwmac4_dma_init(void __iomem *ioaddr,
+static void dwmac4_dma_init(struct stmmac_priv *priv, void __iomem *ioaddr,
 			    struct stmmac_dma_cfg *dma_cfg, int atds)
 {
 	u32 value = readl(ioaddr + DMA_SYS_BUS_MODE);
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
index 72672391675f..e7aef136824b 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
@@ -152,7 +152,8 @@
 #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(struct stmmac_priv *priv,
+				   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,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
index 7907d62d3437..2f0df16fb7e4 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
@@ -28,7 +28,8 @@ 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(struct stmmac_priv *priv,
+				   void __iomem *ioaddr, u32 chan)
 {
 	writel(1, ioaddr + DMA_XMT_POLL_DEMAND);
 }
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
index 3cde695fec91..a06f9573876f 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
@@ -19,7 +19,7 @@ static int dwxgmac2_dma_reset(void __iomem *ioaddr)
 				  !(value & XGMAC_SWR), 0, 100000);
 }
 
-static void dwxgmac2_dma_init(void __iomem *ioaddr,
+static void dwxgmac2_dma_init(struct stmmac_priv *priv, void __iomem *ioaddr,
 			      struct stmmac_dma_cfg *dma_cfg, int atds)
 {
 	u32 value = readl(ioaddr + XGMAC_DMA_SYSBUS_MODE);
diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h
index 7be04b54738b..a44aa3671fb8 100644
--- a/drivers/net/ethernet/stmicro/stmmac/hwif.h
+++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h
@@ -175,8 +175,8 @@ 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)(struct stmmac_priv *priv, 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);
 	void (*init_rx_chan)(struct stmmac_priv *priv, void __iomem *ioaddr,
@@ -198,7 +198,8 @@ 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)(struct stmmac_priv *priv,
+					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,
@@ -240,7 +241,7 @@ struct stmmac_dma_ops {
 };
 
 #define stmmac_dma_init(__priv, __args...) \
-	stmmac_do_void_callback(__priv, dma, init, __args)
+	stmmac_do_void_callback(__priv, dma, init, __priv, __args)
 #define stmmac_init_chan(__priv, __args...) \
 	stmmac_do_void_callback(__priv, dma, init_chan, __priv, __args)
 #define stmmac_init_rx_chan(__priv, __args...) \
@@ -258,7 +259,7 @@ struct stmmac_dma_ops {
 #define stmmac_dma_diagnostic_fr(__priv, __args...) \
 	stmmac_do_void_callback(__priv, dma, dma_diagnostic_fr, __args)
 #define stmmac_enable_dma_transmission(__priv, __args...) \
-	stmmac_do_void_callback(__priv, dma, enable_dma_transmission, __args)
+	stmmac_do_void_callback(__priv, dma, enable_dma_transmission, __priv, __args)
 #define stmmac_enable_dma_irq(__priv, __args...) \
 	stmmac_do_void_callback(__priv, dma, enable_dma_irq, __priv, __args)
 #define stmmac_disable_dma_irq(__priv, __args...) \
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 47de466e432c..d868eb8dafc5 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);
@@ -4679,7 +4679,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);
@@ -4899,7 +4899,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] 48+ messages in thread

* [PATCH net-next v7 2/9] net: stmmac: dwmac-loongson: Refactor code for loongson_dwmac_probe()
  2023-12-19 14:17 [PATCH net-next v7 0/9] stmmac: Add Loongson platform support Yanteng Si
  2023-12-19 14:17 ` [PATCH net-next v7 1/9] net: stmmac: Pass stmmac_priv and chan in some callbacks Yanteng Si
@ 2023-12-19 14:17 ` Yanteng Si
  2024-01-02 10:37   ` Russell King (Oracle)
  2023-12-19 14:17 ` [PATCH net-next v7 3/9] net: stmmac: dwmac-loongson: Add full PCI support Yanteng Si
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 48+ messages in thread
From: Yanteng Si @ 2023-12-19 14:17 UTC (permalink / raw)
  To: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu
  Cc: Yanteng Si, fancer.lancer, Jose.Abreu, chenhuacai, linux,
	guyinggang, netdev, chris.chenfeiyang

Add a setup() function to initialize data, and simplify code for
loongson_dwmac_probe().

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  | 68 +++++++++++++------
 1 file changed, 47 insertions(+), 21 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
index 9e40c28d453a..56d1fd8c61e1 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,38 @@ 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->phy_interface = PHY_INTERFACE_MODE_RGMII_ID;
 
 	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,22 +89,22 @@ 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) {
-		dev_err(&pdev->dev, "%s: ERROR: failed to enable device\n", __func__);
+		dev_err(&pdev->dev, "%s: ERROR: failed to enable device\n",
+			__func__);
 		goto err_put_node;
 	}
 
@@ -98,9 +118,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 +137,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];
@@ -128,7 +151,8 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
 
 	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");
+		dev_info(&pdev->dev,
+			 "IRQ eth_wake_irq not found, using macirq\n");
 		res.wol_irq = res.irq;
 	}
 
@@ -212,8 +236,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] 48+ messages in thread

* [PATCH net-next v7 3/9] net: stmmac: dwmac-loongson: Add full PCI support
  2023-12-19 14:17 [PATCH net-next v7 0/9] stmmac: Add Loongson platform support Yanteng Si
  2023-12-19 14:17 ` [PATCH net-next v7 1/9] net: stmmac: Pass stmmac_priv and chan in some callbacks Yanteng Si
  2023-12-19 14:17 ` [PATCH net-next v7 2/9] net: stmmac: dwmac-loongson: Refactor code for loongson_dwmac_probe() Yanteng Si
@ 2023-12-19 14:17 ` Yanteng Si
  2024-01-02 10:40   ` Russell King (Oracle)
  2023-12-19 14:17 ` [PATCH net-next v7 4/9] net: stmmac: Add multi-channel supports Yanteng Si
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 48+ messages in thread
From: Yanteng Si @ 2023-12-19 14:17 UTC (permalink / raw)
  To: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu
  Cc: Yanteng Si, fancer.lancer, 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, 43 insertions(+), 36 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
index 56d1fd8c61e1..0d79104d7fd3 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;
@@ -56,6 +60,9 @@ static int loongson_gmac_data(struct pci_dev *pdev,
 	plat->dma_cfg->pbl = 32;
 	plat->dma_cfg->pblx8 = true;
 
+	plat->clk_ref_rate = 125000000;
+	plat->clk_ptp_rate = 125000000;
+
 	return 0;
 }
 
@@ -72,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;
@@ -94,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");
@@ -125,42 +126,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] 48+ messages in thread

* [PATCH net-next v7 4/9] net: stmmac: Add multi-channel supports
  2023-12-19 14:17 [PATCH net-next v7 0/9] stmmac: Add Loongson platform support Yanteng Si
                   ` (2 preceding siblings ...)
  2023-12-19 14:17 ` [PATCH net-next v7 3/9] net: stmmac: dwmac-loongson: Add full PCI support Yanteng Si
@ 2023-12-19 14:17 ` Yanteng Si
  2023-12-20 22:36   ` Serge Semin
  2023-12-19 14:26 ` [PATCH net-next v7 5/9] net: stmmac: Add Loongson-specific register definitions Yanteng Si
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 48+ messages in thread
From: Yanteng Si @ 2023-12-19 14:17 UTC (permalink / raw)
  To: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu
  Cc: Yanteng Si, fancer.lancer, Jose.Abreu, chenhuacai, linux,
	guyinggang, netdev, chris.chenfeiyang

Loongson platforms use a DWGMAC which supports multi-channel.

Added dwmac1000_dma_init_channel() and init_chan(), factor out
all the channel-specific setups from dwmac1000_dma_init() to the
new function dma_config(), then distinguish dma initialization
and multi-channel initialization through different parameters.

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/dwmac1000_dma.c   | 55 ++++++++++++++-----
 .../net/ethernet/stmicro/stmmac/dwmac_dma.h   | 17 ++++++
 .../net/ethernet/stmicro/stmmac/dwmac_lib.c   | 30 +++++-----
 3 files changed, 74 insertions(+), 28 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
index 5e80d3eec9db..0fb48e683970 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
@@ -12,7 +12,8 @@
   Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
 *******************************************************************************/
 
-#include <asm/io.h>
+#include <linux/io.h>
+#include "stmmac.h"
 #include "dwmac1000.h"
 #include "dwmac_dma.h"
 
@@ -70,13 +71,16 @@ static void dwmac1000_dma_axi(void __iomem *ioaddr, struct stmmac_axi *axi)
 	writel(value, ioaddr + DMA_AXI_BUS_MODE);
 }
 
-static void dwmac1000_dma_init(struct stmmac_priv *priv, void __iomem *ioaddr,
-			       struct stmmac_dma_cfg *dma_cfg, int atds)
+static void dma_config(void __iomem *modeaddr, void __iomem *enaddr,
+					   struct stmmac_dma_cfg *dma_cfg, u32 dma_intr_mask,
+					   int atds)
 {
-	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;
 
+	value = readl(modeaddr);
+
 	/*
 	 * Set the DMA PBL (Programmable Burst Length) mode.
 	 *
@@ -104,10 +108,34 @@ static void dwmac1000_dma_init(struct stmmac_priv *priv, void __iomem *ioaddr,
 	if (dma_cfg->aal)
 		value |= DMA_BUS_MODE_AAL;
 
-	writel(value, ioaddr + DMA_BUS_MODE);
+	writel(value, modeaddr);
+	writel(dma_intr_mask, enaddr);
+}
+
+static void dwmac1000_dma_init(struct stmmac_priv *priv, void __iomem *ioaddr,
+							   struct stmmac_dma_cfg *dma_cfg, int atds)
+{
+	u32 dma_intr_mask;
 
 	/* Mask interrupts by writing to CSR7 */
-	writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_INTR_ENA);
+	dma_intr_mask = DMA_INTR_DEFAULT_MASK;
+
+	dma_config(ioaddr + DMA_BUS_MODE, ioaddr + DMA_INTR_ENA,
+			  dma_cfg, dma_intr_mask, atds);
+}
+
+static void dwmac1000_dma_init_channel(struct stmmac_priv *priv, void __iomem *ioaddr,
+									   struct stmmac_dma_cfg *dma_cfg, u32 chan)
+{
+	u32 dma_intr_mask;
+
+	/* Mask interrupts by writing to CSR7 */
+	dma_intr_mask = DMA_INTR_DEFAULT_MASK;
+
+	if (dma_cfg->multi_msi_en)
+		dma_config(ioaddr + DMA_CHAN_BUS_MODE(chan),
+					ioaddr + DMA_CHAN_INTR_ENA(chan), dma_cfg,
+					dma_intr_mask, dma_cfg->multi_msi_en);
 }
 
 static void dwmac1000_dma_init_rx(struct stmmac_priv *priv,
@@ -116,7 +144,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 +153,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 +181,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 +203,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 +237,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 +299,13 @@ 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 e7aef136824b..395d5e4c3922 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
@@ -148,6 +148,9 @@
 					 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
@@ -170,4 +173,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 2f0df16fb7e4..968801c694e9 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
@@ -31,63 +31,63 @@ int dwmac_dma_reset(void __iomem *ioaddr)
 void dwmac_enable_dma_transmission(struct stmmac_priv *priv,
 				   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
@@ -167,7 +167,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 */
@@ -237,7 +237,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;
 }
-- 
2.31.4


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

* [PATCH net-next v7 5/9] net: stmmac: Add Loongson-specific register definitions
  2023-12-19 14:17 [PATCH net-next v7 0/9] stmmac: Add Loongson platform support Yanteng Si
                   ` (3 preceding siblings ...)
  2023-12-19 14:17 ` [PATCH net-next v7 4/9] net: stmmac: Add multi-channel supports Yanteng Si
@ 2023-12-19 14:26 ` Yanteng Si
  2023-12-21  2:14   ` Serge Semin
  2023-12-19 14:26 ` [PATCH net-next v7 6/9] net: stmmac: dwmac-loongson: Add MSI support Yanteng Si
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 48+ messages in thread
From: Yanteng Si @ 2023-12-19 14:26 UTC (permalink / raw)
  To: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu
  Cc: Yanteng Si, fancer.lancer, 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.

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/common.h  |  1 +
 .../ethernet/stmicro/stmmac/dwmac-loongson.c  |  2 ++
 .../ethernet/stmicro/stmmac/dwmac1000_dma.c   | 10 ++++--
 .../net/ethernet/stmicro/stmmac/dwmac_dma.h   | 35 +++++++++++++++++++
 .../net/ethernet/stmicro/stmmac/dwmac_lib.c   | 35 +++++++++++++++----
 drivers/net/ethernet/stmicro/stmmac/hwif.c    |  3 +-
 .../net/ethernet/stmicro/stmmac/stmmac_main.c |  1 +
 include/linux/stmmac.h                        |  1 +
 8 files changed, 78 insertions(+), 10 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index 721c1f8e892f..48ab21243b26 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -34,6 +34,7 @@
 #define DWMAC_CORE_5_00		0x50
 #define DWMAC_CORE_5_10		0x51
 #define DWMAC_CORE_5_20		0x52
+#define DWLGMAC_CORE_1_00	0x10
 #define DWXGMAC_CORE_2_10	0x21
 #define DWXGMAC_CORE_2_20	0x22
 #define DWXLGMAC_CORE_2_00	0x20
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
index 0d79104d7fd3..fb7506bbc21b 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
@@ -101,6 +101,8 @@ static int loongson_dwmac_probe(struct pci_dev *pdev,
 		plat->mdio_bus_data->needs_reset = true;
 	}
 
+	plat->flags |= STMMAC_FLAG_HAS_LGMAC;
+
 	/* Enable pci device */
 	ret = pci_enable_device(pdev);
 	if (ret) {
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
index 0fb48e683970..a01fe6b7540a 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
@@ -118,7 +118,10 @@ static void dwmac1000_dma_init(struct stmmac_priv *priv, void __iomem *ioaddr,
 	u32 dma_intr_mask;
 
 	/* Mask interrupts by writing to CSR7 */
-	dma_intr_mask = DMA_INTR_DEFAULT_MASK;
+	if (priv->plat->flags & STMMAC_FLAG_HAS_LGMAC)
+		dma_intr_mask = DMA_INTR_DEFAULT_MASK_LOONGSON;
+	else
+		dma_intr_mask = DMA_INTR_DEFAULT_MASK;
 
 	dma_config(ioaddr + DMA_BUS_MODE, ioaddr + DMA_INTR_ENA,
 			  dma_cfg, dma_intr_mask, atds);
@@ -130,7 +133,10 @@ static void dwmac1000_dma_init_channel(struct stmmac_priv *priv, void __iomem *i
 	u32 dma_intr_mask;
 
 	/* Mask interrupts by writing to CSR7 */
-	dma_intr_mask = DMA_INTR_DEFAULT_MASK;
+	if (priv->plat->flags & STMMAC_FLAG_HAS_LGMAC)
+		dma_intr_mask = DMA_INTR_DEFAULT_MASK_LOONGSON;
+	else
+		dma_intr_mask = DMA_INTR_DEFAULT_MASK;
 
 	if (dma_cfg->multi_msi_en)
 		dma_config(ioaddr + DMA_CHAN_BUS_MODE(chan),
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
index 395d5e4c3922..7d33798c0e72 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
@@ -70,16 +70,23 @@
 #define DMA_CONTROL_SR		0x00000002	/* Start/Stop Receive */
 
 /* DMA Normal interrupt */
+#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_ENA_NIE 0x00010000	/* Normal Summary */
 #define DMA_INTR_ENA_TIE 0x00000001	/* Transmit Interrupt */
 #define DMA_INTR_ENA_TUE 0x00000004	/* Transmit Buffer Unavailable */
 #define DMA_INTR_ENA_RIE 0x00000040	/* Receive Interrupt */
 #define DMA_INTR_ENA_ERE 0x00004000	/* Early Receive */
 
+#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_NORMAL	(DMA_INTR_ENA_NIE | DMA_INTR_ENA_RIE | \
 			DMA_INTR_ENA_TIE)
 
 /* DMA Abnormal interrupt */
+#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_ENA_AIE 0x00008000	/* Abnormal Summary */
 #define DMA_INTR_ENA_FBE 0x00002000	/* Fatal Bus Error */
 #define DMA_INTR_ENA_ETE 0x00000400	/* Early Transmit */
@@ -91,10 +98,14 @@
 #define DMA_INTR_ENA_TJE 0x00000008	/* Transmit Jabber */
 #define DMA_INTR_ENA_TSE 0x00000002	/* Transmit Stopped */
 
+#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_ABNORMAL	(DMA_INTR_ENA_AIE | DMA_INTR_ENA_FBE | \
 				DMA_INTR_ENA_UNE)
 
 /* DMA default interrupt mask */
+#define DMA_INTR_DEFAULT_MASK_LOONGSON	(DMA_INTR_NORMAL_LOONGSON | DMA_INTR_ABNORMAL_LOONGSON)
 #define DMA_INTR_DEFAULT_MASK	(DMA_INTR_NORMAL | DMA_INTR_ABNORMAL)
 #define DMA_INTR_DEFAULT_RX	(DMA_INTR_ENA_RIE)
 #define DMA_INTR_DEFAULT_TX	(DMA_INTR_ENA_TIE)
@@ -111,9 +122,15 @@
 #define DMA_STATUS_TS_SHIFT	20
 #define DMA_STATUS_RS_MASK	0x000e0000	/* Receive Process State */
 #define DMA_STATUS_RS_SHIFT	17
+#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_NIS	0x00010000	/* Normal 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_AIS	0x00008000	/* Abnormal Interrupt Summary */
 #define DMA_STATUS_ERI	0x00004000	/* Early Receive Interrupt */
+#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_FBI	0x00002000	/* Fatal Bus Error Interrupt */
 #define DMA_STATUS_ETI	0x00000400	/* Early Transmit Interrupt */
 #define DMA_STATUS_RWT	0x00000200	/* Receive Watchdog Timeout */
@@ -128,10 +145,21 @@
 #define DMA_STATUS_TI	0x00000001	/* Transmit Interrupt */
 #define DMA_CONTROL_FTF		0x00100000	/* Flush transmit FIFO */
 
+#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_COMMON		(DMA_STATUS_NIS | \
 					 DMA_STATUS_AIS | \
 					 DMA_STATUS_FBI)
 
+#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_RX		(DMA_STATUS_ERI | \
 					 DMA_STATUS_RWT | \
 					 DMA_STATUS_RPS | \
@@ -140,6 +168,13 @@
 					 DMA_STATUS_OVF | \
 					 DMA_STATUS_MSK_COMMON)
 
+#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)
 #define DMA_STATUS_MSK_TX		(DMA_STATUS_ETI | \
 					 DMA_STATUS_UNF | \
 					 DMA_STATUS_TJT | \
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
index 968801c694e9..a6e2ab4d0f4a 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
@@ -167,6 +167,9 @@ 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 nor_intr_status;
+	u32 abnor_intr_status;
+	u32 fb_intr_status;
 	u32 intr_status = readl(ioaddr + DMA_CHAN_STATUS(chan));
 
 #ifdef DWMAC_DMA_DEBUG
@@ -176,13 +179,31 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
 	show_rx_process_state(intr_status);
 #endif
 
-	if (dir == DMA_DIR_RX)
-		intr_status &= DMA_STATUS_MSK_RX;
-	else if (dir == DMA_DIR_TX)
-		intr_status &= DMA_STATUS_MSK_TX;
+	if (priv->plat->flags & STMMAC_FLAG_HAS_LGMAC) {
+		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);
+	} else {
+		if (dir == DMA_DIR_RX)
+			intr_status &= DMA_STATUS_MSK_RX;
+		else if (dir == DMA_DIR_TX)
+			intr_status &= DMA_STATUS_MSK_TX;
+
+		nor_intr_status = intr_status & DMA_STATUS_NIS;
+		abnor_intr_status = intr_status & DMA_STATUS_AIS;
+		fb_intr_status = intr_status & DMA_STATUS_FBI;
+	}
 
 	/* ABNORMAL interrupts */
-	if (unlikely(intr_status & DMA_STATUS_AIS)) {
+	if (unlikely(abnor_intr_status)) {
 		if (unlikely(intr_status & DMA_STATUS_UNF)) {
 			ret = tx_hard_error_bump_tc;
 			x->tx_undeflow_irq++;
@@ -205,13 +226,13 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
 			x->tx_process_stopped_irq++;
 			ret = tx_hard_error;
 		}
-		if (unlikely(intr_status & DMA_STATUS_FBI)) {
+		if (unlikely(intr_status & fb_intr_status)) {
 			x->fatal_bus_error_irq++;
 			ret = tx_hard_error;
 		}
 	}
 	/* TX/RX NORMAL interrupts */
-	if (likely(intr_status & DMA_STATUS_NIS)) {
+	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. */
diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.c b/drivers/net/ethernet/stmicro/stmmac/hwif.c
index 1bd34b2a47e8..3724cf698de6 100644
--- a/drivers/net/ethernet/stmicro/stmmac/hwif.c
+++ b/drivers/net/ethernet/stmicro/stmmac/hwif.c
@@ -59,7 +59,8 @@ static int stmmac_dwmac1_quirks(struct stmmac_priv *priv)
 		dev_info(priv->device, "Enhanced/Alternate descriptors\n");
 
 		/* GMAC older than 3.50 has no extended descriptors */
-		if (priv->synopsys_id >= DWMAC_CORE_3_50) {
+		if (priv->synopsys_id >= DWMAC_CORE_3_50 ||
+		    priv->synopsys_id == DWLGMAC_CORE_1_00) {
 			dev_info(priv->device, "Enabled extended descriptors\n");
 			priv->extend_desc = 1;
 		} else {
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index d868eb8dafc5..9764d2ab7e46 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -7218,6 +7218,7 @@ static int stmmac_hw_init(struct stmmac_priv *priv)
 	 * riwt_off field from the platform.
 	 */
 	if (((priv->synopsys_id >= DWMAC_CORE_3_50) ||
+		(priv->synopsys_id == DWLGMAC_CORE_1_00) ||
 	    (priv->plat->has_xgmac)) && (!priv->plat->riwt_off)) {
 		priv->use_riwt = 1;
 		dev_info(priv->device,
diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
index dee5ad6e48c5..f07f79d50b06 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_HAS_LGMAC			BIT(13)
 
 struct plat_stmmacenet_data {
 	int bus_id;
-- 
2.31.4


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

* [PATCH net-next v7 6/9] net: stmmac: dwmac-loongson: Add MSI support
  2023-12-19 14:17 [PATCH net-next v7 0/9] stmmac: Add Loongson platform support Yanteng Si
                   ` (4 preceding siblings ...)
  2023-12-19 14:26 ` [PATCH net-next v7 5/9] net: stmmac: Add Loongson-specific register definitions Yanteng Si
@ 2023-12-19 14:26 ` Yanteng Si
  2023-12-19 14:26 ` [PATCH net-next v7 7/9] net: stmmac: dwmac-loongson: Add GNET support Yanteng Si
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 48+ messages in thread
From: Yanteng Si @ 2023-12-19 14:26 UTC (permalink / raw)
  To: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu
  Cc: Yanteng Si, fancer.lancer, 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  | 132 ++++++++++++++----
 1 file changed, 102 insertions(+), 30 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
index fb7506bbc21b..2c08d5495214 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
@@ -11,8 +11,85 @@
 
 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 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)
 {
@@ -66,8 +143,29 @@ 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;
+	u32 version = readl(res->addr + GMAC_VERSION);
+
+	switch (version & 0xff) {
+	case DWLGMAC_CORE_1_00:
+		ret = loongson_dwmac_config_multi_msi(pdev, plat, res, np, 8);
+		break;
+	default:
+		ret = loongson_dwmac_config_legacy(pdev, plat, res, np);
+		break;
+	}
+
+	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,
@@ -142,44 +240,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:
@@ -203,7 +276,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] 48+ messages in thread

* [PATCH net-next v7 7/9] net: stmmac: dwmac-loongson: Add GNET support
  2023-12-19 14:17 [PATCH net-next v7 0/9] stmmac: Add Loongson platform support Yanteng Si
                   ` (5 preceding siblings ...)
  2023-12-19 14:26 ` [PATCH net-next v7 6/9] net: stmmac: dwmac-loongson: Add MSI support Yanteng Si
@ 2023-12-19 14:26 ` Yanteng Si
  2023-12-21  2:34   ` Serge Semin
  2023-12-19 14:28 ` [PATCH net-next v7 8/9] net: stmmac: dwmac-loongson: Disable flow control for GMAC Yanteng Si
  2023-12-19 14:28 ` [PATCH net-next v7 9/9] net: stmmac: Disable coe for some Loongson GNET Yanteng Si
  8 siblings, 1 reply; 48+ messages in thread
From: Yanteng Si @ 2023-12-19 14:26 UTC (permalink / raw)
  To: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu
  Cc: Yanteng Si, fancer.lancer, Jose.Abreu, chenhuacai, linux,
	guyinggang, netdev, chris.chenfeiyang

Add Loongson GNET (GMAC with PHY) support. Current GNET does not support
half duplex mode, and 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  | 79 +++++++++++++++++++
 .../ethernet/stmicro/stmmac/stmmac_ethtool.c  |  6 ++
 include/linux/stmmac.h                        |  2 +
 3 files changed, 87 insertions(+)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
index 2c08d5495214..9e4953c7e4e0 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
@@ -168,6 +168,83 @@ 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 net_device *ndev = dev_get_drvdata(priv);
+	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 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 = 0xfffffffb;
+
+	plat->phy_addr = 2;
+	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;
+
+	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;
+	u32 version = readl(res->addr + GMAC_VERSION);
+
+	switch (version & 0xff) {
+	case DWLGMAC_CORE_1_00:
+		ret = loongson_dwmac_config_multi_msi(pdev, plat, res, np, 8);
+		break;
+	default:
+		ret = loongson_dwmac_config_legacy(pdev, plat, res, np);
+		break;
+	}
+
+	switch (pdev->revision) {
+	case 0x00:
+		plat->flags |=
+			FIELD_PREP(STMMAC_FLAG_DISABLE_HALF_DUPLEX, 1) |
+			FIELD_PREP(STMMAC_FLAG_DISABLE_FORCE_1000, 1);
+		break;
+	case 0x01:
+		plat->flags |=
+			FIELD_PREP(STMMAC_FLAG_DISABLE_HALF_DUPLEX, 1);
+		break;
+	default:
+		break;
+	}
+
+	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)
 {
@@ -318,9 +395,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);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
index 8105ce47c6ad..d6939eb9a0d8 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
@@ -420,6 +420,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 f07f79d50b06..067030cdb60f 100644
--- a/include/linux/stmmac.h
+++ b/include/linux/stmmac.h
@@ -222,6 +222,8 @@ struct dwmac4_addrs {
 #define STMMAC_FLAG_EN_TX_LPI_CLOCKGATING	BIT(11)
 #define STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY	BIT(12)
 #define STMMAC_FLAG_HAS_LGMAC			BIT(13)
+#define STMMAC_FLAG_DISABLE_HALF_DUPLEX	BIT(14)
+#define STMMAC_FLAG_DISABLE_FORCE_1000	BIT(15)
 
 struct plat_stmmacenet_data {
 	int bus_id;
-- 
2.31.4


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

* [PATCH net-next v7 8/9] net: stmmac: dwmac-loongson: Disable flow control for GMAC
  2023-12-19 14:17 [PATCH net-next v7 0/9] stmmac: Add Loongson platform support Yanteng Si
                   ` (6 preceding siblings ...)
  2023-12-19 14:26 ` [PATCH net-next v7 7/9] net: stmmac: dwmac-loongson: Add GNET support Yanteng Si
@ 2023-12-19 14:28 ` Yanteng Si
  2023-12-21  2:35   ` Serge Semin
  2023-12-19 14:28 ` [PATCH net-next v7 9/9] net: stmmac: Disable coe for some Loongson GNET Yanteng Si
  8 siblings, 1 reply; 48+ messages in thread
From: Yanteng Si @ 2023-12-19 14:28 UTC (permalink / raw)
  To: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu
  Cc: Yanteng Si, fancer.lancer, 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 | 2 ++
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c    | 6 +++---
 include/linux/stmmac.h                               | 1 +
 3 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
index 9e4953c7e4e0..77c9bcb66a8e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
@@ -160,6 +160,8 @@ static int loongson_gmac_config(struct pci_dev *pdev,
 		break;
 	}
 
+	plat->flags |= FIELD_PREP(STMMAC_FLAG_DISABLE_FLOW_CONTROL, 1);
+
 	return ret;
 }
 
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 9764d2ab7e46..d94f61742772 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -1236,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_ASYM_PAUSE | MAC_SYM_PAUSE |
-						MAC_10FD | MAC_100FD |
-						MAC_1000FD;
+	priv->phylink_config.mac_capabilities = MAC_10FD | MAC_100FD | MAC_1000FD;
+	if (!FIELD_GET(STMMAC_FLAG_DISABLE_FLOW_CONTROL, priv->plat->flags))
+		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 067030cdb60f..5ece92e4d8c3 100644
--- a/include/linux/stmmac.h
+++ b/include/linux/stmmac.h
@@ -224,6 +224,7 @@ struct dwmac4_addrs {
 #define STMMAC_FLAG_HAS_LGMAC			BIT(13)
 #define STMMAC_FLAG_DISABLE_HALF_DUPLEX	BIT(14)
 #define STMMAC_FLAG_DISABLE_FORCE_1000	BIT(15)
+#define STMMAC_FLAG_DISABLE_FLOW_CONTROL	BIT(16)
 
 struct plat_stmmacenet_data {
 	int bus_id;
-- 
2.31.4


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

* [PATCH net-next v7 9/9] net: stmmac: Disable coe for some Loongson GNET
  2023-12-19 14:17 [PATCH net-next v7 0/9] stmmac: Add Loongson platform support Yanteng Si
                   ` (7 preceding siblings ...)
  2023-12-19 14:28 ` [PATCH net-next v7 8/9] net: stmmac: dwmac-loongson: Disable flow control for GMAC Yanteng Si
@ 2023-12-19 14:28 ` Yanteng Si
  2023-12-21  2:36   ` Serge Semin
  8 siblings, 1 reply; 48+ messages in thread
From: Yanteng Si @ 2023-12-19 14:28 UTC (permalink / raw)
  To: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu
  Cc: Yanteng Si, fancer.lancer, Jose.Abreu, chenhuacai, linux,
	guyinggang, netdev, chris.chenfeiyang

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

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/hwif.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.c b/drivers/net/ethernet/stmicro/stmmac/hwif.c
index 3724cf698de6..f211880925aa 100644
--- a/drivers/net/ethernet/stmicro/stmmac/hwif.c
+++ b/drivers/net/ethernet/stmicro/stmmac/hwif.c
@@ -73,6 +73,11 @@ static int stmmac_dwmac1_quirks(struct stmmac_priv *priv)
 		mac->desc = &ndesc_ops;
 	}
 
+	if (priv->synopsys_id == DWLGMAC_CORE_1_00) {
+		priv->plat->tx_coe = 0;
+		priv->plat->rx_coe = STMMAC_RX_COE_NONE;
+	}
+
 	stmmac_dwmac_mode_quirk(priv);
 	return 0;
 }
-- 
2.31.4


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

* Re: [PATCH net-next v7 1/9] net: stmmac: Pass stmmac_priv and chan in some callbacks
  2023-12-19 14:17 ` [PATCH net-next v7 1/9] net: stmmac: Pass stmmac_priv and chan in some callbacks Yanteng Si
@ 2023-12-20 15:08   ` Simon Horman
  2023-12-21  9:40     ` Yanteng Si
  2023-12-20 18:18   ` Serge Semin
  1 sibling, 1 reply; 48+ messages in thread
From: Simon Horman @ 2023-12-20 15:08 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, Dec 19, 2023 at 10:17:04PM +0800, Yanteng Si wrote:
> Loongson GMAC and GNET have some special features. To prepare for that,
> pass stmmac_priv and chan to more callbacks, and adjust the callbacks
> accordingly.
> 
> 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-sun8i.c   |  2 +-
>  drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c |  2 +-
>  drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c  |  2 +-
>  drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c    |  2 +-
>  drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h     |  3 ++-
>  drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c     |  3 ++-
>  drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c  |  2 +-
>  drivers/net/ethernet/stmicro/stmmac/hwif.h          | 11 ++++++-----
>  drivers/net/ethernet/stmicro/stmmac/stmmac_main.c   |  6 +++---
>  9 files changed, 18 insertions(+), 15 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;
>  

Hi Yanteng Si,

perhaps dwmac-sun8i.c needs to be further updated for this change?

  .../dwmac-sun8i.c:568:10: error: incompatible function pointer types initializing 'void (*)(struct stmmac_priv *, void *, struct stmmac_dma_cfg *, int)' with an expression of type 'void (void *, struct stmmac_dma_cfg *, int)' [-Wincompatible-function-pointer-types]
    568 |         .init = sun8i_dwmac_dma_init,
        |                 ^~~~~~~~~~~~~~~~~~~~
  .../dwmac-sun8i.c:574:29: error: incompatible function pointer types initializing 'void (*)(struct stmmac_priv *, void *, u32)' (aka 'void (*)(struct stmmac_priv *, void *, unsigned int)') with an expression of type 'void (void *, u32)' (aka 'void (void *, unsigned int)') [-Wincompatible-function-pointer-types]
    574 |         .enable_dma_transmission = sun8i_dwmac_enable_dma_transmission,
        |                                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2 errors generated.

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

* Re: [PATCH net-next v7 1/9] net: stmmac: Pass stmmac_priv and chan in some callbacks
  2023-12-19 14:17 ` [PATCH net-next v7 1/9] net: stmmac: Pass stmmac_priv and chan in some callbacks Yanteng Si
  2023-12-20 15:08   ` Simon Horman
@ 2023-12-20 18:18   ` Serge Semin
  2023-12-21 11:50     ` Yanteng Si
  1 sibling, 1 reply; 48+ messages in thread
From: Serge Semin @ 2023-12-20 18:18 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, Dec 19, 2023 at 10:17:04PM +0800, Yanteng Si wrote:
> Loongson GMAC and GNET have some special features. To prepare for that,
> pass stmmac_priv and chan to more callbacks, and adjust the callbacks
> accordingly.
> 
> 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-sun8i.c   |  2 +-
>  drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c |  2 +-
>  drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c  |  2 +-
>  drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c    |  2 +-
>  drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h     |  3 ++-
>  drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c     |  3 ++-
>  drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c  |  2 +-
>  drivers/net/ethernet/stmicro/stmmac/hwif.h          | 11 ++++++-----
>  drivers/net/ethernet/stmicro/stmmac/stmmac_main.c   |  6 +++---
>  9 files changed, 18 insertions(+), 15 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)

As Simon correctly noted this prototype is incomplete. Although AFAICS
you never use a pointer to stmmac_priv in this method. So I guess you
could fix the callback prototype instead.

>  {
>  	u32 v;
>  
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> index daf79cdbd3ec..5e80d3eec9db 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> @@ -70,7 +70,7 @@ 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,
> +static void dwmac1000_dma_init(struct stmmac_priv *priv, void __iomem *ioaddr,
>  			       struct stmmac_dma_cfg *dma_cfg, int atds)
>  {
>  	u32 value = readl(ioaddr + DMA_BUS_MODE);
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
> index dea270f60cc3..105e7d4d798f 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
> @@ -18,7 +18,7 @@
>  #include "dwmac100.h"
>  #include "dwmac_dma.h"
>  
> -static void dwmac100_dma_init(void __iomem *ioaddr,
> +static void dwmac100_dma_init(struct stmmac_priv *priv, void __iomem *ioaddr,
>  			      struct stmmac_dma_cfg *dma_cfg, int atds)
>  {
>  	/* Enable Application Access by writing to DMA CSR0 */
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
> index 84d3a8551b03..dc54c4e793fd 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
> @@ -152,7 +152,7 @@ static void dwmac410_dma_init_channel(struct stmmac_priv *priv,
>  	       ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
>  }
>  
> -static void dwmac4_dma_init(void __iomem *ioaddr,
> +static void dwmac4_dma_init(struct stmmac_priv *priv, void __iomem *ioaddr,
>  			    struct stmmac_dma_cfg *dma_cfg, int atds)
>  {
>  	u32 value = readl(ioaddr + DMA_SYS_BUS_MODE);
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
> index 72672391675f..e7aef136824b 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
> @@ -152,7 +152,8 @@
>  #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(struct stmmac_priv *priv,
> +				   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,
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
> index 7907d62d3437..2f0df16fb7e4 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
> @@ -28,7 +28,8 @@ 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(struct stmmac_priv *priv,
> +				   void __iomem *ioaddr, u32 chan)
>  {
>  	writel(1, ioaddr + DMA_XMT_POLL_DEMAND);
>  }
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
> index 3cde695fec91..a06f9573876f 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
> @@ -19,7 +19,7 @@ static int dwxgmac2_dma_reset(void __iomem *ioaddr)
>  				  !(value & XGMAC_SWR), 0, 100000);
>  }
>  
> -static void dwxgmac2_dma_init(void __iomem *ioaddr,
> +static void dwxgmac2_dma_init(struct stmmac_priv *priv, void __iomem *ioaddr,
>  			      struct stmmac_dma_cfg *dma_cfg, int atds)
>  {
>  	u32 value = readl(ioaddr + XGMAC_DMA_SYSBUS_MODE);
> diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h
> index 7be04b54738b..a44aa3671fb8 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/hwif.h
> +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h
> @@ -175,8 +175,8 @@ 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)(struct stmmac_priv *priv, void __iomem *ioaddr,
> +		     struct stmmac_dma_cfg *dma_cfg, int atds);

There is a good chance this change is also unnecessary. I'll post my
comment about that to Patch 4/9.

>  	void (*init_chan)(struct stmmac_priv *priv, void __iomem *ioaddr,
>  			  struct stmmac_dma_cfg *dma_cfg, u32 chan);
>  	void (*init_rx_chan)(struct stmmac_priv *priv, void __iomem *ioaddr,
> @@ -198,7 +198,8 @@ 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)(struct stmmac_priv *priv,
> +					void __iomem *ioaddr, u32 chan);

Why do you need the pointer to the stmmac_priv structure instance
here? I failed to find a place you using it in the subsequent patches.

* Sigh, just a general note in case if somebody would wish to make
* things a bit more optimised and less complicated. The purpose of the
* enable_dma_transmission() callback is to re-activate the DMA-engine
* - exit from suspension and start poll-demanding the DMA descriptors.
* In QoS GMAC and XGMAC the same is done by updating the Tx tail
* pointer.  It's implemented in stmmac_set_tx_tail_ptr(). So basically
* both stmmac_enable_dma_transmission() and stmmac_set_tx_tail_ptr()
* should be almost always called side-by-side. Alas the current
* generic driver part doesn't do that. If it did in a some common way
* you wouldn't have needed the enable_dma_transmission() update
* because it would have already been updated to accept the
* channel/queue parameter.

-Serge(y)

>  	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,
> @@ -240,7 +241,7 @@ struct stmmac_dma_ops {
>  };
>  
>  #define stmmac_dma_init(__priv, __args...) \
> -	stmmac_do_void_callback(__priv, dma, init, __args)
> +	stmmac_do_void_callback(__priv, dma, init, __priv, __args)
>  #define stmmac_init_chan(__priv, __args...) \
>  	stmmac_do_void_callback(__priv, dma, init_chan, __priv, __args)
>  #define stmmac_init_rx_chan(__priv, __args...) \
> @@ -258,7 +259,7 @@ struct stmmac_dma_ops {
>  #define stmmac_dma_diagnostic_fr(__priv, __args...) \
>  	stmmac_do_void_callback(__priv, dma, dma_diagnostic_fr, __args)
>  #define stmmac_enable_dma_transmission(__priv, __args...) \
> -	stmmac_do_void_callback(__priv, dma, enable_dma_transmission, __args)
> +	stmmac_do_void_callback(__priv, dma, enable_dma_transmission, __priv, __args)
>  #define stmmac_enable_dma_irq(__priv, __args...) \
>  	stmmac_do_void_callback(__priv, dma, enable_dma_irq, __priv, __args)
>  #define stmmac_disable_dma_irq(__priv, __args...) \
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> index 47de466e432c..d868eb8dafc5 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);
> @@ -4679,7 +4679,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);
> @@ -4899,7 +4899,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] 48+ messages in thread

* Re: [PATCH net-next v7 4/9] net: stmmac: Add multi-channel supports
  2023-12-19 14:17 ` [PATCH net-next v7 4/9] net: stmmac: Add multi-channel supports Yanteng Si
@ 2023-12-20 22:36   ` Serge Semin
  2023-12-29 10:33     ` Yanteng Si
  0 siblings, 1 reply; 48+ messages in thread
From: Serge Semin @ 2023-12-20 22:36 UTC (permalink / raw)
  To: Yanteng Si
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

On Tue, Dec 19, 2023 at 10:17:07PM +0800, Yanteng Si wrote:
> Loongson platforms use a DWGMAC which supports multi-channel.
> 
> Added dwmac1000_dma_init_channel() and init_chan(), factor out
> all the channel-specific setups from dwmac1000_dma_init() to the
> new function dma_config(), then distinguish dma initialization
> and multi-channel initialization through different parameters.
> 
> 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/dwmac1000_dma.c   | 55 ++++++++++++++-----
>  .../net/ethernet/stmicro/stmmac/dwmac_dma.h   | 17 ++++++
>  .../net/ethernet/stmicro/stmmac/dwmac_lib.c   | 30 +++++-----
>  3 files changed, 74 insertions(+), 28 deletions(-)
> 
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> index 5e80d3eec9db..0fb48e683970 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> @@ -12,7 +12,8 @@
>    Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
>  *******************************************************************************/
>  
> -#include <asm/io.h>
> +#include <linux/io.h>
> +#include "stmmac.h"
>  #include "dwmac1000.h"
>  #include "dwmac_dma.h"
>  
> @@ -70,13 +71,16 @@ static void dwmac1000_dma_axi(void __iomem *ioaddr, struct stmmac_axi *axi)
>  	writel(value, ioaddr + DMA_AXI_BUS_MODE);
>  }
>  
> -static void dwmac1000_dma_init(struct stmmac_priv *priv, void __iomem *ioaddr,
> -			       struct stmmac_dma_cfg *dma_cfg, int atds)

> +static void dma_config(void __iomem *modeaddr, void __iomem *enaddr,
> +					   struct stmmac_dma_cfg *dma_cfg, u32 dma_intr_mask,
> +					   int atds)

Please make sure the arguments are aligned with the function open
parenthesis taking into account that tabs are of _8_ chars:
Documentation/process/coding-style.rst.

>  {
> -	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;
>  
> +	value = readl(modeaddr);
> +
>  	/*
>  	 * Set the DMA PBL (Programmable Burst Length) mode.
>  	 *
> @@ -104,10 +108,34 @@ static void dwmac1000_dma_init(struct stmmac_priv *priv, void __iomem *ioaddr,
>  	if (dma_cfg->aal)
>  		value |= DMA_BUS_MODE_AAL;
>  
> -	writel(value, ioaddr + DMA_BUS_MODE);
> +	writel(value, modeaddr);
> +	writel(dma_intr_mask, enaddr);
> +}
> +

> +static void dwmac1000_dma_init(struct stmmac_priv *priv, void __iomem *ioaddr,
> +							   struct stmmac_dma_cfg *dma_cfg, int atds)
> +{
> +	u32 dma_intr_mask;
>  
>  	/* Mask interrupts by writing to CSR7 */
> -	writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_INTR_ENA);
> +	dma_intr_mask = DMA_INTR_DEFAULT_MASK;
> +
> +	dma_config(ioaddr + DMA_BUS_MODE, ioaddr + DMA_INTR_ENA,
> +			  dma_cfg, dma_intr_mask, atds);
> +}
> +
> +static void dwmac1000_dma_init_channel(struct stmmac_priv *priv, void __iomem *ioaddr,
> +									   struct stmmac_dma_cfg *dma_cfg, u32 chan)
> +{
> +	u32 dma_intr_mask;
> +
> +	/* Mask interrupts by writing to CSR7 */
> +	dma_intr_mask = DMA_INTR_DEFAULT_MASK;
> +
> +	if (dma_cfg->multi_msi_en)
> +		dma_config(ioaddr + DMA_CHAN_BUS_MODE(chan),
> +					ioaddr + DMA_CHAN_INTR_ENA(chan), dma_cfg,

Why so complicated? stmmac_init_chan() is always supposed to be called
in the same context as stmmac_dma_init() (stmmac_xdp_open() is wrong
in not doing that). Seeing DW GMAC v3.x multi-channels feature is
implemented as multiple sets of the same CSRs (except AV traffic
control CSRs specific to channels 1 and higher which are left unused
here anyway) you can just drop the stmmac_dma_ops.init() callback and
convert dwmac1000_dma_init() to being dwmac1000_dma_init_channel()
with no significant modifications:

< you wouldn't need to have a separate dma_config() method.
< you wouldn't need to check for the dma_cfg->multi_msi_en flag state
since the stmmac_init_chan() method is called for as many times as
there are channels available (at least 1 channel always exists).
< just add atds argument.
< just convert the method to using the chan-dependent CSR macros.

> +					dma_intr_mask, dma_cfg->multi_msi_en);
                                                                ^
              +-------------------------------------------------+
This is wrong + ATDS flag means Alternative Descriptor Size. This flag
enables the 8 dword DMA-descriptors size with some DMA-desc fields
semantics changed (see enh_desc.c and norm_desc.c). It's useful for
PTP Timestamping, VLANs, AV feature, L3/L4 filtering, CSum offload
Type 2 (if any of that available). It has nothing to do with the
separate DMA IRQs. Just convert the stmmac_dma_ops.dma_init() callback
to accepting the atds flag as an additional argument, use it here to
activate the extended descriptor size and make sure the atds flag is
passed to the stmmac_init_chan() method in the respective source code.

>  }
>  
>  static void dwmac1000_dma_init_rx(struct stmmac_priv *priv,
> @@ -116,7 +144,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 +153,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 +181,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 +203,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 +237,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 +299,13 @@ 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,

This could be dropped. See my comment above.

> +	.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 e7aef136824b..395d5e4c3922 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
> @@ -148,6 +148,9 @@
>  					 DMA_STATUS_TI | \
>  					 DMA_STATUS_MSK_COMMON)
>  

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

s/chanels/channels

> +#define DMA_CHAN_OFFSET			0x100

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

> +
>  #define NUM_DWMAC100_DMA_REGS	9
>  #define NUM_DWMAC1000_DMA_REGS	23
>  #define NUM_DWMAC4_DMA_REGS	27
> @@ -170,4 +173,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 2f0df16fb7e4..968801c694e9 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
> @@ -31,63 +31,63 @@ int dwmac_dma_reset(void __iomem *ioaddr)
>  void dwmac_enable_dma_transmission(struct stmmac_priv *priv,
>  				   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
> @@ -167,7 +167,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 */
> @@ -237,7 +237,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));

Em, please explain the mask change. Bits CSR5[17:28] are defined as RO
on a normal DW GMAC. Anyway it seems like the mask changes belongs to
the patch 5/9.


Except the last comment, AFAICS this patch provides a generic DW GMAC
v3.x multi-channel support. Despite of several issues noted above the
change in general looks very good.

-Serge(y)

>  
>  	return ret;
>  }
> -- 
> 2.31.4
> 

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

* Re: [PATCH net-next v7 5/9] net: stmmac: Add Loongson-specific register definitions
  2023-12-19 14:26 ` [PATCH net-next v7 5/9] net: stmmac: Add Loongson-specific register definitions Yanteng Si
@ 2023-12-21  2:14   ` Serge Semin
  2024-01-01  8:31     ` Yanteng Si
  0 siblings, 1 reply; 48+ messages in thread
From: Serge Semin @ 2023-12-21  2:14 UTC (permalink / raw)
  To: Yanteng Si
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

On Tue, Dec 19, 2023 at 10:26:45PM +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.

Thanks for the updated patch. It looks much clearer now. Thanks to
that I came up with a better and less invasive solution. See my last
comment for details.

> 
> 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/common.h  |  1 +
>  .../ethernet/stmicro/stmmac/dwmac-loongson.c  |  2 ++
>  .../ethernet/stmicro/stmmac/dwmac1000_dma.c   | 10 ++++--
>  .../net/ethernet/stmicro/stmmac/dwmac_dma.h   | 35 +++++++++++++++++++
>  .../net/ethernet/stmicro/stmmac/dwmac_lib.c   | 35 +++++++++++++++----
>  drivers/net/ethernet/stmicro/stmmac/hwif.c    |  3 +-
>  .../net/ethernet/stmicro/stmmac/stmmac_main.c |  1 +
>  include/linux/stmmac.h                        |  1 +
>  8 files changed, 78 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
> index 721c1f8e892f..48ab21243b26 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/common.h
> +++ b/drivers/net/ethernet/stmicro/stmmac/common.h
> @@ -34,6 +34,7 @@
>  #define DWMAC_CORE_5_00		0x50
>  #define DWMAC_CORE_5_10		0x51
>  #define DWMAC_CORE_5_20		0x52

> +#define DWLGMAC_CORE_1_00	0x10

This doesn't look correct because these IDs have been defined for the
Synopsys IP-core enumerations. Loongson GNET is definitely based on
some DW GMAC v3.x IP-core, but instead of updating the USERVER field
vendor just overwrote the GMAC_VERSION.SNPSVER field. From that
perspective the correct solution would be to override the
priv->synopsys_id field with a correct IP-core version (0x37?). See my
last comment for details of how to do that.

>  #define DWXGMAC_CORE_2_10	0x21
>  #define DWXGMAC_CORE_2_20	0x22
>  #define DWXLGMAC_CORE_2_00	0x20
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> index 0d79104d7fd3..fb7506bbc21b 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> @@ -101,6 +101,8 @@ static int loongson_dwmac_probe(struct pci_dev *pdev,
>  		plat->mdio_bus_data->needs_reset = true;
>  	}
>  

> +	plat->flags |= STMMAC_FLAG_HAS_LGMAC;
> +

If what I suggest in the last comment is implemented this will be
unnecessary.

>  	/* Enable pci device */
>  	ret = pci_enable_device(pdev);
>  	if (ret) {
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> index 0fb48e683970..a01fe6b7540a 100644

> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c

None of the generic parts (dwmac1000_dma.c, dwmac_dma.h, dwmac_lib.c)
will need to be modified if you implement what I suggest in the last
comment.

> @@ -118,7 +118,10 @@ static void dwmac1000_dma_init(struct stmmac_priv *priv, void __iomem *ioaddr,

See my comment to patch 4/9. This method can be fully dropped in favor
of having the dwmac1000_dma_init_channel() function implemented.

>  	u32 dma_intr_mask;
>  
>  	/* Mask interrupts by writing to CSR7 */
> -	dma_intr_mask = DMA_INTR_DEFAULT_MASK;
> +	if (priv->plat->flags & STMMAC_FLAG_HAS_LGMAC)
> +		dma_intr_mask = DMA_INTR_DEFAULT_MASK_LOONGSON;
> +	else
> +		dma_intr_mask = DMA_INTR_DEFAULT_MASK;
>  
>  	dma_config(ioaddr + DMA_BUS_MODE, ioaddr + DMA_INTR_ENA,
>  			  dma_cfg, dma_intr_mask, atds);
> @@ -130,7 +133,10 @@ static void dwmac1000_dma_init_channel(struct stmmac_priv *priv, void __iomem *i
>  	u32 dma_intr_mask;
>  
>  	/* Mask interrupts by writing to CSR7 */
> -	dma_intr_mask = DMA_INTR_DEFAULT_MASK;
> +	if (priv->plat->flags & STMMAC_FLAG_HAS_LGMAC)
> +		dma_intr_mask = DMA_INTR_DEFAULT_MASK_LOONGSON;
> +	else
> +		dma_intr_mask = DMA_INTR_DEFAULT_MASK;
>  
>  	if (dma_cfg->multi_msi_en)
>  		dma_config(ioaddr + DMA_CHAN_BUS_MODE(chan),
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
> index 395d5e4c3922..7d33798c0e72 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
> @@ -70,16 +70,23 @@
>  #define DMA_CONTROL_SR		0x00000002	/* Start/Stop Receive */
>  
>  /* DMA Normal interrupt */
> +#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_ENA_NIE 0x00010000	/* Normal Summary */
>  #define DMA_INTR_ENA_TIE 0x00000001	/* Transmit Interrupt */
>  #define DMA_INTR_ENA_TUE 0x00000004	/* Transmit Buffer Unavailable */
>  #define DMA_INTR_ENA_RIE 0x00000040	/* Receive Interrupt */
>  #define DMA_INTR_ENA_ERE 0x00004000	/* Early Receive */
>  
> +#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_NORMAL	(DMA_INTR_ENA_NIE | DMA_INTR_ENA_RIE | \
>  			DMA_INTR_ENA_TIE)
>  
>  /* DMA Abnormal interrupt */
> +#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_ENA_AIE 0x00008000	/* Abnormal Summary */
>  #define DMA_INTR_ENA_FBE 0x00002000	/* Fatal Bus Error */
>  #define DMA_INTR_ENA_ETE 0x00000400	/* Early Transmit */
> @@ -91,10 +98,14 @@
>  #define DMA_INTR_ENA_TJE 0x00000008	/* Transmit Jabber */
>  #define DMA_INTR_ENA_TSE 0x00000002	/* Transmit Stopped */
>  
> +#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_ABNORMAL	(DMA_INTR_ENA_AIE | DMA_INTR_ENA_FBE | \
>  				DMA_INTR_ENA_UNE)
>  
>  /* DMA default interrupt mask */
> +#define DMA_INTR_DEFAULT_MASK_LOONGSON	(DMA_INTR_NORMAL_LOONGSON | DMA_INTR_ABNORMAL_LOONGSON)
>  #define DMA_INTR_DEFAULT_MASK	(DMA_INTR_NORMAL | DMA_INTR_ABNORMAL)
>  #define DMA_INTR_DEFAULT_RX	(DMA_INTR_ENA_RIE)
>  #define DMA_INTR_DEFAULT_TX	(DMA_INTR_ENA_TIE)
> @@ -111,9 +122,15 @@
>  #define DMA_STATUS_TS_SHIFT	20
>  #define DMA_STATUS_RS_MASK	0x000e0000	/* Receive Process State */
>  #define DMA_STATUS_RS_SHIFT	17
> +#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_NIS	0x00010000	/* Normal 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_AIS	0x00008000	/* Abnormal Interrupt Summary */
>  #define DMA_STATUS_ERI	0x00004000	/* Early Receive Interrupt */
> +#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_FBI	0x00002000	/* Fatal Bus Error Interrupt */
>  #define DMA_STATUS_ETI	0x00000400	/* Early Transmit Interrupt */
>  #define DMA_STATUS_RWT	0x00000200	/* Receive Watchdog Timeout */
> @@ -128,10 +145,21 @@
>  #define DMA_STATUS_TI	0x00000001	/* Transmit Interrupt */
>  #define DMA_CONTROL_FTF		0x00100000	/* Flush transmit FIFO */
>  
> +#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_COMMON		(DMA_STATUS_NIS | \
>  					 DMA_STATUS_AIS | \
>  					 DMA_STATUS_FBI)
>  
> +#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_RX		(DMA_STATUS_ERI | \
>  					 DMA_STATUS_RWT | \
>  					 DMA_STATUS_RPS | \
> @@ -140,6 +168,13 @@
>  					 DMA_STATUS_OVF | \
>  					 DMA_STATUS_MSK_COMMON)
>  
> +#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)
>  #define DMA_STATUS_MSK_TX		(DMA_STATUS_ETI | \
>  					 DMA_STATUS_UNF | \
>  					 DMA_STATUS_TJT | \
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
> index 968801c694e9..a6e2ab4d0f4a 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
> @@ -167,6 +167,9 @@ 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 nor_intr_status;
> +	u32 abnor_intr_status;
> +	u32 fb_intr_status;
>  	u32 intr_status = readl(ioaddr + DMA_CHAN_STATUS(chan));
>  
>  #ifdef DWMAC_DMA_DEBUG
> @@ -176,13 +179,31 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
>  	show_rx_process_state(intr_status);
>  #endif
>  
> -	if (dir == DMA_DIR_RX)
> -		intr_status &= DMA_STATUS_MSK_RX;
> -	else if (dir == DMA_DIR_TX)
> -		intr_status &= DMA_STATUS_MSK_TX;
> +	if (priv->plat->flags & STMMAC_FLAG_HAS_LGMAC) {
> +		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);
> +	} else {
> +		if (dir == DMA_DIR_RX)
> +			intr_status &= DMA_STATUS_MSK_RX;
> +		else if (dir == DMA_DIR_TX)
> +			intr_status &= DMA_STATUS_MSK_TX;
> +
> +		nor_intr_status = intr_status & DMA_STATUS_NIS;
> +		abnor_intr_status = intr_status & DMA_STATUS_AIS;
> +		fb_intr_status = intr_status & DMA_STATUS_FBI;
> +	}
>  
>  	/* ABNORMAL interrupts */
> -	if (unlikely(intr_status & DMA_STATUS_AIS)) {
> +	if (unlikely(abnor_intr_status)) {
>  		if (unlikely(intr_status & DMA_STATUS_UNF)) {
>  			ret = tx_hard_error_bump_tc;
>  			x->tx_undeflow_irq++;
> @@ -205,13 +226,13 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
>  			x->tx_process_stopped_irq++;
>  			ret = tx_hard_error;
>  		}
> -		if (unlikely(intr_status & DMA_STATUS_FBI)) {
> +		if (unlikely(intr_status & fb_intr_status)) {
>  			x->fatal_bus_error_irq++;
>  			ret = tx_hard_error;
>  		}
>  	}
>  	/* TX/RX NORMAL interrupts */
> -	if (likely(intr_status & DMA_STATUS_NIS)) {
> +	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. */
> diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.c b/drivers/net/ethernet/stmicro/stmmac/hwif.c
> index 1bd34b2a47e8..3724cf698de6 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/hwif.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.c
> @@ -59,7 +59,8 @@ static int stmmac_dwmac1_quirks(struct stmmac_priv *priv)
>  		dev_info(priv->device, "Enhanced/Alternate descriptors\n");
>  
>  		/* GMAC older than 3.50 has no extended descriptors */

> -		if (priv->synopsys_id >= DWMAC_CORE_3_50) {
> +		if (priv->synopsys_id >= DWMAC_CORE_3_50 ||
> +		    priv->synopsys_id == DWLGMAC_CORE_1_00) {

This could be left as is if the priv->synopsys_id field is overwritten
with a correct value (see my last comment). 

>  			dev_info(priv->device, "Enabled extended descriptors\n");
>  			priv->extend_desc = 1;
>  		} else {
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> index d868eb8dafc5..9764d2ab7e46 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> @@ -7218,6 +7218,7 @@ static int stmmac_hw_init(struct stmmac_priv *priv)
>  	 * riwt_off field from the platform.
>  	 */

>  	if (((priv->synopsys_id >= DWMAC_CORE_3_50) ||
> +		(priv->synopsys_id == DWLGMAC_CORE_1_00) ||

the same comment here.

>  	    (priv->plat->has_xgmac)) && (!priv->plat->riwt_off)) {
>  		priv->use_riwt = 1;
>  		dev_info(priv->device,
> diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
> index dee5ad6e48c5..f07f79d50b06 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_HAS_LGMAC			BIT(13)

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.

If I didn't miss something stmmac_hwif_init() will call the
platform-specific setup method right after fetching the SNPSVER field
value. Your setup method will allocate mac_device_info structure then,
will pre-initialize the GNET-specific DMA ops field and fix the
Synopsys ID with a proper value (as described in 3 above). The rest of
the ops descriptors will be initialized in the loop afterwards based
on the specified device ID.

-Serge(y)

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

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

* Re: [PATCH net-next v7 7/9] net: stmmac: dwmac-loongson: Add GNET support
  2023-12-19 14:26 ` [PATCH net-next v7 7/9] net: stmmac: dwmac-loongson: Add GNET support Yanteng Si
@ 2023-12-21  2:34   ` Serge Semin
  2024-01-01  7:27     ` Yanteng Si
  0 siblings, 1 reply; 48+ messages in thread
From: Serge Semin @ 2023-12-21  2:34 UTC (permalink / raw)
  To: Yanteng Si
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

On Tue, Dec 19, 2023 at 10:26:47PM +0800, Yanteng Si wrote:
> Add Loongson GNET (GMAC with PHY) support. Current GNET does not support
> half duplex mode, and 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  | 79 +++++++++++++++++++
>  .../ethernet/stmicro/stmmac/stmmac_ethtool.c  |  6 ++
>  include/linux/stmmac.h                        |  2 +
>  3 files changed, 87 insertions(+)
> 
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> index 2c08d5495214..9e4953c7e4e0 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> @@ -168,6 +168,83 @@ 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 net_device *ndev = dev_get_drvdata(priv);
> +	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);

{} around the outer if please.

> +}
> +
> +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 = 0xfffffffb;

~BIT(2)?

> +
> +	plat->phy_addr = 2;
> +	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;
> +
> +	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;
> +	u32 version = readl(res->addr + GMAC_VERSION);
> +
> +	switch (version & 0xff) {

> +	case DWLGMAC_CORE_1_00:
> +		ret = loongson_dwmac_config_multi_msi(pdev, plat, res, np, 8);
> +		break;
> +	default:
> +		ret = loongson_dwmac_config_legacy(pdev, plat, res, np);

Hm, do you have two versions of Loongson GNET? What does the second
one contain in the GMAC_VERSION register then? Can't you distinguish
them by the PCI IDs (device, subsystem, revision)?

-Serge(y)

> +		break;
> +	}
> +
> +	switch (pdev->revision) {
> +	case 0x00:
> +		plat->flags |=
> +			FIELD_PREP(STMMAC_FLAG_DISABLE_HALF_DUPLEX, 1) |
> +			FIELD_PREP(STMMAC_FLAG_DISABLE_FORCE_1000, 1);
> +		break;
> +	case 0x01:
> +		plat->flags |=
> +			FIELD_PREP(STMMAC_FLAG_DISABLE_HALF_DUPLEX, 1);
> +		break;
> +	default:
> +		break;
> +	}
> +
> +	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)
>  {
> @@ -318,9 +395,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);
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> index 8105ce47c6ad..d6939eb9a0d8 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> @@ -420,6 +420,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 f07f79d50b06..067030cdb60f 100644
> --- a/include/linux/stmmac.h
> +++ b/include/linux/stmmac.h
> @@ -222,6 +222,8 @@ struct dwmac4_addrs {
>  #define STMMAC_FLAG_EN_TX_LPI_CLOCKGATING	BIT(11)
>  #define STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY	BIT(12)
>  #define STMMAC_FLAG_HAS_LGMAC			BIT(13)
> +#define STMMAC_FLAG_DISABLE_HALF_DUPLEX	BIT(14)
> +#define STMMAC_FLAG_DISABLE_FORCE_1000	BIT(15)
>  
>  struct plat_stmmacenet_data {
>  	int bus_id;
> -- 
> 2.31.4
> 

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

* Re: [PATCH net-next v7 8/9] net: stmmac: dwmac-loongson: Disable flow control for GMAC
  2023-12-19 14:28 ` [PATCH net-next v7 8/9] net: stmmac: dwmac-loongson: Disable flow control for GMAC Yanteng Si
@ 2023-12-21  2:35   ` Serge Semin
  2024-01-24 10:54     ` Yanteng Si
  0 siblings, 1 reply; 48+ messages in thread
From: Serge Semin @ 2023-12-21  2:35 UTC (permalink / raw)
  To: Yanteng Si
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

On Tue, Dec 19, 2023 at 10:28:18PM +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 | 2 ++
>  drivers/net/ethernet/stmicro/stmmac/stmmac_main.c    | 6 +++---
>  include/linux/stmmac.h                               | 1 +
>  3 files changed, 6 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> index 9e4953c7e4e0..77c9bcb66a8e 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> @@ -160,6 +160,8 @@ static int loongson_gmac_config(struct pci_dev *pdev,
>  		break;
>  	}
>  

> +	plat->flags |= FIELD_PREP(STMMAC_FLAG_DISABLE_FLOW_CONTROL, 1);

Why FIELD_PREP()-ing?

> +
>  	return ret;
>  }
>  
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> index 9764d2ab7e46..d94f61742772 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> @@ -1236,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_ASYM_PAUSE | MAC_SYM_PAUSE |
> -						MAC_10FD | MAC_100FD |
> -						MAC_1000FD;
> +	priv->phylink_config.mac_capabilities = MAC_10FD | MAC_100FD | MAC_1000FD;

> +	if (!FIELD_GET(STMMAC_FLAG_DISABLE_FLOW_CONTROL, priv->plat->flags))

!(priv->plat->flags & STMMAC_FLAG_DISABLE_FLOW_CONTROL) ?

-Serge(y)

> +		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 067030cdb60f..5ece92e4d8c3 100644
> --- a/include/linux/stmmac.h
> +++ b/include/linux/stmmac.h
> @@ -224,6 +224,7 @@ struct dwmac4_addrs {
>  #define STMMAC_FLAG_HAS_LGMAC			BIT(13)
>  #define STMMAC_FLAG_DISABLE_HALF_DUPLEX	BIT(14)
>  #define STMMAC_FLAG_DISABLE_FORCE_1000	BIT(15)
> +#define STMMAC_FLAG_DISABLE_FLOW_CONTROL	BIT(16)
>  
>  struct plat_stmmacenet_data {
>  	int bus_id;
> -- 
> 2.31.4
> 

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

* Re: [PATCH net-next v7 9/9] net: stmmac: Disable coe for some Loongson GNET
  2023-12-19 14:28 ` [PATCH net-next v7 9/9] net: stmmac: Disable coe for some Loongson GNET Yanteng Si
@ 2023-12-21  2:36   ` Serge Semin
  2024-01-23 12:47     ` Yanteng Si
  0 siblings, 1 reply; 48+ messages in thread
From: Serge Semin @ 2023-12-21  2:36 UTC (permalink / raw)
  To: Yanteng Si
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

On Tue, Dec 19, 2023 at 10:28:19PM +0800, Yanteng Si wrote:
> Some chips of Loongson GNET does not support coe, so disable them.
> 
> 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/hwif.c | 5 +++++
>  1 file changed, 5 insertions(+)
> 
> diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.c b/drivers/net/ethernet/stmicro/stmmac/hwif.c
> index 3724cf698de6..f211880925aa 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/hwif.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.c
> @@ -73,6 +73,11 @@ static int stmmac_dwmac1_quirks(struct stmmac_priv *priv)
>  		mac->desc = &ndesc_ops;
>  	}
>  
> +	if (priv->synopsys_id == DWLGMAC_CORE_1_00) {
> +		priv->plat->tx_coe = 0;
> +		priv->plat->rx_coe = STMMAC_RX_COE_NONE;
> +	}

Couldn't this be done in dwmac-loongson.c?

-Serge(y)

> +
>  	stmmac_dwmac_mode_quirk(priv);
>  	return 0;
>  }
> -- 
> 2.31.4
> 

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

* Re: [PATCH net-next v7 1/9] net: stmmac: Pass stmmac_priv and chan in some callbacks
  2023-12-20 15:08   ` Simon Horman
@ 2023-12-21  9:40     ` Yanteng Si
  0 siblings, 0 replies; 48+ messages in thread
From: Yanteng Si @ 2023-12-21  9:40 UTC (permalink / raw)
  To: Simon Horman
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	fancer.lancer, Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang


在 2023/12/20 23:08, Simon Horman 写道:
> On Tue, Dec 19, 2023 at 10:17:04PM +0800, Yanteng Si wrote:
>> Loongson GMAC and GNET have some special features. To prepare for that,
>> pass stmmac_priv and chan to more callbacks, and adjust the callbacks
>> accordingly.
>>
>> 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-sun8i.c   |  2 +-
>>   drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c |  2 +-
>>   drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c  |  2 +-
>>   drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c    |  2 +-
>>   drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h     |  3 ++-
>>   drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c     |  3 ++-
>>   drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c  |  2 +-
>>   drivers/net/ethernet/stmicro/stmmac/hwif.h          | 11 ++++++-----
>>   drivers/net/ethernet/stmicro/stmmac/stmmac_main.c   |  6 +++---
>>   9 files changed, 18 insertions(+), 15 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;
>>   
> Hi Yanteng Si,
>
> perhaps dwmac-sun8i.c needs to be further updated for this change?
>
>    .../dwmac-sun8i.c:568:10: error: incompatible function pointer types initializing 'void (*)(struct stmmac_priv *, void *, struct stmmac_dma_cfg *, int)' with an expression of type 'void (void *, struct stmmac_dma_cfg *, int)' [-Wincompatible-function-pointer-types]
>      568 |         .init = sun8i_dwmac_dma_init,
>          |                 ^~~~~~~~~~~~~~~~~~~~
>    .../dwmac-sun8i.c:574:29: error: incompatible function pointer types initializing 'void (*)(struct stmmac_priv *, void *, u32)' (aka 'void (*)(struct stmmac_priv *, void *, unsigned int)') with an expression of type 'void (void *, u32)' (aka 'void (void *, unsigned int)') [-Wincompatible-function-pointer-types]
>      574 |         .enable_dma_transmission = sun8i_dwmac_enable_dma_transmission,
>          |                                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>    2 errors generated.

Sorry, I'll fix it.


Thanks,

Yanteng


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

* Re: [PATCH net-next v7 1/9] net: stmmac: Pass stmmac_priv and chan in some callbacks
  2023-12-20 18:18   ` Serge Semin
@ 2023-12-21 11:50     ` Yanteng Si
  2023-12-21 12:53       ` Serge Semin
  0 siblings, 1 reply; 48+ messages in thread
From: Yanteng Si @ 2023-12-21 11:50 UTC (permalink / raw)
  To: Serge Semin
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang


在 2023/12/21 02:18, Serge Semin 写道:
> Hi Yanteng
>
> On Tue, Dec 19, 2023 at 10:17:04PM +0800, Yanteng Si wrote:
>> Loongson GMAC and GNET have some special features. To prepare for that,
>> pass stmmac_priv and chan to more callbacks, and adjust the callbacks
>> accordingly.
>>
>> 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-sun8i.c   |  2 +-
>>   drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c |  2 +-
>>   drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c  |  2 +-
>>   drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c    |  2 +-
>>   drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h     |  3 ++-
>>   drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c     |  3 ++-
>>   drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c  |  2 +-
>>   drivers/net/ethernet/stmicro/stmmac/hwif.h          | 11 ++++++-----
>>   drivers/net/ethernet/stmicro/stmmac/stmmac_main.c   |  6 +++---
>>   9 files changed, 18 insertions(+), 15 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)
> As Simon correctly noted this prototype is incomplete. Although AFAICS
> you never use a pointer to stmmac_priv in this method. So I guess you
> could fix the callback prototype instead.
>
>>   {
>>   	u32 v;
>>   
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
>> index daf79cdbd3ec..5e80d3eec9db 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
>> @@ -70,7 +70,7 @@ 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,
>> +static void dwmac1000_dma_init(struct stmmac_priv *priv, void __iomem *ioaddr,
>>   			       struct stmmac_dma_cfg *dma_cfg, int atds)
>>   {
>>   	u32 value = readl(ioaddr + DMA_BUS_MODE);
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
>> index dea270f60cc3..105e7d4d798f 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
>> @@ -18,7 +18,7 @@
>>   #include "dwmac100.h"
>>   #include "dwmac_dma.h"
>>   
>> -static void dwmac100_dma_init(void __iomem *ioaddr,
>> +static void dwmac100_dma_init(struct stmmac_priv *priv, void __iomem *ioaddr,
>>   			      struct stmmac_dma_cfg *dma_cfg, int atds)
>>   {
>>   	/* Enable Application Access by writing to DMA CSR0 */
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
>> index 84d3a8551b03..dc54c4e793fd 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
>> @@ -152,7 +152,7 @@ static void dwmac410_dma_init_channel(struct stmmac_priv *priv,
>>   	       ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
>>   }
>>   
>> -static void dwmac4_dma_init(void __iomem *ioaddr,
>> +static void dwmac4_dma_init(struct stmmac_priv *priv, void __iomem *ioaddr,
>>   			    struct stmmac_dma_cfg *dma_cfg, int atds)
>>   {
>>   	u32 value = readl(ioaddr + DMA_SYS_BUS_MODE);
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
>> index 72672391675f..e7aef136824b 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
>> @@ -152,7 +152,8 @@
>>   #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(struct stmmac_priv *priv,
>> +				   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,
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
>> index 7907d62d3437..2f0df16fb7e4 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
>> @@ -28,7 +28,8 @@ 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(struct stmmac_priv *priv,
>> +				   void __iomem *ioaddr, u32 chan)
>>   {
>>   	writel(1, ioaddr + DMA_XMT_POLL_DEMAND);
>>   }
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
>> index 3cde695fec91..a06f9573876f 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
>> @@ -19,7 +19,7 @@ static int dwxgmac2_dma_reset(void __iomem *ioaddr)
>>   				  !(value & XGMAC_SWR), 0, 100000);
>>   }
>>   
>> -static void dwxgmac2_dma_init(void __iomem *ioaddr,
>> +static void dwxgmac2_dma_init(struct stmmac_priv *priv, void __iomem *ioaddr,
>>   			      struct stmmac_dma_cfg *dma_cfg, int atds)
>>   {
>>   	u32 value = readl(ioaddr + XGMAC_DMA_SYSBUS_MODE);
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h
>> index 7be04b54738b..a44aa3671fb8 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/hwif.h
>> +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h
>> @@ -175,8 +175,8 @@ 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)(struct stmmac_priv *priv, void __iomem *ioaddr,
>> +		     struct stmmac_dma_cfg *dma_cfg, int atds);
> There is a good chance this change is also unnecessary. I'll post my
> comment about that to Patch 4/9.
>
>>   	void (*init_chan)(struct stmmac_priv *priv, void __iomem *ioaddr,
>>   			  struct stmmac_dma_cfg *dma_cfg, u32 chan);
>>   	void (*init_rx_chan)(struct stmmac_priv *priv, void __iomem *ioaddr,
>> @@ -198,7 +198,8 @@ 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)(struct stmmac_priv *priv,
>> +					void __iomem *ioaddr, u32 chan);
> Why do you need the pointer to the stmmac_priv structure instance
> here? I failed to find a place you using it in the subsequent patches.
it's here:

@@ -70,7 +70,7 @@ 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,
+static void dwmac1000_dma_init(struct stmmac_priv *priv, void __iomem 
*ioaddr,
                     struct stmmac_dma_cfg *dma_cfg, int atds)
  {
      u32 value = readl(ioaddr + DMA_BUS_MODE);

@@ -118,7 +118,10 @@ static void dwmac1000_dma_init(struct stmmac_priv 
*priv, void __iomem *ioaddr,

      u32 dma_intr_mask;

      /* Mask interrupts by writing to CSR7 */
-    dma_intr_mask = DMA_INTR_DEFAULT_MASK;
+    if (priv->plat->flags & STMMAC_FLAG_HAS_LGMAC)
+        dma_intr_mask = DMA_INTR_DEFAULT_MASK_LOONGSON;
+    else
+        dma_intr_mask = DMA_INTR_DEFAULT_MASK;

      dma_config(ioaddr + DMA_BUS_MODE, ioaddr + DMA_INTR_ENA,

                dma_cfg, dma_intr_mask, atds);


Thank you for all your comments, I need some time to understand. :)


Thanks,

Yanteng

>
> * Sigh, just a general note in case if somebody would wish to make
> * things a bit more optimised and less complicated. The purpose of the
> * enable_dma_transmission() callback is to re-activate the DMA-engine
> * - exit from suspension and start poll-demanding the DMA descriptors.
> * In QoS GMAC and XGMAC the same is done by updating the Tx tail
> * pointer.  It's implemented in stmmac_set_tx_tail_ptr(). So basically
> * both stmmac_enable_dma_transmission() and stmmac_set_tx_tail_ptr()
> * should be almost always called side-by-side. Alas the current
> * generic driver part doesn't do that. If it did in a some common way
> * you wouldn't have needed the enable_dma_transmission() update
> * because it would have already been updated to accept the
> * channel/queue parameter.
>
> -Serge(y)
>
>>   	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,
>> @@ -240,7 +241,7 @@ struct stmmac_dma_ops {
>>   };
>>   
>>   #define stmmac_dma_init(__priv, __args...) \
>> -	stmmac_do_void_callback(__priv, dma, init, __args)
>> +	stmmac_do_void_callback(__priv, dma, init, __priv, __args)
>>   #define stmmac_init_chan(__priv, __args...) \
>>   	stmmac_do_void_callback(__priv, dma, init_chan, __priv, __args)
>>   #define stmmac_init_rx_chan(__priv, __args...) \
>> @@ -258,7 +259,7 @@ struct stmmac_dma_ops {
>>   #define stmmac_dma_diagnostic_fr(__priv, __args...) \
>>   	stmmac_do_void_callback(__priv, dma, dma_diagnostic_fr, __args)
>>   #define stmmac_enable_dma_transmission(__priv, __args...) \
>> -	stmmac_do_void_callback(__priv, dma, enable_dma_transmission, __args)
>> +	stmmac_do_void_callback(__priv, dma, enable_dma_transmission, __priv, __args)
>>   #define stmmac_enable_dma_irq(__priv, __args...) \
>>   	stmmac_do_void_callback(__priv, dma, enable_dma_irq, __priv, __args)
>>   #define stmmac_disable_dma_irq(__priv, __args...) \
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>> index 47de466e432c..d868eb8dafc5 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);
>> @@ -4679,7 +4679,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);
>> @@ -4899,7 +4899,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] 48+ messages in thread

* Re: [PATCH net-next v7 1/9] net: stmmac: Pass stmmac_priv and chan in some callbacks
  2023-12-21 11:50     ` Yanteng Si
@ 2023-12-21 12:53       ` Serge Semin
  2023-12-21 13:21         ` Yanteng Si
  0 siblings, 1 reply; 48+ messages in thread
From: Serge Semin @ 2023-12-21 12: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, Dec 21, 2023 at 07:50:08PM +0800, Yanteng Si wrote:
> 
> 在 2023/12/21 02:18, Serge Semin 写道:
> > Hi Yanteng
> > 
> > On Tue, Dec 19, 2023 at 10:17:04PM +0800, Yanteng Si wrote:
> > > Loongson GMAC and GNET have some special features. To prepare for that,
> > > pass stmmac_priv and chan to more callbacks, and adjust the callbacks
> > > accordingly.
> > > 
> > > 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-sun8i.c   |  2 +-
> > >   drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c |  2 +-
> > >   drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c  |  2 +-
> > >   drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c    |  2 +-
> > >   drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h     |  3 ++-
> > >   drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c     |  3 ++-
> > >   drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c  |  2 +-
> > >   drivers/net/ethernet/stmicro/stmmac/hwif.h          | 11 ++++++-----
> > >   drivers/net/ethernet/stmicro/stmmac/stmmac_main.c   |  6 +++---
> > >   9 files changed, 18 insertions(+), 15 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)
> > As Simon correctly noted this prototype is incomplete. Although AFAICS
> > you never use a pointer to stmmac_priv in this method. So I guess you
> > could fix the callback prototype instead.
> > 
> > >   {
> > >   	u32 v;
> > > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> > > index daf79cdbd3ec..5e80d3eec9db 100644
> > > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> > > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> > > @@ -70,7 +70,7 @@ 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,
> > > +static void dwmac1000_dma_init(struct stmmac_priv *priv, void __iomem *ioaddr,
> > >   			       struct stmmac_dma_cfg *dma_cfg, int atds)
> > >   {
> > >   	u32 value = readl(ioaddr + DMA_BUS_MODE);
> > > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
> > > index dea270f60cc3..105e7d4d798f 100644
> > > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
> > > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
> > > @@ -18,7 +18,7 @@
> > >   #include "dwmac100.h"
> > >   #include "dwmac_dma.h"
> > > -static void dwmac100_dma_init(void __iomem *ioaddr,
> > > +static void dwmac100_dma_init(struct stmmac_priv *priv, void __iomem *ioaddr,
> > >   			      struct stmmac_dma_cfg *dma_cfg, int atds)
> > >   {
> > >   	/* Enable Application Access by writing to DMA CSR0 */
> > > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
> > > index 84d3a8551b03..dc54c4e793fd 100644
> > > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
> > > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
> > > @@ -152,7 +152,7 @@ static void dwmac410_dma_init_channel(struct stmmac_priv *priv,
> > >   	       ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
> > >   }
> > > -static void dwmac4_dma_init(void __iomem *ioaddr,
> > > +static void dwmac4_dma_init(struct stmmac_priv *priv, void __iomem *ioaddr,
> > >   			    struct stmmac_dma_cfg *dma_cfg, int atds)
> > >   {
> > >   	u32 value = readl(ioaddr + DMA_SYS_BUS_MODE);
> > > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
> > > index 72672391675f..e7aef136824b 100644
> > > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
> > > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
> > > @@ -152,7 +152,8 @@
> > >   #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(struct stmmac_priv *priv,
> > > +				   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,
> > > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
> > > index 7907d62d3437..2f0df16fb7e4 100644
> > > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
> > > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
> > > @@ -28,7 +28,8 @@ 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(struct stmmac_priv *priv,
> > > +				   void __iomem *ioaddr, u32 chan)
> > >   {
> > >   	writel(1, ioaddr + DMA_XMT_POLL_DEMAND);
> > >   }
> > > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
> > > index 3cde695fec91..a06f9573876f 100644
> > > --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
> > > +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
> > > @@ -19,7 +19,7 @@ static int dwxgmac2_dma_reset(void __iomem *ioaddr)
> > >   				  !(value & XGMAC_SWR), 0, 100000);
> > >   }
> > > -static void dwxgmac2_dma_init(void __iomem *ioaddr,
> > > +static void dwxgmac2_dma_init(struct stmmac_priv *priv, void __iomem *ioaddr,
> > >   			      struct stmmac_dma_cfg *dma_cfg, int atds)
> > >   {
> > >   	u32 value = readl(ioaddr + XGMAC_DMA_SYSBUS_MODE);
> > > diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h
> > > index 7be04b54738b..a44aa3671fb8 100644
> > > --- a/drivers/net/ethernet/stmicro/stmmac/hwif.h
> > > +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h
> > > @@ -175,8 +175,8 @@ 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)(struct stmmac_priv *priv, void __iomem *ioaddr,
> > > +		     struct stmmac_dma_cfg *dma_cfg, int atds);
> > There is a good chance this change is also unnecessary. I'll post my
> > comment about that to Patch 4/9.
> > 
> > >   	void (*init_chan)(struct stmmac_priv *priv, void __iomem *ioaddr,
> > >   			  struct stmmac_dma_cfg *dma_cfg, u32 chan);
> > >   	void (*init_rx_chan)(struct stmmac_priv *priv, void __iomem *ioaddr,
> > > @@ -198,7 +198,8 @@ 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)(struct stmmac_priv *priv,
> > > +					void __iomem *ioaddr, u32 chan);
> > Why do you need the pointer to the stmmac_priv structure instance
> > here? I failed to find a place you using it in the subsequent patches.
> it's here:
> 
> @@ -70,7 +70,7 @@ 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,
> +static void dwmac1000_dma_init(struct stmmac_priv *priv, void __iomem

Em, my comment was about enable_dma_transmission() ! I don't see you
using the stmmac_priv pointer in any updates for that method.

> *ioaddr,
>                     struct stmmac_dma_cfg *dma_cfg, int atds)
>  {
>      u32 value = readl(ioaddr + DMA_BUS_MODE);
> 
> @@ -118,7 +118,10 @@ static void dwmac1000_dma_init(struct stmmac_priv
> *priv, void __iomem *ioaddr,
> 
>      u32 dma_intr_mask;
> 
>      /* Mask interrupts by writing to CSR7 */
> -    dma_intr_mask = DMA_INTR_DEFAULT_MASK;
> +    if (priv->plat->flags & STMMAC_FLAG_HAS_LGMAC)
> +        dma_intr_mask = DMA_INTR_DEFAULT_MASK_LOONGSON;
> +    else
> +        dma_intr_mask = DMA_INTR_DEFAULT_MASK;
> 
>      dma_config(ioaddr + DMA_BUS_MODE, ioaddr + DMA_INTR_ENA,
> 
>                dma_cfg, dma_intr_mask, atds);
> 
> 

> Thank you for all your comments, I need some time to understand. :)

Don't hesitate to ask should any question arise in my comments regard.

-Serge(y)

> 
> 
> Thanks,
> 
> Yanteng
> 
> > 
> > * Sigh, just a general note in case if somebody would wish to make
> > * things a bit more optimised and less complicated. The purpose of the
> > * enable_dma_transmission() callback is to re-activate the DMA-engine
> > * - exit from suspension and start poll-demanding the DMA descriptors.
> > * In QoS GMAC and XGMAC the same is done by updating the Tx tail
> > * pointer.  It's implemented in stmmac_set_tx_tail_ptr(). So basically
> > * both stmmac_enable_dma_transmission() and stmmac_set_tx_tail_ptr()
> > * should be almost always called side-by-side. Alas the current
> > * generic driver part doesn't do that. If it did in a some common way
> > * you wouldn't have needed the enable_dma_transmission() update
> > * because it would have already been updated to accept the
> > * channel/queue parameter.
> > 
> > -Serge(y)
> > 
> > >   	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,
> > > @@ -240,7 +241,7 @@ struct stmmac_dma_ops {
> > >   };
> > >   #define stmmac_dma_init(__priv, __args...) \
> > > -	stmmac_do_void_callback(__priv, dma, init, __args)
> > > +	stmmac_do_void_callback(__priv, dma, init, __priv, __args)
> > >   #define stmmac_init_chan(__priv, __args...) \
> > >   	stmmac_do_void_callback(__priv, dma, init_chan, __priv, __args)
> > >   #define stmmac_init_rx_chan(__priv, __args...) \
> > > @@ -258,7 +259,7 @@ struct stmmac_dma_ops {
> > >   #define stmmac_dma_diagnostic_fr(__priv, __args...) \
> > >   	stmmac_do_void_callback(__priv, dma, dma_diagnostic_fr, __args)
> > >   #define stmmac_enable_dma_transmission(__priv, __args...) \
> > > -	stmmac_do_void_callback(__priv, dma, enable_dma_transmission, __args)
> > > +	stmmac_do_void_callback(__priv, dma, enable_dma_transmission, __priv, __args)
> > >   #define stmmac_enable_dma_irq(__priv, __args...) \
> > >   	stmmac_do_void_callback(__priv, dma, enable_dma_irq, __priv, __args)
> > >   #define stmmac_disable_dma_irq(__priv, __args...) \
> > > diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> > > index 47de466e432c..d868eb8dafc5 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);
> > > @@ -4679,7 +4679,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);
> > > @@ -4899,7 +4899,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] 48+ messages in thread

* Re: [PATCH net-next v7 1/9] net: stmmac: Pass stmmac_priv and chan in some callbacks
  2023-12-21 12:53       ` Serge Semin
@ 2023-12-21 13:21         ` Yanteng Si
  0 siblings, 0 replies; 48+ messages in thread
From: Yanteng Si @ 2023-12-21 13:21 UTC (permalink / raw)
  To: Serge Semin
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang


在 2023/12/21 20:53, Serge Semin 写道:
> On Thu, Dec 21, 2023 at 07:50:08PM +0800, Yanteng Si wrote:
>> 在 2023/12/21 02:18, Serge Semin 写道:
>>> Hi Yanteng
>>>
>>> On Tue, Dec 19, 2023 at 10:17:04PM +0800, Yanteng Si wrote:
>>>> Loongson GMAC and GNET have some special features. To prepare for that,
>>>> pass stmmac_priv and chan to more callbacks, and adjust the callbacks
>>>> accordingly.
>>>>
>>>> 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-sun8i.c   |  2 +-
>>>>    drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c |  2 +-
>>>>    drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c  |  2 +-
>>>>    drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c    |  2 +-
>>>>    drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h     |  3 ++-
>>>>    drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c     |  3 ++-
>>>>    drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c  |  2 +-
>>>>    drivers/net/ethernet/stmicro/stmmac/hwif.h          | 11 ++++++-----
>>>>    drivers/net/ethernet/stmicro/stmmac/stmmac_main.c   |  6 +++---
>>>>    9 files changed, 18 insertions(+), 15 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)
>>> As Simon correctly noted this prototype is incomplete. Although AFAICS
>>> you never use a pointer to stmmac_priv in this method. So I guess you
>>> could fix the callback prototype instead.
>>>
>>>>    {
>>>>    	u32 v;
>>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
>>>> index daf79cdbd3ec..5e80d3eec9db 100644
>>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
>>>> @@ -70,7 +70,7 @@ 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,
>>>> +static void dwmac1000_dma_init(struct stmmac_priv *priv, void __iomem *ioaddr,
>>>>    			       struct stmmac_dma_cfg *dma_cfg, int atds)
>>>>    {
>>>>    	u32 value = readl(ioaddr + DMA_BUS_MODE);
>>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
>>>> index dea270f60cc3..105e7d4d798f 100644
>>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
>>>> @@ -18,7 +18,7 @@
>>>>    #include "dwmac100.h"
>>>>    #include "dwmac_dma.h"
>>>> -static void dwmac100_dma_init(void __iomem *ioaddr,
>>>> +static void dwmac100_dma_init(struct stmmac_priv *priv, void __iomem *ioaddr,
>>>>    			      struct stmmac_dma_cfg *dma_cfg, int atds)
>>>>    {
>>>>    	/* Enable Application Access by writing to DMA CSR0 */
>>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
>>>> index 84d3a8551b03..dc54c4e793fd 100644
>>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
>>>> @@ -152,7 +152,7 @@ static void dwmac410_dma_init_channel(struct stmmac_priv *priv,
>>>>    	       ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
>>>>    }
>>>> -static void dwmac4_dma_init(void __iomem *ioaddr,
>>>> +static void dwmac4_dma_init(struct stmmac_priv *priv, void __iomem *ioaddr,
>>>>    			    struct stmmac_dma_cfg *dma_cfg, int atds)
>>>>    {
>>>>    	u32 value = readl(ioaddr + DMA_SYS_BUS_MODE);
>>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
>>>> index 72672391675f..e7aef136824b 100644
>>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
>>>> @@ -152,7 +152,8 @@
>>>>    #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(struct stmmac_priv *priv,
>>>> +				   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,
>>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
>>>> index 7907d62d3437..2f0df16fb7e4 100644
>>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
>>>> @@ -28,7 +28,8 @@ 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(struct stmmac_priv *priv,
>>>> +				   void __iomem *ioaddr, u32 chan)
>>>>    {
>>>>    	writel(1, ioaddr + DMA_XMT_POLL_DEMAND);
>>>>    }
>>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
>>>> index 3cde695fec91..a06f9573876f 100644
>>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
>>>> @@ -19,7 +19,7 @@ static int dwxgmac2_dma_reset(void __iomem *ioaddr)
>>>>    				  !(value & XGMAC_SWR), 0, 100000);
>>>>    }
>>>> -static void dwxgmac2_dma_init(void __iomem *ioaddr,
>>>> +static void dwxgmac2_dma_init(struct stmmac_priv *priv, void __iomem *ioaddr,
>>>>    			      struct stmmac_dma_cfg *dma_cfg, int atds)
>>>>    {
>>>>    	u32 value = readl(ioaddr + XGMAC_DMA_SYSBUS_MODE);
>>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h
>>>> index 7be04b54738b..a44aa3671fb8 100644
>>>> --- a/drivers/net/ethernet/stmicro/stmmac/hwif.h
>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h
>>>> @@ -175,8 +175,8 @@ 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)(struct stmmac_priv *priv, void __iomem *ioaddr,
>>>> +		     struct stmmac_dma_cfg *dma_cfg, int atds);
>>> There is a good chance this change is also unnecessary. I'll post my
>>> comment about that to Patch 4/9.
>>>
>>>>    	void (*init_chan)(struct stmmac_priv *priv, void __iomem *ioaddr,
>>>>    			  struct stmmac_dma_cfg *dma_cfg, u32 chan);
>>>>    	void (*init_rx_chan)(struct stmmac_priv *priv, void __iomem *ioaddr,
>>>> @@ -198,7 +198,8 @@ 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)(struct stmmac_priv *priv,
>>>> +					void __iomem *ioaddr, u32 chan);
>>> Why do you need the pointer to the stmmac_priv structure instance
>>> here? I failed to find a place you using it in the subsequent patches.
>> it's here:
>>
>> @@ -70,7 +70,7 @@ 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,
>> +static void dwmac1000_dma_init(struct stmmac_priv *priv, void __iomem
> Em, my comment was about enable_dma_transmission() ! I don't see you
> using the stmmac_priv pointer in any updates for that method.

Oh! I see.

you're right, it will be removed.

>
>> *ioaddr,
>>                      struct stmmac_dma_cfg *dma_cfg, int atds)
>>   {
>>       u32 value = readl(ioaddr + DMA_BUS_MODE);
>>
>> @@ -118,7 +118,10 @@ static void dwmac1000_dma_init(struct stmmac_priv
>> *priv, void __iomem *ioaddr,
>>
>>       u32 dma_intr_mask;
>>
>>       /* Mask interrupts by writing to CSR7 */
>> -    dma_intr_mask = DMA_INTR_DEFAULT_MASK;
>> +    if (priv->plat->flags & STMMAC_FLAG_HAS_LGMAC)
>> +        dma_intr_mask = DMA_INTR_DEFAULT_MASK_LOONGSON;
>> +    else
>> +        dma_intr_mask = DMA_INTR_DEFAULT_MASK;
>>
>>       dma_config(ioaddr + DMA_BUS_MODE, ioaddr + DMA_INTR_ENA,
>>
>>                 dma_cfg, dma_intr_mask, atds);
>>
>>
>> Thank you for all your comments, I need some time to understand. :)
> Don't hesitate to ask should any question arise in my comments regard.

Ok, I will.


Thanks,

Yanteng

>
> -Serge(y)
>
>>
>> Thanks,
>>
>> Yanteng
>>
>>> * Sigh, just a general note in case if somebody would wish to make
>>> * things a bit more optimised and less complicated. The purpose of the
>>> * enable_dma_transmission() callback is to re-activate the DMA-engine
>>> * - exit from suspension and start poll-demanding the DMA descriptors.
>>> * In QoS GMAC and XGMAC the same is done by updating the Tx tail
>>> * pointer.  It's implemented in stmmac_set_tx_tail_ptr(). So basically
>>> * both stmmac_enable_dma_transmission() and stmmac_set_tx_tail_ptr()
>>> * should be almost always called side-by-side. Alas the current
>>> * generic driver part doesn't do that. If it did in a some common way
>>> * you wouldn't have needed the enable_dma_transmission() update
>>> * because it would have already been updated to accept the
>>> * channel/queue parameter.
>>>
>>> -Serge(y)
>>>
>>>>    	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,
>>>> @@ -240,7 +241,7 @@ struct stmmac_dma_ops {
>>>>    };
>>>>    #define stmmac_dma_init(__priv, __args...) \
>>>> -	stmmac_do_void_callback(__priv, dma, init, __args)
>>>> +	stmmac_do_void_callback(__priv, dma, init, __priv, __args)
>>>>    #define stmmac_init_chan(__priv, __args...) \
>>>>    	stmmac_do_void_callback(__priv, dma, init_chan, __priv, __args)
>>>>    #define stmmac_init_rx_chan(__priv, __args...) \
>>>> @@ -258,7 +259,7 @@ struct stmmac_dma_ops {
>>>>    #define stmmac_dma_diagnostic_fr(__priv, __args...) \
>>>>    	stmmac_do_void_callback(__priv, dma, dma_diagnostic_fr, __args)
>>>>    #define stmmac_enable_dma_transmission(__priv, __args...) \
>>>> -	stmmac_do_void_callback(__priv, dma, enable_dma_transmission, __args)
>>>> +	stmmac_do_void_callback(__priv, dma, enable_dma_transmission, __priv, __args)
>>>>    #define stmmac_enable_dma_irq(__priv, __args...) \
>>>>    	stmmac_do_void_callback(__priv, dma, enable_dma_irq, __priv, __args)
>>>>    #define stmmac_disable_dma_irq(__priv, __args...) \
>>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>>>> index 47de466e432c..d868eb8dafc5 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);
>>>> @@ -4679,7 +4679,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);
>>>> @@ -4899,7 +4899,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] 48+ messages in thread

* Re: [PATCH net-next v7 4/9] net: stmmac: Add multi-channel supports
  2023-12-20 22:36   ` Serge Semin
@ 2023-12-29 10:33     ` Yanteng Si
  2023-12-30 11:25       ` Serge Semin
  0 siblings, 1 reply; 48+ messages in thread
From: Yanteng Si @ 2023-12-29 10:33 UTC (permalink / raw)
  To: Serge Semin
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang


在 2023/12/21 06:36, Serge Semin 写道:
> On Tue, Dec 19, 2023 at 10:17:07PM +0800, Yanteng Si wrote:
>> Loongson platforms use a DWGMAC which supports multi-channel.
>>
>> Added dwmac1000_dma_init_channel() and init_chan(), factor out
>> all the channel-specific setups from dwmac1000_dma_init() to the
>> new function dma_config(), then distinguish dma initialization
>> and multi-channel initialization through different parameters.
>>
>> 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/dwmac1000_dma.c   | 55 ++++++++++++++-----
>>   .../net/ethernet/stmicro/stmmac/dwmac_dma.h   | 17 ++++++
>>   .../net/ethernet/stmicro/stmmac/dwmac_lib.c   | 30 +++++-----
>>   3 files changed, 74 insertions(+), 28 deletions(-)
>>
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
>> index 5e80d3eec9db..0fb48e683970 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
>> @@ -12,7 +12,8 @@
>>     Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
>>   *******************************************************************************/
>>   
>> -#include <asm/io.h>
>> +#include <linux/io.h>
>> +#include "stmmac.h"
>>   #include "dwmac1000.h"
>>   #include "dwmac_dma.h"
>>   
>> @@ -70,13 +71,16 @@ static void dwmac1000_dma_axi(void __iomem *ioaddr, struct stmmac_axi *axi)
>>   	writel(value, ioaddr + DMA_AXI_BUS_MODE);
>>   }
>>   
>> -static void dwmac1000_dma_init(struct stmmac_priv *priv, void __iomem *ioaddr,
>> -			       struct stmmac_dma_cfg *dma_cfg, int atds)
>> +static void dma_config(void __iomem *modeaddr, void __iomem *enaddr,
>> +					   struct stmmac_dma_cfg *dma_cfg, u32 dma_intr_mask,
>> +					   int atds)
> Please make sure the arguments are aligned with the function open
> parenthesis taking into account that tabs are of _8_ chars:
> Documentation/process/coding-style.rst.
OK.
>
>>   {
>> -	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;
>>   
>> +	value = readl(modeaddr);
>> +
>>   	/*
>>   	 * Set the DMA PBL (Programmable Burst Length) mode.
>>   	 *
>> @@ -104,10 +108,34 @@ static void dwmac1000_dma_init(struct stmmac_priv *priv, void __iomem *ioaddr,
>>   	if (dma_cfg->aal)
>>   		value |= DMA_BUS_MODE_AAL;
>>   
>> -	writel(value, ioaddr + DMA_BUS_MODE);
>> +	writel(value, modeaddr);
>> +	writel(dma_intr_mask, enaddr);
>> +}
>> +
>> +static void dwmac1000_dma_init(struct stmmac_priv *priv, void __iomem *ioaddr,
>> +							   struct stmmac_dma_cfg *dma_cfg, int atds)
>> +{
>> +	u32 dma_intr_mask;
>>   
>>   	/* Mask interrupts by writing to CSR7 */
>> -	writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_INTR_ENA);
>> +	dma_intr_mask = DMA_INTR_DEFAULT_MASK;
>> +
>> +	dma_config(ioaddr + DMA_BUS_MODE, ioaddr + DMA_INTR_ENA,
>> +			  dma_cfg, dma_intr_mask, atds);
>> +}
>> +
>> +static void dwmac1000_dma_init_channel(struct stmmac_priv *priv, void __iomem *ioaddr,
>> +									   struct stmmac_dma_cfg *dma_cfg, u32 chan)
>> +{
>> +	u32 dma_intr_mask;
>> +
>> +	/* Mask interrupts by writing to CSR7 */
>> +	dma_intr_mask = DMA_INTR_DEFAULT_MASK;
>> +
>> +	if (dma_cfg->multi_msi_en)
>> +		dma_config(ioaddr + DMA_CHAN_BUS_MODE(chan),
>> +					ioaddr + DMA_CHAN_INTR_ENA(chan), dma_cfg,
> Why so complicated? stmmac_init_chan() is always supposed to be called
> in the same context as stmmac_dma_init() (stmmac_xdp_open() is wrong
> in not doing that). Seeing DW GMAC v3.x multi-channels feature is
> implemented as multiple sets of the same CSRs (except AV traffic
> control CSRs specific to channels 1 and higher which are left unused
> here anyway) you can just drop the stmmac_dma_ops.init() callback and
> convert dwmac1000_dma_init() to being dwmac1000_dma_init_channel()
> with no significant modifications:
>
> < you wouldn't need to have a separate dma_config() method.
> < you wouldn't need to check for the dma_cfg->multi_msi_en flag state
> since the stmmac_init_chan() method is called for as many times as
> there are channels available (at least 1 channel always exists).
> < just add atds argument.
> < just convert the method to using the chan-dependent CSR macros.

Yes, you are right.

>
>> +					dma_intr_mask, dma_cfg->multi_msi_en);
>                                                                  ^
>                +-------------------------------------------------+
> This is wrong + ATDS flag means Alternative Descriptor Size. This flag
> enables the 8 dword DMA-descriptors size with some DMA-desc fields
> semantics changed (see enh_desc.c and norm_desc.c). It's useful for
> PTP Timestamping, VLANs, AV feature, L3/L4 filtering, CSum offload
> Type 2 (if any of that available). It has nothing to do with the
> separate DMA IRQs. Just convert the stmmac_dma_ops.dma_init() callback
> to accepting the atds flag as an additional argument, use it here to
> activate the extended descriptor size and make sure the atds flag is
> passed to the stmmac_init_chan() method in the respective source code.
OK.
>
>>   }
>>   
>>   static void dwmac1000_dma_init_rx(struct stmmac_priv *priv,
>> @@ -116,7 +144,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 +153,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 +181,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 +203,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 +237,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 +299,13 @@ 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,
> This could be dropped. See my comment above.
OK,  I've tried this and it works.
>
>> +	.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 e7aef136824b..395d5e4c3922 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
>> @@ -148,6 +148,9 @@
>>   					 DMA_STATUS_TI | \
>>   					 DMA_STATUS_MSK_COMMON)
>>   
>> +/* Following DMA defines are chanels oriented */
> s/chanels/channels
OK!
>
>> +#define DMA_CHAN_OFFSET			0x100
> DMA_CHAN_BASE_OFFSET? to be looking the same as in DW QoS Eth GMAC
> v4.x/v5.x (dwmac4_dma.h).
OK
>
>> +
>>   #define NUM_DWMAC100_DMA_REGS	9
>>   #define NUM_DWMAC1000_DMA_REGS	23
>>   #define NUM_DWMAC4_DMA_REGS	27
>> @@ -170,4 +173,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 2f0df16fb7e4..968801c694e9 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
>> @@ -31,63 +31,63 @@ int dwmac_dma_reset(void __iomem *ioaddr)
>>   void dwmac_enable_dma_transmission(struct stmmac_priv *priv,
>>   				   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
>> @@ -167,7 +167,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 */
>> @@ -237,7 +237,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));
> Em, please explain the mask change. Bits CSR5[17:28] are defined as RO

I'm not sure I can explain it, but it goes something like this:

We moved these bits up because we split the reception and transmission 
of interrupts.

28    Reserved
27:25 EB
24:22 TS
21:19 RS
18    NTIS


> on a normal DW GMAC. Anyway it seems like the mask changes belongs to
> the patch 5/9.
Yes, I will try.
>
>
> Except the last comment, AFAICS this patch provides a generic DW GMAC
> v3.x multi-channel support. Despite of several issues noted above the
> change in general looks very good.

Thanks, the next version of this patch will only have changes related to 
dma_chan_base_addr.


* dwmac1000_dma_init will be restored.

* dwmac1000_dma_init_channel() will be moved to dwmac-loongson.c.


Thanks for your review!


Thanks,

Yanteng

>
> -Serge(y)
>
>>   
>>   	return ret;
>>   }
>> -- 
>> 2.31.4
>>


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

* Re: [PATCH net-next v7 4/9] net: stmmac: Add multi-channel supports
  2023-12-29 10:33     ` Yanteng Si
@ 2023-12-30 11:25       ` Serge Semin
  2024-01-01  6:57         ` Yanteng Si
  0 siblings, 1 reply; 48+ messages in thread
From: Serge Semin @ 2023-12-30 11:25 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 Fri, Dec 29, 2023 at 06:33:52PM +0800, Yanteng Si wrote:
> 
> 在 2023/12/21 06:36, Serge Semin 写道:
> > On Tue, Dec 19, 2023 at 10:17:07PM +0800, Yanteng Si wrote:
> > > Loongson platforms use a DWGMAC which supports multi-channel.
> > > 
> > > Added dwmac1000_dma_init_channel() and init_chan(), factor out
> > > all the channel-specific setups from dwmac1000_dma_init() to the
> > > new function dma_config(), then distinguish dma initialization
> > > and multi-channel initialization through different parameters.
> > > 
> > > 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/dwmac1000_dma.c   | 55 ++++++++++++++-----
> > >   .../net/ethernet/stmicro/stmmac/dwmac_dma.h   | 17 ++++++
> > >   .../net/ethernet/stmicro/stmmac/dwmac_lib.c   | 30 +++++-----
> > >   3 files changed, 74 insertions(+), 28 deletions(-)
> > > 
> > > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> > > index 5e80d3eec9db..0fb48e683970 100644
> > > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> > > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> > > @@ -12,7 +12,8 @@
> > >     Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
> > >   *******************************************************************************/
> > > -#include <asm/io.h>
> > > +#include <linux/io.h>
> > > +#include "stmmac.h"
> > >   #include "dwmac1000.h"
> > >   #include "dwmac_dma.h"
> > > @@ -70,13 +71,16 @@ static void dwmac1000_dma_axi(void __iomem *ioaddr, struct stmmac_axi *axi)
> > >   	writel(value, ioaddr + DMA_AXI_BUS_MODE);
> > >   }
> > > -static void dwmac1000_dma_init(struct stmmac_priv *priv, void __iomem *ioaddr,
> > > -			       struct stmmac_dma_cfg *dma_cfg, int atds)
> > > +static void dma_config(void __iomem *modeaddr, void __iomem *enaddr,
> > > +					   struct stmmac_dma_cfg *dma_cfg, u32 dma_intr_mask,
> > > +					   int atds)
> > Please make sure the arguments are aligned with the function open
> > parenthesis taking into account that tabs are of _8_ chars:
> > Documentation/process/coding-style.rst.
> OK.
> > 
> > >   {
> > > -	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;
> > > +	value = readl(modeaddr);
> > > +
> > >   	/*
> > >   	 * Set the DMA PBL (Programmable Burst Length) mode.
> > >   	 *
> > > @@ -104,10 +108,34 @@ static void dwmac1000_dma_init(struct stmmac_priv *priv, void __iomem *ioaddr,
> > >   	if (dma_cfg->aal)
> > >   		value |= DMA_BUS_MODE_AAL;
> > > -	writel(value, ioaddr + DMA_BUS_MODE);
> > > +	writel(value, modeaddr);
> > > +	writel(dma_intr_mask, enaddr);
> > > +}
> > > +
> > > +static void dwmac1000_dma_init(struct stmmac_priv *priv, void __iomem *ioaddr,
> > > +							   struct stmmac_dma_cfg *dma_cfg, int atds)
> > > +{
> > > +	u32 dma_intr_mask;
> > >   	/* Mask interrupts by writing to CSR7 */
> > > -	writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_INTR_ENA);
> > > +	dma_intr_mask = DMA_INTR_DEFAULT_MASK;
> > > +
> > > +	dma_config(ioaddr + DMA_BUS_MODE, ioaddr + DMA_INTR_ENA,
> > > +			  dma_cfg, dma_intr_mask, atds);
> > > +}
> > > +
> > > +static void dwmac1000_dma_init_channel(struct stmmac_priv *priv, void __iomem *ioaddr,
> > > +									   struct stmmac_dma_cfg *dma_cfg, u32 chan)
> > > +{
> > > +	u32 dma_intr_mask;
> > > +
> > > +	/* Mask interrupts by writing to CSR7 */
> > > +	dma_intr_mask = DMA_INTR_DEFAULT_MASK;
> > > +
> > > +	if (dma_cfg->multi_msi_en)
> > > +		dma_config(ioaddr + DMA_CHAN_BUS_MODE(chan),
> > > +					ioaddr + DMA_CHAN_INTR_ENA(chan), dma_cfg,
> > Why so complicated? stmmac_init_chan() is always supposed to be called
> > in the same context as stmmac_dma_init() (stmmac_xdp_open() is wrong
> > in not doing that). Seeing DW GMAC v3.x multi-channels feature is
> > implemented as multiple sets of the same CSRs (except AV traffic
> > control CSRs specific to channels 1 and higher which are left unused
> > here anyway) you can just drop the stmmac_dma_ops.init() callback and
> > convert dwmac1000_dma_init() to being dwmac1000_dma_init_channel()
> > with no significant modifications:
> > 
> > < you wouldn't need to have a separate dma_config() method.
> > < you wouldn't need to check for the dma_cfg->multi_msi_en flag state
> > since the stmmac_init_chan() method is called for as many times as
> > there are channels available (at least 1 channel always exists).
> > < just add atds argument.
> > < just convert the method to using the chan-dependent CSR macros.
> 
> Yes, you are right.
> 
> > 
> > > +					dma_intr_mask, dma_cfg->multi_msi_en);
> >                                                                  ^
> >                +-------------------------------------------------+
> > This is wrong + ATDS flag means Alternative Descriptor Size. This flag
> > enables the 8 dword DMA-descriptors size with some DMA-desc fields
> > semantics changed (see enh_desc.c and norm_desc.c). It's useful for
> > PTP Timestamping, VLANs, AV feature, L3/L4 filtering, CSum offload
> > Type 2 (if any of that available). It has nothing to do with the
> > separate DMA IRQs. Just convert the stmmac_dma_ops.dma_init() callback
> > to accepting the atds flag as an additional argument, use it here to
> > activate the extended descriptor size and make sure the atds flag is
> > passed to the stmmac_init_chan() method in the respective source code.
> OK.
> > 
> > >   }
> > >   static void dwmac1000_dma_init_rx(struct stmmac_priv *priv,
> > > @@ -116,7 +144,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 +153,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 +181,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 +203,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 +237,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 +299,13 @@ 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,
> > This could be dropped. See my comment above.
> OK,  I've tried this and it works.
> > 
> > > +	.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 e7aef136824b..395d5e4c3922 100644
> > > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
> > > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
> > > @@ -148,6 +148,9 @@
> > >   					 DMA_STATUS_TI | \
> > >   					 DMA_STATUS_MSK_COMMON)
> > > +/* Following DMA defines are chanels oriented */
> > s/chanels/channels
> OK!
> > 
> > > +#define DMA_CHAN_OFFSET			0x100
> > DMA_CHAN_BASE_OFFSET? to be looking the same as in DW QoS Eth GMAC
> > v4.x/v5.x (dwmac4_dma.h).
> OK
> > 
> > > +
> > >   #define NUM_DWMAC100_DMA_REGS	9
> > >   #define NUM_DWMAC1000_DMA_REGS	23
> > >   #define NUM_DWMAC4_DMA_REGS	27
> > > @@ -170,4 +173,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 2f0df16fb7e4..968801c694e9 100644
> > > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
> > > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
> > > @@ -31,63 +31,63 @@ int dwmac_dma_reset(void __iomem *ioaddr)
> > >   void dwmac_enable_dma_transmission(struct stmmac_priv *priv,
> > >   				   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
> > > @@ -167,7 +167,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 */
> > > @@ -237,7 +237,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));
> > Em, please explain the mask change. Bits CSR5[17:28] are defined as RO
> 
> I'm not sure I can explain it, but it goes something like this:
> 
> We moved these bits up because we split the reception and transmission of
> interrupts.
> 
> 28    Reserved
> 27:25 EB
> 24:22 TS
> 21:19 RS
> 18    NTIS

I see. Thanks for clarification. Let's postpone the IRQ mask
discussion for the next review round.

> 
> 
> > on a normal DW GMAC. Anyway it seems like the mask changes belongs to
> > the patch 5/9.
> Yes, I will try.
> > 
> > 
> > Except the last comment, AFAICS this patch provides a generic DW GMAC
> > v3.x multi-channel support. Despite of several issues noted above the
> > change in general looks very good.
> 

> Thanks, the next version of this patch will only have changes related to
> dma_chan_base_addr.
> 
> 
> * dwmac1000_dma_init will be restored.
> 
> * dwmac1000_dma_init_channel() will be moved to dwmac-loongson.c.

No. That's not what I meant. I said that this patch looks _generic_
enough to be applied (with my notes taken into account) in the common
dwmac1000_dma.c code! It provides useful multi-DMA-channels support in
a way it's implemented by the _generic_ DW GMAC v3.x IP-core. From
that perspective the change will be useful for all users which DW
GMACs support the multi-channels feature. Please fix the patch based
on my notes and repost it as a part of your series. We'll figure out
what to do with the IRQ mask on the next review round.

-Serge(y)

> 
> 
> Thanks for your review!
> 
> 
> Thanks,
> 
> Yanteng
> 
> > 
> > -Serge(y)
> > 
> > >   	return ret;
> > >   }
> > > -- 
> > > 2.31.4
> > > 
> 

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

* Re: [PATCH net-next v7 4/9] net: stmmac: Add multi-channel supports
  2023-12-30 11:25       ` Serge Semin
@ 2024-01-01  6:57         ` Yanteng Si
  2024-01-02  1:04           ` Serge Semin
  0 siblings, 1 reply; 48+ messages in thread
From: Yanteng Si @ 2024-01-01  6:57 UTC (permalink / raw)
  To: Serge Semin
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang


在 2023/12/30 19:25, Serge Semin 写道:
> Hi Yanteng
>
> On Fri, Dec 29, 2023 at 06:33:52PM +0800, Yanteng Si wrote:
>> 在 2023/12/21 06:36, Serge Semin 写道:
>>> On Tue, Dec 19, 2023 at 10:17:07PM +0800, Yanteng Si wrote:
>>>> Loongson platforms use a DWGMAC which supports multi-channel.
>>>>
>>>> Added dwmac1000_dma_init_channel() and init_chan(), factor out
>>>> all the channel-specific setups from dwmac1000_dma_init() to the
>>>> new function dma_config(), then distinguish dma initialization
>>>> and multi-channel initialization through different parameters.
>>>>
>>>> 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/dwmac1000_dma.c   | 55 ++++++++++++++-----
>>>>    .../net/ethernet/stmicro/stmmac/dwmac_dma.h   | 17 ++++++
>>>>    .../net/ethernet/stmicro/stmmac/dwmac_lib.c   | 30 +++++-----
>>>>    3 files changed, 74 insertions(+), 28 deletions(-)
>>>>
>>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
>>>> index 5e80d3eec9db..0fb48e683970 100644
>>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
>>>> @@ -12,7 +12,8 @@
>>>>      Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
>>>>    *******************************************************************************/
>>>> -#include <asm/io.h>
>>>> +#include <linux/io.h>
>>>> +#include "stmmac.h"
>>>>    #include "dwmac1000.h"
>>>>    #include "dwmac_dma.h"
>>>> @@ -70,13 +71,16 @@ static void dwmac1000_dma_axi(void __iomem *ioaddr, struct stmmac_axi *axi)
>>>>    	writel(value, ioaddr + DMA_AXI_BUS_MODE);
>>>>    }
>>>> -static void dwmac1000_dma_init(struct stmmac_priv *priv, void __iomem *ioaddr,
>>>> -			       struct stmmac_dma_cfg *dma_cfg, int atds)
>>>> +static void dma_config(void __iomem *modeaddr, void __iomem *enaddr,
>>>> +					   struct stmmac_dma_cfg *dma_cfg, u32 dma_intr_mask,
>>>> +					   int atds)
>>> Please make sure the arguments are aligned with the function open
>>> parenthesis taking into account that tabs are of _8_ chars:
>>> Documentation/process/coding-style.rst.
>> OK.
>>>>    {
>>>> -	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;
>>>> +	value = readl(modeaddr);
>>>> +
>>>>    	/*
>>>>    	 * Set the DMA PBL (Programmable Burst Length) mode.
>>>>    	 *
>>>> @@ -104,10 +108,34 @@ static void dwmac1000_dma_init(struct stmmac_priv *priv, void __iomem *ioaddr,
>>>>    	if (dma_cfg->aal)
>>>>    		value |= DMA_BUS_MODE_AAL;
>>>> -	writel(value, ioaddr + DMA_BUS_MODE);
>>>> +	writel(value, modeaddr);
>>>> +	writel(dma_intr_mask, enaddr);
>>>> +}
>>>> +
>>>> +static void dwmac1000_dma_init(struct stmmac_priv *priv, void __iomem *ioaddr,
>>>> +							   struct stmmac_dma_cfg *dma_cfg, int atds)
>>>> +{
>>>> +	u32 dma_intr_mask;
>>>>    	/* Mask interrupts by writing to CSR7 */
>>>> -	writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_INTR_ENA);
>>>> +	dma_intr_mask = DMA_INTR_DEFAULT_MASK;
>>>> +
>>>> +	dma_config(ioaddr + DMA_BUS_MODE, ioaddr + DMA_INTR_ENA,
>>>> +			  dma_cfg, dma_intr_mask, atds);
>>>> +}
>>>> +
>>>> +static void dwmac1000_dma_init_channel(struct stmmac_priv *priv, void __iomem *ioaddr,
>>>> +									   struct stmmac_dma_cfg *dma_cfg, u32 chan)
>>>> +{
>>>> +	u32 dma_intr_mask;
>>>> +
>>>> +	/* Mask interrupts by writing to CSR7 */
>>>> +	dma_intr_mask = DMA_INTR_DEFAULT_MASK;
>>>> +
>>>> +	if (dma_cfg->multi_msi_en)
>>>> +		dma_config(ioaddr + DMA_CHAN_BUS_MODE(chan),
>>>> +					ioaddr + DMA_CHAN_INTR_ENA(chan), dma_cfg,
>>> Why so complicated? stmmac_init_chan() is always supposed to be called
>>> in the same context as stmmac_dma_init() (stmmac_xdp_open() is wrong
>>> in not doing that). Seeing DW GMAC v3.x multi-channels feature is
>>> implemented as multiple sets of the same CSRs (except AV traffic
>>> control CSRs specific to channels 1 and higher which are left unused
>>> here anyway) you can just drop the stmmac_dma_ops.init() callback and
>>> convert dwmac1000_dma_init() to being dwmac1000_dma_init_channel()
>>> with no significant modifications:
>>>
>>> < you wouldn't need to have a separate dma_config() method.
>>> < you wouldn't need to check for the dma_cfg->multi_msi_en flag state
>>> since the stmmac_init_chan() method is called for as many times as
>>> there are channels available (at least 1 channel always exists).
>>> < just add atds argument.
>>> < just convert the method to using the chan-dependent CSR macros.
>> Yes, you are right.
>>
>>>> +					dma_intr_mask, dma_cfg->multi_msi_en);
>>>                                                                   ^
>>>                 +-------------------------------------------------+
>>> This is wrong + ATDS flag means Alternative Descriptor Size. This flag
>>> enables the 8 dword DMA-descriptors size with some DMA-desc fields
>>> semantics changed (see enh_desc.c and norm_desc.c). It's useful for
>>> PTP Timestamping, VLANs, AV feature, L3/L4 filtering, CSum offload
>>> Type 2 (if any of that available). It has nothing to do with the
>>> separate DMA IRQs. Just convert the stmmac_dma_ops.dma_init() callback
>>> to accepting the atds flag as an additional argument, use it here to
>>> activate the extended descriptor size and make sure the atds flag is
>>> passed to the stmmac_init_chan() method in the respective source code.
>> OK.
>>>>    }
>>>>    static void dwmac1000_dma_init_rx(struct stmmac_priv *priv,
>>>> @@ -116,7 +144,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 +153,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 +181,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 +203,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 +237,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 +299,13 @@ 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,
>>> This could be dropped. See my comment above.
>> OK,  I've tried this and it works.
>>>> +	.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 e7aef136824b..395d5e4c3922 100644
>>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
>>>> @@ -148,6 +148,9 @@
>>>>    					 DMA_STATUS_TI | \
>>>>    					 DMA_STATUS_MSK_COMMON)
>>>> +/* Following DMA defines are chanels oriented */
>>> s/chanels/channels
>> OK!
>>>> +#define DMA_CHAN_OFFSET			0x100
>>> DMA_CHAN_BASE_OFFSET? to be looking the same as in DW QoS Eth GMAC
>>> v4.x/v5.x (dwmac4_dma.h).
>> OK
>>>> +
>>>>    #define NUM_DWMAC100_DMA_REGS	9
>>>>    #define NUM_DWMAC1000_DMA_REGS	23
>>>>    #define NUM_DWMAC4_DMA_REGS	27
>>>> @@ -170,4 +173,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 2f0df16fb7e4..968801c694e9 100644
>>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
>>>> @@ -31,63 +31,63 @@ int dwmac_dma_reset(void __iomem *ioaddr)
>>>>    void dwmac_enable_dma_transmission(struct stmmac_priv *priv,
>>>>    				   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
>>>> @@ -167,7 +167,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 */
>>>> @@ -237,7 +237,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));
>>> Em, please explain the mask change. Bits CSR5[17:28] are defined as RO
>> I'm not sure I can explain it, but it goes something like this:
>>
>> We moved these bits up because we split the reception and transmission of
>> interrupts.
>>
>> 28    Reserved
>> 27:25 EB
>> 24:22 TS
>> 21:19 RS
>> 18    NTIS
> I see. Thanks for clarification. Let's postpone the IRQ mask
> discussion for the next review round.
OK.
>
>>
>>> on a normal DW GMAC. Anyway it seems like the mask changes belongs to
>>> the patch 5/9.
>> Yes, I will try.
>>>
>>> Except the last comment, AFAICS this patch provides a generic DW GMAC
>>> v3.x multi-channel support. Despite of several issues noted above the
>>> change in general looks very good.
>> Thanks, the next version of this patch will only have changes related to
>> dma_chan_base_addr.
>>
>>
>> * dwmac1000_dma_init will be restored.
>>
>> * dwmac1000_dma_init_channel() will be moved to dwmac-loongson.c.
> No. That's not what I meant. I said that this patch looks _generic_
> enough to be applied (with my notes taken into account) in the common
> dwmac1000_dma.c code! It provides useful multi-DMA-channels support in
> a way it's implemented by the _generic_ DW GMAC v3.x IP-core. From
> that perspective the change will be useful for all users which DW
> GMACs support the multi-channels feature. Please fix the patch based
> on my notes and repost it as a part of your series. We'll figure out
> what to do with the IRQ mask on the next review round.

Em, I see.

In dwmac1000_dma.c:

1. Convert dwmac1000_dma_init() to being dwmac1000_dma_init_channel(); 
(No DMA_INTR_DEFAULT_MASK_LOONGSON)

2. Drop the stmmac_dma_ops.init() callback;

3. Leave other parts of the patch unchanged, such as DMA_CHAN_BASE_OFFSET;

In dwmac-loongson.c:

1. Create the Loongson GNET-specific stmmac_dma_ops.dma_interrupt() and stmmac_dma_ops.init_chan(); (With DMA_INTR_DEFAULT_MASK_LOONGSON)
2. Move all the Loongson-specific macros from dwmac_dma.h to here;
3. Follow your comments in Patch 5 to continue;

Right?


Thanks,
Yanteng

>
> -Serge(y)
>
>>
>> Thanks for your review!
>>
>>
>> Thanks,
>>
>> Yanteng
>>
>>> -Serge(y)
>>>
>>>>    	return ret;
>>>>    }
>>>> -- 
>>>> 2.31.4
>>>>


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

* Re: [PATCH net-next v7 7/9] net: stmmac: dwmac-loongson: Add GNET support
  2023-12-21  2:34   ` Serge Semin
@ 2024-01-01  7:27     ` Yanteng Si
  2024-01-02  1:22       ` Serge Semin
  2024-01-24  9:21       ` Yanteng Si
  0 siblings, 2 replies; 48+ messages in thread
From: Yanteng Si @ 2024-01-01  7:27 UTC (permalink / raw)
  To: Serge Semin
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang


在 2023/12/21 10:34, Serge Semin 写道:
> On Tue, Dec 19, 2023 at 10:26:47PM +0800, Yanteng Si wrote:
>> Add Loongson GNET (GMAC with PHY) support. Current GNET does not support
>> half duplex mode, and 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  | 79 +++++++++++++++++++
>>   .../ethernet/stmicro/stmmac/stmmac_ethtool.c  |  6 ++
>>   include/linux/stmmac.h                        |  2 +
>>   3 files changed, 87 insertions(+)
>>
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>> index 2c08d5495214..9e4953c7e4e0 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>> @@ -168,6 +168,83 @@ 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 net_device *ndev = dev_get_drvdata(priv);
>> +	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);
> {} around the outer if please.
OK.
>
>> +}
>> +
>> +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 = 0xfffffffb;
> ~BIT(2)?
I still need to confirm, please allow me to get back to you later.
>
>> +
>> +	plat->phy_addr = 2;
>> +	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;
>> +
>> +	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;
>> +	u32 version = readl(res->addr + GMAC_VERSION);
>> +
>> +	switch (version & 0xff) {
>> +	case DWLGMAC_CORE_1_00:
>> +		ret = loongson_dwmac_config_multi_msi(pdev, plat, res, np, 8);
>> +		break;
>> +	default:
>> +		ret = loongson_dwmac_config_legacy(pdev, plat, res, np);
> Hm, do you have two versions of Loongson GNET? What does the second
Yes.
> one contain in the GMAC_VERSION register then? Can't you distinguish
> them by the PCI IDs (device, subsystem, revision)?

I'm afraid that's not possible.

Because they have the same pci id and revision.


Thanks,

Yanteng

>
> -Serge(y)
>
>> +		break;
>> +	}
>> +
>> +	switch (pdev->revision) {
>> +	case 0x00:
>> +		plat->flags |=
>> +			FIELD_PREP(STMMAC_FLAG_DISABLE_HALF_DUPLEX, 1) |
>> +			FIELD_PREP(STMMAC_FLAG_DISABLE_FORCE_1000, 1);
>> +		break;
>> +	case 0x01:
>> +		plat->flags |=
>> +			FIELD_PREP(STMMAC_FLAG_DISABLE_HALF_DUPLEX, 1);
>> +		break;
>> +	default:
>> +		break;
>> +	}
>> +
>> +	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)
>>   {
>> @@ -318,9 +395,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);
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
>> index 8105ce47c6ad..d6939eb9a0d8 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
>> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
>> @@ -420,6 +420,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 f07f79d50b06..067030cdb60f 100644
>> --- a/include/linux/stmmac.h
>> +++ b/include/linux/stmmac.h
>> @@ -222,6 +222,8 @@ struct dwmac4_addrs {
>>   #define STMMAC_FLAG_EN_TX_LPI_CLOCKGATING	BIT(11)
>>   #define STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY	BIT(12)
>>   #define STMMAC_FLAG_HAS_LGMAC			BIT(13)
>> +#define STMMAC_FLAG_DISABLE_HALF_DUPLEX	BIT(14)
>> +#define STMMAC_FLAG_DISABLE_FORCE_1000	BIT(15)
>>   
>>   struct plat_stmmacenet_data {
>>   	int bus_id;
>> -- 
>> 2.31.4
>>


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

* Re: [PATCH net-next v7 5/9] net: stmmac: Add Loongson-specific register definitions
  2023-12-21  2:14   ` Serge Semin
@ 2024-01-01  8:31     ` Yanteng Si
  2024-01-01 12:26       ` Serge Semin
  0 siblings, 1 reply; 48+ messages in thread
From: Yanteng Si @ 2024-01-01  8:31 UTC (permalink / raw)
  To: Serge Semin
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang


在 2023/12/21 10:14, Serge Semin 写道:
> On Tue, Dec 19, 2023 at 10:26:45PM +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.
> Thanks for the updated patch. It looks much clearer now. Thanks to
> that I came up with a better and less invasive solution. See my last
> comment for details.
>
>> 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/common.h  |  1 +
>>   .../ethernet/stmicro/stmmac/dwmac-loongson.c  |  2 ++
>>   .../ethernet/stmicro/stmmac/dwmac1000_dma.c   | 10 ++++--
>>   .../net/ethernet/stmicro/stmmac/dwmac_dma.h   | 35 +++++++++++++++++++
>>   .../net/ethernet/stmicro/stmmac/dwmac_lib.c   | 35 +++++++++++++++----
>>   drivers/net/ethernet/stmicro/stmmac/hwif.c    |  3 +-
>>   .../net/ethernet/stmicro/stmmac/stmmac_main.c |  1 +
>>   include/linux/stmmac.h                        |  1 +
>>   8 files changed, 78 insertions(+), 10 deletions(-)
>>
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
>> index 721c1f8e892f..48ab21243b26 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/common.h
>> +++ b/drivers/net/ethernet/stmicro/stmmac/common.h
>> @@ -34,6 +34,7 @@
>>   #define DWMAC_CORE_5_00		0x50
>>   #define DWMAC_CORE_5_10		0x51
>>   #define DWMAC_CORE_5_20		0x52
>> +#define DWLGMAC_CORE_1_00	0x10
> This doesn't look correct because these IDs have been defined for the
> Synopsys IP-core enumerations. Loongson GNET is definitely based on
> some DW GMAC v3.x IP-core, but instead of updating the USERVER field
> vendor just overwrote the GMAC_VERSION.SNPSVER field. From that
> perspective the correct solution would be to override the
> priv->synopsys_id field with a correct IP-core version (0x37?). See my
> last comment for details of how to do that.
See my last reply.
>
>>   #define DWXGMAC_CORE_2_10	0x21
>>   #define DWXGMAC_CORE_2_20	0x22
>>   #define DWXLGMAC_CORE_2_00	0x20
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>> index 0d79104d7fd3..fb7506bbc21b 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>> @@ -101,6 +101,8 @@ static int loongson_dwmac_probe(struct pci_dev *pdev,
>>   		plat->mdio_bus_data->needs_reset = true;
>>   	}
>>   
>> +	plat->flags |= STMMAC_FLAG_HAS_LGMAC;
>> +
> If what I suggest in the last comment is implemented this will be
> unnecessary.
>
>>   	/* Enable pci device */
>>   	ret = pci_enable_device(pdev);
>>   	if (ret) {
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
>> index 0fb48e683970..a01fe6b7540a 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> None of the generic parts (dwmac1000_dma.c, dwmac_dma.h, dwmac_lib.c)
> will need to be modified if you implement what I suggest in the last
> comment.
>
>> @@ -118,7 +118,10 @@ static void dwmac1000_dma_init(struct stmmac_priv *priv, void __iomem *ioaddr,
> See my comment to patch 4/9. This method can be fully dropped in favor
> of having the dwmac1000_dma_init_channel() function implemented.
>
>>   	u32 dma_intr_mask;
>>   
>>   	/* Mask interrupts by writing to CSR7 */
>> -	dma_intr_mask = DMA_INTR_DEFAULT_MASK;
>> +	if (priv->plat->flags & STMMAC_FLAG_HAS_LGMAC)
>> +		dma_intr_mask = DMA_INTR_DEFAULT_MASK_LOONGSON;
>> +	else
>> +		dma_intr_mask = DMA_INTR_DEFAULT_MASK;
>>   
>>   	dma_config(ioaddr + DMA_BUS_MODE, ioaddr + DMA_INTR_ENA,
>>   			  dma_cfg, dma_intr_mask, atds);
>> @@ -130,7 +133,10 @@ static void dwmac1000_dma_init_channel(struct stmmac_priv *priv, void __iomem *i
>>   	u32 dma_intr_mask;
>>   
>>   	/* Mask interrupts by writing to CSR7 */
>> -	dma_intr_mask = DMA_INTR_DEFAULT_MASK;
>> +	if (priv->plat->flags & STMMAC_FLAG_HAS_LGMAC)
>> +		dma_intr_mask = DMA_INTR_DEFAULT_MASK_LOONGSON;
>> +	else
>> +		dma_intr_mask = DMA_INTR_DEFAULT_MASK;
>>   
>>   	if (dma_cfg->multi_msi_en)
>>   		dma_config(ioaddr + DMA_CHAN_BUS_MODE(chan),
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
>> index 395d5e4c3922..7d33798c0e72 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
>> @@ -70,16 +70,23 @@
>>   #define DMA_CONTROL_SR		0x00000002	/* Start/Stop Receive */
>>   
>>   /* DMA Normal interrupt */
>> +#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_ENA_NIE 0x00010000	/* Normal Summary */
>>   #define DMA_INTR_ENA_TIE 0x00000001	/* Transmit Interrupt */
>>   #define DMA_INTR_ENA_TUE 0x00000004	/* Transmit Buffer Unavailable */
>>   #define DMA_INTR_ENA_RIE 0x00000040	/* Receive Interrupt */
>>   #define DMA_INTR_ENA_ERE 0x00004000	/* Early Receive */
>>   
>> +#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_NORMAL	(DMA_INTR_ENA_NIE | DMA_INTR_ENA_RIE | \
>>   			DMA_INTR_ENA_TIE)
>>   
>>   /* DMA Abnormal interrupt */
>> +#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_ENA_AIE 0x00008000	/* Abnormal Summary */
>>   #define DMA_INTR_ENA_FBE 0x00002000	/* Fatal Bus Error */
>>   #define DMA_INTR_ENA_ETE 0x00000400	/* Early Transmit */
>> @@ -91,10 +98,14 @@
>>   #define DMA_INTR_ENA_TJE 0x00000008	/* Transmit Jabber */
>>   #define DMA_INTR_ENA_TSE 0x00000002	/* Transmit Stopped */
>>   
>> +#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_ABNORMAL	(DMA_INTR_ENA_AIE | DMA_INTR_ENA_FBE | \
>>   				DMA_INTR_ENA_UNE)
>>   
>>   /* DMA default interrupt mask */
>> +#define DMA_INTR_DEFAULT_MASK_LOONGSON	(DMA_INTR_NORMAL_LOONGSON | DMA_INTR_ABNORMAL_LOONGSON)
>>   #define DMA_INTR_DEFAULT_MASK	(DMA_INTR_NORMAL | DMA_INTR_ABNORMAL)
>>   #define DMA_INTR_DEFAULT_RX	(DMA_INTR_ENA_RIE)
>>   #define DMA_INTR_DEFAULT_TX	(DMA_INTR_ENA_TIE)
>> @@ -111,9 +122,15 @@
>>   #define DMA_STATUS_TS_SHIFT	20
>>   #define DMA_STATUS_RS_MASK	0x000e0000	/* Receive Process State */
>>   #define DMA_STATUS_RS_SHIFT	17
>> +#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_NIS	0x00010000	/* Normal 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_AIS	0x00008000	/* Abnormal Interrupt Summary */
>>   #define DMA_STATUS_ERI	0x00004000	/* Early Receive Interrupt */
>> +#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_FBI	0x00002000	/* Fatal Bus Error Interrupt */
>>   #define DMA_STATUS_ETI	0x00000400	/* Early Transmit Interrupt */
>>   #define DMA_STATUS_RWT	0x00000200	/* Receive Watchdog Timeout */
>> @@ -128,10 +145,21 @@
>>   #define DMA_STATUS_TI	0x00000001	/* Transmit Interrupt */
>>   #define DMA_CONTROL_FTF		0x00100000	/* Flush transmit FIFO */
>>   
>> +#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_COMMON		(DMA_STATUS_NIS | \
>>   					 DMA_STATUS_AIS | \
>>   					 DMA_STATUS_FBI)
>>   
>> +#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_RX		(DMA_STATUS_ERI | \
>>   					 DMA_STATUS_RWT | \
>>   					 DMA_STATUS_RPS | \
>> @@ -140,6 +168,13 @@
>>   					 DMA_STATUS_OVF | \
>>   					 DMA_STATUS_MSK_COMMON)
>>   
>> +#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)
>>   #define DMA_STATUS_MSK_TX		(DMA_STATUS_ETI | \
>>   					 DMA_STATUS_UNF | \
>>   					 DMA_STATUS_TJT | \
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
>> index 968801c694e9..a6e2ab4d0f4a 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
>> @@ -167,6 +167,9 @@ 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 nor_intr_status;
>> +	u32 abnor_intr_status;
>> +	u32 fb_intr_status;
>>   	u32 intr_status = readl(ioaddr + DMA_CHAN_STATUS(chan));
>>   
>>   #ifdef DWMAC_DMA_DEBUG
>> @@ -176,13 +179,31 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
>>   	show_rx_process_state(intr_status);
>>   #endif
>>   
>> -	if (dir == DMA_DIR_RX)
>> -		intr_status &= DMA_STATUS_MSK_RX;
>> -	else if (dir == DMA_DIR_TX)
>> -		intr_status &= DMA_STATUS_MSK_TX;
>> +	if (priv->plat->flags & STMMAC_FLAG_HAS_LGMAC) {
>> +		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);
>> +	} else {
>> +		if (dir == DMA_DIR_RX)
>> +			intr_status &= DMA_STATUS_MSK_RX;
>> +		else if (dir == DMA_DIR_TX)
>> +			intr_status &= DMA_STATUS_MSK_TX;
>> +
>> +		nor_intr_status = intr_status & DMA_STATUS_NIS;
>> +		abnor_intr_status = intr_status & DMA_STATUS_AIS;
>> +		fb_intr_status = intr_status & DMA_STATUS_FBI;
>> +	}
>>   
>>   	/* ABNORMAL interrupts */
>> -	if (unlikely(intr_status & DMA_STATUS_AIS)) {
>> +	if (unlikely(abnor_intr_status)) {
>>   		if (unlikely(intr_status & DMA_STATUS_UNF)) {
>>   			ret = tx_hard_error_bump_tc;
>>   			x->tx_undeflow_irq++;
>> @@ -205,13 +226,13 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
>>   			x->tx_process_stopped_irq++;
>>   			ret = tx_hard_error;
>>   		}
>> -		if (unlikely(intr_status & DMA_STATUS_FBI)) {
>> +		if (unlikely(intr_status & fb_intr_status)) {
>>   			x->fatal_bus_error_irq++;
>>   			ret = tx_hard_error;
>>   		}
>>   	}
>>   	/* TX/RX NORMAL interrupts */
>> -	if (likely(intr_status & DMA_STATUS_NIS)) {
>> +	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. */
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.c b/drivers/net/ethernet/stmicro/stmmac/hwif.c
>> index 1bd34b2a47e8..3724cf698de6 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/hwif.c
>> +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.c
>> @@ -59,7 +59,8 @@ static int stmmac_dwmac1_quirks(struct stmmac_priv *priv)
>>   		dev_info(priv->device, "Enhanced/Alternate descriptors\n");
>>   
>>   		/* GMAC older than 3.50 has no extended descriptors */
>> -		if (priv->synopsys_id >= DWMAC_CORE_3_50) {
>> +		if (priv->synopsys_id >= DWMAC_CORE_3_50 ||
>> +		    priv->synopsys_id == DWLGMAC_CORE_1_00) {
> This could be left as is if the priv->synopsys_id field is overwritten
> with a correct value (see my last comment).
>
>>   			dev_info(priv->device, "Enabled extended descriptors\n");
>>   			priv->extend_desc = 1;
>>   		} else {
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>> index d868eb8dafc5..9764d2ab7e46 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>> @@ -7218,6 +7218,7 @@ static int stmmac_hw_init(struct stmmac_priv *priv)
>>   	 * riwt_off field from the platform.
>>   	 */
>>   	if (((priv->synopsys_id >= DWMAC_CORE_3_50) ||
>> +		(priv->synopsys_id == DWLGMAC_CORE_1_00) ||
> the same comment here.
>
>>   	    (priv->plat->has_xgmac)) && (!priv->plat->riwt_off)) {
>>   		priv->use_riwt = 1;
>>   		dev_info(priv->device,
>> diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
>> index dee5ad6e48c5..f07f79d50b06 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_HAS_LGMAC			BIT(13)
> 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.
OK.
>
> 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.
It's easy.
>
> 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.

Do this in dwmac1000-dma.c? Because this seems impossible to achieve in 
dwmac-loongson.c:


drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c:606:47: error: 
initializer element is not constant
   606 | const struct stmmac_dma_ops dwlgmac_dma_ops = dwmac1000_dma_ops;
>     + override the stmmac_dma_ops.{dma_interrupt, init_chan} with
>       the pointers to the methods defined in 2.

Likewise, where should I do this?

Sorry. I seem to have misinterpreted your meaning again.



>     + 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.
>
> If I didn't miss something stmmac_hwif_init() will call the
> platform-specific setup method right after fetching the SNPSVER field
> value. Your setup method will allocate mac_device_info structure then,
> will pre-initialize the GNET-specific DMA ops field and fix the
> Synopsys ID with a proper value (as described in 3 above). The rest of
> the ops descriptors will be initialized in the loop afterwards based
> on the specified device ID.

This doesn't seem to work because our device looks something like this:

device     pci id   reversion    core version
LS7A        0x13       0x00       0x35/0x37
LS7A        0x13       0x01       0x35/0x37
LS2K        0x13       0x00       0x10
LS2K        0x13       0x01       0x10


Thanks,

Yanteng

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


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

* Re: [PATCH net-next v7 5/9] net: stmmac: Add Loongson-specific register definitions
  2024-01-01  8:31     ` Yanteng Si
@ 2024-01-01 12:26       ` Serge Semin
  2024-01-12 10:08         ` Yanteng Si
  2024-01-23 13:08         ` Yanteng Si
  0 siblings, 2 replies; 48+ messages in thread
From: Serge Semin @ 2024-01-01 12:26 UTC (permalink / raw)
  To: Yanteng Si
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

On Mon, Jan 01, 2024 at 04:31:48PM +0800, Yanteng Si wrote:
> 
> 在 2023/12/21 10:14, Serge Semin 写道:
> > On Tue, Dec 19, 2023 at 10:26:45PM +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.
> > Thanks for the updated patch. It looks much clearer now. Thanks to
> > that I came up with a better and less invasive solution. See my last
> > comment for details.
> > 
> > > 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/common.h  |  1 +
> > >   .../ethernet/stmicro/stmmac/dwmac-loongson.c  |  2 ++
> > >   .../ethernet/stmicro/stmmac/dwmac1000_dma.c   | 10 ++++--
> > >   .../net/ethernet/stmicro/stmmac/dwmac_dma.h   | 35 +++++++++++++++++++
> > >   .../net/ethernet/stmicro/stmmac/dwmac_lib.c   | 35 +++++++++++++++----
> > >   drivers/net/ethernet/stmicro/stmmac/hwif.c    |  3 +-
> > >   .../net/ethernet/stmicro/stmmac/stmmac_main.c |  1 +
> > >   include/linux/stmmac.h                        |  1 +
> > >   8 files changed, 78 insertions(+), 10 deletions(-)
> > > 
> > > diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
> > > index 721c1f8e892f..48ab21243b26 100644
> > > --- a/drivers/net/ethernet/stmicro/stmmac/common.h
> > > +++ b/drivers/net/ethernet/stmicro/stmmac/common.h
> > > @@ -34,6 +34,7 @@
> > >   #define DWMAC_CORE_5_00		0x50
> > >   #define DWMAC_CORE_5_10		0x51
> > >   #define DWMAC_CORE_5_20		0x52
> > > +#define DWLGMAC_CORE_1_00	0x10
> > This doesn't look correct because these IDs have been defined for the
> > Synopsys IP-core enumerations. Loongson GNET is definitely based on
> > some DW GMAC v3.x IP-core, but instead of updating the USERVER field
> > vendor just overwrote the GMAC_VERSION.SNPSVER field. From that
> > perspective the correct solution would be to override the
> > priv->synopsys_id field with a correct IP-core version (0x37?). See my
> > last comment for details of how to do that.
> See my last reply.
> > 
> > >   #define DWXGMAC_CORE_2_10	0x21
> > >   #define DWXGMAC_CORE_2_20	0x22
> > >   #define DWXLGMAC_CORE_2_00	0x20
> > > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > index 0d79104d7fd3..fb7506bbc21b 100644
> > > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > @@ -101,6 +101,8 @@ static int loongson_dwmac_probe(struct pci_dev *pdev,
> > >   		plat->mdio_bus_data->needs_reset = true;
> > >   	}
> > > +	plat->flags |= STMMAC_FLAG_HAS_LGMAC;
> > > +
> > If what I suggest in the last comment is implemented this will be
> > unnecessary.
> > 
> > >   	/* Enable pci device */
> > >   	ret = pci_enable_device(pdev);
> > >   	if (ret) {
> > > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> > > index 0fb48e683970..a01fe6b7540a 100644
> > > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> > > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> > None of the generic parts (dwmac1000_dma.c, dwmac_dma.h, dwmac_lib.c)
> > will need to be modified if you implement what I suggest in the last
> > comment.
> > 
> > > @@ -118,7 +118,10 @@ static void dwmac1000_dma_init(struct stmmac_priv *priv, void __iomem *ioaddr,
> > See my comment to patch 4/9. This method can be fully dropped in favor
> > of having the dwmac1000_dma_init_channel() function implemented.
> > 
> > >   	u32 dma_intr_mask;
> > >   	/* Mask interrupts by writing to CSR7 */
> > > -	dma_intr_mask = DMA_INTR_DEFAULT_MASK;
> > > +	if (priv->plat->flags & STMMAC_FLAG_HAS_LGMAC)
> > > +		dma_intr_mask = DMA_INTR_DEFAULT_MASK_LOONGSON;
> > > +	else
> > > +		dma_intr_mask = DMA_INTR_DEFAULT_MASK;
> > >   	dma_config(ioaddr + DMA_BUS_MODE, ioaddr + DMA_INTR_ENA,
> > >   			  dma_cfg, dma_intr_mask, atds);
> > > @@ -130,7 +133,10 @@ static void dwmac1000_dma_init_channel(struct stmmac_priv *priv, void __iomem *i
> > >   	u32 dma_intr_mask;
> > >   	/* Mask interrupts by writing to CSR7 */
> > > -	dma_intr_mask = DMA_INTR_DEFAULT_MASK;
> > > +	if (priv->plat->flags & STMMAC_FLAG_HAS_LGMAC)
> > > +		dma_intr_mask = DMA_INTR_DEFAULT_MASK_LOONGSON;
> > > +	else
> > > +		dma_intr_mask = DMA_INTR_DEFAULT_MASK;
> > >   	if (dma_cfg->multi_msi_en)
> > >   		dma_config(ioaddr + DMA_CHAN_BUS_MODE(chan),
> > > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
> > > index 395d5e4c3922..7d33798c0e72 100644
> > > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
> > > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
> > > @@ -70,16 +70,23 @@
> > >   #define DMA_CONTROL_SR		0x00000002	/* Start/Stop Receive */
> > >   /* DMA Normal interrupt */
> > > +#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_ENA_NIE 0x00010000	/* Normal Summary */
> > >   #define DMA_INTR_ENA_TIE 0x00000001	/* Transmit Interrupt */
> > >   #define DMA_INTR_ENA_TUE 0x00000004	/* Transmit Buffer Unavailable */
> > >   #define DMA_INTR_ENA_RIE 0x00000040	/* Receive Interrupt */
> > >   #define DMA_INTR_ENA_ERE 0x00004000	/* Early Receive */
> > > +#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_NORMAL	(DMA_INTR_ENA_NIE | DMA_INTR_ENA_RIE | \
> > >   			DMA_INTR_ENA_TIE)
> > >   /* DMA Abnormal interrupt */
> > > +#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_ENA_AIE 0x00008000	/* Abnormal Summary */
> > >   #define DMA_INTR_ENA_FBE 0x00002000	/* Fatal Bus Error */
> > >   #define DMA_INTR_ENA_ETE 0x00000400	/* Early Transmit */
> > > @@ -91,10 +98,14 @@
> > >   #define DMA_INTR_ENA_TJE 0x00000008	/* Transmit Jabber */
> > >   #define DMA_INTR_ENA_TSE 0x00000002	/* Transmit Stopped */
> > > +#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_ABNORMAL	(DMA_INTR_ENA_AIE | DMA_INTR_ENA_FBE | \
> > >   				DMA_INTR_ENA_UNE)
> > >   /* DMA default interrupt mask */
> > > +#define DMA_INTR_DEFAULT_MASK_LOONGSON	(DMA_INTR_NORMAL_LOONGSON | DMA_INTR_ABNORMAL_LOONGSON)
> > >   #define DMA_INTR_DEFAULT_MASK	(DMA_INTR_NORMAL | DMA_INTR_ABNORMAL)
> > >   #define DMA_INTR_DEFAULT_RX	(DMA_INTR_ENA_RIE)
> > >   #define DMA_INTR_DEFAULT_TX	(DMA_INTR_ENA_TIE)
> > > @@ -111,9 +122,15 @@
> > >   #define DMA_STATUS_TS_SHIFT	20
> > >   #define DMA_STATUS_RS_MASK	0x000e0000	/* Receive Process State */
> > >   #define DMA_STATUS_RS_SHIFT	17
> > > +#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_NIS	0x00010000	/* Normal 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_AIS	0x00008000	/* Abnormal Interrupt Summary */
> > >   #define DMA_STATUS_ERI	0x00004000	/* Early Receive Interrupt */
> > > +#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_FBI	0x00002000	/* Fatal Bus Error Interrupt */
> > >   #define DMA_STATUS_ETI	0x00000400	/* Early Transmit Interrupt */
> > >   #define DMA_STATUS_RWT	0x00000200	/* Receive Watchdog Timeout */
> > > @@ -128,10 +145,21 @@
> > >   #define DMA_STATUS_TI	0x00000001	/* Transmit Interrupt */
> > >   #define DMA_CONTROL_FTF		0x00100000	/* Flush transmit FIFO */
> > > +#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_COMMON		(DMA_STATUS_NIS | \
> > >   					 DMA_STATUS_AIS | \
> > >   					 DMA_STATUS_FBI)
> > > +#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_RX		(DMA_STATUS_ERI | \
> > >   					 DMA_STATUS_RWT | \
> > >   					 DMA_STATUS_RPS | \
> > > @@ -140,6 +168,13 @@
> > >   					 DMA_STATUS_OVF | \
> > >   					 DMA_STATUS_MSK_COMMON)
> > > +#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)
> > >   #define DMA_STATUS_MSK_TX		(DMA_STATUS_ETI | \
> > >   					 DMA_STATUS_UNF | \
> > >   					 DMA_STATUS_TJT | \
> > > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
> > > index 968801c694e9..a6e2ab4d0f4a 100644
> > > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
> > > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
> > > @@ -167,6 +167,9 @@ 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 nor_intr_status;
> > > +	u32 abnor_intr_status;
> > > +	u32 fb_intr_status;
> > >   	u32 intr_status = readl(ioaddr + DMA_CHAN_STATUS(chan));
> > >   #ifdef DWMAC_DMA_DEBUG
> > > @@ -176,13 +179,31 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
> > >   	show_rx_process_state(intr_status);
> > >   #endif
> > > -	if (dir == DMA_DIR_RX)
> > > -		intr_status &= DMA_STATUS_MSK_RX;
> > > -	else if (dir == DMA_DIR_TX)
> > > -		intr_status &= DMA_STATUS_MSK_TX;
> > > +	if (priv->plat->flags & STMMAC_FLAG_HAS_LGMAC) {
> > > +		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);
> > > +	} else {
> > > +		if (dir == DMA_DIR_RX)
> > > +			intr_status &= DMA_STATUS_MSK_RX;
> > > +		else if (dir == DMA_DIR_TX)
> > > +			intr_status &= DMA_STATUS_MSK_TX;
> > > +
> > > +		nor_intr_status = intr_status & DMA_STATUS_NIS;
> > > +		abnor_intr_status = intr_status & DMA_STATUS_AIS;
> > > +		fb_intr_status = intr_status & DMA_STATUS_FBI;
> > > +	}
> > >   	/* ABNORMAL interrupts */
> > > -	if (unlikely(intr_status & DMA_STATUS_AIS)) {
> > > +	if (unlikely(abnor_intr_status)) {
> > >   		if (unlikely(intr_status & DMA_STATUS_UNF)) {
> > >   			ret = tx_hard_error_bump_tc;
> > >   			x->tx_undeflow_irq++;
> > > @@ -205,13 +226,13 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
> > >   			x->tx_process_stopped_irq++;
> > >   			ret = tx_hard_error;
> > >   		}
> > > -		if (unlikely(intr_status & DMA_STATUS_FBI)) {
> > > +		if (unlikely(intr_status & fb_intr_status)) {
> > >   			x->fatal_bus_error_irq++;
> > >   			ret = tx_hard_error;
> > >   		}
> > >   	}
> > >   	/* TX/RX NORMAL interrupts */
> > > -	if (likely(intr_status & DMA_STATUS_NIS)) {
> > > +	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. */
> > > diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.c b/drivers/net/ethernet/stmicro/stmmac/hwif.c
> > > index 1bd34b2a47e8..3724cf698de6 100644
> > > --- a/drivers/net/ethernet/stmicro/stmmac/hwif.c
> > > +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.c
> > > @@ -59,7 +59,8 @@ static int stmmac_dwmac1_quirks(struct stmmac_priv *priv)
> > >   		dev_info(priv->device, "Enhanced/Alternate descriptors\n");
> > >   		/* GMAC older than 3.50 has no extended descriptors */
> > > -		if (priv->synopsys_id >= DWMAC_CORE_3_50) {
> > > +		if (priv->synopsys_id >= DWMAC_CORE_3_50 ||
> > > +		    priv->synopsys_id == DWLGMAC_CORE_1_00) {
> > This could be left as is if the priv->synopsys_id field is overwritten
> > with a correct value (see my last comment).
> > 
> > >   			dev_info(priv->device, "Enabled extended descriptors\n");
> > >   			priv->extend_desc = 1;
> > >   		} else {
> > > diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> > > index d868eb8dafc5..9764d2ab7e46 100644
> > > --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> > > +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> > > @@ -7218,6 +7218,7 @@ static int stmmac_hw_init(struct stmmac_priv *priv)
> > >   	 * riwt_off field from the platform.
> > >   	 */
> > >   	if (((priv->synopsys_id >= DWMAC_CORE_3_50) ||
> > > +		(priv->synopsys_id == DWLGMAC_CORE_1_00) ||
> > the same comment here.
> > 
> > >   	    (priv->plat->has_xgmac)) && (!priv->plat->riwt_off)) {
> > >   		priv->use_riwt = 1;
> > >   		dev_info(priv->device,
> > > diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
> > > index dee5ad6e48c5..f07f79d50b06 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_HAS_LGMAC			BIT(13)
> > 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.
> OK.
> > 
> > 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.
> It's easy.
> > 
> > 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.
> 

> Do this in dwmac1000-dma.c? Because this seems impossible to achieve in
> dwmac-loongson.c:
> 
> 
> drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c:606:47: error:
> initializer element is not constant
>   606 | const struct stmmac_dma_ops dwlgmac_dma_ops = dwmac1000_dma_ops;
> >     + override the stmmac_dma_ops.{dma_interrupt, init_chan} with
> >       the pointers to the methods defined in 2.
> 
> Likewise, where should I do this?
> 
> Sorry. I seem to have misinterpreted your meaning again.

No worries. Here is what I meant:

1. Declare the private Loongson GMAC data like this:
struct loongson_data {
	struct stmmac_dma_ops dma_ops;
};
2. Allocate the memory for the data in the framework of the Loongson
GMAC device probe() method:
loongson_dwmac_probe()
{
	...
	ld = devm_kzalloc(&pdev->dev, sizeof(*ld), GFP_KERNEL);
	if (!ld)
		return -ENOMEM;
	...
	ld->dma_ops = dwmac1000_dma_ops;
	ld->dma_ops.init_chan = loongson_gnat_dma_init_chan;
	ld->dma_ops.dma_interrupt = loongson_gnat_dma_interrupt;
	...
	plat->bsp_priv = ld;
}
3. Define the Loongson-specific plat_stmmacenet_data.setup() method,
which would re-init the stmmac_priv->synopsys_id with a correct value,
allocate the DW *MAC hardware descriptor and pre-initialize it 'dma'
field:
static struct mac_device_info loongson_gnet_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;

	priv->synopsys_id = 0x37; // or whatever is a real version of your IP

	ld = priv->plat->bsp_priv;
	mac->dma = &ld->dma_ops;

	dwmac1000_setup(); // Or Pre-initialize the respective "mac" fields as it's done in dwmac1000_setup()

	return mac;
}
4. Make sure the plat_stmmacenet_data->setup field is initialized with
the Loongson GNAT-specific setup() method:
static int loongson_gnet_data(struct pci_dev *pdev,
                              struct plat_stmmacenet_data *plat)
{
	...
	plat->setup = loongson_gnet_setup;
	...
}

That shall do what I described in by previous message.

Note another platform which gets to define its own setup() method
Sun8i:
drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
although since it fully redefines the DMA-ops descriptor the only
common part with your case is that it needs to have the setup() method
too.

> 
> 
> 
> >     + 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.
> > 
> > If I didn't miss something stmmac_hwif_init() will call the
> > platform-specific setup method right after fetching the SNPSVER field
> > value. Your setup method will allocate mac_device_info structure then,
> > will pre-initialize the GNET-specific DMA ops field and fix the
> > Synopsys ID with a proper value (as described in 3 above). The rest of
> > the ops descriptors will be initialized in the loop afterwards based
> > on the specified device ID.
> 

> This doesn't seem to work because our device looks something like this:

Please see my note above.

> 
> device     pci id   reversion    core version
> LS7A        0x13       0x00       0x35/0x37
> LS7A        0x13       0x01       0x35/0x37
> LS2K        0x13       0x00       0x10
> LS2K        0x13       0x01       0x10

Not sure what you meant by providing this table to me and justifying
that something wouldn't work. But it would have been much useful to
provide a detailed description of what platforms and devices the
current dwmac-loongson.c driver supports and what support you are
trying to add. Cover-letter is a suitable place for it.

In anyway the DW GMAC IP-core can't be 0x10. Seeing your device is
having the multi-channels support it must have a version closer to
0x37 (the highest IP-core version is 3.73a). Please reach the hardware
engineers to clarify what actual DW GMAC IP-core has been utilized in
your case.

-Serge(y)

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

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

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

On Mon, Jan 01, 2024 at 02:57:37PM +0800, Yanteng Si wrote:
> 
> 在 2023/12/30 19:25, Serge Semin 写道:
> > Hi Yanteng
> > 
> > On Fri, Dec 29, 2023 at 06:33:52PM +0800, Yanteng Si wrote:
> > > 在 2023/12/21 06:36, Serge Semin 写道:
> > > > On Tue, Dec 19, 2023 at 10:17:07PM +0800, Yanteng Si wrote:
> > > > > Loongson platforms use a DWGMAC which supports multi-channel.
> > > > > 
> > > > > Added dwmac1000_dma_init_channel() and init_chan(), factor out
> > > > > all the channel-specific setups from dwmac1000_dma_init() to the
> > > > > new function dma_config(), then distinguish dma initialization
> > > > > and multi-channel initialization through different parameters.
> > > > > 
> > > > > 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/dwmac1000_dma.c   | 55 ++++++++++++++-----
> > > > >    .../net/ethernet/stmicro/stmmac/dwmac_dma.h   | 17 ++++++
> > > > >    .../net/ethernet/stmicro/stmmac/dwmac_lib.c   | 30 +++++-----
> > > > >    3 files changed, 74 insertions(+), 28 deletions(-)
> > > > > 
> > > > > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> > > > > index 5e80d3eec9db..0fb48e683970 100644
> > > > > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> > > > > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> > > > > @@ -12,7 +12,8 @@
> > > > >      Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
> > > > >    *******************************************************************************/
> > > > > -#include <asm/io.h>
> > > > > +#include <linux/io.h>
> > > > > +#include "stmmac.h"
> > > > >    #include "dwmac1000.h"
> > > > >    #include "dwmac_dma.h"
> > > > > @@ -70,13 +71,16 @@ static void dwmac1000_dma_axi(void __iomem *ioaddr, struct stmmac_axi *axi)
> > > > >    	writel(value, ioaddr + DMA_AXI_BUS_MODE);
> > > > >    }
> > > > > -static void dwmac1000_dma_init(struct stmmac_priv *priv, void __iomem *ioaddr,
> > > > > -			       struct stmmac_dma_cfg *dma_cfg, int atds)
> > > > > +static void dma_config(void __iomem *modeaddr, void __iomem *enaddr,
> > > > > +					   struct stmmac_dma_cfg *dma_cfg, u32 dma_intr_mask,
> > > > > +					   int atds)
> > > > Please make sure the arguments are aligned with the function open
> > > > parenthesis taking into account that tabs are of _8_ chars:
> > > > Documentation/process/coding-style.rst.
> > > OK.
> > > > >    {
> > > > > -	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;
> > > > > +	value = readl(modeaddr);
> > > > > +
> > > > >    	/*
> > > > >    	 * Set the DMA PBL (Programmable Burst Length) mode.
> > > > >    	 *
> > > > > @@ -104,10 +108,34 @@ static void dwmac1000_dma_init(struct stmmac_priv *priv, void __iomem *ioaddr,
> > > > >    	if (dma_cfg->aal)
> > > > >    		value |= DMA_BUS_MODE_AAL;
> > > > > -	writel(value, ioaddr + DMA_BUS_MODE);
> > > > > +	writel(value, modeaddr);
> > > > > +	writel(dma_intr_mask, enaddr);
> > > > > +}
> > > > > +
> > > > > +static void dwmac1000_dma_init(struct stmmac_priv *priv, void __iomem *ioaddr,
> > > > > +							   struct stmmac_dma_cfg *dma_cfg, int atds)
> > > > > +{
> > > > > +	u32 dma_intr_mask;
> > > > >    	/* Mask interrupts by writing to CSR7 */
> > > > > -	writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_INTR_ENA);
> > > > > +	dma_intr_mask = DMA_INTR_DEFAULT_MASK;
> > > > > +
> > > > > +	dma_config(ioaddr + DMA_BUS_MODE, ioaddr + DMA_INTR_ENA,
> > > > > +			  dma_cfg, dma_intr_mask, atds);
> > > > > +}
> > > > > +
> > > > > +static void dwmac1000_dma_init_channel(struct stmmac_priv *priv, void __iomem *ioaddr,
> > > > > +									   struct stmmac_dma_cfg *dma_cfg, u32 chan)
> > > > > +{
> > > > > +	u32 dma_intr_mask;
> > > > > +
> > > > > +	/* Mask interrupts by writing to CSR7 */
> > > > > +	dma_intr_mask = DMA_INTR_DEFAULT_MASK;
> > > > > +
> > > > > +	if (dma_cfg->multi_msi_en)
> > > > > +		dma_config(ioaddr + DMA_CHAN_BUS_MODE(chan),
> > > > > +					ioaddr + DMA_CHAN_INTR_ENA(chan), dma_cfg,
> > > > Why so complicated? stmmac_init_chan() is always supposed to be called
> > > > in the same context as stmmac_dma_init() (stmmac_xdp_open() is wrong
> > > > in not doing that). Seeing DW GMAC v3.x multi-channels feature is
> > > > implemented as multiple sets of the same CSRs (except AV traffic
> > > > control CSRs specific to channels 1 and higher which are left unused
> > > > here anyway) you can just drop the stmmac_dma_ops.init() callback and
> > > > convert dwmac1000_dma_init() to being dwmac1000_dma_init_channel()
> > > > with no significant modifications:
> > > > 
> > > > < you wouldn't need to have a separate dma_config() method.
> > > > < you wouldn't need to check for the dma_cfg->multi_msi_en flag state
> > > > since the stmmac_init_chan() method is called for as many times as
> > > > there are channels available (at least 1 channel always exists).
> > > > < just add atds argument.
> > > > < just convert the method to using the chan-dependent CSR macros.
> > > Yes, you are right.
> > > 
> > > > > +					dma_intr_mask, dma_cfg->multi_msi_en);
> > > >                                                                   ^
> > > >                 +-------------------------------------------------+
> > > > This is wrong + ATDS flag means Alternative Descriptor Size. This flag
> > > > enables the 8 dword DMA-descriptors size with some DMA-desc fields
> > > > semantics changed (see enh_desc.c and norm_desc.c). It's useful for
> > > > PTP Timestamping, VLANs, AV feature, L3/L4 filtering, CSum offload
> > > > Type 2 (if any of that available). It has nothing to do with the
> > > > separate DMA IRQs. Just convert the stmmac_dma_ops.dma_init() callback
> > > > to accepting the atds flag as an additional argument, use it here to
> > > > activate the extended descriptor size and make sure the atds flag is
> > > > passed to the stmmac_init_chan() method in the respective source code.
> > > OK.
> > > > >    }
> > > > >    static void dwmac1000_dma_init_rx(struct stmmac_priv *priv,
> > > > > @@ -116,7 +144,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 +153,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 +181,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 +203,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 +237,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 +299,13 @@ 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,
> > > > This could be dropped. See my comment above.
> > > OK,  I've tried this and it works.
> > > > > +	.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 e7aef136824b..395d5e4c3922 100644
> > > > > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
> > > > > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
> > > > > @@ -148,6 +148,9 @@
> > > > >    					 DMA_STATUS_TI | \
> > > > >    					 DMA_STATUS_MSK_COMMON)
> > > > > +/* Following DMA defines are chanels oriented */
> > > > s/chanels/channels
> > > OK!
> > > > > +#define DMA_CHAN_OFFSET			0x100
> > > > DMA_CHAN_BASE_OFFSET? to be looking the same as in DW QoS Eth GMAC
> > > > v4.x/v5.x (dwmac4_dma.h).
> > > OK
> > > > > +
> > > > >    #define NUM_DWMAC100_DMA_REGS	9
> > > > >    #define NUM_DWMAC1000_DMA_REGS	23
> > > > >    #define NUM_DWMAC4_DMA_REGS	27
> > > > > @@ -170,4 +173,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 2f0df16fb7e4..968801c694e9 100644
> > > > > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
> > > > > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
> > > > > @@ -31,63 +31,63 @@ int dwmac_dma_reset(void __iomem *ioaddr)
> > > > >    void dwmac_enable_dma_transmission(struct stmmac_priv *priv,
> > > > >    				   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
> > > > > @@ -167,7 +167,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 */
> > > > > @@ -237,7 +237,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));
> > > > Em, please explain the mask change. Bits CSR5[17:28] are defined as RO
> > > I'm not sure I can explain it, but it goes something like this:
> > > 
> > > We moved these bits up because we split the reception and transmission of
> > > interrupts.
> > > 
> > > 28    Reserved
> > > 27:25 EB
> > > 24:22 TS
> > > 21:19 RS
> > > 18    NTIS
> > I see. Thanks for clarification. Let's postpone the IRQ mask
> > discussion for the next review round.
> OK.
> > 
> > > 
> > > > on a normal DW GMAC. Anyway it seems like the mask changes belongs to
> > > > the patch 5/9.
> > > Yes, I will try.
> > > > 
> > > > Except the last comment, AFAICS this patch provides a generic DW GMAC
> > > > v3.x multi-channel support. Despite of several issues noted above the
> > > > change in general looks very good.
> > > Thanks, the next version of this patch will only have changes related to
> > > dma_chan_base_addr.
> > > 
> > > 
> > > * dwmac1000_dma_init will be restored.
> > > 
> > > * dwmac1000_dma_init_channel() will be moved to dwmac-loongson.c.
> > No. That's not what I meant. I said that this patch looks _generic_
> > enough to be applied (with my notes taken into account) in the common
> > dwmac1000_dma.c code! It provides useful multi-DMA-channels support in
> > a way it's implemented by the _generic_ DW GMAC v3.x IP-core. From
> > that perspective the change will be useful for all users which DW
> > GMACs support the multi-channels feature. Please fix the patch based
> > on my notes and repost it as a part of your series. We'll figure out
> > what to do with the IRQ mask on the next review round.
> 
> Em, I see.
> 
> In dwmac1000_dma.c:
> 

> 1. Convert dwmac1000_dma_init() to being dwmac1000_dma_init_channel(); (No
> DMA_INTR_DEFAULT_MASK_LOONGSON)

Right.

> 
> 2. Drop the stmmac_dma_ops.init() callback;

Right. (I'd say that this is implied by 1.)

> 
> 3. Leave other parts of the patch unchanged, such as DMA_CHAN_BASE_OFFSET;

Right. Just take my comments to this patch into account and drop the
Loongson-specific changes, like 0x1ffff->0x7ffff change in
dwmac_dma_interrupt().

> 

> In dwmac-loongson.c:
> 
> 1. Create the Loongson GNET-specific stmmac_dma_ops.dma_interrupt() and stmmac_dma_ops.init_chan(); (With DMA_INTR_DEFAULT_MASK_LOONGSON)
> 2. Move all the Loongson-specific macros from dwmac_dma.h to here;
> 3. Follow your comments in Patch 5 to continue;
> 
> Right?

Right. This patch should be preserved because it will be useful for
the driver further evolution and for the users having multi-channel DW
GMAC v3.x devices. Meanwhile if you implement what I suggested in
Patch 5, there will be almost no need in the generic STMMAC driver
code update.

-Serge(y)

> 
> 
> Thanks,
> Yanteng
> 
> > 
> > -Serge(y)
> > 
> > > 
> > > Thanks for your review!
> > > 
> > > 
> > > Thanks,
> > > 
> > > Yanteng
> > > 
> > > > -Serge(y)
> > > > 
> > > > >    	return ret;
> > > > >    }
> > > > > -- 
> > > > > 2.31.4
> > > > > 
> 

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

* Re: [PATCH net-next v7 7/9] net: stmmac: dwmac-loongson: Add GNET support
  2024-01-01  7:27     ` Yanteng Si
@ 2024-01-02  1:22       ` Serge Semin
  2024-01-25  6:57         ` Yanteng Si
  2024-01-29 11:45         ` Yanteng Si
  2024-01-24  9:21       ` Yanteng Si
  1 sibling, 2 replies; 48+ messages in thread
From: Serge Semin @ 2024-01-02  1:22 UTC (permalink / raw)
  To: Yanteng Si
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

On Mon, Jan 01, 2024 at 03:27:07PM +0800, Yanteng Si wrote:
> 
> 在 2023/12/21 10:34, Serge Semin 写道:
> > On Tue, Dec 19, 2023 at 10:26:47PM +0800, Yanteng Si wrote:
> > > Add Loongson GNET (GMAC with PHY) support. Current GNET does not support
> > > half duplex mode, and 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  | 79 +++++++++++++++++++
> > >   .../ethernet/stmicro/stmmac/stmmac_ethtool.c  |  6 ++
> > >   include/linux/stmmac.h                        |  2 +
> > >   3 files changed, 87 insertions(+)
> > > 
> > > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > index 2c08d5495214..9e4953c7e4e0 100644
> > > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > @@ -168,6 +168,83 @@ 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 net_device *ndev = dev_get_drvdata(priv);
> > > +	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);
> > {} around the outer if please.
> OK.
> > 
> > > +}
> > > +
> > > +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 = 0xfffffffb;
> > ~BIT(2)?
> I still need to confirm, please allow me to get back to you later.
> > 
> > > +
> > > +	plat->phy_addr = 2;
> > > +	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;
> > > +
> > > +	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;
> > > +	u32 version = readl(res->addr + GMAC_VERSION);
> > > +
> > > +	switch (version & 0xff) {
> > > +	case DWLGMAC_CORE_1_00:
> > > +		ret = loongson_dwmac_config_multi_msi(pdev, plat, res, np, 8);
> > > +		break;
> > > +	default:
> > > +		ret = loongson_dwmac_config_legacy(pdev, plat, res, np);

> > Hm, do you have two versions of Loongson GNET? What does the second
> Yes.
> > one contain in the GMAC_VERSION register then? Can't you distinguish
> > them by the PCI IDs (device, subsystem, revision)?
> 
> I'm afraid that's not possible.
> 
> Because they have the same pci id and revision.

Please provide more details about what platform/devices support you
are adding and what PCI IDs and DW GMAC IP-core version they have.

> 
> 
> Thanks,
> 
> Yanteng
> 
> > 
> > -Serge(y)
> > 
> > > +		break;
> > > +	}
> > > +
> > > +	switch (pdev->revision) {
> > > +	case 0x00:
> > > +		plat->flags |=
> > > +			FIELD_PREP(STMMAC_FLAG_DISABLE_HALF_DUPLEX, 1) |
> > > +			FIELD_PREP(STMMAC_FLAG_DISABLE_FORCE_1000, 1);
> > > +		break;
> > > +	case 0x01:
> > > +		plat->flags |=
> > > +			FIELD_PREP(STMMAC_FLAG_DISABLE_HALF_DUPLEX, 1);
> > > +		break;
> > > +	default:
> > > +		break;
> > > +	}
> > > +
> > > +	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)
> > >   {
> > > @@ -318,9 +395,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);
> > > diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> > > index 8105ce47c6ad..d6939eb9a0d8 100644
> > > --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> > > +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> > > @@ -420,6 +420,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 f07f79d50b06..067030cdb60f 100644
> > > --- a/include/linux/stmmac.h
> > > +++ b/include/linux/stmmac.h
> > > @@ -222,6 +222,8 @@ struct dwmac4_addrs {
> > >   #define STMMAC_FLAG_EN_TX_LPI_CLOCKGATING	BIT(11)
> > >   #define STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY	BIT(12)
> > >   #define STMMAC_FLAG_HAS_LGMAC			BIT(13)

> > > +#define STMMAC_FLAG_DISABLE_HALF_DUPLEX	BIT(14)

Just noticed. I do not see this flag affecting any part of the code.
Drop it if no actual action is implied by it.

-Serge(y)

> > > +#define STMMAC_FLAG_DISABLE_FORCE_1000	BIT(15)
> > >   struct plat_stmmacenet_data {
> > >   	int bus_id;
> > > -- 
> > > 2.31.4
> > > 
> 

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

* Re: [PATCH net-next v7 2/9] net: stmmac: dwmac-loongson: Refactor code for loongson_dwmac_probe()
  2023-12-19 14:17 ` [PATCH net-next v7 2/9] net: stmmac: dwmac-loongson: Refactor code for loongson_dwmac_probe() Yanteng Si
@ 2024-01-02 10:37   ` Russell King (Oracle)
  2024-01-18 12:53     ` Yanteng Si
  0 siblings, 1 reply; 48+ messages in thread
From: Russell King (Oracle) @ 2024-01-02 10:37 UTC (permalink / raw)
  To: Yanteng Si
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	fancer.lancer, Jose.Abreu, chenhuacai, guyinggang, netdev,
	chris.chenfeiyang

On Tue, Dec 19, 2023 at 10:17:05PM +0800, Yanteng Si wrote:
> Add a setup() function to initialize data, and simplify code for
> loongson_dwmac_probe().

Not all changes in this patch are described.

> +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->phy_interface = PHY_INTERFACE_MODE_RGMII_ID;

This presumably sets the default phy_interface mode?


> -	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;

loongson_gmac_data() gets called from here...

> +
> +	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) {

This gets the PHY interface mode, and errors out if it can't be found in
firmware.

> @@ -110,11 +137,7 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
>  	}
>  
>  	plat->phy_interface = phy_mode;

So this ends up always overwriting the value written in
loongson_gmac_data(). So it seems to be that initialising
plat->phy_interface in loongson_gmac_data() is just patch noise and
serves no real purpose.

> -	plat->mac_interface = PHY_INTERFACE_MODE_GMII;

This has now gone - and is not described, and I'm left wondering what
the implication of that is on the driver. It also makes me wonder
whether loongson_gmac_data() should've been setting mac_interface
rather than phy_interface.

>  	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");
> +		dev_info(&pdev->dev,
> +			 "IRQ eth_wake_irq not found, using macirq\n");

Whitespace cleanups should be a separate patch.

-- 
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] 48+ messages in thread

* Re: [PATCH net-next v7 3/9] net: stmmac: dwmac-loongson: Add full PCI support
  2023-12-19 14:17 ` [PATCH net-next v7 3/9] net: stmmac: dwmac-loongson: Add full PCI support Yanteng Si
@ 2024-01-02 10:40   ` Russell King (Oracle)
  2024-01-12  9:42     ` Yanteng Si
  2024-01-18 12:56     ` Yanteng Si
  0 siblings, 2 replies; 48+ messages in thread
From: Russell King (Oracle) @ 2024-01-02 10:40 UTC (permalink / raw)
  To: Yanteng Si
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	fancer.lancer, Jose.Abreu, chenhuacai, guyinggang, netdev,
	chris.chenfeiyang

On Tue, Dec 19, 2023 at 10:17:06PM +0800, Yanteng Si wrote:
> @@ -125,42 +126,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;
> -

So this is why phy_interface changes in patch 2. It would have been good
to make a forward reference to this change to explain in patch 2 why the
"default" value has been set there. Or maybe move the setting of that
default value into this patch?

-- 
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] 48+ messages in thread

* Re: [PATCH net-next v7 3/9] net: stmmac: dwmac-loongson: Add full PCI support
  2024-01-02 10:40   ` Russell King (Oracle)
@ 2024-01-12  9:42     ` Yanteng Si
  2024-01-18 12:56     ` Yanteng Si
  1 sibling, 0 replies; 48+ messages in thread
From: Yanteng Si @ 2024-01-12  9:42 UTC (permalink / raw)
  To: Russell King (Oracle)
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	fancer.lancer, Jose.Abreu, chenhuacai, guyinggang, netdev,
	chris.chenfeiyang


在 2024/1/2 18:40, Russell King (Oracle) 写道:
> On Tue, Dec 19, 2023 at 10:17:06PM +0800, Yanteng Si wrote:
>> @@ -125,42 +126,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;
>> -
> So this is why phy_interface changes in patch 2. It would have been good
> to make a forward reference to this change to explain in patch 2 why the
> "default" value has been set there. Or maybe move the setting of that
> default value into this patch?

Thank you for your review. Sorry, I have been modifying the code 
according to serge's

comments for the past 10 days. I have not forgotten your comment. I will 
reply to you

next week.


Thanks,

Yanteng

>


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

* Re: [PATCH net-next v7 5/9] net: stmmac: Add Loongson-specific register definitions
  2024-01-01 12:26       ` Serge Semin
@ 2024-01-12 10:08         ` Yanteng Si
  2024-01-23 13:08         ` Yanteng Si
  1 sibling, 0 replies; 48+ messages in thread
From: Yanteng Si @ 2024-01-12 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/1/1 20:26, Serge Semin 写道:
> On Mon, Jan 01, 2024 at 04:31:48PM +0800, Yanteng Si wrote:
>> 在 2023/12/21 10:14, Serge Semin 写道:
>>> On Tue, Dec 19, 2023 at 10:26:45PM +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.
>>> Thanks for the updated patch. It looks much clearer now. Thanks to
>>> that I came up with a better and less invasive solution. See my last
>>> comment for details.
>>>
>>>> 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/common.h  |  1 +
>>>>    .../ethernet/stmicro/stmmac/dwmac-loongson.c  |  2 ++
>>>>    .../ethernet/stmicro/stmmac/dwmac1000_dma.c   | 10 ++++--
>>>>    .../net/ethernet/stmicro/stmmac/dwmac_dma.h   | 35 +++++++++++++++++++
>>>>    .../net/ethernet/stmicro/stmmac/dwmac_lib.c   | 35 +++++++++++++++----
>>>>    drivers/net/ethernet/stmicro/stmmac/hwif.c    |  3 +-
>>>>    .../net/ethernet/stmicro/stmmac/stmmac_main.c |  1 +
>>>>    include/linux/stmmac.h                        |  1 +
>>>>    8 files changed, 78 insertions(+), 10 deletions(-)
>>>>
>>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
>>>> index 721c1f8e892f..48ab21243b26 100644
>>>> --- a/drivers/net/ethernet/stmicro/stmmac/common.h
>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/common.h
>>>> @@ -34,6 +34,7 @@
>>>>    #define DWMAC_CORE_5_00		0x50
>>>>    #define DWMAC_CORE_5_10		0x51
>>>>    #define DWMAC_CORE_5_20		0x52
>>>> +#define DWLGMAC_CORE_1_00	0x10
>>> This doesn't look correct because these IDs have been defined for the
>>> Synopsys IP-core enumerations. Loongson GNET is definitely based on
>>> some DW GMAC v3.x IP-core, but instead of updating the USERVER field
>>> vendor just overwrote the GMAC_VERSION.SNPSVER field. From that
>>> perspective the correct solution would be to override the
>>> priv->synopsys_id field with a correct IP-core version (0x37?). See my
>>> last comment for details of how to do that.
>> See my last reply.
>>>>    #define DWXGMAC_CORE_2_10	0x21
>>>>    #define DWXGMAC_CORE_2_20	0x22
>>>>    #define DWXLGMAC_CORE_2_00	0x20
>>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>>> index 0d79104d7fd3..fb7506bbc21b 100644
>>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>>> @@ -101,6 +101,8 @@ static int loongson_dwmac_probe(struct pci_dev *pdev,
>>>>    		plat->mdio_bus_data->needs_reset = true;
>>>>    	}
>>>> +	plat->flags |= STMMAC_FLAG_HAS_LGMAC;
>>>> +
>>> If what I suggest in the last comment is implemented this will be
>>> unnecessary.
>>>
>>>>    	/* Enable pci device */
>>>>    	ret = pci_enable_device(pdev);
>>>>    	if (ret) {
>>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
>>>> index 0fb48e683970..a01fe6b7540a 100644
>>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
>>> None of the generic parts (dwmac1000_dma.c, dwmac_dma.h, dwmac_lib.c)
>>> will need to be modified if you implement what I suggest in the last
>>> comment.
>>>
>>>> @@ -118,7 +118,10 @@ static void dwmac1000_dma_init(struct stmmac_priv *priv, void __iomem *ioaddr,
>>> See my comment to patch 4/9. This method can be fully dropped in favor
>>> of having the dwmac1000_dma_init_channel() function implemented.
>>>
>>>>    	u32 dma_intr_mask;
>>>>    	/* Mask interrupts by writing to CSR7 */
>>>> -	dma_intr_mask = DMA_INTR_DEFAULT_MASK;
>>>> +	if (priv->plat->flags & STMMAC_FLAG_HAS_LGMAC)
>>>> +		dma_intr_mask = DMA_INTR_DEFAULT_MASK_LOONGSON;
>>>> +	else
>>>> +		dma_intr_mask = DMA_INTR_DEFAULT_MASK;
>>>>    	dma_config(ioaddr + DMA_BUS_MODE, ioaddr + DMA_INTR_ENA,
>>>>    			  dma_cfg, dma_intr_mask, atds);
>>>> @@ -130,7 +133,10 @@ static void dwmac1000_dma_init_channel(struct stmmac_priv *priv, void __iomem *i
>>>>    	u32 dma_intr_mask;
>>>>    	/* Mask interrupts by writing to CSR7 */
>>>> -	dma_intr_mask = DMA_INTR_DEFAULT_MASK;
>>>> +	if (priv->plat->flags & STMMAC_FLAG_HAS_LGMAC)
>>>> +		dma_intr_mask = DMA_INTR_DEFAULT_MASK_LOONGSON;
>>>> +	else
>>>> +		dma_intr_mask = DMA_INTR_DEFAULT_MASK;
>>>>    	if (dma_cfg->multi_msi_en)
>>>>    		dma_config(ioaddr + DMA_CHAN_BUS_MODE(chan),
>>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
>>>> index 395d5e4c3922..7d33798c0e72 100644
>>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
>>>> @@ -70,16 +70,23 @@
>>>>    #define DMA_CONTROL_SR		0x00000002	/* Start/Stop Receive */
>>>>    /* DMA Normal interrupt */
>>>> +#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_ENA_NIE 0x00010000	/* Normal Summary */
>>>>    #define DMA_INTR_ENA_TIE 0x00000001	/* Transmit Interrupt */
>>>>    #define DMA_INTR_ENA_TUE 0x00000004	/* Transmit Buffer Unavailable */
>>>>    #define DMA_INTR_ENA_RIE 0x00000040	/* Receive Interrupt */
>>>>    #define DMA_INTR_ENA_ERE 0x00004000	/* Early Receive */
>>>> +#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_NORMAL	(DMA_INTR_ENA_NIE | DMA_INTR_ENA_RIE | \
>>>>    			DMA_INTR_ENA_TIE)
>>>>    /* DMA Abnormal interrupt */
>>>> +#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_ENA_AIE 0x00008000	/* Abnormal Summary */
>>>>    #define DMA_INTR_ENA_FBE 0x00002000	/* Fatal Bus Error */
>>>>    #define DMA_INTR_ENA_ETE 0x00000400	/* Early Transmit */
>>>> @@ -91,10 +98,14 @@
>>>>    #define DMA_INTR_ENA_TJE 0x00000008	/* Transmit Jabber */
>>>>    #define DMA_INTR_ENA_TSE 0x00000002	/* Transmit Stopped */
>>>> +#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_ABNORMAL	(DMA_INTR_ENA_AIE | DMA_INTR_ENA_FBE | \
>>>>    				DMA_INTR_ENA_UNE)
>>>>    /* DMA default interrupt mask */
>>>> +#define DMA_INTR_DEFAULT_MASK_LOONGSON	(DMA_INTR_NORMAL_LOONGSON | DMA_INTR_ABNORMAL_LOONGSON)
>>>>    #define DMA_INTR_DEFAULT_MASK	(DMA_INTR_NORMAL | DMA_INTR_ABNORMAL)
>>>>    #define DMA_INTR_DEFAULT_RX	(DMA_INTR_ENA_RIE)
>>>>    #define DMA_INTR_DEFAULT_TX	(DMA_INTR_ENA_TIE)
>>>> @@ -111,9 +122,15 @@
>>>>    #define DMA_STATUS_TS_SHIFT	20
>>>>    #define DMA_STATUS_RS_MASK	0x000e0000	/* Receive Process State */
>>>>    #define DMA_STATUS_RS_SHIFT	17
>>>> +#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_NIS	0x00010000	/* Normal 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_AIS	0x00008000	/* Abnormal Interrupt Summary */
>>>>    #define DMA_STATUS_ERI	0x00004000	/* Early Receive Interrupt */
>>>> +#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_FBI	0x00002000	/* Fatal Bus Error Interrupt */
>>>>    #define DMA_STATUS_ETI	0x00000400	/* Early Transmit Interrupt */
>>>>    #define DMA_STATUS_RWT	0x00000200	/* Receive Watchdog Timeout */
>>>> @@ -128,10 +145,21 @@
>>>>    #define DMA_STATUS_TI	0x00000001	/* Transmit Interrupt */
>>>>    #define DMA_CONTROL_FTF		0x00100000	/* Flush transmit FIFO */
>>>> +#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_COMMON		(DMA_STATUS_NIS | \
>>>>    					 DMA_STATUS_AIS | \
>>>>    					 DMA_STATUS_FBI)
>>>> +#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_RX		(DMA_STATUS_ERI | \
>>>>    					 DMA_STATUS_RWT | \
>>>>    					 DMA_STATUS_RPS | \
>>>> @@ -140,6 +168,13 @@
>>>>    					 DMA_STATUS_OVF | \
>>>>    					 DMA_STATUS_MSK_COMMON)
>>>> +#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)
>>>>    #define DMA_STATUS_MSK_TX		(DMA_STATUS_ETI | \
>>>>    					 DMA_STATUS_UNF | \
>>>>    					 DMA_STATUS_TJT | \
>>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
>>>> index 968801c694e9..a6e2ab4d0f4a 100644
>>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
>>>> @@ -167,6 +167,9 @@ 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 nor_intr_status;
>>>> +	u32 abnor_intr_status;
>>>> +	u32 fb_intr_status;
>>>>    	u32 intr_status = readl(ioaddr + DMA_CHAN_STATUS(chan));
>>>>    #ifdef DWMAC_DMA_DEBUG
>>>> @@ -176,13 +179,31 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
>>>>    	show_rx_process_state(intr_status);
>>>>    #endif
>>>> -	if (dir == DMA_DIR_RX)
>>>> -		intr_status &= DMA_STATUS_MSK_RX;
>>>> -	else if (dir == DMA_DIR_TX)
>>>> -		intr_status &= DMA_STATUS_MSK_TX;
>>>> +	if (priv->plat->flags & STMMAC_FLAG_HAS_LGMAC) {
>>>> +		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);
>>>> +	} else {
>>>> +		if (dir == DMA_DIR_RX)
>>>> +			intr_status &= DMA_STATUS_MSK_RX;
>>>> +		else if (dir == DMA_DIR_TX)
>>>> +			intr_status &= DMA_STATUS_MSK_TX;
>>>> +
>>>> +		nor_intr_status = intr_status & DMA_STATUS_NIS;
>>>> +		abnor_intr_status = intr_status & DMA_STATUS_AIS;
>>>> +		fb_intr_status = intr_status & DMA_STATUS_FBI;
>>>> +	}
>>>>    	/* ABNORMAL interrupts */
>>>> -	if (unlikely(intr_status & DMA_STATUS_AIS)) {
>>>> +	if (unlikely(abnor_intr_status)) {
>>>>    		if (unlikely(intr_status & DMA_STATUS_UNF)) {
>>>>    			ret = tx_hard_error_bump_tc;
>>>>    			x->tx_undeflow_irq++;
>>>> @@ -205,13 +226,13 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
>>>>    			x->tx_process_stopped_irq++;
>>>>    			ret = tx_hard_error;
>>>>    		}
>>>> -		if (unlikely(intr_status & DMA_STATUS_FBI)) {
>>>> +		if (unlikely(intr_status & fb_intr_status)) {
>>>>    			x->fatal_bus_error_irq++;
>>>>    			ret = tx_hard_error;
>>>>    		}
>>>>    	}
>>>>    	/* TX/RX NORMAL interrupts */
>>>> -	if (likely(intr_status & DMA_STATUS_NIS)) {
>>>> +	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. */
>>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.c b/drivers/net/ethernet/stmicro/stmmac/hwif.c
>>>> index 1bd34b2a47e8..3724cf698de6 100644
>>>> --- a/drivers/net/ethernet/stmicro/stmmac/hwif.c
>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.c
>>>> @@ -59,7 +59,8 @@ static int stmmac_dwmac1_quirks(struct stmmac_priv *priv)
>>>>    		dev_info(priv->device, "Enhanced/Alternate descriptors\n");
>>>>    		/* GMAC older than 3.50 has no extended descriptors */
>>>> -		if (priv->synopsys_id >= DWMAC_CORE_3_50) {
>>>> +		if (priv->synopsys_id >= DWMAC_CORE_3_50 ||
>>>> +		    priv->synopsys_id == DWLGMAC_CORE_1_00) {
>>> This could be left as is if the priv->synopsys_id field is overwritten
>>> with a correct value (see my last comment).
>>>
>>>>    			dev_info(priv->device, "Enabled extended descriptors\n");
>>>>    			priv->extend_desc = 1;
>>>>    		} else {
>>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>>>> index d868eb8dafc5..9764d2ab7e46 100644
>>>> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>>>> @@ -7218,6 +7218,7 @@ static int stmmac_hw_init(struct stmmac_priv *priv)
>>>>    	 * riwt_off field from the platform.
>>>>    	 */
>>>>    	if (((priv->synopsys_id >= DWMAC_CORE_3_50) ||
>>>> +		(priv->synopsys_id == DWLGMAC_CORE_1_00) ||
>>> the same comment here.
>>>
>>>>    	    (priv->plat->has_xgmac)) && (!priv->plat->riwt_off)) {
>>>>    		priv->use_riwt = 1;
>>>>    		dev_info(priv->device,
>>>> diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
>>>> index dee5ad6e48c5..f07f79d50b06 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_HAS_LGMAC			BIT(13)
>>> 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.
>> OK.
>>> 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.
>> It's easy.
>>> 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.
>> Do this in dwmac1000-dma.c? Because this seems impossible to achieve in
>> dwmac-loongson.c:
>>
>>
>> drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c:606:47: error:
>> initializer element is not constant
>>    606 | const struct stmmac_dma_ops dwlgmac_dma_ops = dwmac1000_dma_ops;
>>>      + override the stmmac_dma_ops.{dma_interrupt, init_chan} with
>>>        the pointers to the methods defined in 2.
>> Likewise, where should I do this?
>>
>> Sorry. I seem to have misinterpreted your meaning again.
> No worries. Here is what I meant:
>
> 1. Declare the private Loongson GMAC data like this:
> struct loongson_data {
> 	struct stmmac_dma_ops dma_ops;
> };
> 2. Allocate the memory for the data in the framework of the Loongson
> GMAC device probe() method:
> loongson_dwmac_probe()
> {
> 	...
> 	ld = devm_kzalloc(&pdev->dev, sizeof(*ld), GFP_KERNEL);
> 	if (!ld)
> 		return -ENOMEM;
> 	...
> 	ld->dma_ops = dwmac1000_dma_ops;
> 	ld->dma_ops.init_chan = loongson_gnat_dma_init_chan;
> 	ld->dma_ops.dma_interrupt = loongson_gnat_dma_interrupt;
> 	...
> 	plat->bsp_priv = ld;
> }
> 3. Define the Loongson-specific plat_stmmacenet_data.setup() method,
> which would re-init the stmmac_priv->synopsys_id with a correct value,
> allocate the DW *MAC hardware descriptor and pre-initialize it 'dma'
> field:
> static struct mac_device_info loongson_gnet_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;
>
> 	priv->synopsys_id = 0x37; // or whatever is a real version of your IP
>
> 	ld = priv->plat->bsp_priv;
> 	mac->dma = &ld->dma_ops;
>
> 	dwmac1000_setup(); // Or Pre-initialize the respective "mac" fields as it's done in dwmac1000_setup()
>
> 	return mac;
> }
> 4. Make sure the plat_stmmacenet_data->setup field is initialized with
> the Loongson GNAT-specific setup() method:
> static int loongson_gnet_data(struct pci_dev *pdev,
>                                struct plat_stmmacenet_data *plat)
> {
> 	...
> 	plat->setup = loongson_gnet_setup;
> 	...
> }
>
> That shall do what I described in by previous message.
>
> Note another platform which gets to define its own setup() method
> Sun8i:
> drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
> although since it fully redefines the DMA-ops descriptor the only
> common part with your case is that it needs to have the setup() method
> too.

This method is great! I have been constantly modifying the code and 
experimenting

in the past two weeks, but we have too many types of hardware, and some 
of them

are not working now. I am analyzing the reasons, so I still need some 
time. :)


Thanks,

Yanteng

>
>>
>>
>>>      + 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.
>>>
>>> If I didn't miss something stmmac_hwif_init() will call the
>>> platform-specific setup method right after fetching the SNPSVER field
>>> value. Your setup method will allocate mac_device_info structure then,
>>> will pre-initialize the GNET-specific DMA ops field and fix the
>>> Synopsys ID with a proper value (as described in 3 above). The rest of
>>> the ops descriptors will be initialized in the loop afterwards based
>>> on the specified device ID.
>> This doesn't seem to work because our device looks something like this:
> Please see my note above.
>
>> device     pci id   reversion    core version
>> LS7A        0x13       0x00       0x35/0x37
>> LS7A        0x13       0x01       0x35/0x37
>> LS2K        0x13       0x00       0x10
>> LS2K        0x13       0x01       0x10
> Not sure what you meant by providing this table to me and justifying
> that something wouldn't work. But it would have been much useful to
> provide a detailed description of what platforms and devices the
> current dwmac-loongson.c driver supports and what support you are
> trying to add. Cover-letter is a suitable place for it.
>
> In anyway the DW GMAC IP-core can't be 0x10. Seeing your device is
> having the multi-channels support it must have a version closer to
> 0x37 (the highest IP-core version is 3.73a). Please reach the hardware
> engineers to clarify what actual DW GMAC IP-core has been utilized in
> your case.
>
> -Serge(y)
>
>>
>> Thanks,
>>
>> Yanteng
>>
>>> -Serge(y)
>>>
>>>>    struct plat_stmmacenet_data {
>>>>    	int bus_id;
>>>> -- 
>>>> 2.31.4
>>>>


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

* Re: [PATCH net-next v7 2/9] net: stmmac: dwmac-loongson: Refactor code for loongson_dwmac_probe()
  2024-01-02 10:37   ` Russell King (Oracle)
@ 2024-01-18 12:53     ` Yanteng Si
  0 siblings, 0 replies; 48+ messages in thread
From: Yanteng Si @ 2024-01-18 12:53 UTC (permalink / raw)
  To: Russell King (Oracle)
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	fancer.lancer, Jose.Abreu, chenhuacai, guyinggang, netdev,
	chris.chenfeiyang


在 2024/1/2 18:37, Russell King (Oracle) 写道:
> On Tue, Dec 19, 2023 at 10:17:05PM +0800, Yanteng Si wrote:
>> Add a setup() function to initialize data, and simplify code for
>> loongson_dwmac_probe().
> Not all changes in this patch are described.
Okay, I'll re-write it in more detail.
>
>> +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->phy_interface = PHY_INTERFACE_MODE_RGMII_ID;
> This presumably sets the default phy_interface mode?
>
>
>> -	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;
> loongson_gmac_data() gets called from here...
>
>> +
>> +	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) {
> This gets the PHY interface mode, and errors out if it can't be found in
> firmware.
>
>> @@ -110,11 +137,7 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
>>   	}
>>   
>>   	plat->phy_interface = phy_mode;
> So this ends up always overwriting the value written in
> loongson_gmac_data(). So it seems to be that initialising
> plat->phy_interface in loongson_gmac_data() is just patch noise and
> serves no real purpose.
>
>> -	plat->mac_interface = PHY_INTERFACE_MODE_GMII;
> This has now gone - and is not described, and I'm left wondering what
> the implication of that is on the driver. It also makes me wonder
> whether loongson_gmac_data() should've been setting mac_interface
> rather than phy_interface.

You seem to have understood this in Patch 3.

I'll re-split the patch to make the code easier to understand.

>
>>   	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");
>> +		dev_info(&pdev->dev,
>> +			 "IRQ eth_wake_irq not found, using macirq\n");
> Whitespace cleanups should be a separate patch.

OK.


Thanks,

Yanteng

>


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

* Re: [PATCH net-next v7 3/9] net: stmmac: dwmac-loongson: Add full PCI support
  2024-01-02 10:40   ` Russell King (Oracle)
  2024-01-12  9:42     ` Yanteng Si
@ 2024-01-18 12:56     ` Yanteng Si
  1 sibling, 0 replies; 48+ messages in thread
From: Yanteng Si @ 2024-01-18 12:56 UTC (permalink / raw)
  To: Russell King (Oracle)
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	fancer.lancer, Jose.Abreu, chenhuacai, guyinggang, netdev,
	chris.chenfeiyang


在 2024/1/2 18:40, Russell King (Oracle) 写道:
> On Tue, Dec 19, 2023 at 10:17:06PM +0800, Yanteng Si wrote:
>> @@ -125,42 +126,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;
>> -
> So this is why phy_interface changes in patch 2. It would have been good
> to make a forward reference to this change to explain in patch 2 why the
> "default" value has been set there. Or maybe move the setting of that
> default value into this patch?

This sounds great, I will try it.


Thanks,

Yanteng

>


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

* Re: [PATCH net-next v7 9/9] net: stmmac: Disable coe for some Loongson GNET
  2023-12-21  2:36   ` Serge Semin
@ 2024-01-23 12:47     ` Yanteng Si
  0 siblings, 0 replies; 48+ messages in thread
From: Yanteng Si @ 2024-01-23 12:47 UTC (permalink / raw)
  To: Serge Semin
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang


在 2023/12/21 10:36, Serge Semin 写道:
> On Tue, Dec 19, 2023 at 10:28:19PM +0800, Yanteng Si wrote:
>> Some chips of Loongson GNET does not support coe, so disable them.
>>
>> 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/hwif.c | 5 +++++
>>   1 file changed, 5 insertions(+)
>>
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.c b/drivers/net/ethernet/stmicro/stmmac/hwif.c
>> index 3724cf698de6..f211880925aa 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/hwif.c
>> +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.c
>> @@ -73,6 +73,11 @@ static int stmmac_dwmac1_quirks(struct stmmac_priv *priv)
>>   		mac->desc = &ndesc_ops;
>>   	}
>>   
>> +	if (priv->synopsys_id == DWLGMAC_CORE_1_00) {
>> +		priv->plat->tx_coe = 0;
>> +		priv->plat->rx_coe = STMMAC_RX_COE_NONE;
>> +	}
> Couldn't this be done in dwmac-loongson.c?

Sorry for the late reply, I have been busy with patches 4 and 5.

I think I can give you a definite answer: This is possible, just like

the method you mentioned in patch 5, I only need to

overwrite ld->dwlgmac_dma_ops.get_hw_feature.


Thanks,

Yanteng

>
> -Serge(y)
>
>> +
>>   	stmmac_dwmac_mode_quirk(priv);
>>   	return 0;
>>   }
>> -- 
>> 2.31.4
>>


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

* Re: [PATCH net-next v7 5/9] net: stmmac: Add Loongson-specific register definitions
  2024-01-01 12:26       ` Serge Semin
  2024-01-12 10:08         ` Yanteng Si
@ 2024-01-23 13:08         ` Yanteng Si
  2024-01-24 13:59           ` Serge Semin
  1 sibling, 1 reply; 48+ messages in thread
From: Yanteng Si @ 2024-01-23 13:08 UTC (permalink / raw)
  To: Serge Semin
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang


在 2024/1/1 20:26, Serge Semin 写道:
> On Mon, Jan 01, 2024 at 04:31:48PM +0800, Yanteng Si wrote:
>> 在 2023/12/21 10:14, Serge Semin 写道:
>>> On Tue, Dec 19, 2023 at 10:26:45PM +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.
>>> Thanks for the updated patch. It looks much clearer now. Thanks to
>>> that I came up with a better and less invasive solution. See my last
>>> comment for details.
>>>
>>>> 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/common.h  |  1 +
>>>>    .../ethernet/stmicro/stmmac/dwmac-loongson.c  |  2 ++
>>>>    .../ethernet/stmicro/stmmac/dwmac1000_dma.c   | 10 ++++--
>>>>    .../net/ethernet/stmicro/stmmac/dwmac_dma.h   | 35 +++++++++++++++++++
>>>>    .../net/ethernet/stmicro/stmmac/dwmac_lib.c   | 35 +++++++++++++++----
>>>>    drivers/net/ethernet/stmicro/stmmac/hwif.c    |  3 +-
>>>>    .../net/ethernet/stmicro/stmmac/stmmac_main.c |  1 +
>>>>    include/linux/stmmac.h                        |  1 +
>>>>    8 files changed, 78 insertions(+), 10 deletions(-)
>>>>
>>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
>>>> index 721c1f8e892f..48ab21243b26 100644
>>>> --- a/drivers/net/ethernet/stmicro/stmmac/common.h
>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/common.h
>>>> @@ -34,6 +34,7 @@
>>>>    #define DWMAC_CORE_5_00		0x50
>>>>    #define DWMAC_CORE_5_10		0x51
>>>>    #define DWMAC_CORE_5_20		0x52
>>>> +#define DWLGMAC_CORE_1_00	0x10
>>> This doesn't look correct because these IDs have been defined for the
>>> Synopsys IP-core enumerations. Loongson GNET is definitely based on
>>> some DW GMAC v3.x IP-core, but instead of updating the USERVER field
>>> vendor just overwrote the GMAC_VERSION.SNPSVER field. From that
>>> perspective the correct solution would be to override the
>>> priv->synopsys_id field with a correct IP-core version (0x37?). See my
>>> last comment for details of how to do that.
>> See my last reply.
>>>>    #define DWXGMAC_CORE_2_10	0x21
>>>>    #define DWXGMAC_CORE_2_20	0x22
>>>>    #define DWXLGMAC_CORE_2_00	0x20
>>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>>> index 0d79104d7fd3..fb7506bbc21b 100644
>>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>>> @@ -101,6 +101,8 @@ static int loongson_dwmac_probe(struct pci_dev *pdev,
>>>>    		plat->mdio_bus_data->needs_reset = true;
>>>>    	}
>>>> +	plat->flags |= STMMAC_FLAG_HAS_LGMAC;
>>>> +
>>> If what I suggest in the last comment is implemented this will be
>>> unnecessary.
>>>
>>>>    	/* Enable pci device */
>>>>    	ret = pci_enable_device(pdev);
>>>>    	if (ret) {
>>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
>>>> index 0fb48e683970..a01fe6b7540a 100644
>>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
>>> None of the generic parts (dwmac1000_dma.c, dwmac_dma.h, dwmac_lib.c)
>>> will need to be modified if you implement what I suggest in the last
>>> comment.
>>>
>>>> @@ -118,7 +118,10 @@ static void dwmac1000_dma_init(struct stmmac_priv *priv, void __iomem *ioaddr,
>>> See my comment to patch 4/9. This method can be fully dropped in favor
>>> of having the dwmac1000_dma_init_channel() function implemented.
>>>
>>>>    	u32 dma_intr_mask;
>>>>    	/* Mask interrupts by writing to CSR7 */
>>>> -	dma_intr_mask = DMA_INTR_DEFAULT_MASK;
>>>> +	if (priv->plat->flags & STMMAC_FLAG_HAS_LGMAC)
>>>> +		dma_intr_mask = DMA_INTR_DEFAULT_MASK_LOONGSON;
>>>> +	else
>>>> +		dma_intr_mask = DMA_INTR_DEFAULT_MASK;
>>>>    	dma_config(ioaddr + DMA_BUS_MODE, ioaddr + DMA_INTR_ENA,
>>>>    			  dma_cfg, dma_intr_mask, atds);
>>>> @@ -130,7 +133,10 @@ static void dwmac1000_dma_init_channel(struct stmmac_priv *priv, void __iomem *i
>>>>    	u32 dma_intr_mask;
>>>>    	/* Mask interrupts by writing to CSR7 */
>>>> -	dma_intr_mask = DMA_INTR_DEFAULT_MASK;
>>>> +	if (priv->plat->flags & STMMAC_FLAG_HAS_LGMAC)
>>>> +		dma_intr_mask = DMA_INTR_DEFAULT_MASK_LOONGSON;
>>>> +	else
>>>> +		dma_intr_mask = DMA_INTR_DEFAULT_MASK;
>>>>    	if (dma_cfg->multi_msi_en)
>>>>    		dma_config(ioaddr + DMA_CHAN_BUS_MODE(chan),
>>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
>>>> index 395d5e4c3922..7d33798c0e72 100644
>>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
>>>> @@ -70,16 +70,23 @@
>>>>    #define DMA_CONTROL_SR		0x00000002	/* Start/Stop Receive */
>>>>    /* DMA Normal interrupt */
>>>> +#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_ENA_NIE 0x00010000	/* Normal Summary */
>>>>    #define DMA_INTR_ENA_TIE 0x00000001	/* Transmit Interrupt */
>>>>    #define DMA_INTR_ENA_TUE 0x00000004	/* Transmit Buffer Unavailable */
>>>>    #define DMA_INTR_ENA_RIE 0x00000040	/* Receive Interrupt */
>>>>    #define DMA_INTR_ENA_ERE 0x00004000	/* Early Receive */
>>>> +#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_NORMAL	(DMA_INTR_ENA_NIE | DMA_INTR_ENA_RIE | \
>>>>    			DMA_INTR_ENA_TIE)
>>>>    /* DMA Abnormal interrupt */
>>>> +#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_ENA_AIE 0x00008000	/* Abnormal Summary */
>>>>    #define DMA_INTR_ENA_FBE 0x00002000	/* Fatal Bus Error */
>>>>    #define DMA_INTR_ENA_ETE 0x00000400	/* Early Transmit */
>>>> @@ -91,10 +98,14 @@
>>>>    #define DMA_INTR_ENA_TJE 0x00000008	/* Transmit Jabber */
>>>>    #define DMA_INTR_ENA_TSE 0x00000002	/* Transmit Stopped */
>>>> +#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_ABNORMAL	(DMA_INTR_ENA_AIE | DMA_INTR_ENA_FBE | \
>>>>    				DMA_INTR_ENA_UNE)
>>>>    /* DMA default interrupt mask */
>>>> +#define DMA_INTR_DEFAULT_MASK_LOONGSON	(DMA_INTR_NORMAL_LOONGSON | DMA_INTR_ABNORMAL_LOONGSON)
>>>>    #define DMA_INTR_DEFAULT_MASK	(DMA_INTR_NORMAL | DMA_INTR_ABNORMAL)
>>>>    #define DMA_INTR_DEFAULT_RX	(DMA_INTR_ENA_RIE)
>>>>    #define DMA_INTR_DEFAULT_TX	(DMA_INTR_ENA_TIE)
>>>> @@ -111,9 +122,15 @@
>>>>    #define DMA_STATUS_TS_SHIFT	20
>>>>    #define DMA_STATUS_RS_MASK	0x000e0000	/* Receive Process State */
>>>>    #define DMA_STATUS_RS_SHIFT	17
>>>> +#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_NIS	0x00010000	/* Normal 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_AIS	0x00008000	/* Abnormal Interrupt Summary */
>>>>    #define DMA_STATUS_ERI	0x00004000	/* Early Receive Interrupt */
>>>> +#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_FBI	0x00002000	/* Fatal Bus Error Interrupt */
>>>>    #define DMA_STATUS_ETI	0x00000400	/* Early Transmit Interrupt */
>>>>    #define DMA_STATUS_RWT	0x00000200	/* Receive Watchdog Timeout */
>>>> @@ -128,10 +145,21 @@
>>>>    #define DMA_STATUS_TI	0x00000001	/* Transmit Interrupt */
>>>>    #define DMA_CONTROL_FTF		0x00100000	/* Flush transmit FIFO */
>>>> +#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_COMMON		(DMA_STATUS_NIS | \
>>>>    					 DMA_STATUS_AIS | \
>>>>    					 DMA_STATUS_FBI)
>>>> +#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_RX		(DMA_STATUS_ERI | \
>>>>    					 DMA_STATUS_RWT | \
>>>>    					 DMA_STATUS_RPS | \
>>>> @@ -140,6 +168,13 @@
>>>>    					 DMA_STATUS_OVF | \
>>>>    					 DMA_STATUS_MSK_COMMON)
>>>> +#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)
>>>>    #define DMA_STATUS_MSK_TX		(DMA_STATUS_ETI | \
>>>>    					 DMA_STATUS_UNF | \
>>>>    					 DMA_STATUS_TJT | \
>>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
>>>> index 968801c694e9..a6e2ab4d0f4a 100644
>>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
>>>> @@ -167,6 +167,9 @@ 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 nor_intr_status;
>>>> +	u32 abnor_intr_status;
>>>> +	u32 fb_intr_status;
>>>>    	u32 intr_status = readl(ioaddr + DMA_CHAN_STATUS(chan));
>>>>    #ifdef DWMAC_DMA_DEBUG
>>>> @@ -176,13 +179,31 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
>>>>    	show_rx_process_state(intr_status);
>>>>    #endif
>>>> -	if (dir == DMA_DIR_RX)
>>>> -		intr_status &= DMA_STATUS_MSK_RX;
>>>> -	else if (dir == DMA_DIR_TX)
>>>> -		intr_status &= DMA_STATUS_MSK_TX;
>>>> +	if (priv->plat->flags & STMMAC_FLAG_HAS_LGMAC) {
>>>> +		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);
>>>> +	} else {
>>>> +		if (dir == DMA_DIR_RX)
>>>> +			intr_status &= DMA_STATUS_MSK_RX;
>>>> +		else if (dir == DMA_DIR_TX)
>>>> +			intr_status &= DMA_STATUS_MSK_TX;
>>>> +
>>>> +		nor_intr_status = intr_status & DMA_STATUS_NIS;
>>>> +		abnor_intr_status = intr_status & DMA_STATUS_AIS;
>>>> +		fb_intr_status = intr_status & DMA_STATUS_FBI;
>>>> +	}
>>>>    	/* ABNORMAL interrupts */
>>>> -	if (unlikely(intr_status & DMA_STATUS_AIS)) {
>>>> +	if (unlikely(abnor_intr_status)) {
>>>>    		if (unlikely(intr_status & DMA_STATUS_UNF)) {
>>>>    			ret = tx_hard_error_bump_tc;
>>>>    			x->tx_undeflow_irq++;
>>>> @@ -205,13 +226,13 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
>>>>    			x->tx_process_stopped_irq++;
>>>>    			ret = tx_hard_error;
>>>>    		}
>>>> -		if (unlikely(intr_status & DMA_STATUS_FBI)) {
>>>> +		if (unlikely(intr_status & fb_intr_status)) {
>>>>    			x->fatal_bus_error_irq++;
>>>>    			ret = tx_hard_error;
>>>>    		}
>>>>    	}
>>>>    	/* TX/RX NORMAL interrupts */
>>>> -	if (likely(intr_status & DMA_STATUS_NIS)) {
>>>> +	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. */
>>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.c b/drivers/net/ethernet/stmicro/stmmac/hwif.c
>>>> index 1bd34b2a47e8..3724cf698de6 100644
>>>> --- a/drivers/net/ethernet/stmicro/stmmac/hwif.c
>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.c
>>>> @@ -59,7 +59,8 @@ static int stmmac_dwmac1_quirks(struct stmmac_priv *priv)
>>>>    		dev_info(priv->device, "Enhanced/Alternate descriptors\n");
>>>>    		/* GMAC older than 3.50 has no extended descriptors */
>>>> -		if (priv->synopsys_id >= DWMAC_CORE_3_50) {
>>>> +		if (priv->synopsys_id >= DWMAC_CORE_3_50 ||
>>>> +		    priv->synopsys_id == DWLGMAC_CORE_1_00) {
>>> This could be left as is if the priv->synopsys_id field is overwritten
>>> with a correct value (see my last comment).
>>>
>>>>    			dev_info(priv->device, "Enabled extended descriptors\n");
>>>>    			priv->extend_desc = 1;
>>>>    		} else {
>>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>>>> index d868eb8dafc5..9764d2ab7e46 100644
>>>> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>>>> @@ -7218,6 +7218,7 @@ static int stmmac_hw_init(struct stmmac_priv *priv)
>>>>    	 * riwt_off field from the platform.
>>>>    	 */
>>>>    	if (((priv->synopsys_id >= DWMAC_CORE_3_50) ||
>>>> +		(priv->synopsys_id == DWLGMAC_CORE_1_00) ||
>>> the same comment here.
>>>
>>>>    	    (priv->plat->has_xgmac)) && (!priv->plat->riwt_off)) {
>>>>    		priv->use_riwt = 1;
>>>>    		dev_info(priv->device,
>>>> diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
>>>> index dee5ad6e48c5..f07f79d50b06 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_HAS_LGMAC			BIT(13)
>>> 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.
>> OK.
>>> 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.
>> It's easy.
>>> 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.
>> Do this in dwmac1000-dma.c? Because this seems impossible to achieve in
>> dwmac-loongson.c:
>>
>>
>> drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c:606:47: error:
>> initializer element is not constant
>>    606 | const struct stmmac_dma_ops dwlgmac_dma_ops = dwmac1000_dma_ops;
>>>      + override the stmmac_dma_ops.{dma_interrupt, init_chan} with
>>>        the pointers to the methods defined in 2.
>> Likewise, where should I do this?
>>
>> Sorry. I seem to have misinterpreted your meaning again.
> No worries. Here is what I meant:
>
> 1. Declare the private Loongson GMAC data like this:
> struct loongson_data {
> 	struct stmmac_dma_ops dma_ops;
> };
> 2. Allocate the memory for the data in the framework of the Loongson
> GMAC device probe() method:
> loongson_dwmac_probe()
> {
> 	...
> 	ld = devm_kzalloc(&pdev->dev, sizeof(*ld), GFP_KERNEL);
> 	if (!ld)
> 		return -ENOMEM;
> 	...
> 	ld->dma_ops = dwmac1000_dma_ops;
> 	ld->dma_ops.init_chan = loongson_gnat_dma_init_chan;
> 	ld->dma_ops.dma_interrupt = loongson_gnat_dma_interrupt;
> 	...
> 	plat->bsp_priv = ld;
> }
> 3. Define the Loongson-specific plat_stmmacenet_data.setup() method,
> which would re-init the stmmac_priv->synopsys_id with a correct value,
> allocate the DW *MAC hardware descriptor and pre-initialize it 'dma'
> field:
> static struct mac_device_info loongson_gnet_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;
>
> 	priv->synopsys_id = 0x37; // or whatever is a real version of your IP
>
> 	ld = priv->plat->bsp_priv;
> 	mac->dma = &ld->dma_ops;
>
> 	dwmac1000_setup(); // Or Pre-initialize the respective "mac" fields as it's done in dwmac1000_setup()
>
> 	return mac;
> }
> 4. Make sure the plat_stmmacenet_data->setup field is initialized with
> the Loongson GNAT-specific setup() method:
> static int loongson_gnet_data(struct pci_dev *pdev,
>                                struct plat_stmmacenet_data *plat)
> {
> 	...
> 	plat->setup = loongson_gnet_setup;
> 	...
> }
>
> That shall do what I described in by previous message.
>
> Note another platform which gets to define its own setup() method
> Sun8i:
> drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
> although since it fully redefines the DMA-ops descriptor the only
> common part with your case is that it needs to have the setup() method
> too.

Thank you so much, this method is so cool!

  After three weeks of hard work, everything is working now. I will 
reply to your other comments tomorrow.


Thanks,

Yanteng

>>
>>
>>>      + 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.
>>>
>>> If I didn't miss something stmmac_hwif_init() will call the
>>> platform-specific setup method right after fetching the SNPSVER field
>>> value. Your setup method will allocate mac_device_info structure then,
>>> will pre-initialize the GNET-specific DMA ops field and fix the
>>> Synopsys ID with a proper value (as described in 3 above). The rest of
>>> the ops descriptors will be initialized in the loop afterwards based
>>> on the specified device ID.
>> This doesn't seem to work because our device looks something like this:
> Please see my note above.
>
>> device     pci id   reversion    core version
>> LS7A        0x13       0x00       0x35/0x37
>> LS7A        0x13       0x01       0x35/0x37
>> LS2K        0x13       0x00       0x10
>> LS2K        0x13       0x01       0x10
> Not sure what you meant by providing this table to me and justifying
> that something wouldn't work. But it would have been much useful to
> provide a detailed description of what platforms and devices the
> current dwmac-loongson.c driver supports and what support you are
> trying to add. Cover-letter is a suitable place for it.
>
> In anyway the DW GMAC IP-core can't be 0x10. Seeing your device is
> having the multi-channels support it must have a version closer to
> 0x37 (the highest IP-core version is 3.73a). Please reach the hardware
> engineers to clarify what actual DW GMAC IP-core has been utilized in
> your case.
>
> -Serge(y)
>
>>
>> Thanks,
>>
>> Yanteng
>>
>>> -Serge(y)
>>>
>>>>    struct plat_stmmacenet_data {
>>>>    	int bus_id;
>>>> -- 
>>>> 2.31.4
>>>>


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

* Re: [PATCH net-next v7 7/9] net: stmmac: dwmac-loongson: Add GNET support
  2024-01-01  7:27     ` Yanteng Si
  2024-01-02  1:22       ` Serge Semin
@ 2024-01-24  9:21       ` Yanteng Si
  2024-01-24 13:51         ` Serge Semin
  1 sibling, 1 reply; 48+ messages in thread
From: Yanteng Si @ 2024-01-24  9:21 UTC (permalink / raw)
  To: Serge Semin
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang


在 2024/1/1 15:27, Yanteng Si 写道:
>
> 在 2023/12/21 10:34, Serge Semin 写道:
>> On Tue, Dec 19, 2023 at 10:26:47PM +0800, Yanteng Si wrote:
>>> Add Loongson GNET (GMAC with PHY) support. Current GNET does not 
>>> support
>>> half duplex mode, and 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  | 79 
>>> +++++++++++++++++++
>>>   .../ethernet/stmicro/stmmac/stmmac_ethtool.c  |  6 ++
>>>   include/linux/stmmac.h                        |  2 +
>>>   3 files changed, 87 insertions(+)
>>>
>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c 
>>> b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>> index 2c08d5495214..9e4953c7e4e0 100644
>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>> @@ -168,6 +168,83 @@ 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 net_device *ndev = dev_get_drvdata(priv);
>>> +    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);
>> {} around the outer if please.
> OK.
>>
>>> +}
>>> +
>>> +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 = 0xfffffffb;
>> ~BIT(2)?
> I still need to confirm, please allow me to get back to you later.

Yes, that's fine.


Thanks,

Yanteng


>>
>>> +
>>> +    plat->phy_addr = 2;
>>> +    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;
>>> +
>>> +    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;
>>> +    u32 version = readl(res->addr + GMAC_VERSION);
>>> +
>>> +    switch (version & 0xff) {
>>> +    case DWLGMAC_CORE_1_00:
>>> +        ret = loongson_dwmac_config_multi_msi(pdev, plat, res, np, 8);
>>> +        break;
>>> +    default:
>>> +        ret = loongson_dwmac_config_legacy(pdev, plat, res, np);
>> Hm, do you have two versions of Loongson GNET? What does the second
> Yes.
>> one contain in the GMAC_VERSION register then? Can't you distinguish
>> them by the PCI IDs (device, subsystem, revision)?
>
> I'm afraid that's not possible.
>
> Because they have the same pci id and revision.
>
>
> Thanks,
>
> Yanteng
>
>>
>> -Serge(y)
>>
>>> +        break;
>>> +    }
>>> +
>>> +    switch (pdev->revision) {
>>> +    case 0x00:
>>> +        plat->flags |=
>>> +            FIELD_PREP(STMMAC_FLAG_DISABLE_HALF_DUPLEX, 1) |
>>> +            FIELD_PREP(STMMAC_FLAG_DISABLE_FORCE_1000, 1);
>>> +        break;
>>> +    case 0x01:
>>> +        plat->flags |=
>>> +            FIELD_PREP(STMMAC_FLAG_DISABLE_HALF_DUPLEX, 1);
>>> +        break;
>>> +    default:
>>> +        break;
>>> +    }
>>> +
>>> +    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)
>>>   {
>>> @@ -318,9 +395,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);
>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c 
>>> b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
>>> index 8105ce47c6ad..d6939eb9a0d8 100644
>>> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
>>> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
>>> @@ -420,6 +420,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 f07f79d50b06..067030cdb60f 100644
>>> --- a/include/linux/stmmac.h
>>> +++ b/include/linux/stmmac.h
>>> @@ -222,6 +222,8 @@ struct dwmac4_addrs {
>>>   #define STMMAC_FLAG_EN_TX_LPI_CLOCKGATING    BIT(11)
>>>   #define STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY    BIT(12)
>>>   #define STMMAC_FLAG_HAS_LGMAC            BIT(13)
>>> +#define STMMAC_FLAG_DISABLE_HALF_DUPLEX    BIT(14)
>>> +#define STMMAC_FLAG_DISABLE_FORCE_1000    BIT(15)
>>>     struct plat_stmmacenet_data {
>>>       int bus_id;
>>> -- 
>>> 2.31.4
>>>


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

* Re: [PATCH net-next v7 8/9] net: stmmac: dwmac-loongson: Disable flow control for GMAC
  2023-12-21  2:35   ` Serge Semin
@ 2024-01-24 10:54     ` Yanteng Si
  0 siblings, 0 replies; 48+ messages in thread
From: Yanteng Si @ 2024-01-24 10:54 UTC (permalink / raw)
  To: Serge Semin
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang


在 2023/12/21 10:35, Serge Semin 写道:
> On Tue, Dec 19, 2023 at 10:28:18PM +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 | 2 ++
>>   drivers/net/ethernet/stmicro/stmmac/stmmac_main.c    | 6 +++---
>>   include/linux/stmmac.h                               | 1 +
>>   3 files changed, 6 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>> index 9e4953c7e4e0..77c9bcb66a8e 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>> @@ -160,6 +160,8 @@ static int loongson_gmac_config(struct pci_dev *pdev,
>>   		break;
>>   	}
>>   
>> +	plat->flags |= FIELD_PREP(STMMAC_FLAG_DISABLE_FLOW_CONTROL, 1);
> Why FIELD_PREP()-ing?

This is very early code and will be changed to:

plat->flags |= STMMAC_FLAG_DISABLE_FLOW_CONTROL;

>
>> +
>>   	return ret;
>>   }
>>   
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>> index 9764d2ab7e46..d94f61742772 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>> @@ -1236,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_ASYM_PAUSE | MAC_SYM_PAUSE |
>> -						MAC_10FD | MAC_100FD |
>> -						MAC_1000FD;
>> +	priv->phylink_config.mac_capabilities = MAC_10FD | MAC_100FD | MAC_1000FD;
>> +	if (!FIELD_GET(STMMAC_FLAG_DISABLE_FLOW_CONTROL, priv->plat->flags))
> !(priv->plat->flags & STMMAC_FLAG_DISABLE_FLOW_CONTROL) ?

OK!


Thanks,

Yanteng

>
> -Serge(y)
>
>> +		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 067030cdb60f..5ece92e4d8c3 100644
>> --- a/include/linux/stmmac.h
>> +++ b/include/linux/stmmac.h
>> @@ -224,6 +224,7 @@ struct dwmac4_addrs {
>>   #define STMMAC_FLAG_HAS_LGMAC			BIT(13)
>>   #define STMMAC_FLAG_DISABLE_HALF_DUPLEX	BIT(14)
>>   #define STMMAC_FLAG_DISABLE_FORCE_1000	BIT(15)
>> +#define STMMAC_FLAG_DISABLE_FLOW_CONTROL	BIT(16)
>>   
>>   struct plat_stmmacenet_data {
>>   	int bus_id;
>> -- 
>> 2.31.4
>>


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

* Re: [PATCH net-next v7 7/9] net: stmmac: dwmac-loongson: Add GNET support
  2024-01-24  9:21       ` Yanteng Si
@ 2024-01-24 13:51         ` Serge Semin
  2024-01-25  8:36           ` Yanteng Si
  0 siblings, 1 reply; 48+ messages in thread
From: Serge Semin @ 2024-01-24 13:51 UTC (permalink / raw)
  To: Yanteng Si
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

On Wed, Jan 24, 2024 at 05:21:03PM +0800, Yanteng Si wrote:
> 
> 在 2024/1/1 15:27, Yanteng Si 写道:
> > 
> > 在 2023/12/21 10:34, Serge Semin 写道:
> > > On Tue, Dec 19, 2023 at 10:26:47PM +0800, Yanteng Si wrote:
> > > > Add Loongson GNET (GMAC with PHY) support. Current GNET does not
> > > > support
> > > > half duplex mode, and 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  | 79
> > > > +++++++++++++++++++
> > > >   .../ethernet/stmicro/stmmac/stmmac_ethtool.c  |  6 ++
> > > >   include/linux/stmmac.h                        |  2 +
> > > >   3 files changed, 87 insertions(+)
> > > > 
> > > > diff --git
> > > > a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > > b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > > index 2c08d5495214..9e4953c7e4e0 100644
> > > > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > > @@ -168,6 +168,83 @@ 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 net_device *ndev = dev_get_drvdata(priv);
> > > > +    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);
> > > {} around the outer if please.
> > OK.
> > > 
> > > > +}
> > > > +
> > > > +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 = 0xfffffffb;
> > > ~BIT(2)?
> > I still need to confirm, please allow me to get back to you later.
> 
> Yes, that's fine.

Glad this part has been settled.)

-Serge(y)

> 
> 
> Thanks,
> 
> Yanteng
> 
> 
> > > 
> > > > +
> > > > +    plat->phy_addr = 2;
> > > > +    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;
> > > > +
> > > > +    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;
> > > > +    u32 version = readl(res->addr + GMAC_VERSION);
> > > > +
> > > > +    switch (version & 0xff) {
> > > > +    case DWLGMAC_CORE_1_00:
> > > > +        ret = loongson_dwmac_config_multi_msi(pdev, plat, res, np, 8);
> > > > +        break;
> > > > +    default:
> > > > +        ret = loongson_dwmac_config_legacy(pdev, plat, res, np);
> > > Hm, do you have two versions of Loongson GNET? What does the second
> > Yes.
> > > one contain in the GMAC_VERSION register then? Can't you distinguish
> > > them by the PCI IDs (device, subsystem, revision)?
> > 
> > I'm afraid that's not possible.
> > 
> > Because they have the same pci id and revision.
> > 
> > 
> > Thanks,
> > 
> > Yanteng
> > 
> > > 
> > > -Serge(y)
> > > 
> > > > +        break;
> > > > +    }
> > > > +
> > > > +    switch (pdev->revision) {
> > > > +    case 0x00:
> > > > +        plat->flags |=
> > > > +            FIELD_PREP(STMMAC_FLAG_DISABLE_HALF_DUPLEX, 1) |
> > > > +            FIELD_PREP(STMMAC_FLAG_DISABLE_FORCE_1000, 1);
> > > > +        break;
> > > > +    case 0x01:
> > > > +        plat->flags |=
> > > > +            FIELD_PREP(STMMAC_FLAG_DISABLE_HALF_DUPLEX, 1);
> > > > +        break;
> > > > +    default:
> > > > +        break;
> > > > +    }
> > > > +
> > > > +    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)
> > > >   {
> > > > @@ -318,9 +395,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);
> > > > diff --git
> > > > a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> > > > b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> > > > index 8105ce47c6ad..d6939eb9a0d8 100644
> > > > --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> > > > +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> > > > @@ -420,6 +420,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 f07f79d50b06..067030cdb60f 100644
> > > > --- a/include/linux/stmmac.h
> > > > +++ b/include/linux/stmmac.h
> > > > @@ -222,6 +222,8 @@ struct dwmac4_addrs {
> > > >   #define STMMAC_FLAG_EN_TX_LPI_CLOCKGATING    BIT(11)
> > > >   #define STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY    BIT(12)
> > > >   #define STMMAC_FLAG_HAS_LGMAC            BIT(13)
> > > > +#define STMMAC_FLAG_DISABLE_HALF_DUPLEX    BIT(14)
> > > > +#define STMMAC_FLAG_DISABLE_FORCE_1000    BIT(15)
> > > >     struct plat_stmmacenet_data {
> > > >       int bus_id;
> > > > -- 
> > > > 2.31.4
> > > > 
> 

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

* Re: [PATCH net-next v7 5/9] net: stmmac: Add Loongson-specific register definitions
  2024-01-23 13:08         ` Yanteng Si
@ 2024-01-24 13:59           ` Serge Semin
  0 siblings, 0 replies; 48+ messages in thread
From: Serge Semin @ 2024-01-24 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 Tue, Jan 23, 2024 at 09:08:31PM +0800, Yanteng Si wrote:
> 
> 在 2024/1/1 20:26, Serge Semin 写道:
> > On Mon, Jan 01, 2024 at 04:31:48PM +0800, Yanteng Si wrote:
> > > 在 2023/12/21 10:14, Serge Semin 写道:
> > > > On Tue, Dec 19, 2023 at 10:26:45PM +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.
> > > > Thanks for the updated patch. It looks much clearer now. Thanks to
> > > > that I came up with a better and less invasive solution. See my last
> > > > comment for details.
> > > > 
> > > > > 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/common.h  |  1 +
> > > > >    .../ethernet/stmicro/stmmac/dwmac-loongson.c  |  2 ++
> > > > >    .../ethernet/stmicro/stmmac/dwmac1000_dma.c   | 10 ++++--
> > > > >    .../net/ethernet/stmicro/stmmac/dwmac_dma.h   | 35 +++++++++++++++++++
> > > > >    .../net/ethernet/stmicro/stmmac/dwmac_lib.c   | 35 +++++++++++++++----
> > > > >    drivers/net/ethernet/stmicro/stmmac/hwif.c    |  3 +-
> > > > >    .../net/ethernet/stmicro/stmmac/stmmac_main.c |  1 +
> > > > >    include/linux/stmmac.h                        |  1 +
> > > > >    8 files changed, 78 insertions(+), 10 deletions(-)
> > > > > 
> > > > > diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
> > > > > index 721c1f8e892f..48ab21243b26 100644
> > > > > --- a/drivers/net/ethernet/stmicro/stmmac/common.h
> > > > > +++ b/drivers/net/ethernet/stmicro/stmmac/common.h
> > > > > @@ -34,6 +34,7 @@
> > > > >    #define DWMAC_CORE_5_00		0x50
> > > > >    #define DWMAC_CORE_5_10		0x51
> > > > >    #define DWMAC_CORE_5_20		0x52
> > > > > +#define DWLGMAC_CORE_1_00	0x10
> > > > This doesn't look correct because these IDs have been defined for the
> > > > Synopsys IP-core enumerations. Loongson GNET is definitely based on
> > > > some DW GMAC v3.x IP-core, but instead of updating the USERVER field
> > > > vendor just overwrote the GMAC_VERSION.SNPSVER field. From that
> > > > perspective the correct solution would be to override the
> > > > priv->synopsys_id field with a correct IP-core version (0x37?). See my
> > > > last comment for details of how to do that.
> > > See my last reply.
> > > > >    #define DWXGMAC_CORE_2_10	0x21
> > > > >    #define DWXGMAC_CORE_2_20	0x22
> > > > >    #define DWXLGMAC_CORE_2_00	0x20
> > > > > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > > > index 0d79104d7fd3..fb7506bbc21b 100644
> > > > > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > > > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > > > @@ -101,6 +101,8 @@ static int loongson_dwmac_probe(struct pci_dev *pdev,
> > > > >    		plat->mdio_bus_data->needs_reset = true;
> > > > >    	}
> > > > > +	plat->flags |= STMMAC_FLAG_HAS_LGMAC;
> > > > > +
> > > > If what I suggest in the last comment is implemented this will be
> > > > unnecessary.
> > > > 
> > > > >    	/* Enable pci device */
> > > > >    	ret = pci_enable_device(pdev);
> > > > >    	if (ret) {
> > > > > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> > > > > index 0fb48e683970..a01fe6b7540a 100644
> > > > > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> > > > > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> > > > None of the generic parts (dwmac1000_dma.c, dwmac_dma.h, dwmac_lib.c)
> > > > will need to be modified if you implement what I suggest in the last
> > > > comment.
> > > > 
> > > > > @@ -118,7 +118,10 @@ static void dwmac1000_dma_init(struct stmmac_priv *priv, void __iomem *ioaddr,
> > > > See my comment to patch 4/9. This method can be fully dropped in favor
> > > > of having the dwmac1000_dma_init_channel() function implemented.
> > > > 
> > > > >    	u32 dma_intr_mask;
> > > > >    	/* Mask interrupts by writing to CSR7 */
> > > > > -	dma_intr_mask = DMA_INTR_DEFAULT_MASK;
> > > > > +	if (priv->plat->flags & STMMAC_FLAG_HAS_LGMAC)
> > > > > +		dma_intr_mask = DMA_INTR_DEFAULT_MASK_LOONGSON;
> > > > > +	else
> > > > > +		dma_intr_mask = DMA_INTR_DEFAULT_MASK;
> > > > >    	dma_config(ioaddr + DMA_BUS_MODE, ioaddr + DMA_INTR_ENA,
> > > > >    			  dma_cfg, dma_intr_mask, atds);
> > > > > @@ -130,7 +133,10 @@ static void dwmac1000_dma_init_channel(struct stmmac_priv *priv, void __iomem *i
> > > > >    	u32 dma_intr_mask;
> > > > >    	/* Mask interrupts by writing to CSR7 */
> > > > > -	dma_intr_mask = DMA_INTR_DEFAULT_MASK;
> > > > > +	if (priv->plat->flags & STMMAC_FLAG_HAS_LGMAC)
> > > > > +		dma_intr_mask = DMA_INTR_DEFAULT_MASK_LOONGSON;
> > > > > +	else
> > > > > +		dma_intr_mask = DMA_INTR_DEFAULT_MASK;
> > > > >    	if (dma_cfg->multi_msi_en)
> > > > >    		dma_config(ioaddr + DMA_CHAN_BUS_MODE(chan),
> > > > > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
> > > > > index 395d5e4c3922..7d33798c0e72 100644
> > > > > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
> > > > > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
> > > > > @@ -70,16 +70,23 @@
> > > > >    #define DMA_CONTROL_SR		0x00000002	/* Start/Stop Receive */
> > > > >    /* DMA Normal interrupt */
> > > > > +#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_ENA_NIE 0x00010000	/* Normal Summary */
> > > > >    #define DMA_INTR_ENA_TIE 0x00000001	/* Transmit Interrupt */
> > > > >    #define DMA_INTR_ENA_TUE 0x00000004	/* Transmit Buffer Unavailable */
> > > > >    #define DMA_INTR_ENA_RIE 0x00000040	/* Receive Interrupt */
> > > > >    #define DMA_INTR_ENA_ERE 0x00004000	/* Early Receive */
> > > > > +#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_NORMAL	(DMA_INTR_ENA_NIE | DMA_INTR_ENA_RIE | \
> > > > >    			DMA_INTR_ENA_TIE)
> > > > >    /* DMA Abnormal interrupt */
> > > > > +#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_ENA_AIE 0x00008000	/* Abnormal Summary */
> > > > >    #define DMA_INTR_ENA_FBE 0x00002000	/* Fatal Bus Error */
> > > > >    #define DMA_INTR_ENA_ETE 0x00000400	/* Early Transmit */
> > > > > @@ -91,10 +98,14 @@
> > > > >    #define DMA_INTR_ENA_TJE 0x00000008	/* Transmit Jabber */
> > > > >    #define DMA_INTR_ENA_TSE 0x00000002	/* Transmit Stopped */
> > > > > +#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_ABNORMAL	(DMA_INTR_ENA_AIE | DMA_INTR_ENA_FBE | \
> > > > >    				DMA_INTR_ENA_UNE)
> > > > >    /* DMA default interrupt mask */
> > > > > +#define DMA_INTR_DEFAULT_MASK_LOONGSON	(DMA_INTR_NORMAL_LOONGSON | DMA_INTR_ABNORMAL_LOONGSON)
> > > > >    #define DMA_INTR_DEFAULT_MASK	(DMA_INTR_NORMAL | DMA_INTR_ABNORMAL)
> > > > >    #define DMA_INTR_DEFAULT_RX	(DMA_INTR_ENA_RIE)
> > > > >    #define DMA_INTR_DEFAULT_TX	(DMA_INTR_ENA_TIE)
> > > > > @@ -111,9 +122,15 @@
> > > > >    #define DMA_STATUS_TS_SHIFT	20
> > > > >    #define DMA_STATUS_RS_MASK	0x000e0000	/* Receive Process State */
> > > > >    #define DMA_STATUS_RS_SHIFT	17
> > > > > +#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_NIS	0x00010000	/* Normal 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_AIS	0x00008000	/* Abnormal Interrupt Summary */
> > > > >    #define DMA_STATUS_ERI	0x00004000	/* Early Receive Interrupt */
> > > > > +#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_FBI	0x00002000	/* Fatal Bus Error Interrupt */
> > > > >    #define DMA_STATUS_ETI	0x00000400	/* Early Transmit Interrupt */
> > > > >    #define DMA_STATUS_RWT	0x00000200	/* Receive Watchdog Timeout */
> > > > > @@ -128,10 +145,21 @@
> > > > >    #define DMA_STATUS_TI	0x00000001	/* Transmit Interrupt */
> > > > >    #define DMA_CONTROL_FTF		0x00100000	/* Flush transmit FIFO */
> > > > > +#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_COMMON		(DMA_STATUS_NIS | \
> > > > >    					 DMA_STATUS_AIS | \
> > > > >    					 DMA_STATUS_FBI)
> > > > > +#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_RX		(DMA_STATUS_ERI | \
> > > > >    					 DMA_STATUS_RWT | \
> > > > >    					 DMA_STATUS_RPS | \
> > > > > @@ -140,6 +168,13 @@
> > > > >    					 DMA_STATUS_OVF | \
> > > > >    					 DMA_STATUS_MSK_COMMON)
> > > > > +#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)
> > > > >    #define DMA_STATUS_MSK_TX		(DMA_STATUS_ETI | \
> > > > >    					 DMA_STATUS_UNF | \
> > > > >    					 DMA_STATUS_TJT | \
> > > > > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
> > > > > index 968801c694e9..a6e2ab4d0f4a 100644
> > > > > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
> > > > > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
> > > > > @@ -167,6 +167,9 @@ 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 nor_intr_status;
> > > > > +	u32 abnor_intr_status;
> > > > > +	u32 fb_intr_status;
> > > > >    	u32 intr_status = readl(ioaddr + DMA_CHAN_STATUS(chan));
> > > > >    #ifdef DWMAC_DMA_DEBUG
> > > > > @@ -176,13 +179,31 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
> > > > >    	show_rx_process_state(intr_status);
> > > > >    #endif
> > > > > -	if (dir == DMA_DIR_RX)
> > > > > -		intr_status &= DMA_STATUS_MSK_RX;
> > > > > -	else if (dir == DMA_DIR_TX)
> > > > > -		intr_status &= DMA_STATUS_MSK_TX;
> > > > > +	if (priv->plat->flags & STMMAC_FLAG_HAS_LGMAC) {
> > > > > +		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);
> > > > > +	} else {
> > > > > +		if (dir == DMA_DIR_RX)
> > > > > +			intr_status &= DMA_STATUS_MSK_RX;
> > > > > +		else if (dir == DMA_DIR_TX)
> > > > > +			intr_status &= DMA_STATUS_MSK_TX;
> > > > > +
> > > > > +		nor_intr_status = intr_status & DMA_STATUS_NIS;
> > > > > +		abnor_intr_status = intr_status & DMA_STATUS_AIS;
> > > > > +		fb_intr_status = intr_status & DMA_STATUS_FBI;
> > > > > +	}
> > > > >    	/* ABNORMAL interrupts */
> > > > > -	if (unlikely(intr_status & DMA_STATUS_AIS)) {
> > > > > +	if (unlikely(abnor_intr_status)) {
> > > > >    		if (unlikely(intr_status & DMA_STATUS_UNF)) {
> > > > >    			ret = tx_hard_error_bump_tc;
> > > > >    			x->tx_undeflow_irq++;
> > > > > @@ -205,13 +226,13 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
> > > > >    			x->tx_process_stopped_irq++;
> > > > >    			ret = tx_hard_error;
> > > > >    		}
> > > > > -		if (unlikely(intr_status & DMA_STATUS_FBI)) {
> > > > > +		if (unlikely(intr_status & fb_intr_status)) {
> > > > >    			x->fatal_bus_error_irq++;
> > > > >    			ret = tx_hard_error;
> > > > >    		}
> > > > >    	}
> > > > >    	/* TX/RX NORMAL interrupts */
> > > > > -	if (likely(intr_status & DMA_STATUS_NIS)) {
> > > > > +	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. */
> > > > > diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.c b/drivers/net/ethernet/stmicro/stmmac/hwif.c
> > > > > index 1bd34b2a47e8..3724cf698de6 100644
> > > > > --- a/drivers/net/ethernet/stmicro/stmmac/hwif.c
> > > > > +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.c
> > > > > @@ -59,7 +59,8 @@ static int stmmac_dwmac1_quirks(struct stmmac_priv *priv)
> > > > >    		dev_info(priv->device, "Enhanced/Alternate descriptors\n");
> > > > >    		/* GMAC older than 3.50 has no extended descriptors */
> > > > > -		if (priv->synopsys_id >= DWMAC_CORE_3_50) {
> > > > > +		if (priv->synopsys_id >= DWMAC_CORE_3_50 ||
> > > > > +		    priv->synopsys_id == DWLGMAC_CORE_1_00) {
> > > > This could be left as is if the priv->synopsys_id field is overwritten
> > > > with a correct value (see my last comment).
> > > > 
> > > > >    			dev_info(priv->device, "Enabled extended descriptors\n");
> > > > >    			priv->extend_desc = 1;
> > > > >    		} else {
> > > > > diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> > > > > index d868eb8dafc5..9764d2ab7e46 100644
> > > > > --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> > > > > +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> > > > > @@ -7218,6 +7218,7 @@ static int stmmac_hw_init(struct stmmac_priv *priv)
> > > > >    	 * riwt_off field from the platform.
> > > > >    	 */
> > > > >    	if (((priv->synopsys_id >= DWMAC_CORE_3_50) ||
> > > > > +		(priv->synopsys_id == DWLGMAC_CORE_1_00) ||
> > > > the same comment here.
> > > > 
> > > > >    	    (priv->plat->has_xgmac)) && (!priv->plat->riwt_off)) {
> > > > >    		priv->use_riwt = 1;
> > > > >    		dev_info(priv->device,
> > > > > diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
> > > > > index dee5ad6e48c5..f07f79d50b06 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_HAS_LGMAC			BIT(13)
> > > > 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.
> > > OK.
> > > > 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.
> > > It's easy.
> > > > 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.
> > > Do this in dwmac1000-dma.c? Because this seems impossible to achieve in
> > > dwmac-loongson.c:
> > > 
> > > 
> > > drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c:606:47: error:
> > > initializer element is not constant
> > >    606 | const struct stmmac_dma_ops dwlgmac_dma_ops = dwmac1000_dma_ops;
> > > >      + override the stmmac_dma_ops.{dma_interrupt, init_chan} with
> > > >        the pointers to the methods defined in 2.
> > > Likewise, where should I do this?
> > > 
> > > Sorry. I seem to have misinterpreted your meaning again.
> > No worries. Here is what I meant:
> > 
> > 1. Declare the private Loongson GMAC data like this:
> > struct loongson_data {
> > 	struct stmmac_dma_ops dma_ops;
> > };
> > 2. Allocate the memory for the data in the framework of the Loongson
> > GMAC device probe() method:
> > loongson_dwmac_probe()
> > {
> > 	...
> > 	ld = devm_kzalloc(&pdev->dev, sizeof(*ld), GFP_KERNEL);
> > 	if (!ld)
> > 		return -ENOMEM;
> > 	...
> > 	ld->dma_ops = dwmac1000_dma_ops;
> > 	ld->dma_ops.init_chan = loongson_gnat_dma_init_chan;
> > 	ld->dma_ops.dma_interrupt = loongson_gnat_dma_interrupt;
> > 	...
> > 	plat->bsp_priv = ld;
> > }
> > 3. Define the Loongson-specific plat_stmmacenet_data.setup() method,
> > which would re-init the stmmac_priv->synopsys_id with a correct value,
> > allocate the DW *MAC hardware descriptor and pre-initialize it 'dma'
> > field:
> > static struct mac_device_info loongson_gnet_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;
> > 
> > 	priv->synopsys_id = 0x37; // or whatever is a real version of your IP
> > 
> > 	ld = priv->plat->bsp_priv;
> > 	mac->dma = &ld->dma_ops;
> > 
> > 	dwmac1000_setup(); // Or Pre-initialize the respective "mac" fields as it's done in dwmac1000_setup()
> > 
> > 	return mac;
> > }
> > 4. Make sure the plat_stmmacenet_data->setup field is initialized with
> > the Loongson GNAT-specific setup() method:
> > static int loongson_gnet_data(struct pci_dev *pdev,
> >                                struct plat_stmmacenet_data *plat)
> > {
> > 	...
> > 	plat->setup = loongson_gnet_setup;
> > 	...
> > }
> > 
> > That shall do what I described in by previous message.
> > 
> > Note another platform which gets to define its own setup() method
> > Sun8i:
> > drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
> > although since it fully redefines the DMA-ops descriptor the only
> > common part with your case is that it needs to have the setup() method
> > too.
> 

> Thank you so much, this method is so cool!
> 
>  After three weeks of hard work, everything is working now.

Glad my advice could help. Let's see what is done in v8.

* Although I'll be able to get back to review on the next week only.

-Serge(y)

> I will reply to
> your other comments tomorrow.
> 
> 
> Thanks,
> 
> Yanteng
> 
> > > 
> > > 
> > > >      + 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.
> > > > 
> > > > If I didn't miss something stmmac_hwif_init() will call the
> > > > platform-specific setup method right after fetching the SNPSVER field
> > > > value. Your setup method will allocate mac_device_info structure then,
> > > > will pre-initialize the GNET-specific DMA ops field and fix the
> > > > Synopsys ID with a proper value (as described in 3 above). The rest of
> > > > the ops descriptors will be initialized in the loop afterwards based
> > > > on the specified device ID.
> > > This doesn't seem to work because our device looks something like this:
> > Please see my note above.
> > 
> > > device     pci id   reversion    core version
> > > LS7A        0x13       0x00       0x35/0x37
> > > LS7A        0x13       0x01       0x35/0x37
> > > LS2K        0x13       0x00       0x10
> > > LS2K        0x13       0x01       0x10
> > Not sure what you meant by providing this table to me and justifying
> > that something wouldn't work. But it would have been much useful to
> > provide a detailed description of what platforms and devices the
> > current dwmac-loongson.c driver supports and what support you are
> > trying to add. Cover-letter is a suitable place for it.
> > 
> > In anyway the DW GMAC IP-core can't be 0x10. Seeing your device is
> > having the multi-channels support it must have a version closer to
> > 0x37 (the highest IP-core version is 3.73a). Please reach the hardware
> > engineers to clarify what actual DW GMAC IP-core has been utilized in
> > your case.
> > 
> > -Serge(y)
> > 
> > > 
> > > Thanks,
> > > 
> > > Yanteng
> > > 
> > > > -Serge(y)
> > > > 
> > > > >    struct plat_stmmacenet_data {
> > > > >    	int bus_id;
> > > > > -- 
> > > > > 2.31.4
> > > > > 
> 

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

* Re: [PATCH net-next v7 7/9] net: stmmac: dwmac-loongson: Add GNET support
  2024-01-02  1:22       ` Serge Semin
@ 2024-01-25  6:57         ` Yanteng Si
  2024-01-29 11:45         ` Yanteng Si
  1 sibling, 0 replies; 48+ messages in thread
From: Yanteng Si @ 2024-01-25  6:57 UTC (permalink / raw)
  To: Serge Semin
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang


在 2024/1/2 09:22, Serge Semin 写道:
> On Mon, Jan 01, 2024 at 03:27:07PM +0800, Yanteng Si wrote:
>> 在 2023/12/21 10:34, Serge Semin 写道:
>>> On Tue, Dec 19, 2023 at 10:26:47PM +0800, Yanteng Si wrote:
>>>> Add Loongson GNET (GMAC with PHY) support. Current GNET does not support
>>>> half duplex mode, and 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  | 79 +++++++++++++++++++
>>>>    .../ethernet/stmicro/stmmac/stmmac_ethtool.c  |  6 ++
>>>>    include/linux/stmmac.h                        |  2 +
>>>>    3 files changed, 87 insertions(+)
>>>>
>>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>>> index 2c08d5495214..9e4953c7e4e0 100644
>>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>>> @@ -168,6 +168,83 @@ 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 net_device *ndev = dev_get_drvdata(priv);
>>>> +	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);
>>> {} around the outer if please.
>> OK.
>>>> +}
>>>> +
>>>> +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 = 0xfffffffb;
>>> ~BIT(2)?
>> I still need to confirm, please allow me to get back to you later.
>>>> +
>>>> +	plat->phy_addr = 2;
>>>> +	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;
>>>> +
>>>> +	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;
>>>> +	u32 version = readl(res->addr + GMAC_VERSION);
>>>> +
>>>> +	switch (version & 0xff) {
>>>> +	case DWLGMAC_CORE_1_00:
>>>> +		ret = loongson_dwmac_config_multi_msi(pdev, plat, res, np, 8);
>>>> +		break;
>>>> +	default:
>>>> +		ret = loongson_dwmac_config_legacy(pdev, plat, res, np);
>>> Hm, do you have two versions of Loongson GNET? What does the second
>> Yes.
>>> one contain in the GMAC_VERSION register then? Can't you distinguish
>>> them by the PCI IDs (device, subsystem, revision)?
>> I'm afraid that's not possible.
>>
>> Because they have the same pci id and revision.
> Please provide more details about what platform/devices support you
> are adding and what PCI IDs and DW GMAC IP-core version they have.
Okay, I will do my best to make them appear in the next version of the 
commit message.
>
>>
>> Thanks,
>>
>> Yanteng
>>
>>> -Serge(y)
>>>
>>>> +		break;
>>>> +	}
>>>> +
>>>> +	switch (pdev->revision) {
>>>> +	case 0x00:
>>>> +		plat->flags |=
>>>> +			FIELD_PREP(STMMAC_FLAG_DISABLE_HALF_DUPLEX, 1) |
>>>> +			FIELD_PREP(STMMAC_FLAG_DISABLE_FORCE_1000, 1);
>>>> +		break;
>>>> +	case 0x01:
>>>> +		plat->flags |=
>>>> +			FIELD_PREP(STMMAC_FLAG_DISABLE_HALF_DUPLEX, 1);
>>>> +		break;
>>>> +	default:
>>>> +		break;
>>>> +	}
>>>> +
>>>> +	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)
>>>>    {
>>>> @@ -318,9 +395,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);
>>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
>>>> index 8105ce47c6ad..d6939eb9a0d8 100644
>>>> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
>>>> @@ -420,6 +420,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 f07f79d50b06..067030cdb60f 100644
>>>> --- a/include/linux/stmmac.h
>>>> +++ b/include/linux/stmmac.h
>>>> @@ -222,6 +222,8 @@ struct dwmac4_addrs {
>>>>    #define STMMAC_FLAG_EN_TX_LPI_CLOCKGATING	BIT(11)
>>>>    #define STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY	BIT(12)
>>>>    #define STMMAC_FLAG_HAS_LGMAC			BIT(13)
>>>> +#define STMMAC_FLAG_DISABLE_HALF_DUPLEX	BIT(14)
> Just noticed. I do not see this flag affecting any part of the code.
> Drop it if no actual action is implied by it.

Sorry, I lost it, it will be added in the next version, otherwise there 
will be an

error on the 7a13 0x37 device.


@@ -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




Thanks,

Yanteng

>
> -Serge(y)
>
>>>> +#define STMMAC_FLAG_DISABLE_FORCE_1000	BIT(15)
>>>>    struct plat_stmmacenet_data {
>>>>    	int bus_id;
>>>> -- 
>>>> 2.31.4
>>>>


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

* Re: [PATCH net-next v7 7/9] net: stmmac: dwmac-loongson: Add GNET support
  2024-01-24 13:51         ` Serge Semin
@ 2024-01-25  8:36           ` Yanteng Si
  2024-01-25 18:38             ` Serge Semin
  0 siblings, 1 reply; 48+ messages in thread
From: Yanteng Si @ 2024-01-25  8:36 UTC (permalink / raw)
  To: Serge Semin
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang


在 2024/1/24 21:51, Serge Semin 写道:
> On Wed, Jan 24, 2024 at 05:21:03PM +0800, Yanteng Si wrote:
>> 在 2024/1/1 15:27, Yanteng Si 写道:
>>> 在 2023/12/21 10:34, Serge Semin 写道:
>>>> On Tue, Dec 19, 2023 at 10:26:47PM +0800, Yanteng Si wrote:
>>>>> Add Loongson GNET (GMAC with PHY) support. Current GNET does not
>>>>> support
>>>>> half duplex mode, and 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  | 79
>>>>> +++++++++++++++++++
>>>>>    .../ethernet/stmicro/stmmac/stmmac_ethtool.c  |  6 ++
>>>>>    include/linux/stmmac.h                        |  2 +
>>>>>    3 files changed, 87 insertions(+)
>>>>>
>>>>> diff --git
>>>>> a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>>>> b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>>>> index 2c08d5495214..9e4953c7e4e0 100644
>>>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>>>> @@ -168,6 +168,83 @@ 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 net_device *ndev = dev_get_drvdata(priv);
>>>>> +    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);
>>>> {} around the outer if please.
>>> OK.
>>>>> +}
>>>>> +
>>>>> +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 = 0xfffffffb;
>>>> ~BIT(2)?
>>> I still need to confirm, please allow me to get back to you later.
>> Yes, that's fine.

Oops! A warning will be output:

drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c: In function 
'loongson_gnet_data':
drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c:463:41: warning: 
conversion from

'long unsigned int' to 'unsigned int' changes value from 
'18446744073709551611' to '4294967291' [-Woverflow]
   463 |         plat->mdio_bus_data->phy_mask = ~BIT(2);
       |                                         ^

Unfortunately, we don't have an unsigned int macro for BIT(nr).


Thanks,

Yanteng

>
> -Serge(y)
>
>>
>> Thanks,
>>
>> Yanteng
>>
>>
>>>>> +
>>>>> +    plat->phy_addr = 2;
>>>>> +    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;
>>>>> +
>>>>> +    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;
>>>>> +    u32 version = readl(res->addr + GMAC_VERSION);
>>>>> +
>>>>> +    switch (version & 0xff) {
>>>>> +    case DWLGMAC_CORE_1_00:
>>>>> +        ret = loongson_dwmac_config_multi_msi(pdev, plat, res, np, 8);
>>>>> +        break;
>>>>> +    default:
>>>>> +        ret = loongson_dwmac_config_legacy(pdev, plat, res, np);
>>>> Hm, do you have two versions of Loongson GNET? What does the second
>>> Yes.
>>>> one contain in the GMAC_VERSION register then? Can't you distinguish
>>>> them by the PCI IDs (device, subsystem, revision)?
>>> I'm afraid that's not possible.
>>>
>>> Because they have the same pci id and revision.
>>>
>>>
>>> Thanks,
>>>
>>> Yanteng
>>>
>>>> -Serge(y)
>>>>
>>>>> +        break;
>>>>> +    }
>>>>> +
>>>>> +    switch (pdev->revision) {
>>>>> +    case 0x00:
>>>>> +        plat->flags |=
>>>>> +            FIELD_PREP(STMMAC_FLAG_DISABLE_HALF_DUPLEX, 1) |
>>>>> +            FIELD_PREP(STMMAC_FLAG_DISABLE_FORCE_1000, 1);
>>>>> +        break;
>>>>> +    case 0x01:
>>>>> +        plat->flags |=
>>>>> +            FIELD_PREP(STMMAC_FLAG_DISABLE_HALF_DUPLEX, 1);
>>>>> +        break;
>>>>> +    default:
>>>>> +        break;
>>>>> +    }
>>>>> +
>>>>> +    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)
>>>>>    {
>>>>> @@ -318,9 +395,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);
>>>>> diff --git
>>>>> a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
>>>>> b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
>>>>> index 8105ce47c6ad..d6939eb9a0d8 100644
>>>>> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
>>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
>>>>> @@ -420,6 +420,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 f07f79d50b06..067030cdb60f 100644
>>>>> --- a/include/linux/stmmac.h
>>>>> +++ b/include/linux/stmmac.h
>>>>> @@ -222,6 +222,8 @@ struct dwmac4_addrs {
>>>>>    #define STMMAC_FLAG_EN_TX_LPI_CLOCKGATING    BIT(11)
>>>>>    #define STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY    BIT(12)
>>>>>    #define STMMAC_FLAG_HAS_LGMAC            BIT(13)
>>>>> +#define STMMAC_FLAG_DISABLE_HALF_DUPLEX    BIT(14)
>>>>> +#define STMMAC_FLAG_DISABLE_FORCE_1000    BIT(15)
>>>>>      struct plat_stmmacenet_data {
>>>>>        int bus_id;
>>>>> -- 
>>>>> 2.31.4
>>>>>


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

* Re: [PATCH net-next v7 7/9] net: stmmac: dwmac-loongson: Add GNET support
  2024-01-25  8:36           ` Yanteng Si
@ 2024-01-25 18:38             ` Serge Semin
  2024-01-25 18:41               ` Russell King (Oracle)
  0 siblings, 1 reply; 48+ messages in thread
From: Serge Semin @ 2024-01-25 18:38 UTC (permalink / raw)
  To: Yanteng Si
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang

On Thu, Jan 25, 2024 at 04:36:39PM +0800, Yanteng Si wrote:
> 
> 在 2024/1/24 21:51, Serge Semin 写道:
> > On Wed, Jan 24, 2024 at 05:21:03PM +0800, Yanteng Si wrote:
> > > 在 2024/1/1 15:27, Yanteng Si 写道:
> > > > 在 2023/12/21 10:34, Serge Semin 写道:
> > > > > On Tue, Dec 19, 2023 at 10:26:47PM +0800, Yanteng Si wrote:
> > > > > > Add Loongson GNET (GMAC with PHY) support. Current GNET does not
> > > > > > support
> > > > > > half duplex mode, and 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  | 79
> > > > > > +++++++++++++++++++
> > > > > >    .../ethernet/stmicro/stmmac/stmmac_ethtool.c  |  6 ++
> > > > > >    include/linux/stmmac.h                        |  2 +
> > > > > >    3 files changed, 87 insertions(+)
> > > > > > 
> > > > > > diff --git
> > > > > > a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > > > > b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > > > > index 2c08d5495214..9e4953c7e4e0 100644
> > > > > > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > > > > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > > > > @@ -168,6 +168,83 @@ 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 net_device *ndev = dev_get_drvdata(priv);
> > > > > > +    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);
> > > > > {} around the outer if please.
> > > > OK.
> > > > > > +}
> > > > > > +
> > > > > > +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 = 0xfffffffb;
> > > > > ~BIT(2)?
> > > > I still need to confirm, please allow me to get back to you later.
> > > Yes, that's fine.
> 

> Oops! A warning will be output:
> 
> drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c: In function
> 'loongson_gnet_data':
> drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c:463:41: warning:
> conversion from
> 
> 'long unsigned int' to 'unsigned int' changes value from
> '18446744073709551611' to '4294967291' [-Woverflow]
>   463 |         plat->mdio_bus_data->phy_mask = ~BIT(2);
>       |                                         ^
> 
> Unfortunately, we don't have an unsigned int macro for BIT(nr).

Then the alternative ~(1 << 2) would be still more readable then the
open-coded literal like 0xfffffffb. What would be even better than
that:

#define LOONGSON_GNET_PHY_ADDR		0x2
...
	plat->mdio_bus_data->phy_mask = ~(1 << LOONGSON_GNET_PHY_ADDR);
...

-Serge(y)

> 
> 
> Thanks,
> 
> Yanteng
> 
> > 
> > -Serge(y)
> > 
> > > 
> > > Thanks,
> > > 
> > > Yanteng
> > > 
> > > 
> > > > > > +
> > > > > > +    plat->phy_addr = 2;
> > > > > > +    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;
> > > > > > +
> > > > > > +    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;
> > > > > > +    u32 version = readl(res->addr + GMAC_VERSION);
> > > > > > +
> > > > > > +    switch (version & 0xff) {
> > > > > > +    case DWLGMAC_CORE_1_00:
> > > > > > +        ret = loongson_dwmac_config_multi_msi(pdev, plat, res, np, 8);
> > > > > > +        break;
> > > > > > +    default:
> > > > > > +        ret = loongson_dwmac_config_legacy(pdev, plat, res, np);
> > > > > Hm, do you have two versions of Loongson GNET? What does the second
> > > > Yes.
> > > > > one contain in the GMAC_VERSION register then? Can't you distinguish
> > > > > them by the PCI IDs (device, subsystem, revision)?
> > > > I'm afraid that's not possible.
> > > > 
> > > > Because they have the same pci id and revision.
> > > > 
> > > > 
> > > > Thanks,
> > > > 
> > > > Yanteng
> > > > 
> > > > > -Serge(y)
> > > > > 
> > > > > > +        break;
> > > > > > +    }
> > > > > > +
> > > > > > +    switch (pdev->revision) {
> > > > > > +    case 0x00:
> > > > > > +        plat->flags |=
> > > > > > +            FIELD_PREP(STMMAC_FLAG_DISABLE_HALF_DUPLEX, 1) |
> > > > > > +            FIELD_PREP(STMMAC_FLAG_DISABLE_FORCE_1000, 1);
> > > > > > +        break;
> > > > > > +    case 0x01:
> > > > > > +        plat->flags |=
> > > > > > +            FIELD_PREP(STMMAC_FLAG_DISABLE_HALF_DUPLEX, 1);
> > > > > > +        break;
> > > > > > +    default:
> > > > > > +        break;
> > > > > > +    }
> > > > > > +
> > > > > > +    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)
> > > > > >    {
> > > > > > @@ -318,9 +395,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);
> > > > > > diff --git
> > > > > > a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> > > > > > b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> > > > > > index 8105ce47c6ad..d6939eb9a0d8 100644
> > > > > > --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> > > > > > +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> > > > > > @@ -420,6 +420,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 f07f79d50b06..067030cdb60f 100644
> > > > > > --- a/include/linux/stmmac.h
> > > > > > +++ b/include/linux/stmmac.h
> > > > > > @@ -222,6 +222,8 @@ struct dwmac4_addrs {
> > > > > >    #define STMMAC_FLAG_EN_TX_LPI_CLOCKGATING    BIT(11)
> > > > > >    #define STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY    BIT(12)
> > > > > >    #define STMMAC_FLAG_HAS_LGMAC            BIT(13)
> > > > > > +#define STMMAC_FLAG_DISABLE_HALF_DUPLEX    BIT(14)
> > > > > > +#define STMMAC_FLAG_DISABLE_FORCE_1000    BIT(15)
> > > > > >      struct plat_stmmacenet_data {
> > > > > >        int bus_id;
> > > > > > -- 
> > > > > > 2.31.4
> > > > > > 
> 

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

* Re: [PATCH net-next v7 7/9] net: stmmac: dwmac-loongson: Add GNET support
  2024-01-25 18:38             ` Serge Semin
@ 2024-01-25 18:41               ` Russell King (Oracle)
  2024-01-25 20:12                 ` Serge Semin
  0 siblings, 1 reply; 48+ messages in thread
From: Russell King (Oracle) @ 2024-01-25 18:41 UTC (permalink / raw)
  To: Serge Semin
  Cc: Yanteng Si, andrew, hkallweit1, peppe.cavallaro, alexandre.torgue,
	joabreu, Jose.Abreu, chenhuacai, guyinggang, netdev,
	chris.chenfeiyang

On Thu, Jan 25, 2024 at 09:38:30PM +0300, Serge Semin wrote:
> On Thu, Jan 25, 2024 at 04:36:39PM +0800, Yanteng Si wrote:
> > drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c: In function
> > 'loongson_gnet_data':
> > drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c:463:41: warning:
> > conversion from
> > 
> > 'long unsigned int' to 'unsigned int' changes value from
> > '18446744073709551611' to '4294967291' [-Woverflow]
> >   463 |         plat->mdio_bus_data->phy_mask = ~BIT(2);
> >       |                                         ^
> > 
> > Unfortunately, we don't have an unsigned int macro for BIT(nr).
> 
> Then the alternative ~(1 << 2) would be still more readable then the
> open-coded literal like 0xfffffffb. What would be even better than
> that:
> 
> #define LOONGSON_GNET_PHY_ADDR		0x2
> ...
> 	plat->mdio_bus_data->phy_mask = ~(1 << LOONGSON_GNET_PHY_ADDR);

	plat->mdio_bus_data->phy_mask = ~(u32)BIT(2);

would also work.


-- 
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] 48+ messages in thread

* Re: [PATCH net-next v7 7/9] net: stmmac: dwmac-loongson: Add GNET support
  2024-01-25 18:41               ` Russell King (Oracle)
@ 2024-01-25 20:12                 ` Serge Semin
  2024-01-29 11:18                   ` Yanteng Si
  0 siblings, 1 reply; 48+ messages in thread
From: Serge Semin @ 2024-01-25 20:12 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, Jan 25, 2024 at 06:41:08PM +0000, Russell King (Oracle) wrote:
> On Thu, Jan 25, 2024 at 09:38:30PM +0300, Serge Semin wrote:
> > On Thu, Jan 25, 2024 at 04:36:39PM +0800, Yanteng Si wrote:
> > > drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c: In function
> > > 'loongson_gnet_data':
> > > drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c:463:41: warning:
> > > conversion from
> > > 
> > > 'long unsigned int' to 'unsigned int' changes value from
> > > '18446744073709551611' to '4294967291' [-Woverflow]
> > >   463 |         plat->mdio_bus_data->phy_mask = ~BIT(2);
> > >       |                                         ^
> > > 
> > > Unfortunately, we don't have an unsigned int macro for BIT(nr).
> > 
> > Then the alternative ~(1 << 2) would be still more readable then the
> > open-coded literal like 0xfffffffb. What would be even better than
> > that:
> > 
> > #define LOONGSON_GNET_PHY_ADDR		0x2
> > ...
> > 	plat->mdio_bus_data->phy_mask = ~(1 << LOONGSON_GNET_PHY_ADDR);
> 
> 	plat->mdio_bus_data->phy_mask = ~(u32)BIT(2);
> 
> would also work.

Right, explicit type casting will work too. Something
deep inside always inclines me to avoid explicit casts, although in
this case your option may look more readable than the open-coded
bitwise shift.

-Serge(y)

> 
> 
> -- 
> 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] 48+ messages in thread

* Re: [PATCH net-next v7 7/9] net: stmmac: dwmac-loongson: Add GNET support
  2024-01-25 20:12                 ` Serge Semin
@ 2024-01-29 11:18                   ` Yanteng Si
  0 siblings, 0 replies; 48+ messages in thread
From: Yanteng Si @ 2024-01-29 11:18 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/1/26 04:12, Serge Semin 写道:
> On Thu, Jan 25, 2024 at 06:41:08PM +0000, Russell King (Oracle) wrote:
>> On Thu, Jan 25, 2024 at 09:38:30PM +0300, Serge Semin wrote:
>>> On Thu, Jan 25, 2024 at 04:36:39PM +0800, Yanteng Si wrote:
>>>> drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c: In function
>>>> 'loongson_gnet_data':
>>>> drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c:463:41: warning:
>>>> conversion from
>>>>
>>>> 'long unsigned int' to 'unsigned int' changes value from
>>>> '18446744073709551611' to '4294967291' [-Woverflow]
>>>>    463 |         plat->mdio_bus_data->phy_mask = ~BIT(2);
>>>>        |                                         ^
>>>>
>>>> Unfortunately, we don't have an unsigned int macro for BIT(nr).
>>> Then the alternative ~(1 << 2) would be still more readable then the
>>> open-coded literal like 0xfffffffb. What would be even better than
>>> that:
>>>
>>> #define LOONGSON_GNET_PHY_ADDR		0x2
>>> ...
>>> 	plat->mdio_bus_data->phy_mask = ~(1 << LOONGSON_GNET_PHY_ADDR);
>> 	plat->mdio_bus_data->phy_mask = ~(u32)BIT(2);
>>
>> would also work.
> Right, explicit type casting will work too. Something
> deep inside always inclines me to avoid explicit casts, although in
> this case your option may look more readable than the open-coded
> bitwise shift.

OK!


Thanks,

Yanteng

>
> -Serge(y)
>
>>
>> -- 
>> 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] 48+ messages in thread

* Re: [PATCH net-next v7 7/9] net: stmmac: dwmac-loongson: Add GNET support
  2024-01-02  1:22       ` Serge Semin
  2024-01-25  6:57         ` Yanteng Si
@ 2024-01-29 11:45         ` Yanteng Si
  1 sibling, 0 replies; 48+ messages in thread
From: Yanteng Si @ 2024-01-29 11:45 UTC (permalink / raw)
  To: Serge Semin
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang


在 2024/1/2 09:22, Serge Semin 写道:
> On Mon, Jan 01, 2024 at 03:27:07PM +0800, Yanteng Si wrote:
>> 在 2023/12/21 10:34, Serge Semin 写道:
>>> On Tue, Dec 19, 2023 at 10:26:47PM +0800, Yanteng Si wrote:
>>>> Add Loongson GNET (GMAC with PHY) support. Current GNET does not support
>>>> half duplex mode, and 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  | 79 +++++++++++++++++++
>>>>    .../ethernet/stmicro/stmmac/stmmac_ethtool.c  |  6 ++
>>>>    include/linux/stmmac.h                        |  2 +
>>>>    3 files changed, 87 insertions(+)
>>>>
>>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>>> index 2c08d5495214..9e4953c7e4e0 100644
>>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>>> @@ -168,6 +168,83 @@ 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 net_device *ndev = dev_get_drvdata(priv);
>>>> +	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);
>>> {} around the outer if please.
>> OK.
>>>> +}
>>>> +
>>>> +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 = 0xfffffffb;
>>> ~BIT(2)?
>> I still need to confirm, please allow me to get back to you later.
>>>> +
>>>> +	plat->phy_addr = 2;
>>>> +	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;
>>>> +
>>>> +	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;
>>>> +	u32 version = readl(res->addr + GMAC_VERSION);
>>>> +
>>>> +	switch (version & 0xff) {
>>>> +	case DWLGMAC_CORE_1_00:
>>>> +		ret = loongson_dwmac_config_multi_msi(pdev, plat, res, np, 8);
>>>> +		break;
>>>> +	default:
>>>> +		ret = loongson_dwmac_config_legacy(pdev, plat, res, np);
>>> Hm, do you have two versions of Loongson GNET? What does the second
>> Yes.
>>> one contain in the GMAC_VERSION register then? Can't you distinguish
>>> them by the PCI IDs (device, subsystem, revision)?
>> I'm afraid that's not possible.
>>
>> Because they have the same pci id and revision.
> Please provide more details about what platform/devices support you
> are adding and what PCI IDs and DW GMAC IP-core version they have.

DWLGMAC_CORE_1_00 has been removed and I am already making patches.


Thanks,

Yanteng

>
>>
>> Thanks,
>>
>> Yanteng
>>
>>> -Serge(y)
>>>
>>>> +		break;
>>>> +	}
>>>> +
>>>> +	switch (pdev->revision) {
>>>> +	case 0x00:
>>>> +		plat->flags |=
>>>> +			FIELD_PREP(STMMAC_FLAG_DISABLE_HALF_DUPLEX, 1) |
>>>> +			FIELD_PREP(STMMAC_FLAG_DISABLE_FORCE_1000, 1);
>>>> +		break;
>>>> +	case 0x01:
>>>> +		plat->flags |=
>>>> +			FIELD_PREP(STMMAC_FLAG_DISABLE_HALF_DUPLEX, 1);
>>>> +		break;
>>>> +	default:
>>>> +		break;
>>>> +	}
>>>> +
>>>> +	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)
>>>>    {
>>>> @@ -318,9 +395,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);
>>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
>>>> index 8105ce47c6ad..d6939eb9a0d8 100644
>>>> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
>>>> @@ -420,6 +420,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 f07f79d50b06..067030cdb60f 100644
>>>> --- a/include/linux/stmmac.h
>>>> +++ b/include/linux/stmmac.h
>>>> @@ -222,6 +222,8 @@ struct dwmac4_addrs {
>>>>    #define STMMAC_FLAG_EN_TX_LPI_CLOCKGATING	BIT(11)
>>>>    #define STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY	BIT(12)
>>>>    #define STMMAC_FLAG_HAS_LGMAC			BIT(13)
>>>> +#define STMMAC_FLAG_DISABLE_HALF_DUPLEX	BIT(14)
> Just noticed. I do not see this flag affecting any part of the code.
> Drop it if no actual action is implied by it.
>
> -Serge(y)
>
>>>> +#define STMMAC_FLAG_DISABLE_FORCE_1000	BIT(15)
>>>>    struct plat_stmmacenet_data {
>>>>    	int bus_id;
>>>> -- 
>>>> 2.31.4
>>>>


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

end of thread, other threads:[~2024-01-29 11:45 UTC | newest]

Thread overview: 48+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-12-19 14:17 [PATCH net-next v7 0/9] stmmac: Add Loongson platform support Yanteng Si
2023-12-19 14:17 ` [PATCH net-next v7 1/9] net: stmmac: Pass stmmac_priv and chan in some callbacks Yanteng Si
2023-12-20 15:08   ` Simon Horman
2023-12-21  9:40     ` Yanteng Si
2023-12-20 18:18   ` Serge Semin
2023-12-21 11:50     ` Yanteng Si
2023-12-21 12:53       ` Serge Semin
2023-12-21 13:21         ` Yanteng Si
2023-12-19 14:17 ` [PATCH net-next v7 2/9] net: stmmac: dwmac-loongson: Refactor code for loongson_dwmac_probe() Yanteng Si
2024-01-02 10:37   ` Russell King (Oracle)
2024-01-18 12:53     ` Yanteng Si
2023-12-19 14:17 ` [PATCH net-next v7 3/9] net: stmmac: dwmac-loongson: Add full PCI support Yanteng Si
2024-01-02 10:40   ` Russell King (Oracle)
2024-01-12  9:42     ` Yanteng Si
2024-01-18 12:56     ` Yanteng Si
2023-12-19 14:17 ` [PATCH net-next v7 4/9] net: stmmac: Add multi-channel supports Yanteng Si
2023-12-20 22:36   ` Serge Semin
2023-12-29 10:33     ` Yanteng Si
2023-12-30 11:25       ` Serge Semin
2024-01-01  6:57         ` Yanteng Si
2024-01-02  1:04           ` Serge Semin
2023-12-19 14:26 ` [PATCH net-next v7 5/9] net: stmmac: Add Loongson-specific register definitions Yanteng Si
2023-12-21  2:14   ` Serge Semin
2024-01-01  8:31     ` Yanteng Si
2024-01-01 12:26       ` Serge Semin
2024-01-12 10:08         ` Yanteng Si
2024-01-23 13:08         ` Yanteng Si
2024-01-24 13:59           ` Serge Semin
2023-12-19 14:26 ` [PATCH net-next v7 6/9] net: stmmac: dwmac-loongson: Add MSI support Yanteng Si
2023-12-19 14:26 ` [PATCH net-next v7 7/9] net: stmmac: dwmac-loongson: Add GNET support Yanteng Si
2023-12-21  2:34   ` Serge Semin
2024-01-01  7:27     ` Yanteng Si
2024-01-02  1:22       ` Serge Semin
2024-01-25  6:57         ` Yanteng Si
2024-01-29 11:45         ` Yanteng Si
2024-01-24  9:21       ` Yanteng Si
2024-01-24 13:51         ` Serge Semin
2024-01-25  8:36           ` Yanteng Si
2024-01-25 18:38             ` Serge Semin
2024-01-25 18:41               ` Russell King (Oracle)
2024-01-25 20:12                 ` Serge Semin
2024-01-29 11:18                   ` Yanteng Si
2023-12-19 14:28 ` [PATCH net-next v7 8/9] net: stmmac: dwmac-loongson: Disable flow control for GMAC Yanteng Si
2023-12-21  2:35   ` Serge Semin
2024-01-24 10:54     ` Yanteng Si
2023-12-19 14:28 ` [PATCH net-next v7 9/9] net: stmmac: Disable coe for some Loongson GNET Yanteng Si
2023-12-21  2:36   ` Serge Semin
2024-01-23 12:47     ` Yanteng Si

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).