All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH 00/10] net: phy/stmmac: Add Loongson platform support
@ 2023-07-13  2:46 Feiyang Chen
  2023-07-13  2:46 ` [RFC PATCH 01/10] net: phy: Add driver for Loongson PHY Feiyang Chen
                   ` (10 more replies)
  0 siblings, 11 replies; 38+ messages in thread
From: Feiyang Chen @ 2023-07-13  2:46 UTC (permalink / raw)
  To: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	chenhuacai
  Cc: Feiyang Chen, linux, dongbiao, loongson-kernel, netdev,
	loongarch, chris.chenfeiyang

Add driver for Loongson PHY. Extend stmmac functions and macros for
Loongson DWMAC. Add LS7A support for dwmac_loongson.

Feiyang Chen (10):
  net: phy: Add driver for Loongson PHY
  net: stmmac: Pass stmmac_priv and chan in some callbacks
  net: stmmac: dwmac1000: Allow platforms to choose some register
    offsets
  net: stmmac: dwmac1000: Add multi-channel support
  net: stmmac: dwmac1000: Add 64-bit DMA support
  net: stmmac: dwmac1000: Add Loongson register definitions
  net: stmmac: Add Loongson HWIF entry
  net: stmmac: dwmac-loongson: Add LS7A support
  net: stmmac: dwmac-loongson: Add 64-bit DMA and multi-vector support
  net: stmmac: dwmac-loongson: Add GNET support

 drivers/net/ethernet/stmicro/stmmac/Kconfig   |   1 +
 .../net/ethernet/stmicro/stmmac/chain_mode.c  |  28 ++-
 drivers/net/ethernet/stmicro/stmmac/common.h  |   3 +
 drivers/net/ethernet/stmicro/stmmac/descs.h   |   7 +
 .../net/ethernet/stmicro/stmmac/descs_com.h   |  49 ++--
 .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 214 +++++++++++++-----
 .../net/ethernet/stmicro/stmmac/dwmac-sun8i.c |  20 +-
 .../net/ethernet/stmicro/stmmac/dwmac1000.h   |   4 +-
 .../ethernet/stmicro/stmmac/dwmac1000_core.c  |  63 ++++--
 .../ethernet/stmicro/stmmac/dwmac1000_dma.c   | 110 +++++++--
 .../ethernet/stmicro/stmmac/dwmac100_core.c   |  12 +-
 .../ethernet/stmicro/stmmac/dwmac100_dma.c    |   2 +-
 .../net/ethernet/stmicro/stmmac/dwmac4_core.c |  11 +-
 .../ethernet/stmicro/stmmac/dwmac4_descs.c    |  19 +-
 .../net/ethernet/stmicro/stmmac/dwmac4_dma.c  |   8 +-
 .../net/ethernet/stmicro/stmmac/dwmac_dma.h   | 210 +++++++++--------
 .../net/ethernet/stmicro/stmmac/dwmac_lib.c   | 156 +++++++++++--
 .../ethernet/stmicro/stmmac/dwxgmac2_core.c   |  11 +-
 .../ethernet/stmicro/stmmac/dwxgmac2_descs.c  |  17 +-
 .../ethernet/stmicro/stmmac/dwxgmac2_dma.c    |   8 +-
 .../net/ethernet/stmicro/stmmac/enh_desc.c    |  38 ++--
 drivers/net/ethernet/stmicro/stmmac/hwif.c    |  48 +++-
 drivers/net/ethernet/stmicro/stmmac/hwif.h    |  77 ++++---
 .../net/ethernet/stmicro/stmmac/norm_desc.c   |  17 +-
 .../net/ethernet/stmicro/stmmac/ring_mode.c   | 105 +++++++--
 .../net/ethernet/stmicro/stmmac/stmmac_main.c |  31 ++-
 drivers/net/phy/Kconfig                       |   5 +
 drivers/net/phy/Makefile                      |   1 +
 drivers/net/phy/loongson-phy.c                |  69 ++++++
 drivers/net/phy/phy_device.c                  |  16 ++
 include/linux/phy.h                           |   2 +
 include/linux/stmmac.h                        |  51 +++++
 32 files changed, 1054 insertions(+), 359 deletions(-)
 create mode 100644 drivers/net/phy/loongson-phy.c

-- 
2.39.3


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

* [RFC PATCH 01/10] net: phy: Add driver for Loongson PHY
  2023-07-13  2:46 [RFC PATCH 00/10] net: phy/stmmac: Add Loongson platform support Feiyang Chen
@ 2023-07-13  2:46 ` Feiyang Chen
  2023-07-13  4:00   ` Andrew Lunn
  2023-07-13  7:53   ` Russell King (Oracle)
  2023-07-13  2:46 ` [RFC PATCH 02/10] net: stmmac: Pass stmmac_priv and chan in some callbacks Feiyang Chen
                   ` (9 subsequent siblings)
  10 siblings, 2 replies; 38+ messages in thread
From: Feiyang Chen @ 2023-07-13  2:46 UTC (permalink / raw)
  To: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	chenhuacai
  Cc: Feiyang Chen, linux, dongbiao, loongson-kernel, netdev,
	loongarch, chris.chenfeiyang

Add support for the Loongson PHY.

Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
---
 drivers/net/phy/Kconfig        |  5 +++
 drivers/net/phy/Makefile       |  1 +
 drivers/net/phy/loongson-phy.c | 69 ++++++++++++++++++++++++++++++++++
 drivers/net/phy/phy_device.c   | 16 ++++++++
 include/linux/phy.h            |  2 +
 5 files changed, 93 insertions(+)
 create mode 100644 drivers/net/phy/loongson-phy.c

diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 93b8efc79227..4f8ea32cbc68 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -202,6 +202,11 @@ config INTEL_XWAY_PHY
 	  PEF 7061, PEF 7071 and PEF 7072 or integrated into the Intel
 	  SoCs xRX200, xRX300, xRX330, xRX350 and xRX550.
 
+config LOONGSON_PHY
+	tristate "Loongson PHY driver"
+	help
+	  Supports the Loongson PHY.
+
 config LSI_ET1011C_PHY
 	tristate "LSI ET1011C PHY"
 	help
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index f289ab16a1da..f775373e12b7 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -62,6 +62,7 @@ obj-$(CONFIG_DP83TD510_PHY)	+= dp83td510.o
 obj-$(CONFIG_FIXED_PHY)		+= fixed_phy.o
 obj-$(CONFIG_ICPLUS_PHY)	+= icplus.o
 obj-$(CONFIG_INTEL_XWAY_PHY)	+= intel-xway.o
+obj-$(CONFIG_LOONGSON_PHY)	+= loongson-phy.o
 obj-$(CONFIG_LSI_ET1011C_PHY)	+= et1011c.o
 obj-$(CONFIG_LXT_PHY)		+= lxt.o
 obj-$(CONFIG_MARVELL_10G_PHY)	+= marvell10g.o
diff --git a/drivers/net/phy/loongson-phy.c b/drivers/net/phy/loongson-phy.c
new file mode 100644
index 000000000000..d4aefa2110f8
--- /dev/null
+++ b/drivers/net/phy/loongson-phy.c
@@ -0,0 +1,69 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * LS7A PHY driver
+ *
+ * Copyright (C) 2020-2023 Loongson Technology Corporation Limited
+ *
+ * Author: Zhang Baoqi <zhangbaoqi@loongson.cn>
+ */
+
+#include <linux/mii.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/pci.h>
+#include <linux/phy.h>
+
+#define PHY_ID_LS7A2000		0x00061ce0
+#define GNET_REV_LS7A2000	0x00
+
+static int ls7a2000_config_aneg(struct phy_device *phydev)
+{
+	if (phydev->speed == SPEED_1000)
+		phydev->autoneg = AUTONEG_ENABLE;
+
+	if (linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT,
+	    phydev->advertising) ||
+	    linkmode_test_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
+	    phydev->advertising) ||
+	    linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
+	    phydev->advertising))
+	    return genphy_config_aneg(phydev);
+
+	netdev_info(phydev->attached_dev, "Parameter Setting Error\n");
+	return -1;
+}
+
+int ls7a2000_match_phy_device(struct phy_device *phydev)
+{
+	struct net_device *ndev;
+	struct pci_dev *pdev;
+
+	if ((phydev->phy_id & 0xfffffff0) != PHY_ID_LS7A2000)
+		return 0;
+
+	ndev = phydev->mdio.bus->priv;
+	pdev = to_pci_dev(ndev->dev.parent);
+
+	return pdev->revision == GNET_REV_LS7A2000;
+}
+
+static struct phy_driver loongson_phy_driver[] = {
+	{
+		PHY_ID_MATCH_MODEL(PHY_ID_LS7A2000),
+		.name			= "LS7A2000 PHY",
+		.features		= PHY_LOONGSON_FEATURES,
+		.config_aneg		= ls7a2000_config_aneg,
+		.match_phy_device	= ls7a2000_match_phy_device,
+	},
+};
+module_phy_driver(loongson_phy_driver);
+
+static struct mdio_device_id __maybe_unused loongson_tbl[] = {
+	{ PHY_ID_MATCH_MODEL(PHY_ID_LS7A2000) },
+	{ },
+};
+MODULE_DEVICE_TABLE(mdio, loongson_tbl);
+
+MODULE_DESCRIPTION("Loongson PHY driver");
+MODULE_AUTHOR("Zhang Baoqi <zhangbaoqi@loongson.cn>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 53598210be6c..00568608118a 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -146,6 +146,15 @@ static const int phy_eee_cap1_features_array[] = {
 __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_eee_cap1_features) __ro_after_init;
 EXPORT_SYMBOL_GPL(phy_eee_cap1_features);
 
+static const int phy_10_100_1000_full_features_array[] = {
+	ETHTOOL_LINK_MODE_10baseT_Full_BIT,
+	ETHTOOL_LINK_MODE_100baseT_Full_BIT,
+	ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
+};
+
+__ETHTOOL_DECLARE_LINK_MODE_MASK(phy_loongson_features) __ro_after_init;
+EXPORT_SYMBOL_GPL(phy_loongson_features);
+
 static void features_init(void)
 {
 	/* 10/100 half/full*/
@@ -230,6 +239,13 @@ static void features_init(void)
 	linkmode_set_bit_array(phy_eee_cap1_features_array,
 			       ARRAY_SIZE(phy_eee_cap1_features_array),
 			       phy_eee_cap1_features);
+	/* 10/100/1000 full */
+	linkmode_set_bit_array(phy_basic_ports_array,
+			       ARRAY_SIZE(phy_basic_ports_array),
+			       phy_loongson_features);
+	linkmode_set_bit_array(phy_10_100_1000_full_features_array,
+			       ARRAY_SIZE(phy_10_100_1000_full_features_array),
+			       phy_loongson_features);
 
 }
 
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 6478838405a0..6bdb2a479755 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -54,6 +54,7 @@ extern __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_10gbit_features) __ro_after_init;
 extern __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_10gbit_fec_features) __ro_after_init;
 extern __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_10gbit_full_features) __ro_after_init;
 extern __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_eee_cap1_features) __ro_after_init;
+extern __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_loongson_features) __ro_after_init;
 
 #define PHY_BASIC_FEATURES ((unsigned long *)&phy_basic_features)
 #define PHY_BASIC_T1_FEATURES ((unsigned long *)&phy_basic_t1_features)
@@ -65,6 +66,7 @@ extern __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_eee_cap1_features) __ro_after_init;
 #define PHY_10GBIT_FEC_FEATURES ((unsigned long *)&phy_10gbit_fec_features)
 #define PHY_10GBIT_FULL_FEATURES ((unsigned long *)&phy_10gbit_full_features)
 #define PHY_EEE_CAP1_FEATURES ((unsigned long *)&phy_eee_cap1_features)
+#define PHY_LOONGSON_FEATURES ((unsigned long *)&phy_loongson_features)
 
 extern const int phy_basic_ports_array[3];
 extern const int phy_fibre_port_array[1];
-- 
2.39.3


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

* [RFC PATCH 02/10] net: stmmac: Pass stmmac_priv and chan in some callbacks
  2023-07-13  2:46 [RFC PATCH 00/10] net: phy/stmmac: Add Loongson platform support Feiyang Chen
  2023-07-13  2:46 ` [RFC PATCH 01/10] net: phy: Add driver for Loongson PHY Feiyang Chen
@ 2023-07-13  2:46 ` Feiyang Chen
  2023-07-13  4:02   ` Andrew Lunn
  2023-07-13  2:46 ` [RFC PATCH 03/10] net: stmmac: dwmac1000: Allow platforms to choose some register offsets Feiyang Chen
                   ` (8 subsequent siblings)
  10 siblings, 1 reply; 38+ messages in thread
From: Feiyang Chen @ 2023-07-13  2:46 UTC (permalink / raw)
  To: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	chenhuacai
  Cc: Feiyang Chen, linux, dongbiao, loongson-kernel, netdev,
	loongarch, chris.chenfeiyang

Like commit 1d84b487bc2d90 ("net: stmmac: Pass stmmac_priv in some
callbacks"), passing stmmac_priv and chan to more callbacks and
adjust the callbacks accordingly.

Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
---
 .../net/ethernet/stmicro/stmmac/chain_mode.c  |  5 +-
 .../net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 20 +++--
 .../ethernet/stmicro/stmmac/dwmac1000_core.c  |  9 ++-
 .../ethernet/stmicro/stmmac/dwmac1000_dma.c   |  8 +-
 .../ethernet/stmicro/stmmac/dwmac100_core.c   |  9 ++-
 .../ethernet/stmicro/stmmac/dwmac100_dma.c    |  2 +-
 .../net/ethernet/stmicro/stmmac/dwmac4_core.c | 11 ++-
 .../ethernet/stmicro/stmmac/dwmac4_descs.c    | 19 ++---
 .../net/ethernet/stmicro/stmmac/dwmac4_dma.c  |  8 +-
 .../net/ethernet/stmicro/stmmac/dwmac_dma.h   |  3 +-
 .../net/ethernet/stmicro/stmmac/dwmac_lib.c   |  3 +-
 .../ethernet/stmicro/stmmac/dwxgmac2_core.c   | 11 ++-
 .../ethernet/stmicro/stmmac/dwxgmac2_descs.c  | 17 ++--
 .../ethernet/stmicro/stmmac/dwxgmac2_dma.c    |  8 +-
 .../net/ethernet/stmicro/stmmac/enh_desc.c    | 17 ++--
 drivers/net/ethernet/stmicro/stmmac/hwif.h    | 77 ++++++++++---------
 .../net/ethernet/stmicro/stmmac/norm_desc.c   | 17 ++--
 .../net/ethernet/stmicro/stmmac/ring_mode.c   |  4 +-
 .../net/ethernet/stmicro/stmmac/stmmac_main.c |  6 +-
 19 files changed, 145 insertions(+), 109 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/chain_mode.c b/drivers/net/ethernet/stmicro/stmmac/chain_mode.c
index fb55efd52240..a95866871f3e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/chain_mode.c
+++ b/drivers/net/ethernet/stmicro/stmmac/chain_mode.c
@@ -95,8 +95,9 @@ static unsigned int is_jumbo_frm(int len, int enh_desc)
 	return ret;
 }
 
-static void init_dma_chain(void *des, dma_addr_t phy_addr,
-				  unsigned int size, unsigned int extend_desc)
+static void init_dma_chain(struct stmmac_priv *priv, void *des,
+			   dma_addr_t phy_addr, unsigned int size,
+			   unsigned int extend_desc)
 {
 	/*
 	 * In chained mode the des3 points to the next element in the ring.
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
index c2c592ba0eb8..bcb95dcb4371 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
@@ -297,7 +297,7 @@ static int sun8i_dwmac_dma_reset(void __iomem *ioaddr)
 /* sun8i_dwmac_dma_init() - initialize the EMAC
  * Called from stmmac via stmmac_dma_ops->init
  */
-static void sun8i_dwmac_dma_init(void __iomem *ioaddr,
+static void sun8i_dwmac_dma_init(struct stmmac_priv *priv, void __iomem *ioaddr,
 				 struct stmmac_dma_cfg *dma_cfg, int atds)
 {
 	writel(EMAC_RX_INT | EMAC_TX_INT, ioaddr + EMAC_INT_EN);
@@ -394,7 +394,8 @@ 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(struct stmmac_priv *priv,
+						void __iomem *ioaddr, u32 chan)
 {
 	u32 v;
 
@@ -636,7 +637,8 @@ static void sun8i_dwmac_set_mac(void __iomem *ioaddr, bool enable)
  * All slot > 0 need to be enabled with MAC_ADDR_TYPE_DST
  * If addr is NULL, clear the slot
  */
-static void sun8i_dwmac_set_umac_addr(struct mac_device_info *hw,
+static void sun8i_dwmac_set_umac_addr(struct stmmac_priv *priv,
+				      struct mac_device_info *hw,
 				      const unsigned char *addr,
 				      unsigned int reg_n)
 {
@@ -657,7 +659,8 @@ static void sun8i_dwmac_set_umac_addr(struct mac_device_info *hw,
 	}
 }
 
-static void sun8i_dwmac_get_umac_addr(struct mac_device_info *hw,
+static void sun8i_dwmac_get_umac_addr(struct stmmac_priv *priv,
+				      struct mac_device_info *hw,
 				      unsigned char *addr,
 				      unsigned int reg_n)
 {
@@ -680,7 +683,8 @@ static int sun8i_dwmac_rx_ipc_enable(struct mac_device_info *hw)
 	return 1;
 }
 
-static void sun8i_dwmac_set_filter(struct mac_device_info *hw,
+static void sun8i_dwmac_set_filter(struct stmmac_priv *priv,
+				   struct mac_device_info *hw,
 				   struct net_device *dev)
 {
 	void __iomem *ioaddr = hw->pcsr;
@@ -698,13 +702,13 @@ static void sun8i_dwmac_set_filter(struct mac_device_info *hw,
 	} else if (macaddrs <= hw->unicast_filter_entries) {
 		if (!netdev_mc_empty(dev)) {
 			netdev_for_each_mc_addr(ha, dev) {
-				sun8i_dwmac_set_umac_addr(hw, ha->addr, i);
+				sun8i_dwmac_set_umac_addr(priv, hw, ha->addr, i);
 				i++;
 			}
 		}
 		if (!netdev_uc_empty(dev)) {
 			netdev_for_each_uc_addr(ha, dev) {
-				sun8i_dwmac_set_umac_addr(hw, ha->addr, i);
+				sun8i_dwmac_set_umac_addr(priv, hw, ha->addr, i);
 				i++;
 			}
 		}
@@ -716,7 +720,7 @@ static void sun8i_dwmac_set_filter(struct mac_device_info *hw,
 
 	/* Disable unused address filter slots */
 	while (i < hw->unicast_filter_entries)
-		sun8i_dwmac_set_umac_addr(hw, NULL, i++);
+		sun8i_dwmac_set_umac_addr(priv, hw, NULL, i++);
 
 	writel(v, ioaddr + EMAC_RX_FRM_FLT);
 }
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
index 3927609abc44..b52793edf62f 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
@@ -94,7 +94,8 @@ static void dwmac1000_dump_regs(struct mac_device_info *hw, u32 *reg_space)
 		reg_space[i] = readl(ioaddr + i * 4);
 }
 
-static void dwmac1000_set_umac_addr(struct mac_device_info *hw,
+static void dwmac1000_set_umac_addr(struct stmmac_priv *priv,
+				    struct mac_device_info *hw,
 				    const unsigned char *addr,
 				    unsigned int reg_n)
 {
@@ -103,7 +104,8 @@ static void dwmac1000_set_umac_addr(struct mac_device_info *hw,
 			    GMAC_ADDR_LOW(reg_n));
 }
 
-static void dwmac1000_get_umac_addr(struct mac_device_info *hw,
+static void dwmac1000_get_umac_addr(struct stmmac_priv *priv,
+				    struct mac_device_info *hw,
 				    unsigned char *addr,
 				    unsigned int reg_n)
 {
@@ -137,7 +139,8 @@ static void dwmac1000_set_mchash(void __iomem *ioaddr, u32 *mcfilterbits,
 		       ioaddr + GMAC_EXTHASH_BASE + regs * 4);
 }
 
-static void dwmac1000_set_filter(struct mac_device_info *hw,
+static void dwmac1000_set_filter(struct stmmac_priv *priv,
+				 struct mac_device_info *hw,
 				 struct net_device *dev)
 {
 	void __iomem *ioaddr = (void __iomem *)dev->base_addr;
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
index daf79cdbd3ec..ce0e6ca6f3a2 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
@@ -16,7 +16,8 @@
 #include "dwmac1000.h"
 #include "dwmac_dma.h"
 
-static void dwmac1000_dma_axi(void __iomem *ioaddr, struct stmmac_axi *axi)
+static void dwmac1000_dma_axi(struct stmmac_priv *priv, void __iomem *ioaddr,
+			      struct stmmac_axi *axi)
 {
 	u32 value = readl(ioaddr + DMA_AXI_BUS_MODE);
 	int i;
@@ -70,7 +71,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);
@@ -223,7 +224,8 @@ static void dwmac1000_dump_dma_regs(struct stmmac_priv *priv,
 				readl(ioaddr + DMA_BUS_MODE + i * 4);
 }
 
-static int dwmac1000_get_hw_feature(void __iomem *ioaddr,
+static int dwmac1000_get_hw_feature(struct stmmac_priv *priv,
+				    void __iomem *ioaddr,
 				    struct dma_features *dma_cap)
 {
 	u32 hw_cap = readl(ioaddr + DMA_HW_FEATURE);
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
index a6e8d7bd9588..c03623edeb75 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
@@ -59,7 +59,8 @@ static int dwmac100_irq_status(struct mac_device_info *hw,
 	return 0;
 }
 
-static void dwmac100_set_umac_addr(struct mac_device_info *hw,
+static void dwmac100_set_umac_addr(struct stmmac_priv *priv,
+				   struct mac_device_info *hw,
 				   const unsigned char *addr,
 				   unsigned int reg_n)
 {
@@ -67,7 +68,8 @@ static void dwmac100_set_umac_addr(struct mac_device_info *hw,
 	stmmac_set_mac_addr(ioaddr, addr, MAC_ADDR_HIGH, MAC_ADDR_LOW);
 }
 
-static void dwmac100_get_umac_addr(struct mac_device_info *hw,
+static void dwmac100_get_umac_addr(struct stmmac_priv *priv,
+				   struct mac_device_info *hw,
 				   unsigned char *addr,
 				   unsigned int reg_n)
 {
@@ -75,7 +77,8 @@ static void dwmac100_get_umac_addr(struct mac_device_info *hw,
 	stmmac_get_mac_addr(ioaddr, addr, MAC_ADDR_HIGH, MAC_ADDR_LOW);
 }
 
-static void dwmac100_set_filter(struct mac_device_info *hw,
+static void dwmac100_set_filter(struct stmmac_priv *priv,
+				struct mac_device_info *hw,
 				struct net_device *dev)
 {
 	void __iomem *ioaddr = (void __iomem *)dev->base_addr;
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
index 1c32b1788f02..e6ae230fa453 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_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
index 11a51a8a80ff..c0db43138bb7 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
@@ -330,7 +330,8 @@ static void dwmac4_pmt(struct mac_device_info *hw, unsigned long mode)
 	writel(pmt, ioaddr + GMAC_PMT);
 }
 
-static void dwmac4_set_umac_addr(struct mac_device_info *hw,
+static void dwmac4_set_umac_addr(struct stmmac_priv *priv,
+				 struct mac_device_info *hw,
 				 const unsigned char *addr, unsigned int reg_n)
 {
 	void __iomem *ioaddr = hw->pcsr;
@@ -339,7 +340,8 @@ static void dwmac4_set_umac_addr(struct mac_device_info *hw,
 				   GMAC_ADDR_LOW(reg_n));
 }
 
-static void dwmac4_get_umac_addr(struct mac_device_info *hw,
+static void dwmac4_get_umac_addr(struct stmmac_priv *priv,
+				 struct mac_device_info *hw,
 				 unsigned char *addr, unsigned int reg_n)
 {
 	void __iomem *ioaddr = hw->pcsr;
@@ -588,7 +590,8 @@ static void dwmac4_restore_hw_vlan_rx_fltr(struct net_device *dev,
 	}
 }
 
-static void dwmac4_set_filter(struct mac_device_info *hw,
+static void dwmac4_set_filter(struct stmmac_priv *priv,
+			      struct mac_device_info *hw,
 			      struct net_device *dev)
 {
 	void __iomem *ioaddr = (void __iomem *)dev->base_addr;
@@ -664,7 +667,7 @@ static void dwmac4_set_filter(struct mac_device_info *hw,
 		int reg = 1;
 
 		netdev_for_each_uc_addr(ha, dev) {
-			dwmac4_set_umac_addr(hw, ha->addr, reg);
+			dwmac4_set_umac_addr(priv, hw, ha->addr, reg);
 			reg++;
 		}
 
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c
index 6a011d8633e8..98061986c5f4 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c
@@ -175,7 +175,7 @@ static int dwmac4_wrback_get_rx_status(struct net_device_stats *stats,
 	return ret;
 }
 
-static int dwmac4_rd_get_tx_len(struct dma_desc *p)
+static int dwmac4_rd_get_tx_len(struct stmmac_priv *priv, struct dma_desc *p)
 {
 	return (le32_to_cpu(p->des2) & TDES2_BUFFER1_SIZE_MASK);
 }
@@ -296,8 +296,8 @@ static int dwmac4_wrback_get_rx_timestamp_status(void *desc, void *next_desc,
 	return 0;
 }
 
-static void dwmac4_rd_init_rx_desc(struct dma_desc *p, int disable_rx_ic,
-				   int mode, int end, int bfsize)
+static void dwmac4_rd_init_rx_desc(struct stmmac_priv *priv, struct dma_desc *p,
+				   int disable_rx_ic, int mode, int end, int bfsize)
 {
 	dwmac4_set_rx_owner(p, disable_rx_ic);
 }
@@ -310,9 +310,9 @@ static void dwmac4_rd_init_tx_desc(struct dma_desc *p, int mode, int end)
 	p->des3 = 0;
 }
 
-static void dwmac4_rd_prepare_tx_desc(struct dma_desc *p, int is_fs, int len,
-				      bool csum_flag, int mode, bool tx_own,
-				      bool ls, unsigned int tot_pkt_len)
+static void dwmac4_rd_prepare_tx_desc(struct stmmac_priv *priv, struct dma_desc *p,
+				      int is_fs, int len, bool csum_flag, int mode,
+				      bool tx_own, bool ls, unsigned int tot_pkt_len)
 {
 	unsigned int tdes3 = le32_to_cpu(p->des3);
 
@@ -462,13 +462,14 @@ static void dwmac4_set_mss_ctxt(struct dma_desc *p, unsigned int mss)
 	p->des3 = cpu_to_le32(TDES3_CONTEXT_TYPE | TDES3_CTXT_TCMSSV);
 }
 
-static void dwmac4_set_addr(struct dma_desc *p, dma_addr_t addr)
+static void dwmac4_set_addr(struct stmmac_priv *priv, struct dma_desc *p,
+			    dma_addr_t addr)
 {
 	p->des0 = cpu_to_le32(lower_32_bits(addr));
 	p->des1 = cpu_to_le32(upper_32_bits(addr));
 }
 
-static void dwmac4_clear(struct dma_desc *p)
+static void dwmac4_clear(struct stmmac_priv *priv, struct dma_desc *p)
 {
 	p->des0 = 0;
 	p->des1 = 0;
@@ -483,7 +484,7 @@ static void dwmac4_set_sarc(struct dma_desc *p, u32 sarc_type)
 	p->des3 |= cpu_to_le32(sarc_type & TDES3_SA_INSERT_CTRL_MASK);
 }
 
-static int set_16kib_bfsize(int mtu)
+static int set_16kib_bfsize(struct stmmac_priv *priv, int mtu)
 {
 	int ret = 0;
 
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
index 84d3a8551b03..97dad00dc850 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
@@ -15,7 +15,8 @@
 #include "dwmac4_dma.h"
 #include "stmmac.h"
 
-static void dwmac4_dma_axi(void __iomem *ioaddr, struct stmmac_axi *axi)
+static void dwmac4_dma_axi(struct stmmac_priv *priv, void __iomem *ioaddr,
+			   struct stmmac_axi *axi)
 {
 	u32 value = readl(ioaddr + DMA_SYS_BUS_MODE);
 	int i;
@@ -152,7 +153,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);
@@ -374,7 +375,8 @@ static void dwmac4_dma_tx_chan_op_mode(struct stmmac_priv *priv,
 	writel(mtl_tx_op, ioaddr +  MTL_CHAN_TX_OP_MODE(dwmac4_addrs, channel));
 }
 
-static int dwmac4_get_hw_feature(void __iomem *ioaddr,
+static int dwmac4_get_hw_feature(struct stmmac_priv *priv,
+				 void __iomem *ioaddr,
 				 struct dma_features *dma_cap)
 {
 	u32 hw_cap = readl(ioaddr + GMAC_HW_FEATURE0);
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 0b6f999a8305..2dd457032187 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
@@ -27,7 +27,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_core.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
index a0c2ef8bb0ac..640c1b4a0c14 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
@@ -337,7 +337,8 @@ static void dwxgmac2_pmt(struct mac_device_info *hw, unsigned long mode)
 	writel(val, ioaddr + XGMAC_PMT);
 }
 
-static void dwxgmac2_set_umac_addr(struct mac_device_info *hw,
+static void dwxgmac2_set_umac_addr(struct stmmac_priv *priv,
+				   struct mac_device_info *hw,
 				   const unsigned char *addr,
 				   unsigned int reg_n)
 {
@@ -351,7 +352,8 @@ static void dwxgmac2_set_umac_addr(struct mac_device_info *hw,
 	writel(value, ioaddr + XGMAC_ADDRx_LOW(reg_n));
 }
 
-static void dwxgmac2_get_umac_addr(struct mac_device_info *hw,
+static void dwxgmac2_get_umac_addr(struct stmmac_priv *priv,
+				   struct mac_device_info *hw,
 				   unsigned char *addr, unsigned int reg_n)
 {
 	void __iomem *ioaddr = hw->pcsr;
@@ -440,7 +442,8 @@ static void dwxgmac2_set_mchash(void __iomem *ioaddr, u32 *mcfilterbits,
 		writel(mcfilterbits[regs], ioaddr + XGMAC_HASH_TABLE(regs));
 }
 
-static void dwxgmac2_set_filter(struct mac_device_info *hw,
+static void dwxgmac2_set_filter(struct stmmac_priv *priv,
+				struct mac_device_info *hw,
 				struct net_device *dev)
 {
 	void __iomem *ioaddr = (void __iomem *)dev->base_addr;
@@ -485,7 +488,7 @@ static void dwxgmac2_set_filter(struct mac_device_info *hw,
 		int reg = 1;
 
 		netdev_for_each_uc_addr(ha, dev) {
-			dwxgmac2_set_umac_addr(hw, ha->addr, reg);
+			dwxgmac2_set_umac_addr(priv, hw, ha->addr, reg);
 			reg++;
 		}
 
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c
index 13c347ee8be9..e6fb47563fc0 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c
@@ -41,7 +41,7 @@ static int dwxgmac2_get_rx_status(struct net_device_stats *stats,
 	return good_frame;
 }
 
-static int dwxgmac2_get_tx_len(struct dma_desc *p)
+static int dwxgmac2_get_tx_len(struct stmmac_priv *priv, struct dma_desc *p)
 {
 	return (le32_to_cpu(p->des2) & XGMAC_TDES2_B1L);
 }
@@ -128,8 +128,8 @@ static int dwxgmac2_get_rx_timestamp_status(void *desc, void *next_desc,
 	return !ret;
 }
 
-static void dwxgmac2_init_rx_desc(struct dma_desc *p, int disable_rx_ic,
-				  int mode, int end, int bfsize)
+static void dwxgmac2_init_rx_desc(struct stmmac_priv *priv, struct dma_desc *p,
+				  int disable_rx_ic, int mode, int end, int bfsize)
 {
 	dwxgmac2_set_rx_owner(p, disable_rx_ic);
 }
@@ -142,9 +142,9 @@ static void dwxgmac2_init_tx_desc(struct dma_desc *p, int mode, int end)
 	p->des3 = 0;
 }
 
-static void dwxgmac2_prepare_tx_desc(struct dma_desc *p, int is_fs, int len,
-				     bool csum_flag, int mode, bool tx_own,
-				     bool ls, unsigned int tot_pkt_len)
+static void dwxgmac2_prepare_tx_desc(struct stmmac_priv *priv, struct dma_desc *p,
+				     int is_fs, int len, bool csum_flag, int mode,
+				     bool tx_own, bool ls, unsigned int tot_pkt_len)
 {
 	unsigned int tdes3 = le32_to_cpu(p->des3);
 
@@ -241,13 +241,14 @@ static void dwxgmac2_set_mss(struct dma_desc *p, unsigned int mss)
 	p->des3 = cpu_to_le32(XGMAC_TDES3_CTXT | XGMAC_TDES3_TCMSSV);
 }
 
-static void dwxgmac2_set_addr(struct dma_desc *p, dma_addr_t addr)
+static void dwxgmac2_set_addr(struct stmmac_priv *priv, struct dma_desc *p,
+			      dma_addr_t addr)
 {
 	p->des0 = cpu_to_le32(lower_32_bits(addr));
 	p->des1 = cpu_to_le32(upper_32_bits(addr));
 }
 
-static void dwxgmac2_clear(struct dma_desc *p)
+static void dwxgmac2_clear(struct stmmac_priv *priv, struct dma_desc *p)
 {
 	p->des0 = 0;
 	p->des1 = 0;
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
index dfd53264e036..c6b032cd6d9a 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);
@@ -81,7 +81,8 @@ static void dwxgmac2_dma_init_tx_chan(struct stmmac_priv *priv,
 	writel(lower_32_bits(phy), ioaddr + XGMAC_DMA_CH_TxDESC_LADDR(chan));
 }
 
-static void dwxgmac2_dma_axi(void __iomem *ioaddr, struct stmmac_axi *axi)
+static void dwxgmac2_dma_axi(struct stmmac_priv *priv, void __iomem *ioaddr,
+			     struct stmmac_axi *axi)
 {
 	u32 value = readl(ioaddr + XGMAC_DMA_SYSBUS_MODE);
 	int i;
@@ -382,7 +383,8 @@ static int dwxgmac2_dma_interrupt(struct stmmac_priv *priv,
 	return ret;
 }
 
-static int dwxgmac2_get_hw_feature(void __iomem *ioaddr,
+static int dwxgmac2_get_hw_feature(struct stmmac_priv *priv,
+				   void __iomem *ioaddr,
 				   struct dma_features *dma_cap)
 {
 	u32 hw_cap;
diff --git a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
index a91d8f13a931..1932a3a8e03c 100644
--- a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
+++ b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
@@ -79,7 +79,7 @@ static int enh_desc_get_tx_status(struct net_device_stats *stats,
 	return ret;
 }
 
-static int enh_desc_get_tx_len(struct dma_desc *p)
+static int enh_desc_get_tx_len(struct stmmac_priv *priv, struct dma_desc *p)
 {
 	return (le32_to_cpu(p->des1) & ETDES1_BUFFER1_SIZE_MASK);
 }
@@ -255,8 +255,8 @@ static int enh_desc_get_rx_status(struct net_device_stats *stats,
 	return ret;
 }
 
-static void enh_desc_init_rx_desc(struct dma_desc *p, int disable_rx_ic,
-				  int mode, int end, int bfsize)
+static void enh_desc_init_rx_desc(struct stmmac_priv *priv, struct dma_desc *p,
+				  int disable_rx_ic, int mode, int end, int bfsize)
 {
 	int bfsize1;
 
@@ -314,9 +314,9 @@ static void enh_desc_release_tx_desc(struct dma_desc *p, int mode)
 		enh_desc_end_tx_desc_on_ring(p, ter);
 }
 
-static void enh_desc_prepare_tx_desc(struct dma_desc *p, int is_fs, int len,
-				     bool csum_flag, int mode, bool tx_own,
-				     bool ls, unsigned int tot_pkt_len)
+static void enh_desc_prepare_tx_desc(struct stmmac_priv *priv, struct dma_desc *p,
+				     int is_fs, int len, bool csum_flag, int mode,
+				     bool tx_own, bool ls, unsigned int tot_pkt_len)
 {
 	unsigned int tdes0 = le32_to_cpu(p->des0);
 
@@ -441,12 +441,13 @@ static void enh_desc_display_ring(void *head, unsigned int size, bool rx,
 	pr_info("\n");
 }
 
-static void enh_desc_set_addr(struct dma_desc *p, dma_addr_t addr)
+static void enh_desc_set_addr(struct stmmac_priv *priv, struct dma_desc *p,
+			      dma_addr_t addr)
 {
 	p->des2 = cpu_to_le32(addr);
 }
 
-static void enh_desc_clear(struct dma_desc *p)
+static void enh_desc_clear(struct stmmac_priv *priv, struct dma_desc *p)
 {
 	p->des2 = 0;
 }
diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h
index 6ee7cf07cfd7..ed083112c8f1 100644
--- a/drivers/net/ethernet/stmicro/stmmac/hwif.h
+++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h
@@ -35,14 +35,14 @@ struct dma_edesc;
 /* Descriptors helpers */
 struct stmmac_desc_ops {
 	/* DMA RX descriptor ring initialization */
-	void (*init_rx_desc)(struct dma_desc *p, int disable_rx_ic, int mode,
-			int end, int bfsize);
+	void (*init_rx_desc)(struct stmmac_priv *priv, struct dma_desc *p,
+			int disable_rx_ic, int mode, int end, int bfsize);
 	/* DMA TX descriptor ring initialization */
 	void (*init_tx_desc)(struct dma_desc *p, int mode, int end);
 	/* Invoked by the xmit function to prepare the tx descriptor */
-	void (*prepare_tx_desc)(struct dma_desc *p, int is_fs, int len,
-			bool csum_flag, int mode, bool tx_own, bool ls,
-			unsigned int tot_pkt_len);
+	void (*prepare_tx_desc)(struct stmmac_priv *priv, struct dma_desc *p,
+			int is_fs, int len, bool csum_flag, int mode,
+			bool tx_own, bool ls, unsigned int tot_pkt_len);
 	void (*prepare_tso_tx_desc)(struct dma_desc *p, int is_fs, int len1,
 			int len2, bool tx_own, bool ls, unsigned int tcphdrlen,
 			unsigned int tcppayloadlen);
@@ -61,7 +61,7 @@ struct stmmac_desc_ops {
 			 struct stmmac_extra_stats *x,
 			 struct dma_desc *p, void __iomem *ioaddr);
 	/* Get the buffer size from the descriptor */
-	int (*get_tx_len)(struct dma_desc *p);
+	int (*get_tx_len)(struct stmmac_priv *priv, struct dma_desc *p);
 	/* Handle extra events on specific interrupts hw dependent */
 	void (*set_rx_owner)(struct dma_desc *p, int disable_rx_ic);
 	/* Get the receive frame size */
@@ -87,9 +87,10 @@ struct stmmac_desc_ops {
 	/* set MSS via context descriptor */
 	void (*set_mss)(struct dma_desc *p, unsigned int mss);
 	/* set descriptor skbuff address */
-	void (*set_addr)(struct dma_desc *p, dma_addr_t addr);
+	void (*set_addr)(struct stmmac_priv *priv, struct dma_desc *p,
+			dma_addr_t addr);
 	/* clear descriptor */
-	void (*clear)(struct dma_desc *p);
+	void (*clear)(struct stmmac_priv *priv, struct dma_desc *p);
 	/* RSS */
 	int (*get_rx_hash)(struct dma_desc *p, u32 *hash,
 			   enum pkt_hash_types *type);
@@ -103,11 +104,11 @@ struct stmmac_desc_ops {
 };
 
 #define stmmac_init_rx_desc(__priv, __args...) \
-	stmmac_do_void_callback(__priv, desc, init_rx_desc, __args)
+	stmmac_do_void_callback(__priv, desc, init_rx_desc, __priv, __args)
 #define stmmac_init_tx_desc(__priv, __args...) \
 	stmmac_do_void_callback(__priv, desc, init_tx_desc, __args)
 #define stmmac_prepare_tx_desc(__priv, __args...) \
-	stmmac_do_void_callback(__priv, desc, prepare_tx_desc, __args)
+	stmmac_do_void_callback(__priv, desc, prepare_tx_desc, __priv, __args)
 #define stmmac_prepare_tso_tx_desc(__priv, __args...) \
 	stmmac_do_void_callback(__priv, desc, prepare_tso_tx_desc, __args)
 #define stmmac_set_tx_owner(__priv, __args...) \
@@ -123,7 +124,7 @@ struct stmmac_desc_ops {
 #define stmmac_tx_status(__priv, __args...) \
 	stmmac_do_callback(__priv, desc, tx_status, __args)
 #define stmmac_get_tx_len(__priv, __args...) \
-	stmmac_do_callback(__priv, desc, get_tx_len, __args)
+	stmmac_do_callback(__priv, desc, get_tx_len, __priv, __args)
 #define stmmac_set_rx_owner(__priv, __args...) \
 	stmmac_do_void_callback(__priv, desc, set_rx_owner, __args)
 #define stmmac_get_rx_frame_len(__priv, __args...) \
@@ -145,9 +146,9 @@ struct stmmac_desc_ops {
 #define stmmac_set_mss(__priv, __args...) \
 	stmmac_do_void_callback(__priv, desc, set_mss, __args)
 #define stmmac_set_desc_addr(__priv, __args...) \
-	stmmac_do_void_callback(__priv, desc, set_addr, __args)
+	stmmac_do_void_callback(__priv, desc, set_addr, __priv, __args)
 #define stmmac_clear_desc(__priv, __args...) \
-	stmmac_do_void_callback(__priv, desc, clear, __args)
+	stmmac_do_void_callback(__priv, desc, clear, __priv, __args)
 #define stmmac_get_rx_hash(__priv, __args...) \
 	stmmac_do_callback(__priv, desc, get_rx_hash, __args)
 #define stmmac_get_rx_header_len(__priv, __args...) \
@@ -170,8 +171,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,
@@ -181,7 +182,8 @@ struct stmmac_dma_ops {
 			     struct stmmac_dma_cfg *dma_cfg,
 			     dma_addr_t phy, u32 chan);
 	/* Configure the AXI Bus Mode Register */
-	void (*axi)(void __iomem *ioaddr, struct stmmac_axi *axi);
+	void (*axi)(struct stmmac_priv *priv, void __iomem *ioaddr,
+		    struct stmmac_axi *axi);
 	/* Dump DMA registers */
 	void (*dump_regs)(struct stmmac_priv *priv, void __iomem *ioaddr,
 			  u32 *reg_space);
@@ -194,7 +196,8 @@ struct stmmac_dma_ops {
 	void (*dma_diagnostic_fr)(struct net_device_stats *stats,
 				  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,
@@ -210,7 +213,7 @@ struct stmmac_dma_ops {
 	int (*dma_interrupt)(struct stmmac_priv *priv, void __iomem *ioaddr,
 			     struct stmmac_extra_stats *x, u32 chan, u32 dir);
 	/* If supported then get the optional core features */
-	int (*get_hw_feature)(void __iomem *ioaddr,
+	int (*get_hw_feature)(struct stmmac_priv *priv, void __iomem *ioaddr,
 			      struct dma_features *dma_cap);
 	/* Program the HW RX Watchdog */
 	void (*rx_watchdog)(struct stmmac_priv *priv, void __iomem *ioaddr,
@@ -236,7 +239,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...) \
@@ -244,7 +247,7 @@ struct stmmac_dma_ops {
 #define stmmac_init_tx_chan(__priv, __args...) \
 	stmmac_do_void_callback(__priv, dma, init_tx_chan, __priv, __args)
 #define stmmac_axi(__priv, __args...) \
-	stmmac_do_void_callback(__priv, dma, axi, __args)
+	stmmac_do_void_callback(__priv, dma, axi, __priv, __args)
 #define stmmac_dump_dma_regs(__priv, __args...) \
 	stmmac_do_void_callback(__priv, dma, dump_regs, __priv, __args)
 #define stmmac_dma_rx_mode(__priv, __args...) \
@@ -254,7 +257,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...) \
@@ -270,7 +273,7 @@ struct stmmac_dma_ops {
 #define stmmac_dma_interrupt_status(__priv, __args...) \
 	stmmac_do_callback(__priv, dma, dma_interrupt, __priv, __args)
 #define stmmac_get_hw_feature(__priv, __args...) \
-	stmmac_do_callback(__priv, dma, get_hw_feature, __args)
+	stmmac_do_callback(__priv, dma, get_hw_feature, __priv, __args)
 #define stmmac_rx_watchdog(__priv, __args...) \
 	stmmac_do_void_callback(__priv, dma, rx_watchdog, __priv, __args)
 #define stmmac_set_tx_ring_len(__priv, __args...) \
@@ -340,17 +343,21 @@ struct stmmac_ops {
 	int (*host_mtl_irq_status)(struct stmmac_priv *priv,
 				   struct mac_device_info *hw, u32 chan);
 	/* Multicast filter setting */
-	void (*set_filter)(struct mac_device_info *hw, struct net_device *dev);
+	void (*set_filter)(struct stmmac_priv *priv, struct mac_device_info *hw,
+			   struct net_device *dev);
 	/* Flow control setting */
 	void (*flow_ctrl)(struct mac_device_info *hw, unsigned int duplex,
 			  unsigned int fc, unsigned int pause_time, u32 tx_cnt);
 	/* Set power management mode (e.g. magic frame) */
 	void (*pmt)(struct mac_device_info *hw, unsigned long mode);
 	/* Set/Get Unicast MAC addresses */
-	void (*set_umac_addr)(struct mac_device_info *hw,
+	void (*set_umac_addr)(struct stmmac_priv *priv,
+			      struct mac_device_info *hw,
 			      const unsigned char *addr,
 			      unsigned int reg_n);
-	void (*get_umac_addr)(struct mac_device_info *hw, unsigned char *addr,
+	void (*get_umac_addr)(struct stmmac_priv *priv,
+			      struct mac_device_info *hw,
+			      unsigned char *addr,
 			      unsigned int reg_n);
 	void (*set_eee_mode)(struct mac_device_info *hw,
 			     bool en_tx_lpi_clockgating);
@@ -452,15 +459,15 @@ struct stmmac_ops {
 #define stmmac_host_mtl_irq_status(__priv, __args...) \
 	stmmac_do_callback(__priv, mac, host_mtl_irq_status, __priv, __args)
 #define stmmac_set_filter(__priv, __args...) \
-	stmmac_do_void_callback(__priv, mac, set_filter, __args)
+	stmmac_do_void_callback(__priv, mac, set_filter, __priv, __args)
 #define stmmac_flow_ctrl(__priv, __args...) \
 	stmmac_do_void_callback(__priv, mac, flow_ctrl, __args)
 #define stmmac_pmt(__priv, __args...) \
 	stmmac_do_void_callback(__priv, mac, pmt, __args)
 #define stmmac_set_umac_addr(__priv, __args...) \
-	stmmac_do_void_callback(__priv, mac, set_umac_addr, __args)
+	stmmac_do_void_callback(__priv, mac, set_umac_addr, __priv, __args)
 #define stmmac_get_umac_addr(__priv, __args...) \
-	stmmac_do_void_callback(__priv, mac, get_umac_addr, __args)
+	stmmac_do_void_callback(__priv, mac, get_umac_addr, __priv, __args)
 #define stmmac_set_eee_mode(__priv, __args...) \
 	stmmac_do_void_callback(__priv, mac, set_eee_mode, __args)
 #define stmmac_reset_eee_mode(__priv, __args...) \
@@ -560,27 +567,27 @@ struct stmmac_rx_queue;
 
 /* Helpers to manage the descriptors for chain and ring modes */
 struct stmmac_mode_ops {
-	void (*init) (void *des, dma_addr_t phy_addr, unsigned int size,
-		      unsigned int extend_desc);
+	void (*init) (struct stmmac_priv *priv, void *des, dma_addr_t phy_addr,
+		      unsigned int size, unsigned int extend_desc);
 	unsigned int (*is_jumbo_frm) (int len, int ehn_desc);
 	int (*jumbo_frm)(struct stmmac_tx_queue *tx_q, struct sk_buff *skb,
 			 int csum);
-	int (*set_16kib_bfsize)(int mtu);
-	void (*init_desc3)(struct dma_desc *p);
+	int (*set_16kib_bfsize)(struct stmmac_priv *priv, int mtu);
+	void (*init_desc3)(struct stmmac_priv *priv, struct dma_desc *p);
 	void (*refill_desc3)(struct stmmac_rx_queue *rx_q, struct dma_desc *p);
 	void (*clean_desc3)(struct stmmac_tx_queue *tx_q, struct dma_desc *p);
 };
 
 #define stmmac_mode_init(__priv, __args...) \
-	stmmac_do_void_callback(__priv, mode, init, __args)
+	stmmac_do_void_callback(__priv, mode, init, __priv, __args)
 #define stmmac_is_jumbo_frm(__priv, __args...) \
 	stmmac_do_callback(__priv, mode, is_jumbo_frm, __args)
 #define stmmac_jumbo_frm(__priv, __args...) \
 	stmmac_do_callback(__priv, mode, jumbo_frm, __args)
 #define stmmac_set_16kib_bfsize(__priv, __args...) \
-	stmmac_do_callback(__priv, mode, set_16kib_bfsize, __args)
+	stmmac_do_callback(__priv, mode, set_16kib_bfsize, __priv, __args)
 #define stmmac_init_desc3(__priv, __args...) \
-	stmmac_do_void_callback(__priv, mode, init_desc3, __args)
+	stmmac_do_void_callback(__priv, mode, init_desc3, __priv, __args)
 #define stmmac_refill_desc3(__priv, __args...) \
 	stmmac_do_void_callback(__priv, mode, refill_desc3, __args)
 #define stmmac_clean_desc3(__priv, __args...) \
diff --git a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
index 350e6670a576..22b8f27edfab 100644
--- a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
+++ b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
@@ -61,7 +61,7 @@ static int ndesc_get_tx_status(struct net_device_stats *stats,
 	return ret;
 }
 
-static int ndesc_get_tx_len(struct dma_desc *p)
+static int ndesc_get_tx_len(struct stmmac_priv *priv, struct dma_desc *p)
 {
 	return (le32_to_cpu(p->des1) & RDES1_BUFFER1_SIZE_MASK);
 }
@@ -122,8 +122,8 @@ static int ndesc_get_rx_status(struct net_device_stats *stats,
 	return ret;
 }
 
-static void ndesc_init_rx_desc(struct dma_desc *p, int disable_rx_ic, int mode,
-			       int end, int bfsize)
+static void ndesc_init_rx_desc(struct stmmac_priv *priv, struct dma_desc *p,
+			       int disable_rx_ic, int mode, int end, int bfsize)
 {
 	int bfsize1;
 
@@ -181,9 +181,9 @@ static void ndesc_release_tx_desc(struct dma_desc *p, int mode)
 		ndesc_end_tx_desc_on_ring(p, ter);
 }
 
-static void ndesc_prepare_tx_desc(struct dma_desc *p, int is_fs, int len,
-				  bool csum_flag, int mode, bool tx_own,
-				  bool ls, unsigned int tot_pkt_len)
+static void ndesc_prepare_tx_desc(struct stmmac_priv *priv, struct dma_desc *p,
+				  int is_fs, int len, bool csum_flag, int mode,
+				  bool tx_own, bool ls, unsigned int tot_pkt_len)
 {
 	unsigned int tdes1 = le32_to_cpu(p->des1);
 
@@ -292,12 +292,13 @@ static void ndesc_display_ring(void *head, unsigned int size, bool rx,
 	pr_info("\n");
 }
 
-static void ndesc_set_addr(struct dma_desc *p, dma_addr_t addr)
+static void ndesc_set_addr(struct stmmac_priv *priv, struct dma_desc *p,
+			   dma_addr_t addr)
 {
 	p->des2 = cpu_to_le32(addr);
 }
 
-static void ndesc_clear(struct dma_desc *p)
+static void ndesc_clear(struct stmmac_priv *priv, struct dma_desc *p)
 {
 	p->des2 = 0;
 }
diff --git a/drivers/net/ethernet/stmicro/stmmac/ring_mode.c b/drivers/net/ethernet/stmicro/stmmac/ring_mode.c
index d218412ca832..49dd6ea07416 100644
--- a/drivers/net/ethernet/stmicro/stmmac/ring_mode.c
+++ b/drivers/net/ethernet/stmicro/stmmac/ring_mode.c
@@ -111,7 +111,7 @@ static void refill_desc3(struct stmmac_rx_queue *rx_q, struct dma_desc *p)
 }
 
 /* In ring mode we need to fill the desc3 because it is used as buffer */
-static void init_desc3(struct dma_desc *p)
+static void init_desc3(struct stmmac_priv *priv, struct dma_desc *p)
 {
 	p->des3 = cpu_to_le32(le32_to_cpu(p->des2) + BUF_SIZE_8KiB);
 }
@@ -128,7 +128,7 @@ static void clean_desc3(struct stmmac_tx_queue *tx_q, struct dma_desc *p)
 		p->des3 = 0;
 }
 
-static int set_16kib_bfsize(int mtu)
+static int set_16kib_bfsize(struct stmmac_priv *priv, int mtu)
 {
 	int ret = 0;
 	if (unlikely(mtu > BUF_SIZE_8KiB))
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 1bd8f69d7be4..2e95568b1e4a 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -2488,7 +2488,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);
 
 		tx_q->cur_tx = STMMAC_GET_ENTRY(tx_q->cur_tx, priv->dma_conf.dma_tx_size);
 		entry = tx_q->cur_tx;
@@ -4547,7 +4547,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);
@@ -4763,7 +4763,7 @@ static int stmmac_xdp_xmit_xdpf(struct stmmac_priv *priv, int queue,
 		priv->xstats.tx_set_ic_bit++;
 	}
 
-	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.39.3


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

* [RFC PATCH 03/10] net: stmmac: dwmac1000: Allow platforms to choose some register offsets
  2023-07-13  2:46 [RFC PATCH 00/10] net: phy/stmmac: Add Loongson platform support Feiyang Chen
  2023-07-13  2:46 ` [RFC PATCH 01/10] net: phy: Add driver for Loongson PHY Feiyang Chen
  2023-07-13  2:46 ` [RFC PATCH 02/10] net: stmmac: Pass stmmac_priv and chan in some callbacks Feiyang Chen
@ 2023-07-13  2:46 ` Feiyang Chen
  2023-07-13  2:46 ` [RFC PATCH 04/10] net: stmmac: dwmac1000: Add multi-channel support Feiyang Chen
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 38+ messages in thread
From: Feiyang Chen @ 2023-07-13  2:46 UTC (permalink / raw)
  To: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	chenhuacai
  Cc: Feiyang Chen, linux, dongbiao, loongson-kernel, netdev,
	loongarch, chris.chenfeiyang

Some platforms have dwmac1000 implementations that have a different
address space layout than the default. Extend the macro to allow a
platform driver to choose the appropriate register offsets.

Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
---
 .../ethernet/stmicro/stmmac/dwmac1000_core.c  |  14 +-
 .../ethernet/stmicro/stmmac/dwmac100_core.c   |   3 +
 .../net/ethernet/stmicro/stmmac/dwmac_dma.h   | 205 +++++++++---------
 .../net/ethernet/stmicro/stmmac/dwmac_lib.c   |  41 ++++
 include/linux/stmmac.h                        |  48 ++++
 5 files changed, 210 insertions(+), 101 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
index b52793edf62f..9015a61f804c 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
@@ -19,6 +19,7 @@
 #include "stmmac.h"
 #include "stmmac_pcs.h"
 #include "dwmac1000.h"
+#include "dwmac_dma.h"
 
 static void dwmac1000_core_init(struct mac_device_info *hw,
 				struct net_device *dev)
@@ -527,12 +528,10 @@ const struct stmmac_ops dwmac1000_ops = {
 	.set_mac_loopback = dwmac1000_set_mac_loopback,
 };
 
-int dwmac1000_setup(struct stmmac_priv *priv)
+static int _dwmac1000_setup(struct stmmac_priv *priv)
 {
 	struct mac_device_info *mac = priv->hw;
 
-	dev_info(priv->device, "\tDWMAC1000\n");
-
 	priv->dev->priv_flags |= IFF_UNICAST_FLT;
 	mac->pcsr = priv->ioaddr;
 	mac->multicast_filter_bins = priv->plat->multicast_filter_bins;
@@ -558,3 +557,12 @@ int dwmac1000_setup(struct stmmac_priv *priv)
 
 	return 0;
 }
+
+int dwmac1000_setup(struct stmmac_priv *priv)
+{
+	dev_info(priv->device, "\tDWMAC1000\n");
+
+	priv->plat->dwmac_regs = &dwmac_default_dma_regs;
+
+	return _dwmac1000_setup(priv);
+}
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
index c03623edeb75..73ee16549775 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
@@ -18,6 +18,7 @@
 #include <asm/io.h>
 #include "stmmac.h"
 #include "dwmac100.h"
+#include "dwmac_dma.h"
 
 static void dwmac100_core_init(struct mac_device_info *hw,
 			       struct net_device *dev)
@@ -177,6 +178,8 @@ int dwmac100_setup(struct stmmac_priv *priv)
 
 	dev_info(priv->device, "\tDWMAC100\n");
 
+	priv->plat->dwmac_regs = &dwmac_default_dma_regs;
+
 	mac->pcsr = priv->ioaddr;
 	mac->link.duplex = MAC_CONTROL_F;
 	mac->link.speed10 = 0;
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
index e7aef136824b..915a4d70fd3b 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
@@ -11,38 +11,49 @@
 #ifndef __DWMAC_DMA_H__
 #define __DWMAC_DMA_H__
 
-/* DMA CRS Control and Status Register Mapping */
-#define DMA_BUS_MODE		0x00001000	/* Bus Mode */
-#define DMA_XMT_POLL_DEMAND	0x00001004	/* Transmit Poll Demand */
-#define DMA_RCV_POLL_DEMAND	0x00001008	/* Received Poll Demand */
-#define DMA_RCV_BASE_ADDR	0x0000100c	/* Receive List Base */
-#define DMA_TX_BASE_ADDR	0x00001010	/* Transmit List Base */
-#define DMA_STATUS		0x00001014	/* Status Register */
-#define DMA_CONTROL		0x00001018	/* Ctrl (Operational Mode) */
-#define DMA_INTR_ENA		0x0000101c	/* Interrupt Enable */
-#define DMA_MISSED_FRAME_CTR	0x00001020	/* Missed Frame Counter */
+#include "stmmac.h"
 
-/* SW Reset */
-#define DMA_BUS_MODE_SFT_RESET	0x00000001	/* Software Reset */
+#define _REGS			(priv->plat->dwmac_regs)
 
-/* Rx watchdog register */
+/* DMA CRS Control and Status Register Mapping */
+#define DMA_CHAN_OFFSET		(_REGS->addrs->chan_offset)
+#define DMA_BUS_MODE		0x00001000
+#define DMA_XMT_POLL_DEMAND	0x00001004
+#define DMA_RCV_POLL_DEMAND	0x00001008
+#define DMA_RCV_BASE_ADDR	(_REGS->addrs->rcv_base_addr)
+#define DMA_RCV_BASE_ADDR_HI	(DMA_RCV_BASE_ADDR + 0x4)
+#define DMA_TX_BASE_ADDR	(_REGS->addrs->tx_base_addr)
+#define DMA_TX_BASE_ADDR_HI	(DMA_TX_BASE_ADDR + 0x4)
+#define DMA_STATUS		0x00001014
+#define DMA_CONTROL		0x00001018
+#define DMA_INTR_ENA		0x0000101c
+#define DMA_MISSED_FRAME_CTR	0x00001020
 #define DMA_RX_WATCHDOG		0x00001024
-
-/* AXI Master Bus Mode */
 #define DMA_AXI_BUS_MODE	0x00001028
+#define DMA_HW_FEATURE		0x00001058
+#define DMA_FUNC_CONFIG		0x00001080
+#define DMA_FUNC_CONFIG_HI	(DMA_FUNC_CONFIG + 0x4)
+#define DMA_CUR_TX_BUF_ADDR	(_REGS->addrs->cur_tx_buf_addr)
+#define DMA_CUR_TX_BUF_ADDR_HI	(DMA_CUR_TX_BUF_ADDR + 0x4)
+#define DMA_CUR_RX_BUF_ADDR	(_REGS->addrs->cur_rx_buf_addr)
+#define DMA_CUR_RX_BUF_ADDR_HI	(DMA_CUR_RX_BUF_ADDR + 0x4)
+#define DMA_RCV_BASE_ADDR_SHADOW1	0x00001068
+#define DMA_RCV_BASE_ADDR_SHADOW2	0x000010a8
+
+/* SW Reset */
+#define DMA_BUS_MODE_SFT_RESET	0x00000001	/* Software Reset */
 
 #define DMA_AXI_EN_LPI		BIT(31)
 #define DMA_AXI_LPI_XIT_FRM	BIT(30)
-#define DMA_AXI_WR_OSR_LMT	GENMASK(23, 20)
-#define DMA_AXI_WR_OSR_LMT_SHIFT	20
-#define DMA_AXI_WR_OSR_LMT_MASK	0xf
-#define DMA_AXI_RD_OSR_LMT	GENMASK(19, 16)
-#define DMA_AXI_RD_OSR_LMT_SHIFT	16
-#define DMA_AXI_RD_OSR_LMT_MASK	0xf
-
-#define DMA_AXI_OSR_MAX		0xf
-#define DMA_AXI_MAX_OSR_LIMIT ((DMA_AXI_OSR_MAX << DMA_AXI_WR_OSR_LMT_SHIFT) | \
-			       (DMA_AXI_OSR_MAX << DMA_AXI_RD_OSR_LMT_SHIFT))
+#define DMA_AXI_WR_OSR_LMT	(_REGS->axi->wr_osr_lmt)
+#define DMA_AXI_WR_OSR_LMT_SHIFT	(_REGS->axi->wr_osr_lmt_shift)
+#define DMA_AXI_WR_OSR_LMT_MASK	(_REGS->axi->wr_osr_lmt_mask)
+#define DMA_AXI_RD_OSR_LMT	(_REGS->axi->rd_osr_lmt)
+#define DMA_AXI_RD_OSR_LMT_SHIFT	(_REGS->axi->rd_osr_lmt_shift)
+#define DMA_AXI_RD_OSR_LMT_MASK	(_REGS->axi->rd_osr_lmt_mask)
+#define DMA_AXI_OSR_MAX		(_REGS->axi->osr_max)
+#define DMA_AXI_MAX_OSR_LIMIT	((DMA_AXI_OSR_MAX << DMA_AXI_WR_OSR_LMT_SHIFT) | \
+				 (DMA_AXI_OSR_MAX << DMA_AXI_RD_OSR_LMT_SHIFT))
 #define	DMA_AXI_1KBBE		BIT(13)
 #define DMA_AXI_AAL		BIT(12)
 #define DMA_AXI_BLEN256		BIT(7)
@@ -61,38 +72,30 @@
 
 #define DMA_AXI_BURST_LEN_MASK	0x000000FE
 
-#define DMA_CUR_TX_BUF_ADDR	0x00001050	/* Current Host Tx Buffer */
-#define DMA_CUR_RX_BUF_ADDR	0x00001054	/* Current Host Rx Buffer */
-#define DMA_HW_FEATURE		0x00001058	/* HW Feature Register */
-
-/* DMA Control register defines */
-#define DMA_CONTROL_ST		0x00002000	/* Start/Stop Transmission */
-#define DMA_CONTROL_SR		0x00000002	/* Start/Stop Receive */
-
 /* DMA Normal interrupt */
-#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_ENA_NIE	(_REGS->intr_ena->nie)
+#define DMA_INTR_ENA_TIE	0x00000001
+#define DMA_INTR_ENA_TUE	0x00000004
+#define DMA_INTR_ENA_RIE	0x00000040
+#define DMA_INTR_ENA_ERE	0x00004000
 
-#define DMA_INTR_NORMAL	(DMA_INTR_ENA_NIE | 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 0x00008000	/* Abnormal Summary */
-#define DMA_INTR_ENA_FBE 0x00002000	/* Fatal Bus Error */
-#define DMA_INTR_ENA_ETE 0x00000400	/* Early Transmit */
-#define DMA_INTR_ENA_RWE 0x00000200	/* Receive Watchdog */
-#define DMA_INTR_ENA_RSE 0x00000100	/* Receive Stopped */
-#define DMA_INTR_ENA_RUE 0x00000080	/* Receive Buffer Unavailable */
-#define DMA_INTR_ENA_UNE 0x00000020	/* Tx Underflow */
-#define DMA_INTR_ENA_OVE 0x00000010	/* Receive Overflow */
-#define DMA_INTR_ENA_TJE 0x00000008	/* Transmit Jabber */
-#define DMA_INTR_ENA_TSE 0x00000002	/* Transmit Stopped */
+#define DMA_INTR_ENA_AIE	(_REGS->intr_ena->aie)
+#define DMA_INTR_ENA_FBE	0x00002000
+#define DMA_INTR_ENA_ETE	0x00000400
+#define DMA_INTR_ENA_RWE	0x00000200
+#define DMA_INTR_ENA_RSE	0x00000100
+#define DMA_INTR_ENA_RUE	0x00000080
+#define DMA_INTR_ENA_UNE	0x00000020
+#define DMA_INTR_ENA_OVE	0x00000010
+#define DMA_INTR_ENA_TJE	0x00000008
+#define DMA_INTR_ENA_TSE	0x00000002
 
 #define DMA_INTR_ABNORMAL	(DMA_INTR_ENA_AIE | DMA_INTR_ENA_FBE | \
-				DMA_INTR_ENA_UNE)
+				 DMA_INTR_ENA_UNE)
 
 /* DMA default interrupt mask */
 #define DMA_INTR_DEFAULT_MASK	(DMA_INTR_NORMAL | DMA_INTR_ABNORMAL)
@@ -100,58 +103,64 @@
 #define DMA_INTR_DEFAULT_TX	(DMA_INTR_ENA_TIE)
 
 /* DMA Status register defines */
-#define DMA_STATUS_GLPII	0x40000000	/* GMAC LPI interrupt */
-#define DMA_STATUS_GPI		0x10000000	/* PMT interrupt */
-#define DMA_STATUS_GMI		0x08000000	/* MMC interrupt */
-#define DMA_STATUS_GLI		0x04000000	/* GMAC Line interface int */
-#define DMA_STATUS_EB_MASK	0x00380000	/* Error Bits Mask */
-#define DMA_STATUS_EB_TX_ABORT	0x00080000	/* Error Bits - TX Abort */
-#define DMA_STATUS_EB_RX_ABORT	0x00100000	/* Error Bits - RX Abort */
-#define DMA_STATUS_TS_MASK	0x00700000	/* Transmit Process State */
-#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	0x00010000	/* Normal Interrupt Summary */
-#define DMA_STATUS_AIS	0x00008000	/* Abnormal Interrupt Summary */
-#define DMA_STATUS_ERI	0x00004000	/* Early Receive 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 */
-#define DMA_STATUS_RPS	0x00000100	/* Receive Process Stopped */
-#define DMA_STATUS_RU	0x00000080	/* Receive Buffer Unavailable */
-#define DMA_STATUS_RI	0x00000040	/* Receive Interrupt */
-#define DMA_STATUS_UNF	0x00000020	/* Transmit Underflow */
-#define DMA_STATUS_OVF	0x00000010	/* Receive Overflow */
-#define DMA_STATUS_TJT	0x00000008	/* Transmit Jabber Timeout */
-#define DMA_STATUS_TU	0x00000004	/* Transmit Buffer Unavailable */
-#define DMA_STATUS_TPS	0x00000002	/* Transmit Process Stopped */
-#define DMA_STATUS_TI	0x00000001	/* Transmit Interrupt */
-#define DMA_CONTROL_FTF		0x00100000	/* Flush transmit FIFO */
-
-#define DMA_STATUS_MSK_COMMON		(DMA_STATUS_NIS | \
-					 DMA_STATUS_AIS | \
-					 DMA_STATUS_FBI)
-
-#define DMA_STATUS_MSK_RX		(DMA_STATUS_ERI | \
-					 DMA_STATUS_RWT | \
-					 DMA_STATUS_RPS | \
-					 DMA_STATUS_RU | \
-					 DMA_STATUS_RI | \
-					 DMA_STATUS_OVF | \
-					 DMA_STATUS_MSK_COMMON)
-
-#define DMA_STATUS_MSK_TX		(DMA_STATUS_ETI | \
-					 DMA_STATUS_UNF | \
-					 DMA_STATUS_TJT | \
-					 DMA_STATUS_TU | \
-					 DMA_STATUS_TPS | \
-					 DMA_STATUS_TI | \
-					 DMA_STATUS_MSK_COMMON)
+#define DMA_STATUS_GLPII	(_REGS->status->glpii)
+#define DMA_STATUS_GPI		0x10000000
+#define DMA_STATUS_GMI		0x08000000
+#define DMA_STATUS_GLI		0x04000000
+#define DMA_STATUS_EB_MASK	(_REGS->status->eb_mask)
+#define DMA_STATUS_EB_TX_ABORT	0x00080000
+#define DMA_STATUS_EB_RX_ABORT	0x00100000
+#define DMA_STATUS_TS_MASK	(_REGS->status->ts_mask)
+#define DMA_STATUS_TS_SHIFT	(_REGS->status->ts_shift)
+#define DMA_STATUS_RS_MASK	(_REGS->status->rs_mask)
+#define DMA_STATUS_RS_SHIFT	(_REGS->status->rs_shift)
+#define DMA_STATUS_NIS		(_REGS->status->nis)
+#define DMA_STATUS_AIS		(_REGS->status->ais)
+#define DMA_STATUS_ERI		0x00004000
+#define DMA_STATUS_FBI		(_REGS->status->fbi)
+#define DMA_STATUS_ETI		0x00000400
+#define DMA_STATUS_RWT		0x00000200
+#define DMA_STATUS_RPS		0x00000100
+#define DMA_STATUS_RU		0x00000080
+#define DMA_STATUS_RI		0x00000040
+#define DMA_STATUS_UNF		0x00000020
+#define DMA_STATUS_OVF		0x00000010
+#define DMA_STATUS_TJT		0x00000008
+#define DMA_STATUS_TU		0x00000004
+#define DMA_STATUS_TPS		0x00000002
+#define DMA_STATUS_TI		0x00000001
+
+#define DMA_STATUS_MSK_COMMON	(DMA_STATUS_NIS | \
+				 DMA_STATUS_AIS | \
+				 DMA_STATUS_FBI)
+
+#define DMA_STATUS_MSK_RX	(DMA_STATUS_ERI | \
+				 DMA_STATUS_RWT | \
+				 DMA_STATUS_RPS | \
+				 DMA_STATUS_RU | \
+				 DMA_STATUS_RI | \
+				 DMA_STATUS_OVF | \
+				 DMA_STATUS_MSK_COMMON)
+
+#define DMA_STATUS_MSK_TX	(DMA_STATUS_ETI | \
+				 DMA_STATUS_UNF | \
+				 DMA_STATUS_TJT | \
+				 DMA_STATUS_TU | \
+				 DMA_STATUS_TPS | \
+				 DMA_STATUS_TI | \
+				 DMA_STATUS_MSK_COMMON)
+
+/* DMA Control register defines */
+#define DMA_CONTROL_ST		0x00002000	/* Start/Stop Transmission */
+#define DMA_CONTROL_SR		0x00000002	/* Start/Stop Receive */
+#define DMA_CONTROL_FTF		0x00100000      /* Flush transmit FIFO */
 
 #define NUM_DWMAC100_DMA_REGS	9
 #define NUM_DWMAC1000_DMA_REGS	23
 #define NUM_DWMAC4_DMA_REGS	27
 
+extern const struct dwmac_regs dwmac_default_dma_regs;
+
 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,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
index 2dd457032187..266f64148c1a 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
@@ -13,6 +13,47 @@
 
 #define GMAC_HI_REG_AE		0x80000000
 
+static const struct dwmac_dma_addrs default_dma_addrs = {
+	.rcv_base_addr = 0x0000100c,
+	.tx_base_addr = 0x00001010,
+	.cur_tx_buf_addr = 0x00001050,
+	.cur_rx_buf_addr = 0x00001054
+};
+
+static const struct dwmac_dma_axi default_dma_axi = {
+	.wr_osr_lmt = GENMASK(23, 20),
+	.wr_osr_lmt_shift = 20,
+	.wr_osr_lmt_mask = 0xf,
+	.rd_osr_lmt = GENMASK(19, 16),
+	.rd_osr_lmt_shift = 16,
+	.rd_osr_lmt_mask = 0xf,
+	.osr_max = 0xf
+};
+
+static const struct dwmac_dma_intr_ena default_dma_intr_ena = {
+	.nie = 0x00010000,
+	.aie = 0x00008000
+};
+
+static const struct dwmac_dma_status default_dma_status = {
+	.glpii = 0x40000000,
+	.eb_mask = 0x00380000,
+	.ts_mask = 0x00700000,
+	.ts_shift = 20,
+	.rs_mask = 0x000e0000,
+	.rs_shift = 17,
+	.nis = 0x00010000,
+	.ais = 0x00008000,
+	.fbi = 0x00002000
+};
+
+const struct dwmac_regs dwmac_default_dma_regs = {
+	.addrs = &default_dma_addrs,
+	.axi = &default_dma_axi,
+	.intr_ena = &default_dma_intr_ena,
+	.status = &default_dma_status
+};
+
 int dwmac_dma_reset(void __iomem *ioaddr)
 {
 	u32 value = readl(ioaddr + DMA_BUS_MODE);
diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
index 225751a8fd8e..eafe85e45977 100644
--- a/include/linux/stmmac.h
+++ b/include/linux/stmmac.h
@@ -204,6 +204,53 @@ struct dwmac4_addrs {
 	u32 mtl_low_cred_offset;
 };
 
+/* DMA addresses that may be customized by a platform */
+struct dwmac_dma_addrs {
+	u32 chan_offset;
+	u32 rcv_base_addr;
+	u32 tx_base_addr;
+	u32 cur_tx_buf_addr;
+	u32 cur_rx_buf_addr;
+};
+
+/* DMA AXI registers that may be customized by a platform */
+struct dwmac_dma_axi {
+	u32 wr_osr_lmt;
+	u32 wr_osr_lmt_shift;
+	u32 wr_osr_lmt_mask;
+	u32 rd_osr_lmt;
+	u32 rd_osr_lmt_shift;
+	u32 rd_osr_lmt_mask;
+	u32 osr_max;
+};
+
+/* DMA normal and abnormal interrupt that may be customized by a platform */
+struct dwmac_dma_intr_ena {
+	u32 nie;
+	u32 aie;
+};
+
+/* DMA Status register that may be customized by a platform */
+struct dwmac_dma_status {
+	u32 glpii;
+	u32 eb_mask;
+	u32 ts_mask;
+	u32 ts_shift;
+	u32 rs_mask;
+	u32 rs_shift;
+	u32 nis;
+	u32 ais;
+	u32 fbi;
+};
+
+/* Registers that may be customized by a platform */
+struct dwmac_regs {
+	const struct dwmac_dma_addrs *addrs;
+	const struct dwmac_dma_axi *axi;
+	const struct dwmac_dma_intr_ena *intr_ena;
+	const struct dwmac_dma_status *status;
+};
+
 struct plat_stmmacenet_data {
 	int bus_id;
 	int phy_addr;
@@ -293,5 +340,6 @@ struct plat_stmmacenet_data {
 	bool sph_disable;
 	bool serdes_up_after_phy_linkup;
 	const struct dwmac4_addrs *dwmac4_addrs;
+	const struct dwmac_regs *dwmac_regs;
 };
 #endif
-- 
2.39.3


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

* [RFC PATCH 04/10] net: stmmac: dwmac1000: Add multi-channel support
  2023-07-13  2:46 [RFC PATCH 00/10] net: phy/stmmac: Add Loongson platform support Feiyang Chen
                   ` (2 preceding siblings ...)
  2023-07-13  2:46 ` [RFC PATCH 03/10] net: stmmac: dwmac1000: Allow platforms to choose some register offsets Feiyang Chen
@ 2023-07-13  2:46 ` Feiyang Chen
  2023-07-13  2:48 ` [RFC PATCH 05/10] net: stmmac: dwmac1000: Add 64-bit DMA support Feiyang Chen
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 38+ messages in thread
From: Feiyang Chen @ 2023-07-13  2:46 UTC (permalink / raw)
  To: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	chenhuacai
  Cc: Feiyang Chen, linux, dongbiao, loongson-kernel, netdev,
	loongarch, chris.chenfeiyang

Some platforms have dwmac1000 implementations that support multi-
channel. Extend the functions to add multi-channel support.

Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
---
 .../ethernet/stmicro/stmmac/dwmac1000_core.c  |  1 +
 .../ethernet/stmicro/stmmac/dwmac1000_dma.c   | 64 +++++++++++++++++--
 .../net/ethernet/stmicro/stmmac/dwmac_lib.c   | 28 ++++----
 include/linux/stmmac.h                        |  1 +
 4 files changed, 73 insertions(+), 21 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
index 9015a61f804c..a9b42a122ed6 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
@@ -562,6 +562,7 @@ int dwmac1000_setup(struct stmmac_priv *priv)
 {
 	dev_info(priv->device, "\tDWMAC1000\n");
 
+	priv->plat->dwmac_is_loongson = false;
 	priv->plat->dwmac_regs = &dwmac_default_dma_regs;
 
 	return _dwmac1000_setup(priv);
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
index ce0e6ca6f3a2..efb219999a20 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
@@ -111,13 +111,61 @@ static void dwmac1000_dma_init(struct stmmac_priv *priv, void __iomem *ioaddr,
 	writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_INTR_ENA);
 }
 
+void dwmac1000_dma_init_channel(struct stmmac_priv *priv, void __iomem *ioaddr,
+				struct stmmac_dma_cfg *dma_cfg,
+				u32 chan)
+{
+	u32 value;
+	int txpbl = dma_cfg->txpbl ?: dma_cfg->pbl;
+	int rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl;
+
+	if (!priv->plat->dwmac_is_loongson)
+		return;
+
+	/* common channel control register config */
+	value = readl(ioaddr + DMA_BUS_MODE + chan * DMA_CHAN_OFFSET);
+
+	/*
+	 * Set the DMA PBL (Programmable Burst Length) mode.
+	 *
+	 * Note: before stmmac core 3.50 this mode bit was 4xPBL, and
+	 * post 3.5 mode bit acts as 8*PBL.
+	 */
+	if (dma_cfg->pblx8)
+		value |= DMA_BUS_MODE_MAXPBL;
+	value |= DMA_BUS_MODE_USP;
+	value &= ~(DMA_BUS_MODE_PBL_MASK | DMA_BUS_MODE_RPBL_MASK);
+	value |= (txpbl << DMA_BUS_MODE_PBL_SHIFT);
+	value |= (rxpbl << DMA_BUS_MODE_RPBL_SHIFT);
+
+	/* Set the Fixed burst mode */
+	if (dma_cfg->fixed_burst)
+		value |= DMA_BUS_MODE_FB;
+
+	/* Mixed Burst has no effect when fb is set */
+	if (dma_cfg->mixed_burst)
+		value |= DMA_BUS_MODE_MB;
+
+	value |= DMA_BUS_MODE_ATDS;
+
+	if (dma_cfg->aal)
+		value |= DMA_BUS_MODE_AAL;
+
+	writel(value, ioaddr + DMA_BUS_MODE + chan * DMA_CHAN_OFFSET);
+
+	/* Mask interrupts by writing to CSR7 */
+	writel(DMA_INTR_DEFAULT_MASK,
+	       ioaddr + DMA_INTR_ENA + chan * DMA_CHAN_OFFSET);
+}
+
 static void dwmac1000_dma_init_rx(struct stmmac_priv *priv,
 				  void __iomem *ioaddr,
 				  struct stmmac_dma_cfg *dma_cfg,
 				  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_RCV_BASE_ADDR +
+		chan * DMA_CHAN_OFFSET);
 }
 
 static void dwmac1000_dma_init_tx(struct stmmac_priv *priv,
@@ -126,7 +174,8 @@ 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_TX_BASE_ADDR +
+		chan * DMA_CHAN_OFFSET);
 }
 
 static u32 dwmac1000_configure_fc(u32 csr6, int rxfifosz)
@@ -154,7 +203,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_CONTROL + channel * DMA_CHAN_OFFSET);
 
 	if (mode == SF_DMA_MODE) {
 		pr_debug("GMAC: enable RX store and forward mode\n");
@@ -176,14 +225,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_CONTROL + channel * DMA_CHAN_OFFSET);
 }
 
 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_CONTROL + channel * DMA_CHAN_OFFSET);
 
 	if (mode == SF_DMA_MODE) {
 		pr_debug("GMAC: enable TX store and forward mode\n");
@@ -210,7 +259,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_CONTROL + channel * DMA_CHAN_OFFSET);
 }
 
 static void dwmac1000_dump_dma_regs(struct stmmac_priv *priv,
@@ -273,12 +322,13 @@ static int dwmac1000_get_hw_feature(struct stmmac_priv *priv,
 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_RX_WATCHDOG + queue * DMA_CHAN_OFFSET);
 }
 
 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_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
index 266f64148c1a..99838497b183 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
@@ -71,63 +71,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_XMT_POLL_DEMAND + chan * DMA_CHAN_OFFSET);
 }
 
 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_INTR_ENA + chan * DMA_CHAN_OFFSET);
 
 	if (rx)
 		value |= DMA_INTR_DEFAULT_RX;
 	if (tx)
 		value |= DMA_INTR_DEFAULT_TX;
 
-	writel(value, ioaddr + DMA_INTR_ENA);
+	writel(value, ioaddr + DMA_INTR_ENA + chan * DMA_CHAN_OFFSET);
 }
 
 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_INTR_ENA + chan * DMA_CHAN_OFFSET);
 
 	if (rx)
 		value &= ~DMA_INTR_DEFAULT_RX;
 	if (tx)
 		value &= ~DMA_INTR_DEFAULT_TX;
 
-	writel(value, ioaddr + DMA_INTR_ENA);
+	writel(value, ioaddr + DMA_INTR_ENA + chan * DMA_CHAN_OFFSET);
 }
 
 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_CONTROL + chan * DMA_CHAN_OFFSET);
 	value |= DMA_CONTROL_ST;
-	writel(value, ioaddr + DMA_CONTROL);
+	writel(value, ioaddr + DMA_CONTROL + chan * DMA_CHAN_OFFSET);
 }
 
 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_CONTROL + chan * DMA_CHAN_OFFSET);
 	value &= ~DMA_CONTROL_ST;
-	writel(value, ioaddr + DMA_CONTROL);
+	writel(value, ioaddr + DMA_CONTROL + chan * DMA_CHAN_OFFSET);
 }
 
 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_CONTROL + chan * DMA_CHAN_OFFSET);
 	value |= DMA_CONTROL_SR;
-	writel(value, ioaddr + DMA_CONTROL);
+	writel(value, ioaddr + DMA_CONTROL + chan * DMA_CHAN_OFFSET);
 }
 
 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_CONTROL + chan * DMA_CHAN_OFFSET);
 	value &= ~DMA_CONTROL_SR;
-	writel(value, ioaddr + DMA_CONTROL);
+	writel(value, ioaddr + DMA_CONTROL + chan * DMA_CHAN_OFFSET);
 }
 
 #ifdef DWMAC_DMA_DEBUG
@@ -205,7 +205,7 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
 {
 	int ret = 0;
 	/* read the status register (CSR5) */
-	u32 intr_status = readl(ioaddr + DMA_STATUS);
+	u32 intr_status = readl(ioaddr + DMA_STATUS + chan * DMA_CHAN_OFFSET);
 
 #ifdef DWMAC_DMA_DEBUG
 	/* Enable it to monitor DMA rx/tx status in case of critical problems */
diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
index eafe85e45977..ff539681a3a4 100644
--- a/include/linux/stmmac.h
+++ b/include/linux/stmmac.h
@@ -340,6 +340,7 @@ struct plat_stmmacenet_data {
 	bool sph_disable;
 	bool serdes_up_after_phy_linkup;
 	const struct dwmac4_addrs *dwmac4_addrs;
+	bool dwmac_is_loongson;
 	const struct dwmac_regs *dwmac_regs;
 };
 #endif
-- 
2.39.3


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

* [RFC PATCH 05/10] net: stmmac: dwmac1000: Add 64-bit DMA support
  2023-07-13  2:46 [RFC PATCH 00/10] net: phy/stmmac: Add Loongson platform support Feiyang Chen
                   ` (3 preceding siblings ...)
  2023-07-13  2:46 ` [RFC PATCH 04/10] net: stmmac: dwmac1000: Add multi-channel support Feiyang Chen
@ 2023-07-13  2:48 ` Feiyang Chen
  2023-07-13  2:48 ` [RFC PATCH 06/10] net: stmmac: dwmac1000: Add Loongson register definitions Feiyang Chen
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 38+ messages in thread
From: Feiyang Chen @ 2023-07-13  2:48 UTC (permalink / raw)
  To: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	chenhuacai
  Cc: Feiyang Chen, linux, dongbiao, loongson-kernel, netdev,
	loongarch, chris.chenfeiyang

Some platforms have dwmac1000 implementations that support 64-bit
DMA. Extend the functions to add 64-bit DMA support.

Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
---
 .../net/ethernet/stmicro/stmmac/chain_mode.c  |  23 +++-
 drivers/net/ethernet/stmicro/stmmac/descs.h   |   7 ++
 .../net/ethernet/stmicro/stmmac/descs_com.h   |  49 ++++++---
 .../ethernet/stmicro/stmmac/dwmac1000_dma.c   |  30 ++++--
 .../net/ethernet/stmicro/stmmac/enh_desc.c    |  21 +++-
 .../net/ethernet/stmicro/stmmac/ring_mode.c   | 101 ++++++++++++++----
 include/linux/stmmac.h                        |   1 +
 7 files changed, 183 insertions(+), 49 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/chain_mode.c b/drivers/net/ethernet/stmicro/stmmac/chain_mode.c
index a95866871f3e..c8d77cbd51bc 100644
--- a/drivers/net/ethernet/stmicro/stmmac/chain_mode.c
+++ b/drivers/net/ethernet/stmicro/stmmac/chain_mode.c
@@ -36,6 +36,9 @@ static int jumbo_frm(struct stmmac_tx_queue *tx_q, struct sk_buff *skb,
 	des2 = dma_map_single(priv->device, skb->data,
 			      bmax, DMA_TO_DEVICE);
 	desc->des2 = cpu_to_le32(des2);
+	if (priv->plat->dma_cfg->dma64)
+		desc->des3 = cpu_to_le32(upper_32_bits(des2));
+
 	if (dma_mapping_error(priv->device, des2))
 		return -1;
 	tx_q->tx_skbuff_dma[entry].buf = des2;
@@ -54,12 +57,16 @@ static int jumbo_frm(struct stmmac_tx_queue *tx_q, struct sk_buff *skb,
 					      (skb->data + bmax * i),
 					      bmax, DMA_TO_DEVICE);
 			desc->des2 = cpu_to_le32(des2);
+			if (priv->plat->dma_cfg->dma64)
+				desc->des3 = cpu_to_le32(upper_32_bits(des2));
 			if (dma_mapping_error(priv->device, des2))
 				return -1;
 			tx_q->tx_skbuff_dma[entry].buf = des2;
 			tx_q->tx_skbuff_dma[entry].len = bmax;
 			stmmac_prepare_tx_desc(priv, desc, 0, bmax, csum,
-					STMMAC_CHAIN_MODE, 1, false, skb->len);
+					       STMMAC_CHAIN_MODE,
+					       !priv->plat->dma_cfg->dma64,
+					       false, skb->len);
 			len -= bmax;
 			i++;
 		} else {
@@ -67,6 +74,8 @@ static int jumbo_frm(struct stmmac_tx_queue *tx_q, struct sk_buff *skb,
 					      (skb->data + bmax * i), len,
 					      DMA_TO_DEVICE);
 			desc->des2 = cpu_to_le32(des2);
+			if (priv->plat->dma_cfg->dma64)
+				desc->des3 = cpu_to_le32(upper_32_bits(des2));
 			if (dma_mapping_error(priv->device, des2))
 				return -1;
 			tx_q->tx_skbuff_dma[entry].buf = des2;
@@ -110,7 +119,11 @@ static void init_dma_chain(struct stmmac_priv *priv, void *des,
 		struct dma_extended_desc *p = (struct dma_extended_desc *)des;
 		for (i = 0; i < (size - 1); i++) {
 			dma_phy += sizeof(struct dma_extended_desc);
-			p->basic.des3 = cpu_to_le32((unsigned int)dma_phy);
+			if (priv->plat->dma_cfg->dma64) {
+				p->des6 = cpu_to_le32((unsigned int)dma_phy);
+				p->des7 = cpu_to_le32(upper_32_bits(dma_phy));
+			} else
+				p->basic.des3 = cpu_to_le32((unsigned int)dma_phy);
 			p++;
 		}
 		p->basic.des3 = cpu_to_le32((unsigned int)phy_addr);
@@ -130,6 +143,9 @@ static void refill_desc3(struct stmmac_rx_queue *rx_q, struct dma_desc *p)
 {
 	struct stmmac_priv *priv = rx_q->priv_data;
 
+	if (priv->plat->dma_cfg->dma64)
+		return;
+
 	if (priv->hwts_rx_en && !priv->extend_desc)
 		/* NOTE: Device will overwrite des3 with timestamp value if
 		 * 1588-2002 time stamping is enabled, hence reinitialize it
@@ -146,6 +162,9 @@ static void clean_desc3(struct stmmac_tx_queue *tx_q, struct dma_desc *p)
 	struct stmmac_priv *priv = tx_q->priv_data;
 	unsigned int entry = tx_q->dirty_tx;
 
+	if (priv->plat->dma_cfg->dma64)
+		return;
+
 	if (tx_q->tx_skbuff_dma[entry].last_segment && !priv->extend_desc &&
 	    priv->hwts_tx_en)
 		/* NOTE: Device will overwrite des3 with timestamp value if
diff --git a/drivers/net/ethernet/stmicro/stmmac/descs.h b/drivers/net/ethernet/stmicro/stmmac/descs.h
index 49d6a866244f..223b77f0271c 100644
--- a/drivers/net/ethernet/stmicro/stmmac/descs.h
+++ b/drivers/net/ethernet/stmicro/stmmac/descs.h
@@ -56,6 +56,9 @@
 #define ERDES1_BUFFER2_SIZE_SHIFT	16
 #define	ERDES1_DISABLE_IC		BIT(31)
 
+#define	E64RDES1_BUFFER1_SIZE_MASK	GENMASK(13, 0)
+#define	E64RDES1_BUFFER2_SIZE_MASK	GENMASK(29, 16)
+
 /* Normal transmit descriptor defines */
 /* TDES0 */
 #define	TDES0_DEFERRED			BIT(0)
@@ -122,6 +125,10 @@
 #define	ETDES1_BUFFER2_SIZE_MASK	GENMASK(28, 16)
 #define	ETDES1_BUFFER2_SIZE_SHIFT	16
 
+#define	E64TDES1_BUFFER1_SIZE_MASK	GENMASK(13, 0)
+#define	E64TDES1_BUFFER2_SIZE_MASK	GENMASK(28, 15)
+#define	E64TDES1_BUFFER2_SIZE_SHIFT	15
+
 /* Extended Receive descriptor definitions */
 #define	ERDES4_IP_PAYLOAD_TYPE_MASK	GENMASK(6, 2)
 #define	ERDES4_IP_HDR_ERR		BIT(3)
diff --git a/drivers/net/ethernet/stmicro/stmmac/descs_com.h b/drivers/net/ethernet/stmicro/stmmac/descs_com.h
index 40f7f2da9c5e..c5e7f2e5aee8 100644
--- a/drivers/net/ethernet/stmicro/stmmac/descs_com.h
+++ b/drivers/net/ethernet/stmicro/stmmac/descs_com.h
@@ -20,12 +20,18 @@
 
 /* Enhanced descriptors */
 static inline void ehn_desc_rx_set_on_ring(struct dma_desc *p, int end,
-					   int bfsize)
+					   int bfsize, bool dma64)
 {
-	if (bfsize == BUF_SIZE_16KiB)
-		p->des1 |= cpu_to_le32((BUF_SIZE_8KiB
-				<< ERDES1_BUFFER2_SIZE_SHIFT)
-			   & ERDES1_BUFFER2_SIZE_MASK);
+	if (bfsize == BUF_SIZE_16KiB) {
+		if (dma64)
+			p->des1 |= cpu_to_le32((BUF_SIZE_8KiB
+					<< ERDES1_BUFFER2_SIZE_SHIFT)
+				   & E64RDES1_BUFFER2_SIZE_MASK);
+		else
+			p->des1 |= cpu_to_le32((BUF_SIZE_8KiB
+					<< ERDES1_BUFFER2_SIZE_SHIFT)
+				   & ERDES1_BUFFER2_SIZE_MASK);
+	}
 
 	if (end)
 		p->des1 |= cpu_to_le32(ERDES1_END_RING);
@@ -39,15 +45,26 @@ static inline void enh_desc_end_tx_desc_on_ring(struct dma_desc *p, int end)
 		p->des0 &= cpu_to_le32(~ETDES0_END_RING);
 }
 
-static inline void enh_set_tx_desc_len_on_ring(struct dma_desc *p, int len)
+static inline void enh_set_tx_desc_len_on_ring(struct dma_desc *p, int len,
+					       bool dma64)
 {
 	if (unlikely(len > BUF_SIZE_4KiB)) {
-		p->des1 |= cpu_to_le32((((len - BUF_SIZE_4KiB)
-					<< ETDES1_BUFFER2_SIZE_SHIFT)
-			    & ETDES1_BUFFER2_SIZE_MASK) | (BUF_SIZE_4KiB
-			    & ETDES1_BUFFER1_SIZE_MASK));
-	} else
-		p->des1 |= cpu_to_le32((len & ETDES1_BUFFER1_SIZE_MASK));
+		if (dma64)
+			p->des1 |= cpu_to_le32((((len - BUF_SIZE_8KiB)
+						<< E64TDES1_BUFFER2_SIZE_SHIFT)
+				    & E64TDES1_BUFFER2_SIZE_MASK) | (BUF_SIZE_8KiB
+				    & E64TDES1_BUFFER1_SIZE_MASK));
+		else
+			p->des1 |= cpu_to_le32((((len - BUF_SIZE_4KiB)
+						<< ETDES1_BUFFER2_SIZE_SHIFT)
+				    & ETDES1_BUFFER2_SIZE_MASK) | (BUF_SIZE_4KiB
+				    & ETDES1_BUFFER1_SIZE_MASK));
+	} else {
+		if (dma64)
+			p->des1 |= cpu_to_le32((len & E64TDES1_BUFFER1_SIZE_MASK));
+		else
+			p->des1 |= cpu_to_le32((len & ETDES1_BUFFER1_SIZE_MASK));
+	}
 }
 
 /* Normal descriptors */
@@ -98,9 +115,13 @@ static inline void enh_desc_end_tx_desc_on_chain(struct dma_desc *p)
 	p->des0 |= cpu_to_le32(ETDES0_SECOND_ADDRESS_CHAINED);
 }
 
-static inline void enh_set_tx_desc_len_on_chain(struct dma_desc *p, int len)
+static inline void enh_set_tx_desc_len_on_chain(struct dma_desc *p, int len,
+						bool dma64)
 {
-	p->des1 |= cpu_to_le32(len & ETDES1_BUFFER1_SIZE_MASK);
+	if (dma64)
+		p->des1 |= cpu_to_le32(len & E64TDES1_BUFFER1_SIZE_MASK);
+	else
+		p->des1 |= cpu_to_le32(len & ETDES1_BUFFER1_SIZE_MASK);
 }
 
 /* Normal descriptors */
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
index efb219999a20..632c4f110d01 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
@@ -15,6 +15,7 @@
 #include <asm/io.h>
 #include "dwmac1000.h"
 #include "dwmac_dma.h"
+#include "stmmac.h"
 
 static void dwmac1000_dma_axi(struct stmmac_priv *priv, void __iomem *ioaddr,
 			      struct stmmac_axi *axi)
@@ -109,6 +110,9 @@ static void dwmac1000_dma_init(struct stmmac_priv *priv, void __iomem *ioaddr,
 
 	/* Mask interrupts by writing to CSR7 */
 	writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_INTR_ENA);
+
+	if (dma_cfg->dma64)
+		writel(0x100, ioaddr + DMA_FUNC_CONFIG);
 }
 
 void dwmac1000_dma_init_channel(struct stmmac_priv *priv, void __iomem *ioaddr,
@@ -163,9 +167,16 @@ static void dwmac1000_dma_init_rx(struct stmmac_priv *priv,
 				  struct stmmac_dma_cfg *dma_cfg,
 				  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 +
-		chan * DMA_CHAN_OFFSET);
+	if (dma_cfg->dma64) {
+		writel(lower_32_bits(dma_rx_phy), ioaddr + DMA_RCV_BASE_ADDR +
+		       chan * DMA_CHAN_OFFSET);
+		writel(upper_32_bits(dma_rx_phy), ioaddr + DMA_RCV_BASE_ADDR_HI +
+		       chan * DMA_CHAN_OFFSET);
+	} else {
+		/* RX descriptor base address list must be written into DMA CSR3 */
+		writel(lower_32_bits(dma_rx_phy), ioaddr + DMA_RCV_BASE_ADDR +
+		       chan * DMA_CHAN_OFFSET);
+	}
 }
 
 static void dwmac1000_dma_init_tx(struct stmmac_priv *priv,
@@ -173,9 +184,16 @@ static void dwmac1000_dma_init_tx(struct stmmac_priv *priv,
 				  struct stmmac_dma_cfg *dma_cfg,
 				  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 +
-		chan * DMA_CHAN_OFFSET);
+	if (dma_cfg->dma64) {
+		writel(lower_32_bits(dma_tx_phy), ioaddr + DMA_TX_BASE_ADDR +
+		       chan * DMA_CHAN_OFFSET);
+		writel(upper_32_bits(dma_tx_phy), ioaddr + DMA_TX_BASE_ADDR_HI +
+		       chan * DMA_CHAN_OFFSET);
+	} else {
+		/* TX descriptor base address list must be written into DMA CSR4 */
+		writel(lower_32_bits(dma_tx_phy), ioaddr + DMA_TX_BASE_ADDR +
+		       chan * DMA_CHAN_OFFSET);
+	}
 }
 
 static u32 dwmac1000_configure_fc(u32 csr6, int rxfifosz)
diff --git a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
index 1932a3a8e03c..ee07006c97c1 100644
--- a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
+++ b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
@@ -11,6 +11,7 @@
 #include <linux/stmmac.h>
 #include "common.h"
 #include "descs_com.h"
+#include "stmmac.h"
 
 static int enh_desc_get_tx_status(struct net_device_stats *stats,
 				  struct stmmac_extra_stats *x,
@@ -81,7 +82,10 @@ static int enh_desc_get_tx_status(struct net_device_stats *stats,
 
 static int enh_desc_get_tx_len(struct stmmac_priv *priv, struct dma_desc *p)
 {
-	return (le32_to_cpu(p->des1) & ETDES1_BUFFER1_SIZE_MASK);
+	if (priv->plat->dma_cfg->dma64)
+		return (le32_to_cpu(p->des1) & E64TDES1_BUFFER1_SIZE_MASK);
+	else
+		return (le32_to_cpu(p->des1) & ETDES1_BUFFER1_SIZE_MASK);
 }
 
 static int enh_desc_coe_rdes0(int ipc_err, int type, int payload_err)
@@ -263,12 +267,15 @@ static void enh_desc_init_rx_desc(struct stmmac_priv *priv, struct dma_desc *p,
 	p->des0 |= cpu_to_le32(RDES0_OWN);
 
 	bfsize1 = min(bfsize, BUF_SIZE_8KiB);
-	p->des1 |= cpu_to_le32(bfsize1 & ERDES1_BUFFER1_SIZE_MASK);
+	if (priv->plat->dma_cfg->dma64)
+		p->des1 |= cpu_to_le32(bfsize1 & E64RDES1_BUFFER1_SIZE_MASK);
+	else
+		p->des1 |= cpu_to_le32(bfsize1 & ERDES1_BUFFER1_SIZE_MASK);
 
 	if (mode == STMMAC_CHAIN_MODE)
 		ehn_desc_rx_set_on_chain(p);
 	else
-		ehn_desc_rx_set_on_ring(p, end, bfsize);
+		ehn_desc_rx_set_on_ring(p, end, bfsize, priv->plat->dma_cfg->dma64);
 
 	if (disable_rx_ic)
 		p->des1 |= cpu_to_le32(ERDES1_DISABLE_IC);
@@ -321,9 +328,9 @@ static void enh_desc_prepare_tx_desc(struct stmmac_priv *priv, struct dma_desc *
 	unsigned int tdes0 = le32_to_cpu(p->des0);
 
 	if (mode == STMMAC_CHAIN_MODE)
-		enh_set_tx_desc_len_on_chain(p, len);
+		enh_set_tx_desc_len_on_chain(p, len, priv->plat->dma_cfg->dma64);
 	else
-		enh_set_tx_desc_len_on_ring(p, len);
+		enh_set_tx_desc_len_on_ring(p, len, priv->plat->dma_cfg->dma64);
 
 	if (is_fs)
 		tdes0 |= ETDES0_FIRST_SEGMENT;
@@ -445,11 +452,15 @@ static void enh_desc_set_addr(struct stmmac_priv *priv, struct dma_desc *p,
 			      dma_addr_t addr)
 {
 	p->des2 = cpu_to_le32(addr);
+	if (priv->plat->dma_cfg->dma64)
+		p->des3 = cpu_to_le32(upper_32_bits(addr));
 }
 
 static void enh_desc_clear(struct stmmac_priv *priv, struct dma_desc *p)
 {
 	p->des2 = 0;
+	if (priv->plat->dma_cfg->dma64)
+		p->des3 = 0;
 }
 
 const struct stmmac_desc_ops enh_desc_ops = {
diff --git a/drivers/net/ethernet/stmicro/stmmac/ring_mode.c b/drivers/net/ethernet/stmicro/stmmac/ring_mode.c
index 49dd6ea07416..2b664a51a4f7 100644
--- a/drivers/net/ethernet/stmicro/stmmac/ring_mode.c
+++ b/drivers/net/ethernet/stmicro/stmmac/ring_mode.c
@@ -21,10 +21,14 @@ static int jumbo_frm(struct stmmac_tx_queue *tx_q, struct sk_buff *skb,
 	struct stmmac_priv *priv = tx_q->priv_data;
 	unsigned int entry = tx_q->cur_tx;
 	unsigned int bmax, len, des2;
+	unsigned int bmax2, len2;
+	struct dma_extended_desc *edesc;
 	struct dma_desc *desc;
 
-	if (priv->extend_desc)
-		desc = (struct dma_desc *)(tx_q->dma_etx + entry);
+	if (priv->extend_desc) {
+		edesc = tx_q->dma_etx + entry;
+		desc = (struct dma_desc *)edesc;
+	}
 	else
 		desc = tx_q->dma_tx + entry;
 
@@ -33,23 +37,37 @@ static int jumbo_frm(struct stmmac_tx_queue *tx_q, struct sk_buff *skb,
 	else
 		bmax = BUF_SIZE_2KiB;
 
-	len = nopaged_len - bmax;
+	if (priv->plat->dma_cfg->dma64) {
+		bmax2 = bmax * 2;
+		len2 = bmax2;
+	} else {
+		bmax2 = bmax;
+		len2 = BUF_SIZE_8KiB;
+	}
+	len = nopaged_len - bmax2;
 
-	if (nopaged_len > BUF_SIZE_8KiB) {
+	if (nopaged_len > len2) {
 
-		des2 = dma_map_single(priv->device, skb->data, bmax,
+		des2 = dma_map_single(priv->device, skb->data, bmax2,
 				      DMA_TO_DEVICE);
 		desc->des2 = cpu_to_le32(des2);
+		if (priv->plat->dma_cfg->dma64)
+			desc->des3 = cpu_to_le32(upper_32_bits(des2));
 		if (dma_mapping_error(priv->device, des2))
 			return -1;
 
 		tx_q->tx_skbuff_dma[entry].buf = des2;
-		tx_q->tx_skbuff_dma[entry].len = bmax;
+		tx_q->tx_skbuff_dma[entry].len = bmax2;
 		tx_q->tx_skbuff_dma[entry].is_jumbo = true;
 
-		desc->des3 = cpu_to_le32(des2 + BUF_SIZE_4KiB);
+		if (priv->plat->dma_cfg->dma64) {
+			edesc->des6 = cpu_to_le32(des2 + bmax);
+			edesc->des7 = cpu_to_le32(upper_32_bits(edesc->des6));
+		} else
+			desc->des3 = cpu_to_le32(des2 + BUF_SIZE_4KiB);
 		stmmac_prepare_tx_desc(priv, desc, 1, bmax, csum,
-				STMMAC_RING_MODE, 0, false, skb->len);
+				STMMAC_RING_MODE, priv->plat->dma_cfg->dma64,
+				false, skb->len);
 		tx_q->tx_skbuff[entry] = NULL;
 		entry = STMMAC_GET_ENTRY(entry, priv->dma_conf.dma_tx_size);
 
@@ -61,13 +79,19 @@ static int jumbo_frm(struct stmmac_tx_queue *tx_q, struct sk_buff *skb,
 		des2 = dma_map_single(priv->device, skb->data + bmax, len,
 				      DMA_TO_DEVICE);
 		desc->des2 = cpu_to_le32(des2);
+		if (priv->plat->dma_cfg->dma64)
+			desc->des3 = cpu_to_le32(upper_32_bits(des2));
 		if (dma_mapping_error(priv->device, des2))
 			return -1;
 		tx_q->tx_skbuff_dma[entry].buf = des2;
 		tx_q->tx_skbuff_dma[entry].len = len;
 		tx_q->tx_skbuff_dma[entry].is_jumbo = true;
 
-		desc->des3 = cpu_to_le32(des2 + BUF_SIZE_4KiB);
+		if (priv->plat->dma_cfg->dma64) {
+			edesc->des6 = cpu_to_le32(des2 + bmax);
+			edesc->des7 = cpu_to_le32(upper_32_bits(edesc->des6));
+		} else
+			desc->des3 = cpu_to_le32(des2 + BUF_SIZE_4KiB);
 		stmmac_prepare_tx_desc(priv, desc, 0, len, csum,
 				STMMAC_RING_MODE, 1, !skb_is_nonlinear(skb),
 				skb->len);
@@ -82,8 +106,8 @@ static int jumbo_frm(struct stmmac_tx_queue *tx_q, struct sk_buff *skb,
 		tx_q->tx_skbuff_dma[entry].is_jumbo = true;
 		desc->des3 = cpu_to_le32(des2 + BUF_SIZE_4KiB);
 		stmmac_prepare_tx_desc(priv, desc, 1, nopaged_len, csum,
-				STMMAC_RING_MODE, 0, !skb_is_nonlinear(skb),
-				skb->len);
+				STMMAC_RING_MODE, priv->plat->dma_cfg->dma64,
+				!skb_is_nonlinear(skb), skb->len);
 	}
 
 	tx_q->cur_tx = entry;
@@ -103,36 +127,69 @@ static unsigned int is_jumbo_frm(int len, int enh_desc)
 
 static void refill_desc3(struct stmmac_rx_queue *rx_q, struct dma_desc *p)
 {
+	struct dma_extended_desc *edesc = (struct dma_extended_desc *)p;
 	struct stmmac_priv *priv = rx_q->priv_data;
 
-	/* Fill DES3 in case of RING mode */
-	if (priv->dma_conf.dma_buf_sz == BUF_SIZE_16KiB)
-		p->des3 = cpu_to_le32(le32_to_cpu(p->des2) + BUF_SIZE_8KiB);
+	if (priv->plat->dma_cfg->dma64) {
+		if (priv->dma_conf.dma_buf_sz >= BUF_SIZE_8KiB) {
+			edesc->des6 = cpu_to_le32(le32_to_cpu(edesc->basic.des2) +
+						BUF_SIZE_8KiB);
+			edesc->des7 = cpu_to_le32(le32_to_cpu(edesc->basic.des3));
+		}
+	} else {
+		/* Fill DES3 in case of RING mode */
+		if (priv->dma_conf.dma_buf_sz == BUF_SIZE_16KiB)
+			p->des3 = cpu_to_le32(le32_to_cpu(p->des2) +
+					BUF_SIZE_8KiB);
+	}
 }
 
 /* In ring mode we need to fill the desc3 because it is used as buffer */
 static void init_desc3(struct stmmac_priv *priv, struct dma_desc *p)
 {
-	p->des3 = cpu_to_le32(le32_to_cpu(p->des2) + BUF_SIZE_8KiB);
+	struct dma_extended_desc *edesc = (struct dma_extended_desc *)p;
+
+	if (priv->plat->dma_cfg->dma64) {
+		edesc->des6 = cpu_to_le32(le32_to_cpu(edesc->basic.des2) +
+					BUF_SIZE_8KiB);
+		edesc->des7 = cpu_to_le32(le32_to_cpu(edesc->basic.des3));
+	} else
+		p->des3 = cpu_to_le32(le32_to_cpu(p->des2) +
+				BUF_SIZE_8KiB);
 }
 
 static void clean_desc3(struct stmmac_tx_queue *tx_q, struct dma_desc *p)
 {
+	struct dma_extended_desc *edesc = (struct dma_extended_desc *)p;
 	struct stmmac_priv *priv = tx_q->priv_data;
 	unsigned int entry = tx_q->dirty_tx;
 
-	/* des3 is only used for jumbo frames tx or time stamping */
-	if (unlikely(tx_q->tx_skbuff_dma[entry].is_jumbo ||
-		     (tx_q->tx_skbuff_dma[entry].last_segment &&
-		      !priv->extend_desc && priv->hwts_tx_en)))
-		p->des3 = 0;
+	if (priv->plat->dma_cfg->dma64) {
+		if (unlikely(tx_q->tx_skbuff_dma[entry].is_jumbo)) {
+			edesc->des6 = 0;
+			edesc->des7 = 0;
+		}
+	} else {
+		/* des3 is only used for jumbo frames tx or time stamping */
+		if (unlikely(tx_q->tx_skbuff_dma[entry].is_jumbo ||
+			     (tx_q->tx_skbuff_dma[entry].last_segment &&
+			      !priv->extend_desc && priv->hwts_tx_en)))
+			p->des3 = 0;
+	}
 }
 
 static int set_16kib_bfsize(struct stmmac_priv *priv, int mtu)
 {
 	int ret = 0;
-	if (unlikely(mtu > BUF_SIZE_8KiB))
-		ret = BUF_SIZE_16KiB;
+
+	if (priv->plat->dma_cfg->dma64) {
+		if (unlikely(mtu >= BUF_SIZE_8KiB))
+			ret = BUF_SIZE_16KiB;
+	} else {
+		if (unlikely(mtu > BUF_SIZE_8KiB))
+			ret = BUF_SIZE_16KiB;
+	}
+
 	return ret;
 }
 
diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
index ff539681a3a4..f9af24f760d4 100644
--- a/include/linux/stmmac.h
+++ b/include/linux/stmmac.h
@@ -98,6 +98,7 @@ struct stmmac_dma_cfg {
 	bool eame;
 	bool multi_msi_en;
 	bool dche;
+	bool dma64;
 };
 
 #define AXI_BLEN	7
-- 
2.39.3


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

* [RFC PATCH 06/10] net: stmmac: dwmac1000: Add Loongson register definitions
  2023-07-13  2:46 [RFC PATCH 00/10] net: phy/stmmac: Add Loongson platform support Feiyang Chen
                   ` (4 preceding siblings ...)
  2023-07-13  2:48 ` [RFC PATCH 05/10] net: stmmac: dwmac1000: Add 64-bit DMA support Feiyang Chen
@ 2023-07-13  2:48 ` Feiyang Chen
  2023-07-13  2:48 ` [RFC PATCH 07/10] net: stmmac: Add Loongson HWIF entry Feiyang Chen
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 38+ messages in thread
From: Feiyang Chen @ 2023-07-13  2:48 UTC (permalink / raw)
  To: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	chenhuacai
  Cc: Feiyang Chen, linux, dongbiao, loongson-kernel, netdev,
	loongarch, chris.chenfeiyang

Add definitions for Loongson platform.

Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
---
 .../net/ethernet/stmicro/stmmac/dwmac1000.h   |  4 +-
 .../ethernet/stmicro/stmmac/dwmac1000_core.c  | 43 +++++++---
 .../ethernet/stmicro/stmmac/dwmac1000_dma.c   | 10 ++-
 .../net/ethernet/stmicro/stmmac/dwmac_dma.h   |  2 +
 .../net/ethernet/stmicro/stmmac/dwmac_lib.c   | 84 +++++++++++++++++--
 5 files changed, 119 insertions(+), 24 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
index 4296ddda8aaa..f827bf8f30a9 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
@@ -76,9 +76,9 @@ enum power_event {
 #define LPI_CTRL_STATUS_TLPIEN	0x00000001	/* Transmit LPI Entry */
 
 /* GMAC HW ADDR regs */
-#define GMAC_ADDR_HIGH(reg)	((reg > 15) ? 0x00000800 + (reg - 16) * 8 : \
+#define GMAC_ADDR_HIGH(reg, x)	((reg > 15) ? 0x00000800 + (reg - 16) * 8 * (x) : \
 				 0x00000040 + (reg * 8))
-#define GMAC_ADDR_LOW(reg)	((reg > 15) ? 0x00000804 + (reg - 16) * 8 : \
+#define GMAC_ADDR_LOW(reg, x)	((reg > 15) ? 0x00000804 + (reg - 16) * 8 * (x) : \
 				 0x00000044 + (reg * 8))
 #define GMAC_MAX_PERFECT_ADDRESSES	1
 
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
index a9b42a122ed6..1063865d126e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
@@ -24,6 +24,7 @@
 static void dwmac1000_core_init(struct mac_device_info *hw,
 				struct net_device *dev)
 {
+	struct stmmac_priv *priv = netdev_priv(dev);
 	void __iomem *ioaddr = hw->pcsr;
 	u32 value = readl(ioaddr + GMAC_CONTROL);
 	int mtu = dev->mtu;
@@ -31,6 +32,9 @@ static void dwmac1000_core_init(struct mac_device_info *hw,
 	/* Configure GMAC core */
 	value |= GMAC_CORE_INIT;
 
+	if (priv->plat->dwmac_is_loongson)
+		value |= GMAC_CONTROL_ACS;
+
 	if (mtu > 1500)
 		value |= GMAC_CONTROL_2K;
 	if (mtu > 2000)
@@ -100,9 +104,10 @@ static void dwmac1000_set_umac_addr(struct stmmac_priv *priv,
 				    const unsigned char *addr,
 				    unsigned int reg_n)
 {
+	bool is_loongson = priv->plat->dwmac_is_loongson;
 	void __iomem *ioaddr = hw->pcsr;
-	stmmac_set_mac_addr(ioaddr, addr, GMAC_ADDR_HIGH(reg_n),
-			    GMAC_ADDR_LOW(reg_n));
+	stmmac_set_mac_addr(ioaddr, addr, GMAC_ADDR_HIGH(reg_n, !is_loongson),
+			    GMAC_ADDR_LOW(reg_n, !is_loongson));
 }
 
 static void dwmac1000_get_umac_addr(struct stmmac_priv *priv,
@@ -110,9 +115,10 @@ static void dwmac1000_get_umac_addr(struct stmmac_priv *priv,
 				    unsigned char *addr,
 				    unsigned int reg_n)
 {
+	bool is_loongson = priv->plat->dwmac_is_loongson;
 	void __iomem *ioaddr = hw->pcsr;
-	stmmac_get_mac_addr(ioaddr, addr, GMAC_ADDR_HIGH(reg_n),
-			    GMAC_ADDR_LOW(reg_n));
+	stmmac_get_mac_addr(ioaddr, addr, GMAC_ADDR_HIGH(reg_n, !is_loongson),
+			    GMAC_ADDR_LOW(reg_n, !is_loongson));
 }
 
 static void dwmac1000_set_mchash(void __iomem *ioaddr, u32 *mcfilterbits,
@@ -144,6 +150,7 @@ static void dwmac1000_set_filter(struct stmmac_priv *priv,
 				 struct mac_device_info *hw,
 				 struct net_device *dev)
 {
+	bool is_loongson = priv->plat->dwmac_is_loongson;
 	void __iomem *ioaddr = (void __iomem *)dev->base_addr;
 	unsigned int value = 0;
 	unsigned int perfect_addr_number = hw->unicast_filter_entries;
@@ -156,7 +163,9 @@ static void dwmac1000_set_filter(struct stmmac_priv *priv,
 	memset(mc_filter, 0, sizeof(mc_filter));
 
 	if (dev->flags & IFF_PROMISC) {
-		value = GMAC_FRAME_FILTER_PR | GMAC_FRAME_FILTER_PCF;
+		value = GMAC_FRAME_FILTER_PR;
+		if (!is_loongson)
+			value |= GMAC_FRAME_FILTER_PCF;
 	} else if (dev->flags & IFF_ALLMULTI) {
 		value = GMAC_FRAME_FILTER_PM;	/* pass all multi */
 	} else if (!netdev_mc_empty(dev) && (mcbitslog2 == 0)) {
@@ -200,14 +209,14 @@ static void dwmac1000_set_filter(struct stmmac_priv *priv,
 
 		netdev_for_each_uc_addr(ha, dev) {
 			stmmac_set_mac_addr(ioaddr, ha->addr,
-					    GMAC_ADDR_HIGH(reg),
-					    GMAC_ADDR_LOW(reg));
+					    GMAC_ADDR_HIGH(reg, !is_loongson),
+					    GMAC_ADDR_LOW(reg, !is_loongson));
 			reg++;
 		}
 
 		while (reg < perfect_addr_number) {
-			writel(0, ioaddr + GMAC_ADDR_HIGH(reg));
-			writel(0, ioaddr + GMAC_ADDR_LOW(reg));
+			writel(0, ioaddr + GMAC_ADDR_HIGH(reg, !is_loongson));
+			writel(0, ioaddr + GMAC_ADDR_LOW(reg, !is_loongson));
 			reg++;
 		}
 	}
@@ -562,8 +571,20 @@ int dwmac1000_setup(struct stmmac_priv *priv)
 {
 	dev_info(priv->device, "\tDWMAC1000\n");
 
-	priv->plat->dwmac_is_loongson = false;
-	priv->plat->dwmac_regs = &dwmac_default_dma_regs;
+	if (priv->plat->dma_cfg->dma64)
+		priv->plat->dwmac_regs = &dwmac_loongson64_dma_regs;
+	else
+		priv->plat->dwmac_regs = &dwmac_default_dma_regs;
+
+	return _dwmac1000_setup(priv);
+}
+
+int dwmac_loongson_setup(struct stmmac_priv *priv)
+{
+	dev_info(priv->device, "\tDWMAC1000(LOONGSON)\n");
+
+	priv->plat->dwmac_is_loongson = true;
+	priv->plat->dwmac_regs = &dwmac_loongson_dma_regs;
 
 	return _dwmac1000_setup(priv);
 }
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
index 632c4f110d01..7aa450d6a81a 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
@@ -329,8 +329,14 @@ static int dwmac1000_get_hw_feature(struct stmmac_priv *priv,
 	dma_cap->rx_coe_type2 = (hw_cap & DMA_HW_FEAT_RXTYP2COE) >> 18;
 	dma_cap->rxfifo_over_2048 = (hw_cap & DMA_HW_FEAT_RXFIFOSIZE) >> 19;
 	/* TX and RX number of channels */
-	dma_cap->number_rx_channel = (hw_cap & DMA_HW_FEAT_RXCHCNT) >> 20;
-	dma_cap->number_tx_channel = (hw_cap & DMA_HW_FEAT_TXCHCNT) >> 22;
+	if (priv->plat->dwmac_is_loongson &&
+	    ((hw_cap & (DMA_HW_FEAT_RXCHCNT | DMA_HW_FEAT_TXCHCNT)) >> 20) == 0) {
+		dma_cap->number_rx_channel = 8;
+		dma_cap->number_tx_channel = 8;
+	} else {
+		dma_cap->number_rx_channel = (hw_cap & DMA_HW_FEAT_RXCHCNT) >> 20;
+		dma_cap->number_tx_channel = (hw_cap & DMA_HW_FEAT_TXCHCNT) >> 22;
+	}
 	/* Alternate (enhanced) DESC mode */
 	dma_cap->enh_desc = (hw_cap & DMA_HW_FEAT_ENHDESSEL) >> 24;
 
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
index 915a4d70fd3b..3828902baa80 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
@@ -160,6 +160,8 @@
 #define NUM_DWMAC4_DMA_REGS	27
 
 extern const struct dwmac_regs dwmac_default_dma_regs;
+extern const struct dwmac_regs dwmac_loongson_dma_regs;
+extern const struct dwmac_regs dwmac_loongson64_dma_regs;
 
 void dwmac_enable_dma_transmission(struct stmmac_priv *priv,
 				   void __iomem *ioaddr, u32 chan);
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
index 99838497b183..7911eab175d9 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
@@ -20,6 +20,21 @@ static const struct dwmac_dma_addrs default_dma_addrs = {
 	.cur_rx_buf_addr = 0x00001054
 };
 
+static const struct dwmac_dma_addrs loongson_dma_addrs = {
+	.chan_offset = 0x100,
+	.rcv_base_addr = 0x0000100c,
+	.tx_base_addr = 0x00001010,
+	.cur_tx_buf_addr = 0x00001050,
+	.cur_rx_buf_addr = 0x00001054
+};
+
+static const struct dwmac_dma_addrs loongson64_dma_addrs = {
+	.rcv_base_addr = 0x00001090,
+	.tx_base_addr = 0x00001098,
+	.cur_tx_buf_addr = 0x000010b0,
+	.cur_rx_buf_addr = 0x000010b8
+};
+
 static const struct dwmac_dma_axi default_dma_axi = {
 	.wr_osr_lmt = GENMASK(23, 20),
 	.wr_osr_lmt_shift = 20,
@@ -30,11 +45,26 @@ static const struct dwmac_dma_axi default_dma_axi = {
 	.osr_max = 0xf
 };
 
+static const struct dwmac_dma_axi loongson_dma_axi = {
+	.wr_osr_lmt = BIT(20),
+	.wr_osr_lmt_shift = 20,
+	.wr_osr_lmt_mask = 0x1,
+	.rd_osr_lmt = BIT(16),
+	.rd_osr_lmt_shift = 16,
+	.rd_osr_lmt_mask = 0x1,
+	.osr_max = 0x1
+};
+
 static const struct dwmac_dma_intr_ena default_dma_intr_ena = {
 	.nie = 0x00010000,
 	.aie = 0x00008000
 };
 
+static const struct dwmac_dma_intr_ena loongson_dma_intr_ena = {
+	.nie = 0x00060000,
+	.aie = 0x00018000
+};
+
 static const struct dwmac_dma_status default_dma_status = {
 	.glpii = 0x40000000,
 	.eb_mask = 0x00380000,
@@ -47,6 +77,18 @@ static const struct dwmac_dma_status default_dma_status = {
 	.fbi = 0x00002000
 };
 
+static const struct dwmac_dma_status loongson_dma_status = {
+	.glpii = 0x10000000,
+	.eb_mask = 0x0e000000,
+	.ts_mask = 0x01c00000,
+	.ts_shift = 22,
+	.rs_mask = 0x00380000,
+	.rs_shift = 19,
+	.nis = 0x00040000 | 0x00020000,
+	.ais = 0x00010000 | 0x00008000,
+	.fbi = 0x00002000 | 0x00001000
+};
+
 const struct dwmac_regs dwmac_default_dma_regs = {
 	.addrs = &default_dma_addrs,
 	.axi = &default_dma_axi,
@@ -54,17 +96,37 @@ const struct dwmac_regs dwmac_default_dma_regs = {
 	.status = &default_dma_status
 };
 
+const struct dwmac_regs dwmac_loongson_dma_regs = {
+	.addrs = &loongson_dma_addrs,
+	.axi = &loongson_dma_axi,
+	.intr_ena = &loongson_dma_intr_ena,
+	.status = &loongson_dma_status
+};
+
+const struct dwmac_regs dwmac_loongson64_dma_regs = {
+	.addrs = &loongson64_dma_addrs,
+	.axi = &loongson_dma_axi,
+	.intr_ena = &default_dma_intr_ena,
+	.status = &default_dma_status
+};
+
 int dwmac_dma_reset(void __iomem *ioaddr)
 {
+	int err;
+	int cnt = 5;
 	u32 value = readl(ioaddr + DMA_BUS_MODE);
 
 	/* DMA SW reset */
-	value |= DMA_BUS_MODE_SFT_RESET;
-	writel(value, ioaddr + DMA_BUS_MODE);
+	do {
+		value |= DMA_BUS_MODE_SFT_RESET;
+		writel(value, ioaddr + DMA_BUS_MODE);
+
+		err = readl_poll_timeout(ioaddr + DMA_BUS_MODE, value,
+					 !(value & DMA_BUS_MODE_SFT_RESET),
+					 10000, 200000);
+	} while (cnt-- && err);
 
-	return readl_poll_timeout(ioaddr + DMA_BUS_MODE, value,
-				 !(value & DMA_BUS_MODE_SFT_RESET),
-				 10000, 200000);
+	return err;
 }
 
 /* CSR1 enables the transmit DMA to check for new descriptor */
@@ -267,12 +329,16 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
 			x->rx_early_irq++;
 	}
 	/* Optional hardware blocks, interrupts should be disabled */
-	if (unlikely(intr_status &
-		     (DMA_STATUS_GPI | DMA_STATUS_GMI | DMA_STATUS_GLI)))
+	if (!priv->plat->dwmac_is_loongson &&
+	    unlikely(intr_status & (DMA_STATUS_GPI | DMA_STATUS_GMI | DMA_STATUS_GLI)))
 		pr_warn("%s: unexpected status %08x\n", __func__, intr_status);
 
-	/* Clear the interrupt by writing a logic 1 to the CSR5[15-0] */
-	writel((intr_status & 0x1ffff), ioaddr + DMA_STATUS);
+	if (priv->plat->dwmac_is_loongson)
+		writel((intr_status & 0x7ffff), ioaddr + DMA_STATUS);
+	else {
+		/* Clear the interrupt by writing a logic 1 to the CSR5[15-0] */
+		writel((intr_status & 0x1ffff), ioaddr + DMA_STATUS);
+	}
 
 	return ret;
 }
-- 
2.39.3


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

* [RFC PATCH 07/10] net: stmmac: Add Loongson HWIF entry
  2023-07-13  2:46 [RFC PATCH 00/10] net: phy/stmmac: Add Loongson platform support Feiyang Chen
                   ` (5 preceding siblings ...)
  2023-07-13  2:48 ` [RFC PATCH 06/10] net: stmmac: dwmac1000: Add Loongson register definitions Feiyang Chen
@ 2023-07-13  2:48 ` Feiyang Chen
  2023-07-13  2:48 ` [RFC PATCH 08/10] net: stmmac: dwmac-loongson: Add LS7A support Feiyang Chen
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 38+ messages in thread
From: Feiyang Chen @ 2023-07-13  2:48 UTC (permalink / raw)
  To: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	chenhuacai
  Cc: Feiyang Chen, linux, dongbiao, loongson-kernel, netdev,
	loongarch, chris.chenfeiyang

Add a new entry to HWIF table for Loongson.

Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
---
 drivers/net/ethernet/stmicro/stmmac/common.h  |  3 ++
 .../ethernet/stmicro/stmmac/dwmac1000_dma.c   |  6 +++
 drivers/net/ethernet/stmicro/stmmac/hwif.c    | 48 ++++++++++++++++++-
 .../net/ethernet/stmicro/stmmac/stmmac_main.c | 25 ++++++----
 include/linux/stmmac.h                        |  1 +
 5 files changed, 73 insertions(+), 10 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index 4ad692c4116c..45c49c7a9ccb 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -29,11 +29,13 @@
 /* Synopsys Core versions */
 #define	DWMAC_CORE_3_40		0x34
 #define	DWMAC_CORE_3_50		0x35
+#define	DWMAC_CORE_3_70		0x37
 #define	DWMAC_CORE_4_00		0x40
 #define DWMAC_CORE_4_10		0x41
 #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 DWXLGMAC_CORE_2_00	0x20
 
@@ -546,6 +548,7 @@ int dwmac1000_setup(struct stmmac_priv *priv);
 int dwmac4_setup(struct stmmac_priv *priv);
 int dwxgmac2_setup(struct stmmac_priv *priv);
 int dwxlgmac2_setup(struct stmmac_priv *priv);
+int dwmac_loongson_setup(struct stmmac_priv *priv);
 
 void stmmac_set_mac_addr(void __iomem *ioaddr, const u8 addr[6],
 			 unsigned int high, unsigned int low);
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
index 7aa450d6a81a..5da5f111d7e0 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
@@ -172,6 +172,12 @@ static void dwmac1000_dma_init_rx(struct stmmac_priv *priv,
 		       chan * DMA_CHAN_OFFSET);
 		writel(upper_32_bits(dma_rx_phy), ioaddr + DMA_RCV_BASE_ADDR_HI +
 		       chan * DMA_CHAN_OFFSET);
+		if (priv->plat->has_lgmac) {
+			writel(upper_32_bits(dma_rx_phy),
+			       ioaddr + DMA_RCV_BASE_ADDR_SHADOW1);
+			writel(upper_32_bits(dma_rx_phy),
+			       ioaddr + DMA_RCV_BASE_ADDR_SHADOW2);
+		}
 	} else {
 		/* RX descriptor base address list must be written into DMA CSR3 */
 		writel(lower_32_bits(dma_rx_phy), ioaddr + DMA_RCV_BASE_ADDR +
diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.c b/drivers/net/ethernet/stmicro/stmmac/hwif.c
index b8ba8f2d8041..b376ac4f80d5 100644
--- a/drivers/net/ethernet/stmicro/stmmac/hwif.c
+++ b/drivers/net/ethernet/stmicro/stmmac/hwif.c
@@ -58,7 +58,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->plat->has_lgmac) {
 			dev_info(priv->device, "Enabled extended descriptors\n");
 			priv->extend_desc = 1;
 		} else {
@@ -104,6 +105,7 @@ static const struct stmmac_hwif_entry {
 	bool gmac;
 	bool gmac4;
 	bool xgmac;
+	bool lgmac;
 	u32 min_id;
 	u32 dev_id;
 	const struct stmmac_regs_off regs;
@@ -122,6 +124,7 @@ static const struct stmmac_hwif_entry {
 		.gmac = false,
 		.gmac4 = false,
 		.xgmac = false,
+		.lgmac = false,
 		.min_id = 0,
 		.regs = {
 			.ptp_off = PTP_GMAC3_X_OFFSET,
@@ -140,6 +143,7 @@ static const struct stmmac_hwif_entry {
 		.gmac = true,
 		.gmac4 = false,
 		.xgmac = false,
+		.lgmac = false,
 		.min_id = 0,
 		.regs = {
 			.ptp_off = PTP_GMAC3_X_OFFSET,
@@ -158,6 +162,7 @@ static const struct stmmac_hwif_entry {
 		.gmac = false,
 		.gmac4 = true,
 		.xgmac = false,
+		.lgmac = false,
 		.min_id = 0,
 		.regs = {
 			.ptp_off = PTP_GMAC4_OFFSET,
@@ -176,6 +181,7 @@ static const struct stmmac_hwif_entry {
 		.gmac = false,
 		.gmac4 = true,
 		.xgmac = false,
+		.lgmac = false,
 		.min_id = DWMAC_CORE_4_00,
 		.regs = {
 			.ptp_off = PTP_GMAC4_OFFSET,
@@ -194,6 +200,7 @@ static const struct stmmac_hwif_entry {
 		.gmac = false,
 		.gmac4 = true,
 		.xgmac = false,
+		.lgmac = false,
 		.min_id = DWMAC_CORE_4_10,
 		.regs = {
 			.ptp_off = PTP_GMAC4_OFFSET,
@@ -212,6 +219,7 @@ static const struct stmmac_hwif_entry {
 		.gmac = false,
 		.gmac4 = true,
 		.xgmac = false,
+		.lgmac = false,
 		.min_id = DWMAC_CORE_5_10,
 		.regs = {
 			.ptp_off = PTP_GMAC4_OFFSET,
@@ -230,6 +238,7 @@ static const struct stmmac_hwif_entry {
 		.gmac = false,
 		.gmac4 = false,
 		.xgmac = true,
+		.lgmac = false,
 		.min_id = DWXGMAC_CORE_2_10,
 		.dev_id = DWXGMAC_ID,
 		.regs = {
@@ -249,6 +258,7 @@ static const struct stmmac_hwif_entry {
 		.gmac = false,
 		.gmac4 = false,
 		.xgmac = true,
+		.lgmac = false,
 		.min_id = DWXLGMAC_CORE_2_00,
 		.dev_id = DWXLGMAC_ID,
 		.regs = {
@@ -264,6 +274,42 @@ static const struct stmmac_hwif_entry {
 		.mmc = &dwxgmac_mmc_ops,
 		.setup = dwxlgmac2_setup,
 		.quirks = stmmac_dwxlgmac_quirks,
+	}, {
+		.gmac = true,
+		.gmac4 = false,
+		.xgmac = false,
+		.lgmac = true,
+		.min_id = DWLGMAC_CORE_1_00,
+		.regs = {
+			.ptp_off = PTP_GMAC3_X_OFFSET,
+			.mmc_off = MMC_GMAC3_X_OFFSET,
+		},
+		.desc = NULL,
+		.dma = &dwmac1000_dma_ops,
+		.mac = &dwmac1000_ops,
+		.hwtimestamp = &stmmac_ptp,
+		.mode = NULL,
+		.tc = NULL,
+		.setup = dwmac_loongson_setup,
+		.quirks = stmmac_dwmac1_quirks,
+	}, {
+		.gmac = true,
+		.gmac4 = false,
+		.xgmac = false,
+		.lgmac = true,
+		.min_id = DWMAC_CORE_3_50,
+		.regs = {
+			.ptp_off = PTP_GMAC3_X_OFFSET,
+			.mmc_off = MMC_GMAC3_X_OFFSET,
+		},
+		.desc = NULL,
+		.dma = &dwmac1000_dma_ops,
+		.mac = &dwmac1000_ops,
+		.hwtimestamp = &stmmac_ptp,
+		.mode = NULL,
+		.tc = NULL,
+		.setup = dwmac1000_setup,
+		.quirks = stmmac_dwmac1_quirks,
 	},
 };
 
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 2e95568b1e4a..59e9b61315bb 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -3494,17 +3494,21 @@ static int stmmac_request_irq_multi_msi(struct net_device *dev)
 {
 	struct stmmac_priv *priv = netdev_priv(dev);
 	enum request_irq_err irq_err;
+	unsigned long flags = 0;
 	cpumask_t cpu_mask;
 	int irq_idx = 0;
 	char *int_name;
 	int ret;
 	int i;
 
+	if (priv->plat->has_lgmac)
+		flags |= IRQF_TRIGGER_RISING;
+
 	/* For common interrupt */
 	int_name = priv->int_name_mac;
 	sprintf(int_name, "%s:%s", dev->name, "mac");
 	ret = request_irq(dev->irq, stmmac_mac_interrupt,
-			  0, int_name, dev);
+			  flags, int_name, dev);
 	if (unlikely(ret < 0)) {
 		netdev_err(priv->dev,
 			   "%s: alloc mac MSI %d (error: %d)\n",
@@ -3521,7 +3525,7 @@ static int stmmac_request_irq_multi_msi(struct net_device *dev)
 		sprintf(int_name, "%s:%s", dev->name, "wol");
 		ret = request_irq(priv->wol_irq,
 				  stmmac_mac_interrupt,
-				  0, int_name, dev);
+				  flags, int_name, dev);
 		if (unlikely(ret < 0)) {
 			netdev_err(priv->dev,
 				   "%s: alloc wol MSI %d (error: %d)\n",
@@ -3539,7 +3543,7 @@ static int stmmac_request_irq_multi_msi(struct net_device *dev)
 		sprintf(int_name, "%s:%s", dev->name, "lpi");
 		ret = request_irq(priv->lpi_irq,
 				  stmmac_mac_interrupt,
-				  0, int_name, dev);
+				  flags, int_name, dev);
 		if (unlikely(ret < 0)) {
 			netdev_err(priv->dev,
 				   "%s: alloc lpi MSI %d (error: %d)\n",
@@ -3557,7 +3561,7 @@ static int stmmac_request_irq_multi_msi(struct net_device *dev)
 		sprintf(int_name, "%s:%s", dev->name, "safety-ce");
 		ret = request_irq(priv->sfty_ce_irq,
 				  stmmac_safety_interrupt,
-				  0, int_name, dev);
+				  flags, int_name, dev);
 		if (unlikely(ret < 0)) {
 			netdev_err(priv->dev,
 				   "%s: alloc sfty ce MSI %d (error: %d)\n",
@@ -3575,7 +3579,7 @@ static int stmmac_request_irq_multi_msi(struct net_device *dev)
 		sprintf(int_name, "%s:%s", dev->name, "safety-ue");
 		ret = request_irq(priv->sfty_ue_irq,
 				  stmmac_safety_interrupt,
-				  0, int_name, dev);
+				  flags, int_name, dev);
 		if (unlikely(ret < 0)) {
 			netdev_err(priv->dev,
 				   "%s: alloc sfty ue MSI %d (error: %d)\n",
@@ -3596,7 +3600,7 @@ static int stmmac_request_irq_multi_msi(struct net_device *dev)
 		sprintf(int_name, "%s:%s-%d", dev->name, "rx", i);
 		ret = request_irq(priv->rx_irq[i],
 				  stmmac_msi_intr_rx,
-				  0, int_name, &priv->dma_conf.rx_queue[i]);
+				  flags, int_name, &priv->dma_conf.rx_queue[i]);
 		if (unlikely(ret < 0)) {
 			netdev_err(priv->dev,
 				   "%s: alloc rx-%d  MSI %d (error: %d)\n",
@@ -3621,7 +3625,7 @@ static int stmmac_request_irq_multi_msi(struct net_device *dev)
 		sprintf(int_name, "%s:%s-%d", dev->name, "tx", i);
 		ret = request_irq(priv->tx_irq[i],
 				  stmmac_msi_intr_tx,
-				  0, int_name, &priv->dma_conf.tx_queue[i]);
+				  flags, int_name, &priv->dma_conf.tx_queue[i]);
 		if (unlikely(ret < 0)) {
 			netdev_err(priv->dev,
 				   "%s: alloc tx-%d  MSI %d (error: %d)\n",
@@ -6045,8 +6049,10 @@ static u16 stmmac_select_queue(struct net_device *dev, struct sk_buff *skb,
 			       struct net_device *sb_dev)
 {
 	int gso = skb_shinfo(skb)->gso_type;
+	struct stmmac_priv *priv = netdev_priv(dev);
 
-	if (gso & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6 | SKB_GSO_UDP_L4)) {
+	if ((gso & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6 | SKB_GSO_UDP_L4)) ||
+	    priv->plat->has_lgmac) {
 		/*
 		 * There is no way to determine the number of TSO/USO
 		 * capable Queues. Let's use always the Queue 0
@@ -6924,7 +6930,8 @@ static int stmmac_hw_init(struct stmmac_priv *priv)
 	 * riwt_off field from the platform.
 	 */
 	if (((priv->synopsys_id >= DWMAC_CORE_3_50) ||
-	    (priv->plat->has_xgmac)) && (!priv->plat->riwt_off)) {
+	    (priv->plat->has_xgmac) || (priv->plat->has_lgmac)) &&
+	    (!priv->plat->riwt_off)) {
 		priv->use_riwt = 1;
 		dev_info(priv->device,
 			 "Enable RX Mitigation via HW Watchdog Timer\n");
diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
index f9af24f760d4..8ee1d8c7827f 100644
--- a/include/linux/stmmac.h
+++ b/include/linux/stmmac.h
@@ -341,6 +341,7 @@ struct plat_stmmacenet_data {
 	bool sph_disable;
 	bool serdes_up_after_phy_linkup;
 	const struct dwmac4_addrs *dwmac4_addrs;
+	int has_lgmac;
 	bool dwmac_is_loongson;
 	const struct dwmac_regs *dwmac_regs;
 };
-- 
2.39.3


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

* [RFC PATCH 08/10] net: stmmac: dwmac-loongson: Add LS7A support
  2023-07-13  2:46 [RFC PATCH 00/10] net: phy/stmmac: Add Loongson platform support Feiyang Chen
                   ` (6 preceding siblings ...)
  2023-07-13  2:48 ` [RFC PATCH 07/10] net: stmmac: Add Loongson HWIF entry Feiyang Chen
@ 2023-07-13  2:48 ` Feiyang Chen
  2023-07-13  2:48 ` [RFC PATCH 09/10] net: stmmac: dwmac-loongson: Add 64-bit DMA and multi-vector support Feiyang Chen
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 38+ messages in thread
From: Feiyang Chen @ 2023-07-13  2:48 UTC (permalink / raw)
  To: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	chenhuacai
  Cc: Feiyang Chen, linux, dongbiao, loongson-kernel, netdev,
	loongarch, chris.chenfeiyang

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

Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
---
 .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 135 +++++++++++-------
 1 file changed, 82 insertions(+), 53 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
index a25c187d3185..dc0916f2e9b8 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
@@ -9,14 +9,22 @@
 #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 common_default_data(struct pci_dev *pdev,
+				struct plat_stmmacenet_data *plat)
 {
+	plat->bus_id = (pci_domain_nr(pdev->bus) << 16) | PCI_DEVID(pdev->bus->number, pdev->devfn);
+	plat->interface = PHY_INTERFACE_MODE_GMII;
+
 	plat->clk_csr = 2;	/* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */
 	plat->has_gmac = 1;
 	plat->force_sf_dma_mode = 1;
 
 	/* Set default value for multicast hash bins */
-	plat->multicast_filter_bins = HASH_TABLE_SIZE;
+	plat->multicast_filter_bins = 256;
 
 	/* Set default value for unicast filter entries */
 	plat->unicast_filter_entries = 1;
@@ -35,31 +43,43 @@ static int loongson_default_data(struct plat_stmmacenet_data *plat)
 	/* Disable RX queues routing by default */
 	plat->rx_queues_cfg[0].pkt_route = 0x0;
 
-	/* Default to phy auto-detection */
-	plat->phy_addr = -1;
-
 	plat->dma_cfg->pbl = 32;
 	plat->dma_cfg->pblx8 = true;
 
-	plat->multicast_filter_bins = 256;
+	plat->clk_ref_rate = 125000000;
+	plat->clk_ptp_rate = 125000000;
+
+	plat->has_lgmac = 1;
+}
+
+static int loongson_gmac_data(struct pci_dev *pdev,
+			      struct plat_stmmacenet_data *plat)
+{
+	common_default_data(pdev, plat);
+
+	plat->mdio_bus_data->phy_mask = 0;
+
+	plat->phy_addr = -1;
+	plat->phy_interface = PHY_INTERFACE_MODE_RGMII_ID;
+
 	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);
-
-	if (!np) {
-		pr_info("dwmac_loongson_pci: No OF node\n");
-		return -ENODEV;
-	}
-
-	if (!of_device_is_compatible(np, "loongson, pci-gmac")) {
+	if (np && !of_device_is_compatible(np, "loongson, pci-gmac")) {
 		pr_info("dwmac_loongson_pci: Incompatible OF node\n");
 		return -ENODEV;
 	}
@@ -68,17 +88,14 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
 	if (!plat)
 		return -ENOMEM;
 
+	plat->mdio_bus_data = devm_kzalloc(&pdev->dev,
+				   sizeof(*plat->mdio_bus_data), GFP_KERNEL);
+	if (!plat->mdio_bus_data)
+		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 = devm_kzalloc(&pdev->dev,
-						   sizeof(*plat->mdio_bus_data),
-						   GFP_KERNEL);
-		if (!plat->mdio_bus_data) {
-			ret = -ENOMEM;
-			goto err_put_node;
-		}
 		plat->mdio_bus_data->needs_reset = true;
 	}
 
@@ -105,45 +122,55 @@ 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);
 
-	phy_mode = device_get_phy_mode(&pdev->dev);
-	if (phy_mode < 0) {
-		dev_err(&pdev->dev, "phy_mode not found\n");
-		ret = phy_mode;
+	info = (struct stmmac_pci_info *)id->driver_data;
+	ret = info->setup(pdev, plat);
+	if (ret)
 		goto err_disable_device;
-	}
 
-	plat->phy_interface = phy_mode;
-	plat->interface = PHY_INTERFACE_MODE_GMII;
+	if (np) {
+		bus_id = of_alias_get_id(np, "ethernet");
+		if (bus_id >= 0)
+			plat->bus_id = bus_id;
 
-	pci_set_master(pdev);
+		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;
+	}
 
-	loongson_default_data(plat);
 	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.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.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;
+		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);
@@ -219,8 +246,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.39.3


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

* [RFC PATCH 09/10] net: stmmac: dwmac-loongson: Add 64-bit DMA and multi-vector support
  2023-07-13  2:46 [RFC PATCH 00/10] net: phy/stmmac: Add Loongson platform support Feiyang Chen
                   ` (7 preceding siblings ...)
  2023-07-13  2:48 ` [RFC PATCH 08/10] net: stmmac: dwmac-loongson: Add LS7A support Feiyang Chen
@ 2023-07-13  2:48 ` Feiyang Chen
  2023-07-13  2:49 ` [RFC PATCH 10/10] net: stmmac: dwmac-loongson: Add GNET support Feiyang Chen
  2023-07-13  4:09 ` [RFC PATCH 00/10] net: phy/stmmac: Add Loongson platform support Andrew Lunn
  10 siblings, 0 replies; 38+ messages in thread
From: Feiyang Chen @ 2023-07-13  2:48 UTC (permalink / raw)
  To: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	chenhuacai
  Cc: Feiyang Chen, linux, dongbiao, loongson-kernel, netdev,
	loongarch, chris.chenfeiyang

Set 64-Bit DMA for specific versions. Request allocation for multi-
vector interrupts for DWLGMAC_CORE_1_00. If it fails, fallback to
request allocation for single interrupts.

Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
---
 .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 53 ++++++++++++++++++-
 1 file changed, 51 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
index dc0916f2e9b8..3732f90a79c7 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
@@ -72,11 +72,12 @@ static struct stmmac_pci_info loongson_gmac_pci_info = {
 static int loongson_dwmac_probe(struct pci_dev *pdev,
 				const struct pci_device_id *id)
 {
-	int ret, i, bus_id, phy_mode;
+	int ret, i, bus_id, phy_mode, ch_cnt, vecs;
 	struct plat_stmmacenet_data *plat;
 	struct stmmac_pci_info *info;
 	struct stmmac_resources res;
 	struct device_node *np;
+	u32 version;
 
 	np = dev_of_node(&pdev->dev);
 	if (np && !of_device_is_compatible(np, "loongson, pci-gmac")) {
@@ -173,12 +174,59 @@ static int loongson_dwmac_probe(struct pci_dev *pdev,
 		res.wol_irq = pdev->irq;
 	}
 
+	version = readl(res.addr + GMAC_VERSION);
+	switch (version & 0xff) {
+	case DWLGMAC_CORE_1_00:
+		ch_cnt = 8;
+		plat->multi_msi_en = 1;
+		break;
+
+	case DWMAC_CORE_3_50:
+	case DWMAC_CORE_3_70:
+	default:
+		plat->multi_msi_en = 0;
+		if (version & 0x00008000) {
+			plat->host_dma_width = 64;
+			plat->dma_cfg->dma64 = true;
+		}
+		break;
+	}
+
+	if (plat->multi_msi_en) {
+		plat->rx_queues_to_use = ch_cnt;
+		plat->tx_queues_to_use = ch_cnt;
+
+		pci_disable_msi(pdev);
+
+		res.irq = pci_irq_vector(pdev, 0);
+		res.wol_irq = res.irq;
+		vecs = roundup_pow_of_two(ch_cnt * 2 + 1);
+		if (pci_alloc_irq_vectors(pdev, vecs, vecs, PCI_IRQ_MSI) < 0) {
+			dev_info(&pdev->dev,
+				 "MSI enable failed, Fallback to line interrupt\n");
+			plat->multi_msi_en = 0;
+		} else {
+			/*
+			 * INT NAME | MAC | CH7 rx | CH7 tx | ... | CH0 rx | CH0 tx |
+			 * --------- ----- -------- --------  ...  -------- --------
+			 * IRQ NUM  |  0  |   1    |   2    | ... |   15   |   16   |
+			 */
+			for (i = 0; i < ch_cnt; i++) {
+				res.rx_irq[ch_cnt - 1 - i] = pci_irq_vector(pdev, 1 + i * 2);
+				res.tx_irq[ch_cnt - 1 - i] = pci_irq_vector(pdev, 2 + i * 2);
+			}
+		}
+	}
+
 	ret = stmmac_dvr_probe(&pdev->dev, plat, &res);
 	if (ret)
-		goto err_disable_msi;
+		goto err_free_irq_vectors;
 
 	return ret;
 
+err_free_irq_vectors:
+	if (plat->multi_msi_en)
+		pci_free_irq_vectors(pdev);
 err_disable_msi:
 	pci_disable_msi(pdev);
 err_disable_device:
@@ -204,6 +252,7 @@ static void loongson_dwmac_remove(struct pci_dev *pdev)
 		break;
 	}
 
+	pci_free_irq_vectors(pdev);
 	pci_disable_msi(pdev);
 	pci_disable_device(pdev);
 }
-- 
2.39.3


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

* [RFC PATCH 10/10] net: stmmac: dwmac-loongson: Add GNET support
  2023-07-13  2:46 [RFC PATCH 00/10] net: phy/stmmac: Add Loongson platform support Feiyang Chen
                   ` (8 preceding siblings ...)
  2023-07-13  2:48 ` [RFC PATCH 09/10] net: stmmac: dwmac-loongson: Add 64-bit DMA and multi-vector support Feiyang Chen
@ 2023-07-13  2:49 ` Feiyang Chen
  2023-07-13  4:07   ` Andrew Lunn
  2023-07-13  8:06   ` Russell King (Oracle)
  2023-07-13  4:09 ` [RFC PATCH 00/10] net: phy/stmmac: Add Loongson platform support Andrew Lunn
  10 siblings, 2 replies; 38+ messages in thread
From: Feiyang Chen @ 2023-07-13  2:49 UTC (permalink / raw)
  To: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	chenhuacai
  Cc: Feiyang Chen, linux, dongbiao, loongson-kernel, netdev,
	loongarch, chris.chenfeiyang

Add GNET support. Use the fix_mac_speed() callback to workaround
issues with the Loongson PHY.

Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
---
 drivers/net/ethernet/stmicro/stmmac/Kconfig   |  1 +
 .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 34 +++++++++++++++++++
 2 files changed, 35 insertions(+)

diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
index 5f5a997f21f3..8c25d5616941 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
@@ -279,6 +279,7 @@ config DWMAC_LOONGSON
 	default MACH_LOONGSON64
 	depends on STMMAC_ETH && PCI
 	depends on COMMON_CLK
+	select LOONGSON_PHY
 	help
 	  This selects the LOONGSON PCI bus support for the stmmac driver,
 	  Support for ethernet controller on Loongson-2K1000 SoC and LS7A1000 bridge.
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
index 3732f90a79c7..c840d9d1d72a 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
@@ -69,6 +69,38 @@ static struct stmmac_pci_info loongson_gmac_pci_info = {
 	.setup = loongson_gmac_data,
 };
 
+static void loongson_gnet_fix_speed(void *priv, unsigned int speed)
+{
+	struct net_device *ndev = (struct net_device *)(*(unsigned long *)priv);
+	struct stmmac_priv *ptr = netdev_priv(ndev);
+
+	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)
+{
+	common_default_data(pdev, plat);
+
+	plat->mdio_bus_data->phy_mask = 0xfffffffb;
+
+	plat->phy_addr = 2;
+	plat->phy_interface = PHY_INTERFACE_MODE_GMII;
+
+	plat->fix_mac_speed = loongson_gnet_fix_speed;
+
+	/* Get netdev pointer address */
+	plat->bsp_priv = &(pdev->dev.driver_data);
+
+	return 0;
+}
+
+static struct stmmac_pci_info loongson_gnet_pci_info = {
+	.setup = loongson_gnet_data,
+};
+
 static int loongson_dwmac_probe(struct pci_dev *pdev,
 				const struct pci_device_id *id)
 {
@@ -296,9 +328,11 @@ static SIMPLE_DEV_PM_OPS(loongson_dwmac_pm_ops, loongson_dwmac_suspend,
 			 loongson_dwmac_resume);
 
 #define PCI_DEVICE_ID_LOONGSON_GMAC	0x7a03
+#define PCI_DEVICE_ID_LOONGSON_GNET	0x7a13
 
 static const struct pci_device_id loongson_dwmac_id_table[] = {
 	{ PCI_DEVICE_DATA(LOONGSON, GMAC, &loongson_gmac_pci_info) },
+	{ PCI_DEVICE_DATA(LOONGSON, GNET, &loongson_gnet_pci_info) },
 	{}
 };
 MODULE_DEVICE_TABLE(pci, loongson_dwmac_id_table);
-- 
2.39.3


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

* Re: [RFC PATCH 01/10] net: phy: Add driver for Loongson PHY
  2023-07-13  2:46 ` [RFC PATCH 01/10] net: phy: Add driver for Loongson PHY Feiyang Chen
@ 2023-07-13  4:00   ` Andrew Lunn
  2023-07-14  2:15     ` Feiyang Chen
  2023-07-13  7:53   ` Russell King (Oracle)
  1 sibling, 1 reply; 38+ messages in thread
From: Andrew Lunn @ 2023-07-13  4:00 UTC (permalink / raw)
  To: Feiyang Chen
  Cc: hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	chenhuacai, linux, dongbiao, loongson-kernel, netdev, loongarch,
	chris.chenfeiyang

On Thu, Jul 13, 2023 at 10:46:53AM +0800, Feiyang Chen wrote:
> Add support for the Loongson PHY.
> 
> Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
> ---
>  drivers/net/phy/Kconfig        |  5 +++
>  drivers/net/phy/Makefile       |  1 +
>  drivers/net/phy/loongson-phy.c | 69 ++++++++++++++++++++++++++++++++++

Please drop -phy from the filename. No other phy driver does this.

>  drivers/net/phy/phy_device.c   | 16 ++++++++
>  include/linux/phy.h            |  2 +
>  5 files changed, 93 insertions(+)
>  create mode 100644 drivers/net/phy/loongson-phy.c
> 
> diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
> index 93b8efc79227..4f8ea32cbc68 100644
> --- a/drivers/net/phy/Kconfig
> +++ b/drivers/net/phy/Kconfig
> @@ -202,6 +202,11 @@ config INTEL_XWAY_PHY
>  	  PEF 7061, PEF 7071 and PEF 7072 or integrated into the Intel
>  	  SoCs xRX200, xRX300, xRX330, xRX350 and xRX550.
>  
> +config LOONGSON_PHY
> +	tristate "Loongson PHY driver"
> +	help
> +	  Supports the Loongson PHY.
> +
>  config LSI_ET1011C_PHY
>  	tristate "LSI ET1011C PHY"
>  	help
> diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
> index f289ab16a1da..f775373e12b7 100644
> --- a/drivers/net/phy/Makefile
> +++ b/drivers/net/phy/Makefile
> @@ -62,6 +62,7 @@ obj-$(CONFIG_DP83TD510_PHY)	+= dp83td510.o
>  obj-$(CONFIG_FIXED_PHY)		+= fixed_phy.o
>  obj-$(CONFIG_ICPLUS_PHY)	+= icplus.o
>  obj-$(CONFIG_INTEL_XWAY_PHY)	+= intel-xway.o
> +obj-$(CONFIG_LOONGSON_PHY)	+= loongson-phy.o
>  obj-$(CONFIG_LSI_ET1011C_PHY)	+= et1011c.o
>  obj-$(CONFIG_LXT_PHY)		+= lxt.o
>  obj-$(CONFIG_MARVELL_10G_PHY)	+= marvell10g.o
> diff --git a/drivers/net/phy/loongson-phy.c b/drivers/net/phy/loongson-phy.c
> new file mode 100644
> index 000000000000..d4aefa2110f8
> --- /dev/null
> +++ b/drivers/net/phy/loongson-phy.c
> @@ -0,0 +1,69 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * LS7A PHY driver
> + *
> + * Copyright (C) 2020-2023 Loongson Technology Corporation Limited
> + *
> + * Author: Zhang Baoqi <zhangbaoqi@loongson.cn>
> + */
> +
> +#include <linux/mii.h>
> +#include <linux/module.h>
> +#include <linux/netdevice.h>
> +#include <linux/pci.h>
> +#include <linux/phy.h>
> +
> +#define PHY_ID_LS7A2000		0x00061ce0

What is Loongson OUI?

> +#define GNET_REV_LS7A2000	0x00
> +
> +static int ls7a2000_config_aneg(struct phy_device *phydev)
> +{
> +	if (phydev->speed == SPEED_1000)
> +		phydev->autoneg = AUTONEG_ENABLE;

Please explain.

> +
> +	if (linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT,
> +	    phydev->advertising) ||
> +	    linkmode_test_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
> +	    phydev->advertising) ||
> +	    linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
> +	    phydev->advertising))
> +	    return genphy_config_aneg(phydev);
> +
> +	netdev_info(phydev->attached_dev, "Parameter Setting Error\n");

This also needs explaining. How can it be asked to do something it
does not support?

> +	return -1;

Always use error codes. In this case EINVAL.

> +}
> +
> +int ls7a2000_match_phy_device(struct phy_device *phydev)
> +{
> +	struct net_device *ndev;
> +	struct pci_dev *pdev;
> +
> +	if ((phydev->phy_id & 0xfffffff0) != PHY_ID_LS7A2000)
> +		return 0;
> +
> +	ndev = phydev->mdio.bus->priv;
> +	pdev = to_pci_dev(ndev->dev.parent);
> +
> +	return pdev->revision == GNET_REV_LS7A2000;

That is very unusual. Why is the PHY ID not sufficient?

> +}
> +
> +static struct phy_driver loongson_phy_driver[] = {
> +	{
> +		PHY_ID_MATCH_MODEL(PHY_ID_LS7A2000),
> +		.name			= "LS7A2000 PHY",
> +		.features		= PHY_LOONGSON_FEATURES,

So what are the capabilities of this PHY? You seem to have some very
odd hacks here, and no explanation of why they are needed. If you do
something which no other device does, you need to explain it.

Does the PHY itself only support full duplex? No half duplex? Does the
PHY support autoneg? Does it support fixed settings? What does
genphy_read_abilities() return for this PHY?

	Andrew

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

* Re: [RFC PATCH 02/10] net: stmmac: Pass stmmac_priv and chan in some callbacks
  2023-07-13  2:46 ` [RFC PATCH 02/10] net: stmmac: Pass stmmac_priv and chan in some callbacks Feiyang Chen
@ 2023-07-13  4:02   ` Andrew Lunn
  2023-07-14  2:16     ` Feiyang Chen
  0 siblings, 1 reply; 38+ messages in thread
From: Andrew Lunn @ 2023-07-13  4:02 UTC (permalink / raw)
  To: Feiyang Chen
  Cc: hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	chenhuacai, linux, dongbiao, loongson-kernel, netdev, loongarch,
	chris.chenfeiyang

On Thu, Jul 13, 2023 at 10:46:54AM +0800, Feiyang Chen wrote:
> Like commit 1d84b487bc2d90 ("net: stmmac: Pass stmmac_priv in some
> callbacks"), passing stmmac_priv and chan to more callbacks and
> adjust the callbacks accordingly.

Commit messages don't say what a patch does, you can see that from
reading the patch. The commit message should explain why it is doing
something. 

	Andrew

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

* Re: [RFC PATCH 10/10] net: stmmac: dwmac-loongson: Add GNET support
  2023-07-13  2:49 ` [RFC PATCH 10/10] net: stmmac: dwmac-loongson: Add GNET support Feiyang Chen
@ 2023-07-13  4:07   ` Andrew Lunn
  2023-07-14  2:24     ` Feiyang Chen
  2023-07-13  8:06   ` Russell King (Oracle)
  1 sibling, 1 reply; 38+ messages in thread
From: Andrew Lunn @ 2023-07-13  4:07 UTC (permalink / raw)
  To: Feiyang Chen
  Cc: hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	chenhuacai, linux, dongbiao, loongson-kernel, netdev, loongarch,
	chris.chenfeiyang

On Thu, Jul 13, 2023 at 10:49:38AM +0800, Feiyang Chen wrote:
> Add GNET support. Use the fix_mac_speed() callback to workaround
> issues with the Loongson PHY.

What are the issues?

> +static void loongson_gnet_fix_speed(void *priv, unsigned int speed)
> +{
> +	struct net_device *ndev = (struct net_device *)(*(unsigned long *)priv);
> +	struct stmmac_priv *ptr = netdev_priv(ndev);
> +
> +	if (speed == SPEED_1000)
> +		if (readl(ptr->ioaddr + MAC_CTRL_REG) & (1 << 15) /* PS */)
> +			phy_restart_aneg(ndev->phydev);

This needs a comment at least, but if you explain what is actually
FUBAR in this PHY, we might be able to tell you a better way to work
around its problems.

> +static int loongson_gnet_data(struct pci_dev *pdev,
> +			      struct plat_stmmacenet_data *plat)
> +{
> +	common_default_data(pdev, plat);
> +
> +	plat->mdio_bus_data->phy_mask = 0xfffffffb;
> +
> +	plat->phy_addr = 2;
> +	plat->phy_interface = PHY_INTERFACE_MODE_GMII;

You would normally get this from DT. Is the PHY integrated? Is it
really using GMII, or would PHY_INTERFACE_MODE_INTERNAL be better?

       Andrew

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

* Re: [RFC PATCH 00/10] net: phy/stmmac: Add Loongson platform support
  2023-07-13  2:46 [RFC PATCH 00/10] net: phy/stmmac: Add Loongson platform support Feiyang Chen
                   ` (9 preceding siblings ...)
  2023-07-13  2:49 ` [RFC PATCH 10/10] net: stmmac: dwmac-loongson: Add GNET support Feiyang Chen
@ 2023-07-13  4:09 ` Andrew Lunn
  2023-07-14  2:16   ` Feiyang Chen
  10 siblings, 1 reply; 38+ messages in thread
From: Andrew Lunn @ 2023-07-13  4:09 UTC (permalink / raw)
  To: Feiyang Chen
  Cc: hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	chenhuacai, linux, dongbiao, loongson-kernel, netdev, loongarch,
	chris.chenfeiyang

On Thu, Jul 13, 2023 at 10:46:52AM +0800, Feiyang Chen wrote:
> Add driver for Loongson PHY. Extend stmmac functions and macros for
> Loongson DWMAC. Add LS7A support for dwmac_loongson.

Why is this RFC? What do you actually want comment on?

    Andrew

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

* Re: [RFC PATCH 01/10] net: phy: Add driver for Loongson PHY
  2023-07-13  2:46 ` [RFC PATCH 01/10] net: phy: Add driver for Loongson PHY Feiyang Chen
  2023-07-13  4:00   ` Andrew Lunn
@ 2023-07-13  7:53   ` Russell King (Oracle)
  2023-07-14  2:41     ` Feiyang Chen
  1 sibling, 1 reply; 38+ messages in thread
From: Russell King (Oracle) @ 2023-07-13  7:53 UTC (permalink / raw)
  To: Feiyang Chen
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	chenhuacai, dongbiao, loongson-kernel, netdev, loongarch,
	chris.chenfeiyang

On Thu, Jul 13, 2023 at 10:46:53AM +0800, Feiyang Chen wrote:
> +#define PHY_ID_LS7A2000		0x00061ce0
> +#define GNET_REV_LS7A2000	0x00
> +
> +static int ls7a2000_config_aneg(struct phy_device *phydev)
> +{
> +	if (phydev->speed == SPEED_1000)
> +		phydev->autoneg = AUTONEG_ENABLE;
> +
> +	if (linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT,
> +	    phydev->advertising) ||
> +	    linkmode_test_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
> +	    phydev->advertising) ||
> +	    linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
> +	    phydev->advertising))
> +	    return genphy_config_aneg(phydev);

While it's fine to use four spaces within the if () expression, this
"return" should be indented with a tab.

> +
> +	netdev_info(phydev->attached_dev, "Parameter Setting Error\n");

Does this give the opportunity for userspace to spam the kernel log?
E.g. by a daemon repeatedly trying to set link parameters? Should it
be rate limited?

> +	return -1;

Sigh, not this laziness disease yet again. -1 is -EPERM. Return a
real errno code.

> +int ls7a2000_match_phy_device(struct phy_device *phydev)
> +{
> +	struct net_device *ndev;
> +	struct pci_dev *pdev;
> +
> +	if ((phydev->phy_id & 0xfffffff0) != PHY_ID_LS7A2000)
> +		return 0;

	if (!phy_id_compare(phydev->phy_id, PHY_ID_LS7A2000, 0xfffffff0))
		return 0;

> +
> +	ndev = phydev->mdio.bus->priv;

This doesn't look safe to me - you're assuming that if the PHY ID
above matches, that the MDIO bus' private data is something you know
which is far from guaranteed.

The mdio bus has a parent device - that would be a safer route to
check what the parent device is, provided the mdio bus is created so
that it's a child of the parent PCI device.

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

* Re: [RFC PATCH 10/10] net: stmmac: dwmac-loongson: Add GNET support
  2023-07-13  2:49 ` [RFC PATCH 10/10] net: stmmac: dwmac-loongson: Add GNET support Feiyang Chen
  2023-07-13  4:07   ` Andrew Lunn
@ 2023-07-13  8:06   ` Russell King (Oracle)
  2023-07-14  2:27     ` Feiyang Chen
  1 sibling, 1 reply; 38+ messages in thread
From: Russell King (Oracle) @ 2023-07-13  8:06 UTC (permalink / raw)
  To: Feiyang Chen
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	chenhuacai, dongbiao, loongson-kernel, netdev, loongarch,
	chris.chenfeiyang

On Thu, Jul 13, 2023 at 10:49:38AM +0800, Feiyang Chen wrote:
> Add GNET support. Use the fix_mac_speed() callback to workaround
> issues with the Loongson PHY.

It would be good to document what those issue(s) are, and if they are a
PHY issue, why they need to be resolved in a MAC driver rather than
using the PHY driver's link_change_notify().

Thanks.

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

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

* Re: [RFC PATCH 01/10] net: phy: Add driver for Loongson PHY
  2023-07-13  4:00   ` Andrew Lunn
@ 2023-07-14  2:15     ` Feiyang Chen
  2023-07-14  4:19       ` Andrew Lunn
  0 siblings, 1 reply; 38+ messages in thread
From: Feiyang Chen @ 2023-07-14  2:15 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Feiyang Chen, hkallweit1, peppe.cavallaro, alexandre.torgue,
	joabreu, chenhuacai, linux, dongbiao, loongson-kernel, netdev,
	loongarch

On Thu, Jul 13, 2023 at 12:00 PM Andrew Lunn <andrew@lunn.ch> wrote:
>
> On Thu, Jul 13, 2023 at 10:46:53AM +0800, Feiyang Chen wrote:
> > Add support for the Loongson PHY.
> >
> > Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
> > ---
> >  drivers/net/phy/Kconfig        |  5 +++
> >  drivers/net/phy/Makefile       |  1 +
> >  drivers/net/phy/loongson-phy.c | 69 ++++++++++++++++++++++++++++++++++
>
> Please drop -phy from the filename. No other phy driver does this.
>

Hi, Andrew,

OK.

> >  drivers/net/phy/phy_device.c   | 16 ++++++++
> >  include/linux/phy.h            |  2 +
> >  5 files changed, 93 insertions(+)
> >  create mode 100644 drivers/net/phy/loongson-phy.c
> >
> > diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
> > index 93b8efc79227..4f8ea32cbc68 100644
> > --- a/drivers/net/phy/Kconfig
> > +++ b/drivers/net/phy/Kconfig
> > @@ -202,6 +202,11 @@ config INTEL_XWAY_PHY
> >         PEF 7061, PEF 7071 and PEF 7072 or integrated into the Intel
> >         SoCs xRX200, xRX300, xRX330, xRX350 and xRX550.
> >
> > +config LOONGSON_PHY
> > +     tristate "Loongson PHY driver"
> > +     help
> > +       Supports the Loongson PHY.
> > +
> >  config LSI_ET1011C_PHY
> >       tristate "LSI ET1011C PHY"
> >       help
> > diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
> > index f289ab16a1da..f775373e12b7 100644
> > --- a/drivers/net/phy/Makefile
> > +++ b/drivers/net/phy/Makefile
> > @@ -62,6 +62,7 @@ obj-$(CONFIG_DP83TD510_PHY) += dp83td510.o
> >  obj-$(CONFIG_FIXED_PHY)              += fixed_phy.o
> >  obj-$(CONFIG_ICPLUS_PHY)     += icplus.o
> >  obj-$(CONFIG_INTEL_XWAY_PHY) += intel-xway.o
> > +obj-$(CONFIG_LOONGSON_PHY)   += loongson-phy.o
> >  obj-$(CONFIG_LSI_ET1011C_PHY)        += et1011c.o
> >  obj-$(CONFIG_LXT_PHY)                += lxt.o
> >  obj-$(CONFIG_MARVELL_10G_PHY)        += marvell10g.o
> > diff --git a/drivers/net/phy/loongson-phy.c b/drivers/net/phy/loongson-phy.c
> > new file mode 100644
> > index 000000000000..d4aefa2110f8
> > --- /dev/null
> > +++ b/drivers/net/phy/loongson-phy.c
> > @@ -0,0 +1,69 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * LS7A PHY driver
> > + *
> > + * Copyright (C) 2020-2023 Loongson Technology Corporation Limited
> > + *
> > + * Author: Zhang Baoqi <zhangbaoqi@loongson.cn>
> > + */
> > +
> > +#include <linux/mii.h>
> > +#include <linux/module.h>
> > +#include <linux/netdevice.h>
> > +#include <linux/pci.h>
> > +#include <linux/phy.h>
> > +
> > +#define PHY_ID_LS7A2000              0x00061ce0
>
> What is Loongson OUI?
>

Currently, we do not have an OUI for Loongson, but we are in the
process of applying for one.

> > +#define GNET_REV_LS7A2000    0x00
> > +
> > +static int ls7a2000_config_aneg(struct phy_device *phydev)
> > +{
> > +     if (phydev->speed == SPEED_1000)
> > +             phydev->autoneg = AUTONEG_ENABLE;
>
> Please explain.
>

The PHY itself supports half-duplex, but there are issues with the
controller used in the 7A2000 chip. Moreover, the controller only
supports auto-negotiation for gigabit speeds.

> > +
> > +     if (linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT,
> > +         phydev->advertising) ||
> > +         linkmode_test_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
> > +         phydev->advertising) ||
> > +         linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
> > +         phydev->advertising))
> > +         return genphy_config_aneg(phydev);
> > +
> > +     netdev_info(phydev->attached_dev, "Parameter Setting Error\n");
>
> This also needs explaining. How can it be asked to do something it
> does not support?
>

Perhaps I missed something, but I think that if someone uses ethtool,
they can request it to perform actions or configurations that the
tool does not support.

> > +     return -1;
>
> Always use error codes. In this case EINVAL.
>

OK.

> > +}
> > +
> > +int ls7a2000_match_phy_device(struct phy_device *phydev)
> > +{
> > +     struct net_device *ndev;
> > +     struct pci_dev *pdev;
> > +
> > +     if ((phydev->phy_id & 0xfffffff0) != PHY_ID_LS7A2000)
> > +             return 0;
> > +
> > +     ndev = phydev->mdio.bus->priv;
> > +     pdev = to_pci_dev(ndev->dev.parent);
> > +
> > +     return pdev->revision == GNET_REV_LS7A2000;
>
> That is very unusual. Why is the PHY ID not sufficient?
>

To work around the controller's issues, we enable the usage of this
driver specifically for a certain version of the 7A2000 chip.

> > +}
> > +
> > +static struct phy_driver loongson_phy_driver[] = {
> > +     {
> > +             PHY_ID_MATCH_MODEL(PHY_ID_LS7A2000),
> > +             .name                   = "LS7A2000 PHY",
> > +             .features               = PHY_LOONGSON_FEATURES,
>
> So what are the capabilities of this PHY? You seem to have some very
> odd hacks here, and no explanation of why they are needed. If you do
> something which no other device does, you need to explain it.
>
> Does the PHY itself only support full duplex? No half duplex? Does the
> PHY support autoneg? Does it support fixed settings? What does
> genphy_read_abilities() return for this PHY?
>

As mentioned earlier, this driver is specifically designed for the PHY
on the problematic 7A2000 chip. Therefore, we assume that this PHY only
supports full- duplex mode and performs auto-negotiation exclusively for
gigabit speeds.

Thanks,
Feiyang

>         Andrew

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

* Re: [RFC PATCH 00/10] net: phy/stmmac: Add Loongson platform support
  2023-07-13  4:09 ` [RFC PATCH 00/10] net: phy/stmmac: Add Loongson platform support Andrew Lunn
@ 2023-07-14  2:16   ` Feiyang Chen
  2023-07-14  8:39     ` Russell King (Oracle)
  0 siblings, 1 reply; 38+ messages in thread
From: Feiyang Chen @ 2023-07-14  2:16 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Feiyang Chen, hkallweit1, peppe.cavallaro, alexandre.torgue,
	joabreu, chenhuacai, linux, dongbiao, loongson-kernel, netdev,
	loongarch

On Thu, Jul 13, 2023 at 12:09 PM Andrew Lunn <andrew@lunn.ch> wrote:
>
> On Thu, Jul 13, 2023 at 10:46:52AM +0800, Feiyang Chen wrote:
> > Add driver for Loongson PHY. Extend stmmac functions and macros for
> > Loongson DWMAC. Add LS7A support for dwmac_loongson.
>
> Why is this RFC? What do you actually want comment on?
>

Hi, Andrew,

I marked this patch series as an RFC because I believe it involves
significant changes to the dwmac1000 driver. I want comments on the
design and any alternative suggestions.

Thanks,
Feiyang

>     Andrew

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

* Re: [RFC PATCH 02/10] net: stmmac: Pass stmmac_priv and chan in some callbacks
  2023-07-13  4:02   ` Andrew Lunn
@ 2023-07-14  2:16     ` Feiyang Chen
  0 siblings, 0 replies; 38+ messages in thread
From: Feiyang Chen @ 2023-07-14  2:16 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Feiyang Chen, hkallweit1, peppe.cavallaro, alexandre.torgue,
	joabreu, chenhuacai, linux, dongbiao, loongson-kernel, netdev,
	loongarch

On Thu, Jul 13, 2023 at 12:02 PM Andrew Lunn <andrew@lunn.ch> wrote:
>
> On Thu, Jul 13, 2023 at 10:46:54AM +0800, Feiyang Chen wrote:
> > Like commit 1d84b487bc2d90 ("net: stmmac: Pass stmmac_priv in some
> > callbacks"), passing stmmac_priv and chan to more callbacks and
> > adjust the callbacks accordingly.
>
> Commit messages don't say what a patch does, you can see that from
> reading the patch. The commit message should explain why it is doing
> something.
>

Hi, Andrew,

Alright, I will make improvements in the next version.

Thanks,
Feiyang

>         Andrew

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

* Re: [RFC PATCH 10/10] net: stmmac: dwmac-loongson: Add GNET support
  2023-07-13  4:07   ` Andrew Lunn
@ 2023-07-14  2:24     ` Feiyang Chen
  2023-07-14  4:26       ` Andrew Lunn
  2023-07-14  8:45       ` Russell King (Oracle)
  0 siblings, 2 replies; 38+ messages in thread
From: Feiyang Chen @ 2023-07-14  2:24 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Feiyang Chen, hkallweit1, peppe.cavallaro, alexandre.torgue,
	joabreu, chenhuacai, linux, dongbiao, loongson-kernel, netdev,
	loongarch

On Thu, Jul 13, 2023 at 12:07 PM Andrew Lunn <andrew@lunn.ch> wrote:
>
> On Thu, Jul 13, 2023 at 10:49:38AM +0800, Feiyang Chen wrote:
> > Add GNET support. Use the fix_mac_speed() callback to workaround
> > issues with the Loongson PHY.
>
> What are the issues?
>

Hi, Andrew,

There is an issue with the synchronization between the network card
and the PHY. In the case of gigabit operation, if the PHY's speed
changes, the network card's speed remains unaffected. Hence, it is
necessary to initiate a re-negotiation process with the PHY to align
the link speeds properly.

> > +static void loongson_gnet_fix_speed(void *priv, unsigned int speed)
> > +{
> > +     struct net_device *ndev = (struct net_device *)(*(unsigned long *)priv);
> > +     struct stmmac_priv *ptr = netdev_priv(ndev);
> > +
> > +     if (speed == SPEED_1000)
> > +             if (readl(ptr->ioaddr + MAC_CTRL_REG) & (1 << 15) /* PS */)
> > +                     phy_restart_aneg(ndev->phydev);
>
> This needs a comment at least, but if you explain what is actually
> FUBAR in this PHY, we might be able to tell you a better way to work
> around its problems.
>
> > +static int loongson_gnet_data(struct pci_dev *pdev,
> > +                           struct plat_stmmacenet_data *plat)
> > +{
> > +     common_default_data(pdev, plat);
> > +
> > +     plat->mdio_bus_data->phy_mask = 0xfffffffb;
> > +
> > +     plat->phy_addr = 2;
> > +     plat->phy_interface = PHY_INTERFACE_MODE_GMII;
>
> You would normally get this from DT. Is the PHY integrated? Is it
> really using GMII, or would PHY_INTERFACE_MODE_INTERNAL be better?
>

Yes, the PHY is integrated. I'll try to use PHY_INTERFACE_MODE_INTERNAL
later.

Thanks,
Feiyang

>        Andrew

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

* Re: [RFC PATCH 10/10] net: stmmac: dwmac-loongson: Add GNET support
  2023-07-13  8:06   ` Russell King (Oracle)
@ 2023-07-14  2:27     ` Feiyang Chen
  2023-07-14  4:22       ` Andrew Lunn
  0 siblings, 1 reply; 38+ messages in thread
From: Feiyang Chen @ 2023-07-14  2:27 UTC (permalink / raw)
  To: Russell King (Oracle)
  Cc: Feiyang Chen, andrew, hkallweit1, peppe.cavallaro,
	alexandre.torgue, joabreu, chenhuacai, dongbiao, loongson-kernel,
	netdev, loongarch

On Thu, Jul 13, 2023 at 4:06 PM Russell King (Oracle)
<linux@armlinux.org.uk> wrote:
>
> On Thu, Jul 13, 2023 at 10:49:38AM +0800, Feiyang Chen wrote:
> > Add GNET support. Use the fix_mac_speed() callback to workaround
> > issues with the Loongson PHY.
>
> It would be good to document what those issue(s) are, and if they are a
> PHY issue, why they need to be resolved in a MAC driver rather than
> using the PHY driver's link_change_notify().
>

Hi, Russell,

There is an issue with the synchronization between the network card
and the PHY. I believe that I am unable to access certain bits of the
network card's registers within the PHY driver.

Thanks,
Feiyang

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

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

* Re: [RFC PATCH 01/10] net: phy: Add driver for Loongson PHY
  2023-07-13  7:53   ` Russell King (Oracle)
@ 2023-07-14  2:41     ` Feiyang Chen
  0 siblings, 0 replies; 38+ messages in thread
From: Feiyang Chen @ 2023-07-14  2:41 UTC (permalink / raw)
  To: Russell King (Oracle)
  Cc: Feiyang Chen, andrew, hkallweit1, peppe.cavallaro,
	alexandre.torgue, joabreu, chenhuacai, dongbiao, loongson-kernel,
	netdev, loongarch

On Thu, Jul 13, 2023 at 3:53 PM Russell King (Oracle)
<linux@armlinux.org.uk> wrote:
>
> On Thu, Jul 13, 2023 at 10:46:53AM +0800, Feiyang Chen wrote:
> > +#define PHY_ID_LS7A2000              0x00061ce0
> > +#define GNET_REV_LS7A2000    0x00
> > +
> > +static int ls7a2000_config_aneg(struct phy_device *phydev)
> > +{
> > +     if (phydev->speed == SPEED_1000)
> > +             phydev->autoneg = AUTONEG_ENABLE;
> > +
> > +     if (linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT,
> > +         phydev->advertising) ||
> > +         linkmode_test_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
> > +         phydev->advertising) ||
> > +         linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
> > +         phydev->advertising))
> > +         return genphy_config_aneg(phydev);
>
> While it's fine to use four spaces within the if () expression, this
> "return" should be indented with a tab.
>

Hi, Russell,

Sorry for the typo. I will correct it in the next version.

> > +
> > +     netdev_info(phydev->attached_dev, "Parameter Setting Error\n");
>
> Does this give the opportunity for userspace to spam the kernel log?
> E.g. by a daemon repeatedly trying to set link parameters? Should it
> be rate limited?
>
> > +     return -1;
>
> Sigh, not this laziness disease yet again. -1 is -EPERM. Return a
> real errno code.
>

OK.

> > +int ls7a2000_match_phy_device(struct phy_device *phydev)
> > +{
> > +     struct net_device *ndev;
> > +     struct pci_dev *pdev;
> > +
> > +     if ((phydev->phy_id & 0xfffffff0) != PHY_ID_LS7A2000)
> > +             return 0;
>
>         if (!phy_id_compare(phydev->phy_id, PHY_ID_LS7A2000, 0xfffffff0))
>                 return 0;
>

OK.

> > +
> > +     ndev = phydev->mdio.bus->priv;
>
> This doesn't look safe to me - you're assuming that if the PHY ID
> above matches, that the MDIO bus' private data is something you know
> which is far from guaranteed.
>
> The mdio bus has a parent device - that would be a safer route to
> check what the parent device is, provided the mdio bus is created so
> that it's a child of the parent PCI device.
>

OK. I’ll get right on that.

Thanks,
Feiyang



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

* Re: [RFC PATCH 01/10] net: phy: Add driver for Loongson PHY
  2023-07-14  2:15     ` Feiyang Chen
@ 2023-07-14  4:19       ` Andrew Lunn
  2023-07-17  2:43         ` Feiyang Chen
  0 siblings, 1 reply; 38+ messages in thread
From: Andrew Lunn @ 2023-07-14  4:19 UTC (permalink / raw)
  To: Feiyang Chen
  Cc: Feiyang Chen, hkallweit1, peppe.cavallaro, alexandre.torgue,
	joabreu, chenhuacai, linux, dongbiao, loongson-kernel, netdev,
	loongarch

> > > +#include <linux/mii.h>
> > > +#include <linux/module.h>
> > > +#include <linux/netdevice.h>
> > > +#include <linux/pci.h>
> > > +#include <linux/phy.h>
> > > +
> > > +#define PHY_ID_LS7A2000              0x00061ce0
> >
> > What is Loongson OUI?
> >
> 
> Currently, we do not have an OUI for Loongson, but we are in the
> process of applying for one.

Is the value 0x00061ce0 baked into the silicon? Or can it be changed
once you have an OUI?

> > > +#define GNET_REV_LS7A2000    0x00
> > > +
> > > +static int ls7a2000_config_aneg(struct phy_device *phydev)
> > > +{
> > > +     if (phydev->speed == SPEED_1000)
> > > +             phydev->autoneg = AUTONEG_ENABLE;
> >
> > Please explain.
> >
> 
> The PHY itself supports half-duplex, but there are issues with the
> controller used in the 7A2000 chip. Moreover, the controller only
> supports auto-negotiation for gigabit speeds.

So you can force 10/100/1000, but auto neg only succeeds for 1G?

Are the LP autoneg values available for genphy_read_lpa() to read? If
the LP values are available, maybe the PHY driver can resolve the
autoneg for 10 an 100.

> > > +     if (linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT,
> > > +         phydev->advertising) ||
> > > +         linkmode_test_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
> > > +         phydev->advertising) ||
> > > +         linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
> > > +         phydev->advertising))
> > > +         return genphy_config_aneg(phydev);
> > > +
> > > +     netdev_info(phydev->attached_dev, "Parameter Setting Error\n");
> >
> > This also needs explaining. How can it be asked to do something it
> > does not support?
> >
> 
> Perhaps I missed something, but I think that if someone uses ethtool,
> they can request it to perform actions or configurations that the
> tool does not support.

No. The PHY should indicate what it can do, via the .get_abilities()
etc. The MAC can also remove some of those link modes if it is more
limited than the PHY. phylib will then not allow ksetting_set() to
enable things which are not supported. So this should not happen.  It
would actually be a bad design, since it would force every driver to
do such checks, rather than implement it once in the core.

> > > +int ls7a2000_match_phy_device(struct phy_device *phydev)
> > > +{
> > > +     struct net_device *ndev;
> > > +     struct pci_dev *pdev;
> > > +
> > > +     if ((phydev->phy_id & 0xfffffff0) != PHY_ID_LS7A2000)
> > > +             return 0;
> > > +
> > > +     ndev = phydev->mdio.bus->priv;
> > > +     pdev = to_pci_dev(ndev->dev.parent);
> > > +
> > > +     return pdev->revision == GNET_REV_LS7A2000;
> >
> > That is very unusual. Why is the PHY ID not sufficient?
> >
> 
> To work around the controller's issues, we enable the usage of this
> driver specifically for a certain version of the 7A2000 chip.
> 
> > > +}
> > > +
> > > +static struct phy_driver loongson_phy_driver[] = {
> > > +     {
> > > +             PHY_ID_MATCH_MODEL(PHY_ID_LS7A2000),
> > > +             .name                   = "LS7A2000 PHY",
> > > +             .features               = PHY_LOONGSON_FEATURES,
> >
> > So what are the capabilities of this PHY? You seem to have some very
> > odd hacks here, and no explanation of why they are needed. If you do
> > something which no other device does, you need to explain it.
> >
> > Does the PHY itself only support full duplex? No half duplex? Does the
> > PHY support autoneg? Does it support fixed settings? What does
> > genphy_read_abilities() return for this PHY?
> >
> 
> As mentioned earlier, this driver is specifically designed for the PHY
> on the problematic 7A2000 chip. Therefore, we assume that this PHY only
> supports full- duplex mode and performs auto-negotiation exclusively for
> gigabit speeds.

So what does genphy_read_abilities() return?

Nobody else going to use PHY_LOONGSON_FEATURES, so i would prefer not
to add it to the core. If your PHY is designed correctly,
genphy_read_abilities() should determine what the PHY can do from its
registers. If the registers are wrong, it is better to add a
.get_features function.

	Andrew

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

* Re: [RFC PATCH 10/10] net: stmmac: dwmac-loongson: Add GNET support
  2023-07-14  2:27     ` Feiyang Chen
@ 2023-07-14  4:22       ` Andrew Lunn
  0 siblings, 0 replies; 38+ messages in thread
From: Andrew Lunn @ 2023-07-14  4:22 UTC (permalink / raw)
  To: Feiyang Chen
  Cc: Russell King (Oracle),
	Feiyang Chen, hkallweit1, peppe.cavallaro, alexandre.torgue,
	joabreu, chenhuacai, dongbiao, loongson-kernel, netdev,
	loongarch

> Hi, Russell,
> 
> There is an issue with the synchronization between the network card
> and the PHY.

Details. We need the details in order to tell you the best workaround
for your broken hardware.

I believe that I am unable to access certain bits of the
> network card's registers within the PHY driver.

The PHY driver and the MAC driver should never access each others
registers.

	Andrew

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

* Re: [RFC PATCH 10/10] net: stmmac: dwmac-loongson: Add GNET support
  2023-07-14  2:24     ` Feiyang Chen
@ 2023-07-14  4:26       ` Andrew Lunn
  2023-07-14  8:52         ` Russell King (Oracle)
  2023-07-14  8:45       ` Russell King (Oracle)
  1 sibling, 1 reply; 38+ messages in thread
From: Andrew Lunn @ 2023-07-14  4:26 UTC (permalink / raw)
  To: Feiyang Chen
  Cc: Feiyang Chen, hkallweit1, peppe.cavallaro, alexandre.torgue,
	joabreu, chenhuacai, linux, dongbiao, loongson-kernel, netdev,
	loongarch

On Fri, Jul 14, 2023 at 10:24:37AM +0800, Feiyang Chen wrote:
> On Thu, Jul 13, 2023 at 12:07 PM Andrew Lunn <andrew@lunn.ch> wrote:
> >
> > On Thu, Jul 13, 2023 at 10:49:38AM +0800, Feiyang Chen wrote:
> > > Add GNET support. Use the fix_mac_speed() callback to workaround
> > > issues with the Loongson PHY.
> >
> > What are the issues?
> >
> 
> Hi, Andrew,
> 
> There is an issue with the synchronization between the network card
> and the PHY. In the case of gigabit operation, if the PHY's speed
> changes, the network card's speed remains unaffected. Hence, it is
> necessary to initiate a re-negotiation process with the PHY to align
> the link speeds properly.

When the line side speed changes, the PHY will first report link down
via the adjust_link callback in the MAC driver. Once the PHY has
determined the new speed, the adjust_link callback will be called
again with the new speed and pause parameters.

So what is actually going wrong?

   Andrew

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

* Re: [RFC PATCH 00/10] net: phy/stmmac: Add Loongson platform support
  2023-07-14  2:16   ` Feiyang Chen
@ 2023-07-14  8:39     ` Russell King (Oracle)
  2023-07-16 14:59       ` Andrew Lunn
  0 siblings, 1 reply; 38+ messages in thread
From: Russell King (Oracle) @ 2023-07-14  8:39 UTC (permalink / raw)
  To: Feiyang Chen
  Cc: Andrew Lunn, Feiyang Chen, hkallweit1, peppe.cavallaro,
	alexandre.torgue, joabreu, chenhuacai, dongbiao, loongson-kernel,
	netdev, loongarch

On Fri, Jul 14, 2023 at 10:16:07AM +0800, Feiyang Chen wrote:
> On Thu, Jul 13, 2023 at 12:09 PM Andrew Lunn <andrew@lunn.ch> wrote:
> >
> > On Thu, Jul 13, 2023 at 10:46:52AM +0800, Feiyang Chen wrote:
> > > Add driver for Loongson PHY. Extend stmmac functions and macros for
> > > Loongson DWMAC. Add LS7A support for dwmac_loongson.
> >
> > Why is this RFC? What do you actually want comment on?
> >
> 
> Hi, Andrew,
> 
> I marked this patch series as an RFC because I believe it involves
> significant changes to the dwmac1000 driver. I want comments on the
> design and any alternative suggestions.

That is admirable, but in practice, I've found that posting RFCs is
a waste of effort and time - basically, it seems people ignore
patches posted as RFC.

This turns the whole thing when posting patches into basically what
I'd summarise as "reviewer blackmail" - post the patches non-RFC
even when you want only comments, and reviewers _have_ to comment on
the patches if there's something they don't like to prevent them
being merged.

It's sad that it comes to that, but that is the reality of how things
appear to 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] 38+ messages in thread

* Re: [RFC PATCH 10/10] net: stmmac: dwmac-loongson: Add GNET support
  2023-07-14  2:24     ` Feiyang Chen
  2023-07-14  4:26       ` Andrew Lunn
@ 2023-07-14  8:45       ` Russell King (Oracle)
  2023-07-17  7:54         ` Feiyang Chen
  1 sibling, 1 reply; 38+ messages in thread
From: Russell King (Oracle) @ 2023-07-14  8:45 UTC (permalink / raw)
  To: Feiyang Chen
  Cc: Andrew Lunn, Feiyang Chen, hkallweit1, peppe.cavallaro,
	alexandre.torgue, joabreu, chenhuacai, dongbiao, loongson-kernel,
	netdev, loongarch

On Fri, Jul 14, 2023 at 10:24:37AM +0800, Feiyang Chen wrote:
> On Thu, Jul 13, 2023 at 12:07 PM Andrew Lunn <andrew@lunn.ch> wrote:
> >
> > On Thu, Jul 13, 2023 at 10:49:38AM +0800, Feiyang Chen wrote:
> > > Add GNET support. Use the fix_mac_speed() callback to workaround
> > > issues with the Loongson PHY.
> >
> > What are the issues?
> >
> 
> Hi, Andrew,
> 
> There is an issue with the synchronization between the network card
> and the PHY. In the case of gigabit operation, if the PHY's speed
> changes, the network card's speed remains unaffected. Hence, it is
> necessary to initiate a re-negotiation process with the PHY to align
> the link speeds properly.

Please could you explain a bit more what happens when "the PHY's speed
changes". Are you suggesting that:

You have a connection where the media side has negotiated 1G speed.
The gigabit partner is disconnected, so the link goes down, and is then
replaced by a partner only capable of 100M. The link comes back up at
100M, but the network card continues trying to operate at 1G?

Thanks.

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

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

* Re: [RFC PATCH 10/10] net: stmmac: dwmac-loongson: Add GNET support
  2023-07-14  4:26       ` Andrew Lunn
@ 2023-07-14  8:52         ` Russell King (Oracle)
  0 siblings, 0 replies; 38+ messages in thread
From: Russell King (Oracle) @ 2023-07-14  8:52 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Feiyang Chen, Feiyang Chen, hkallweit1, peppe.cavallaro,
	alexandre.torgue, joabreu, chenhuacai, dongbiao, loongson-kernel,
	netdev, loongarch

On Fri, Jul 14, 2023 at 06:26:14AM +0200, Andrew Lunn wrote:
> On Fri, Jul 14, 2023 at 10:24:37AM +0800, Feiyang Chen wrote:
> > On Thu, Jul 13, 2023 at 12:07 PM Andrew Lunn <andrew@lunn.ch> wrote:
> > >
> > > On Thu, Jul 13, 2023 at 10:49:38AM +0800, Feiyang Chen wrote:
> > > > Add GNET support. Use the fix_mac_speed() callback to workaround
> > > > issues with the Loongson PHY.
> > >
> > > What are the issues?
> > >
> > 
> > Hi, Andrew,
> > 
> > There is an issue with the synchronization between the network card
> > and the PHY. In the case of gigabit operation, if the PHY's speed
> > changes, the network card's speed remains unaffected. Hence, it is
> > necessary to initiate a re-negotiation process with the PHY to align
> > the link speeds properly.
> 
> When the line side speed changes, the PHY will first report link down
> via the adjust_link callback in the MAC driver. Once the PHY has
> determined the new speed, the adjust_link callback will be called
> again with the new speed and pause parameters.

Or in the case of stmmac, phylink is involved, so .mac_link_down will
get called and then .mac_link_up with the new parameters.

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

* Re: [RFC PATCH 00/10] net: phy/stmmac: Add Loongson platform support
  2023-07-14  8:39     ` Russell King (Oracle)
@ 2023-07-16 14:59       ` Andrew Lunn
  2023-07-17  2:57         ` Feiyang Chen
  0 siblings, 1 reply; 38+ messages in thread
From: Andrew Lunn @ 2023-07-16 14:59 UTC (permalink / raw)
  To: Russell King (Oracle)
  Cc: Feiyang Chen, Feiyang Chen, hkallweit1, peppe.cavallaro,
	alexandre.torgue, joabreu, chenhuacai, dongbiao, loongson-kernel,
	netdev, loongarch

On Fri, Jul 14, 2023 at 09:39:07AM +0100, Russell King (Oracle) wrote:
> On Fri, Jul 14, 2023 at 10:16:07AM +0800, Feiyang Chen wrote:
> > On Thu, Jul 13, 2023 at 12:09 PM Andrew Lunn <andrew@lunn.ch> wrote:
> > >
> > > On Thu, Jul 13, 2023 at 10:46:52AM +0800, Feiyang Chen wrote:
> > > > Add driver for Loongson PHY. Extend stmmac functions and macros for
> > > > Loongson DWMAC. Add LS7A support for dwmac_loongson.
> > >
> > > Why is this RFC? What do you actually want comment on?
> > >
> > 
> > Hi, Andrew,
> > 
> > I marked this patch series as an RFC because I believe it involves
> > significant changes to the dwmac1000 driver. I want comments on the
> > design and any alternative suggestions.
> 
> That is admirable, but in practice, I've found that posting RFCs is
> a waste of effort and time - basically, it seems people ignore
> patches posted as RFC.
> 
> This turns the whole thing when posting patches into basically what
> I'd summarise as "reviewer blackmail" - post the patches non-RFC
> even when you want only comments, and reviewers _have_ to comment on
> the patches if there's something they don't like to prevent them
> being merged.
> 
> It's sad that it comes to that, but that is the reality of how things
> appear to work.

I have to agree with Russell. You wanted comments on the dwmac1000
patches, but all you received where comments on the PHY parts. Maybe
if you had requested comments on the MAC driver changes, somebody
might of commented, but i doubt it.

RFC seems best used during the merge window, and when you know the
target audience well enough to know they will look at the patches even
when it does have RFC.

     Andrew

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

* Re: [RFC PATCH 01/10] net: phy: Add driver for Loongson PHY
  2023-07-14  4:19       ` Andrew Lunn
@ 2023-07-17  2:43         ` Feiyang Chen
  2023-07-17 12:22           ` Andrew Lunn
  0 siblings, 1 reply; 38+ messages in thread
From: Feiyang Chen @ 2023-07-17  2:43 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Feiyang Chen, hkallweit1, peppe.cavallaro, alexandre.torgue,
	joabreu, chenhuacai, linux, dongbiao, loongson-kernel, netdev,
	loongarch

On Fri, Jul 14, 2023 at 12:20 PM Andrew Lunn <andrew@lunn.ch> wrote:
>
> > > > +#include <linux/mii.h>
> > > > +#include <linux/module.h>
> > > > +#include <linux/netdevice.h>
> > > > +#include <linux/pci.h>
> > > > +#include <linux/phy.h>
> > > > +
> > > > +#define PHY_ID_LS7A2000              0x00061ce0
> > >
> > > What is Loongson OUI?
> > >
> >
> > Currently, we do not have an OUI for Loongson, but we are in the
> > process of applying for one.
>
> Is the value 0x00061ce0 baked into the silicon? Or can it be changed
> once you have an OUI?
>

Hi, Andrew,

The value is baked into the silicon.

> > > > +#define GNET_REV_LS7A2000    0x00
> > > > +
> > > > +static int ls7a2000_config_aneg(struct phy_device *phydev)
> > > > +{
> > > > +     if (phydev->speed == SPEED_1000)
> > > > +             phydev->autoneg = AUTONEG_ENABLE;
> > >
> > > Please explain.
> > >
> >
> > The PHY itself supports half-duplex, but there are issues with the
> > controller used in the 7A2000 chip. Moreover, the controller only
> > supports auto-negotiation for gigabit speeds.
>
> So you can force 10/100/1000, but auto neg only succeeds for 1G?
>
> Are the LP autoneg values available for genphy_read_lpa() to read? If
> the LP values are available, maybe the PHY driver can resolve the
> autoneg for 10 an 100.
>

I apologize for the confusion caused by my previous description. To
clarify, the PHY supports auto-negotiation and non-auto-negotiation
for 10/100, but non-auto-negotiation for 1000 does not work correctly.

> > > > +     if (linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT,
> > > > +         phydev->advertising) ||
> > > > +         linkmode_test_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
> > > > +         phydev->advertising) ||
> > > > +         linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
> > > > +         phydev->advertising))
> > > > +         return genphy_config_aneg(phydev);
> > > > +
> > > > +     netdev_info(phydev->attached_dev, "Parameter Setting Error\n");
> > >
> > > This also needs explaining. How can it be asked to do something it
> > > does not support?
> > >
> >
> > Perhaps I missed something, but I think that if someone uses ethtool,
> > they can request it to perform actions or configurations that the
> > tool does not support.
>
> No. The PHY should indicate what it can do, via the .get_abilities()
> etc. The MAC can also remove some of those link modes if it is more
> limited than the PHY. phylib will then not allow ksetting_set() to
> enable things which are not supported. So this should not happen.  It
> would actually be a bad design, since it would force every driver to
> do such checks, rather than implement it once in the core.
>

I see.

> > > > +int ls7a2000_match_phy_device(struct phy_device *phydev)
> > > > +{
> > > > +     struct net_device *ndev;
> > > > +     struct pci_dev *pdev;
> > > > +
> > > > +     if ((phydev->phy_id & 0xfffffff0) != PHY_ID_LS7A2000)
> > > > +             return 0;
> > > > +
> > > > +     ndev = phydev->mdio.bus->priv;
> > > > +     pdev = to_pci_dev(ndev->dev.parent);
> > > > +
> > > > +     return pdev->revision == GNET_REV_LS7A2000;
> > >
> > > That is very unusual. Why is the PHY ID not sufficient?
> > >
> >
> > To work around the controller's issues, we enable the usage of this
> > driver specifically for a certain version of the 7A2000 chip.
> >
> > > > +}
> > > > +
> > > > +static struct phy_driver loongson_phy_driver[] = {
> > > > +     {
> > > > +             PHY_ID_MATCH_MODEL(PHY_ID_LS7A2000),
> > > > +             .name                   = "LS7A2000 PHY",
> > > > +             .features               = PHY_LOONGSON_FEATURES,
> > >
> > > So what are the capabilities of this PHY? You seem to have some very
> > > odd hacks here, and no explanation of why they are needed. If you do
> > > something which no other device does, you need to explain it.
> > >
> > > Does the PHY itself only support full duplex? No half duplex? Does the
> > > PHY support autoneg? Does it support fixed settings? What does
> > > genphy_read_abilities() return for this PHY?
> > >
> >
> > As mentioned earlier, this driver is specifically designed for the PHY
> > on the problematic 7A2000 chip. Therefore, we assume that this PHY only
> > supports full- duplex mode and performs auto-negotiation exclusively for
> > gigabit speeds.
>
> So what does genphy_read_abilities() return?
>
> Nobody else going to use PHY_LOONGSON_FEATURES, so i would prefer not
> to add it to the core. If your PHY is designed correctly,
> genphy_read_abilities() should determine what the PHY can do from its
> registers. If the registers are wrong, it is better to add a
> .get_features function.
>

genphy_read_abilities() returns 0, and it seems to be working fine.
The registers are incorrect, so I will use the .get_features function
to clear some of the half-duplex bits.

Thanks,
Feiyang

>         Andrew

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

* Re: [RFC PATCH 00/10] net: phy/stmmac: Add Loongson platform support
  2023-07-16 14:59       ` Andrew Lunn
@ 2023-07-17  2:57         ` Feiyang Chen
  0 siblings, 0 replies; 38+ messages in thread
From: Feiyang Chen @ 2023-07-17  2:57 UTC (permalink / raw)
  To: Russell King (Oracle), Andrew Lunn
  Cc: Feiyang Chen, hkallweit1, peppe.cavallaro, alexandre.torgue,
	joabreu, chenhuacai, dongbiao, loongson-kernel, netdev,
	loongarch

Hi, Russell, Andrew,

Thank you for your insights on RFC patches. I'll remove the
RFC in the next version of the patch series.

Thanks,
Feiyang

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

* Re: [RFC PATCH 10/10] net: stmmac: dwmac-loongson: Add GNET support
  2023-07-14  8:45       ` Russell King (Oracle)
@ 2023-07-17  7:54         ` Feiyang Chen
  0 siblings, 0 replies; 38+ messages in thread
From: Feiyang Chen @ 2023-07-17  7:54 UTC (permalink / raw)
  To: Russell King (Oracle), Andrew Lunn
  Cc: Feiyang Chen, hkallweit1, peppe.cavallaro, alexandre.torgue,
	joabreu, chenhuacai, dongbiao, loongson-kernel, netdev,
	loongarch

On Fri, Jul 14, 2023 at 4:45 PM Russell King (Oracle)
<linux@armlinux.org.uk> wrote:
>
> On Fri, Jul 14, 2023 at 10:24:37AM +0800, Feiyang Chen wrote:
> > On Thu, Jul 13, 2023 at 12:07 PM Andrew Lunn <andrew@lunn.ch> wrote:
> > >
> > > On Thu, Jul 13, 2023 at 10:49:38AM +0800, Feiyang Chen wrote:
> > > > Add GNET support. Use the fix_mac_speed() callback to workaround
> > > > issues with the Loongson PHY.
> > >
> > > What are the issues?
> > >
> >
> > Hi, Andrew,
> >
> > There is an issue with the synchronization between the network card
> > and the PHY. In the case of gigabit operation, if the PHY's speed
> > changes, the network card's speed remains unaffected. Hence, it is
> > necessary to initiate a re-negotiation process with the PHY to align
> > the link speeds properly.
>
> Please could you explain a bit more what happens when "the PHY's speed
> changes". Are you suggesting that:
>
> You have a connection where the media side has negotiated 1G speed.
> The gigabit partner is disconnected, so the link goes down, and is then
> replaced by a partner only capable of 100M. The link comes back up at
> 100M, but the network card continues trying to operate at 1G?
>

Hi, Russell, Andrew,

This bug shows up in the following way: when the speed is set to 1000M,
PHY is set up correctly and its status is normal. However, the controller
and PHY don't work well together, causing the controller to fail in
establishing a gigabit connection, which leads to a network disruption.
So, we need to use this bit to check if the controller's status is correct
and reset PHY if necessary.

if (readl(ptr->ioaddr + MAC_CTRL_REG) & (1 << 15) /* PS */)

The troublesome issue is that we have to check this bit in stmmac.
As a result, we are forced to place phy_restart_aneg() there.

Thanks,
Feiyang

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

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

* Re: [RFC PATCH 01/10] net: phy: Add driver for Loongson PHY
  2023-07-17  2:43         ` Feiyang Chen
@ 2023-07-17 12:22           ` Andrew Lunn
  2023-07-21  3:31             ` Feiyang Chen
  0 siblings, 1 reply; 38+ messages in thread
From: Andrew Lunn @ 2023-07-17 12:22 UTC (permalink / raw)
  To: Feiyang Chen
  Cc: Feiyang Chen, hkallweit1, peppe.cavallaro, alexandre.torgue,
	joabreu, chenhuacai, linux, dongbiao, loongson-kernel, netdev,
	loongarch

> > > > > +#define PHY_ID_LS7A2000              0x00061ce0
> > > >
> > > > What is Loongson OUI?
> > > >
> > >
> > > Currently, we do not have an OUI for Loongson, but we are in the
> > > process of applying for one.
> >
> > Is the value 0x00061ce0 baked into the silicon? Or can it be changed
> > once you have an OUI?
> >
> 
> Hi, Andrew,
> 
> The value is baked into the silicon.

O.K. Thanks. Do you have an idea how long it will take to get an OUI?

Does the PCI ID uniquely identify the MAC+PHY combination? 

> > > The PHY itself supports half-duplex, but there are issues with the
> > > controller used in the 7A2000 chip. Moreover, the controller only
> > > supports auto-negotiation for gigabit speeds.
> >
> > So you can force 10/100/1000, but auto neg only succeeds for 1G?
> >
> > Are the LP autoneg values available for genphy_read_lpa() to read? If
> > the LP values are available, maybe the PHY driver can resolve the
> > autoneg for 10 an 100.
> >
> 
> I apologize for the confusion caused by my previous description. To
> clarify, the PHY supports auto-negotiation and non-auto-negotiation
> for 10/100, but non-auto-negotiation for 1000 does not work correctly.

So you can force 10/100, but auto-neg 10/100/1000.

So i would suggest .get_features() indicates normal 10/100/1000
operation. Have your .config_aneg function which is used for both
auto-neg and forced configuration check for phydev->autoneg ==
AUTONEG_DISABLE and phydev->speed == SPEED_1000 and return
-EOPNOTSUPP. Otherwise call genphy_config_aneg().

> > So what does genphy_read_abilities() return?
> >
> > Nobody else going to use PHY_LOONGSON_FEATURES, so i would prefer not
> > to add it to the core. If your PHY is designed correctly,
> > genphy_read_abilities() should determine what the PHY can do from its
> > registers. If the registers are wrong, it is better to add a
> > .get_features function.
> >
> 
> genphy_read_abilities() returns 0, and it seems to be working fine.
> The registers are incorrect, so I will use the .get_features function
> to clear some of the half-duplex bits.

You said above that the PHY supports half duplex, the MAC has problems
with half duplex. So it should be the MAC which indicates it does not
unsupported half duplex link modes.

So you need to modify phylink_config.mac_capabilities before
phylink_create() is called. There is already

        /* Half-Duplex can only work with single queue */
	if (priv->plat->tx_queues_to_use > 1)
                priv->phylink_config.mac_capabilities &=
                        ~(MAC_10HD | MAC_100HD | MAC_1000HD);

so you just need to add a quirk for your broken hardware.

	Andrew


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

* Re: [RFC PATCH 01/10] net: phy: Add driver for Loongson PHY
  2023-07-17 12:22           ` Andrew Lunn
@ 2023-07-21  3:31             ` Feiyang Chen
  2023-07-21  9:04               ` Andrew Lunn
  0 siblings, 1 reply; 38+ messages in thread
From: Feiyang Chen @ 2023-07-21  3:31 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Feiyang Chen, hkallweit1, peppe.cavallaro, alexandre.torgue,
	joabreu, chenhuacai, linux, dongbiao, loongson-kernel, netdev,
	loongarch

On Mon, Jul 17, 2023 at 8:22 PM Andrew Lunn <andrew@lunn.ch> wrote:
>
> > > > > > +#define PHY_ID_LS7A2000              0x00061ce0
> > > > >
> > > > > What is Loongson OUI?
> > > > >
> > > >
> > > > Currently, we do not have an OUI for Loongson, but we are in the
> > > > process of applying for one.
> > >
> > > Is the value 0x00061ce0 baked into the silicon? Or can it be changed
> > > once you have an OUI?
> > >
> >
> > Hi, Andrew,
> >
> > The value is baked into the silicon.
>
> O.K. Thanks. Do you have an idea how long it will take to get an OUI?
>
> Does the PCI ID uniquely identify the MAC+PHY combination?
>

Hi, Andrew,

Sorry, I currently don't have an exact timeline for when the OUI will
be available. The next hardware version will address these bugs, so
we won't be going with this driver.

> > > > The PHY itself supports half-duplex, but there are issues with the
> > > > controller used in the 7A2000 chip. Moreover, the controller only
> > > > supports auto-negotiation for gigabit speeds.
> > >
> > > So you can force 10/100/1000, but auto neg only succeeds for 1G?
> > >
> > > Are the LP autoneg values available for genphy_read_lpa() to read? If
> > > the LP values are available, maybe the PHY driver can resolve the
> > > autoneg for 10 an 100.
> > >
> >
> > I apologize for the confusion caused by my previous description. To
> > clarify, the PHY supports auto-negotiation and non-auto-negotiation
> > for 10/100, but non-auto-negotiation for 1000 does not work correctly.
>
> So you can force 10/100, but auto-neg 10/100/1000.
>
> So i would suggest .get_features() indicates normal 10/100/1000
> operation. Have your .config_aneg function which is used for both
> auto-neg and forced configuration check for phydev->autoneg ==
> AUTONEG_DISABLE and phydev->speed == SPEED_1000 and return
> -EOPNOTSUPP. Otherwise call genphy_config_aneg().
>

Well, can I return -EINVAL in the .set_link_ksettings callback?
Considering that our next hardware version will have the OUI
allocated and these bugs fixed, I won't submit this driver in
the next patch version. I believe we can just use the generic
PHY for now.

> > > So what does genphy_read_abilities() return?
> > >
> > > Nobody else going to use PHY_LOONGSON_FEATURES, so i would prefer not
> > > to add it to the core. If your PHY is designed correctly,
> > > genphy_read_abilities() should determine what the PHY can do from its
> > > registers. If the registers are wrong, it is better to add a
> > > .get_features function.
> > >
> >
> > genphy_read_abilities() returns 0, and it seems to be working fine.
> > The registers are incorrect, so I will use the .get_features function
> > to clear some of the half-duplex bits.
>
> You said above that the PHY supports half duplex, the MAC has problems
> with half duplex. So it should be the MAC which indicates it does not
> unsupported half duplex link modes.
>
> So you need to modify phylink_config.mac_capabilities before
> phylink_create() is called. There is already
>
>         /* Half-Duplex can only work with single queue */
>         if (priv->plat->tx_queues_to_use > 1)
>                 priv->phylink_config.mac_capabilities &=
>                         ~(MAC_10HD | MAC_100HD | MAC_1000HD);
>
> so you just need to add a quirk for your broken hardware.
>

OK.

Thanks,
Feiyang

>         Andrew
>

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

* Re: [RFC PATCH 01/10] net: phy: Add driver for Loongson PHY
  2023-07-21  3:31             ` Feiyang Chen
@ 2023-07-21  9:04               ` Andrew Lunn
  2023-07-25  2:02                 ` Feiyang Chen
  0 siblings, 1 reply; 38+ messages in thread
From: Andrew Lunn @ 2023-07-21  9:04 UTC (permalink / raw)
  To: Feiyang Chen
  Cc: Feiyang Chen, hkallweit1, peppe.cavallaro, alexandre.torgue,
	joabreu, chenhuacai, linux, dongbiao, loongson-kernel, netdev,
	loongarch

> Hi, Andrew,
> 
> Sorry, I currently don't have an exact timeline for when the OUI will
> be available. The next hardware version will address these bugs, so
> we won't be going with this driver.

Not having an OUI breaks the standard. So i was actually thinking you
should trap the reads to the ID registers in the MDIO bus driver and
return valid values. Some Marvell Ethernet switch integrated PHYs have
a valid OUI, and no device part. We trap those and insert valid
values. So there is some president for doing this. Doing this would
also allow you to avoid the PHY driver poking around the MAC drivers
PCI bus.

> > So i would suggest .get_features() indicates normal 10/100/1000
> > operation. Have your .config_aneg function which is used for both
> > auto-neg and forced configuration check for phydev->autoneg ==
> > AUTONEG_DISABLE and phydev->speed == SPEED_1000 and return
> > -EOPNOTSUPP. Otherwise call genphy_config_aneg().
> >
> 
> Well, can I return -EINVAL in the .set_link_ksettings callback?

If the PHY is broken, the PHY should do it. If the MAC is broken, the
MAC should do it. We have clean separation here, even when the
hardware is integrated.

> Considering that our next hardware version will have the OUI
> allocated and these bugs fixed, I won't submit this driver in
> the next patch version. I believe we can just use the generic
> PHY for now.

The problem with the generic driver is you cannot have workarounds in
it. You don't want to put PHY workarounds in the MAC driver.

    Andrew


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

* Re: [RFC PATCH 01/10] net: phy: Add driver for Loongson PHY
  2023-07-21  9:04               ` Andrew Lunn
@ 2023-07-25  2:02                 ` Feiyang Chen
  2023-07-25 17:20                   ` Andrew Lunn
  0 siblings, 1 reply; 38+ messages in thread
From: Feiyang Chen @ 2023-07-25  2:02 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Feiyang Chen, hkallweit1, peppe.cavallaro, alexandre.torgue,
	joabreu, chenhuacai, linux, dongbiao, loongson-kernel, netdev,
	loongarch

On Fri, Jul 21, 2023 at 5:04 PM Andrew Lunn <andrew@lunn.ch> wrote:
>
> > Hi, Andrew,
> >
> > Sorry, I currently don't have an exact timeline for when the OUI will
> > be available. The next hardware version will address these bugs, so
> > we won't be going with this driver.
>
> Not having an OUI breaks the standard. So i was actually thinking you
> should trap the reads to the ID registers in the MDIO bus driver and
> return valid values. Some Marvell Ethernet switch integrated PHYs have
> a valid OUI, and no device part. We trap those and insert valid
> values. So there is some president for doing this. Doing this would
> also allow you to avoid the PHY driver poking around the MAC drivers
> PCI bus.
>
> > > So i would suggest .get_features() indicates normal 10/100/1000
> > > operation. Have your .config_aneg function which is used for both
> > > auto-neg and forced configuration check for phydev->autoneg ==
> > > AUTONEG_DISABLE and phydev->speed == SPEED_1000 and return
> > > -EOPNOTSUPP. Otherwise call genphy_config_aneg().
> > >
> >
> > Well, can I return -EINVAL in the .set_link_ksettings callback?
>
> If the PHY is broken, the PHY should do it. If the MAC is broken, the
> MAC should do it. We have clean separation here, even when the
> hardware is integrated.
>

Hi, Andrew,

I get it. To be honest, I'm not familiar with the hardware, so I asked
the colleague who designed this chip. The real problem is the same as I
described in Patch 10 - the Ethernet controller doesn't work well with
the PHY. If the controller works properly, we can force 1000. Are there
any methods to work around this problem in the MAC driver?

> > Considering that our next hardware version will have the OUI
> > allocated and these bugs fixed, I won't submit this driver in
> > the next patch version. I believe we can just use the generic
> > PHY for now.
>
> The problem with the generic driver is you cannot have workarounds in
> it. You don't want to put PHY workarounds in the MAC driver.
>

Sure, we should not put PHY workarounds in the MAC driver and vice
versa.

This PHY driver was designed to solve two problems at first:
1. We cannot force 1000.
2. We cannot use half duplex.

Now, we are sure that the MAC is broken, not the PHY, so I think we
can solve these problems in the MAC driver.

Thanks,
Feiyang

>     Andrew
>

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

* Re: [RFC PATCH 01/10] net: phy: Add driver for Loongson PHY
  2023-07-25  2:02                 ` Feiyang Chen
@ 2023-07-25 17:20                   ` Andrew Lunn
  0 siblings, 0 replies; 38+ messages in thread
From: Andrew Lunn @ 2023-07-25 17:20 UTC (permalink / raw)
  To: Feiyang Chen
  Cc: Feiyang Chen, hkallweit1, peppe.cavallaro, alexandre.torgue,
	joabreu, chenhuacai, linux, dongbiao, loongson-kernel, netdev,
	loongarch

> This PHY driver was designed to solve two problems at first:
> 1. We cannot force 1000.
> 2. We cannot use half duplex.
> 
> Now, we are sure that the MAC is broken, not the PHY, so I think we
> can solve these problems in the MAC driver.

You can solve both of these in the MAC. You can remove the half duplex
link modes after the PHY is connected to the MAC. And you can add a
test in ksetting_set to check for 1000 Force and return EOPNOTSUPP.

     Andrew

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

end of thread, other threads:[~2023-07-25 17:20 UTC | newest]

Thread overview: 38+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-07-13  2:46 [RFC PATCH 00/10] net: phy/stmmac: Add Loongson platform support Feiyang Chen
2023-07-13  2:46 ` [RFC PATCH 01/10] net: phy: Add driver for Loongson PHY Feiyang Chen
2023-07-13  4:00   ` Andrew Lunn
2023-07-14  2:15     ` Feiyang Chen
2023-07-14  4:19       ` Andrew Lunn
2023-07-17  2:43         ` Feiyang Chen
2023-07-17 12:22           ` Andrew Lunn
2023-07-21  3:31             ` Feiyang Chen
2023-07-21  9:04               ` Andrew Lunn
2023-07-25  2:02                 ` Feiyang Chen
2023-07-25 17:20                   ` Andrew Lunn
2023-07-13  7:53   ` Russell King (Oracle)
2023-07-14  2:41     ` Feiyang Chen
2023-07-13  2:46 ` [RFC PATCH 02/10] net: stmmac: Pass stmmac_priv and chan in some callbacks Feiyang Chen
2023-07-13  4:02   ` Andrew Lunn
2023-07-14  2:16     ` Feiyang Chen
2023-07-13  2:46 ` [RFC PATCH 03/10] net: stmmac: dwmac1000: Allow platforms to choose some register offsets Feiyang Chen
2023-07-13  2:46 ` [RFC PATCH 04/10] net: stmmac: dwmac1000: Add multi-channel support Feiyang Chen
2023-07-13  2:48 ` [RFC PATCH 05/10] net: stmmac: dwmac1000: Add 64-bit DMA support Feiyang Chen
2023-07-13  2:48 ` [RFC PATCH 06/10] net: stmmac: dwmac1000: Add Loongson register definitions Feiyang Chen
2023-07-13  2:48 ` [RFC PATCH 07/10] net: stmmac: Add Loongson HWIF entry Feiyang Chen
2023-07-13  2:48 ` [RFC PATCH 08/10] net: stmmac: dwmac-loongson: Add LS7A support Feiyang Chen
2023-07-13  2:48 ` [RFC PATCH 09/10] net: stmmac: dwmac-loongson: Add 64-bit DMA and multi-vector support Feiyang Chen
2023-07-13  2:49 ` [RFC PATCH 10/10] net: stmmac: dwmac-loongson: Add GNET support Feiyang Chen
2023-07-13  4:07   ` Andrew Lunn
2023-07-14  2:24     ` Feiyang Chen
2023-07-14  4:26       ` Andrew Lunn
2023-07-14  8:52         ` Russell King (Oracle)
2023-07-14  8:45       ` Russell King (Oracle)
2023-07-17  7:54         ` Feiyang Chen
2023-07-13  8:06   ` Russell King (Oracle)
2023-07-14  2:27     ` Feiyang Chen
2023-07-14  4:22       ` Andrew Lunn
2023-07-13  4:09 ` [RFC PATCH 00/10] net: phy/stmmac: Add Loongson platform support Andrew Lunn
2023-07-14  2:16   ` Feiyang Chen
2023-07-14  8:39     ` Russell King (Oracle)
2023-07-16 14:59       ` Andrew Lunn
2023-07-17  2:57         ` Feiyang Chen

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