All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH net-next v11 0/6] stmmac: Add Loongson platform support
@ 2024-04-12 11:28 Yanteng Si
  2024-04-12 11:28 ` [PATCH net-next v11 1/6] net: stmmac: Move all PHYLINK MAC capabilities initializations to MAC-specific setup methods Yanteng Si
                   ` (6 more replies)
  0 siblings, 7 replies; 36+ messages in thread
From: Yanteng Si @ 2024-04-12 11:28 UTC (permalink / raw)
  To: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	fancer.lancer
  Cc: Yanteng Si, Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang, siyanteng01

v11:
* Break loongson_phylink_get_caps(), fix bad logic.
* Remove a unnecessary ";".
* Remove some unnecessary "{}".
* add a blank.
* Move the code of fix _force_1000 to patch 6/6.

The main changes occur in these two functions:
loongson_dwmac_probe();
loongson_dwmac_setup();

v10:
As Andrew's comment:
* Add a #define for the 0x37.
* Add a #define for Port Select.

others:
* Pick Serge's patch, This patch resulted from the process
  of reviewing our patch set.
* Based on Serge's patch, modify our loongson_phylink_get_caps().
* Drop patch 3/6, we need mac_interface.
* Adjusted the code layout of gnet patch.
* Corrected several errata in commit message.
* Move DISABLE_FORCE flag to loongson_gnet_data().

v9:
We have not provided a detailed list of equipment for a long time,
and I apologize for this. During this period, I have collected some
information and now present it to you, hoping to alleviate the pressure
of review.

1. IP core
We now have two types of IP cores, one is 0x37, similar to dwmac1000;
The other is 0x10.  Compared to 0x37, we split several DMA registers
from one to two, and it is not worth adding a new entry for this.
According to Serge's comment, we made these devices work by overwriting
priv->synopsys_id = 0x37 and mac->dma = <LS_dma_ops>.

1.1.  Some more detailed information
The number of DMA channels for 0x37 is 1; The number of DMA channels
for 0x10 is 8.  Except for channel 0, otherchannels do not support
sending hardware checksums. Supported AV features are Qav, Qat, and Qas,
and the rest are consistent with 3.73.

2. DEVICE
We have two types of devices,
one is GMAC, which only has a MAC chip inside and needs an external PHY
chip;
the other is GNET, which integrates both MAC and PHY chips inside.

2.1.  Some more detailed information
GMAC device: LS7A1000, LS2K1000, these devices do not support any pause
mode.
gnet device: LS7A2000, LS2K2000, the chip connection between the mac and
             phy of these devices is not normal and requires two rounds of
             negotiation; LS7A2000 does not support half-duplex and
multi-channel;
             to enable multi-channel on LS2K2000, you need to turn off
hardware checksum.
**Note**: Only the LS2K2000's IP core is 0x10, while the IP cores of other
devices are 0x37.

3. TABLE

device    type    pci_id    ip_core
ls7a1000  gmac    7a03      0x35/0x37
ls2k1000  gmac    7a03      0x35/0x37
ls7a2000  gnet    7a13      0x37
ls2k2000  gnet    7a13      0x10
-----------------------------------------------
Changes:

* passed the CI
  <https://github.com/linux-netdev/nipa/blob/main/tests/patch/checkpatch
  /checkpatch.sh>
* reverse xmas tree order.
* Silence build warning.
* Re-split the patch.
* Add more detailed commit message.
* Add more code comment.
* Reduce modification of generic code.
* using the GNET-specific prefix.
* define a new macro for the GNET MAC.
* Use an easier way to overwrite mac.
* Removed some useless printk.


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

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

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

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

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

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

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

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


v6:

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

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

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

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


v4 -> v5:

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

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

Serge Semin (1):
  net: stmmac: Move all PHYLINK MAC capabilities initializations to
    MAC-specific setup methods

Yanteng Si (5):
  net: stmmac: Add multi-channel support
  net: stmmac: dwmac-loongson: Use PCI_DEVICE_DATA() macro for device
    identification
  net: stmmac: dwmac-loongson: Introduce GMAC setup
  net: stmmac: dwmac-loongson: Add full PCI support
  net: stmmac: dwmac-loongson: Add Loongson GNET support

 drivers/net/ethernet/stmicro/stmmac/common.h  |   3 +
 .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 544 ++++++++++++++++--
 .../net/ethernet/stmicro/stmmac/dwmac-sun8i.c |   6 +-
 .../ethernet/stmicro/stmmac/dwmac1000_core.c  |   2 +
 .../ethernet/stmicro/stmmac/dwmac1000_dma.c   |  35 +-
 .../ethernet/stmicro/stmmac/dwmac100_core.c   |   2 +
 .../ethernet/stmicro/stmmac/dwmac100_dma.c    |   2 +-
 .../net/ethernet/stmicro/stmmac/dwmac4_core.c |   8 +-
 .../net/ethernet/stmicro/stmmac/dwmac4_dma.c  |   2 +-
 .../net/ethernet/stmicro/stmmac/dwmac_dma.h   |  20 +-
 .../net/ethernet/stmicro/stmmac/dwmac_lib.c   |  32 +-
 .../ethernet/stmicro/stmmac/dwxgmac2_core.c   |  15 +-
 .../ethernet/stmicro/stmmac/dwxgmac2_dma.c    |   2 +-
 drivers/net/ethernet/stmicro/stmmac/hwif.h    |   5 +-
 .../ethernet/stmicro/stmmac/stmmac_ethtool.c  |   6 +
 .../net/ethernet/stmicro/stmmac/stmmac_main.c |  54 +-
 include/linux/stmmac.h                        |   2 +
 17 files changed, 599 insertions(+), 141 deletions(-)

-- 
2.31.4


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

* [PATCH net-next v11 1/6] net: stmmac: Move all PHYLINK MAC capabilities initializations to MAC-specific setup methods
  2024-04-12 11:28 [PATCH net-next v11 0/6] stmmac: Add Loongson platform support Yanteng Si
@ 2024-04-12 11:28 ` Yanteng Si
  2024-04-12 18:32   ` Serge Semin
  2024-04-12 11:28 ` [PATCH net-next v11 2/6] net: stmmac: Add multi-channel support Yanteng Si
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 36+ messages in thread
From: Yanteng Si @ 2024-04-12 11:28 UTC (permalink / raw)
  To: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	fancer.lancer
  Cc: Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang, siyanteng01, Yanteng Si

From: Serge Semin <fancer.lancer@gmail.com>

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

But there are a better option to implement the MAC capabilities
detection procedure. Let's see what MAC-capabilities can be currently
specified based on the DW MAC IP-core versions:

DW MAC100: MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
	   MAC_10 | MAC_100

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

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

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

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

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

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

Others see:
<https://lore.kernel.org/netdev/cover.1706601050.git.siyanteng@loong
son.cn/T/#m7d724d33faee34fed696e4458d9f6b09b0572e77>

Signed-off-by: Serge Semin <fancer.lancer@gmail.com>
Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
---
 drivers/net/ethernet/stmicro/stmmac/common.h  |  1 +
 .../net/ethernet/stmicro/stmmac/dwmac-sun8i.c |  2 +
 .../ethernet/stmicro/stmmac/dwmac1000_core.c  |  2 +
 .../ethernet/stmicro/stmmac/dwmac100_core.c   |  2 +
 .../net/ethernet/stmicro/stmmac/dwmac4_core.c |  8 +++-
 .../ethernet/stmicro/stmmac/dwxgmac2_core.c   | 15 +++----
 .../net/ethernet/stmicro/stmmac/stmmac_main.c | 43 ++++++++-----------
 7 files changed, 36 insertions(+), 37 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index f55cf09f0783..9cd62b2110a1 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -553,6 +553,7 @@ extern const struct stmmac_hwtimestamp stmmac_ptp;
 extern const struct stmmac_mode_ops dwmac4_ring_mode_ops;
 
 struct mac_link {
+	u32 caps;
 	u32 speed_mask;
 	u32 speed10;
 	u32 speed100;
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
index b21d99faa2d0..e1b761dcfa1d 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
@@ -1096,6 +1096,8 @@ static struct mac_device_info *sun8i_dwmac_setup(void *ppriv)
 
 	priv->dev->priv_flags |= IFF_UNICAST_FLT;
 
+	mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
+			 MAC_10 | MAC_100 | MAC_1000;
 	/* The loopback bit seems to be re-set when link change
 	 * Simply mask it each time
 	 * Speed 10/100/1000 are set in BIT(2)/BIT(3)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
index 3927609abc44..8555299443f4 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
@@ -539,6 +539,8 @@ int dwmac1000_setup(struct stmmac_priv *priv)
 	if (mac->multicast_filter_bins)
 		mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins);
 
+	mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
+			 MAC_10 | MAC_100 | MAC_1000;
 	mac->link.duplex = GMAC_CONTROL_DM;
 	mac->link.speed10 = GMAC_CONTROL_PS;
 	mac->link.speed100 = GMAC_CONTROL_PS | GMAC_CONTROL_FES;
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
index a6e8d7bd9588..7667d103cd0e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
@@ -175,6 +175,8 @@ int dwmac100_setup(struct stmmac_priv *priv)
 	dev_info(priv->device, "\tDWMAC100\n");
 
 	mac->pcsr = priv->ioaddr;
+	mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
+			 MAC_10 | MAC_100;
 	mac->link.duplex = MAC_CONTROL_F;
 	mac->link.speed10 = 0;
 	mac->link.speed100 = 0;
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
index cef25efbdff9..70a4ac16d3c8 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
@@ -70,7 +70,11 @@ static void dwmac4_core_init(struct mac_device_info *hw,
 
 static void dwmac4_phylink_get_caps(struct stmmac_priv *priv)
 {
-	priv->phylink_config.mac_capabilities |= MAC_2500FD;
+	/* Half-Duplex can only work with single tx queue */
+	if (priv->plat->tx_queues_to_use > 1)
+		priv->hw->link.caps &= ~(MAC_10HD | MAC_100HD | MAC_1000HD);
+	else
+		priv->hw->link.caps |= (MAC_10HD | MAC_100HD | MAC_1000HD);
 }
 
 static void dwmac4_rx_queue_enable(struct mac_device_info *hw,
@@ -1378,6 +1382,8 @@ int dwmac4_setup(struct stmmac_priv *priv)
 	if (mac->multicast_filter_bins)
 		mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins);
 
+	mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
+			 MAC_10 | MAC_100 | MAC_1000 | MAC_2500FD;
 	mac->link.duplex = GMAC_CONFIG_DM;
 	mac->link.speed10 = GMAC_CONFIG_PS;
 	mac->link.speed100 = GMAC_CONFIG_FES | GMAC_CONFIG_PS;
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
index e841e312077e..759b9b7a2f3f 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
@@ -47,14 +47,6 @@ static void dwxgmac2_core_init(struct mac_device_info *hw,
 	writel(XGMAC_INT_DEFAULT_EN, ioaddr + XGMAC_INT_EN);
 }
 
-static void xgmac_phylink_get_caps(struct stmmac_priv *priv)
-{
-	priv->phylink_config.mac_capabilities |= MAC_2500FD | MAC_5000FD |
-						 MAC_10000FD | MAC_25000FD |
-						 MAC_40000FD | MAC_50000FD |
-						 MAC_100000FD;
-}
-
 static void dwxgmac2_set_mac(void __iomem *ioaddr, bool enable)
 {
 	u32 tx = readl(ioaddr + XGMAC_TX_CONFIG);
@@ -1540,7 +1532,6 @@ static void dwxgmac3_fpe_configure(void __iomem *ioaddr, struct stmmac_fpe_cfg *
 
 const struct stmmac_ops dwxgmac210_ops = {
 	.core_init = dwxgmac2_core_init,
-	.phylink_get_caps = xgmac_phylink_get_caps,
 	.set_mac = dwxgmac2_set_mac,
 	.rx_ipc = dwxgmac2_rx_ipc,
 	.rx_queue_enable = dwxgmac2_rx_queue_enable,
@@ -1601,7 +1592,6 @@ static void dwxlgmac2_rx_queue_enable(struct mac_device_info *hw, u8 mode,
 
 const struct stmmac_ops dwxlgmac2_ops = {
 	.core_init = dwxgmac2_core_init,
-	.phylink_get_caps = xgmac_phylink_get_caps,
 	.set_mac = dwxgmac2_set_mac,
 	.rx_ipc = dwxgmac2_rx_ipc,
 	.rx_queue_enable = dwxlgmac2_rx_queue_enable,
@@ -1698,6 +1688,11 @@ int dwxlgmac2_setup(struct stmmac_priv *priv)
 	if (mac->multicast_filter_bins)
 		mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins);
 
+	mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
+			 MAC_1000FD | MAC_2500FD | MAC_5000FD |
+			 MAC_10000FD | MAC_25000FD |
+			 MAC_40000FD | MAC_50000FD |
+			 MAC_100000FD;
 	mac->link.duplex = 0;
 	mac->link.speed1000 = XLGMAC_CONFIG_SS_1000;
 	mac->link.speed2500 = XLGMAC_CONFIG_SS_2500;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index fe3498e86de9..af16efeedf4a 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -936,6 +936,22 @@ static void stmmac_mac_flow_ctrl(struct stmmac_priv *priv, u32 duplex)
 			priv->pause, tx_cnt);
 }
 
+static unsigned long stmmac_mac_get_caps(struct phylink_config *config,
+					 phy_interface_t interface)
+{
+	struct stmmac_priv *priv = netdev_priv(to_net_dev(config->dev));
+
+	/* Get the MAC-specific capabilities */
+	stmmac_mac_phylink_get_caps(priv);
+
+	config->mac_capabilities = priv->hw->link.caps;
+
+	if (priv->plat->max_speed)
+		phylink_limit_mac_speed(config, priv->plat->max_speed);
+
+	return config->mac_capabilities;
+}
+
 static struct phylink_pcs *stmmac_mac_select_pcs(struct phylink_config *config,
 						 phy_interface_t interface)
 {
@@ -1102,6 +1118,7 @@ static void stmmac_mac_link_up(struct phylink_config *config,
 }
 
 static const struct phylink_mac_ops stmmac_phylink_mac_ops = {
+	.mac_get_caps = stmmac_mac_get_caps,
 	.mac_select_pcs = stmmac_mac_select_pcs,
 	.mac_config = stmmac_mac_config,
 	.mac_link_down = stmmac_mac_link_down,
@@ -1195,24 +1212,12 @@ static int stmmac_init_phy(struct net_device *dev)
 	return ret;
 }
 
-static void stmmac_set_half_duplex(struct stmmac_priv *priv)
-{
-	/* Half-Duplex can only work with single tx queue */
-	if (priv->plat->tx_queues_to_use > 1)
-		priv->phylink_config.mac_capabilities &=
-			~(MAC_10HD | MAC_100HD | MAC_1000HD);
-	else
-		priv->phylink_config.mac_capabilities |=
-			(MAC_10HD | MAC_100HD | MAC_1000HD);
-}
-
 static int stmmac_phy_setup(struct stmmac_priv *priv)
 {
 	struct stmmac_mdio_bus_data *mdio_bus_data;
 	int mode = priv->plat->phy_interface;
 	struct fwnode_handle *fwnode;
 	struct phylink *phylink;
-	int max_speed;
 
 	priv->phylink_config.dev = &priv->dev->dev;
 	priv->phylink_config.type = PHYLINK_NETDEV;
@@ -1236,19 +1241,6 @@ static int stmmac_phy_setup(struct stmmac_priv *priv)
 		xpcs_get_interfaces(priv->hw->xpcs,
 				    priv->phylink_config.supported_interfaces);
 
-	priv->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
-						MAC_10FD | MAC_100FD |
-						MAC_1000FD;
-
-	stmmac_set_half_duplex(priv);
-
-	/* Get the MAC specific capabilities */
-	stmmac_mac_phylink_get_caps(priv);
-
-	max_speed = priv->plat->max_speed;
-	if (max_speed)
-		phylink_limit_mac_speed(&priv->phylink_config, max_speed);
-
 	fwnode = priv->plat->port_node;
 	if (!fwnode)
 		fwnode = dev_fwnode(priv->device);
@@ -7357,7 +7349,6 @@ int stmmac_reinit_queues(struct net_device *dev, u32 rx_cnt, u32 tx_cnt)
 			priv->rss.table[i] = ethtool_rxfh_indir_default(i,
 									rx_cnt);
 
-	stmmac_set_half_duplex(priv);
 	stmmac_napi_add(dev);
 
 	if (netif_running(dev))
-- 
2.31.4


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

* [PATCH net-next v11 2/6] net: stmmac: Add multi-channel support
  2024-04-12 11:28 [PATCH net-next v11 0/6] stmmac: Add Loongson platform support Yanteng Si
  2024-04-12 11:28 ` [PATCH net-next v11 1/6] net: stmmac: Move all PHYLINK MAC capabilities initializations to MAC-specific setup methods Yanteng Si
@ 2024-04-12 11:28 ` Yanteng Si
  2024-04-18 11:02   ` Serge Semin
  2024-04-12 11:28 ` [PATCH net-next v11 3/6] net: stmmac: dwmac-loongson: Use PCI_DEVICE_DATA() macro for device identification Yanteng Si
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 36+ messages in thread
From: Yanteng Si @ 2024-04-12 11:28 UTC (permalink / raw)
  To: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	fancer.lancer
  Cc: Yanteng Si, Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang, siyanteng01

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

Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
---
 .../net/ethernet/stmicro/stmmac/dwmac-sun8i.c |  4 +--
 .../ethernet/stmicro/stmmac/dwmac1000_dma.c   | 34 ++++++++++---------
 .../ethernet/stmicro/stmmac/dwmac100_dma.c    |  2 +-
 .../net/ethernet/stmicro/stmmac/dwmac4_dma.c  |  2 +-
 .../net/ethernet/stmicro/stmmac/dwmac_dma.h   | 20 +++++++++--
 .../net/ethernet/stmicro/stmmac/dwmac_lib.c   | 32 ++++++++---------
 .../ethernet/stmicro/stmmac/dwxgmac2_dma.c    |  2 +-
 drivers/net/ethernet/stmicro/stmmac/hwif.h    |  5 ++-
 .../net/ethernet/stmicro/stmmac/stmmac_main.c | 11 +++---
 include/linux/stmmac.h                        |  1 +
 10 files changed, 65 insertions(+), 48 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
index e1b761dcfa1d..cc93f73a380e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
@@ -299,7 +299,7 @@ static int sun8i_dwmac_dma_reset(void __iomem *ioaddr)
  * Called from stmmac via stmmac_dma_ops->init
  */
 static void sun8i_dwmac_dma_init(void __iomem *ioaddr,
-				 struct stmmac_dma_cfg *dma_cfg, int atds)
+				 struct stmmac_dma_cfg *dma_cfg)
 {
 	writel(EMAC_RX_INT | EMAC_TX_INT, ioaddr + EMAC_INT_EN);
 	writel(0x1FFFFFF, ioaddr + EMAC_INT_STA);
@@ -395,7 +395,7 @@ static void sun8i_dwmac_dma_start_tx(struct stmmac_priv *priv,
 	writel(v, ioaddr + EMAC_TX_CTL1);
 }
 
-static void sun8i_dwmac_enable_dma_transmission(void __iomem *ioaddr)
+static void sun8i_dwmac_enable_dma_transmission(void __iomem *ioaddr, u32 chan)
 {
 	u32 v;
 
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
index daf79cdbd3ec..f161ec9ac490 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
@@ -70,15 +70,17 @@ static void dwmac1000_dma_axi(void __iomem *ioaddr, struct stmmac_axi *axi)
 	writel(value, ioaddr + DMA_AXI_BUS_MODE);
 }
 
-static void dwmac1000_dma_init(void __iomem *ioaddr,
-			       struct stmmac_dma_cfg *dma_cfg, int atds)
+static void dwmac1000_dma_init_channel(struct stmmac_priv *priv,
+				       void __iomem *ioaddr,
+				       struct stmmac_dma_cfg *dma_cfg, u32 chan)
 {
-	u32 value = readl(ioaddr + DMA_BUS_MODE);
 	int txpbl = dma_cfg->txpbl ?: dma_cfg->pbl;
 	int rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl;
+	u32 value;
 
-	/*
-	 * Set the DMA PBL (Programmable Burst Length) mode.
+	value = readl(ioaddr + DMA_CHAN_BUS_MODE(chan));
+
+	/* Set the DMA PBL (Programmable Burst Length) mode.
 	 *
 	 * Note: before stmmac core 3.50 this mode bit was 4xPBL, and
 	 * post 3.5 mode bit acts as 8*PBL.
@@ -98,16 +100,16 @@ static void dwmac1000_dma_init(void __iomem *ioaddr,
 	if (dma_cfg->mixed_burst)
 		value |= DMA_BUS_MODE_MB;
 
-	if (atds)
+	if (dma_cfg->atds)
 		value |= DMA_BUS_MODE_ATDS;
 
 	if (dma_cfg->aal)
 		value |= DMA_BUS_MODE_AAL;
 
-	writel(value, ioaddr + DMA_BUS_MODE);
+	writel(value, ioaddr + DMA_CHAN_BUS_MODE(chan));
 
 	/* Mask interrupts by writing to CSR7 */
-	writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_INTR_ENA);
+	writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_CHAN_INTR_ENA(chan));
 }
 
 static void dwmac1000_dma_init_rx(struct stmmac_priv *priv,
@@ -116,7 +118,7 @@ static void dwmac1000_dma_init_rx(struct stmmac_priv *priv,
 				  dma_addr_t dma_rx_phy, u32 chan)
 {
 	/* RX descriptor base address list must be written into DMA CSR3 */
-	writel(lower_32_bits(dma_rx_phy), ioaddr + DMA_RCV_BASE_ADDR);
+	writel(lower_32_bits(dma_rx_phy), ioaddr + DMA_CHAN_RCV_BASE_ADDR(chan));
 }
 
 static void dwmac1000_dma_init_tx(struct stmmac_priv *priv,
@@ -125,7 +127,7 @@ static void dwmac1000_dma_init_tx(struct stmmac_priv *priv,
 				  dma_addr_t dma_tx_phy, u32 chan)
 {
 	/* TX descriptor base address list must be written into DMA CSR4 */
-	writel(lower_32_bits(dma_tx_phy), ioaddr + DMA_TX_BASE_ADDR);
+	writel(lower_32_bits(dma_tx_phy), ioaddr + DMA_CHAN_TX_BASE_ADDR(chan));
 }
 
 static u32 dwmac1000_configure_fc(u32 csr6, int rxfifosz)
@@ -153,7 +155,7 @@ static void dwmac1000_dma_operation_mode_rx(struct stmmac_priv *priv,
 					    void __iomem *ioaddr, int mode,
 					    u32 channel, int fifosz, u8 qmode)
 {
-	u32 csr6 = readl(ioaddr + DMA_CONTROL);
+	u32 csr6 = readl(ioaddr + DMA_CHAN_CONTROL(channel));
 
 	if (mode == SF_DMA_MODE) {
 		pr_debug("GMAC: enable RX store and forward mode\n");
@@ -175,14 +177,14 @@ static void dwmac1000_dma_operation_mode_rx(struct stmmac_priv *priv,
 	/* Configure flow control based on rx fifo size */
 	csr6 = dwmac1000_configure_fc(csr6, fifosz);
 
-	writel(csr6, ioaddr + DMA_CONTROL);
+	writel(csr6, ioaddr + DMA_CHAN_CONTROL(channel));
 }
 
 static void dwmac1000_dma_operation_mode_tx(struct stmmac_priv *priv,
 					    void __iomem *ioaddr, int mode,
 					    u32 channel, int fifosz, u8 qmode)
 {
-	u32 csr6 = readl(ioaddr + DMA_CONTROL);
+	u32 csr6 = readl(ioaddr + DMA_CHAN_CONTROL(channel));
 
 	if (mode == SF_DMA_MODE) {
 		pr_debug("GMAC: enable TX store and forward mode\n");
@@ -209,7 +211,7 @@ static void dwmac1000_dma_operation_mode_tx(struct stmmac_priv *priv,
 			csr6 |= DMA_CONTROL_TTC_256;
 	}
 
-	writel(csr6, ioaddr + DMA_CONTROL);
+	writel(csr6, ioaddr + DMA_CHAN_CONTROL(channel));
 }
 
 static void dwmac1000_dump_dma_regs(struct stmmac_priv *priv,
@@ -271,12 +273,12 @@ static int dwmac1000_get_hw_feature(void __iomem *ioaddr,
 static void dwmac1000_rx_watchdog(struct stmmac_priv *priv,
 				  void __iomem *ioaddr, u32 riwt, u32 queue)
 {
-	writel(riwt, ioaddr + DMA_RX_WATCHDOG);
+	writel(riwt, ioaddr + DMA_CHAN_RX_WATCHDOG(queue));
 }
 
 const struct stmmac_dma_ops dwmac1000_dma_ops = {
 	.reset = dwmac_dma_reset,
-	.init = dwmac1000_dma_init,
+	.init_chan = dwmac1000_dma_init_channel,
 	.init_rx_chan = dwmac1000_dma_init_rx,
 	.init_tx_chan = dwmac1000_dma_init_tx,
 	.axi = dwmac1000_dma_axi,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
index dea270f60cc3..f861babc06f9 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
@@ -19,7 +19,7 @@
 #include "dwmac_dma.h"
 
 static void dwmac100_dma_init(void __iomem *ioaddr,
-			      struct stmmac_dma_cfg *dma_cfg, int atds)
+			      struct stmmac_dma_cfg *dma_cfg)
 {
 	/* Enable Application Access by writing to DMA CSR0 */
 	writel(DMA_BUS_MODE_DEFAULT | (dma_cfg->pbl << DMA_BUS_MODE_PBL_SHIFT),
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
index 84d3a8551b03..e0165358c4ac 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
@@ -153,7 +153,7 @@ static void dwmac410_dma_init_channel(struct stmmac_priv *priv,
 }
 
 static void dwmac4_dma_init(void __iomem *ioaddr,
-			    struct stmmac_dma_cfg *dma_cfg, int atds)
+			    struct stmmac_dma_cfg *dma_cfg)
 {
 	u32 value = readl(ioaddr + DMA_SYS_BUS_MODE);
 
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
index 72672391675f..7c8b3ad739f7 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
@@ -22,6 +22,23 @@
 #define DMA_INTR_ENA		0x0000101c	/* Interrupt Enable */
 #define DMA_MISSED_FRAME_CTR	0x00001020	/* Missed Frame Counter */
 
+/* Following DMA defines are channels oriented */
+#define DMA_CHAN_BASE_OFFSET			0x100
+
+static inline u32 dma_chan_base_addr(u32 base, u32 chan)
+{
+	return base + chan * DMA_CHAN_BASE_OFFSET;
+}
+
+#define DMA_CHAN_XMT_POLL_DEMAND(chan)	dma_chan_base_addr(DMA_XMT_POLL_DEMAND, chan)
+#define DMA_CHAN_INTR_ENA(chan)		dma_chan_base_addr(DMA_INTR_ENA, chan)
+#define DMA_CHAN_CONTROL(chan)		dma_chan_base_addr(DMA_CONTROL, chan)
+#define DMA_CHAN_STATUS(chan)		dma_chan_base_addr(DMA_STATUS, chan)
+#define DMA_CHAN_BUS_MODE(chan)		dma_chan_base_addr(DMA_BUS_MODE, chan)
+#define DMA_CHAN_RCV_BASE_ADDR(chan)	dma_chan_base_addr(DMA_RCV_BASE_ADDR, chan)
+#define DMA_CHAN_TX_BASE_ADDR(chan)	dma_chan_base_addr(DMA_TX_BASE_ADDR, chan)
+#define DMA_CHAN_RX_WATCHDOG(chan)	dma_chan_base_addr(DMA_RX_WATCHDOG, chan)
+
 /* SW Reset */
 #define DMA_BUS_MODE_SFT_RESET	0x00000001	/* Software Reset */
 
@@ -152,7 +169,7 @@
 #define NUM_DWMAC1000_DMA_REGS	23
 #define NUM_DWMAC4_DMA_REGS	27
 
-void dwmac_enable_dma_transmission(void __iomem *ioaddr);
+void dwmac_enable_dma_transmission(void __iomem *ioaddr, u32 chan);
 void dwmac_enable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr,
 			  u32 chan, bool rx, bool tx);
 void dwmac_disable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr,
@@ -168,5 +185,4 @@ void dwmac_dma_stop_rx(struct stmmac_priv *priv, void __iomem *ioaddr,
 int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
 			struct stmmac_extra_stats *x, u32 chan, u32 dir);
 int dwmac_dma_reset(void __iomem *ioaddr);
-
 #endif /* __DWMAC_DMA_H__ */
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
index 85e18f9a22f9..7570f01838a8 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
@@ -28,65 +28,65 @@ int dwmac_dma_reset(void __iomem *ioaddr)
 }
 
 /* CSR1 enables the transmit DMA to check for new descriptor */
-void dwmac_enable_dma_transmission(void __iomem *ioaddr)
+void dwmac_enable_dma_transmission(void __iomem *ioaddr, u32 chan)
 {
-	writel(1, ioaddr + DMA_XMT_POLL_DEMAND);
+	writel(1, ioaddr + DMA_CHAN_XMT_POLL_DEMAND(chan));
 }
 
 void dwmac_enable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr,
 			  u32 chan, bool rx, bool tx)
 {
-	u32 value = readl(ioaddr + DMA_INTR_ENA);
+	u32 value = readl(ioaddr + DMA_CHAN_INTR_ENA(chan));
 
 	if (rx)
 		value |= DMA_INTR_DEFAULT_RX;
 	if (tx)
 		value |= DMA_INTR_DEFAULT_TX;
 
-	writel(value, ioaddr + DMA_INTR_ENA);
+	writel(value, ioaddr + DMA_CHAN_INTR_ENA(chan));
 }
 
 void dwmac_disable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr,
 			   u32 chan, bool rx, bool tx)
 {
-	u32 value = readl(ioaddr + DMA_INTR_ENA);
+	u32 value = readl(ioaddr + DMA_CHAN_INTR_ENA(chan));
 
 	if (rx)
 		value &= ~DMA_INTR_DEFAULT_RX;
 	if (tx)
 		value &= ~DMA_INTR_DEFAULT_TX;
 
-	writel(value, ioaddr + DMA_INTR_ENA);
+	writel(value, ioaddr + DMA_CHAN_INTR_ENA(chan));
 }
 
 void dwmac_dma_start_tx(struct stmmac_priv *priv, void __iomem *ioaddr,
 			u32 chan)
 {
-	u32 value = readl(ioaddr + DMA_CONTROL);
+	u32 value = readl(ioaddr + DMA_CHAN_CONTROL(chan));
 	value |= DMA_CONTROL_ST;
-	writel(value, ioaddr + DMA_CONTROL);
+	writel(value, ioaddr + DMA_CHAN_CONTROL(chan));
 }
 
 void dwmac_dma_stop_tx(struct stmmac_priv *priv, void __iomem *ioaddr, u32 chan)
 {
-	u32 value = readl(ioaddr + DMA_CONTROL);
+	u32 value = readl(ioaddr + DMA_CHAN_CONTROL(chan));
 	value &= ~DMA_CONTROL_ST;
-	writel(value, ioaddr + DMA_CONTROL);
+	writel(value, ioaddr + DMA_CHAN_CONTROL(chan));
 }
 
 void dwmac_dma_start_rx(struct stmmac_priv *priv, void __iomem *ioaddr,
 			u32 chan)
 {
-	u32 value = readl(ioaddr + DMA_CONTROL);
+	u32 value = readl(ioaddr + DMA_CHAN_CONTROL(chan));
 	value |= DMA_CONTROL_SR;
-	writel(value, ioaddr + DMA_CONTROL);
+	writel(value, ioaddr + DMA_CHAN_CONTROL(chan));
 }
 
 void dwmac_dma_stop_rx(struct stmmac_priv *priv, void __iomem *ioaddr, u32 chan)
 {
-	u32 value = readl(ioaddr + DMA_CONTROL);
+	u32 value = readl(ioaddr + DMA_CHAN_CONTROL(chan));
 	value &= ~DMA_CONTROL_SR;
-	writel(value, ioaddr + DMA_CONTROL);
+	writel(value, ioaddr + DMA_CHAN_CONTROL(chan));
 }
 
 #ifdef DWMAC_DMA_DEBUG
@@ -165,7 +165,7 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
 	struct stmmac_pcpu_stats *stats = this_cpu_ptr(priv->xstats.pcpu_stats);
 	int ret = 0;
 	/* read the status register (CSR5) */
-	u32 intr_status = readl(ioaddr + DMA_STATUS);
+	u32 intr_status = readl(ioaddr + DMA_CHAN_STATUS(chan));
 
 #ifdef DWMAC_DMA_DEBUG
 	/* Enable it to monitor DMA rx/tx status in case of critical problems */
@@ -235,7 +235,7 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
 		pr_warn("%s: unexpected status %08x\n", __func__, intr_status);
 
 	/* Clear the interrupt by writing a logic 1 to the CSR5[15-0] */
-	writel((intr_status & 0x1ffff), ioaddr + DMA_STATUS);
+	writel((intr_status & 0x7ffff), ioaddr + DMA_CHAN_STATUS(chan));
 
 	return ret;
 }
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
index dd2ab6185c40..7840bc403788 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
@@ -20,7 +20,7 @@ static int dwxgmac2_dma_reset(void __iomem *ioaddr)
 }
 
 static void dwxgmac2_dma_init(void __iomem *ioaddr,
-			      struct stmmac_dma_cfg *dma_cfg, int atds)
+			      struct stmmac_dma_cfg *dma_cfg)
 {
 	u32 value = readl(ioaddr + XGMAC_DMA_SYSBUS_MODE);
 
diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h
index 7be04b54738b..3b20fb7f3a61 100644
--- a/drivers/net/ethernet/stmicro/stmmac/hwif.h
+++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h
@@ -175,8 +175,7 @@ struct dma_features;
 struct stmmac_dma_ops {
 	/* DMA core initialization */
 	int (*reset)(void __iomem *ioaddr);
-	void (*init)(void __iomem *ioaddr, struct stmmac_dma_cfg *dma_cfg,
-		     int atds);
+	void (*init)(void __iomem *ioaddr, struct stmmac_dma_cfg *dma_cfg);
 	void (*init_chan)(struct stmmac_priv *priv, void __iomem *ioaddr,
 			  struct stmmac_dma_cfg *dma_cfg, u32 chan);
 	void (*init_rx_chan)(struct stmmac_priv *priv, void __iomem *ioaddr,
@@ -198,7 +197,7 @@ struct stmmac_dma_ops {
 	/* To track extra statistic (if supported) */
 	void (*dma_diagnostic_fr)(struct stmmac_extra_stats *x,
 				  void __iomem *ioaddr);
-	void (*enable_dma_transmission) (void __iomem *ioaddr);
+	void (*enable_dma_transmission)(void __iomem *ioaddr, u32 chan);
 	void (*enable_dma_irq)(struct stmmac_priv *priv, void __iomem *ioaddr,
 			       u32 chan, bool rx, bool tx);
 	void (*disable_dma_irq)(struct stmmac_priv *priv, void __iomem *ioaddr,
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index af16efeedf4a..45e28f9211df 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -2556,7 +2556,7 @@ static bool stmmac_xdp_xmit_zc(struct stmmac_priv *priv, u32 queue, u32 budget)
 				       true, priv->mode, true, true,
 				       xdp_desc.len);
 
-		stmmac_enable_dma_transmission(priv, priv->ioaddr);
+		stmmac_enable_dma_transmission(priv, priv->ioaddr, queue);
 
 		xsk_tx_metadata_to_compl(meta,
 					 &tx_q->tx_skbuff_dma[entry].xsk_meta);
@@ -3006,7 +3006,6 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv)
 	struct stmmac_rx_queue *rx_q;
 	struct stmmac_tx_queue *tx_q;
 	u32 chan = 0;
-	int atds = 0;
 	int ret = 0;
 
 	if (!priv->plat->dma_cfg || !priv->plat->dma_cfg->pbl) {
@@ -3015,7 +3014,7 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv)
 	}
 
 	if (priv->extend_desc && (priv->mode == STMMAC_RING_MODE))
-		atds = 1;
+		priv->plat->dma_cfg->atds = 1;
 
 	ret = stmmac_reset(priv, priv->ioaddr);
 	if (ret) {
@@ -3024,7 +3023,7 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv)
 	}
 
 	/* DMA Configuration */
-	stmmac_dma_init(priv, priv->ioaddr, priv->plat->dma_cfg, atds);
+	stmmac_dma_init(priv, priv->ioaddr, priv->plat->dma_cfg);
 
 	if (priv->plat->axi)
 		stmmac_axi(priv, priv->ioaddr, priv->plat->axi);
@@ -4753,7 +4752,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);
@@ -4980,7 +4979,7 @@ static int stmmac_xdp_xmit_xdpf(struct stmmac_priv *priv, int queue,
 		u64_stats_update_end(&txq_stats->q_syncp);
 	}
 
-	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;
diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
index dfa1828cd756..1b54b84a6785 100644
--- a/include/linux/stmmac.h
+++ b/include/linux/stmmac.h
@@ -100,6 +100,7 @@ struct stmmac_dma_cfg {
 	bool eame;
 	bool multi_msi_en;
 	bool dche;
+	bool atds;
 };
 
 #define AXI_BLEN	7
-- 
2.31.4


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

* [PATCH net-next v11 3/6] net: stmmac: dwmac-loongson: Use PCI_DEVICE_DATA() macro for device identification
  2024-04-12 11:28 [PATCH net-next v11 0/6] stmmac: Add Loongson platform support Yanteng Si
  2024-04-12 11:28 ` [PATCH net-next v11 1/6] net: stmmac: Move all PHYLINK MAC capabilities initializations to MAC-specific setup methods Yanteng Si
  2024-04-12 11:28 ` [PATCH net-next v11 2/6] net: stmmac: Add multi-channel support Yanteng Si
@ 2024-04-12 11:28 ` Yanteng Si
  2024-04-13  1:49   ` Jakub Kicinski
  2024-04-12 11:28 ` [PATCH net-next v11 4/6] net: stmmac: dwmac-loongson: Introduce GMAC setup Yanteng Si
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 36+ messages in thread
From: Yanteng Si @ 2024-04-12 11:28 UTC (permalink / raw)
  To: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	fancer.lancer
  Cc: Yanteng Si, Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang, siyanteng01

Just use PCI_DEVICE_DATA() macro for device identification,
No changes to function functionality.

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

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
index 9e40c28d453a..995c9bd144e0 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
@@ -213,7 +213,7 @@ static SIMPLE_DEV_PM_OPS(loongson_dwmac_pm_ops, loongson_dwmac_suspend,
 			 loongson_dwmac_resume);
 
 static const struct pci_device_id loongson_dwmac_id_table[] = {
-	{ PCI_VDEVICE(LOONGSON, 0x7a03) },
+	{ PCI_DEVICE_DATA(LOONGSON, GMAC, &loongson_gmac_pci_info) },
 	{}
 };
 MODULE_DEVICE_TABLE(pci, loongson_dwmac_id_table);
-- 
2.31.4


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

* [PATCH net-next v11 4/6] net: stmmac: dwmac-loongson: Introduce GMAC setup
  2024-04-12 11:28 [PATCH net-next v11 0/6] stmmac: Add Loongson platform support Yanteng Si
                   ` (2 preceding siblings ...)
  2024-04-12 11:28 ` [PATCH net-next v11 3/6] net: stmmac: dwmac-loongson: Use PCI_DEVICE_DATA() macro for device identification Yanteng Si
@ 2024-04-12 11:28 ` Yanteng Si
  2024-04-18 12:26   ` Serge Semin
  2024-04-22 10:17   ` Yanteng Si
  2024-04-12 11:28 ` [PATCH net-next v11 5/6] net: stmmac: dwmac-loongson: Add full PCI support Yanteng Si
                   ` (2 subsequent siblings)
  6 siblings, 2 replies; 36+ messages in thread
From: Yanteng Si @ 2024-04-12 11:28 UTC (permalink / raw)
  To: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	fancer.lancer
  Cc: Yanteng Si, Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang, siyanteng01

Based on IP core classification, loongson has two types of network
devices: GMAC and GNET. GMAC's ip_core id is 0x35/0x37, while GNET's
ip_core id is 0x37/0x10.

Device tables:

device    type    pci_id    ip_core
ls2k1000  gmac    7a03      0x35/0x37
ls7a1000  gmac    7a03      0x35/0x37
ls2k2000  gnet    7a13      0x10
ls7a2000  gnet    7a13      0x37

The ref/ptp clock of gmac is 125000000. gmac device only
has a MAC chip inside and needs an external PHY chip;

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

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
index 995c9bd144e0..ad19b4087974 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
@@ -9,7 +9,8 @@
 #include <linux/of_irq.h>
 #include "stmmac.h"
 
-static int loongson_default_data(struct plat_stmmacenet_data *plat)
+static void loongson_default_data(struct pci_dev *pdev,
+				  struct plat_stmmacenet_data *plat)
 {
 	plat->clk_csr = 2;	/* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */
 	plat->has_gmac = 1;
@@ -24,16 +25,18 @@ static int loongson_default_data(struct plat_stmmacenet_data *plat)
 	/* Set the maxmtu to a default of JUMBO_LEN */
 	plat->maxmtu = JUMBO_LEN;
 
-	/* Set default number of RX and TX queues to use */
-	plat->tx_queues_to_use = 1;
-	plat->rx_queues_to_use = 1;
-
 	/* Disable Priority config by default */
 	plat->tx_queues_cfg[0].use_prio = false;
 	plat->rx_queues_cfg[0].use_prio = false;
 
 	/* Disable RX queues routing by default */
 	plat->rx_queues_cfg[0].pkt_route = 0x0;
+}
+
+static int loongson_gmac_data(struct pci_dev *pdev,
+			      struct plat_stmmacenet_data *plat)
+{
+	loongson_default_data(pdev, plat);
 
 	/* Default to phy auto-detection */
 	plat->phy_addr = -1;
@@ -42,6 +45,12 @@ static int loongson_default_data(struct plat_stmmacenet_data *plat)
 	plat->dma_cfg->pblx8 = true;
 
 	plat->multicast_filter_bins = 256;
+	plat->clk_ref_rate = 125000000;
+	plat->clk_ptp_rate = 125000000;
+
+	plat->tx_queues_to_use = 1;
+	plat->rx_queues_to_use = 1;
+
 	return 0;
 }
 
@@ -114,7 +123,7 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
 
 	pci_set_master(pdev);
 
-	loongson_default_data(plat);
+	loongson_gmac_data(pdev, plat);
 	pci_enable_msi(pdev);
 	memset(&res, 0, sizeof(res));
 	res.addr = pcim_iomap_table(pdev)[0];
-- 
2.31.4


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

* [PATCH net-next v11 5/6] net: stmmac: dwmac-loongson: Add full PCI support
  2024-04-12 11:28 [PATCH net-next v11 0/6] stmmac: Add Loongson platform support Yanteng Si
                   ` (3 preceding siblings ...)
  2024-04-12 11:28 ` [PATCH net-next v11 4/6] net: stmmac: dwmac-loongson: Introduce GMAC setup Yanteng Si
@ 2024-04-12 11:28 ` Yanteng Si
  2024-04-18 13:08   ` Serge Semin
  2024-04-12 11:28 ` [PATCH net-next v11 6/6] net: stmmac: dwmac-loongson: Add Loongson GNET support Yanteng Si
  2024-04-12 18:34 ` [PATCH net-next v11 0/6] stmmac: Add Loongson platform support Serge Semin
  6 siblings, 1 reply; 36+ messages in thread
From: Yanteng Si @ 2024-04-12 11:28 UTC (permalink / raw)
  To: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	fancer.lancer
  Cc: Yanteng Si, Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang, siyanteng01

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

Others:
LS2K is a SoC and LS7A is a bridge chip. In the current driving state,
they are both gmac and phy_interface is RGMII.

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

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
index ad19b4087974..69078eb1f923 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
@@ -9,9 +9,19 @@
 #include <linux/of_irq.h>
 #include "stmmac.h"
 
+#define PCI_DEVICE_ID_LOONGSON_GMAC	0x7a03
+
+struct stmmac_pci_info {
+	int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat);
+};
+
 static void loongson_default_data(struct pci_dev *pdev,
 				  struct plat_stmmacenet_data *plat)
 {
+	/* Get bus_id, this can be overloaded later */
+	plat->bus_id = (pci_domain_nr(pdev->bus) << 16) |
+		       PCI_DEVID(pdev->bus->number, pdev->devfn);
+
 	plat->clk_csr = 2;	/* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */
 	plat->has_gmac = 1;
 	plat->force_sf_dma_mode = 1;
@@ -40,6 +50,7 @@ static int loongson_gmac_data(struct pci_dev *pdev,
 
 	/* Default to phy auto-detection */
 	plat->phy_addr = -1;
+	plat->phy_interface = PHY_INTERFACE_MODE_RGMII_ID;
 
 	plat->dma_cfg->pbl = 32;
 	plat->dma_cfg->pblx8 = true;
@@ -54,19 +65,17 @@ static int loongson_gmac_data(struct pci_dev *pdev,
 	return 0;
 }
 
+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)
 {
 	struct plat_stmmacenet_data *plat;
+	int ret, i, bus_id, phy_mode;
+	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;
-	}
 
 	plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL);
 	if (!plat)
@@ -78,12 +87,6 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
 	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->needs_reset = true;
-	}
-
 	plat->dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*plat->dma_cfg), GFP_KERNEL);
 	if (!plat->dma_cfg) {
 		ret = -ENOMEM;
@@ -107,10 +110,6 @@ 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);
-
 	phy_mode = device_get_phy_mode(&pdev->dev);
 	if (phy_mode < 0) {
 		dev_err(&pdev->dev, "phy_mode not found\n");
@@ -123,30 +122,56 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
 
 	pci_set_master(pdev);
 
-	loongson_gmac_data(pdev, plat);
-	pci_enable_msi(pdev);
-	memset(&res, 0, sizeof(res));
-	res.addr = pcim_iomap_table(pdev)[0];
-
-	res.irq = of_irq_get_byname(np, "macirq");
-	if (res.irq < 0) {
-		dev_err(&pdev->dev, "IRQ macirq not found\n");
-		ret = -ENODEV;
-		goto err_disable_msi;
-	}
+	info = (struct stmmac_pci_info *)id->driver_data;
+	ret = info->setup(pdev, plat);
+	if (ret)
+		goto err_disable_device;
 
-	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;
+	if (np) {
+		plat->mdio_node = of_get_child_by_name(np, "mdio");
+		if (plat->mdio_node) {
+			dev_info(&pdev->dev, "Found MDIO subnode\n");
+			plat->mdio_bus_data->needs_reset = true;
+		}
+
+		bus_id = of_alias_get_id(np, "ethernet");
+		if (bus_id >= 0)
+			plat->bus_id = bus_id;
+
+		phy_mode = device_get_phy_mode(&pdev->dev);
+		if (phy_mode < 0) {
+			dev_err(&pdev->dev, "phy_mode not found\n");
+			ret = phy_mode;
+			goto err_disable_device;
+		}
+		plat->phy_interface = phy_mode;
+
+		res.irq = of_irq_get_byname(np, "macirq");
+		if (res.irq < 0) {
+			dev_err(&pdev->dev, "IRQ macirq not found\n");
+			ret = -ENODEV;
+			goto err_disable_msi;
+		}
+
+		res.wol_irq = of_irq_get_byname(np, "eth_wake_irq");
+		if (res.wol_irq < 0) {
+			dev_info(&pdev->dev, "IRQ eth_wake_irq not found, using macirq\n");
+			res.wol_irq = res.irq;
+		}
+
+		res.lpi_irq = of_irq_get_byname(np, "eth_lpi");
+		if (res.lpi_irq < 0) {
+			dev_err(&pdev->dev, "IRQ eth_lpi not found\n");
+			ret = -ENODEV;
+			goto err_disable_msi;
+		}
+	} else {
+		res.irq = pdev->irq;
 	}
 
-	res.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;
-	}
+	pci_enable_msi(pdev);
+	memset(&res, 0, sizeof(res));
+	res.addr = pcim_iomap_table(pdev)[0];
 
 	ret = stmmac_dvr_probe(&pdev->dev, plat, &res);
 	if (ret)
-- 
2.31.4


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

* [PATCH net-next v11 6/6] net: stmmac: dwmac-loongson: Add Loongson GNET support
  2024-04-12 11:28 [PATCH net-next v11 0/6] stmmac: Add Loongson platform support Yanteng Si
                   ` (4 preceding siblings ...)
  2024-04-12 11:28 ` [PATCH net-next v11 5/6] net: stmmac: dwmac-loongson: Add full PCI support Yanteng Si
@ 2024-04-12 11:28 ` Yanteng Si
  2024-04-18 14:01   ` Serge Semin
  2024-04-24 13:37   ` Huacai Chen
  2024-04-12 18:34 ` [PATCH net-next v11 0/6] stmmac: Add Loongson platform support Serge Semin
  6 siblings, 2 replies; 36+ messages in thread
From: Yanteng Si @ 2024-04-12 11:28 UTC (permalink / raw)
  To: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	fancer.lancer
  Cc: Yanteng Si, Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang, siyanteng01

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

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

     Name              Tx          Rx

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

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

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

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

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

GNET features:

 Speeds: 10/100/1000Mbps
 DMA-descriptors type: normal and enhanced
 L3/L4 filters availability: support
 VLAN hash table filter: support
 PHY-interface: GMII
 Remote Wake-up support: support
 Mac Management Counters (MMC): support
 DMA chennel number: 0x10 device is 8 and 0x37 device is 1

Others:

 GNET integrates both MAC and PHY chips inside.
 GNET device: LS2K2000, LS7A2000, the chip connection between the mac and
             phy of these devices is not normal and requires two rounds of
             negotiation; LS7A2000 does not support half-duplex and
             multi-channel;

             To enable multi-channel on LS2K2000, you need to turn off
             hardware checksum.

**Note**: Currently, only the LS2K2000's IP core is 0x10, while the IP
cores of other devices are 0x37.

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

diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index 9cd62b2110a1..6777dc997e9f 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -29,6 +29,7 @@
 /* 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
@@ -258,6 +259,7 @@ struct stmmac_safety_stats {
 #define CSR_F_300M	300000000
 
 #define	MAC_CSR_H_FRQ_MASK	0x20
+#define	MAC_CTRL_PORT_SELECT_10_100	BIT(15)
 
 #define HASH_TABLE_SIZE 64
 #define PAUSE_TIME 0xffff
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
index 69078eb1f923..4edfbb4fcb64 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
@@ -8,8 +8,70 @@
 #include <linux/device.h>
 #include <linux/of_irq.h>
 #include "stmmac.h"
+#include "dwmac_dma.h"
+#include "dwmac1000.h"
+
+/* Normal Loongson Tx Summary */
+#define DMA_INTR_ENA_NIE_TX_LOONGSON	0x00040000
+/* Normal Loongson Rx Summary */
+#define DMA_INTR_ENA_NIE_RX_LOONGSON	0x00020000
+
+#define DMA_INTR_NORMAL_LOONGSON	(DMA_INTR_ENA_NIE_TX_LOONGSON | \
+					 DMA_INTR_ENA_NIE_RX_LOONGSON | \
+					 DMA_INTR_ENA_RIE | DMA_INTR_ENA_TIE)
+
+/* Abnormal Loongson Tx Summary */
+#define DMA_INTR_ENA_AIE_TX_LOONGSON	0x00010000
+/* Abnormal Loongson Rx Summary */
+#define DMA_INTR_ENA_AIE_RX_LOONGSON	0x00008000
+
+#define DMA_INTR_ABNORMAL_LOONGSON	(DMA_INTR_ENA_AIE_TX_LOONGSON | \
+					 DMA_INTR_ENA_AIE_RX_LOONGSON | \
+					 DMA_INTR_ENA_FBE | DMA_INTR_ENA_UNE)
+
+#define DMA_INTR_DEFAULT_MASK_LOONGSON	(DMA_INTR_NORMAL_LOONGSON | \
+					 DMA_INTR_ABNORMAL_LOONGSON)
+
+/* Normal Loongson Tx Interrupt Summary */
+#define DMA_STATUS_NIS_TX_LOONGSON	0x00040000
+/* Normal Loongson Rx Interrupt Summary */
+#define DMA_STATUS_NIS_RX_LOONGSON	0x00020000
+
+/* Abnormal Loongson Tx Interrupt Summary */
+#define DMA_STATUS_AIS_TX_LOONGSON	0x00010000
+/* Abnormal Loongson Rx Interrupt Summary */
+#define DMA_STATUS_AIS_RX_LOONGSON	0x00008000
+
+/* Fatal Loongson Tx Bus Error Interrupt */
+#define DMA_STATUS_FBI_TX_LOONGSON	0x00002000
+/* Fatal Loongson Rx Bus Error Interrupt */
+#define DMA_STATUS_FBI_RX_LOONGSON	0x00001000
+
+#define DMA_STATUS_MSK_COMMON_LOONGSON	(DMA_STATUS_NIS_TX_LOONGSON | \
+					 DMA_STATUS_NIS_RX_LOONGSON | \
+					 DMA_STATUS_AIS_TX_LOONGSON | \
+					 DMA_STATUS_AIS_RX_LOONGSON | \
+					 DMA_STATUS_FBI_TX_LOONGSON | \
+					 DMA_STATUS_FBI_RX_LOONGSON)
+
+#define DMA_STATUS_MSK_RX_LOONGSON	(DMA_STATUS_ERI | DMA_STATUS_RWT | \
+					 DMA_STATUS_RPS | DMA_STATUS_RU  | \
+					 DMA_STATUS_RI  | DMA_STATUS_OVF | \
+					 DMA_STATUS_MSK_COMMON_LOONGSON)
+
+#define DMA_STATUS_MSK_TX_LOONGSON	(DMA_STATUS_ETI | DMA_STATUS_UNF | \
+					 DMA_STATUS_TJT | DMA_STATUS_TU  | \
+					 DMA_STATUS_TPS | DMA_STATUS_TI  | \
+					 DMA_STATUS_MSK_COMMON_LOONGSON)
 
 #define PCI_DEVICE_ID_LOONGSON_GMAC	0x7a03
+#define PCI_DEVICE_ID_LOONGSON_GNET	0x7a13
+#define LOONGSON_DWMAC_CORE_1_00	0x10	/* Loongson custom IP */
+#define CHANNEL_NUM			8
+
+struct loongson_data {
+	struct device *dev;
+};
 
 struct stmmac_pci_info {
 	int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat);
@@ -56,6 +117,8 @@ static int loongson_gmac_data(struct pci_dev *pdev,
 	plat->dma_cfg->pblx8 = true;
 
 	plat->multicast_filter_bins = 256;
+	plat->mdio_bus_data->phy_mask = 0;
+
 	plat->clk_ref_rate = 125000000;
 	plat->clk_ptp_rate = 125000000;
 
@@ -69,13 +132,342 @@ 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)
+static void loongson_gnet_dma_init_channel(struct stmmac_priv *priv,
+					   void __iomem *ioaddr,
+					   struct stmmac_dma_cfg *dma_cfg,
+					   u32 chan)
+{
+	int txpbl = dma_cfg->txpbl ?: dma_cfg->pbl;
+	int rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl;
+	u32 value;
+
+	/* common channel control register config */
+	value = readl(ioaddr + DMA_CHAN_BUS_MODE(chan));
+
+	/* Set the DMA PBL (Programmable Burst Length) mode.
+	 *
+	 * Note: before stmmac core 3.50 this mode bit was 4xPBL, and
+	 * post 3.5 mode bit acts as 8*PBL.
+	 */
+	if (dma_cfg->pblx8)
+		value |= DMA_BUS_MODE_MAXPBL;
+
+	value |= DMA_BUS_MODE_USP;
+	value &= ~(DMA_BUS_MODE_PBL_MASK | DMA_BUS_MODE_RPBL_MASK);
+	value |= (txpbl << DMA_BUS_MODE_PBL_SHIFT);
+	value |= (rxpbl << DMA_BUS_MODE_RPBL_SHIFT);
+
+	/* Set the Fixed burst mode */
+	if (dma_cfg->fixed_burst)
+		value |= DMA_BUS_MODE_FB;
+
+	/* Mixed Burst has no effect when fb is set */
+	if (dma_cfg->mixed_burst)
+		value |= DMA_BUS_MODE_MB;
+
+	if (dma_cfg->atds)
+		value |= DMA_BUS_MODE_ATDS;
+
+	if (dma_cfg->aal)
+		value |= DMA_BUS_MODE_AAL;
+
+	writel(value, ioaddr + DMA_CHAN_BUS_MODE(chan));
+
+	/* Mask interrupts by writing to CSR7 */
+	writel(DMA_INTR_DEFAULT_MASK_LOONGSON, ioaddr +
+	       DMA_CHAN_INTR_ENA(chan));
+}
+
+static int loongson_gnet_dma_interrupt(struct stmmac_priv *priv,
+				       void __iomem *ioaddr,
+				       struct stmmac_extra_stats *x,
+				       u32 chan, u32 dir)
+{
+	struct stmmac_pcpu_stats *stats = this_cpu_ptr(priv->xstats.pcpu_stats);
+	u32 abnor_intr_status;
+	u32 nor_intr_status;
+	u32 fb_intr_status;
+	u32 intr_status;
+	int ret = 0;
+
+	/* read the status register (CSR5) */
+	intr_status = readl(ioaddr + DMA_CHAN_STATUS(chan));
+
+	if (dir == DMA_DIR_RX)
+		intr_status &= DMA_STATUS_MSK_RX_LOONGSON;
+	else if (dir == DMA_DIR_TX)
+		intr_status &= DMA_STATUS_MSK_TX_LOONGSON;
+
+	nor_intr_status = intr_status & (DMA_STATUS_NIS_TX_LOONGSON |
+		DMA_STATUS_NIS_RX_LOONGSON);
+	abnor_intr_status = intr_status & (DMA_STATUS_AIS_TX_LOONGSON |
+		DMA_STATUS_AIS_RX_LOONGSON);
+	fb_intr_status = intr_status & (DMA_STATUS_FBI_TX_LOONGSON |
+		DMA_STATUS_FBI_RX_LOONGSON);
+
+	/* ABNORMAL interrupts */
+	if (unlikely(abnor_intr_status)) {
+		if (unlikely(intr_status & DMA_STATUS_UNF)) {
+			ret = tx_hard_error_bump_tc;
+			x->tx_undeflow_irq++;
+		}
+		if (unlikely(intr_status & DMA_STATUS_TJT))
+			x->tx_jabber_irq++;
+		if (unlikely(intr_status & DMA_STATUS_OVF))
+			x->rx_overflow_irq++;
+		if (unlikely(intr_status & DMA_STATUS_RU))
+			x->rx_buf_unav_irq++;
+		if (unlikely(intr_status & DMA_STATUS_RPS))
+			x->rx_process_stopped_irq++;
+		if (unlikely(intr_status & DMA_STATUS_RWT))
+			x->rx_watchdog_irq++;
+		if (unlikely(intr_status & DMA_STATUS_ETI))
+			x->tx_early_irq++;
+		if (unlikely(intr_status & DMA_STATUS_TPS)) {
+			x->tx_process_stopped_irq++;
+			ret = tx_hard_error;
+		}
+		if (unlikely(fb_intr_status)) {
+			x->fatal_bus_error_irq++;
+			ret = tx_hard_error;
+		}
+	}
+	/* TX/RX NORMAL interrupts */
+	if (likely(nor_intr_status)) {
+		if (likely(intr_status & DMA_STATUS_RI)) {
+			u32 value = readl(ioaddr + DMA_INTR_ENA);
+			/* to schedule NAPI on real RIE event. */
+			if (likely(value & DMA_INTR_ENA_RIE)) {
+				u64_stats_update_begin(&stats->syncp);
+				u64_stats_inc(&stats->rx_normal_irq_n[chan]);
+				u64_stats_update_end(&stats->syncp);
+				ret |= handle_rx;
+			}
+		}
+		if (likely(intr_status & DMA_STATUS_TI)) {
+			u64_stats_update_begin(&stats->syncp);
+			u64_stats_inc(&stats->tx_normal_irq_n[chan]);
+			u64_stats_update_end(&stats->syncp);
+			ret |= handle_tx;
+		}
+		if (unlikely(intr_status & DMA_STATUS_ERI))
+			x->rx_early_irq++;
+	}
+	/* Optional hardware blocks, interrupts should be disabled */
+	if (unlikely(intr_status &
+		     (DMA_STATUS_GPI | DMA_STATUS_GMI | DMA_STATUS_GLI)))
+		pr_warn("%s: unexpected status %08x\n", __func__, intr_status);
+
+	/* Clear the interrupt by writing a logic 1 to the CSR5[15-0] */
+	writel((intr_status & 0x7ffff), ioaddr + DMA_CHAN_STATUS(chan));
+
+	return ret;
+}
+
+static void loongson_gnet_fix_speed(void *priv, unsigned int speed,
+				    unsigned int mode)
+{
+	struct loongson_data *ld = (struct loongson_data *)priv;
+	struct net_device *ndev = dev_get_drvdata(ld->dev);
+	struct stmmac_priv *ptr = netdev_priv(ndev);
+
+	/* The controller and PHY don't work well together.
+	 * We need to use the PS bit to check if the controller's status
+	 * is correct and reset PHY if necessary.
+	 * MAC_CTRL_REG.15 is defined by the GMAC_CONTROL_PS macro.
+	 */
+	if (speed == SPEED_1000) {
+		if (readl(ptr->ioaddr + MAC_CTRL_REG) &
+		    MAC_CTRL_PORT_SELECT_10_100)
+			/* Word around hardware bug, restart autoneg */
+			phy_restart_aneg(ndev->phydev);
+	}
+}
+
+static int loongson_gnet_data(struct pci_dev *pdev,
+			      struct plat_stmmacenet_data *plat)
+{
+	loongson_default_data(pdev, plat);
+
+	plat->phy_addr = -1;
+	plat->phy_interface = PHY_INTERFACE_MODE_GMII;
+
+	plat->dma_cfg->pbl = 32;
+	plat->dma_cfg->pblx8 = true;
+
+	plat->multicast_filter_bins = 256;
+	plat->mdio_bus_data->phy_mask = ~(u32)BIT(2);
+
+	plat->clk_ref_rate = 125000000;
+	plat->clk_ptp_rate = 125000000;
+
+	plat->fix_mac_speed = loongson_gnet_fix_speed;
+
+	return 0;
+}
+
+static struct stmmac_pci_info loongson_gnet_pci_info = {
+	.setup = loongson_gnet_data,
+};
+
+static int loongson_dwmac_config_legacy(struct pci_dev *pdev,
+					struct plat_stmmacenet_data *plat,
+					struct stmmac_resources *res,
+					struct device_node *np)
+{
+	if (np) {
+		res->irq = of_irq_get_byname(np, "macirq");
+		if (res->irq < 0) {
+			dev_err(&pdev->dev, "IRQ macirq not found\n");
+			return -ENODEV;
+		}
+
+		res->wol_irq = of_irq_get_byname(np, "eth_wake_irq");
+		if (res->wol_irq < 0) {
+			dev_info(&pdev->dev,
+				 "IRQ eth_wake_irq not found, using macirq\n");
+			res->wol_irq = res->irq;
+		}
+
+		res->lpi_irq = of_irq_get_byname(np, "eth_lpi");
+		if (res->lpi_irq < 0) {
+			dev_err(&pdev->dev, "IRQ eth_lpi not found\n");
+			return -ENODEV;
+		}
+	} else {
+		res->irq = pdev->irq;
+		res->wol_irq = res->irq;
+	}
+
+	return 0;
+}
+
+static int loongson_dwmac_config_msi(struct pci_dev *pdev,
+				     struct plat_stmmacenet_data *plat,
+				     struct stmmac_resources *res,
+				     struct device_node *np)
+{
+	int i, ret, vecs;
+
+	vecs = roundup_pow_of_two(CHANNEL_NUM * 2 + 1);
+	ret = pci_alloc_irq_vectors(pdev, vecs, vecs, PCI_IRQ_MSI);
+	if (ret < 0) {
+		dev_info(&pdev->dev,
+			 "MSI enable failed, Fallback to legacy interrupt\n");
+		return loongson_dwmac_config_legacy(pdev, plat, res, np);
+	}
+
+	res->irq = pci_irq_vector(pdev, 0);
+	res->wol_irq = 0;
+
+	/* INT NAME | MAC | CH7 rx | CH7 tx | ... | CH0 rx | CH0 tx |
+	 * --------- ----- -------- --------  ...  -------- --------
+	 * IRQ NUM  |  0  |   1    |   2    | ... |   15   |   16   |
+	 */
+	for (i = 0; i < CHANNEL_NUM; i++) {
+		res->rx_irq[CHANNEL_NUM - 1 - i] =
+			pci_irq_vector(pdev, 1 + i * 2);
+		res->tx_irq[CHANNEL_NUM - 1 - i] =
+			pci_irq_vector(pdev, 2 + i * 2);
+	}
+
+	plat->flags |= STMMAC_FLAG_MULTI_MSI_EN;
+
+	return 0;
+}
+
+static struct mac_device_info *loongson_dwmac_setup(void *apriv)
+{
+	struct stmmac_priv *priv = apriv;
+	struct stmmac_resources res;
+	struct mac_device_info *mac;
+	struct stmmac_dma_ops *dma;
+	struct pci_dev *pdev;
+	u32 loongson_gmac;
+
+	memset(&res, 0, sizeof(res));
+	pdev = to_pci_dev(priv->device);
+	res.addr = pcim_iomap_table(pdev)[0];
+	loongson_gmac = readl(res.addr + GMAC_VERSION) & 0xff;
+
+	mac = devm_kzalloc(priv->device, sizeof(*mac), GFP_KERNEL);
+	if (!mac)
+		return NULL;
+
+	dma = devm_kzalloc(priv->device, sizeof(*dma), GFP_KERNEL);
+	if (!dma)
+		return NULL;
+
+	/* The original IP-core version is 0x37 in all Loongson GNET
+	 * (ls2k2000 and ls7a2000), but the GNET HW designers have changed the
+	 * GMAC_VERSION.SNPSVER field to the custom 0x10 value on the Loongson
+	 * ls2k2000 MAC to emphasize the differences: multiple DMA-channels,
+	 * AV feature and GMAC_INT_STATUS CSR flags layout. Get back the
+	 * original value so the correct HW-interface would be selected.
+	 */
+	if (loongson_gmac == LOONGSON_DWMAC_CORE_1_00) {
+		priv->synopsys_id = DWMAC_CORE_3_70;
+		*dma = dwmac1000_dma_ops;
+		dma->init_chan = loongson_gnet_dma_init_channel;
+		dma->dma_interrupt = loongson_gnet_dma_interrupt;
+		mac->dma = dma;
+	}
+
+	mac->mac = &dwmac1000_ops;
+	priv->dev->priv_flags |= IFF_UNICAST_FLT;
+
+	/* Pre-initialize the respective "mac" fields as it's done in
+	 * dwmac1000_setup()
+	 */
+	mac->pcsr = priv->ioaddr;
+	mac->multicast_filter_bins = priv->plat->multicast_filter_bins;
+	mac->unicast_filter_entries = priv->plat->unicast_filter_entries;
+	mac->mcast_bits_log2 = 0;
+
+	if (mac->multicast_filter_bins)
+		mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins);
+
+	/* The GMAC devices with PCI ID 0x7a03 does not support any pause mode.
+	 * The GNET devices without CORE ID 0x10 does not support half-duplex.
+	 */
+	if (pdev->device == PCI_DEVICE_ID_LOONGSON_GMAC) {
+		mac->link.caps = MAC_10 | MAC_100 | MAC_1000;
+	} else {
+		if (loongson_gmac == LOONGSON_DWMAC_CORE_1_00)
+			mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
+					 MAC_10 | MAC_100 | MAC_1000;
+		else
+			mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
+					 MAC_10FD | MAC_100FD | MAC_1000FD;
+	}
+
+	mac->link.duplex = GMAC_CONTROL_DM;
+	mac->link.speed10 = GMAC_CONTROL_PS;
+	mac->link.speed100 = GMAC_CONTROL_PS | GMAC_CONTROL_FES;
+	mac->link.speed1000 = 0;
+	mac->link.speed_mask = GMAC_CONTROL_PS | GMAC_CONTROL_FES;
+	mac->mii.addr = GMAC_MII_ADDR;
+	mac->mii.data = GMAC_MII_DATA;
+	mac->mii.addr_shift = 11;
+	mac->mii.addr_mask = 0x0000F800;
+	mac->mii.reg_shift = 6;
+	mac->mii.reg_mask = 0x000007C0;
+	mac->mii.clk_csr_shift = 2;
+	mac->mii.clk_csr_mask = GENMASK(5, 2);
+
+	return mac;
+}
+
+static int loongson_dwmac_probe(struct pci_dev *pdev,
+				const struct pci_device_id *id)
 {
 	struct plat_stmmacenet_data *plat;
 	int ret, i, bus_id, phy_mode;
 	struct stmmac_pci_info *info;
 	struct stmmac_resources res;
+	struct loongson_data *ld;
 	struct device_node *np;
+	u32 loongson_gmac;
 
 	plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL);
 	if (!plat)
@@ -88,10 +482,14 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
 		return -ENOMEM;
 
 	plat->dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*plat->dma_cfg), GFP_KERNEL);
-	if (!plat->dma_cfg) {
-		ret = -ENOMEM;
-		goto err_put_node;
-	}
+	if (!plat->dma_cfg)
+		return -ENOMEM;
+
+	ld = devm_kzalloc(&pdev->dev, sizeof(*ld), GFP_KERNEL);
+	if (!ld)
+		return -ENOMEM;
+
+	np = dev_of_node(&pdev->dev);
 
 	/* Enable pci device */
 	ret = pci_enable_device(pdev);
@@ -110,14 +508,6 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
 		break;
 	}
 
-	phy_mode = device_get_phy_mode(&pdev->dev);
-	if (phy_mode < 0) {
-		dev_err(&pdev->dev, "phy_mode not found\n");
-		ret = phy_mode;
-		goto err_disable_device;
-	}
-
-	plat->phy_interface = phy_mode;
 	plat->mac_interface = PHY_INTERFACE_MODE_GMII;
 
 	pci_set_master(pdev);
@@ -133,7 +523,6 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
 			dev_info(&pdev->dev, "Found MDIO subnode\n");
 			plat->mdio_bus_data->needs_reset = true;
 		}
-
 		bus_id = of_alias_get_id(np, "ethernet");
 		if (bus_id >= 0)
 			plat->bus_id = bus_id;
@@ -145,42 +534,49 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
 			goto err_disable_device;
 		}
 		plat->phy_interface = phy_mode;
+	}
 
-		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;
-		}
+	plat->bsp_priv = ld;
+	plat->setup = loongson_dwmac_setup;
+	ld->dev = &pdev->dev;
 
-		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;
-		}
+	memset(&res, 0, sizeof(res));
+	res.addr = pcim_iomap_table(pdev)[0];
+	loongson_gmac = readl(res.addr + GMAC_VERSION) & 0xff;
 
-		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;
+	switch (loongson_gmac) {
+	case LOONGSON_DWMAC_CORE_1_00:
+		plat->rx_queues_to_use = CHANNEL_NUM;
+		plat->tx_queues_to_use = CHANNEL_NUM;
+
+		/* Only channel 0 supports checksum,
+		 * so turn off checksum to enable multiple channels.
+		 */
+		for (i = 1; i < CHANNEL_NUM; i++)
+			plat->tx_queues_cfg[i].coe_unsupported = 1;
+
+		ret = loongson_dwmac_config_msi(pdev, plat, &res, np);
+		break;
+	default:	/* 0x35 device and 0x37 device. */
+		plat->tx_queues_to_use = 1;
+		plat->rx_queues_to_use = 1;
+		ret = loongson_dwmac_config_legacy(pdev, plat, &res, np);
+		break;
 	}
 
-	pci_enable_msi(pdev);
-	memset(&res, 0, sizeof(res));
-	res.addr = pcim_iomap_table(pdev)[0];
+	/* GNET devices with dev revision 0x00 do not support manually
+	 * setting the speed to 1000.
+	 */
+	if (pdev->device == PCI_DEVICE_ID_LOONGSON_GNET &&
+	    pdev->revision == 0x00)
+		plat->flags |= STMMAC_FLAG_DISABLE_FORCE_1000;
 
 	ret = stmmac_dvr_probe(&pdev->dev, plat, &res);
 	if (ret)
-		goto err_disable_msi;
+		goto err_disable_device;
 
 	return ret;
 
-err_disable_msi:
-	pci_disable_msi(pdev);
 err_disable_device:
 	pci_disable_device(pdev);
 err_put_node:
@@ -248,6 +644,7 @@ static SIMPLE_DEV_PM_OPS(loongson_dwmac_pm_ops, loongson_dwmac_suspend,
 
 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);
@@ -266,4 +663,5 @@ module_pci_driver(loongson_dwmac_driver);
 
 MODULE_DESCRIPTION("Loongson DWMAC PCI driver");
 MODULE_AUTHOR("Qing Zhang <zhangqing@loongson.cn>");
+MODULE_AUTHOR("Yanteng Si <siyanteng@loongson.cn>");
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
index f161ec9ac490..66c0c22908b1 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
@@ -296,3 +296,4 @@ const struct stmmac_dma_ops dwmac1000_dma_ops = {
 	.get_hw_feature = dwmac1000_get_hw_feature,
 	.rx_watchdog = dwmac1000_rx_watchdog,
 };
+EXPORT_SYMBOL_GPL(dwmac1000_dma_ops);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
index e1537a57815f..e94faa72f30e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
@@ -420,6 +420,12 @@ stmmac_ethtool_set_link_ksettings(struct net_device *dev,
 		return 0;
 	}
 
+	if (priv->plat->flags & STMMAC_FLAG_DISABLE_FORCE_1000) {
+		if (cmd->base.speed == SPEED_1000 &&
+		    cmd->base.autoneg != AUTONEG_ENABLE)
+			return -EOPNOTSUPP;
+	}
+
 	return phylink_ethtool_ksettings_set(priv->phylink, cmd);
 }
 
diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
index 1b54b84a6785..c5d3d0ddb6f8 100644
--- a/include/linux/stmmac.h
+++ b/include/linux/stmmac.h
@@ -223,6 +223,7 @@ struct dwmac4_addrs {
 #define STMMAC_FLAG_RX_CLK_RUNS_IN_LPI		BIT(10)
 #define STMMAC_FLAG_EN_TX_LPI_CLOCKGATING	BIT(11)
 #define STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY	BIT(12)
+#define STMMAC_FLAG_DISABLE_FORCE_1000		BIT(13)
 
 struct plat_stmmacenet_data {
 	int bus_id;
-- 
2.31.4


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

* Re: [PATCH net-next v11 1/6] net: stmmac: Move all PHYLINK MAC capabilities initializations to MAC-specific setup methods
  2024-04-12 11:28 ` [PATCH net-next v11 1/6] net: stmmac: Move all PHYLINK MAC capabilities initializations to MAC-specific setup methods Yanteng Si
@ 2024-04-12 18:32   ` Serge Semin
  2024-04-18  5:02     ` Yanteng Si
  0 siblings, 1 reply; 36+ messages in thread
From: Serge Semin @ 2024-04-12 18:32 UTC (permalink / raw)
  To: Yanteng Si, Andrew Lunn, Russell King, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni
  Cc: hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang, siyanteng01

Hi Yanteng

On Fri, Apr 12, 2024 at 07:28:06PM +0800, Yanteng Si wrote:
> From: Serge Semin <fancer.lancer@gmail.com>
> 
> Seeing the Tx-queues-based constraint is DW QoS Eth-specific there is
> such reason. It might be better to move the selective Half-duplex
> mode disabling to the MAC-specific callback.
> 
> But there are a better option to implement the MAC capabilities
> detection procedure. Let's see what MAC-capabilities can be currently
> specified based on the DW MAC IP-core versions:
> 
> DW MAC100: MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
> 	   MAC_10 | MAC_100
> 
> DW GMAC: MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
>          MAC_10 | MAC_100 | MAC_1000
> 
> DW QoS Eth: MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
>             MAC_10 | MAC_100 | MAC_1000 | MAC_2500FD
> but if the amount of the active Tx queues is > 1, then:
> 	   MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
>            MAC_10FD | MAC_100FD | MAC_1000FD | MAC_2500FD
> 
> DW XGMAC: MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
>           MAC_1000FD | MAC_2500FD | MAC_5000FD |
>           MAC_10000FD | MAC_25000FD |
>           MAC_40000FD | MAC_50000FD |
>           MAC_100000FD
> 
> As you can see there are only two common capabilities:
> MAC_ASYM_PAUSE | MAC_SYM_PAUSE. Seeing the flow-control is implemented
> as a callback for each MAC IP-core (see dwmac100_flow_ctrl(),
> dwmac1000_flow_ctrl(), sun8i_dwmac_flow_ctrl(), etc) we can freely
> move all the PHYLINK MAC capabilities initializations to the
> MAC-specific setup methods.
> 
> After that the only IP-core which requires the capabilities update will
> be DW QoS Eth. So the Tx-queue-based capabilities update can be moved
> there and the rest of the xgmac_phylink_get_caps() callback can be
> dropped.
> 
> We can go further. Instead of calling the
> stmmac_set_half_duplex()/stmmac_set_mac_capabilties() methods on the
> device init and queues reinit stages, we can move their bodies into
> the phylink:mac_get_caps() callback.
> 
> Others see:
> <https://lore.kernel.org/netdev/cover.1706601050.git.siyanteng@loong
> son.cn/T/#m7d724d33faee34fed696e4458d9f6b09b0572e77>

Just submitted the series with this patch being properly split up and
described:
https://lore.kernel.org/netdev/20240412180340.7965-1-fancer.lancer@gmail.com/

You can drop this patch, copy my patchset into your repo and rebase
your series onto it. Thus for the time being, until my series is
reviewed and merged in, you'll be able to continue with your patchset
developments/reviews, but submitting only your portion of the patches.

Alternatively my series could be just merged into yours as a set of
the preparation patches, for instance, after it's fully reviewed.

Not sure which solution is better. Andrew? Russell? David? Eric?
Jakub? Paolo?

-Serge(y)

> 
> Signed-off-by: Serge Semin <fancer.lancer@gmail.com>
> Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
> ---
>  drivers/net/ethernet/stmicro/stmmac/common.h  |  1 +
>  .../net/ethernet/stmicro/stmmac/dwmac-sun8i.c |  2 +
>  .../ethernet/stmicro/stmmac/dwmac1000_core.c  |  2 +
>  .../ethernet/stmicro/stmmac/dwmac100_core.c   |  2 +
>  .../net/ethernet/stmicro/stmmac/dwmac4_core.c |  8 +++-
>  .../ethernet/stmicro/stmmac/dwxgmac2_core.c   | 15 +++----
>  .../net/ethernet/stmicro/stmmac/stmmac_main.c | 43 ++++++++-----------
>  7 files changed, 36 insertions(+), 37 deletions(-)
> 
> diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
> index f55cf09f0783..9cd62b2110a1 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/common.h
> +++ b/drivers/net/ethernet/stmicro/stmmac/common.h
> @@ -553,6 +553,7 @@ extern const struct stmmac_hwtimestamp stmmac_ptp;
>  extern const struct stmmac_mode_ops dwmac4_ring_mode_ops;
>  
>  struct mac_link {
> +	u32 caps;
>  	u32 speed_mask;
>  	u32 speed10;
>  	u32 speed100;
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
> index b21d99faa2d0..e1b761dcfa1d 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
> @@ -1096,6 +1096,8 @@ static struct mac_device_info *sun8i_dwmac_setup(void *ppriv)
>  
>  	priv->dev->priv_flags |= IFF_UNICAST_FLT;
>  
> +	mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
> +			 MAC_10 | MAC_100 | MAC_1000;
>  	/* The loopback bit seems to be re-set when link change
>  	 * Simply mask it each time
>  	 * Speed 10/100/1000 are set in BIT(2)/BIT(3)
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
> index 3927609abc44..8555299443f4 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
> @@ -539,6 +539,8 @@ int dwmac1000_setup(struct stmmac_priv *priv)
>  	if (mac->multicast_filter_bins)
>  		mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins);
>  
> +	mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
> +			 MAC_10 | MAC_100 | MAC_1000;
>  	mac->link.duplex = GMAC_CONTROL_DM;
>  	mac->link.speed10 = GMAC_CONTROL_PS;
>  	mac->link.speed100 = GMAC_CONTROL_PS | GMAC_CONTROL_FES;
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
> index a6e8d7bd9588..7667d103cd0e 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
> @@ -175,6 +175,8 @@ int dwmac100_setup(struct stmmac_priv *priv)
>  	dev_info(priv->device, "\tDWMAC100\n");
>  
>  	mac->pcsr = priv->ioaddr;
> +	mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
> +			 MAC_10 | MAC_100;
>  	mac->link.duplex = MAC_CONTROL_F;
>  	mac->link.speed10 = 0;
>  	mac->link.speed100 = 0;
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
> index cef25efbdff9..70a4ac16d3c8 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
> @@ -70,7 +70,11 @@ static void dwmac4_core_init(struct mac_device_info *hw,
>  
>  static void dwmac4_phylink_get_caps(struct stmmac_priv *priv)
>  {
> -	priv->phylink_config.mac_capabilities |= MAC_2500FD;
> +	/* Half-Duplex can only work with single tx queue */
> +	if (priv->plat->tx_queues_to_use > 1)
> +		priv->hw->link.caps &= ~(MAC_10HD | MAC_100HD | MAC_1000HD);
> +	else
> +		priv->hw->link.caps |= (MAC_10HD | MAC_100HD | MAC_1000HD);
>  }
>  
>  static void dwmac4_rx_queue_enable(struct mac_device_info *hw,
> @@ -1378,6 +1382,8 @@ int dwmac4_setup(struct stmmac_priv *priv)
>  	if (mac->multicast_filter_bins)
>  		mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins);
>  
> +	mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
> +			 MAC_10 | MAC_100 | MAC_1000 | MAC_2500FD;
>  	mac->link.duplex = GMAC_CONFIG_DM;
>  	mac->link.speed10 = GMAC_CONFIG_PS;
>  	mac->link.speed100 = GMAC_CONFIG_FES | GMAC_CONFIG_PS;
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
> index e841e312077e..759b9b7a2f3f 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
> @@ -47,14 +47,6 @@ static void dwxgmac2_core_init(struct mac_device_info *hw,
>  	writel(XGMAC_INT_DEFAULT_EN, ioaddr + XGMAC_INT_EN);
>  }
>  
> -static void xgmac_phylink_get_caps(struct stmmac_priv *priv)
> -{
> -	priv->phylink_config.mac_capabilities |= MAC_2500FD | MAC_5000FD |
> -						 MAC_10000FD | MAC_25000FD |
> -						 MAC_40000FD | MAC_50000FD |
> -						 MAC_100000FD;
> -}
> -
>  static void dwxgmac2_set_mac(void __iomem *ioaddr, bool enable)
>  {
>  	u32 tx = readl(ioaddr + XGMAC_TX_CONFIG);
> @@ -1540,7 +1532,6 @@ static void dwxgmac3_fpe_configure(void __iomem *ioaddr, struct stmmac_fpe_cfg *
>  
>  const struct stmmac_ops dwxgmac210_ops = {
>  	.core_init = dwxgmac2_core_init,
> -	.phylink_get_caps = xgmac_phylink_get_caps,
>  	.set_mac = dwxgmac2_set_mac,
>  	.rx_ipc = dwxgmac2_rx_ipc,
>  	.rx_queue_enable = dwxgmac2_rx_queue_enable,
> @@ -1601,7 +1592,6 @@ static void dwxlgmac2_rx_queue_enable(struct mac_device_info *hw, u8 mode,
>  
>  const struct stmmac_ops dwxlgmac2_ops = {
>  	.core_init = dwxgmac2_core_init,
> -	.phylink_get_caps = xgmac_phylink_get_caps,
>  	.set_mac = dwxgmac2_set_mac,
>  	.rx_ipc = dwxgmac2_rx_ipc,
>  	.rx_queue_enable = dwxlgmac2_rx_queue_enable,
> @@ -1698,6 +1688,11 @@ int dwxlgmac2_setup(struct stmmac_priv *priv)
>  	if (mac->multicast_filter_bins)
>  		mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins);
>  
> +	mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
> +			 MAC_1000FD | MAC_2500FD | MAC_5000FD |
> +			 MAC_10000FD | MAC_25000FD |
> +			 MAC_40000FD | MAC_50000FD |
> +			 MAC_100000FD;
>  	mac->link.duplex = 0;
>  	mac->link.speed1000 = XLGMAC_CONFIG_SS_1000;
>  	mac->link.speed2500 = XLGMAC_CONFIG_SS_2500;
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> index fe3498e86de9..af16efeedf4a 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> @@ -936,6 +936,22 @@ static void stmmac_mac_flow_ctrl(struct stmmac_priv *priv, u32 duplex)
>  			priv->pause, tx_cnt);
>  }
>  
> +static unsigned long stmmac_mac_get_caps(struct phylink_config *config,
> +					 phy_interface_t interface)
> +{
> +	struct stmmac_priv *priv = netdev_priv(to_net_dev(config->dev));
> +
> +	/* Get the MAC-specific capabilities */
> +	stmmac_mac_phylink_get_caps(priv);
> +
> +	config->mac_capabilities = priv->hw->link.caps;
> +
> +	if (priv->plat->max_speed)
> +		phylink_limit_mac_speed(config, priv->plat->max_speed);
> +
> +	return config->mac_capabilities;
> +}
> +
>  static struct phylink_pcs *stmmac_mac_select_pcs(struct phylink_config *config,
>  						 phy_interface_t interface)
>  {
> @@ -1102,6 +1118,7 @@ static void stmmac_mac_link_up(struct phylink_config *config,
>  }
>  
>  static const struct phylink_mac_ops stmmac_phylink_mac_ops = {
> +	.mac_get_caps = stmmac_mac_get_caps,
>  	.mac_select_pcs = stmmac_mac_select_pcs,
>  	.mac_config = stmmac_mac_config,
>  	.mac_link_down = stmmac_mac_link_down,
> @@ -1195,24 +1212,12 @@ static int stmmac_init_phy(struct net_device *dev)
>  	return ret;
>  }
>  
> -static void stmmac_set_half_duplex(struct stmmac_priv *priv)
> -{
> -	/* Half-Duplex can only work with single tx queue */
> -	if (priv->plat->tx_queues_to_use > 1)
> -		priv->phylink_config.mac_capabilities &=
> -			~(MAC_10HD | MAC_100HD | MAC_1000HD);
> -	else
> -		priv->phylink_config.mac_capabilities |=
> -			(MAC_10HD | MAC_100HD | MAC_1000HD);
> -}
> -
>  static int stmmac_phy_setup(struct stmmac_priv *priv)
>  {
>  	struct stmmac_mdio_bus_data *mdio_bus_data;
>  	int mode = priv->plat->phy_interface;
>  	struct fwnode_handle *fwnode;
>  	struct phylink *phylink;
> -	int max_speed;
>  
>  	priv->phylink_config.dev = &priv->dev->dev;
>  	priv->phylink_config.type = PHYLINK_NETDEV;
> @@ -1236,19 +1241,6 @@ static int stmmac_phy_setup(struct stmmac_priv *priv)
>  		xpcs_get_interfaces(priv->hw->xpcs,
>  				    priv->phylink_config.supported_interfaces);
>  
> -	priv->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
> -						MAC_10FD | MAC_100FD |
> -						MAC_1000FD;
> -
> -	stmmac_set_half_duplex(priv);
> -
> -	/* Get the MAC specific capabilities */
> -	stmmac_mac_phylink_get_caps(priv);
> -
> -	max_speed = priv->plat->max_speed;
> -	if (max_speed)
> -		phylink_limit_mac_speed(&priv->phylink_config, max_speed);
> -
>  	fwnode = priv->plat->port_node;
>  	if (!fwnode)
>  		fwnode = dev_fwnode(priv->device);
> @@ -7357,7 +7349,6 @@ int stmmac_reinit_queues(struct net_device *dev, u32 rx_cnt, u32 tx_cnt)
>  			priv->rss.table[i] = ethtool_rxfh_indir_default(i,
>  									rx_cnt);
>  
> -	stmmac_set_half_duplex(priv);
>  	stmmac_napi_add(dev);
>  
>  	if (netif_running(dev))
> -- 
> 2.31.4
> 

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

* Re: [PATCH net-next v11 0/6] stmmac: Add Loongson platform support
  2024-04-12 11:28 [PATCH net-next v11 0/6] stmmac: Add Loongson platform support Yanteng Si
                   ` (5 preceding siblings ...)
  2024-04-12 11:28 ` [PATCH net-next v11 6/6] net: stmmac: dwmac-loongson: Add Loongson GNET support Yanteng Si
@ 2024-04-12 18:34 ` Serge Semin
  2024-04-18  5:16   ` Yanteng Si
  6 siblings, 1 reply; 36+ messages in thread
From: Serge Semin @ 2024-04-12 18:34 UTC (permalink / raw)
  To: Yanteng Si
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang, siyanteng01

Hi Yanteng

On Fri, Apr 12, 2024 at 07:28:05PM +0800, Yanteng Si wrote:
> v11:
> * Break loongson_phylink_get_caps(), fix bad logic.
> * Remove a unnecessary ";".
> * Remove some unnecessary "{}".
> * add a blank.
> * Move the code of fix _force_1000 to patch 6/6.
> 
> The main changes occur in these two functions:
> loongson_dwmac_probe();
> loongson_dwmac_setup();
> 
> v10:
> As Andrew's comment:
> * Add a #define for the 0x37.
> * Add a #define for Port Select.
> 
> others:
> * Pick Serge's patch, This patch resulted from the process
>   of reviewing our patch set.
> * Based on Serge's patch, modify our loongson_phylink_get_caps().
> * Drop patch 3/6, we need mac_interface.
> * Adjusted the code layout of gnet patch.
> * Corrected several errata in commit message.
> * Move DISABLE_FORCE flag to loongson_gnet_data().
> 
> v9:
> We have not provided a detailed list of equipment for a long time,
> and I apologize for this. During this period, I have collected some
> information and now present it to you, hoping to alleviate the pressure
> of review.
> 
> 1. IP core
> We now have two types of IP cores, one is 0x37, similar to dwmac1000;
> The other is 0x10.  Compared to 0x37, we split several DMA registers
> from one to two, and it is not worth adding a new entry for this.
> According to Serge's comment, we made these devices work by overwriting
> priv->synopsys_id = 0x37 and mac->dma = <LS_dma_ops>.
> 
> 1.1.  Some more detailed information
> The number of DMA channels for 0x37 is 1; The number of DMA channels
> for 0x10 is 8.  Except for channel 0, otherchannels do not support
> sending hardware checksums. Supported AV features are Qav, Qat, and Qas,
> and the rest are consistent with 3.73.
> 
> 2. DEVICE
> We have two types of devices,
> one is GMAC, which only has a MAC chip inside and needs an external PHY
> chip;
> the other is GNET, which integrates both MAC and PHY chips inside.
> 
> 2.1.  Some more detailed information
> GMAC device: LS7A1000, LS2K1000, these devices do not support any pause
> mode.
> gnet device: LS7A2000, LS2K2000, the chip connection between the mac and
>              phy of these devices is not normal and requires two rounds of
>              negotiation; LS7A2000 does not support half-duplex and
> multi-channel;
>              to enable multi-channel on LS2K2000, you need to turn off
> hardware checksum.
> **Note**: Only the LS2K2000's IP core is 0x10, while the IP cores of other
> devices are 0x37.
> 
> 3. TABLE
> 
> device    type    pci_id    ip_core
> ls7a1000  gmac    7a03      0x35/0x37
> ls2k1000  gmac    7a03      0x35/0x37
> ls7a2000  gnet    7a13      0x37
> ls2k2000  gnet    7a13      0x10
> -----------------------------------------------
> Changes:
> 
> * passed the CI
>   <https://github.com/linux-netdev/nipa/blob/main/tests/patch/checkpatch
>   /checkpatch.sh>
> * reverse xmas tree order.
> * Silence build warning.
> * Re-split the patch.
> * Add more detailed commit message.
> * Add more code comment.
> * Reduce modification of generic code.
> * using the GNET-specific prefix.
> * define a new macro for the GNET MAC.
> * Use an easier way to overwrite mac.
> * Removed some useless printk.
> 

Thanks you very much for taking my notes into account and resubmitting
the patchset. I'll get back to reviewing your series within 2-5 days.

-Serge(y)

> 
> v8:
> * The biggest change is according to Serge's comment in the previous
>   edition:
>    Seeing the patch in the current state would overcomplicate the generic
>    code and the only functions you need to update are
>    dwmac_dma_interrupt()
>    dwmac1000_dma_init_channel()
>    you can have these methods re-defined with all the Loongson GNET
>    specifics in the low-level platform driver (dwmac-loongson.c). After
>    that you can just override the mac_device_info.dma pointer with a
>    fixed stmmac_dma_ops descriptor. Here is what should be done for that:
> 
>    1. Keep the Patch 4/9 with my comments fixed. First it will be partly
>    useful for your GNET device. Second in general it's a correct
>    implementation of the normal DW GMAC v3.x multi-channels feature and
>    will be useful for the DW GMACs with that feature enabled.
> 
>    2. Create the Loongson GNET-specific
>    stmmac_dma_ops.dma_interrupt()
>    stmmac_dma_ops.init_chan()
>    methods in the dwmac-loongson.c driver. Don't forget to move all the
>    Loongson-specific macros from dwmac_dma.h to dwmac-loongson.c.
> 
>    3. Create a Loongson GNET-specific platform setup method with the next
>    semantics:
>       + allocate stmmac_dma_ops instance and initialize it with
>         dwmac1000_dma_ops.
>       + override the stmmac_dma_ops.{dma_interrupt, init_chan} with
>         the pointers to the methods defined in 2.
>       + allocate mac_device_info instance and initialize the
>         mac_device_info.dma field with a pointer to the new
>         stmmac_dma_ops instance.
>       + call dwmac1000_setup() or initialize mac_device_info in a way
>         it's done in dwmac1000_setup() (the later might be better so you
>         wouldn't need to export the dwmac1000_setup() function).
>       + override stmmac_priv.synopsys_id with a correct value.
> 
>    4. Initialize plat_stmmacenet_data.setup() with the pointer to the
>    method created in 3.
> 
> * Others:
>   Re-split the patch.
>   Passed checkpatch.pl test.
> 
> v7:
> * Refer to andrew's suggestion:
>   - Add DMA_INTR_ENA_NIE_RX and DMA_INTR_ENA_NIE_TX #define's, etc.
> 
> * Others:
>   - Using --subject-prefix="PATCH net-next vN" to indicate that the
>     patches are for the networking tree.
>   - Rebase to the latest networking tree:
>     <git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git>
> 
> 
> v6:
> 
> * Refer to Serge's suggestion:
>   - Add new platform feature flag:
>     include/linux/stmmac.h:
>     +#define STMMAC_FLAG_HAS_LGMAC			BIT(13)
> 
>   - Add the IRQs macros specific to the Loongson Multi-channels GMAC:
>      drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h:
>      +#define DMA_INTR_ENA_NIE_LOONGSON 0x00060000      /* ...*/
>      #define DMA_INTR_ENA_NIE 0x00010000	/* Normal Summary */
>      ...
> 
>   - Drop all of redundant changes that don't require the
>     prototypes being converted to accepting the stmmac_priv
>     pointer.
> 
> * Refer to andrew's suggestion:
>   - Drop white space changes.
>   - break patch up into lots of smaller parts.
>      Some small patches have been put into another series as a preparation
>      see <https://lore.kernel.org/loongarch/cover.1702289232.git.siyanteng@loongson.cn/T/#t>
>      
>      *note* : This series of patches relies on the three small patches above.
> * others
>   - Drop irq_flags changes.
>   - Changed patch order.
> 
> 
> v4 -> v5:
> 
> * Remove an ugly and useless patch (fix channel number).
> * Remove the non-standard dma64 driver code, and also remove
>   the HWIF entries, since the associated custom callbacks no
>   longer exist.
> * Refer to Serge's suggestion: Update the dwmac1000_dma.c to
>   support the multi-DMA-channels controller setup.
> 
> See:
> v4: <https://lore.kernel.org/loongarch/cover.1692696115.git.chenfeiyang@loongson.cn/>
> v3: <https://lore.kernel.org/loongarch/cover.1691047285.git.chenfeiyang@loongson.cn/>
> v2: <https://lore.kernel.org/loongarch/cover.1690439335.git.chenfeiyang@loongson.cn/>
> v1: <https://lore.kernel.org/loongarch/cover.1689215889.git.chenfeiyang@loongson.cn/>
> 
> Serge Semin (1):
>   net: stmmac: Move all PHYLINK MAC capabilities initializations to
>     MAC-specific setup methods
> 
> Yanteng Si (5):
>   net: stmmac: Add multi-channel support
>   net: stmmac: dwmac-loongson: Use PCI_DEVICE_DATA() macro for device
>     identification
>   net: stmmac: dwmac-loongson: Introduce GMAC setup
>   net: stmmac: dwmac-loongson: Add full PCI support
>   net: stmmac: dwmac-loongson: Add Loongson GNET support
> 
>  drivers/net/ethernet/stmicro/stmmac/common.h  |   3 +
>  .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 544 ++++++++++++++++--
>  .../net/ethernet/stmicro/stmmac/dwmac-sun8i.c |   6 +-
>  .../ethernet/stmicro/stmmac/dwmac1000_core.c  |   2 +
>  .../ethernet/stmicro/stmmac/dwmac1000_dma.c   |  35 +-
>  .../ethernet/stmicro/stmmac/dwmac100_core.c   |   2 +
>  .../ethernet/stmicro/stmmac/dwmac100_dma.c    |   2 +-
>  .../net/ethernet/stmicro/stmmac/dwmac4_core.c |   8 +-
>  .../net/ethernet/stmicro/stmmac/dwmac4_dma.c  |   2 +-
>  .../net/ethernet/stmicro/stmmac/dwmac_dma.h   |  20 +-
>  .../net/ethernet/stmicro/stmmac/dwmac_lib.c   |  32 +-
>  .../ethernet/stmicro/stmmac/dwxgmac2_core.c   |  15 +-
>  .../ethernet/stmicro/stmmac/dwxgmac2_dma.c    |   2 +-
>  drivers/net/ethernet/stmicro/stmmac/hwif.h    |   5 +-
>  .../ethernet/stmicro/stmmac/stmmac_ethtool.c  |   6 +
>  .../net/ethernet/stmicro/stmmac/stmmac_main.c |  54 +-
>  include/linux/stmmac.h                        |   2 +
>  17 files changed, 599 insertions(+), 141 deletions(-)
> 
> -- 
> 2.31.4
> 

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

* Re: [PATCH net-next v11 3/6] net: stmmac: dwmac-loongson: Use PCI_DEVICE_DATA() macro for device identification
  2024-04-12 11:28 ` [PATCH net-next v11 3/6] net: stmmac: dwmac-loongson: Use PCI_DEVICE_DATA() macro for device identification Yanteng Si
@ 2024-04-13  1:49   ` Jakub Kicinski
  2024-04-15  2:21     ` Yanteng Si
  0 siblings, 1 reply; 36+ messages in thread
From: Jakub Kicinski @ 2024-04-13  1:49 UTC (permalink / raw)
  To: Yanteng Si
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	fancer.lancer, Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang, siyanteng01

On Fri, 12 Apr 2024 19:28:08 +0800 Yanteng Si wrote:
> Just use PCI_DEVICE_DATA() macro for device identification,
> No changes to function functionality.
> 
> Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
> Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
> Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
> ---
>  drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> index 9e40c28d453a..995c9bd144e0 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> @@ -213,7 +213,7 @@ static SIMPLE_DEV_PM_OPS(loongson_dwmac_pm_ops, loongson_dwmac_suspend,
>  			 loongson_dwmac_resume);
>  
>  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);

In file included from ../drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c:6:
../include/linux/pci.h:1061:51: error: ‘PCI_DEVICE_ID_LOONGSON_GMAC’ undeclared here (not in a function); did you mean ‘PCI_DEVICE_ID_LOONGSON_HDA’?
 1061 |         .vendor = PCI_VENDOR_ID_##vend, .device = PCI_DEVICE_ID_##vend##_##dev, \
      |                                                   ^~~~~~~~~~~~~~
../drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c:216:11: note: in expansion of macro ‘PCI_DEVICE_DATA’
  216 |         { PCI_DEVICE_DATA(LOONGSON, GMAC, &loongson_gmac_pci_info) },
      |           ^~~~~~~~~~~~~~~
../drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c:216:44: error: ‘loongson_gmac_pci_info’ undeclared here (not in a function)
  216 |         { PCI_DEVICE_DATA(LOONGSON, GMAC, &loongson_gmac_pci_info) },
      |                                            ^~~~~~~~~~~~~~~~~~~~~~
../include/linux/pci.h:1063:41: note: in definition of macro ‘PCI_DEVICE_DATA’
 1063 |         .driver_data = (kernel_ulong_t)(data)
      |                                         ^~~~
-- 
pw-bot: cr

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

* Re: [PATCH net-next v11 3/6] net: stmmac: dwmac-loongson: Use PCI_DEVICE_DATA() macro for device identification
  2024-04-13  1:49   ` Jakub Kicinski
@ 2024-04-15  2:21     ` Yanteng Si
  2024-04-18 11:14       ` Serge Semin
  0 siblings, 1 reply; 36+ messages in thread
From: Yanteng Si @ 2024-04-15  2:21 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	fancer.lancer, Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang, siyanteng01

>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>> index 9e40c28d453a..995c9bd144e0 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>> @@ -213,7 +213,7 @@ static SIMPLE_DEV_PM_OPS(loongson_dwmac_pm_ops, loongson_dwmac_suspend,
>>   			 loongson_dwmac_resume);
>>   
>>   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);
> In file included from ../drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c:6:
> ../include/linux/pci.h:1061:51: error: ‘PCI_DEVICE_ID_LOONGSON_GMAC’ undeclared here (not in a function); did you mean ‘PCI_DEVICE_ID_LOONGSON_HDA’?
>   1061 |         .vendor = PCI_VENDOR_ID_##vend, .device = PCI_DEVICE_ID_##vend##_##dev, \
>        |                                                   ^~~~~~~~~~~~~~
> ../drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c:216:11: note: in expansion of macro ‘PCI_DEVICE_DATA’
>    216 |         { PCI_DEVICE_DATA(LOONGSON, GMAC, &loongson_gmac_pci_info) },
>        |           ^~~~~~~~~~~~~~~
> ../drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c:216:44: error: ‘loongson_gmac_pci_info’ undeclared here (not in a function)
>    216 |         { PCI_DEVICE_DATA(LOONGSON, GMAC, &loongson_gmac_pci_info) },
>        |                                            ^~~~~~~~~~~~~~~~~~~~~~
> ../include/linux/pci.h:1063:41: note: in definition of macro ‘PCI_DEVICE_DATA’
>   1063 |         .driver_data = (kernel_ulong_t)(data)
>        |                                         ^~~~

Will be fixed in v12.


Thanks,

Yanteng


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

* Re: [PATCH net-next v11 1/6] net: stmmac: Move all PHYLINK MAC capabilities initializations to MAC-specific setup methods
  2024-04-12 18:32   ` Serge Semin
@ 2024-04-18  5:02     ` Yanteng Si
  2024-04-18  9:53       ` Serge Semin
  0 siblings, 1 reply; 36+ messages in thread
From: Yanteng Si @ 2024-04-18  5:02 UTC (permalink / raw)
  To: Serge Semin, Andrew Lunn, Russell King, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni
  Cc: hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, guyinggang, netdev, chris.chenfeiyang,
	siyanteng01


在 2024/4/13 02:32, Serge Semin 写道:
> Just submitted the series with this patch being properly split up and
> described:
> https://lore.kernel.org/netdev/20240412180340.7965-1-fancer.lancer@gmail.com/
>
> You can drop this patch, copy my patchset into your repo and rebase
> your series onto it. Thus for the time being, until my series is
> reviewed and merged in, you'll be able to continue with your patchset
> developments/reviews, but submitting only your portion of the patches.
>
> Alternatively my series could be just merged into yours as a set of
> the preparation patches, for instance, after it's fully reviewed.

Okay, I've seen your patch. I'll drop it.


Thanks,

Yanteng


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

* Re: [PATCH net-next v11 0/6] stmmac: Add Loongson platform support
  2024-04-12 18:34 ` [PATCH net-next v11 0/6] stmmac: Add Loongson platform support Serge Semin
@ 2024-04-18  5:16   ` Yanteng Si
  0 siblings, 0 replies; 36+ messages in thread
From: Yanteng Si @ 2024-04-18  5:16 UTC (permalink / raw)
  To: Serge Semin
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang, siyanteng01


在 2024/4/13 02:34, Serge Semin 写道:
>> Changes:
>>
>> * passed the CI
>>    <https://github.com/linux-netdev/nipa/blob/main/tests/patch/checkpatch
>>    /checkpatch.sh>
>> * reverse xmas tree order.
>> * Silence build warning.
>> * Re-split the patch.
>> * Add more detailed commit message.
>> * Add more code comment.
>> * Reduce modification of generic code.
>> * using the GNET-specific prefix.
>> * define a new macro for the GNET MAC.
>> * Use an easier way to overwrite mac.
>> * Removed some useless printk.
>>
> Thanks you very much for taking my notes into account and resubmitting
> the patchset. I'll get back to reviewing your series within 2-5 days.

Thanks for your patience. if you don't mind, how about reviewing them in 
v12?


I'm already working on v12, which is a minor version update, and I'm 
going to

rebase my patch and make some minor changes about splitting to silence

some warnings.


Thanks,

Yanteng




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

* Re: [PATCH net-next v11 1/6] net: stmmac: Move all PHYLINK MAC capabilities initializations to MAC-specific setup methods
  2024-04-18  5:02     ` Yanteng Si
@ 2024-04-18  9:53       ` Serge Semin
  2024-04-19  7:01         ` Yanteng Si
  0 siblings, 1 reply; 36+ messages in thread
From: Serge Semin @ 2024-04-18  9:53 UTC (permalink / raw)
  To: Yanteng Si
  Cc: Andrew Lunn, Russell King, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, hkallweit1, peppe.cavallaro,
	alexandre.torgue, joabreu, Jose.Abreu, chenhuacai, guyinggang,
	netdev, chris.chenfeiyang, siyanteng01

On Thu, Apr 18, 2024 at 01:02:28PM +0800, Yanteng Si wrote:
> 
> 在 2024/4/13 02:32, Serge Semin 写道:
> > Just submitted the series with this patch being properly split up and
> > described:
> > https://lore.kernel.org/netdev/20240412180340.7965-1-fancer.lancer@gmail.com/
> > 
> > You can drop this patch, copy my patchset into your repo and rebase
> > your series onto it. Thus for the time being, until my series is
> > reviewed and merged in, you'll be able to continue with your patchset
> > developments/reviews, but submitting only your portion of the patches.
> > 
> > Alternatively my series could be just merged into yours as a set of
> > the preparation patches, for instance, after it's fully reviewed.
> 
> Okay, I've seen your patch. I'll drop it.

The series has been partly merged in:
https://lore.kernel.org/netdev/20240412180340.7965-1-fancer.lancer@gmail.com/
You can pick the first three patches up into your repo to rebase your
work onto.

Two leftover patches I've just resubmitted:
https://lore.kernel.org/netdev/20240417140013.12575-1-fancer.lancer@gmail.com/

-Serge(y)

> 
> 
> Thanks,
> 
> Yanteng
> 

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

* Re: [PATCH net-next v11 2/6] net: stmmac: Add multi-channel support
  2024-04-12 11:28 ` [PATCH net-next v11 2/6] net: stmmac: Add multi-channel support Yanteng Si
@ 2024-04-18 11:02   ` Serge Semin
  2024-04-19  9:02     ` Yanteng Si
  0 siblings, 1 reply; 36+ messages in thread
From: Serge Semin @ 2024-04-18 11:02 UTC (permalink / raw)
  To: Yanteng Si
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang, siyanteng01

On Fri, Apr 12, 2024 at 07:28:07PM +0800, Yanteng Si wrote:
> DW GMAC v3.x multi-channels feature is implemented as multiple
> sets of the same CSRs. Here is only preliminary support, it will
> be useful for the driver further evolution and for the users
> having multi-channel DWGMAC v3.x devices.
> 
> Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
> Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
> Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
> ---
>  .../net/ethernet/stmicro/stmmac/dwmac-sun8i.c |  4 +--
>  .../ethernet/stmicro/stmmac/dwmac1000_dma.c   | 34 ++++++++++---------
>  .../ethernet/stmicro/stmmac/dwmac100_dma.c    |  2 +-
>  .../net/ethernet/stmicro/stmmac/dwmac4_dma.c  |  2 +-
>  .../net/ethernet/stmicro/stmmac/dwmac_dma.h   | 20 +++++++++--
>  .../net/ethernet/stmicro/stmmac/dwmac_lib.c   | 32 ++++++++---------
>  .../ethernet/stmicro/stmmac/dwxgmac2_dma.c    |  2 +-
>  drivers/net/ethernet/stmicro/stmmac/hwif.h    |  5 ++-
>  .../net/ethernet/stmicro/stmmac/stmmac_main.c | 11 +++---
>  include/linux/stmmac.h                        |  1 +
>  10 files changed, 65 insertions(+), 48 deletions(-)
> 
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
> index e1b761dcfa1d..cc93f73a380e 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
> @@ -299,7 +299,7 @@ static int sun8i_dwmac_dma_reset(void __iomem *ioaddr)
>   * Called from stmmac via stmmac_dma_ops->init
>   */
>  static void sun8i_dwmac_dma_init(void __iomem *ioaddr,
> -				 struct stmmac_dma_cfg *dma_cfg, int atds)
> +				 struct stmmac_dma_cfg *dma_cfg)
>  {
>  	writel(EMAC_RX_INT | EMAC_TX_INT, ioaddr + EMAC_INT_EN);
>  	writel(0x1FFFFFF, ioaddr + EMAC_INT_STA);
> @@ -395,7 +395,7 @@ static void sun8i_dwmac_dma_start_tx(struct stmmac_priv *priv,
>  	writel(v, ioaddr + EMAC_TX_CTL1);
>  }
>  
> -static void sun8i_dwmac_enable_dma_transmission(void __iomem *ioaddr)
> +static void sun8i_dwmac_enable_dma_transmission(void __iomem *ioaddr, u32 chan)
>  {
>  	u32 v;
>  
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> index daf79cdbd3ec..f161ec9ac490 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> @@ -70,15 +70,17 @@ static void dwmac1000_dma_axi(void __iomem *ioaddr, struct stmmac_axi *axi)
>  	writel(value, ioaddr + DMA_AXI_BUS_MODE);
>  }
>  
> -static void dwmac1000_dma_init(void __iomem *ioaddr,
> -			       struct stmmac_dma_cfg *dma_cfg, int atds)
> +static void dwmac1000_dma_init_channel(struct stmmac_priv *priv,
> +				       void __iomem *ioaddr,

> +				       struct stmmac_dma_cfg *dma_cfg, u32 chan)

please create a pre-requisite/preparation patch with the atds argument
movement to the stmmac_dma_cfg structure as I suggested in v8:
https://lore.kernel.org/netdev/yzs6eqx2swdhaegxxcbijhtb5tkhkvvyvso2perkessv5swq47@ywmea5xswsug/
That will make this patch looking simpler and providing a single
coherent change.

> [...]
> 
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
> index 72672391675f..7c8b3ad739f7 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
>
> [...]
> 
>  void dwmac_dma_stop_rx(struct stmmac_priv *priv, void __iomem *ioaddr, u32 chan)
>  {
> -	u32 value = readl(ioaddr + DMA_CONTROL);
> +	u32 value = readl(ioaddr + DMA_CHAN_CONTROL(chan));
>  	value &= ~DMA_CONTROL_SR;
> -	writel(value, ioaddr + DMA_CONTROL);
> +	writel(value, ioaddr + DMA_CHAN_CONTROL(chan));
>  }
>  
>  #ifdef DWMAC_DMA_DEBUG
> @@ -165,7 +165,7 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
>  	struct stmmac_pcpu_stats *stats = this_cpu_ptr(priv->xstats.pcpu_stats);
>  	int ret = 0;
>  	/* read the status register (CSR5) */
> -	u32 intr_status = readl(ioaddr + DMA_STATUS);
> +	u32 intr_status = readl(ioaddr + DMA_CHAN_STATUS(chan));
>  
>  #ifdef DWMAC_DMA_DEBUG
>  	/* Enable it to monitor DMA rx/tx status in case of critical problems */
> @@ -235,7 +235,7 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
>  		pr_warn("%s: unexpected status %08x\n", __func__, intr_status);
>  

>  	/* Clear the interrupt by writing a logic 1 to the CSR5[15-0] */
> -	writel((intr_status & 0x1ffff), ioaddr + DMA_STATUS);
> +	writel((intr_status & 0x7ffff), ioaddr + DMA_CHAN_STATUS(chan));

I'll ask once again:

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

The rest of the changes look good. Thanks.

-Serge(y)

>
> [...]
>

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

* Re: [PATCH net-next v11 3/6] net: stmmac: dwmac-loongson: Use PCI_DEVICE_DATA() macro for device identification
  2024-04-15  2:21     ` Yanteng Si
@ 2024-04-18 11:14       ` Serge Semin
  2024-04-18 12:31         ` Serge Semin
  0 siblings, 1 reply; 36+ messages in thread
From: Serge Semin @ 2024-04-18 11:14 UTC (permalink / raw)
  To: Yanteng Si
  Cc: Jakub Kicinski, andrew, hkallweit1, peppe.cavallaro,
	alexandre.torgue, joabreu, Jose.Abreu, chenhuacai, linux,
	guyinggang, netdev, chris.chenfeiyang, siyanteng01

On Mon, Apr 15, 2024 at 10:21:39AM +0800, Yanteng Si wrote:
> > > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > index 9e40c28d453a..995c9bd144e0 100644
> > > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > @@ -213,7 +213,7 @@ static SIMPLE_DEV_PM_OPS(loongson_dwmac_pm_ops, loongson_dwmac_suspend,
> > >   			 loongson_dwmac_resume);
> > >   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);
> > In file included from ../drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c:6:
> > ../include/linux/pci.h:1061:51: error: ‘PCI_DEVICE_ID_LOONGSON_GMAC’ undeclared here (not in a function); did you mean ‘PCI_DEVICE_ID_LOONGSON_HDA’?
> >   1061 |         .vendor = PCI_VENDOR_ID_##vend, .device = PCI_DEVICE_ID_##vend##_##dev, \
> >        |                                                   ^~~~~~~~~~~~~~
> > ../drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c:216:11: note: in expansion of macro ‘PCI_DEVICE_DATA’
> >    216 |         { PCI_DEVICE_DATA(LOONGSON, GMAC, &loongson_gmac_pci_info) },
> >        |           ^~~~~~~~~~~~~~~
> > ../drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c:216:44: error: ‘loongson_gmac_pci_info’ undeclared here (not in a function)
> >    216 |         { PCI_DEVICE_DATA(LOONGSON, GMAC, &loongson_gmac_pci_info) },
> >        |                                            ^~~~~~~~~~~~~~~~~~~~~~
> > ../include/linux/pci.h:1063:41: note: in definition of macro ‘PCI_DEVICE_DATA’
> >   1063 |         .driver_data = (kernel_ulong_t)(data)
> >        |                                         ^~~~
> 

> Will be fixed in v12.

Just move the PCI_DEVICE_ID_LOONGSON_GMAC macro definition from Patch
5/6 to this one.

-Serge(y)

> 
> 
> Thanks,
> 
> Yanteng
> 

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

* Re: [PATCH net-next v11 4/6] net: stmmac: dwmac-loongson: Introduce GMAC setup
  2024-04-12 11:28 ` [PATCH net-next v11 4/6] net: stmmac: dwmac-loongson: Introduce GMAC setup Yanteng Si
@ 2024-04-18 12:26   ` Serge Semin
  2024-04-19 10:06     ` Yanteng Si
  2024-04-22 10:17   ` Yanteng Si
  1 sibling, 1 reply; 36+ messages in thread
From: Serge Semin @ 2024-04-18 12:26 UTC (permalink / raw)
  To: Yanteng Si
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang, siyanteng01

On Fri, Apr 12, 2024 at 07:28:49PM +0800, Yanteng Si wrote:
> Based on IP core classification, loongson has two types of network
> devices: GMAC and GNET. GMAC's ip_core id is 0x35/0x37, while GNET's
> ip_core id is 0x37/0x10.
> 
> Device tables:
> 
> device    type    pci_id    ip_core
> ls2k1000  gmac    7a03      0x35/0x37
> ls7a1000  gmac    7a03      0x35/0x37
> ls2k2000  gnet    7a13      0x10
> ls7a2000  gnet    7a13      0x37
> 
> The ref/ptp clock of gmac is 125000000. gmac device only
> has a MAC chip inside and needs an external PHY chip;
> 
> Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
> Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
> Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
> ---
>  .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 21 +++++++++++++------
>  1 file changed, 15 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> index 995c9bd144e0..ad19b4087974 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> @@ -9,7 +9,8 @@
>  #include <linux/of_irq.h>
>  #include "stmmac.h"
>  
> -static int loongson_default_data(struct plat_stmmacenet_data *plat)
> +static void loongson_default_data(struct pci_dev *pdev,
> +				  struct plat_stmmacenet_data *plat)
>  {
>  	plat->clk_csr = 2;	/* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */
>  	plat->has_gmac = 1;
> @@ -24,16 +25,18 @@ static int loongson_default_data(struct plat_stmmacenet_data *plat)
>  	/* Set the maxmtu to a default of JUMBO_LEN */
>  	plat->maxmtu = JUMBO_LEN;
>  
> -	/* Set default number of RX and TX queues to use */
> -	plat->tx_queues_to_use = 1;
> -	plat->rx_queues_to_use = 1;
> -
>  	/* Disable Priority config by default */
>  	plat->tx_queues_cfg[0].use_prio = false;
>  	plat->rx_queues_cfg[0].use_prio = false;
>  
>  	/* Disable RX queues routing by default */
>  	plat->rx_queues_cfg[0].pkt_route = 0x0;
> +}
> +
> +static int loongson_gmac_data(struct pci_dev *pdev,
> +			      struct plat_stmmacenet_data *plat)
> +{
> +	loongson_default_data(pdev, plat);
>  
>  	/* Default to phy auto-detection */
>  	plat->phy_addr = -1;
> @@ -42,6 +45,12 @@ static int loongson_default_data(struct plat_stmmacenet_data *plat)
>  	plat->dma_cfg->pblx8 = true;
>  

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

This change is unrelated to the rest of the changes in this patch.
Please split the patch up into two:
1. Add ref and ptp clocks for Loongson GMAC
2. Split up the platform data initialization
First one is a new feature adding the actual ref clock rates to the
driver. The second patch is a preparation before adding the full PCI
support.

-Serge(y)

> +
> +	plat->tx_queues_to_use = 1;
> +	plat->rx_queues_to_use = 1;
> +
>  	return 0;
>  }
>  
> @@ -114,7 +123,7 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
>  
>  	pci_set_master(pdev);
>  
> -	loongson_default_data(plat);
> +	loongson_gmac_data(pdev, plat);
>  	pci_enable_msi(pdev);
>  	memset(&res, 0, sizeof(res));
>  	res.addr = pcim_iomap_table(pdev)[0];
> -- 
> 2.31.4
> 

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

* Re: [PATCH net-next v11 3/6] net: stmmac: dwmac-loongson: Use PCI_DEVICE_DATA() macro for device identification
  2024-04-18 11:14       ` Serge Semin
@ 2024-04-18 12:31         ` Serge Semin
  2024-04-19  9:40           ` Yanteng Si
  0 siblings, 1 reply; 36+ messages in thread
From: Serge Semin @ 2024-04-18 12:31 UTC (permalink / raw)
  To: Yanteng Si
  Cc: Jakub Kicinski, andrew, hkallweit1, peppe.cavallaro,
	alexandre.torgue, joabreu, Jose.Abreu, chenhuacai, linux,
	guyinggang, netdev, chris.chenfeiyang, siyanteng01

On Thu, Apr 18, 2024 at 02:14:17PM +0300, Serge Semin wrote:
> On Mon, Apr 15, 2024 at 10:21:39AM +0800, Yanteng Si wrote:
> > > > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > > index 9e40c28d453a..995c9bd144e0 100644
> > > > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > > @@ -213,7 +213,7 @@ static SIMPLE_DEV_PM_OPS(loongson_dwmac_pm_ops, loongson_dwmac_suspend,
> > > >   			 loongson_dwmac_resume);
> > > >   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);
> > > In file included from ../drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c:6:
> > > ../include/linux/pci.h:1061:51: error: ‘PCI_DEVICE_ID_LOONGSON_GMAC’ undeclared here (not in a function); did you mean ‘PCI_DEVICE_ID_LOONGSON_HDA’?
> > >   1061 |         .vendor = PCI_VENDOR_ID_##vend, .device = PCI_DEVICE_ID_##vend##_##dev, \
> > >        |                                                   ^~~~~~~~~~~~~~
> > > ../drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c:216:11: note: in expansion of macro ‘PCI_DEVICE_DATA’
> > >    216 |         { PCI_DEVICE_DATA(LOONGSON, GMAC, &loongson_gmac_pci_info) },
> > >        |           ^~~~~~~~~~~~~~~
> > > ../drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c:216:44: error: ‘loongson_gmac_pci_info’ undeclared here (not in a function)
> > >    216 |         { PCI_DEVICE_DATA(LOONGSON, GMAC, &loongson_gmac_pci_info) },
> > >        |                                            ^~~~~~~~~~~~~~~~~~~~~~
> > > ../include/linux/pci.h:1063:41: note: in definition of macro ‘PCI_DEVICE_DATA’
> > >   1063 |         .driver_data = (kernel_ulong_t)(data)
> > >        |                                         ^~~~
> > 
> 
> > Will be fixed in v12.
> 

> Just move the PCI_DEVICE_ID_LOONGSON_GMAC macro definition from Patch
> 5/6 to this one.

... and of course pass NULL as the data-pointer to PCI_DEVICE_DATA().

-Serge(y)

> 
> -Serge(y)
> 
> > 
> > 
> > Thanks,
> > 
> > Yanteng
> > 

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

* Re: [PATCH net-next v11 5/6] net: stmmac: dwmac-loongson: Add full PCI support
  2024-04-12 11:28 ` [PATCH net-next v11 5/6] net: stmmac: dwmac-loongson: Add full PCI support Yanteng Si
@ 2024-04-18 13:08   ` Serge Semin
  2024-04-20  2:41     ` Yanteng Si
  0 siblings, 1 reply; 36+ messages in thread
From: Serge Semin @ 2024-04-18 13:08 UTC (permalink / raw)
  To: Yanteng Si
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang, siyanteng01

On Fri, Apr 12, 2024 at 07:28:50PM +0800, Yanteng Si wrote:
> Current dwmac-loongson only support LS2K in the "probed with PCI and
> configured with DT" manner. Add LS7A support on which the devices are
> fully PCI (non-DT).
> 
> Others:
> LS2K is a SoC and LS7A is a bridge chip. In the current driving state,
> they are both gmac and phy_interface is RGMII.
> 
> Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
> Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
> Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
> ---
>  .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 103 +++++++++++-------
>  1 file changed, 64 insertions(+), 39 deletions(-)
> 
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> index ad19b4087974..69078eb1f923 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> @@ -9,9 +9,19 @@
>  #include <linux/of_irq.h>
>  #include "stmmac.h"
>  
> +#define PCI_DEVICE_ID_LOONGSON_GMAC	0x7a03
> +
> +struct stmmac_pci_info {
> +	int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat);
> +};
> +
>  static void loongson_default_data(struct pci_dev *pdev,
>  				  struct plat_stmmacenet_data *plat)
>  {
> +	/* Get bus_id, this can be overloaded later */
> +	plat->bus_id = (pci_domain_nr(pdev->bus) << 16) |
> +		       PCI_DEVID(pdev->bus->number, pdev->devfn);
> +
>  	plat->clk_csr = 2;	/* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */
>  	plat->has_gmac = 1;
>  	plat->force_sf_dma_mode = 1;
> @@ -40,6 +50,7 @@ static int loongson_gmac_data(struct pci_dev *pdev,
>  
>  	/* Default to phy auto-detection */
>  	plat->phy_addr = -1;
> +	plat->phy_interface = PHY_INTERFACE_MODE_RGMII_ID;
>  
>  	plat->dma_cfg->pbl = 32;
>  	plat->dma_cfg->pblx8 = true;
> @@ -54,19 +65,17 @@ static int loongson_gmac_data(struct pci_dev *pdev,
>  	return 0;
>  }
>  
> +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)
>  {
>  	struct plat_stmmacenet_data *plat;
> +	int ret, i, bus_id, phy_mode;
> +	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;
> -	}

Hm, I see you dropping this snippet and never getting it back in this
patch. Thus after the patch is applied np will be left uninitialized,
which will completely break the driver. Please make sure it's fixed.

This problem has been introduced at the v9 stage, which I didn't have
time to review. There were no problem like that in v8.

-Serge(y)

>  
>  	plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL);
>  	if (!plat)
> @@ -78,12 +87,6 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
>  	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->needs_reset = true;
> -	}
> -
>  	plat->dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*plat->dma_cfg), GFP_KERNEL);
>  	if (!plat->dma_cfg) {
>  		ret = -ENOMEM;
> @@ -107,10 +110,6 @@ 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);
> -
>  	phy_mode = device_get_phy_mode(&pdev->dev);
>  	if (phy_mode < 0) {
>  		dev_err(&pdev->dev, "phy_mode not found\n");
> @@ -123,30 +122,56 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
>  
>  	pci_set_master(pdev);
>  
> -	loongson_gmac_data(pdev, plat);
> -	pci_enable_msi(pdev);
> -	memset(&res, 0, sizeof(res));
> -	res.addr = pcim_iomap_table(pdev)[0];
> -
> -	res.irq = of_irq_get_byname(np, "macirq");
> -	if (res.irq < 0) {
> -		dev_err(&pdev->dev, "IRQ macirq not found\n");
> -		ret = -ENODEV;
> -		goto err_disable_msi;
> -	}
> +	info = (struct stmmac_pci_info *)id->driver_data;
> +	ret = info->setup(pdev, plat);
> +	if (ret)
> +		goto err_disable_device;
>  
> -	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;
> +	if (np) {
> +		plat->mdio_node = of_get_child_by_name(np, "mdio");
> +		if (plat->mdio_node) {
> +			dev_info(&pdev->dev, "Found MDIO subnode\n");
> +			plat->mdio_bus_data->needs_reset = true;
> +		}
> +
> +		bus_id = of_alias_get_id(np, "ethernet");
> +		if (bus_id >= 0)
> +			plat->bus_id = bus_id;
> +
> +		phy_mode = device_get_phy_mode(&pdev->dev);
> +		if (phy_mode < 0) {
> +			dev_err(&pdev->dev, "phy_mode not found\n");
> +			ret = phy_mode;
> +			goto err_disable_device;
> +		}
> +		plat->phy_interface = phy_mode;
> +
> +		res.irq = of_irq_get_byname(np, "macirq");
> +		if (res.irq < 0) {
> +			dev_err(&pdev->dev, "IRQ macirq not found\n");
> +			ret = -ENODEV;
> +			goto err_disable_msi;
> +		}
> +
> +		res.wol_irq = of_irq_get_byname(np, "eth_wake_irq");
> +		if (res.wol_irq < 0) {
> +			dev_info(&pdev->dev, "IRQ eth_wake_irq not found, using macirq\n");
> +			res.wol_irq = res.irq;
> +		}
> +
> +		res.lpi_irq = of_irq_get_byname(np, "eth_lpi");
> +		if (res.lpi_irq < 0) {
> +			dev_err(&pdev->dev, "IRQ eth_lpi not found\n");
> +			ret = -ENODEV;
> +			goto err_disable_msi;
> +		}
> +	} else {
> +		res.irq = pdev->irq;
>  	}
>  
> -	res.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;
> -	}
> +	pci_enable_msi(pdev);
> +	memset(&res, 0, sizeof(res));
> +	res.addr = pcim_iomap_table(pdev)[0];
>  
>  	ret = stmmac_dvr_probe(&pdev->dev, plat, &res);
>  	if (ret)
> -- 
> 2.31.4
> 

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

* Re: [PATCH net-next v11 6/6] net: stmmac: dwmac-loongson: Add Loongson GNET support
  2024-04-12 11:28 ` [PATCH net-next v11 6/6] net: stmmac: dwmac-loongson: Add Loongson GNET support Yanteng Si
@ 2024-04-18 14:01   ` Serge Semin
  2024-04-20 11:02     ` Yanteng Si
                       ` (2 more replies)
  2024-04-24 13:37   ` Huacai Chen
  1 sibling, 3 replies; 36+ messages in thread
From: Serge Semin @ 2024-04-18 14:01 UTC (permalink / raw)
  To: Yanteng Si
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang, siyanteng01

On Fri, Apr 12, 2024 at 07:28:51PM +0800, Yanteng Si wrote:
> There are two types of Loongson DWGMAC. The first type shares the same
> register definitions and has similar logic as dwmac1000. The second type
> uses several different register definitions, we think it is necessary to
> distinguish rx and tx, so we split these bits into two.
> 
> Simply put, we split some single bit fields into double bits fileds:
> 
>      Name              Tx          Rx
> 
> DMA_INTR_ENA_NIE = 0x00040000 | 0x00020000;
> DMA_INTR_ENA_AIE = 0x00010000 | 0x00008000;
> DMA_STATUS_NIS   = 0x00040000 | 0x00020000;
> DMA_STATUS_AIS   = 0x00010000 | 0x00008000;
> DMA_STATUS_FBI   = 0x00002000 | 0x00001000;
> 
> Therefore, when using, TX and RX must be set at the same time.
> 
> How to use them:
>  1. Create the Loongson GNET-specific
>  stmmac_dma_ops.dma_interrupt()
>  stmmac_dma_ops.init_chan()
>  methods in the dwmac-loongson.c driver. Adding all the
>  Loongson-specific macros
> 
>  2. Create a Loongson GNET-specific platform setup method with the next
>  semantics:
>     + allocate stmmac_dma_ops instance and initialize it with
>       dwmac1000_dma_ops.
>     + override the stmmac_dma_ops.{dma_interrupt, init_chan} with
>       the pointers to the methods defined in 2.
>     + allocate mac_device_info instance and initialize the
>       mac_device_info.dma field with a pointer to the new
>       stmmac_dma_ops instance.
>     + initialize mac_device_info in a way it's done in
>       dwmac1000_setup().
> 
>  3. Initialize plat_stmmacenet_data.setup() with the pointer to the
>  method created in 2.
> 
> GNET features:
> 
>  Speeds: 10/100/1000Mbps

>  DMA-descriptors type: normal and enhanced

Hm, it's either one or another. They can't be both supported because
the alternative descriptors are enabled by the DESC_ENHANCED_FORMAT
HDL parameter defined on the IP-core synthesize stage.

>  L3/L4 filters availability: support
>  VLAN hash table filter: support
>  PHY-interface: GMII
>  Remote Wake-up support: support
>  Mac Management Counters (MMC): support
>  DMA chennel number: 0x10 device is 8 and 0x37 device is 1

What about adding the info like:
Number of additional MAC addresses
MAC Hash-based filter support and if supported the hash table size.

> 
> Others:
> 
>  GNET integrates both MAC and PHY chips inside.
>  GNET device: LS2K2000, LS7A2000, the chip connection between the mac and
>              phy of these devices is not normal and requires two rounds of
>              negotiation; LS7A2000 does not support half-duplex and
>              multi-channel;
> 
>              To enable multi-channel on LS2K2000, you need to turn off
>              hardware checksum.
> 

> **Note**: Currently, only the LS2K2000's IP core is 0x10,

This doesn't sound correct. The LS2K2000's IP-core is v3.73a. But the
SNPS Version ID was manually altered by the hardware designers.

> while the IP
> cores of other devices are 0x37.

Real IP-core ID isn't described by the hex number. It's a digit number
like v3.73a/v3.50a/etc. Hex number you constantly repeat is the
MAC_Version.SNPSVER register value. So please use the IP-core version
in the v3.xx format all over the patch text.

> 
> Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
> Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
> Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
> ---
>  drivers/net/ethernet/stmicro/stmmac/common.h  |   2 +
>  .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 476 ++++++++++++++++--
>  .../ethernet/stmicro/stmmac/dwmac1000_dma.c   |   1 +
>  .../ethernet/stmicro/stmmac/stmmac_ethtool.c  |   6 +
>  include/linux/stmmac.h                        |   1 +
>  5 files changed, 447 insertions(+), 39 deletions(-)
> 
> diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
> index 9cd62b2110a1..6777dc997e9f 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/common.h
> +++ b/drivers/net/ethernet/stmicro/stmmac/common.h
> @@ -29,6 +29,7 @@
>  /* 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
> @@ -258,6 +259,7 @@ struct stmmac_safety_stats {
>  #define CSR_F_300M	300000000
>  
>  #define	MAC_CSR_H_FRQ_MASK	0x20

> +#define	MAC_CTRL_PORT_SELECT_10_100	BIT(15)

No, this is already defined in:
drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
as GMAC_CONTROL_PS macros. Use it instead of adding new macros.

>  
>  #define HASH_TABLE_SIZE 64
>  #define PAUSE_TIME 0xffff
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> index 69078eb1f923..4edfbb4fcb64 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> @@ -8,8 +8,70 @@
>  #include <linux/device.h>
>  #include <linux/of_irq.h>
>  #include "stmmac.h"
> +#include "dwmac_dma.h"
> +#include "dwmac1000.h"
> +
> +/* Normal Loongson Tx Summary */
> +#define DMA_INTR_ENA_NIE_TX_LOONGSON	0x00040000
> +/* Normal Loongson Rx Summary */
> +#define DMA_INTR_ENA_NIE_RX_LOONGSON	0x00020000
> +
> +#define DMA_INTR_NORMAL_LOONGSON	(DMA_INTR_ENA_NIE_TX_LOONGSON | \
> +					 DMA_INTR_ENA_NIE_RX_LOONGSON | \
> +					 DMA_INTR_ENA_RIE | DMA_INTR_ENA_TIE)
> +
> +/* Abnormal Loongson Tx Summary */
> +#define DMA_INTR_ENA_AIE_TX_LOONGSON	0x00010000
> +/* Abnormal Loongson Rx Summary */
> +#define DMA_INTR_ENA_AIE_RX_LOONGSON	0x00008000
> +
> +#define DMA_INTR_ABNORMAL_LOONGSON	(DMA_INTR_ENA_AIE_TX_LOONGSON | \
> +					 DMA_INTR_ENA_AIE_RX_LOONGSON | \
> +					 DMA_INTR_ENA_FBE | DMA_INTR_ENA_UNE)
> +
> +#define DMA_INTR_DEFAULT_MASK_LOONGSON	(DMA_INTR_NORMAL_LOONGSON | \
> +					 DMA_INTR_ABNORMAL_LOONGSON)
> +
> +/* Normal Loongson Tx Interrupt Summary */
> +#define DMA_STATUS_NIS_TX_LOONGSON	0x00040000
> +/* Normal Loongson Rx Interrupt Summary */
> +#define DMA_STATUS_NIS_RX_LOONGSON	0x00020000
> +
> +/* Abnormal Loongson Tx Interrupt Summary */
> +#define DMA_STATUS_AIS_TX_LOONGSON	0x00010000
> +/* Abnormal Loongson Rx Interrupt Summary */
> +#define DMA_STATUS_AIS_RX_LOONGSON	0x00008000
> +
> +/* Fatal Loongson Tx Bus Error Interrupt */
> +#define DMA_STATUS_FBI_TX_LOONGSON	0x00002000
> +/* Fatal Loongson Rx Bus Error Interrupt */
> +#define DMA_STATUS_FBI_RX_LOONGSON	0x00001000
> +
> +#define DMA_STATUS_MSK_COMMON_LOONGSON	(DMA_STATUS_NIS_TX_LOONGSON | \
> +					 DMA_STATUS_NIS_RX_LOONGSON | \
> +					 DMA_STATUS_AIS_TX_LOONGSON | \
> +					 DMA_STATUS_AIS_RX_LOONGSON | \
> +					 DMA_STATUS_FBI_TX_LOONGSON | \
> +					 DMA_STATUS_FBI_RX_LOONGSON)
> +
> +#define DMA_STATUS_MSK_RX_LOONGSON	(DMA_STATUS_ERI | DMA_STATUS_RWT | \
> +					 DMA_STATUS_RPS | DMA_STATUS_RU  | \
> +					 DMA_STATUS_RI  | DMA_STATUS_OVF | \
> +					 DMA_STATUS_MSK_COMMON_LOONGSON)
> +
> +#define DMA_STATUS_MSK_TX_LOONGSON	(DMA_STATUS_ETI | DMA_STATUS_UNF | \
> +					 DMA_STATUS_TJT | DMA_STATUS_TU  | \
> +					 DMA_STATUS_TPS | DMA_STATUS_TI  | \
> +					 DMA_STATUS_MSK_COMMON_LOONGSON)
>  
>  #define PCI_DEVICE_ID_LOONGSON_GMAC	0x7a03
> +#define PCI_DEVICE_ID_LOONGSON_GNET	0x7a13
> +#define LOONGSON_DWMAC_CORE_1_00	0x10	/* Loongson custom IP */
> +#define CHANNEL_NUM			8
> +
> +struct loongson_data {
> +	struct device *dev;
> +};
>  
>  struct stmmac_pci_info {
>  	int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat);
> @@ -56,6 +117,8 @@ static int loongson_gmac_data(struct pci_dev *pdev,
>  	plat->dma_cfg->pblx8 = true;
>  
>  	plat->multicast_filter_bins = 256;

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

And this change isn't related to the GNET. Why is it here?

>  	plat->clk_ref_rate = 125000000;
>  	plat->clk_ptp_rate = 125000000;
>  
> @@ -69,13 +132,342 @@ 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)
> +static void loongson_gnet_dma_init_channel(struct stmmac_priv *priv,
> +					   void __iomem *ioaddr,
> +					   struct stmmac_dma_cfg *dma_cfg,
> +					   u32 chan)
> +{
> +	int txpbl = dma_cfg->txpbl ?: dma_cfg->pbl;
> +	int rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl;
> +	u32 value;
> +

> +	/* common channel control register config */

Useless comment. Please drop.

> +	value = readl(ioaddr + DMA_CHAN_BUS_MODE(chan));
> +

> +	/* Set the DMA PBL (Programmable Burst Length) mode.
> +	 *
> +	 * Note: before stmmac core 3.50 this mode bit was 4xPBL, and
> +	 * post 3.5 mode bit acts as 8*PBL.
> +	 */

Do you have an IP-core older than v3.50a? No. So please drop the
comment.

> +	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;
> +
> +	if (dma_cfg->atds)
> +		value |= DMA_BUS_MODE_ATDS;
> +
> +	if (dma_cfg->aal)
> +		value |= DMA_BUS_MODE_AAL;
> +
> +	writel(value, ioaddr + DMA_CHAN_BUS_MODE(chan));
> +
> +	/* Mask interrupts by writing to CSR7 */
> +	writel(DMA_INTR_DEFAULT_MASK_LOONGSON, ioaddr +
> +	       DMA_CHAN_INTR_ENA(chan));
> +}
> +
> +static int loongson_gnet_dma_interrupt(struct stmmac_priv *priv,
> +				       void __iomem *ioaddr,
> +				       struct stmmac_extra_stats *x,
> +				       u32 chan, u32 dir)
> +{
> +	struct stmmac_pcpu_stats *stats = this_cpu_ptr(priv->xstats.pcpu_stats);
> +	u32 abnor_intr_status;
> +	u32 nor_intr_status;
> +	u32 fb_intr_status;
> +	u32 intr_status;
> +	int ret = 0;
> +
> +	/* read the status register (CSR5) */
> +	intr_status = readl(ioaddr + DMA_CHAN_STATUS(chan));
> +
> +	if (dir == DMA_DIR_RX)
> +		intr_status &= DMA_STATUS_MSK_RX_LOONGSON;
> +	else if (dir == DMA_DIR_TX)
> +		intr_status &= DMA_STATUS_MSK_TX_LOONGSON;
> +
> +	nor_intr_status = intr_status & (DMA_STATUS_NIS_TX_LOONGSON |
> +		DMA_STATUS_NIS_RX_LOONGSON);
> +	abnor_intr_status = intr_status & (DMA_STATUS_AIS_TX_LOONGSON |
> +		DMA_STATUS_AIS_RX_LOONGSON);
> +	fb_intr_status = intr_status & (DMA_STATUS_FBI_TX_LOONGSON |
> +		DMA_STATUS_FBI_RX_LOONGSON);
> +
> +	/* ABNORMAL interrupts */
> +	if (unlikely(abnor_intr_status)) {
> +		if (unlikely(intr_status & DMA_STATUS_UNF)) {
> +			ret = tx_hard_error_bump_tc;
> +			x->tx_undeflow_irq++;
> +		}
> +		if (unlikely(intr_status & DMA_STATUS_TJT))
> +			x->tx_jabber_irq++;
> +		if (unlikely(intr_status & DMA_STATUS_OVF))
> +			x->rx_overflow_irq++;
> +		if (unlikely(intr_status & DMA_STATUS_RU))
> +			x->rx_buf_unav_irq++;
> +		if (unlikely(intr_status & DMA_STATUS_RPS))
> +			x->rx_process_stopped_irq++;
> +		if (unlikely(intr_status & DMA_STATUS_RWT))
> +			x->rx_watchdog_irq++;
> +		if (unlikely(intr_status & DMA_STATUS_ETI))
> +			x->tx_early_irq++;
> +		if (unlikely(intr_status & DMA_STATUS_TPS)) {
> +			x->tx_process_stopped_irq++;
> +			ret = tx_hard_error;
> +		}
> +		if (unlikely(fb_intr_status)) {
> +			x->fatal_bus_error_irq++;
> +			ret = tx_hard_error;
> +		}
> +	}
> +	/* TX/RX NORMAL interrupts */
> +	if (likely(nor_intr_status)) {
> +		if (likely(intr_status & DMA_STATUS_RI)) {
> +			u32 value = readl(ioaddr + DMA_INTR_ENA);
> +			/* to schedule NAPI on real RIE event. */
> +			if (likely(value & DMA_INTR_ENA_RIE)) {
> +				u64_stats_update_begin(&stats->syncp);
> +				u64_stats_inc(&stats->rx_normal_irq_n[chan]);
> +				u64_stats_update_end(&stats->syncp);
> +				ret |= handle_rx;
> +			}
> +		}
> +		if (likely(intr_status & DMA_STATUS_TI)) {
> +			u64_stats_update_begin(&stats->syncp);
> +			u64_stats_inc(&stats->tx_normal_irq_n[chan]);
> +			u64_stats_update_end(&stats->syncp);
> +			ret |= handle_tx;
> +		}
> +		if (unlikely(intr_status & DMA_STATUS_ERI))
> +			x->rx_early_irq++;
> +	}
> +	/* Optional hardware blocks, interrupts should be disabled */
> +	if (unlikely(intr_status &
> +		     (DMA_STATUS_GPI | DMA_STATUS_GMI | DMA_STATUS_GLI)))
> +		pr_warn("%s: unexpected status %08x\n", __func__, intr_status);
> +
> +	/* Clear the interrupt by writing a logic 1 to the CSR5[15-0] */
> +	writel((intr_status & 0x7ffff), ioaddr + DMA_CHAN_STATUS(chan));
> +
> +	return ret;
> +}
> +
> +static void loongson_gnet_fix_speed(void *priv, unsigned int speed,
> +				    unsigned int mode)
> +{
> +	struct loongson_data *ld = (struct loongson_data *)priv;
> +	struct net_device *ndev = dev_get_drvdata(ld->dev);
> +	struct stmmac_priv *ptr = netdev_priv(ndev);
> +
> +	/* The controller and PHY don't work well together.
> +	 * We need to use the PS bit to check if the controller's status
> +	 * is correct and reset PHY if necessary.
> +	 * MAC_CTRL_REG.15 is defined by the GMAC_CONTROL_PS macro.
> +	 */
> +	if (speed == SPEED_1000) {
> +		if (readl(ptr->ioaddr + MAC_CTRL_REG) &

> +		    MAC_CTRL_PORT_SELECT_10_100)

GMAC_CONTROL_PS?

> +			/* Word around hardware bug, restart autoneg */
> +			phy_restart_aneg(ndev->phydev);
> +	}
> +}
> +
> +static int loongson_gnet_data(struct pci_dev *pdev,
> +			      struct plat_stmmacenet_data *plat)
> +{
> +	loongson_default_data(pdev, plat);
> +
> +	plat->phy_addr = -1;
> +	plat->phy_interface = PHY_INTERFACE_MODE_GMII;
> +
> +	plat->dma_cfg->pbl = 32;
> +	plat->dma_cfg->pblx8 = true;
> +
> +	plat->multicast_filter_bins = 256;
> +	plat->mdio_bus_data->phy_mask = ~(u32)BIT(2);
> +

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

If this is common for both GMAC and GNET what about moving it to the
loongson_default_data() method?

If so please just do that in the patch 4 where you get to add these
fields initialization in the first place.

> +
> +	plat->fix_mac_speed = loongson_gnet_fix_speed;
> +
> +	return 0;
> +}
> +
> +static struct stmmac_pci_info loongson_gnet_pci_info = {
> +	.setup = loongson_gnet_data,
> +};
> +
> +static int loongson_dwmac_config_legacy(struct pci_dev *pdev,
> +					struct plat_stmmacenet_data *plat,
> +					struct stmmac_resources *res,
> +					struct device_node *np)
> +{
> +	if (np) {
> +		res->irq = of_irq_get_byname(np, "macirq");
> +		if (res->irq < 0) {
> +			dev_err(&pdev->dev, "IRQ macirq not found\n");
> +			return -ENODEV;
> +		}
> +
> +		res->wol_irq = of_irq_get_byname(np, "eth_wake_irq");
> +		if (res->wol_irq < 0) {
> +			dev_info(&pdev->dev,
> +				 "IRQ eth_wake_irq not found, using macirq\n");
> +			res->wol_irq = res->irq;
> +		}
> +
> +		res->lpi_irq = of_irq_get_byname(np, "eth_lpi");
> +		if (res->lpi_irq < 0) {
> +			dev_err(&pdev->dev, "IRQ eth_lpi not found\n");
> +			return -ENODEV;
> +		}
> +	} else {
> +		res->irq = pdev->irq;
> +		res->wol_irq = res->irq;
> +	}
> +
> +	return 0;
> +}
> +
> +static int loongson_dwmac_config_msi(struct pci_dev *pdev,
> +				     struct plat_stmmacenet_data *plat,
> +				     struct stmmac_resources *res,
> +				     struct device_node *np)
> +{
> +	int i, ret, vecs;
> +
> +	vecs = roundup_pow_of_two(CHANNEL_NUM * 2 + 1);
> +	ret = pci_alloc_irq_vectors(pdev, vecs, vecs, PCI_IRQ_MSI);
> +	if (ret < 0) {
> +		dev_info(&pdev->dev,
> +			 "MSI enable failed, Fallback to legacy interrupt\n");
> +		return loongson_dwmac_config_legacy(pdev, plat, res, np);
> +	}
> +
> +	res->irq = pci_irq_vector(pdev, 0);
> +	res->wol_irq = 0;
> +
> +	/* INT NAME | MAC | CH7 rx | CH7 tx | ... | CH0 rx | CH0 tx |
> +	 * --------- ----- -------- --------  ...  -------- --------
> +	 * IRQ NUM  |  0  |   1    |   2    | ... |   15   |   16   |
> +	 */
> +	for (i = 0; i < CHANNEL_NUM; i++) {
> +		res->rx_irq[CHANNEL_NUM - 1 - i] =
> +			pci_irq_vector(pdev, 1 + i * 2);
> +		res->tx_irq[CHANNEL_NUM - 1 - i] =
> +			pci_irq_vector(pdev, 2 + i * 2);
> +	}
> +
> +	plat->flags |= STMMAC_FLAG_MULTI_MSI_EN;

Once again. Please replace this with simpler solution:

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


> +
> +	return 0;
> +}
> +
> +static struct mac_device_info *loongson_dwmac_setup(void *apriv)
> +{
> +	struct stmmac_priv *priv = apriv;
> +	struct stmmac_resources res;
> +	struct mac_device_info *mac;
> +	struct stmmac_dma_ops *dma;
> +	struct pci_dev *pdev;
> +	u32 loongson_gmac;
> +
> +	memset(&res, 0, sizeof(res));
> +	pdev = to_pci_dev(priv->device);
> +	res.addr = pcim_iomap_table(pdev)[0];
> +	loongson_gmac = readl(res.addr + GMAC_VERSION) & 0xff;
> +
> +	mac = devm_kzalloc(priv->device, sizeof(*mac), GFP_KERNEL);
> +	if (!mac)
> +		return NULL;
> +
> +	dma = devm_kzalloc(priv->device, sizeof(*dma), GFP_KERNEL);
> +	if (!dma)
> +		return NULL;
> +
> +	/* The original IP-core version is 0x37 in all Loongson GNET
> +	 * (ls2k2000 and ls7a2000), but the GNET HW designers have changed the
> +	 * GMAC_VERSION.SNPSVER field to the custom 0x10 value on the Loongson
> +	 * ls2k2000 MAC to emphasize the differences: multiple DMA-channels,
> +	 * AV feature and GMAC_INT_STATUS CSR flags layout. Get back the
> +	 * original value so the correct HW-interface would be selected.
> +	 */
> +	if (loongson_gmac == LOONGSON_DWMAC_CORE_1_00) {
> +		priv->synopsys_id = DWMAC_CORE_3_70;
> +		*dma = dwmac1000_dma_ops;
> +		dma->init_chan = loongson_gnet_dma_init_channel;
> +		dma->dma_interrupt = loongson_gnet_dma_interrupt;
> +		mac->dma = dma;
> +	}
> +
> +	mac->mac = &dwmac1000_ops;
> +	priv->dev->priv_flags |= IFF_UNICAST_FLT;
> +
> +	/* Pre-initialize the respective "mac" fields as it's done in
> +	 * dwmac1000_setup()
> +	 */
> +	mac->pcsr = priv->ioaddr;
> +	mac->multicast_filter_bins = priv->plat->multicast_filter_bins;
> +	mac->unicast_filter_entries = priv->plat->unicast_filter_entries;
> +	mac->mcast_bits_log2 = 0;
> +
> +	if (mac->multicast_filter_bins)
> +		mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins);
> +
> +	/* The GMAC devices with PCI ID 0x7a03 does not support any pause mode.
> +	 * The GNET devices without CORE ID 0x10 does not support half-duplex.
> +	 */
> +	if (pdev->device == PCI_DEVICE_ID_LOONGSON_GMAC) {
> +		mac->link.caps = MAC_10 | MAC_100 | MAC_1000;
> +	} else {
> +		if (loongson_gmac == LOONGSON_DWMAC_CORE_1_00)
> +			mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
> +					 MAC_10 | MAC_100 | MAC_1000;
> +		else
> +			mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
> +					 MAC_10FD | MAC_100FD | MAC_1000FD;
> +	}
> +
> +	mac->link.duplex = GMAC_CONTROL_DM;
> +	mac->link.speed10 = GMAC_CONTROL_PS;
> +	mac->link.speed100 = GMAC_CONTROL_PS | GMAC_CONTROL_FES;
> +	mac->link.speed1000 = 0;
> +	mac->link.speed_mask = GMAC_CONTROL_PS | GMAC_CONTROL_FES;
> +	mac->mii.addr = GMAC_MII_ADDR;
> +	mac->mii.data = GMAC_MII_DATA;
> +	mac->mii.addr_shift = 11;
> +	mac->mii.addr_mask = 0x0000F800;
> +	mac->mii.reg_shift = 6;
> +	mac->mii.reg_mask = 0x000007C0;
> +	mac->mii.clk_csr_shift = 2;
> +	mac->mii.clk_csr_mask = GENMASK(5, 2);
> +
> +	return mac;
> +}
> +
> +static int loongson_dwmac_probe(struct pci_dev *pdev,
> +				const struct pci_device_id *id)
>  {
>  	struct plat_stmmacenet_data *plat;
>  	int ret, i, bus_id, phy_mode;
>  	struct stmmac_pci_info *info;
>  	struct stmmac_resources res;
> +	struct loongson_data *ld;
>  	struct device_node *np;
> +	u32 loongson_gmac;
>  
>  	plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL);
>  	if (!plat)
> @@ -88,10 +482,14 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
>  		return -ENOMEM;
>  
>  	plat->dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*plat->dma_cfg), GFP_KERNEL);
> -	if (!plat->dma_cfg) {
> -		ret = -ENOMEM;
> -		goto err_put_node;
> -	}
> +	if (!plat->dma_cfg)
> +		return -ENOMEM;
> +
> +	ld = devm_kzalloc(&pdev->dev, sizeof(*ld), GFP_KERNEL);
> +	if (!ld)
> +		return -ENOMEM;
> +

> +	np = dev_of_node(&pdev->dev);

Here is the missing np from the patch 5...

>  
>  	/* Enable pci device */
>  	ret = pci_enable_device(pdev);
> @@ -110,14 +508,6 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
>  		break;
>  	}
>  

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

This change must have been added to the Patch 5 where you get to move
all the NP-related things into the "if (np) {}" clause!

>  	plat->mac_interface = PHY_INTERFACE_MODE_GMII;
>  
>  	pci_set_master(pdev);
> @@ -133,7 +523,6 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
>  			dev_info(&pdev->dev, "Found MDIO subnode\n");
>  			plat->mdio_bus_data->needs_reset = true;
>  		}
> -
>  		bus_id = of_alias_get_id(np, "ethernet");
>  		if (bus_id >= 0)
>  			plat->bus_id = bus_id;
> @@ -145,42 +534,49 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
>  			goto err_disable_device;
>  		}
>  		plat->phy_interface = phy_mode;

> +	}
>  
> -		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;
> -		}
> +	plat->bsp_priv = ld;
> +	plat->setup = loongson_dwmac_setup;
> +	ld->dev = &pdev->dev;
>  
> -		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;
> -		}
> +	memset(&res, 0, sizeof(res));
> +	res.addr = pcim_iomap_table(pdev)[0];
> +	loongson_gmac = readl(res.addr + GMAC_VERSION) & 0xff;
>  
> -		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;

Please, move the loongson_dwmac_config_legacy() method creation change
into a preparation/pre-requisite patch. That will vastly simplify this
patch and will help with reviewing it!

> +	switch (loongson_gmac) {
> +	case LOONGSON_DWMAC_CORE_1_00:
> +		plat->rx_queues_to_use = CHANNEL_NUM;
> +		plat->tx_queues_to_use = CHANNEL_NUM;
> +
> +		/* Only channel 0 supports checksum,
> +		 * so turn off checksum to enable multiple channels.
> +		 */
> +		for (i = 1; i < CHANNEL_NUM; i++)
> +			plat->tx_queues_cfg[i].coe_unsupported = 1;
> +
> +		ret = loongson_dwmac_config_msi(pdev, plat, &res, np);
> +		break;
> +	default:	/* 0x35 device and 0x37 device. */
> +		plat->tx_queues_to_use = 1;
> +		plat->rx_queues_to_use = 1;
> +		ret = loongson_dwmac_config_legacy(pdev, plat, &res, np);
> +		break;
>  	}
>  
> -	pci_enable_msi(pdev);
> -	memset(&res, 0, sizeof(res));
> -	res.addr = pcim_iomap_table(pdev)[0];

> +	/* GNET devices with dev revision 0x00 do not support manually
> +	 * setting the speed to 1000.
> +	 */
> +	if (pdev->device == PCI_DEVICE_ID_LOONGSON_GNET &&
> +	    pdev->revision == 0x00)
> +		plat->flags |= STMMAC_FLAG_DISABLE_FORCE_1000;

Move this to the loongson_gnet_data() method.

>  
>  	ret = stmmac_dvr_probe(&pdev->dev, plat, &res);
>  	if (ret)
> -		goto err_disable_msi;
> +		goto err_disable_device;
>  
>  	return ret;
>  
> -err_disable_msi:
> -	pci_disable_msi(pdev);
>  err_disable_device:
>  	pci_disable_device(pdev);
>  err_put_node:
> @@ -248,6 +644,7 @@ static SIMPLE_DEV_PM_OPS(loongson_dwmac_pm_ops, loongson_dwmac_suspend,
>  
>  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);

> @@ -266,4 +663,5 @@ module_pci_driver(loongson_dwmac_driver);
>  
>  MODULE_DESCRIPTION("Loongson DWMAC PCI driver");
>  MODULE_AUTHOR("Qing Zhang <zhangqing@loongson.cn>");
> +MODULE_AUTHOR("Yanteng Si <siyanteng@loongson.cn>");
>  MODULE_LICENSE("GPL v2");

Please move this into a separate patch. It can be the last patch in
the series.

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


Please move this into a preparation/pre-requisite patch.


> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> index e1537a57815f..e94faa72f30e 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> @@ -420,6 +420,12 @@ stmmac_ethtool_set_link_ksettings(struct net_device *dev,
>  		return 0;
>  	}
>  
> +	if (priv->plat->flags & STMMAC_FLAG_DISABLE_FORCE_1000) {
> +		if (cmd->base.speed == SPEED_1000 &&
> +		    cmd->base.autoneg != AUTONEG_ENABLE)
> +			return -EOPNOTSUPP;
> +	}
> +
>  	return phylink_ethtool_ksettings_set(priv->phylink, cmd);
>  }
>  
> diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
> index 1b54b84a6785..c5d3d0ddb6f8 100644
> --- a/include/linux/stmmac.h
> +++ b/include/linux/stmmac.h
> @@ -223,6 +223,7 @@ struct dwmac4_addrs {
>  #define STMMAC_FLAG_RX_CLK_RUNS_IN_LPI		BIT(10)
>  #define STMMAC_FLAG_EN_TX_LPI_CLOCKGATING	BIT(11)
>  #define STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY	BIT(12)
> +#define STMMAC_FLAG_DISABLE_FORCE_1000		BIT(13)
>  
>  struct plat_stmmacenet_data {
>  	int bus_id;

Please move this in a separate _pre-requisite/preparation_ patch.
Really. Why have you merged it into this one? This patch already got
to be too complicated. Don't make it even more complex.

---

I look at v8 and look at v9 series. Why have you re-shuffled the
change so significantly??? It has made my life in reviewing your bits
much harder because instead of checking whether you took my v8-notes
into account I had to once again analyze the entire series. Sigh...

-Serge(y)

> -- 
> 2.31.4
> 

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

* Re: [PATCH net-next v11 1/6] net: stmmac: Move all PHYLINK MAC capabilities initializations to MAC-specific setup methods
  2024-04-18  9:53       ` Serge Semin
@ 2024-04-19  7:01         ` Yanteng Si
  0 siblings, 0 replies; 36+ messages in thread
From: Yanteng Si @ 2024-04-19  7:01 UTC (permalink / raw)
  To: Serge Semin
  Cc: Andrew Lunn, Russell King, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, hkallweit1, peppe.cavallaro,
	alexandre.torgue, joabreu, Jose.Abreu, chenhuacai, guyinggang,
	netdev, chris.chenfeiyang, siyanteng01


在 2024/4/18 17:53, Serge Semin 写道:
> On Thu, Apr 18, 2024 at 01:02:28PM +0800, Yanteng Si wrote:
>> 在 2024/4/13 02:32, Serge Semin 写道:
>>> Just submitted the series with this patch being properly split up and
>>> described:
>>> https://lore.kernel.org/netdev/20240412180340.7965-1-fancer.lancer@gmail.com/
>>>
>>> You can drop this patch, copy my patchset into your repo and rebase
>>> your series onto it. Thus for the time being, until my series is
>>> reviewed and merged in, you'll be able to continue with your patchset
>>> developments/reviews, but submitting only your portion of the patches.
>>>
>>> Alternatively my series could be just merged into yours as a set of
>>> the preparation patches, for instance, after it's fully reviewed.
>> Okay, I've seen your patch. I'll drop it.
> The series has been partly merged in:
> https://lore.kernel.org/netdev/20240412180340.7965-1-fancer.lancer@gmail.com/
> You can pick the first three patches up into your repo to rebase your
> work onto.
Ok, I'm using net-next.git trees, I've seen them, that's why I started 
preparing v12.
>
> Two leftover patches I've just resubmitted:
> https://lore.kernel.org/netdev/20240417140013.12575-1-fancer.lancer@gmail.com/

Okay, thank you.


Thanks,

Yanteng



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

* Re: [PATCH net-next v11 2/6] net: stmmac: Add multi-channel support
  2024-04-18 11:02   ` Serge Semin
@ 2024-04-19  9:02     ` Yanteng Si
  2024-04-19  9:17       ` Serge Semin
  0 siblings, 1 reply; 36+ messages in thread
From: Yanteng Si @ 2024-04-19  9:02 UTC (permalink / raw)
  To: Serge Semin
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang, siyanteng01

>>   
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
>> index daf79cdbd3ec..f161ec9ac490 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
>> @@ -70,15 +70,17 @@ static void dwmac1000_dma_axi(void __iomem *ioaddr, struct stmmac_axi *axi)
>>   	writel(value, ioaddr + DMA_AXI_BUS_MODE);
>>   }
>>   
>> -static void dwmac1000_dma_init(void __iomem *ioaddr,
>> -			       struct stmmac_dma_cfg *dma_cfg, int atds)
>> +static void dwmac1000_dma_init_channel(struct stmmac_priv *priv,
>> +				       void __iomem *ioaddr,
>> +				       struct stmmac_dma_cfg *dma_cfg, u32 chan)
> please create a pre-requisite/preparation patch with the atds argument
> movement to the stmmac_dma_cfg structure as I suggested in v8:
> https://lore.kernel.org/netdev/yzs6eqx2swdhaegxxcbijhtb5tkhkvvyvso2perkessv5swq47@ywmea5xswsug/
> That will make this patch looking simpler and providing a single
> coherent change.
OK.
>>   	/* Clear the interrupt by writing a logic 1 to the CSR5[15-0] */
>> -	writel((intr_status & 0x1ffff), ioaddr + DMA_STATUS);
>> +	writel((intr_status & 0x7ffff), ioaddr + DMA_CHAN_STATUS(chan));
> I'll ask once again:
>
> "Isn't the mask change going to be implemented in the framework of the
> Loongson-specific DMA-interrupt handler in some of the further
> patches?"
>
The future is not going to change.


Thanks,

Yanteng

>


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

* Re: [PATCH net-next v11 2/6] net: stmmac: Add multi-channel support
  2024-04-19  9:02     ` Yanteng Si
@ 2024-04-19  9:17       ` Serge Semin
  2024-04-19  9:51         ` Yanteng Si
  0 siblings, 1 reply; 36+ messages in thread
From: Serge Semin @ 2024-04-19  9:17 UTC (permalink / raw)
  To: Yanteng Si
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang, siyanteng01

On Fri, Apr 19, 2024 at 05:02:17PM +0800, Yanteng Si wrote:
> > > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> > > index daf79cdbd3ec..f161ec9ac490 100644
> > > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> > > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> > > @@ -70,15 +70,17 @@ static void dwmac1000_dma_axi(void __iomem *ioaddr, struct stmmac_axi *axi)
> > >   	writel(value, ioaddr + DMA_AXI_BUS_MODE);
> > >   }
> > > -static void dwmac1000_dma_init(void __iomem *ioaddr,
> > > -			       struct stmmac_dma_cfg *dma_cfg, int atds)
> > > +static void dwmac1000_dma_init_channel(struct stmmac_priv *priv,
> > > +				       void __iomem *ioaddr,
> > > +				       struct stmmac_dma_cfg *dma_cfg, u32 chan)
> > please create a pre-requisite/preparation patch with the atds argument
> > movement to the stmmac_dma_cfg structure as I suggested in v8:
> > https://lore.kernel.org/netdev/yzs6eqx2swdhaegxxcbijhtb5tkhkvvyvso2perkessv5swq47@ywmea5xswsug/
> > That will make this patch looking simpler and providing a single
> > coherent change.
> OK.

> > >   	/* Clear the interrupt by writing a logic 1 to the CSR5[15-0] */
> > > -	writel((intr_status & 0x1ffff), ioaddr + DMA_STATUS);
> > > +	writel((intr_status & 0x7ffff), ioaddr + DMA_CHAN_STATUS(chan));
> > I'll ask once again:
> > 
> > "Isn't the mask change going to be implemented in the framework of the
> > Loongson-specific DMA-interrupt handler in some of the further
> > patches?"
> > 
> The future is not going to change.

Not sure I've completely got what you meant. You are adding the
Loongson-specific DMA IRQ handler in Patch 6/6:
https://lore.kernel.org/netdev/cover.1712917541.git.siyanteng@loongson.cn/T/#m439c1d8957cd6997beb0374484a8d0efbeac0182

The change in the patch 2/6 concerns the _generic_ DW MAC DMA IRQ
handler. You can't change the mask here without justification.
Moreover the generic DW MAC doesn't have the status flags behind the
mask you set. That's why earlier we find out a solution with creating
the Loongson-specific DMA IRQ-handler. You have it implemented in the
patch 6/6.

So my question was mostly rhetorical. You should have dropped the mask
change in this patch ever since the Loongson-specific DMA
IRQ-handler was added to your series.

-Serge(y) 

> 
> 
> Thanks,
> 
> Yanteng
> 
> > 
> 

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

* Re: [PATCH net-next v11 3/6] net: stmmac: dwmac-loongson: Use PCI_DEVICE_DATA() macro for device identification
  2024-04-18 12:31         ` Serge Semin
@ 2024-04-19  9:40           ` Yanteng Si
  0 siblings, 0 replies; 36+ messages in thread
From: Yanteng Si @ 2024-04-19  9:40 UTC (permalink / raw)
  To: Serge Semin
  Cc: Jakub Kicinski, andrew, hkallweit1, peppe.cavallaro,
	alexandre.torgue, joabreu, Jose.Abreu, chenhuacai, linux,
	guyinggang, netdev, chris.chenfeiyang, siyanteng01


在 2024/4/18 20:31, Serge Semin 写道:
> On Thu, Apr 18, 2024 at 02:14:17PM +0300, Serge Semin wrote:
>> On Mon, Apr 15, 2024 at 10:21:39AM +0800, Yanteng Si wrote:
>>>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>>>> index 9e40c28d453a..995c9bd144e0 100644
>>>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>>>> @@ -213,7 +213,7 @@ static SIMPLE_DEV_PM_OPS(loongson_dwmac_pm_ops, loongson_dwmac_suspend,
>>>>>    			 loongson_dwmac_resume);
>>>>>    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);
>>>> In file included from ../drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c:6:
>>>> ../include/linux/pci.h:1061:51: error: ‘PCI_DEVICE_ID_LOONGSON_GMAC’ undeclared here (not in a function); did you mean ‘PCI_DEVICE_ID_LOONGSON_HDA’?
>>>>    1061 |         .vendor = PCI_VENDOR_ID_##vend, .device = PCI_DEVICE_ID_##vend##_##dev, \
>>>>         |                                                   ^~~~~~~~~~~~~~
>>>> ../drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c:216:11: note: in expansion of macro ‘PCI_DEVICE_DATA’
>>>>     216 |         { PCI_DEVICE_DATA(LOONGSON, GMAC, &loongson_gmac_pci_info) },
>>>>         |           ^~~~~~~~~~~~~~~
>>>> ../drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c:216:44: error: ‘loongson_gmac_pci_info’ undeclared here (not in a function)
>>>>     216 |         { PCI_DEVICE_DATA(LOONGSON, GMAC, &loongson_gmac_pci_info) },
>>>>         |                                            ^~~~~~~~~~~~~~~~~~~~~~
>>>> ../include/linux/pci.h:1063:41: note: in definition of macro ‘PCI_DEVICE_DATA’
>>>>    1063 |         .driver_data = (kernel_ulong_t)(data)
>>>>         |                                         ^~~~
>>> Will be fixed in v12.
>> Just move the PCI_DEVICE_ID_LOONGSON_GMAC macro definition from Patch
>> 5/6 to this one.
OK.
> ... and of course pass NULL as the data-pointer to PCI_DEVICE_DATA().

OK. Thank you!


Thanks,

Yanteng




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

* Re: [PATCH net-next v11 2/6] net: stmmac: Add multi-channel support
  2024-04-19  9:17       ` Serge Semin
@ 2024-04-19  9:51         ` Yanteng Si
  0 siblings, 0 replies; 36+ messages in thread
From: Yanteng Si @ 2024-04-19  9:51 UTC (permalink / raw)
  To: Serge Semin
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang, siyanteng01


在 2024/4/19 17:17, Serge Semin 写道:
> The change in the patch 2/6 concerns the_generic_  DW MAC DMA IRQ
> handler. You can't change the mask here without justification.
> Moreover the generic DW MAC doesn't have the status flags behind the
> mask you set. That's why earlier we find out a solution with creating
> the Loongson-specific DMA IRQ-handler. You have it implemented in the
> patch 6/6.
Sorry, I misinterpreted your comment earlier.
>
> So my question was mostly rhetorical. You should have dropped the mask
> change in this patch ever since the Loongson-specific DMA
> IRQ-handler was added to your series.

I see. I'll restore this mask.


Thanks,

Yanteng


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

* Re: [PATCH net-next v11 4/6] net: stmmac: dwmac-loongson: Introduce GMAC setup
  2024-04-18 12:26   ` Serge Semin
@ 2024-04-19 10:06     ` Yanteng Si
  0 siblings, 0 replies; 36+ messages in thread
From: Yanteng Si @ 2024-04-19 10:06 UTC (permalink / raw)
  To: Serge Semin
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang, siyanteng01


在 2024/4/18 20:26, Serge Semin 写道:
>>   	plat->multicast_filter_bins = 256;
>> +	plat->clk_ref_rate = 125000000;
>> +	plat->clk_ptp_rate = 125000000;
> This change is unrelated to the rest of the changes in this patch.
> Please split the patch up into two:
> 1. Add ref and ptp clocks for Loongson GMAC
> 2. Split up the platform data initialization
> First one is a new feature adding the actual ref clock rates to the
> driver. The second patch is a preparation before adding the full PCI
> support.
>
Ok, but we need to reverse the order:

1. Split up the platform data initialization

2. Add ref and ptp clocks for Loongson GMAC


Since loongson_gmac_data() needs to be introduced first, then we can add the

clock rates of GMAC.


Thanks,
Yanteng



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

* Re: [PATCH net-next v11 5/6] net: stmmac: dwmac-loongson: Add full PCI support
  2024-04-18 13:08   ` Serge Semin
@ 2024-04-20  2:41     ` Yanteng Si
  0 siblings, 0 replies; 36+ messages in thread
From: Yanteng Si @ 2024-04-20  2:41 UTC (permalink / raw)
  To: Serge Semin
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang, siyanteng01


在 2024/4/18 21:08, Serge Semin 写道:
>> -	np = dev_of_node(&pdev->dev);
>> -
>> -	if (!np) {
>> -		pr_info("dwmac_loongson_pci: No OF node\n");
>> -		return -ENODEV;
>> -	}
> Hm, I see you dropping this snippet and never getting it back in this
> patch. Thus after the patch is applied np will be left uninitialized,
> which will completely break the driver. Please make sure it's fixed.
>
> This problem has been introduced at the v9 stage, which I didn't have
> time to review. There were no problem like that in v8.

Okay, I will restore it.


Thanks,

Yanteng


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

* Re: [PATCH net-next v11 6/6] net: stmmac: dwmac-loongson: Add Loongson GNET support
  2024-04-18 14:01   ` Serge Semin
@ 2024-04-20 11:02     ` Yanteng Si
  2024-04-21  5:35       ` Yanteng Si
  2024-04-23 13:16     ` Yanteng Si
  2024-04-24 14:11     ` Huacai Chen
  2 siblings, 1 reply; 36+ messages in thread
From: Yanteng Si @ 2024-04-20 11:02 UTC (permalink / raw)
  To: Serge Semin
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang, siyanteng01


在 2024/4/18 22:01, Serge Semin 写道:
> On Fri, Apr 12, 2024 at 07:28:51PM +0800, Yanteng Si wrote:
>> There are two types of Loongson DWGMAC. The first type shares the same
>> register definitions and has similar logic as dwmac1000. The second type
>> uses several different register definitions, we think it is necessary to
>> distinguish rx and tx, so we split these bits into two.
>>
>> Simply put, we split some single bit fields into double bits fileds:
>>
>>       Name              Tx          Rx
>>
>> DMA_INTR_ENA_NIE = 0x00040000 | 0x00020000;
>> DMA_INTR_ENA_AIE = 0x00010000 | 0x00008000;
>> DMA_STATUS_NIS   = 0x00040000 | 0x00020000;
>> DMA_STATUS_AIS   = 0x00010000 | 0x00008000;
>> DMA_STATUS_FBI   = 0x00002000 | 0x00001000;
>>
>> Therefore, when using, TX and RX must be set at the same time.
>>
>> How to use them:
>>   1. Create the Loongson GNET-specific
>>   stmmac_dma_ops.dma_interrupt()
>>   stmmac_dma_ops.init_chan()
>>   methods in the dwmac-loongson.c driver. Adding all the
>>   Loongson-specific macros
>>
>>   2. Create a Loongson GNET-specific platform setup method with the next
>>   semantics:
>>      + allocate stmmac_dma_ops instance and initialize it with
>>        dwmac1000_dma_ops.
>>      + override the stmmac_dma_ops.{dma_interrupt, init_chan} with
>>        the pointers to the methods defined in 2.
>>      + allocate mac_device_info instance and initialize the
>>        mac_device_info.dma field with a pointer to the new
>>        stmmac_dma_ops instance.
>>      + initialize mac_device_info in a way it's done in
>>        dwmac1000_setup().
>>
>>   3. Initialize plat_stmmacenet_data.setup() with the pointer to the
>>   method created in 2.
>>
>> GNET features:
>>
>>   Speeds: 10/100/1000Mbps
>>   DMA-descriptors type: normal and enhanced
> Hm, it's either one or another. They can't be both supported because
> the alternative descriptors are enabled by the DESC_ENHANCED_FORMAT
> HDL parameter defined on the IP-core synthesize stage.
Sorry, It is enhanced.
>
>>   L3/L4 filters availability: support
>>   VLAN hash table filter: support
>>   PHY-interface: GMII
>>   Remote Wake-up support: support
>>   Mac Management Counters (MMC): support
>>   DMA chennel number: 0x10 device is 8 and 0x37 device is 1
> What about adding the info like:
> Number of additional MAC addresses
> MAC Hash-based filter support and if supported the hash table size.

It is OK.

  Number of additional MAC addresses: 5
  MAC Hash-based filter: support
  Number of ash table size: 256

>> **Note**: Currently, only the LS2K2000's IP core is 0x10,
> This doesn't sound correct. The LS2K2000's IP-core is v3.73a. But the
> SNPS Version ID was manually altered by the hardware designers.

Hmm,  Our original intention was to express the reality of the hardware, 
How about:

**Note**: Currently, only the LS2K2000's synopsys_id is 0x10, while the
synopsys_id of other devices are 0x37.

>
>> while the IP
>> cores of other devices are 0x37.
> Real IP-core ID isn't described by the hex number. It's a digit number
> like v3.73a/v3.50a/etc. Hex number you constantly repeat is the
> MAC_Version.SNPSVER register value. So please use the IP-core version
> in the v3.xx format all over the patch text.
In this context, using synopsys_id is more accurate.
>
>> Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
>> Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
>> Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
>> ---
>>   drivers/net/ethernet/stmicro/stmmac/common.h  |   2 +
>>   .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 476 ++++++++++++++++--
>>   .../ethernet/stmicro/stmmac/dwmac1000_dma.c   |   1 +
>>   .../ethernet/stmicro/stmmac/stmmac_ethtool.c  |   6 +
>>   include/linux/stmmac.h                        |   1 +
>>   5 files changed, 447 insertions(+), 39 deletions(-)
>>
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
>> index 9cd62b2110a1..6777dc997e9f 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/common.h
>> +++ b/drivers/net/ethernet/stmicro/stmmac/common.h
>> @@ -29,6 +29,7 @@
>>   /* 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
>> @@ -258,6 +259,7 @@ struct stmmac_safety_stats {
>>   #define CSR_F_300M	300000000
>>   
>>   #define	MAC_CSR_H_FRQ_MASK	0x20
>> +#define	MAC_CTRL_PORT_SELECT_10_100	BIT(15)
> No, this is already defined in:
> drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
> as GMAC_CONTROL_PS macros. Use it instead of adding new macros.
Okay, let's call it.
>
>>   
>>   #define HASH_TABLE_SIZE 64
>>   #define PAUSE_TIME 0xffff
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>> index 69078eb1f923..4edfbb4fcb64 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>> @@ -8,8 +8,70 @@
>>   #include <linux/device.h>
>>   #include <linux/of_irq.h>
>>   #include "stmmac.h"
>> +#include "dwmac_dma.h"
>> +#include "dwmac1000.h"
>> +
>> +/* Normal Loongson Tx Summary */
>> +#define DMA_INTR_ENA_NIE_TX_LOONGSON	0x00040000
>> +/* Normal Loongson Rx Summary */
>> +#define DMA_INTR_ENA_NIE_RX_LOONGSON	0x00020000
>> +
>> +#define DMA_INTR_NORMAL_LOONGSON	(DMA_INTR_ENA_NIE_TX_LOONGSON | \
>> +					 DMA_INTR_ENA_NIE_RX_LOONGSON | \
>> +					 DMA_INTR_ENA_RIE | DMA_INTR_ENA_TIE)
>> +
>> +/* Abnormal Loongson Tx Summary */
>> +#define DMA_INTR_ENA_AIE_TX_LOONGSON	0x00010000
>> +/* Abnormal Loongson Rx Summary */
>> +#define DMA_INTR_ENA_AIE_RX_LOONGSON	0x00008000
>> +
>> +#define DMA_INTR_ABNORMAL_LOONGSON	(DMA_INTR_ENA_AIE_TX_LOONGSON | \
>> +					 DMA_INTR_ENA_AIE_RX_LOONGSON | \
>> +					 DMA_INTR_ENA_FBE | DMA_INTR_ENA_UNE)
>> +
>> +#define DMA_INTR_DEFAULT_MASK_LOONGSON	(DMA_INTR_NORMAL_LOONGSON | \
>> +					 DMA_INTR_ABNORMAL_LOONGSON)
>> +
>> +/* Normal Loongson Tx Interrupt Summary */
>> +#define DMA_STATUS_NIS_TX_LOONGSON	0x00040000
>> +/* Normal Loongson Rx Interrupt Summary */
>> +#define DMA_STATUS_NIS_RX_LOONGSON	0x00020000
>> +
>> +/* Abnormal Loongson Tx Interrupt Summary */
>> +#define DMA_STATUS_AIS_TX_LOONGSON	0x00010000
>> +/* Abnormal Loongson Rx Interrupt Summary */
>> +#define DMA_STATUS_AIS_RX_LOONGSON	0x00008000
>> +
>> +/* Fatal Loongson Tx Bus Error Interrupt */
>> +#define DMA_STATUS_FBI_TX_LOONGSON	0x00002000
>> +/* Fatal Loongson Rx Bus Error Interrupt */
>> +#define DMA_STATUS_FBI_RX_LOONGSON	0x00001000
>> +
>> +#define DMA_STATUS_MSK_COMMON_LOONGSON	(DMA_STATUS_NIS_TX_LOONGSON | \
>> +					 DMA_STATUS_NIS_RX_LOONGSON | \
>> +					 DMA_STATUS_AIS_TX_LOONGSON | \
>> +					 DMA_STATUS_AIS_RX_LOONGSON | \
>> +					 DMA_STATUS_FBI_TX_LOONGSON | \
>> +					 DMA_STATUS_FBI_RX_LOONGSON)
>> +
>> +#define DMA_STATUS_MSK_RX_LOONGSON	(DMA_STATUS_ERI | DMA_STATUS_RWT | \
>> +					 DMA_STATUS_RPS | DMA_STATUS_RU  | \
>> +					 DMA_STATUS_RI  | DMA_STATUS_OVF | \
>> +					 DMA_STATUS_MSK_COMMON_LOONGSON)
>> +
>> +#define DMA_STATUS_MSK_TX_LOONGSON	(DMA_STATUS_ETI | DMA_STATUS_UNF | \
>> +					 DMA_STATUS_TJT | DMA_STATUS_TU  | \
>> +					 DMA_STATUS_TPS | DMA_STATUS_TI  | \
>> +					 DMA_STATUS_MSK_COMMON_LOONGSON)
>>   
>>   #define PCI_DEVICE_ID_LOONGSON_GMAC	0x7a03
>> +#define PCI_DEVICE_ID_LOONGSON_GNET	0x7a13
>> +#define LOONGSON_DWMAC_CORE_1_00	0x10	/* Loongson custom IP */
>> +#define CHANNEL_NUM			8
>> +
>> +struct loongson_data {
>> +	struct device *dev;
>> +};
>>   
>>   struct stmmac_pci_info {
>>   	int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat);
>> @@ -56,6 +117,8 @@ static int loongson_gmac_data(struct pci_dev *pdev,
>>   	plat->dma_cfg->pblx8 = true;
>>   
>>   	plat->multicast_filter_bins = 256;
>> +	plat->mdio_bus_data->phy_mask = 0;
>> +
> And this change isn't related to the GNET. Why is it here?
OK, move this into a preparation/pre-requisite patch

>
>>   	plat->clk_ref_rate = 125000000;
>>   	plat->clk_ptp_rate = 125000000;
>>   
>> @@ -69,13 +132,342 @@ 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)
>> +static void loongson_gnet_dma_init_channel(struct stmmac_priv *priv,
>> +					   void __iomem *ioaddr,
>> +					   struct stmmac_dma_cfg *dma_cfg,
>> +					   u32 chan)
>> +{
>> +	int txpbl = dma_cfg->txpbl ?: dma_cfg->pbl;
>> +	int rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl;
>> +	u32 value;
>> +
>> +	/* common channel control register config */
> Useless comment. Please drop.
Ok.
>
>> +	value = readl(ioaddr + DMA_CHAN_BUS_MODE(chan));
>> +
>> +	/* Set the DMA PBL (Programmable Burst Length) mode.
>> +	 *
>> +	 * Note: before stmmac core 3.50 this mode bit was 4xPBL, and
>> +	 * post 3.5 mode bit acts as 8*PBL.
>> +	 */
> Do you have an IP-core older than v3.50a? No. So please drop the
> comment.

I will drop it.

>
>> +	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;
>> +
>> +	if (dma_cfg->atds)
>> +		value |= DMA_BUS_MODE_ATDS;
>> +
>> +	if (dma_cfg->aal)
>> +		value |= DMA_BUS_MODE_AAL;
>> +
>> +	writel(value, ioaddr + DMA_CHAN_BUS_MODE(chan));
>> +
>> +	/* Mask interrupts by writing to CSR7 */
>> +	writel(DMA_INTR_DEFAULT_MASK_LOONGSON, ioaddr +
>> +	       DMA_CHAN_INTR_ENA(chan));
>> +}
>> +
>> +static int loongson_gnet_dma_interrupt(struct stmmac_priv *priv,
>> +				       void __iomem *ioaddr,
>> +				       struct stmmac_extra_stats *x,
>> +				       u32 chan, u32 dir)
>> +{
>> +	struct stmmac_pcpu_stats *stats = this_cpu_ptr(priv->xstats.pcpu_stats);
>> +	u32 abnor_intr_status;
>> +	u32 nor_intr_status;
>> +	u32 fb_intr_status;
>> +	u32 intr_status;
>> +	int ret = 0;
>> +
>> +	/* read the status register (CSR5) */
>> +	intr_status = readl(ioaddr + DMA_CHAN_STATUS(chan));
>> +
>> +	if (dir == DMA_DIR_RX)
>> +		intr_status &= DMA_STATUS_MSK_RX_LOONGSON;
>> +	else if (dir == DMA_DIR_TX)
>> +		intr_status &= DMA_STATUS_MSK_TX_LOONGSON;
>> +
>> +	nor_intr_status = intr_status & (DMA_STATUS_NIS_TX_LOONGSON |
>> +		DMA_STATUS_NIS_RX_LOONGSON);
>> +	abnor_intr_status = intr_status & (DMA_STATUS_AIS_TX_LOONGSON |
>> +		DMA_STATUS_AIS_RX_LOONGSON);
>> +	fb_intr_status = intr_status & (DMA_STATUS_FBI_TX_LOONGSON |
>> +		DMA_STATUS_FBI_RX_LOONGSON);
>> +
>> +	/* ABNORMAL interrupts */
>> +	if (unlikely(abnor_intr_status)) {
>> +		if (unlikely(intr_status & DMA_STATUS_UNF)) {
>> +			ret = tx_hard_error_bump_tc;
>> +			x->tx_undeflow_irq++;
>> +		}
>> +		if (unlikely(intr_status & DMA_STATUS_TJT))
>> +			x->tx_jabber_irq++;
>> +		if (unlikely(intr_status & DMA_STATUS_OVF))
>> +			x->rx_overflow_irq++;
>> +		if (unlikely(intr_status & DMA_STATUS_RU))
>> +			x->rx_buf_unav_irq++;
>> +		if (unlikely(intr_status & DMA_STATUS_RPS))
>> +			x->rx_process_stopped_irq++;
>> +		if (unlikely(intr_status & DMA_STATUS_RWT))
>> +			x->rx_watchdog_irq++;
>> +		if (unlikely(intr_status & DMA_STATUS_ETI))
>> +			x->tx_early_irq++;
>> +		if (unlikely(intr_status & DMA_STATUS_TPS)) {
>> +			x->tx_process_stopped_irq++;
>> +			ret = tx_hard_error;
>> +		}
>> +		if (unlikely(fb_intr_status)) {
>> +			x->fatal_bus_error_irq++;
>> +			ret = tx_hard_error;
>> +		}
>> +	}
>> +	/* TX/RX NORMAL interrupts */
>> +	if (likely(nor_intr_status)) {
>> +		if (likely(intr_status & DMA_STATUS_RI)) {
>> +			u32 value = readl(ioaddr + DMA_INTR_ENA);
>> +			/* to schedule NAPI on real RIE event. */
>> +			if (likely(value & DMA_INTR_ENA_RIE)) {
>> +				u64_stats_update_begin(&stats->syncp);
>> +				u64_stats_inc(&stats->rx_normal_irq_n[chan]);
>> +				u64_stats_update_end(&stats->syncp);
>> +				ret |= handle_rx;
>> +			}
>> +		}
>> +		if (likely(intr_status & DMA_STATUS_TI)) {
>> +			u64_stats_update_begin(&stats->syncp);
>> +			u64_stats_inc(&stats->tx_normal_irq_n[chan]);
>> +			u64_stats_update_end(&stats->syncp);
>> +			ret |= handle_tx;
>> +		}
>> +		if (unlikely(intr_status & DMA_STATUS_ERI))
>> +			x->rx_early_irq++;
>> +	}
>> +	/* Optional hardware blocks, interrupts should be disabled */
>> +	if (unlikely(intr_status &
>> +		     (DMA_STATUS_GPI | DMA_STATUS_GMI | DMA_STATUS_GLI)))
>> +		pr_warn("%s: unexpected status %08x\n", __func__, intr_status);
>> +
>> +	/* Clear the interrupt by writing a logic 1 to the CSR5[15-0] */
>> +	writel((intr_status & 0x7ffff), ioaddr + DMA_CHAN_STATUS(chan));
>> +
>> +	return ret;
>> +}
>> +
>> +static void loongson_gnet_fix_speed(void *priv, unsigned int speed,
>> +				    unsigned int mode)
>> +{
>> +	struct loongson_data *ld = (struct loongson_data *)priv;
>> +	struct net_device *ndev = dev_get_drvdata(ld->dev);
>> +	struct stmmac_priv *ptr = netdev_priv(ndev);
>> +
>> +	/* The controller and PHY don't work well together.
>> +	 * We need to use the PS bit to check if the controller's status
>> +	 * is correct and reset PHY if necessary.
>> +	 * MAC_CTRL_REG.15 is defined by the GMAC_CONTROL_PS macro.
>> +	 */
>> +	if (speed == SPEED_1000) {
>> +		if (readl(ptr->ioaddr + MAC_CTRL_REG) &
>> +		    MAC_CTRL_PORT_SELECT_10_100)
> GMAC_CONTROL_PS?
Yeah!
>> +			/* Word around hardware bug, restart autoneg */
>> +			phy_restart_aneg(ndev->phydev);
>> +	}
>> +}
>> +
>> +static int loongson_gnet_data(struct pci_dev *pdev,
>> +			      struct plat_stmmacenet_data *plat)
>> +{
>> +	loongson_default_data(pdev, plat);
>> +
>> +	plat->phy_addr = -1;
>> +	plat->phy_interface = PHY_INTERFACE_MODE_GMII;
>> +
>> +	plat->dma_cfg->pbl = 32;
>> +	plat->dma_cfg->pblx8 = true;
>> +
>> +	plat->multicast_filter_bins = 256;
>> +	plat->mdio_bus_data->phy_mask = ~(u32)BIT(2);
>> +
>> +	plat->clk_ref_rate = 125000000;
>> +	plat->clk_ptp_rate = 125000000;
> If this is common for both GMAC and GNET what about moving it to the
> loongson_default_data() method?
>
> If so please just do that in the patch 4 where you get to add these
> fields initialization in the first place.
Okay!
>
>> +
>> +	plat->fix_mac_speed = loongson_gnet_fix_speed;
>> +
>> +	return 0;
>> +}
>> +
>> +static struct stmmac_pci_info loongson_gnet_pci_info = {
>> +	.setup = loongson_gnet_data,
>> +};
>> +
>> +static int loongson_dwmac_config_legacy(struct pci_dev *pdev,
>> +					struct plat_stmmacenet_data *plat,
>> +					struct stmmac_resources *res,
>> +					struct device_node *np)
>> +{
>> +	if (np) {
>> +		res->irq = of_irq_get_byname(np, "macirq");
>> +		if (res->irq < 0) {
>> +			dev_err(&pdev->dev, "IRQ macirq not found\n");
>> +			return -ENODEV;
>> +		}
>> +
>> +		res->wol_irq = of_irq_get_byname(np, "eth_wake_irq");
>> +		if (res->wol_irq < 0) {
>> +			dev_info(&pdev->dev,
>> +				 "IRQ eth_wake_irq not found, using macirq\n");
>> +			res->wol_irq = res->irq;
>> +		}
>> +
>> +		res->lpi_irq = of_irq_get_byname(np, "eth_lpi");
>> +		if (res->lpi_irq < 0) {
>> +			dev_err(&pdev->dev, "IRQ eth_lpi not found\n");
>> +			return -ENODEV;
>> +		}
>> +	} else {
>> +		res->irq = pdev->irq;
>> +		res->wol_irq = res->irq;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static int loongson_dwmac_config_msi(struct pci_dev *pdev,
>> +				     struct plat_stmmacenet_data *plat,
>> +				     struct stmmac_resources *res,
>> +				     struct device_node *np)
>> +{
>> +	int i, ret, vecs;
>> +
>> +	vecs = roundup_pow_of_two(CHANNEL_NUM * 2 + 1);
>> +	ret = pci_alloc_irq_vectors(pdev, vecs, vecs, PCI_IRQ_MSI);
>> +	if (ret < 0) {
>> +		dev_info(&pdev->dev,
>> +			 "MSI enable failed, Fallback to legacy interrupt\n");
>> +		return loongson_dwmac_config_legacy(pdev, plat, res, np);
>> +	}
>> +
>> +	res->irq = pci_irq_vector(pdev, 0);
>> +	res->wol_irq = 0;
>> +
>> +	/* INT NAME | MAC | CH7 rx | CH7 tx | ... | CH0 rx | CH0 tx |
>> +	 * --------- ----- -------- --------  ...  -------- --------
>> +	 * IRQ NUM  |  0  |   1    |   2    | ... |   15   |   16   |
>> +	 */
>> +	for (i = 0; i < CHANNEL_NUM; i++) {
>> +		res->rx_irq[CHANNEL_NUM - 1 - i] =
>> +			pci_irq_vector(pdev, 1 + i * 2);
>> +		res->tx_irq[CHANNEL_NUM - 1 - i] =
>> +			pci_irq_vector(pdev, 2 + i * 2);
>> +	}
>> +
>> +	plat->flags |= STMMAC_FLAG_MULTI_MSI_EN;
> Once again. Please replace this with simpler solution:
>
> static int loongson_dwmac_config_multi_msi(struct pci_dev *pdev,
> +					   struct plat_stmmacenet_data *plat,
> +					   struct stmmac_resources *res)
> +{
> +	int i, ret, vecs;
> +
> +	/* INT NAME | MAC | CH7 rx | CH7 tx | ... | CH0 rx | CH0 tx |
> +	 * --------- ----- -------- --------  ...  -------- --------
> +	 * IRQ NUM  |  0  |   1    |   2    | ... |   15   |   16   |
> +	 */
> +	vecs = plat->rx_queues_to_use + plat->tx_queues_to_use + 1;
> +	ret = pci_alloc_irq_vectors(pdev, 1, vecs, PCI_IRQ_MSI | PCI_IRQ_LEGACY);
> +	if (ret < 0) {
> +		dev_err(&pdev->dev, "Failed to allocate PCI IRQs\n");
> +		return ret;
> +	} else if (ret >= vecs) {
> +		for (i = 0; i < plat->rx_queues_to_use; i++) {
> +			res->rx_irq[CHANNELS_NUM - 1 - i] =
> +				pci_irq_vector(pdev, 1 + i * 2);
> +		}
> +		for (i = 0; i < plat->tx_queues_to_use; i++) {
> +			res->tx_irq[CHANNELS_NUM - 1 - i] =
> +				pci_irq_vector(pdev, 2 + i * 2);
> +		}
> +
> +		plat->flags |= STMMAC_FLAG_MULTI_MSI_EN;
> +	}
> +
> +	res->irq = pci_irq_vector(pdev, 0);
> +
> +	return 0;
> +}
Well, I'll try again.
>
>> +
>> +	return 0;
>> +}
>> +
>> +static struct mac_device_info *loongson_dwmac_setup(void *apriv)
>> +{
>> +	struct stmmac_priv *priv = apriv;
>> +	struct stmmac_resources res;
>> +	struct mac_device_info *mac;
>> +	struct stmmac_dma_ops *dma;
>> +	struct pci_dev *pdev;
>> +	u32 loongson_gmac;
>> +
>> +	memset(&res, 0, sizeof(res));
>> +	pdev = to_pci_dev(priv->device);
>> +	res.addr = pcim_iomap_table(pdev)[0];
>> +	loongson_gmac = readl(res.addr + GMAC_VERSION) & 0xff;
>> +
>> +	mac = devm_kzalloc(priv->device, sizeof(*mac), GFP_KERNEL);
>> +	if (!mac)
>> +		return NULL;
>> +
>> +	dma = devm_kzalloc(priv->device, sizeof(*dma), GFP_KERNEL);
>> +	if (!dma)
>> +		return NULL;
>> +
>> +	/* The original IP-core version is 0x37 in all Loongson GNET
>> +	 * (ls2k2000 and ls7a2000), but the GNET HW designers have changed the
>> +	 * GMAC_VERSION.SNPSVER field to the custom 0x10 value on the Loongson
>> +	 * ls2k2000 MAC to emphasize the differences: multiple DMA-channels,
>> +	 * AV feature and GMAC_INT_STATUS CSR flags layout. Get back the
>> +	 * original value so the correct HW-interface would be selected.
>> +	 */
>> +	if (loongson_gmac == LOONGSON_DWMAC_CORE_1_00) {
>> +		priv->synopsys_id = DWMAC_CORE_3_70;
>> +		*dma = dwmac1000_dma_ops;
>> +		dma->init_chan = loongson_gnet_dma_init_channel;
>> +		dma->dma_interrupt = loongson_gnet_dma_interrupt;
>> +		mac->dma = dma;
>> +	}
>> +
>> +	mac->mac = &dwmac1000_ops;
>> +	priv->dev->priv_flags |= IFF_UNICAST_FLT;
>> +
>> +	/* Pre-initialize the respective "mac" fields as it's done in
>> +	 * dwmac1000_setup()
>> +	 */
>> +	mac->pcsr = priv->ioaddr;
>> +	mac->multicast_filter_bins = priv->plat->multicast_filter_bins;
>> +	mac->unicast_filter_entries = priv->plat->unicast_filter_entries;
>> +	mac->mcast_bits_log2 = 0;
>> +
>> +	if (mac->multicast_filter_bins)
>> +		mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins);
>> +
>> +	/* The GMAC devices with PCI ID 0x7a03 does not support any pause mode.
>> +	 * The GNET devices without CORE ID 0x10 does not support half-duplex.
>> +	 */
>> +	if (pdev->device == PCI_DEVICE_ID_LOONGSON_GMAC) {
>> +		mac->link.caps = MAC_10 | MAC_100 | MAC_1000;
>> +	} else {
>> +		if (loongson_gmac == LOONGSON_DWMAC_CORE_1_00)
>> +			mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
>> +					 MAC_10 | MAC_100 | MAC_1000;
>> +		else
>> +			mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
>> +					 MAC_10FD | MAC_100FD | MAC_1000FD;
>> +	}
>> +
>> +	mac->link.duplex = GMAC_CONTROL_DM;
>> +	mac->link.speed10 = GMAC_CONTROL_PS;
>> +	mac->link.speed100 = GMAC_CONTROL_PS | GMAC_CONTROL_FES;
>> +	mac->link.speed1000 = 0;
>> +	mac->link.speed_mask = GMAC_CONTROL_PS | GMAC_CONTROL_FES;
>> +	mac->mii.addr = GMAC_MII_ADDR;
>> +	mac->mii.data = GMAC_MII_DATA;
>> +	mac->mii.addr_shift = 11;
>> +	mac->mii.addr_mask = 0x0000F800;
>> +	mac->mii.reg_shift = 6;
>> +	mac->mii.reg_mask = 0x000007C0;
>> +	mac->mii.clk_csr_shift = 2;
>> +	mac->mii.clk_csr_mask = GENMASK(5, 2);
>> +
>> +	return mac;
>> +}
>> +
>> +static int loongson_dwmac_probe(struct pci_dev *pdev,
>> +				const struct pci_device_id *id)
>>   {
>>   	struct plat_stmmacenet_data *plat;
>>   	int ret, i, bus_id, phy_mode;
>>   	struct stmmac_pci_info *info;
>>   	struct stmmac_resources res;
>> +	struct loongson_data *ld;
>>   	struct device_node *np;
>> +	u32 loongson_gmac;
>>   
>>   	plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL);
>>   	if (!plat)
>> @@ -88,10 +482,14 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
>>   		return -ENOMEM;
>>   
>>   	plat->dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*plat->dma_cfg), GFP_KERNEL);
>> -	if (!plat->dma_cfg) {
>> -		ret = -ENOMEM;
>> -		goto err_put_node;
>> -	}
>> +	if (!plat->dma_cfg)
>> +		return -ENOMEM;
>> +
>> +	ld = devm_kzalloc(&pdev->dev, sizeof(*ld), GFP_KERNEL);
>> +	if (!ld)
>> +		return -ENOMEM;
>> +
>> +	np = dev_of_node(&pdev->dev);
> Here is the missing np from the patch 5...
Yeah, I will merge it to patch 5.
>
>>   
>>   	/* Enable pci device */
>>   	ret = pci_enable_device(pdev);
>> @@ -110,14 +508,6 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
>>   		break;
>>   	}
>>   
>> -	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;
> This change must have been added to the Patch 5 where you get to move
> all the NP-related things into the "if (np) {}" clause!
Sorry, this part is in patch 5.
>
>>   	plat->mac_interface = PHY_INTERFACE_MODE_GMII;
>>   
>>   	pci_set_master(pdev);
>> @@ -133,7 +523,6 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
>>   			dev_info(&pdev->dev, "Found MDIO subnode\n");
>>   			plat->mdio_bus_data->needs_reset = true;
>>   		}
>> -
>>   		bus_id = of_alias_get_id(np, "ethernet");
>>   		if (bus_id >= 0)
>>   			plat->bus_id = bus_id;
>> @@ -145,42 +534,49 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
>>   			goto err_disable_device;
>>   		}
>>   		plat->phy_interface = phy_mode;
>> +	}
>>   
>> -		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;
>> -		}
>> +	plat->bsp_priv = ld;
>> +	plat->setup = loongson_dwmac_setup;
>> +	ld->dev = &pdev->dev;
>>   
>> -		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;
>> -		}
>> +	memset(&res, 0, sizeof(res));
>> +	res.addr = pcim_iomap_table(pdev)[0];
>> +	loongson_gmac = readl(res.addr + GMAC_VERSION) & 0xff;
>>   
>> -		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;
> Please, move the loongson_dwmac_config_legacy() method creation change
> into a preparation/pre-requisite patch. That will vastly simplify this
> patch and will help with reviewing it!
Okay!
>
>> +	switch (loongson_gmac) {
>> +	case LOONGSON_DWMAC_CORE_1_00:
>> +		plat->rx_queues_to_use = CHANNEL_NUM;
>> +		plat->tx_queues_to_use = CHANNEL_NUM;
>> +
>> +		/* Only channel 0 supports checksum,
>> +		 * so turn off checksum to enable multiple channels.
>> +		 */
>> +		for (i = 1; i < CHANNEL_NUM; i++)
>> +			plat->tx_queues_cfg[i].coe_unsupported = 1;
>> +
>> +		ret = loongson_dwmac_config_msi(pdev, plat, &res, np);
>> +		break;
>> +	default:	/* 0x35 device and 0x37 device. */
>> +		plat->tx_queues_to_use = 1;
>> +		plat->rx_queues_to_use = 1;
>> +		ret = loongson_dwmac_config_legacy(pdev, plat, &res, np);
>> +		break;
>>   	}
>>   
>> -	pci_enable_msi(pdev);
>> -	memset(&res, 0, sizeof(res));
>> -	res.addr = pcim_iomap_table(pdev)[0];
>> +	/* GNET devices with dev revision 0x00 do not support manually
>> +	 * setting the speed to 1000.
>> +	 */
>> +	if (pdev->device == PCI_DEVICE_ID_LOONGSON_GNET &&
>> +	    pdev->revision == 0x00)
>> +		plat->flags |= STMMAC_FLAG_DISABLE_FORCE_1000;
> Move this to the loongson_gnet_data() method.
Okay, But I noticed your comment at the end that we need to splite as a

separate _pre-requisite/preparation_ patch, this fix is for gnet devices, there is no gnet at this time. So, if I 
understand you correctly, we should need two patches: net: stmmac: 
dwmac-loongson: Disable force 1000 net: stmmac: dwmac-loongson: Add 
Loongson GNET support net: stmmac: dwmac-loongson:  Move DISABLE_FORCE_1000 flag to loongson_gnet_data() method

>
>>   
>>   	ret = stmmac_dvr_probe(&pdev->dev, plat, &res);
>>   	if (ret)
>> -		goto err_disable_msi;
>> +		goto err_disable_device;
>>   
>>   	return ret;
>>   
>> -err_disable_msi:
>> -	pci_disable_msi(pdev);
>>   err_disable_device:
>>   	pci_disable_device(pdev);
>>   err_put_node:
>> @@ -248,6 +644,7 @@ static SIMPLE_DEV_PM_OPS(loongson_dwmac_pm_ops, loongson_dwmac_suspend,
>>   
>>   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);
>> @@ -266,4 +663,5 @@ module_pci_driver(loongson_dwmac_driver);
>>   
>>   MODULE_DESCRIPTION("Loongson DWMAC PCI driver");
>>   MODULE_AUTHOR("Qing Zhang <zhangqing@loongson.cn>");
>> +MODULE_AUTHOR("Yanteng Si <siyanteng@loongson.cn>");
>>   MODULE_LICENSE("GPL v2");
> Please move this into a separate patch. It can be the last patch in
> the series.
Okay.
>
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
>> index f161ec9ac490..66c0c22908b1 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
>> @@ -296,3 +296,4 @@ const struct stmmac_dma_ops dwmac1000_dma_ops = {
>>   	.get_hw_feature = dwmac1000_get_hw_feature,
>>   	.rx_watchdog = dwmac1000_rx_watchdog,
>>   };
>> +EXPORT_SYMBOL_GPL(dwmac1000_dma_ops);
>
> Please move this into a preparation/pre-requisite patch.
Okay.
>
>
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
>> index e1537a57815f..e94faa72f30e 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
>> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
>> @@ -420,6 +420,12 @@ stmmac_ethtool_set_link_ksettings(struct net_device *dev,
>>   		return 0;
>>   	}
>>   
>> +	if (priv->plat->flags & STMMAC_FLAG_DISABLE_FORCE_1000) {
>> +		if (cmd->base.speed == SPEED_1000 &&
>> +		    cmd->base.autoneg != AUTONEG_ENABLE)
>> +			return -EOPNOTSUPP;
>> +	}
>> +
>>   	return phylink_ethtool_ksettings_set(priv->phylink, cmd);
>>   }
>>   
>> diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
>> index 1b54b84a6785..c5d3d0ddb6f8 100644
>> --- a/include/linux/stmmac.h
>> +++ b/include/linux/stmmac.h
>> @@ -223,6 +223,7 @@ struct dwmac4_addrs {
>>   #define STMMAC_FLAG_RX_CLK_RUNS_IN_LPI		BIT(10)
>>   #define STMMAC_FLAG_EN_TX_LPI_CLOCKGATING	BIT(11)
>>   #define STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY	BIT(12)
>> +#define STMMAC_FLAG_DISABLE_FORCE_1000		BIT(13)
>>   
>>   struct plat_stmmacenet_data {
>>   	int bus_id;
> Please move this in a separate _pre-requisite/preparation_ patch.
> Really. Why have you merged it into this one? This patch already got
> to be too complicated. Don't make it even more complex.
Ok, I'll split them again.
>
> ---
>
> I look at v8 and look at v9 series. Why have you re-shuffled the
> change so significantly??? It has made my life in reviewing your bits
> much harder because instead of checking whether you took my v8-notes
> into account I had to once again analyze the entire series. Sigh...

Sorry to put the pressure on you.

I think it is because there ware so many changes to the v8, and I take a 
long

time to get through all the comments. I'll try to shorten it in the future.


This version of the comments I can do easily, except 
loongson_dwmac_config_multi_msi(),

and once I get it done, I will send v12. (Maybe next Monday? I hope so.)


Thanks,

Yanteng



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

* Re: [PATCH net-next v11 6/6] net: stmmac: dwmac-loongson: Add Loongson GNET support
  2024-04-20 11:02     ` Yanteng Si
@ 2024-04-21  5:35       ` Yanteng Si
  0 siblings, 0 replies; 36+ messages in thread
From: Yanteng Si @ 2024-04-21  5:35 UTC (permalink / raw)
  To: Serge Semin
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang, siyanteng01


在 2024/4/20 19:02, Yanteng Si 写道:
>>> - memset(&res, 0, sizeof(res));
>>> -    res.addr = pcim_iomap_table(pdev)[0];
>>> +    /* GNET devices with dev revision 0x00 do not support manually
>>> +     * setting the speed to 1000.
>>> +     */
>>> +    if (pdev->device == PCI_DEVICE_ID_LOONGSON_GNET &&
>>> +        pdev->revision == 0x00)
>>> +        plat->flags |= STMMAC_FLAG_DISABLE_FORCE_1000;
>> Move this to the loongson_gnet_data() method.
> Okay, But I noticed your comment at the end that we need to splite as a
>
> separate _pre-requisite/preparation_ patch, this fix is for gnet 
> devices, there is no gnet at this time. So, if I understand you 
> correctly, we should need two patches: net: stmmac: dwmac-loongson: 
> Disable force 1000 net: stmmac: dwmac-loongson: Add Loongson GNET 
> support net: stmmac: dwmac-loongson:  Move DISABLE_FORCE_1000 flag to 
> loongson_gnet_data() method

Sorry, my email client messed things up.

Okay, But I noticed your comment at the end that we need to splite as a

separate _pre-requisite/preparation_ patch, this fix is for gnet devices,

there is no gnet at this time. So, if I understand you correctly, we should

need two new patches:

++ net: stmmac: dwmac-loongson: Disable force 1000

     net: stmmac: dwmac-loongson: Add Loongson GNET support

++ net: stmmac: dwmac-loongson:  Move DISABLE_FORCE_1000 flag to 
loongson_gnet_data() method


Thanks,

Yanteng



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

* Re: [PATCH net-next v11 4/6] net: stmmac: dwmac-loongson: Introduce GMAC setup
  2024-04-12 11:28 ` [PATCH net-next v11 4/6] net: stmmac: dwmac-loongson: Introduce GMAC setup Yanteng Si
  2024-04-18 12:26   ` Serge Semin
@ 2024-04-22 10:17   ` Yanteng Si
  1 sibling, 0 replies; 36+ messages in thread
From: Yanteng Si @ 2024-04-22 10:17 UTC (permalink / raw)
  To: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	fancer.lancer
  Cc: Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang, siyanteng01

Hi all

在 2024/4/12 19:28, Yanteng Si 写道:
> @@ -42,6 +45,12 @@ static int loongson_default_data(struct plat_stmmacenet_data *plat)
>   	plat->dma_cfg->pblx8 = true;
>   
>   	plat->multicast_filter_bins = 256;
> +	plat->clk_ref_rate = 125000000;
> +	plat->clk_ptp_rate = 125000000;
> +

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

Sorry, I forgot to delete them.


This part of the code has been moved to loongson_dwmac_probe() in this 
patch set, Why?


Because we have two different gnet devices: the 2k2000 supports multiple 
channels,

the 7a2000 only supports single channels, and all GMAC devices only 
support single channels.


If we keep this part of the code here, we will get GMAC_VERSION again in 
gnet_data()

  to distinguish them, which will make the code more complex. We can use 
GMAC_VERSION

in probe to distinguish them easily.


  so the patch will be redesigned in v12.


Thanks,

Yanteng


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

* Re: [PATCH net-next v11 6/6] net: stmmac: dwmac-loongson: Add Loongson GNET support
  2024-04-18 14:01   ` Serge Semin
  2024-04-20 11:02     ` Yanteng Si
@ 2024-04-23 13:16     ` Yanteng Si
  2024-04-24 14:11     ` Huacai Chen
  2 siblings, 0 replies; 36+ messages in thread
From: Yanteng Si @ 2024-04-23 13:16 UTC (permalink / raw)
  To: Serge Semin
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, chenhuacai, linux, guyinggang, netdev,
	chris.chenfeiyang, siyanteng01

Hi Serge,

在 2024/4/18 22:01, Serge Semin 写道:
> Once again. Please replace this with simpler solution:
>
> static int loongson_dwmac_config_multi_msi(struct pci_dev *pdev,
> +					   struct plat_stmmacenet_data *plat,
> +					   struct stmmac_resources *res)
> +{
> +	int i, ret, vecs;
> +
> +	/* INT NAME | MAC | CH7 rx | CH7 tx | ... | CH0 rx | CH0 tx |
> +	 * --------- ----- -------- --------  ...  -------- --------
> +	 * IRQ NUM  |  0  |   1    |   2    | ... |   15   |   16   |
> +	 */
> +	vecs = plat->rx_queues_to_use + plat->tx_queues_to_use + 1;

Referring to the msi spec, the number of vectors should be the power of 
two, so let's:


vecs = roundup_pow_of_two(plat->rx_queues_to_use + 
plat->tx_queues_to_use + 1);

or

vecs = roundup_pow_of_two(CHANNEL_NUM * 2 + 1);


? :)


Thanks,

Yanteng



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

* Re: [PATCH net-next v11 6/6] net: stmmac: dwmac-loongson: Add Loongson GNET support
  2024-04-12 11:28 ` [PATCH net-next v11 6/6] net: stmmac: dwmac-loongson: Add Loongson GNET support Yanteng Si
  2024-04-18 14:01   ` Serge Semin
@ 2024-04-24 13:37   ` Huacai Chen
  2024-04-25  8:09     ` Yanteng Si
  1 sibling, 1 reply; 36+ messages in thread
From: Huacai Chen @ 2024-04-24 13:37 UTC (permalink / raw)
  To: Yanteng Si
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	fancer.lancer, Jose.Abreu, linux, guyinggang, netdev,
	chris.chenfeiyang, siyanteng01

Hi, Yanteng,

On Fri, Apr 12, 2024 at 7:29 PM Yanteng Si <siyanteng@loongson.cn> wrote:
>
> There are two types of Loongson DWGMAC. The first type shares the same
> register definitions and has similar logic as dwmac1000. The second type
> uses several different register definitions, we think it is necessary to
> distinguish rx and tx, so we split these bits into two.
>
> Simply put, we split some single bit fields into double bits fileds:
>
>      Name              Tx          Rx
>
> DMA_INTR_ENA_NIE = 0x00040000 | 0x00020000;
> DMA_INTR_ENA_AIE = 0x00010000 | 0x00008000;
> DMA_STATUS_NIS   = 0x00040000 | 0x00020000;
> DMA_STATUS_AIS   = 0x00010000 | 0x00008000;
> DMA_STATUS_FBI   = 0x00002000 | 0x00001000;
>
> Therefore, when using, TX and RX must be set at the same time.
>
> How to use them:
>  1. Create the Loongson GNET-specific
>  stmmac_dma_ops.dma_interrupt()
>  stmmac_dma_ops.init_chan()
>  methods in the dwmac-loongson.c driver. Adding all the
>  Loongson-specific macros
>
>  2. Create a Loongson GNET-specific platform setup method with the next
>  semantics:
>     + allocate stmmac_dma_ops instance and initialize it with
>       dwmac1000_dma_ops.
>     + override the stmmac_dma_ops.{dma_interrupt, init_chan} with
>       the pointers to the methods defined in 2.
>     + allocate mac_device_info instance and initialize the
>       mac_device_info.dma field with a pointer to the new
>       stmmac_dma_ops instance.
>     + initialize mac_device_info in a way it's done in
>       dwmac1000_setup().
>
>  3. Initialize plat_stmmacenet_data.setup() with the pointer to the
>  method created in 2.
>
> GNET features:
>
>  Speeds: 10/100/1000Mbps
>  DMA-descriptors type: normal and enhanced
>  L3/L4 filters availability: support
>  VLAN hash table filter: support
>  PHY-interface: GMII
>  Remote Wake-up support: support
>  Mac Management Counters (MMC): support
>  DMA chennel number: 0x10 device is 8 and 0x37 device is 1
>
> Others:
>
>  GNET integrates both MAC and PHY chips inside.
>  GNET device: LS2K2000, LS7A2000, the chip connection between the mac and
>              phy of these devices is not normal and requires two rounds of
>              negotiation; LS7A2000 does not support half-duplex and
>              multi-channel;
>
>              To enable multi-channel on LS2K2000, you need to turn off
>              hardware checksum.
>
> **Note**: Currently, only the LS2K2000's IP core is 0x10, while the IP
> cores of other devices are 0x37.
>
> Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
> Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
> Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
> ---
>  drivers/net/ethernet/stmicro/stmmac/common.h  |   2 +
>  .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 476 ++++++++++++++++--
>  .../ethernet/stmicro/stmmac/dwmac1000_dma.c   |   1 +
>  .../ethernet/stmicro/stmmac/stmmac_ethtool.c  |   6 +
>  include/linux/stmmac.h                        |   1 +
>  5 files changed, 447 insertions(+), 39 deletions(-)
>
> diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
> index 9cd62b2110a1..6777dc997e9f 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/common.h
> +++ b/drivers/net/ethernet/stmicro/stmmac/common.h
> @@ -29,6 +29,7 @@
>  /* 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
> @@ -258,6 +259,7 @@ struct stmmac_safety_stats {
>  #define CSR_F_300M     300000000
>
>  #define        MAC_CSR_H_FRQ_MASK      0x20
> +#define        MAC_CTRL_PORT_SELECT_10_100     BIT(15)
>
>  #define HASH_TABLE_SIZE 64
>  #define PAUSE_TIME 0xffff
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> index 69078eb1f923..4edfbb4fcb64 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> @@ -8,8 +8,70 @@
>  #include <linux/device.h>
>  #include <linux/of_irq.h>
>  #include "stmmac.h"
> +#include "dwmac_dma.h"
> +#include "dwmac1000.h"
> +
> +/* Normal Loongson Tx Summary */
> +#define DMA_INTR_ENA_NIE_TX_LOONGSON   0x00040000
> +/* Normal Loongson Rx Summary */
> +#define DMA_INTR_ENA_NIE_RX_LOONGSON   0x00020000
> +
> +#define DMA_INTR_NORMAL_LOONGSON       (DMA_INTR_ENA_NIE_TX_LOONGSON | \
> +                                        DMA_INTR_ENA_NIE_RX_LOONGSON | \
> +                                        DMA_INTR_ENA_RIE | DMA_INTR_ENA_TIE)
> +
> +/* Abnormal Loongson Tx Summary */
> +#define DMA_INTR_ENA_AIE_TX_LOONGSON   0x00010000
> +/* Abnormal Loongson Rx Summary */
> +#define DMA_INTR_ENA_AIE_RX_LOONGSON   0x00008000
> +
> +#define DMA_INTR_ABNORMAL_LOONGSON     (DMA_INTR_ENA_AIE_TX_LOONGSON | \
> +                                        DMA_INTR_ENA_AIE_RX_LOONGSON | \
> +                                        DMA_INTR_ENA_FBE | DMA_INTR_ENA_UNE)
> +
> +#define DMA_INTR_DEFAULT_MASK_LOONGSON (DMA_INTR_NORMAL_LOONGSON | \
> +                                        DMA_INTR_ABNORMAL_LOONGSON)
> +
> +/* Normal Loongson Tx Interrupt Summary */
> +#define DMA_STATUS_NIS_TX_LOONGSON     0x00040000
> +/* Normal Loongson Rx Interrupt Summary */
> +#define DMA_STATUS_NIS_RX_LOONGSON     0x00020000
> +
> +/* Abnormal Loongson Tx Interrupt Summary */
> +#define DMA_STATUS_AIS_TX_LOONGSON     0x00010000
> +/* Abnormal Loongson Rx Interrupt Summary */
> +#define DMA_STATUS_AIS_RX_LOONGSON     0x00008000
> +
> +/* Fatal Loongson Tx Bus Error Interrupt */
> +#define DMA_STATUS_FBI_TX_LOONGSON     0x00002000
> +/* Fatal Loongson Rx Bus Error Interrupt */
> +#define DMA_STATUS_FBI_RX_LOONGSON     0x00001000
> +
> +#define DMA_STATUS_MSK_COMMON_LOONGSON (DMA_STATUS_NIS_TX_LOONGSON | \
> +                                        DMA_STATUS_NIS_RX_LOONGSON | \
> +                                        DMA_STATUS_AIS_TX_LOONGSON | \
> +                                        DMA_STATUS_AIS_RX_LOONGSON | \
> +                                        DMA_STATUS_FBI_TX_LOONGSON | \
> +                                        DMA_STATUS_FBI_RX_LOONGSON)
> +
> +#define DMA_STATUS_MSK_RX_LOONGSON     (DMA_STATUS_ERI | DMA_STATUS_RWT | \
> +                                        DMA_STATUS_RPS | DMA_STATUS_RU  | \
> +                                        DMA_STATUS_RI  | DMA_STATUS_OVF | \
> +                                        DMA_STATUS_MSK_COMMON_LOONGSON)
> +
> +#define DMA_STATUS_MSK_TX_LOONGSON     (DMA_STATUS_ETI | DMA_STATUS_UNF | \
> +                                        DMA_STATUS_TJT | DMA_STATUS_TU  | \
> +                                        DMA_STATUS_TPS | DMA_STATUS_TI  | \
> +                                        DMA_STATUS_MSK_COMMON_LOONGSON)
>
>  #define PCI_DEVICE_ID_LOONGSON_GMAC    0x7a03
> +#define PCI_DEVICE_ID_LOONGSON_GNET    0x7a13
> +#define LOONGSON_DWMAC_CORE_1_00       0x10    /* Loongson custom IP */
> +#define CHANNEL_NUM                    8
> +
> +struct loongson_data {
> +       struct device *dev;
> +};
>
>  struct stmmac_pci_info {
>         int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat);
> @@ -56,6 +117,8 @@ static int loongson_gmac_data(struct pci_dev *pdev,
>         plat->dma_cfg->pblx8 = true;
>
>         plat->multicast_filter_bins = 256;
> +       plat->mdio_bus_data->phy_mask = 0;
> +
>         plat->clk_ref_rate = 125000000;
>         plat->clk_ptp_rate = 125000000;
>
> @@ -69,13 +132,342 @@ 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)
> +static void loongson_gnet_dma_init_channel(struct stmmac_priv *priv,
> +                                          void __iomem *ioaddr,
> +                                          struct stmmac_dma_cfg *dma_cfg,
> +                                          u32 chan)
> +{
> +       int txpbl = dma_cfg->txpbl ?: dma_cfg->pbl;
> +       int rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl;
> +       u32 value;
> +
> +       /* common channel control register config */
> +       value = readl(ioaddr + DMA_CHAN_BUS_MODE(chan));
> +
> +       /* Set the DMA PBL (Programmable Burst Length) mode.
> +        *
> +        * Note: before stmmac core 3.50 this mode bit was 4xPBL, and
> +        * post 3.5 mode bit acts as 8*PBL.
> +        */
> +       if (dma_cfg->pblx8)
> +               value |= DMA_BUS_MODE_MAXPBL;
> +
> +       value |= DMA_BUS_MODE_USP;
> +       value &= ~(DMA_BUS_MODE_PBL_MASK | DMA_BUS_MODE_RPBL_MASK);
> +       value |= (txpbl << DMA_BUS_MODE_PBL_SHIFT);
> +       value |= (rxpbl << DMA_BUS_MODE_RPBL_SHIFT);
> +
> +       /* Set the Fixed burst mode */
> +       if (dma_cfg->fixed_burst)
> +               value |= DMA_BUS_MODE_FB;
> +
> +       /* Mixed Burst has no effect when fb is set */
> +       if (dma_cfg->mixed_burst)
> +               value |= DMA_BUS_MODE_MB;
> +
> +       if (dma_cfg->atds)
> +               value |= DMA_BUS_MODE_ATDS;
> +
> +       if (dma_cfg->aal)
> +               value |= DMA_BUS_MODE_AAL;
> +
> +       writel(value, ioaddr + DMA_CHAN_BUS_MODE(chan));
> +
> +       /* Mask interrupts by writing to CSR7 */
> +       writel(DMA_INTR_DEFAULT_MASK_LOONGSON, ioaddr +
> +              DMA_CHAN_INTR_ENA(chan));
> +}
> +
> +static int loongson_gnet_dma_interrupt(struct stmmac_priv *priv,
> +                                      void __iomem *ioaddr,
> +                                      struct stmmac_extra_stats *x,
> +                                      u32 chan, u32 dir)
> +{
> +       struct stmmac_pcpu_stats *stats = this_cpu_ptr(priv->xstats.pcpu_stats);
> +       u32 abnor_intr_status;
> +       u32 nor_intr_status;
> +       u32 fb_intr_status;
> +       u32 intr_status;
> +       int ret = 0;
> +
> +       /* read the status register (CSR5) */
> +       intr_status = readl(ioaddr + DMA_CHAN_STATUS(chan));
> +
> +       if (dir == DMA_DIR_RX)
> +               intr_status &= DMA_STATUS_MSK_RX_LOONGSON;
> +       else if (dir == DMA_DIR_TX)
> +               intr_status &= DMA_STATUS_MSK_TX_LOONGSON;
> +
> +       nor_intr_status = intr_status & (DMA_STATUS_NIS_TX_LOONGSON |
> +               DMA_STATUS_NIS_RX_LOONGSON);
> +       abnor_intr_status = intr_status & (DMA_STATUS_AIS_TX_LOONGSON |
> +               DMA_STATUS_AIS_RX_LOONGSON);
> +       fb_intr_status = intr_status & (DMA_STATUS_FBI_TX_LOONGSON |
> +               DMA_STATUS_FBI_RX_LOONGSON);
> +
> +       /* ABNORMAL interrupts */
> +       if (unlikely(abnor_intr_status)) {
> +               if (unlikely(intr_status & DMA_STATUS_UNF)) {
> +                       ret = tx_hard_error_bump_tc;
> +                       x->tx_undeflow_irq++;
> +               }
> +               if (unlikely(intr_status & DMA_STATUS_TJT))
> +                       x->tx_jabber_irq++;
> +               if (unlikely(intr_status & DMA_STATUS_OVF))
> +                       x->rx_overflow_irq++;
> +               if (unlikely(intr_status & DMA_STATUS_RU))
> +                       x->rx_buf_unav_irq++;
> +               if (unlikely(intr_status & DMA_STATUS_RPS))
> +                       x->rx_process_stopped_irq++;
> +               if (unlikely(intr_status & DMA_STATUS_RWT))
> +                       x->rx_watchdog_irq++;
> +               if (unlikely(intr_status & DMA_STATUS_ETI))
> +                       x->tx_early_irq++;
> +               if (unlikely(intr_status & DMA_STATUS_TPS)) {
> +                       x->tx_process_stopped_irq++;
> +                       ret = tx_hard_error;
> +               }
> +               if (unlikely(fb_intr_status)) {
> +                       x->fatal_bus_error_irq++;
> +                       ret = tx_hard_error;
> +               }
> +       }
> +       /* TX/RX NORMAL interrupts */
> +       if (likely(nor_intr_status)) {
> +               if (likely(intr_status & DMA_STATUS_RI)) {
> +                       u32 value = readl(ioaddr + DMA_INTR_ENA);
> +                       /* to schedule NAPI on real RIE event. */
> +                       if (likely(value & DMA_INTR_ENA_RIE)) {
> +                               u64_stats_update_begin(&stats->syncp);
> +                               u64_stats_inc(&stats->rx_normal_irq_n[chan]);
> +                               u64_stats_update_end(&stats->syncp);
> +                               ret |= handle_rx;
> +                       }
> +               }
> +               if (likely(intr_status & DMA_STATUS_TI)) {
> +                       u64_stats_update_begin(&stats->syncp);
> +                       u64_stats_inc(&stats->tx_normal_irq_n[chan]);
> +                       u64_stats_update_end(&stats->syncp);
> +                       ret |= handle_tx;
> +               }
> +               if (unlikely(intr_status & DMA_STATUS_ERI))
> +                       x->rx_early_irq++;
> +       }
> +       /* Optional hardware blocks, interrupts should be disabled */
> +       if (unlikely(intr_status &
> +                    (DMA_STATUS_GPI | DMA_STATUS_GMI | DMA_STATUS_GLI)))
> +               pr_warn("%s: unexpected status %08x\n", __func__, intr_status);
> +
> +       /* Clear the interrupt by writing a logic 1 to the CSR5[15-0] */
> +       writel((intr_status & 0x7ffff), ioaddr + DMA_CHAN_STATUS(chan));
> +
> +       return ret;
> +}
> +
> +static void loongson_gnet_fix_speed(void *priv, unsigned int speed,
> +                                   unsigned int mode)
> +{
> +       struct loongson_data *ld = (struct loongson_data *)priv;
> +       struct net_device *ndev = dev_get_drvdata(ld->dev);
> +       struct stmmac_priv *ptr = netdev_priv(ndev);
> +
> +       /* The controller and PHY don't work well together.
> +        * We need to use the PS bit to check if the controller's status
> +        * is correct and reset PHY if necessary.
> +        * MAC_CTRL_REG.15 is defined by the GMAC_CONTROL_PS macro.
> +        */
> +       if (speed == SPEED_1000) {
> +               if (readl(ptr->ioaddr + MAC_CTRL_REG) &
> +                   MAC_CTRL_PORT_SELECT_10_100)
> +                       /* Word around hardware bug, restart autoneg */
> +                       phy_restart_aneg(ndev->phydev);
> +       }
> +}
> +
> +static int loongson_gnet_data(struct pci_dev *pdev,
> +                             struct plat_stmmacenet_data *plat)
> +{
> +       loongson_default_data(pdev, plat);
> +
> +       plat->phy_addr = -1;
> +       plat->phy_interface = PHY_INTERFACE_MODE_GMII;
> +
> +       plat->dma_cfg->pbl = 32;
> +       plat->dma_cfg->pblx8 = true;
> +
> +       plat->multicast_filter_bins = 256;
> +       plat->mdio_bus_data->phy_mask = ~(u32)BIT(2);
> +
> +       plat->clk_ref_rate = 125000000;
> +       plat->clk_ptp_rate = 125000000;
> +
> +       plat->fix_mac_speed = loongson_gnet_fix_speed;
> +
> +       return 0;
> +}
> +
> +static struct stmmac_pci_info loongson_gnet_pci_info = {
> +       .setup = loongson_gnet_data,
> +};
> +
> +static int loongson_dwmac_config_legacy(struct pci_dev *pdev,
> +                                       struct plat_stmmacenet_data *plat,
> +                                       struct stmmac_resources *res,
> +                                       struct device_node *np)
> +{
> +       if (np) {
> +               res->irq = of_irq_get_byname(np, "macirq");
> +               if (res->irq < 0) {
> +                       dev_err(&pdev->dev, "IRQ macirq not found\n");
> +                       return -ENODEV;
> +               }
> +
> +               res->wol_irq = of_irq_get_byname(np, "eth_wake_irq");
> +               if (res->wol_irq < 0) {
> +                       dev_info(&pdev->dev,
> +                                "IRQ eth_wake_irq not found, using macirq\n");
> +                       res->wol_irq = res->irq;
> +               }
> +
> +               res->lpi_irq = of_irq_get_byname(np, "eth_lpi");
> +               if (res->lpi_irq < 0) {
> +                       dev_err(&pdev->dev, "IRQ eth_lpi not found\n");
> +                       return -ENODEV;
> +               }
> +       } else {
> +               res->irq = pdev->irq;
> +               res->wol_irq = res->irq;
> +       }
> +
> +       return 0;
> +}
> +
> +static int loongson_dwmac_config_msi(struct pci_dev *pdev,
> +                                    struct plat_stmmacenet_data *plat,
> +                                    struct stmmac_resources *res,
> +                                    struct device_node *np)
> +{
> +       int i, ret, vecs;
> +
> +       vecs = roundup_pow_of_two(CHANNEL_NUM * 2 + 1);
> +       ret = pci_alloc_irq_vectors(pdev, vecs, vecs, PCI_IRQ_MSI);
> +       if (ret < 0) {
> +               dev_info(&pdev->dev,
> +                        "MSI enable failed, Fallback to legacy interrupt\n");
> +               return loongson_dwmac_config_legacy(pdev, plat, res, np);
> +       }
> +
> +       res->irq = pci_irq_vector(pdev, 0);
> +       res->wol_irq = 0;
> +
> +       /* INT NAME | MAC | CH7 rx | CH7 tx | ... | CH0 rx | CH0 tx |
> +        * --------- ----- -------- --------  ...  -------- --------
> +        * IRQ NUM  |  0  |   1    |   2    | ... |   15   |   16   |
> +        */
> +       for (i = 0; i < CHANNEL_NUM; i++) {
> +               res->rx_irq[CHANNEL_NUM - 1 - i] =
> +                       pci_irq_vector(pdev, 1 + i * 2);
> +               res->tx_irq[CHANNEL_NUM - 1 - i] =
> +                       pci_irq_vector(pdev, 2 + i * 2);
> +       }
> +
> +       plat->flags |= STMMAC_FLAG_MULTI_MSI_EN;
> +
> +       return 0;
> +}
> +
> +static struct mac_device_info *loongson_dwmac_setup(void *apriv)
> +{
> +       struct stmmac_priv *priv = apriv;
> +       struct stmmac_resources res;
> +       struct mac_device_info *mac;
> +       struct stmmac_dma_ops *dma;
> +       struct pci_dev *pdev;
> +       u32 loongson_gmac;
> +
> +       memset(&res, 0, sizeof(res));
> +       pdev = to_pci_dev(priv->device);
> +       res.addr = pcim_iomap_table(pdev)[0];
> +       loongson_gmac = readl(res.addr + GMAC_VERSION) & 0xff;
We can add a "gmac_version" in loongson_data, then we only need to
read it once in the probe function.

Huacai

> +
> +       mac = devm_kzalloc(priv->device, sizeof(*mac), GFP_KERNEL);
> +       if (!mac)
> +               return NULL;
> +
> +       dma = devm_kzalloc(priv->device, sizeof(*dma), GFP_KERNEL);
> +       if (!dma)
> +               return NULL;
> +
> +       /* The original IP-core version is 0x37 in all Loongson GNET
> +        * (ls2k2000 and ls7a2000), but the GNET HW designers have changed the
> +        * GMAC_VERSION.SNPSVER field to the custom 0x10 value on the Loongson
> +        * ls2k2000 MAC to emphasize the differences: multiple DMA-channels,
> +        * AV feature and GMAC_INT_STATUS CSR flags layout. Get back the
> +        * original value so the correct HW-interface would be selected.
> +        */
> +       if (loongson_gmac == LOONGSON_DWMAC_CORE_1_00) {
> +               priv->synopsys_id = DWMAC_CORE_3_70;
> +               *dma = dwmac1000_dma_ops;
> +               dma->init_chan = loongson_gnet_dma_init_channel;
> +               dma->dma_interrupt = loongson_gnet_dma_interrupt;
> +               mac->dma = dma;
> +       }
> +
> +       mac->mac = &dwmac1000_ops;
> +       priv->dev->priv_flags |= IFF_UNICAST_FLT;
> +
> +       /* Pre-initialize the respective "mac" fields as it's done in
> +        * dwmac1000_setup()
> +        */
> +       mac->pcsr = priv->ioaddr;
> +       mac->multicast_filter_bins = priv->plat->multicast_filter_bins;
> +       mac->unicast_filter_entries = priv->plat->unicast_filter_entries;
> +       mac->mcast_bits_log2 = 0;
> +
> +       if (mac->multicast_filter_bins)
> +               mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins);
> +
> +       /* The GMAC devices with PCI ID 0x7a03 does not support any pause mode.
> +        * The GNET devices without CORE ID 0x10 does not support half-duplex.
> +        */
> +       if (pdev->device == PCI_DEVICE_ID_LOONGSON_GMAC) {
> +               mac->link.caps = MAC_10 | MAC_100 | MAC_1000;
> +       } else {
> +               if (loongson_gmac == LOONGSON_DWMAC_CORE_1_00)
> +                       mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
> +                                        MAC_10 | MAC_100 | MAC_1000;
> +               else
> +                       mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
> +                                        MAC_10FD | MAC_100FD | MAC_1000FD;
> +       }
> +
> +       mac->link.duplex = GMAC_CONTROL_DM;
> +       mac->link.speed10 = GMAC_CONTROL_PS;
> +       mac->link.speed100 = GMAC_CONTROL_PS | GMAC_CONTROL_FES;
> +       mac->link.speed1000 = 0;
> +       mac->link.speed_mask = GMAC_CONTROL_PS | GMAC_CONTROL_FES;
> +       mac->mii.addr = GMAC_MII_ADDR;
> +       mac->mii.data = GMAC_MII_DATA;
> +       mac->mii.addr_shift = 11;
> +       mac->mii.addr_mask = 0x0000F800;
> +       mac->mii.reg_shift = 6;
> +       mac->mii.reg_mask = 0x000007C0;
> +       mac->mii.clk_csr_shift = 2;
> +       mac->mii.clk_csr_mask = GENMASK(5, 2);
> +
> +       return mac;
> +}
> +
> +static int loongson_dwmac_probe(struct pci_dev *pdev,
> +                               const struct pci_device_id *id)
>  {
>         struct plat_stmmacenet_data *plat;
>         int ret, i, bus_id, phy_mode;
>         struct stmmac_pci_info *info;
>         struct stmmac_resources res;
> +       struct loongson_data *ld;
>         struct device_node *np;
> +       u32 loongson_gmac;
>
>         plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL);
>         if (!plat)
> @@ -88,10 +482,14 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
>                 return -ENOMEM;
>
>         plat->dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*plat->dma_cfg), GFP_KERNEL);
> -       if (!plat->dma_cfg) {
> -               ret = -ENOMEM;
> -               goto err_put_node;
> -       }
> +       if (!plat->dma_cfg)
> +               return -ENOMEM;
> +
> +       ld = devm_kzalloc(&pdev->dev, sizeof(*ld), GFP_KERNEL);
> +       if (!ld)
> +               return -ENOMEM;
> +
> +       np = dev_of_node(&pdev->dev);
>
>         /* Enable pci device */
>         ret = pci_enable_device(pdev);
> @@ -110,14 +508,6 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
>                 break;
>         }
>
> -       phy_mode = device_get_phy_mode(&pdev->dev);
> -       if (phy_mode < 0) {
> -               dev_err(&pdev->dev, "phy_mode not found\n");
> -               ret = phy_mode;
> -               goto err_disable_device;
> -       }
> -
> -       plat->phy_interface = phy_mode;
>         plat->mac_interface = PHY_INTERFACE_MODE_GMII;
>
>         pci_set_master(pdev);
> @@ -133,7 +523,6 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
>                         dev_info(&pdev->dev, "Found MDIO subnode\n");
>                         plat->mdio_bus_data->needs_reset = true;
>                 }
> -
>                 bus_id = of_alias_get_id(np, "ethernet");
>                 if (bus_id >= 0)
>                         plat->bus_id = bus_id;
> @@ -145,42 +534,49 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
>                         goto err_disable_device;
>                 }
>                 plat->phy_interface = phy_mode;
> +       }
>
> -               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;
> -               }
> +       plat->bsp_priv = ld;
> +       plat->setup = loongson_dwmac_setup;
> +       ld->dev = &pdev->dev;
>
> -               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;
> -               }
> +       memset(&res, 0, sizeof(res));
> +       res.addr = pcim_iomap_table(pdev)[0];
> +       loongson_gmac = readl(res.addr + GMAC_VERSION) & 0xff;
>
> -               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;
> +       switch (loongson_gmac) {
> +       case LOONGSON_DWMAC_CORE_1_00:
> +               plat->rx_queues_to_use = CHANNEL_NUM;
> +               plat->tx_queues_to_use = CHANNEL_NUM;
> +
> +               /* Only channel 0 supports checksum,
> +                * so turn off checksum to enable multiple channels.
> +                */
> +               for (i = 1; i < CHANNEL_NUM; i++)
> +                       plat->tx_queues_cfg[i].coe_unsupported = 1;
> +
> +               ret = loongson_dwmac_config_msi(pdev, plat, &res, np);
> +               break;
> +       default:        /* 0x35 device and 0x37 device. */
> +               plat->tx_queues_to_use = 1;
> +               plat->rx_queues_to_use = 1;
> +               ret = loongson_dwmac_config_legacy(pdev, plat, &res, np);
> +               break;
>         }
>
> -       pci_enable_msi(pdev);
> -       memset(&res, 0, sizeof(res));
> -       res.addr = pcim_iomap_table(pdev)[0];
> +       /* GNET devices with dev revision 0x00 do not support manually
> +        * setting the speed to 1000.
> +        */
> +       if (pdev->device == PCI_DEVICE_ID_LOONGSON_GNET &&
> +           pdev->revision == 0x00)
> +               plat->flags |= STMMAC_FLAG_DISABLE_FORCE_1000;
>
>         ret = stmmac_dvr_probe(&pdev->dev, plat, &res);
>         if (ret)
> -               goto err_disable_msi;
> +               goto err_disable_device;
>
>         return ret;
>
> -err_disable_msi:
> -       pci_disable_msi(pdev);
>  err_disable_device:
>         pci_disable_device(pdev);
>  err_put_node:
> @@ -248,6 +644,7 @@ static SIMPLE_DEV_PM_OPS(loongson_dwmac_pm_ops, loongson_dwmac_suspend,
>
>  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);
> @@ -266,4 +663,5 @@ module_pci_driver(loongson_dwmac_driver);
>
>  MODULE_DESCRIPTION("Loongson DWMAC PCI driver");
>  MODULE_AUTHOR("Qing Zhang <zhangqing@loongson.cn>");
> +MODULE_AUTHOR("Yanteng Si <siyanteng@loongson.cn>");
>  MODULE_LICENSE("GPL v2");
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> index f161ec9ac490..66c0c22908b1 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> @@ -296,3 +296,4 @@ const struct stmmac_dma_ops dwmac1000_dma_ops = {
>         .get_hw_feature = dwmac1000_get_hw_feature,
>         .rx_watchdog = dwmac1000_rx_watchdog,
>  };
> +EXPORT_SYMBOL_GPL(dwmac1000_dma_ops);
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> index e1537a57815f..e94faa72f30e 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> @@ -420,6 +420,12 @@ stmmac_ethtool_set_link_ksettings(struct net_device *dev,
>                 return 0;
>         }
>
> +       if (priv->plat->flags & STMMAC_FLAG_DISABLE_FORCE_1000) {
> +               if (cmd->base.speed == SPEED_1000 &&
> +                   cmd->base.autoneg != AUTONEG_ENABLE)
> +                       return -EOPNOTSUPP;
> +       }
> +
>         return phylink_ethtool_ksettings_set(priv->phylink, cmd);
>  }
>
> diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
> index 1b54b84a6785..c5d3d0ddb6f8 100644
> --- a/include/linux/stmmac.h
> +++ b/include/linux/stmmac.h
> @@ -223,6 +223,7 @@ struct dwmac4_addrs {
>  #define STMMAC_FLAG_RX_CLK_RUNS_IN_LPI         BIT(10)
>  #define STMMAC_FLAG_EN_TX_LPI_CLOCKGATING      BIT(11)
>  #define STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY   BIT(12)
> +#define STMMAC_FLAG_DISABLE_FORCE_1000         BIT(13)
>
>  struct plat_stmmacenet_data {
>         int bus_id;
> --
> 2.31.4
>

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

* Re: [PATCH net-next v11 6/6] net: stmmac: dwmac-loongson: Add Loongson GNET support
  2024-04-18 14:01   ` Serge Semin
  2024-04-20 11:02     ` Yanteng Si
  2024-04-23 13:16     ` Yanteng Si
@ 2024-04-24 14:11     ` Huacai Chen
  2024-04-24 14:46       ` Russell King (Oracle)
  2024-04-25  8:07       ` Yanteng Si
  2 siblings, 2 replies; 36+ messages in thread
From: Huacai Chen @ 2024-04-24 14:11 UTC (permalink / raw)
  To: Serge Semin
  Cc: Yanteng Si, andrew, hkallweit1, peppe.cavallaro,
	alexandre.torgue, joabreu, Jose.Abreu, linux, guyinggang, netdev,
	chris.chenfeiyang, siyanteng01

Hi, Serge,

On Thu, Apr 18, 2024 at 10:01 PM Serge Semin <fancer.lancer@gmail.com> wrote:
>
> On Fri, Apr 12, 2024 at 07:28:51PM +0800, Yanteng Si wrote:
> > There are two types of Loongson DWGMAC. The first type shares the same
> > register definitions and has similar logic as dwmac1000. The second type
> > uses several different register definitions, we think it is necessary to
> > distinguish rx and tx, so we split these bits into two.
> >
> > Simply put, we split some single bit fields into double bits fileds:
> >
> >      Name              Tx          Rx
> >
> > DMA_INTR_ENA_NIE = 0x00040000 | 0x00020000;
> > DMA_INTR_ENA_AIE = 0x00010000 | 0x00008000;
> > DMA_STATUS_NIS   = 0x00040000 | 0x00020000;
> > DMA_STATUS_AIS   = 0x00010000 | 0x00008000;
> > DMA_STATUS_FBI   = 0x00002000 | 0x00001000;
> >
> > Therefore, when using, TX and RX must be set at the same time.
> >
> > How to use them:
> >  1. Create the Loongson GNET-specific
> >  stmmac_dma_ops.dma_interrupt()
> >  stmmac_dma_ops.init_chan()
> >  methods in the dwmac-loongson.c driver. Adding all the
> >  Loongson-specific macros
> >
> >  2. Create a Loongson GNET-specific platform setup method with the next
> >  semantics:
> >     + allocate stmmac_dma_ops instance and initialize it with
> >       dwmac1000_dma_ops.
> >     + override the stmmac_dma_ops.{dma_interrupt, init_chan} with
> >       the pointers to the methods defined in 2.
> >     + allocate mac_device_info instance and initialize the
> >       mac_device_info.dma field with a pointer to the new
> >       stmmac_dma_ops instance.
> >     + initialize mac_device_info in a way it's done in
> >       dwmac1000_setup().
> >
> >  3. Initialize plat_stmmacenet_data.setup() with the pointer to the
> >  method created in 2.
> >
> > GNET features:
> >
> >  Speeds: 10/100/1000Mbps
>
> >  DMA-descriptors type: normal and enhanced
>
> Hm, it's either one or another. They can't be both supported because
> the alternative descriptors are enabled by the DESC_ENHANCED_FORMAT
> HDL parameter defined on the IP-core synthesize stage.
>
> >  L3/L4 filters availability: support
> >  VLAN hash table filter: support
> >  PHY-interface: GMII
> >  Remote Wake-up support: support
> >  Mac Management Counters (MMC): support
> >  DMA chennel number: 0x10 device is 8 and 0x37 device is 1
>
> What about adding the info like:
> Number of additional MAC addresses
> MAC Hash-based filter support and if supported the hash table size.
>
> >
> > Others:
> >
> >  GNET integrates both MAC and PHY chips inside.
> >  GNET device: LS2K2000, LS7A2000, the chip connection between the mac and
> >              phy of these devices is not normal and requires two rounds of
> >              negotiation; LS7A2000 does not support half-duplex and
> >              multi-channel;
> >
> >              To enable multi-channel on LS2K2000, you need to turn off
> >              hardware checksum.
> >
>
> > **Note**: Currently, only the LS2K2000's IP core is 0x10,
>
> This doesn't sound correct. The LS2K2000's IP-core is v3.73a. But the
> SNPS Version ID was manually altered by the hardware designers.
>
> > while the IP
> > cores of other devices are 0x37.
>
> Real IP-core ID isn't described by the hex number. It's a digit number
> like v3.73a/v3.50a/etc. Hex number you constantly repeat is the
> MAC_Version.SNPSVER register value. So please use the IP-core version
> in the v3.xx format all over the patch text.
>
> >
> > Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
> > Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
> > Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
> > ---
> >  drivers/net/ethernet/stmicro/stmmac/common.h  |   2 +
> >  .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 476 ++++++++++++++++--
> >  .../ethernet/stmicro/stmmac/dwmac1000_dma.c   |   1 +
> >  .../ethernet/stmicro/stmmac/stmmac_ethtool.c  |   6 +
> >  include/linux/stmmac.h                        |   1 +
> >  5 files changed, 447 insertions(+), 39 deletions(-)
> >
> > diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
> > index 9cd62b2110a1..6777dc997e9f 100644
> > --- a/drivers/net/ethernet/stmicro/stmmac/common.h
> > +++ b/drivers/net/ethernet/stmicro/stmmac/common.h
> > @@ -29,6 +29,7 @@
> >  /* 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
> > @@ -258,6 +259,7 @@ struct stmmac_safety_stats {
> >  #define CSR_F_300M   300000000
> >
> >  #define      MAC_CSR_H_FRQ_MASK      0x20
>
> > +#define      MAC_CTRL_PORT_SELECT_10_100     BIT(15)
>
> No, this is already defined in:
> drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
> as GMAC_CONTROL_PS macros. Use it instead of adding new macros.
>
> >
> >  #define HASH_TABLE_SIZE 64
> >  #define PAUSE_TIME 0xffff
> > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > index 69078eb1f923..4edfbb4fcb64 100644
> > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > @@ -8,8 +8,70 @@
> >  #include <linux/device.h>
> >  #include <linux/of_irq.h>
> >  #include "stmmac.h"
> > +#include "dwmac_dma.h"
> > +#include "dwmac1000.h"
> > +
> > +/* Normal Loongson Tx Summary */
> > +#define DMA_INTR_ENA_NIE_TX_LOONGSON 0x00040000
> > +/* Normal Loongson Rx Summary */
> > +#define DMA_INTR_ENA_NIE_RX_LOONGSON 0x00020000
> > +
> > +#define DMA_INTR_NORMAL_LOONGSON     (DMA_INTR_ENA_NIE_TX_LOONGSON | \
> > +                                      DMA_INTR_ENA_NIE_RX_LOONGSON | \
> > +                                      DMA_INTR_ENA_RIE | DMA_INTR_ENA_TIE)
> > +
> > +/* Abnormal Loongson Tx Summary */
> > +#define DMA_INTR_ENA_AIE_TX_LOONGSON 0x00010000
> > +/* Abnormal Loongson Rx Summary */
> > +#define DMA_INTR_ENA_AIE_RX_LOONGSON 0x00008000
> > +
> > +#define DMA_INTR_ABNORMAL_LOONGSON   (DMA_INTR_ENA_AIE_TX_LOONGSON | \
> > +                                      DMA_INTR_ENA_AIE_RX_LOONGSON | \
> > +                                      DMA_INTR_ENA_FBE | DMA_INTR_ENA_UNE)
> > +
> > +#define DMA_INTR_DEFAULT_MASK_LOONGSON       (DMA_INTR_NORMAL_LOONGSON | \
> > +                                      DMA_INTR_ABNORMAL_LOONGSON)
> > +
> > +/* Normal Loongson Tx Interrupt Summary */
> > +#define DMA_STATUS_NIS_TX_LOONGSON   0x00040000
> > +/* Normal Loongson Rx Interrupt Summary */
> > +#define DMA_STATUS_NIS_RX_LOONGSON   0x00020000
> > +
> > +/* Abnormal Loongson Tx Interrupt Summary */
> > +#define DMA_STATUS_AIS_TX_LOONGSON   0x00010000
> > +/* Abnormal Loongson Rx Interrupt Summary */
> > +#define DMA_STATUS_AIS_RX_LOONGSON   0x00008000
> > +
> > +/* Fatal Loongson Tx Bus Error Interrupt */
> > +#define DMA_STATUS_FBI_TX_LOONGSON   0x00002000
> > +/* Fatal Loongson Rx Bus Error Interrupt */
> > +#define DMA_STATUS_FBI_RX_LOONGSON   0x00001000
> > +
> > +#define DMA_STATUS_MSK_COMMON_LOONGSON       (DMA_STATUS_NIS_TX_LOONGSON | \
> > +                                      DMA_STATUS_NIS_RX_LOONGSON | \
> > +                                      DMA_STATUS_AIS_TX_LOONGSON | \
> > +                                      DMA_STATUS_AIS_RX_LOONGSON | \
> > +                                      DMA_STATUS_FBI_TX_LOONGSON | \
> > +                                      DMA_STATUS_FBI_RX_LOONGSON)
> > +
> > +#define DMA_STATUS_MSK_RX_LOONGSON   (DMA_STATUS_ERI | DMA_STATUS_RWT | \
> > +                                      DMA_STATUS_RPS | DMA_STATUS_RU  | \
> > +                                      DMA_STATUS_RI  | DMA_STATUS_OVF | \
> > +                                      DMA_STATUS_MSK_COMMON_LOONGSON)
> > +
> > +#define DMA_STATUS_MSK_TX_LOONGSON   (DMA_STATUS_ETI | DMA_STATUS_UNF | \
> > +                                      DMA_STATUS_TJT | DMA_STATUS_TU  | \
> > +                                      DMA_STATUS_TPS | DMA_STATUS_TI  | \
> > +                                      DMA_STATUS_MSK_COMMON_LOONGSON)
> >
> >  #define PCI_DEVICE_ID_LOONGSON_GMAC  0x7a03
> > +#define PCI_DEVICE_ID_LOONGSON_GNET  0x7a13
> > +#define LOONGSON_DWMAC_CORE_1_00     0x10    /* Loongson custom IP */
> > +#define CHANNEL_NUM                  8
> > +
> > +struct loongson_data {
> > +     struct device *dev;
> > +};
> >
> >  struct stmmac_pci_info {
> >       int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat);
> > @@ -56,6 +117,8 @@ static int loongson_gmac_data(struct pci_dev *pdev,
> >       plat->dma_cfg->pblx8 = true;
> >
> >       plat->multicast_filter_bins = 256;
>
> > +     plat->mdio_bus_data->phy_mask = 0;
> > +
>
> And this change isn't related to the GNET. Why is it here?
>
> >       plat->clk_ref_rate = 125000000;
> >       plat->clk_ptp_rate = 125000000;
> >
> > @@ -69,13 +132,342 @@ 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)
> > +static void loongson_gnet_dma_init_channel(struct stmmac_priv *priv,
> > +                                        void __iomem *ioaddr,
> > +                                        struct stmmac_dma_cfg *dma_cfg,
> > +                                        u32 chan)
> > +{
> > +     int txpbl = dma_cfg->txpbl ?: dma_cfg->pbl;
> > +     int rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl;
> > +     u32 value;
> > +
>
> > +     /* common channel control register config */
>
> Useless comment. Please drop.
>
> > +     value = readl(ioaddr + DMA_CHAN_BUS_MODE(chan));
> > +
>
> > +     /* Set the DMA PBL (Programmable Burst Length) mode.
> > +      *
> > +      * Note: before stmmac core 3.50 this mode bit was 4xPBL, and
> > +      * post 3.5 mode bit acts as 8*PBL.
> > +      */
>
> Do you have an IP-core older than v3.50a? No. So please drop the
> comment.
>
> > +     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;
> > +
> > +     if (dma_cfg->atds)
> > +             value |= DMA_BUS_MODE_ATDS;
> > +
> > +     if (dma_cfg->aal)
> > +             value |= DMA_BUS_MODE_AAL;
> > +
> > +     writel(value, ioaddr + DMA_CHAN_BUS_MODE(chan));
> > +
> > +     /* Mask interrupts by writing to CSR7 */
> > +     writel(DMA_INTR_DEFAULT_MASK_LOONGSON, ioaddr +
> > +            DMA_CHAN_INTR_ENA(chan));
> > +}
> > +
> > +static int loongson_gnet_dma_interrupt(struct stmmac_priv *priv,
> > +                                    void __iomem *ioaddr,
> > +                                    struct stmmac_extra_stats *x,
> > +                                    u32 chan, u32 dir)
> > +{
> > +     struct stmmac_pcpu_stats *stats = this_cpu_ptr(priv->xstats.pcpu_stats);
> > +     u32 abnor_intr_status;
> > +     u32 nor_intr_status;
> > +     u32 fb_intr_status;
> > +     u32 intr_status;
> > +     int ret = 0;
> > +
> > +     /* read the status register (CSR5) */
> > +     intr_status = readl(ioaddr + DMA_CHAN_STATUS(chan));
> > +
> > +     if (dir == DMA_DIR_RX)
> > +             intr_status &= DMA_STATUS_MSK_RX_LOONGSON;
> > +     else if (dir == DMA_DIR_TX)
> > +             intr_status &= DMA_STATUS_MSK_TX_LOONGSON;
> > +
> > +     nor_intr_status = intr_status & (DMA_STATUS_NIS_TX_LOONGSON |
> > +             DMA_STATUS_NIS_RX_LOONGSON);
> > +     abnor_intr_status = intr_status & (DMA_STATUS_AIS_TX_LOONGSON |
> > +             DMA_STATUS_AIS_RX_LOONGSON);
> > +     fb_intr_status = intr_status & (DMA_STATUS_FBI_TX_LOONGSON |
> > +             DMA_STATUS_FBI_RX_LOONGSON);
> > +
> > +     /* ABNORMAL interrupts */
> > +     if (unlikely(abnor_intr_status)) {
> > +             if (unlikely(intr_status & DMA_STATUS_UNF)) {
> > +                     ret = tx_hard_error_bump_tc;
> > +                     x->tx_undeflow_irq++;
> > +             }
> > +             if (unlikely(intr_status & DMA_STATUS_TJT))
> > +                     x->tx_jabber_irq++;
> > +             if (unlikely(intr_status & DMA_STATUS_OVF))
> > +                     x->rx_overflow_irq++;
> > +             if (unlikely(intr_status & DMA_STATUS_RU))
> > +                     x->rx_buf_unav_irq++;
> > +             if (unlikely(intr_status & DMA_STATUS_RPS))
> > +                     x->rx_process_stopped_irq++;
> > +             if (unlikely(intr_status & DMA_STATUS_RWT))
> > +                     x->rx_watchdog_irq++;
> > +             if (unlikely(intr_status & DMA_STATUS_ETI))
> > +                     x->tx_early_irq++;
> > +             if (unlikely(intr_status & DMA_STATUS_TPS)) {
> > +                     x->tx_process_stopped_irq++;
> > +                     ret = tx_hard_error;
> > +             }
> > +             if (unlikely(fb_intr_status)) {
> > +                     x->fatal_bus_error_irq++;
> > +                     ret = tx_hard_error;
> > +             }
> > +     }
> > +     /* TX/RX NORMAL interrupts */
> > +     if (likely(nor_intr_status)) {
> > +             if (likely(intr_status & DMA_STATUS_RI)) {
> > +                     u32 value = readl(ioaddr + DMA_INTR_ENA);
> > +                     /* to schedule NAPI on real RIE event. */
> > +                     if (likely(value & DMA_INTR_ENA_RIE)) {
> > +                             u64_stats_update_begin(&stats->syncp);
> > +                             u64_stats_inc(&stats->rx_normal_irq_n[chan]);
> > +                             u64_stats_update_end(&stats->syncp);
> > +                             ret |= handle_rx;
> > +                     }
> > +             }
> > +             if (likely(intr_status & DMA_STATUS_TI)) {
> > +                     u64_stats_update_begin(&stats->syncp);
> > +                     u64_stats_inc(&stats->tx_normal_irq_n[chan]);
> > +                     u64_stats_update_end(&stats->syncp);
> > +                     ret |= handle_tx;
> > +             }
> > +             if (unlikely(intr_status & DMA_STATUS_ERI))
> > +                     x->rx_early_irq++;
> > +     }
> > +     /* Optional hardware blocks, interrupts should be disabled */
> > +     if (unlikely(intr_status &
> > +                  (DMA_STATUS_GPI | DMA_STATUS_GMI | DMA_STATUS_GLI)))
> > +             pr_warn("%s: unexpected status %08x\n", __func__, intr_status);
> > +
> > +     /* Clear the interrupt by writing a logic 1 to the CSR5[15-0] */
> > +     writel((intr_status & 0x7ffff), ioaddr + DMA_CHAN_STATUS(chan));
> > +
> > +     return ret;
> > +}
> > +
> > +static void loongson_gnet_fix_speed(void *priv, unsigned int speed,
> > +                                 unsigned int mode)
> > +{
> > +     struct loongson_data *ld = (struct loongson_data *)priv;
> > +     struct net_device *ndev = dev_get_drvdata(ld->dev);
> > +     struct stmmac_priv *ptr = netdev_priv(ndev);
> > +
> > +     /* The controller and PHY don't work well together.
> > +      * We need to use the PS bit to check if the controller's status
> > +      * is correct and reset PHY if necessary.
> > +      * MAC_CTRL_REG.15 is defined by the GMAC_CONTROL_PS macro.
> > +      */
> > +     if (speed == SPEED_1000) {
> > +             if (readl(ptr->ioaddr + MAC_CTRL_REG) &
>
> > +                 MAC_CTRL_PORT_SELECT_10_100)
>
> GMAC_CONTROL_PS?
>
> > +                     /* Word around hardware bug, restart autoneg */
> > +                     phy_restart_aneg(ndev->phydev);
> > +     }
> > +}
> > +
> > +static int loongson_gnet_data(struct pci_dev *pdev,
> > +                           struct plat_stmmacenet_data *plat)
> > +{
> > +     loongson_default_data(pdev, plat);
> > +
> > +     plat->phy_addr = -1;
> > +     plat->phy_interface = PHY_INTERFACE_MODE_GMII;
> > +
> > +     plat->dma_cfg->pbl = 32;
> > +     plat->dma_cfg->pblx8 = true;
> > +
> > +     plat->multicast_filter_bins = 256;
> > +     plat->mdio_bus_data->phy_mask = ~(u32)BIT(2);
> > +
>
> > +     plat->clk_ref_rate = 125000000;
> > +     plat->clk_ptp_rate = 125000000;
>
> If this is common for both GMAC and GNET what about moving it to the
> loongson_default_data() method?
>
> If so please just do that in the patch 4 where you get to add these
> fields initialization in the first place.
>
> > +
> > +     plat->fix_mac_speed = loongson_gnet_fix_speed;
> > +
> > +     return 0;
> > +}
> > +
> > +static struct stmmac_pci_info loongson_gnet_pci_info = {
> > +     .setup = loongson_gnet_data,
> > +};
> > +
> > +static int loongson_dwmac_config_legacy(struct pci_dev *pdev,
> > +                                     struct plat_stmmacenet_data *plat,
> > +                                     struct stmmac_resources *res,
> > +                                     struct device_node *np)
> > +{
> > +     if (np) {
> > +             res->irq = of_irq_get_byname(np, "macirq");
> > +             if (res->irq < 0) {
> > +                     dev_err(&pdev->dev, "IRQ macirq not found\n");
> > +                     return -ENODEV;
> > +             }
> > +
> > +             res->wol_irq = of_irq_get_byname(np, "eth_wake_irq");
> > +             if (res->wol_irq < 0) {
> > +                     dev_info(&pdev->dev,
> > +                              "IRQ eth_wake_irq not found, using macirq\n");
> > +                     res->wol_irq = res->irq;
> > +             }
> > +
> > +             res->lpi_irq = of_irq_get_byname(np, "eth_lpi");
> > +             if (res->lpi_irq < 0) {
> > +                     dev_err(&pdev->dev, "IRQ eth_lpi not found\n");
> > +                     return -ENODEV;
> > +             }
> > +     } else {
> > +             res->irq = pdev->irq;
> > +             res->wol_irq = res->irq;
> > +     }
> > +
> > +     return 0;
> > +}
> > +
> > +static int loongson_dwmac_config_msi(struct pci_dev *pdev,
> > +                                  struct plat_stmmacenet_data *plat,
> > +                                  struct stmmac_resources *res,
> > +                                  struct device_node *np)
> > +{
> > +     int i, ret, vecs;
> > +
> > +     vecs = roundup_pow_of_two(CHANNEL_NUM * 2 + 1);
> > +     ret = pci_alloc_irq_vectors(pdev, vecs, vecs, PCI_IRQ_MSI);
> > +     if (ret < 0) {
> > +             dev_info(&pdev->dev,
> > +                      "MSI enable failed, Fallback to legacy interrupt\n");
> > +             return loongson_dwmac_config_legacy(pdev, plat, res, np);
> > +     }
> > +
> > +     res->irq = pci_irq_vector(pdev, 0);
> > +     res->wol_irq = 0;
> > +
> > +     /* INT NAME | MAC | CH7 rx | CH7 tx | ... | CH0 rx | CH0 tx |
> > +      * --------- ----- -------- --------  ...  -------- --------
> > +      * IRQ NUM  |  0  |   1    |   2    | ... |   15   |   16   |
> > +      */
> > +     for (i = 0; i < CHANNEL_NUM; i++) {
> > +             res->rx_irq[CHANNEL_NUM - 1 - i] =
> > +                     pci_irq_vector(pdev, 1 + i * 2);
> > +             res->tx_irq[CHANNEL_NUM - 1 - i] =
> > +                     pci_irq_vector(pdev, 2 + i * 2);
> > +     }
> > +
> > +     plat->flags |= STMMAC_FLAG_MULTI_MSI_EN;
>
> Once again. Please replace this with simpler solution:
In full PCI system the below function works fine, because alloc irq
vectors with PCI_IRQ_LEGACY do the same thing as fallback to call
loongson_dwmac_config_legacy(). But for a DT-based system it doesn't
work.

Huacai
>
> static int loongson_dwmac_config_multi_msi(struct pci_dev *pdev,
> +                                          struct plat_stmmacenet_data *plat,
> +                                          struct stmmac_resources *res)
> +{
> +       int i, ret, vecs;
> +
> +       /* INT NAME | MAC | CH7 rx | CH7 tx | ... | CH0 rx | CH0 tx |
> +        * --------- ----- -------- --------  ...  -------- --------
> +        * IRQ NUM  |  0  |   1    |   2    | ... |   15   |   16   |
> +        */
> +       vecs = plat->rx_queues_to_use + plat->tx_queues_to_use + 1;
> +       ret = pci_alloc_irq_vectors(pdev, 1, vecs, PCI_IRQ_MSI | PCI_IRQ_LEGACY);
> +       if (ret < 0) {
> +               dev_err(&pdev->dev, "Failed to allocate PCI IRQs\n");
> +               return ret;
> +       } else if (ret >= vecs) {
> +               for (i = 0; i < plat->rx_queues_to_use; i++) {
> +                       res->rx_irq[CHANNELS_NUM - 1 - i] =
> +                               pci_irq_vector(pdev, 1 + i * 2);
> +               }
> +               for (i = 0; i < plat->tx_queues_to_use; i++) {
> +                       res->tx_irq[CHANNELS_NUM - 1 - i] =
> +                               pci_irq_vector(pdev, 2 + i * 2);
> +               }
> +
> +               plat->flags |= STMMAC_FLAG_MULTI_MSI_EN;
> +       }
> +
> +       res->irq = pci_irq_vector(pdev, 0);
> +
> +       return 0;
> +}
>
>
> > +
> > +     return 0;
> > +}
> > +
> > +static struct mac_device_info *loongson_dwmac_setup(void *apriv)
> > +{
> > +     struct stmmac_priv *priv = apriv;
> > +     struct stmmac_resources res;
> > +     struct mac_device_info *mac;
> > +     struct stmmac_dma_ops *dma;
> > +     struct pci_dev *pdev;
> > +     u32 loongson_gmac;
> > +
> > +     memset(&res, 0, sizeof(res));
> > +     pdev = to_pci_dev(priv->device);
> > +     res.addr = pcim_iomap_table(pdev)[0];
> > +     loongson_gmac = readl(res.addr + GMAC_VERSION) & 0xff;
> > +
> > +     mac = devm_kzalloc(priv->device, sizeof(*mac), GFP_KERNEL);
> > +     if (!mac)
> > +             return NULL;
> > +
> > +     dma = devm_kzalloc(priv->device, sizeof(*dma), GFP_KERNEL);
> > +     if (!dma)
> > +             return NULL;
> > +
> > +     /* The original IP-core version is 0x37 in all Loongson GNET
> > +      * (ls2k2000 and ls7a2000), but the GNET HW designers have changed the
> > +      * GMAC_VERSION.SNPSVER field to the custom 0x10 value on the Loongson
> > +      * ls2k2000 MAC to emphasize the differences: multiple DMA-channels,
> > +      * AV feature and GMAC_INT_STATUS CSR flags layout. Get back the
> > +      * original value so the correct HW-interface would be selected.
> > +      */
> > +     if (loongson_gmac == LOONGSON_DWMAC_CORE_1_00) {
> > +             priv->synopsys_id = DWMAC_CORE_3_70;
> > +             *dma = dwmac1000_dma_ops;
> > +             dma->init_chan = loongson_gnet_dma_init_channel;
> > +             dma->dma_interrupt = loongson_gnet_dma_interrupt;
> > +             mac->dma = dma;
> > +     }
> > +
> > +     mac->mac = &dwmac1000_ops;
> > +     priv->dev->priv_flags |= IFF_UNICAST_FLT;
> > +
> > +     /* Pre-initialize the respective "mac" fields as it's done in
> > +      * dwmac1000_setup()
> > +      */
> > +     mac->pcsr = priv->ioaddr;
> > +     mac->multicast_filter_bins = priv->plat->multicast_filter_bins;
> > +     mac->unicast_filter_entries = priv->plat->unicast_filter_entries;
> > +     mac->mcast_bits_log2 = 0;
> > +
> > +     if (mac->multicast_filter_bins)
> > +             mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins);
> > +
> > +     /* The GMAC devices with PCI ID 0x7a03 does not support any pause mode.
> > +      * The GNET devices without CORE ID 0x10 does not support half-duplex.
> > +      */
> > +     if (pdev->device == PCI_DEVICE_ID_LOONGSON_GMAC) {
> > +             mac->link.caps = MAC_10 | MAC_100 | MAC_1000;
> > +     } else {
> > +             if (loongson_gmac == LOONGSON_DWMAC_CORE_1_00)
> > +                     mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
> > +                                      MAC_10 | MAC_100 | MAC_1000;
> > +             else
> > +                     mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
> > +                                      MAC_10FD | MAC_100FD | MAC_1000FD;
> > +     }
> > +
> > +     mac->link.duplex = GMAC_CONTROL_DM;
> > +     mac->link.speed10 = GMAC_CONTROL_PS;
> > +     mac->link.speed100 = GMAC_CONTROL_PS | GMAC_CONTROL_FES;
> > +     mac->link.speed1000 = 0;
> > +     mac->link.speed_mask = GMAC_CONTROL_PS | GMAC_CONTROL_FES;
> > +     mac->mii.addr = GMAC_MII_ADDR;
> > +     mac->mii.data = GMAC_MII_DATA;
> > +     mac->mii.addr_shift = 11;
> > +     mac->mii.addr_mask = 0x0000F800;
> > +     mac->mii.reg_shift = 6;
> > +     mac->mii.reg_mask = 0x000007C0;
> > +     mac->mii.clk_csr_shift = 2;
> > +     mac->mii.clk_csr_mask = GENMASK(5, 2);
> > +
> > +     return mac;
> > +}
> > +
> > +static int loongson_dwmac_probe(struct pci_dev *pdev,
> > +                             const struct pci_device_id *id)
> >  {
> >       struct plat_stmmacenet_data *plat;
> >       int ret, i, bus_id, phy_mode;
> >       struct stmmac_pci_info *info;
> >       struct stmmac_resources res;
> > +     struct loongson_data *ld;
> >       struct device_node *np;
> > +     u32 loongson_gmac;
> >
> >       plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL);
> >       if (!plat)
> > @@ -88,10 +482,14 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
> >               return -ENOMEM;
> >
> >       plat->dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*plat->dma_cfg), GFP_KERNEL);
> > -     if (!plat->dma_cfg) {
> > -             ret = -ENOMEM;
> > -             goto err_put_node;
> > -     }
> > +     if (!plat->dma_cfg)
> > +             return -ENOMEM;
> > +
> > +     ld = devm_kzalloc(&pdev->dev, sizeof(*ld), GFP_KERNEL);
> > +     if (!ld)
> > +             return -ENOMEM;
> > +
>
> > +     np = dev_of_node(&pdev->dev);
>
> Here is the missing np from the patch 5...
>
> >
> >       /* Enable pci device */
> >       ret = pci_enable_device(pdev);
> > @@ -110,14 +508,6 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
> >               break;
> >       }
> >
>
> > -     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;
>
> This change must have been added to the Patch 5 where you get to move
> all the NP-related things into the "if (np) {}" clause!
>
> >       plat->mac_interface = PHY_INTERFACE_MODE_GMII;
> >
> >       pci_set_master(pdev);
> > @@ -133,7 +523,6 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
> >                       dev_info(&pdev->dev, "Found MDIO subnode\n");
> >                       plat->mdio_bus_data->needs_reset = true;
> >               }
> > -
> >               bus_id = of_alias_get_id(np, "ethernet");
> >               if (bus_id >= 0)
> >                       plat->bus_id = bus_id;
> > @@ -145,42 +534,49 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
> >                       goto err_disable_device;
> >               }
> >               plat->phy_interface = phy_mode;
>
> > +     }
> >
> > -             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;
> > -             }
> > +     plat->bsp_priv = ld;
> > +     plat->setup = loongson_dwmac_setup;
> > +     ld->dev = &pdev->dev;
> >
> > -             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;
> > -             }
> > +     memset(&res, 0, sizeof(res));
> > +     res.addr = pcim_iomap_table(pdev)[0];
> > +     loongson_gmac = readl(res.addr + GMAC_VERSION) & 0xff;
> >
> > -             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;
>
> Please, move the loongson_dwmac_config_legacy() method creation change
> into a preparation/pre-requisite patch. That will vastly simplify this
> patch and will help with reviewing it!
>
> > +     switch (loongson_gmac) {
> > +     case LOONGSON_DWMAC_CORE_1_00:
> > +             plat->rx_queues_to_use = CHANNEL_NUM;
> > +             plat->tx_queues_to_use = CHANNEL_NUM;
> > +
> > +             /* Only channel 0 supports checksum,
> > +              * so turn off checksum to enable multiple channels.
> > +              */
> > +             for (i = 1; i < CHANNEL_NUM; i++)
> > +                     plat->tx_queues_cfg[i].coe_unsupported = 1;
> > +
> > +             ret = loongson_dwmac_config_msi(pdev, plat, &res, np);
> > +             break;
> > +     default:        /* 0x35 device and 0x37 device. */
> > +             plat->tx_queues_to_use = 1;
> > +             plat->rx_queues_to_use = 1;
> > +             ret = loongson_dwmac_config_legacy(pdev, plat, &res, np);
> > +             break;
> >       }
> >
> > -     pci_enable_msi(pdev);
> > -     memset(&res, 0, sizeof(res));
> > -     res.addr = pcim_iomap_table(pdev)[0];
>
> > +     /* GNET devices with dev revision 0x00 do not support manually
> > +      * setting the speed to 1000.
> > +      */
> > +     if (pdev->device == PCI_DEVICE_ID_LOONGSON_GNET &&
> > +         pdev->revision == 0x00)
> > +             plat->flags |= STMMAC_FLAG_DISABLE_FORCE_1000;
>
> Move this to the loongson_gnet_data() method.
>
> >
> >       ret = stmmac_dvr_probe(&pdev->dev, plat, &res);
> >       if (ret)
> > -             goto err_disable_msi;
> > +             goto err_disable_device;
> >
> >       return ret;
> >
> > -err_disable_msi:
> > -     pci_disable_msi(pdev);
> >  err_disable_device:
> >       pci_disable_device(pdev);
> >  err_put_node:
> > @@ -248,6 +644,7 @@ static SIMPLE_DEV_PM_OPS(loongson_dwmac_pm_ops, loongson_dwmac_suspend,
> >
> >  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);
>
> > @@ -266,4 +663,5 @@ module_pci_driver(loongson_dwmac_driver);
> >
> >  MODULE_DESCRIPTION("Loongson DWMAC PCI driver");
> >  MODULE_AUTHOR("Qing Zhang <zhangqing@loongson.cn>");
> > +MODULE_AUTHOR("Yanteng Si <siyanteng@loongson.cn>");
> >  MODULE_LICENSE("GPL v2");
>
> Please move this into a separate patch. It can be the last patch in
> the series.
>
> > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> > index f161ec9ac490..66c0c22908b1 100644
> > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> > @@ -296,3 +296,4 @@ const struct stmmac_dma_ops dwmac1000_dma_ops = {
> >       .get_hw_feature = dwmac1000_get_hw_feature,
> >       .rx_watchdog = dwmac1000_rx_watchdog,
> >  };
> > +EXPORT_SYMBOL_GPL(dwmac1000_dma_ops);
>
>
> Please move this into a preparation/pre-requisite patch.
>
>
> > diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> > index e1537a57815f..e94faa72f30e 100644
> > --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> > +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> > @@ -420,6 +420,12 @@ stmmac_ethtool_set_link_ksettings(struct net_device *dev,
> >               return 0;
> >       }
> >
> > +     if (priv->plat->flags & STMMAC_FLAG_DISABLE_FORCE_1000) {
> > +             if (cmd->base.speed == SPEED_1000 &&
> > +                 cmd->base.autoneg != AUTONEG_ENABLE)
> > +                     return -EOPNOTSUPP;
> > +     }
> > +
> >       return phylink_ethtool_ksettings_set(priv->phylink, cmd);
> >  }
> >
> > diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
> > index 1b54b84a6785..c5d3d0ddb6f8 100644
> > --- a/include/linux/stmmac.h
> > +++ b/include/linux/stmmac.h
> > @@ -223,6 +223,7 @@ struct dwmac4_addrs {
> >  #define STMMAC_FLAG_RX_CLK_RUNS_IN_LPI               BIT(10)
> >  #define STMMAC_FLAG_EN_TX_LPI_CLOCKGATING    BIT(11)
> >  #define STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY BIT(12)
> > +#define STMMAC_FLAG_DISABLE_FORCE_1000               BIT(13)
> >
> >  struct plat_stmmacenet_data {
> >       int bus_id;
>
> Please move this in a separate _pre-requisite/preparation_ patch.
> Really. Why have you merged it into this one? This patch already got
> to be too complicated. Don't make it even more complex.
>
> ---
>
> I look at v8 and look at v9 series. Why have you re-shuffled the
> change so significantly??? It has made my life in reviewing your bits
> much harder because instead of checking whether you took my v8-notes
> into account I had to once again analyze the entire series. Sigh...
>
> -Serge(y)
>
> > --
> > 2.31.4
> >

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

* Re: [PATCH net-next v11 6/6] net: stmmac: dwmac-loongson: Add Loongson GNET support
  2024-04-24 14:11     ` Huacai Chen
@ 2024-04-24 14:46       ` Russell King (Oracle)
  2024-04-25  8:07       ` Yanteng Si
  1 sibling, 0 replies; 36+ messages in thread
From: Russell King (Oracle) @ 2024-04-24 14:46 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Serge Semin, Yanteng Si, andrew, hkallweit1, peppe.cavallaro,
	alexandre.torgue, joabreu, Jose.Abreu, guyinggang, netdev,
	chris.chenfeiyang, siyanteng01

Hi,

Is there any comment in your reply? I gave up paging through trying to
find it. Hint: trim the context in your replies.

Thanks.

On Wed, Apr 24, 2024 at 10:11:20PM +0800, Huacai Chen wrote:
> Hi, Serge,
> 
> On Thu, Apr 18, 2024 at 10:01 PM Serge Semin <fancer.lancer@gmail.com> wrote:
> >
> > On Fri, Apr 12, 2024 at 07:28:51PM +0800, Yanteng Si wrote:
> > > There are two types of Loongson DWGMAC. The first type shares the same
> > > register definitions and has similar logic as dwmac1000. The second type
> > > uses several different register definitions, we think it is necessary to
> > > distinguish rx and tx, so we split these bits into two.
> > >
> > > Simply put, we split some single bit fields into double bits fileds:
> > >
> > >      Name              Tx          Rx
> > >
> > > DMA_INTR_ENA_NIE = 0x00040000 | 0x00020000;
> > > DMA_INTR_ENA_AIE = 0x00010000 | 0x00008000;
> > > DMA_STATUS_NIS   = 0x00040000 | 0x00020000;
> > > DMA_STATUS_AIS   = 0x00010000 | 0x00008000;
> > > DMA_STATUS_FBI   = 0x00002000 | 0x00001000;
> > >
> > > Therefore, when using, TX and RX must be set at the same time.
> > >
> > > How to use them:
> > >  1. Create the Loongson GNET-specific
> > >  stmmac_dma_ops.dma_interrupt()
> > >  stmmac_dma_ops.init_chan()
> > >  methods in the dwmac-loongson.c driver. Adding all the
> > >  Loongson-specific macros
> > >
> > >  2. Create a Loongson GNET-specific platform setup method with the next
> > >  semantics:
> > >     + allocate stmmac_dma_ops instance and initialize it with
> > >       dwmac1000_dma_ops.
> > >     + override the stmmac_dma_ops.{dma_interrupt, init_chan} with
> > >       the pointers to the methods defined in 2.
> > >     + allocate mac_device_info instance and initialize the
> > >       mac_device_info.dma field with a pointer to the new
> > >       stmmac_dma_ops instance.
> > >     + initialize mac_device_info in a way it's done in
> > >       dwmac1000_setup().
> > >
> > >  3. Initialize plat_stmmacenet_data.setup() with the pointer to the
> > >  method created in 2.
> > >
> > > GNET features:
> > >
> > >  Speeds: 10/100/1000Mbps
> >
> > >  DMA-descriptors type: normal and enhanced
> >
> > Hm, it's either one or another. They can't be both supported because
> > the alternative descriptors are enabled by the DESC_ENHANCED_FORMAT
> > HDL parameter defined on the IP-core synthesize stage.
> >
> > >  L3/L4 filters availability: support
> > >  VLAN hash table filter: support
> > >  PHY-interface: GMII
> > >  Remote Wake-up support: support
> > >  Mac Management Counters (MMC): support
> > >  DMA chennel number: 0x10 device is 8 and 0x37 device is 1
> >
> > What about adding the info like:
> > Number of additional MAC addresses
> > MAC Hash-based filter support and if supported the hash table size.
> >
> > >
> > > Others:
> > >
> > >  GNET integrates both MAC and PHY chips inside.
> > >  GNET device: LS2K2000, LS7A2000, the chip connection between the mac and
> > >              phy of these devices is not normal and requires two rounds of
> > >              negotiation; LS7A2000 does not support half-duplex and
> > >              multi-channel;
> > >
> > >              To enable multi-channel on LS2K2000, you need to turn off
> > >              hardware checksum.
> > >
> >
> > > **Note**: Currently, only the LS2K2000's IP core is 0x10,
> >
> > This doesn't sound correct. The LS2K2000's IP-core is v3.73a. But the
> > SNPS Version ID was manually altered by the hardware designers.
> >
> > > while the IP
> > > cores of other devices are 0x37.
> >
> > Real IP-core ID isn't described by the hex number. It's a digit number
> > like v3.73a/v3.50a/etc. Hex number you constantly repeat is the
> > MAC_Version.SNPSVER register value. So please use the IP-core version
> > in the v3.xx format all over the patch text.
> >
> > >
> > > Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
> > > Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
> > > Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
> > > ---
> > >  drivers/net/ethernet/stmicro/stmmac/common.h  |   2 +
> > >  .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 476 ++++++++++++++++--
> > >  .../ethernet/stmicro/stmmac/dwmac1000_dma.c   |   1 +
> > >  .../ethernet/stmicro/stmmac/stmmac_ethtool.c  |   6 +
> > >  include/linux/stmmac.h                        |   1 +
> > >  5 files changed, 447 insertions(+), 39 deletions(-)
> > >
> > > diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
> > > index 9cd62b2110a1..6777dc997e9f 100644
> > > --- a/drivers/net/ethernet/stmicro/stmmac/common.h
> > > +++ b/drivers/net/ethernet/stmicro/stmmac/common.h
> > > @@ -29,6 +29,7 @@
> > >  /* 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
> > > @@ -258,6 +259,7 @@ struct stmmac_safety_stats {
> > >  #define CSR_F_300M   300000000
> > >
> > >  #define      MAC_CSR_H_FRQ_MASK      0x20
> >
> > > +#define      MAC_CTRL_PORT_SELECT_10_100     BIT(15)
> >
> > No, this is already defined in:
> > drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
> > as GMAC_CONTROL_PS macros. Use it instead of adding new macros.
> >
> > >
> > >  #define HASH_TABLE_SIZE 64
> > >  #define PAUSE_TIME 0xffff
> > > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > index 69078eb1f923..4edfbb4fcb64 100644
> > > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > @@ -8,8 +8,70 @@
> > >  #include <linux/device.h>
> > >  #include <linux/of_irq.h>
> > >  #include "stmmac.h"
> > > +#include "dwmac_dma.h"
> > > +#include "dwmac1000.h"
> > > +
> > > +/* Normal Loongson Tx Summary */
> > > +#define DMA_INTR_ENA_NIE_TX_LOONGSON 0x00040000
> > > +/* Normal Loongson Rx Summary */
> > > +#define DMA_INTR_ENA_NIE_RX_LOONGSON 0x00020000
> > > +
> > > +#define DMA_INTR_NORMAL_LOONGSON     (DMA_INTR_ENA_NIE_TX_LOONGSON | \
> > > +                                      DMA_INTR_ENA_NIE_RX_LOONGSON | \
> > > +                                      DMA_INTR_ENA_RIE | DMA_INTR_ENA_TIE)
> > > +
> > > +/* Abnormal Loongson Tx Summary */
> > > +#define DMA_INTR_ENA_AIE_TX_LOONGSON 0x00010000
> > > +/* Abnormal Loongson Rx Summary */
> > > +#define DMA_INTR_ENA_AIE_RX_LOONGSON 0x00008000
> > > +
> > > +#define DMA_INTR_ABNORMAL_LOONGSON   (DMA_INTR_ENA_AIE_TX_LOONGSON | \
> > > +                                      DMA_INTR_ENA_AIE_RX_LOONGSON | \
> > > +                                      DMA_INTR_ENA_FBE | DMA_INTR_ENA_UNE)
> > > +
> > > +#define DMA_INTR_DEFAULT_MASK_LOONGSON       (DMA_INTR_NORMAL_LOONGSON | \
> > > +                                      DMA_INTR_ABNORMAL_LOONGSON)
> > > +
> > > +/* Normal Loongson Tx Interrupt Summary */
> > > +#define DMA_STATUS_NIS_TX_LOONGSON   0x00040000
> > > +/* Normal Loongson Rx Interrupt Summary */
> > > +#define DMA_STATUS_NIS_RX_LOONGSON   0x00020000
> > > +
> > > +/* Abnormal Loongson Tx Interrupt Summary */
> > > +#define DMA_STATUS_AIS_TX_LOONGSON   0x00010000
> > > +/* Abnormal Loongson Rx Interrupt Summary */
> > > +#define DMA_STATUS_AIS_RX_LOONGSON   0x00008000
> > > +
> > > +/* Fatal Loongson Tx Bus Error Interrupt */
> > > +#define DMA_STATUS_FBI_TX_LOONGSON   0x00002000
> > > +/* Fatal Loongson Rx Bus Error Interrupt */
> > > +#define DMA_STATUS_FBI_RX_LOONGSON   0x00001000
> > > +
> > > +#define DMA_STATUS_MSK_COMMON_LOONGSON       (DMA_STATUS_NIS_TX_LOONGSON | \
> > > +                                      DMA_STATUS_NIS_RX_LOONGSON | \
> > > +                                      DMA_STATUS_AIS_TX_LOONGSON | \
> > > +                                      DMA_STATUS_AIS_RX_LOONGSON | \
> > > +                                      DMA_STATUS_FBI_TX_LOONGSON | \
> > > +                                      DMA_STATUS_FBI_RX_LOONGSON)
> > > +
> > > +#define DMA_STATUS_MSK_RX_LOONGSON   (DMA_STATUS_ERI | DMA_STATUS_RWT | \
> > > +                                      DMA_STATUS_RPS | DMA_STATUS_RU  | \
> > > +                                      DMA_STATUS_RI  | DMA_STATUS_OVF | \
> > > +                                      DMA_STATUS_MSK_COMMON_LOONGSON)
> > > +
> > > +#define DMA_STATUS_MSK_TX_LOONGSON   (DMA_STATUS_ETI | DMA_STATUS_UNF | \
> > > +                                      DMA_STATUS_TJT | DMA_STATUS_TU  | \
> > > +                                      DMA_STATUS_TPS | DMA_STATUS_TI  | \
> > > +                                      DMA_STATUS_MSK_COMMON_LOONGSON)
> > >
> > >  #define PCI_DEVICE_ID_LOONGSON_GMAC  0x7a03
> > > +#define PCI_DEVICE_ID_LOONGSON_GNET  0x7a13
> > > +#define LOONGSON_DWMAC_CORE_1_00     0x10    /* Loongson custom IP */
> > > +#define CHANNEL_NUM                  8
> > > +
> > > +struct loongson_data {
> > > +     struct device *dev;
> > > +};
> > >
> > >  struct stmmac_pci_info {
> > >       int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat);
> > > @@ -56,6 +117,8 @@ static int loongson_gmac_data(struct pci_dev *pdev,
> > >       plat->dma_cfg->pblx8 = true;
> > >
> > >       plat->multicast_filter_bins = 256;
> >
> > > +     plat->mdio_bus_data->phy_mask = 0;
> > > +
> >
> > And this change isn't related to the GNET. Why is it here?
> >
> > >       plat->clk_ref_rate = 125000000;
> > >       plat->clk_ptp_rate = 125000000;
> > >
> > > @@ -69,13 +132,342 @@ 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)
> > > +static void loongson_gnet_dma_init_channel(struct stmmac_priv *priv,
> > > +                                        void __iomem *ioaddr,
> > > +                                        struct stmmac_dma_cfg *dma_cfg,
> > > +                                        u32 chan)
> > > +{
> > > +     int txpbl = dma_cfg->txpbl ?: dma_cfg->pbl;
> > > +     int rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl;
> > > +     u32 value;
> > > +
> >
> > > +     /* common channel control register config */
> >
> > Useless comment. Please drop.
> >
> > > +     value = readl(ioaddr + DMA_CHAN_BUS_MODE(chan));
> > > +
> >
> > > +     /* Set the DMA PBL (Programmable Burst Length) mode.
> > > +      *
> > > +      * Note: before stmmac core 3.50 this mode bit was 4xPBL, and
> > > +      * post 3.5 mode bit acts as 8*PBL.
> > > +      */
> >
> > Do you have an IP-core older than v3.50a? No. So please drop the
> > comment.
> >
> > > +     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;
> > > +
> > > +     if (dma_cfg->atds)
> > > +             value |= DMA_BUS_MODE_ATDS;
> > > +
> > > +     if (dma_cfg->aal)
> > > +             value |= DMA_BUS_MODE_AAL;
> > > +
> > > +     writel(value, ioaddr + DMA_CHAN_BUS_MODE(chan));
> > > +
> > > +     /* Mask interrupts by writing to CSR7 */
> > > +     writel(DMA_INTR_DEFAULT_MASK_LOONGSON, ioaddr +
> > > +            DMA_CHAN_INTR_ENA(chan));
> > > +}
> > > +
> > > +static int loongson_gnet_dma_interrupt(struct stmmac_priv *priv,
> > > +                                    void __iomem *ioaddr,
> > > +                                    struct stmmac_extra_stats *x,
> > > +                                    u32 chan, u32 dir)
> > > +{
> > > +     struct stmmac_pcpu_stats *stats = this_cpu_ptr(priv->xstats.pcpu_stats);
> > > +     u32 abnor_intr_status;
> > > +     u32 nor_intr_status;
> > > +     u32 fb_intr_status;
> > > +     u32 intr_status;
> > > +     int ret = 0;
> > > +
> > > +     /* read the status register (CSR5) */
> > > +     intr_status = readl(ioaddr + DMA_CHAN_STATUS(chan));
> > > +
> > > +     if (dir == DMA_DIR_RX)
> > > +             intr_status &= DMA_STATUS_MSK_RX_LOONGSON;
> > > +     else if (dir == DMA_DIR_TX)
> > > +             intr_status &= DMA_STATUS_MSK_TX_LOONGSON;
> > > +
> > > +     nor_intr_status = intr_status & (DMA_STATUS_NIS_TX_LOONGSON |
> > > +             DMA_STATUS_NIS_RX_LOONGSON);
> > > +     abnor_intr_status = intr_status & (DMA_STATUS_AIS_TX_LOONGSON |
> > > +             DMA_STATUS_AIS_RX_LOONGSON);
> > > +     fb_intr_status = intr_status & (DMA_STATUS_FBI_TX_LOONGSON |
> > > +             DMA_STATUS_FBI_RX_LOONGSON);
> > > +
> > > +     /* ABNORMAL interrupts */
> > > +     if (unlikely(abnor_intr_status)) {
> > > +             if (unlikely(intr_status & DMA_STATUS_UNF)) {
> > > +                     ret = tx_hard_error_bump_tc;
> > > +                     x->tx_undeflow_irq++;
> > > +             }
> > > +             if (unlikely(intr_status & DMA_STATUS_TJT))
> > > +                     x->tx_jabber_irq++;
> > > +             if (unlikely(intr_status & DMA_STATUS_OVF))
> > > +                     x->rx_overflow_irq++;
> > > +             if (unlikely(intr_status & DMA_STATUS_RU))
> > > +                     x->rx_buf_unav_irq++;
> > > +             if (unlikely(intr_status & DMA_STATUS_RPS))
> > > +                     x->rx_process_stopped_irq++;
> > > +             if (unlikely(intr_status & DMA_STATUS_RWT))
> > > +                     x->rx_watchdog_irq++;
> > > +             if (unlikely(intr_status & DMA_STATUS_ETI))
> > > +                     x->tx_early_irq++;
> > > +             if (unlikely(intr_status & DMA_STATUS_TPS)) {
> > > +                     x->tx_process_stopped_irq++;
> > > +                     ret = tx_hard_error;
> > > +             }
> > > +             if (unlikely(fb_intr_status)) {
> > > +                     x->fatal_bus_error_irq++;
> > > +                     ret = tx_hard_error;
> > > +             }
> > > +     }
> > > +     /* TX/RX NORMAL interrupts */
> > > +     if (likely(nor_intr_status)) {
> > > +             if (likely(intr_status & DMA_STATUS_RI)) {
> > > +                     u32 value = readl(ioaddr + DMA_INTR_ENA);
> > > +                     /* to schedule NAPI on real RIE event. */
> > > +                     if (likely(value & DMA_INTR_ENA_RIE)) {
> > > +                             u64_stats_update_begin(&stats->syncp);
> > > +                             u64_stats_inc(&stats->rx_normal_irq_n[chan]);
> > > +                             u64_stats_update_end(&stats->syncp);
> > > +                             ret |= handle_rx;
> > > +                     }
> > > +             }
> > > +             if (likely(intr_status & DMA_STATUS_TI)) {
> > > +                     u64_stats_update_begin(&stats->syncp);
> > > +                     u64_stats_inc(&stats->tx_normal_irq_n[chan]);
> > > +                     u64_stats_update_end(&stats->syncp);
> > > +                     ret |= handle_tx;
> > > +             }
> > > +             if (unlikely(intr_status & DMA_STATUS_ERI))
> > > +                     x->rx_early_irq++;
> > > +     }
> > > +     /* Optional hardware blocks, interrupts should be disabled */
> > > +     if (unlikely(intr_status &
> > > +                  (DMA_STATUS_GPI | DMA_STATUS_GMI | DMA_STATUS_GLI)))
> > > +             pr_warn("%s: unexpected status %08x\n", __func__, intr_status);
> > > +
> > > +     /* Clear the interrupt by writing a logic 1 to the CSR5[15-0] */
> > > +     writel((intr_status & 0x7ffff), ioaddr + DMA_CHAN_STATUS(chan));
> > > +
> > > +     return ret;
> > > +}
> > > +
> > > +static void loongson_gnet_fix_speed(void *priv, unsigned int speed,
> > > +                                 unsigned int mode)
> > > +{
> > > +     struct loongson_data *ld = (struct loongson_data *)priv;
> > > +     struct net_device *ndev = dev_get_drvdata(ld->dev);
> > > +     struct stmmac_priv *ptr = netdev_priv(ndev);
> > > +
> > > +     /* The controller and PHY don't work well together.
> > > +      * We need to use the PS bit to check if the controller's status
> > > +      * is correct and reset PHY if necessary.
> > > +      * MAC_CTRL_REG.15 is defined by the GMAC_CONTROL_PS macro.
> > > +      */
> > > +     if (speed == SPEED_1000) {
> > > +             if (readl(ptr->ioaddr + MAC_CTRL_REG) &
> >
> > > +                 MAC_CTRL_PORT_SELECT_10_100)
> >
> > GMAC_CONTROL_PS?
> >
> > > +                     /* Word around hardware bug, restart autoneg */
> > > +                     phy_restart_aneg(ndev->phydev);
> > > +     }
> > > +}
> > > +
> > > +static int loongson_gnet_data(struct pci_dev *pdev,
> > > +                           struct plat_stmmacenet_data *plat)
> > > +{
> > > +     loongson_default_data(pdev, plat);
> > > +
> > > +     plat->phy_addr = -1;
> > > +     plat->phy_interface = PHY_INTERFACE_MODE_GMII;
> > > +
> > > +     plat->dma_cfg->pbl = 32;
> > > +     plat->dma_cfg->pblx8 = true;
> > > +
> > > +     plat->multicast_filter_bins = 256;
> > > +     plat->mdio_bus_data->phy_mask = ~(u32)BIT(2);
> > > +
> >
> > > +     plat->clk_ref_rate = 125000000;
> > > +     plat->clk_ptp_rate = 125000000;
> >
> > If this is common for both GMAC and GNET what about moving it to the
> > loongson_default_data() method?
> >
> > If so please just do that in the patch 4 where you get to add these
> > fields initialization in the first place.
> >
> > > +
> > > +     plat->fix_mac_speed = loongson_gnet_fix_speed;
> > > +
> > > +     return 0;
> > > +}
> > > +
> > > +static struct stmmac_pci_info loongson_gnet_pci_info = {
> > > +     .setup = loongson_gnet_data,
> > > +};
> > > +
> > > +static int loongson_dwmac_config_legacy(struct pci_dev *pdev,
> > > +                                     struct plat_stmmacenet_data *plat,
> > > +                                     struct stmmac_resources *res,
> > > +                                     struct device_node *np)
> > > +{
> > > +     if (np) {
> > > +             res->irq = of_irq_get_byname(np, "macirq");
> > > +             if (res->irq < 0) {
> > > +                     dev_err(&pdev->dev, "IRQ macirq not found\n");
> > > +                     return -ENODEV;
> > > +             }
> > > +
> > > +             res->wol_irq = of_irq_get_byname(np, "eth_wake_irq");
> > > +             if (res->wol_irq < 0) {
> > > +                     dev_info(&pdev->dev,
> > > +                              "IRQ eth_wake_irq not found, using macirq\n");
> > > +                     res->wol_irq = res->irq;
> > > +             }
> > > +
> > > +             res->lpi_irq = of_irq_get_byname(np, "eth_lpi");
> > > +             if (res->lpi_irq < 0) {
> > > +                     dev_err(&pdev->dev, "IRQ eth_lpi not found\n");
> > > +                     return -ENODEV;
> > > +             }
> > > +     } else {
> > > +             res->irq = pdev->irq;
> > > +             res->wol_irq = res->irq;
> > > +     }
> > > +
> > > +     return 0;
> > > +}
> > > +
> > > +static int loongson_dwmac_config_msi(struct pci_dev *pdev,
> > > +                                  struct plat_stmmacenet_data *plat,
> > > +                                  struct stmmac_resources *res,
> > > +                                  struct device_node *np)
> > > +{
> > > +     int i, ret, vecs;
> > > +
> > > +     vecs = roundup_pow_of_two(CHANNEL_NUM * 2 + 1);
> > > +     ret = pci_alloc_irq_vectors(pdev, vecs, vecs, PCI_IRQ_MSI);
> > > +     if (ret < 0) {
> > > +             dev_info(&pdev->dev,
> > > +                      "MSI enable failed, Fallback to legacy interrupt\n");
> > > +             return loongson_dwmac_config_legacy(pdev, plat, res, np);
> > > +     }
> > > +
> > > +     res->irq = pci_irq_vector(pdev, 0);
> > > +     res->wol_irq = 0;
> > > +
> > > +     /* INT NAME | MAC | CH7 rx | CH7 tx | ... | CH0 rx | CH0 tx |
> > > +      * --------- ----- -------- --------  ...  -------- --------
> > > +      * IRQ NUM  |  0  |   1    |   2    | ... |   15   |   16   |
> > > +      */
> > > +     for (i = 0; i < CHANNEL_NUM; i++) {
> > > +             res->rx_irq[CHANNEL_NUM - 1 - i] =
> > > +                     pci_irq_vector(pdev, 1 + i * 2);
> > > +             res->tx_irq[CHANNEL_NUM - 1 - i] =
> > > +                     pci_irq_vector(pdev, 2 + i * 2);
> > > +     }
> > > +
> > > +     plat->flags |= STMMAC_FLAG_MULTI_MSI_EN;
> >
> > Once again. Please replace this with simpler solution:
> In full PCI system the below function works fine, because alloc irq
> vectors with PCI_IRQ_LEGACY do the same thing as fallback to call
> loongson_dwmac_config_legacy(). But for a DT-based system it doesn't
> work.
> 
> Huacai
> >
> > static int loongson_dwmac_config_multi_msi(struct pci_dev *pdev,
> > +                                          struct plat_stmmacenet_data *plat,
> > +                                          struct stmmac_resources *res)
> > +{
> > +       int i, ret, vecs;
> > +
> > +       /* INT NAME | MAC | CH7 rx | CH7 tx | ... | CH0 rx | CH0 tx |
> > +        * --------- ----- -------- --------  ...  -------- --------
> > +        * IRQ NUM  |  0  |   1    |   2    | ... |   15   |   16   |
> > +        */
> > +       vecs = plat->rx_queues_to_use + plat->tx_queues_to_use + 1;
> > +       ret = pci_alloc_irq_vectors(pdev, 1, vecs, PCI_IRQ_MSI | PCI_IRQ_LEGACY);
> > +       if (ret < 0) {
> > +               dev_err(&pdev->dev, "Failed to allocate PCI IRQs\n");
> > +               return ret;
> > +       } else if (ret >= vecs) {
> > +               for (i = 0; i < plat->rx_queues_to_use; i++) {
> > +                       res->rx_irq[CHANNELS_NUM - 1 - i] =
> > +                               pci_irq_vector(pdev, 1 + i * 2);
> > +               }
> > +               for (i = 0; i < plat->tx_queues_to_use; i++) {
> > +                       res->tx_irq[CHANNELS_NUM - 1 - i] =
> > +                               pci_irq_vector(pdev, 2 + i * 2);
> > +               }
> > +
> > +               plat->flags |= STMMAC_FLAG_MULTI_MSI_EN;
> > +       }
> > +
> > +       res->irq = pci_irq_vector(pdev, 0);
> > +
> > +       return 0;
> > +}
> >
> >
> > > +
> > > +     return 0;
> > > +}
> > > +
> > > +static struct mac_device_info *loongson_dwmac_setup(void *apriv)
> > > +{
> > > +     struct stmmac_priv *priv = apriv;
> > > +     struct stmmac_resources res;
> > > +     struct mac_device_info *mac;
> > > +     struct stmmac_dma_ops *dma;
> > > +     struct pci_dev *pdev;
> > > +     u32 loongson_gmac;
> > > +
> > > +     memset(&res, 0, sizeof(res));
> > > +     pdev = to_pci_dev(priv->device);
> > > +     res.addr = pcim_iomap_table(pdev)[0];
> > > +     loongson_gmac = readl(res.addr + GMAC_VERSION) & 0xff;
> > > +
> > > +     mac = devm_kzalloc(priv->device, sizeof(*mac), GFP_KERNEL);
> > > +     if (!mac)
> > > +             return NULL;
> > > +
> > > +     dma = devm_kzalloc(priv->device, sizeof(*dma), GFP_KERNEL);
> > > +     if (!dma)
> > > +             return NULL;
> > > +
> > > +     /* The original IP-core version is 0x37 in all Loongson GNET
> > > +      * (ls2k2000 and ls7a2000), but the GNET HW designers have changed the
> > > +      * GMAC_VERSION.SNPSVER field to the custom 0x10 value on the Loongson
> > > +      * ls2k2000 MAC to emphasize the differences: multiple DMA-channels,
> > > +      * AV feature and GMAC_INT_STATUS CSR flags layout. Get back the
> > > +      * original value so the correct HW-interface would be selected.
> > > +      */
> > > +     if (loongson_gmac == LOONGSON_DWMAC_CORE_1_00) {
> > > +             priv->synopsys_id = DWMAC_CORE_3_70;
> > > +             *dma = dwmac1000_dma_ops;
> > > +             dma->init_chan = loongson_gnet_dma_init_channel;
> > > +             dma->dma_interrupt = loongson_gnet_dma_interrupt;
> > > +             mac->dma = dma;
> > > +     }
> > > +
> > > +     mac->mac = &dwmac1000_ops;
> > > +     priv->dev->priv_flags |= IFF_UNICAST_FLT;
> > > +
> > > +     /* Pre-initialize the respective "mac" fields as it's done in
> > > +      * dwmac1000_setup()
> > > +      */
> > > +     mac->pcsr = priv->ioaddr;
> > > +     mac->multicast_filter_bins = priv->plat->multicast_filter_bins;
> > > +     mac->unicast_filter_entries = priv->plat->unicast_filter_entries;
> > > +     mac->mcast_bits_log2 = 0;
> > > +
> > > +     if (mac->multicast_filter_bins)
> > > +             mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins);
> > > +
> > > +     /* The GMAC devices with PCI ID 0x7a03 does not support any pause mode.
> > > +      * The GNET devices without CORE ID 0x10 does not support half-duplex.
> > > +      */
> > > +     if (pdev->device == PCI_DEVICE_ID_LOONGSON_GMAC) {
> > > +             mac->link.caps = MAC_10 | MAC_100 | MAC_1000;
> > > +     } else {
> > > +             if (loongson_gmac == LOONGSON_DWMAC_CORE_1_00)
> > > +                     mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
> > > +                                      MAC_10 | MAC_100 | MAC_1000;
> > > +             else
> > > +                     mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
> > > +                                      MAC_10FD | MAC_100FD | MAC_1000FD;
> > > +     }
> > > +
> > > +     mac->link.duplex = GMAC_CONTROL_DM;
> > > +     mac->link.speed10 = GMAC_CONTROL_PS;
> > > +     mac->link.speed100 = GMAC_CONTROL_PS | GMAC_CONTROL_FES;
> > > +     mac->link.speed1000 = 0;
> > > +     mac->link.speed_mask = GMAC_CONTROL_PS | GMAC_CONTROL_FES;
> > > +     mac->mii.addr = GMAC_MII_ADDR;
> > > +     mac->mii.data = GMAC_MII_DATA;
> > > +     mac->mii.addr_shift = 11;
> > > +     mac->mii.addr_mask = 0x0000F800;
> > > +     mac->mii.reg_shift = 6;
> > > +     mac->mii.reg_mask = 0x000007C0;
> > > +     mac->mii.clk_csr_shift = 2;
> > > +     mac->mii.clk_csr_mask = GENMASK(5, 2);
> > > +
> > > +     return mac;
> > > +}
> > > +
> > > +static int loongson_dwmac_probe(struct pci_dev *pdev,
> > > +                             const struct pci_device_id *id)
> > >  {
> > >       struct plat_stmmacenet_data *plat;
> > >       int ret, i, bus_id, phy_mode;
> > >       struct stmmac_pci_info *info;
> > >       struct stmmac_resources res;
> > > +     struct loongson_data *ld;
> > >       struct device_node *np;
> > > +     u32 loongson_gmac;
> > >
> > >       plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL);
> > >       if (!plat)
> > > @@ -88,10 +482,14 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
> > >               return -ENOMEM;
> > >
> > >       plat->dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*plat->dma_cfg), GFP_KERNEL);
> > > -     if (!plat->dma_cfg) {
> > > -             ret = -ENOMEM;
> > > -             goto err_put_node;
> > > -     }
> > > +     if (!plat->dma_cfg)
> > > +             return -ENOMEM;
> > > +
> > > +     ld = devm_kzalloc(&pdev->dev, sizeof(*ld), GFP_KERNEL);
> > > +     if (!ld)
> > > +             return -ENOMEM;
> > > +
> >
> > > +     np = dev_of_node(&pdev->dev);
> >
> > Here is the missing np from the patch 5...
> >
> > >
> > >       /* Enable pci device */
> > >       ret = pci_enable_device(pdev);
> > > @@ -110,14 +508,6 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
> > >               break;
> > >       }
> > >
> >
> > > -     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;
> >
> > This change must have been added to the Patch 5 where you get to move
> > all the NP-related things into the "if (np) {}" clause!
> >
> > >       plat->mac_interface = PHY_INTERFACE_MODE_GMII;
> > >
> > >       pci_set_master(pdev);
> > > @@ -133,7 +523,6 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
> > >                       dev_info(&pdev->dev, "Found MDIO subnode\n");
> > >                       plat->mdio_bus_data->needs_reset = true;
> > >               }
> > > -
> > >               bus_id = of_alias_get_id(np, "ethernet");
> > >               if (bus_id >= 0)
> > >                       plat->bus_id = bus_id;
> > > @@ -145,42 +534,49 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
> > >                       goto err_disable_device;
> > >               }
> > >               plat->phy_interface = phy_mode;
> >
> > > +     }
> > >
> > > -             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;
> > > -             }
> > > +     plat->bsp_priv = ld;
> > > +     plat->setup = loongson_dwmac_setup;
> > > +     ld->dev = &pdev->dev;
> > >
> > > -             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;
> > > -             }
> > > +     memset(&res, 0, sizeof(res));
> > > +     res.addr = pcim_iomap_table(pdev)[0];
> > > +     loongson_gmac = readl(res.addr + GMAC_VERSION) & 0xff;
> > >
> > > -             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;
> >
> > Please, move the loongson_dwmac_config_legacy() method creation change
> > into a preparation/pre-requisite patch. That will vastly simplify this
> > patch and will help with reviewing it!
> >
> > > +     switch (loongson_gmac) {
> > > +     case LOONGSON_DWMAC_CORE_1_00:
> > > +             plat->rx_queues_to_use = CHANNEL_NUM;
> > > +             plat->tx_queues_to_use = CHANNEL_NUM;
> > > +
> > > +             /* Only channel 0 supports checksum,
> > > +              * so turn off checksum to enable multiple channels.
> > > +              */
> > > +             for (i = 1; i < CHANNEL_NUM; i++)
> > > +                     plat->tx_queues_cfg[i].coe_unsupported = 1;
> > > +
> > > +             ret = loongson_dwmac_config_msi(pdev, plat, &res, np);
> > > +             break;
> > > +     default:        /* 0x35 device and 0x37 device. */
> > > +             plat->tx_queues_to_use = 1;
> > > +             plat->rx_queues_to_use = 1;
> > > +             ret = loongson_dwmac_config_legacy(pdev, plat, &res, np);
> > > +             break;
> > >       }
> > >
> > > -     pci_enable_msi(pdev);
> > > -     memset(&res, 0, sizeof(res));
> > > -     res.addr = pcim_iomap_table(pdev)[0];
> >
> > > +     /* GNET devices with dev revision 0x00 do not support manually
> > > +      * setting the speed to 1000.
> > > +      */
> > > +     if (pdev->device == PCI_DEVICE_ID_LOONGSON_GNET &&
> > > +         pdev->revision == 0x00)
> > > +             plat->flags |= STMMAC_FLAG_DISABLE_FORCE_1000;
> >
> > Move this to the loongson_gnet_data() method.
> >
> > >
> > >       ret = stmmac_dvr_probe(&pdev->dev, plat, &res);
> > >       if (ret)
> > > -             goto err_disable_msi;
> > > +             goto err_disable_device;
> > >
> > >       return ret;
> > >
> > > -err_disable_msi:
> > > -     pci_disable_msi(pdev);
> > >  err_disable_device:
> > >       pci_disable_device(pdev);
> > >  err_put_node:
> > > @@ -248,6 +644,7 @@ static SIMPLE_DEV_PM_OPS(loongson_dwmac_pm_ops, loongson_dwmac_suspend,
> > >
> > >  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);
> >
> > > @@ -266,4 +663,5 @@ module_pci_driver(loongson_dwmac_driver);
> > >
> > >  MODULE_DESCRIPTION("Loongson DWMAC PCI driver");
> > >  MODULE_AUTHOR("Qing Zhang <zhangqing@loongson.cn>");
> > > +MODULE_AUTHOR("Yanteng Si <siyanteng@loongson.cn>");
> > >  MODULE_LICENSE("GPL v2");
> >
> > Please move this into a separate patch. It can be the last patch in
> > the series.
> >
> > > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> > > index f161ec9ac490..66c0c22908b1 100644
> > > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> > > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
> > > @@ -296,3 +296,4 @@ const struct stmmac_dma_ops dwmac1000_dma_ops = {
> > >       .get_hw_feature = dwmac1000_get_hw_feature,
> > >       .rx_watchdog = dwmac1000_rx_watchdog,
> > >  };
> > > +EXPORT_SYMBOL_GPL(dwmac1000_dma_ops);
> >
> >
> > Please move this into a preparation/pre-requisite patch.
> >
> >
> > > diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> > > index e1537a57815f..e94faa72f30e 100644
> > > --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> > > +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> > > @@ -420,6 +420,12 @@ stmmac_ethtool_set_link_ksettings(struct net_device *dev,
> > >               return 0;
> > >       }
> > >
> > > +     if (priv->plat->flags & STMMAC_FLAG_DISABLE_FORCE_1000) {
> > > +             if (cmd->base.speed == SPEED_1000 &&
> > > +                 cmd->base.autoneg != AUTONEG_ENABLE)
> > > +                     return -EOPNOTSUPP;
> > > +     }
> > > +
> > >       return phylink_ethtool_ksettings_set(priv->phylink, cmd);
> > >  }
> > >
> > > diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
> > > index 1b54b84a6785..c5d3d0ddb6f8 100644
> > > --- a/include/linux/stmmac.h
> > > +++ b/include/linux/stmmac.h
> > > @@ -223,6 +223,7 @@ struct dwmac4_addrs {
> > >  #define STMMAC_FLAG_RX_CLK_RUNS_IN_LPI               BIT(10)
> > >  #define STMMAC_FLAG_EN_TX_LPI_CLOCKGATING    BIT(11)
> > >  #define STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY BIT(12)
> > > +#define STMMAC_FLAG_DISABLE_FORCE_1000               BIT(13)
> > >
> > >  struct plat_stmmacenet_data {
> > >       int bus_id;
> >
> > Please move this in a separate _pre-requisite/preparation_ patch.
> > Really. Why have you merged it into this one? This patch already got
> > to be too complicated. Don't make it even more complex.
> >
> > ---
> >
> > I look at v8 and look at v9 series. Why have you re-shuffled the
> > change so significantly??? It has made my life in reviewing your bits
> > much harder because instead of checking whether you took my v8-notes
> > into account I had to once again analyze the entire series. Sigh...
> >
> > -Serge(y)
> >
> > > --
> > > 2.31.4
> > >
> 

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

* Re: [PATCH net-next v11 6/6] net: stmmac: dwmac-loongson: Add Loongson GNET support
  2024-04-24 14:11     ` Huacai Chen
  2024-04-24 14:46       ` Russell King (Oracle)
@ 2024-04-25  8:07       ` Yanteng Si
  1 sibling, 0 replies; 36+ messages in thread
From: Yanteng Si @ 2024-04-25  8:07 UTC (permalink / raw)
  To: Huacai Chen, Serge Semin
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	Jose.Abreu, linux, guyinggang, netdev, chris.chenfeiyang,
	siyanteng01

Hi Serge and Russell,

在 2024/4/24 22:11, Huacai Chen 写道:
>> Once again. Please replace this with simpler solution:
> In full PCI system the below function works fine, because alloc irq
> vectors with PCI_IRQ_LEGACY do the same thing as fallback to call
> loongson_dwmac_config_legacy(). But for a DT-based system it doesn't
> work.
huacai's comments are here.
>
>
>> static int loongson_dwmac_config_multi_msi(struct pci_dev *pdev,
>> +                                          struct plat_stmmacenet_data *plat,
>> +                                          struct stmmac_resources *res)
>> +{
>> +       int i, ret, vecs;
>> +
>> +       /* INT NAME | MAC | CH7 rx | CH7 tx | ... | CH0 rx | CH0 tx |
>> +        * --------- ----- -------- --------  ...  -------- --------
>> +        * IRQ NUM  |  0  |   1    |   2    | ... |   15   |   16   |
>> +        */
>> +       vecs = plat->rx_queues_to_use + plat->tx_queues_to_use + 1;
>> +       ret = pci_alloc_irq_vectors(pdev, 1, vecs, PCI_IRQ_MSI | PCI_IRQ_LEGACY);
>> +       if (ret < 0) {
>> +               dev_err(&pdev->dev, "Failed to allocate PCI IRQs\n");
>> +               return ret;
>> +       } else if (ret >= vecs) {
>> +               for (i = 0; i < plat->rx_queues_to_use; i++) {
>> +                       res->rx_irq[CHANNELS_NUM - 1 - i] =
>> +                               pci_irq_vector(pdev, 1 + i * 2);
>> +               }
>> +               for (i = 0; i < plat->tx_queues_to_use; i++) {
>> +                       res->tx_irq[CHANNELS_NUM - 1 - i] =
>> +                               pci_irq_vector(pdev, 2 + i * 2);
>> +               }
>> +
>> +               plat->flags |= STMMAC_FLAG_MULTI_MSI_EN;
>> +       }
>> +
>> +       res->irq = pci_irq_vector(pdev, 0);
>> +
>> +       return 0;
>> +}

How about we stay the same in v12?


Thanks,

Yanteng



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

* Re: [PATCH net-next v11 6/6] net: stmmac: dwmac-loongson: Add Loongson GNET support
  2024-04-24 13:37   ` Huacai Chen
@ 2024-04-25  8:09     ` Yanteng Si
  0 siblings, 0 replies; 36+ messages in thread
From: Yanteng Si @ 2024-04-25  8:09 UTC (permalink / raw)
  To: Huacai Chen
  Cc: andrew, hkallweit1, peppe.cavallaro, alexandre.torgue, joabreu,
	fancer.lancer, Jose.Abreu, linux, guyinggang, netdev,
	chris.chenfeiyang, siyanteng01


在 2024/4/24 21:37, Huacai Chen 写道:
>> +static struct mac_device_info *loongson_dwmac_setup(void *apriv)
>> +{
>> +       struct stmmac_priv *priv = apriv;
>> +       struct stmmac_resources res;
>> +       struct mac_device_info *mac;
>> +       struct stmmac_dma_ops *dma;
>> +       struct pci_dev *pdev;
>> +       u32 loongson_gmac;
>> +
>> +       memset(&res, 0, sizeof(res));
>> +       pdev = to_pci_dev(priv->device);
>> +       res.addr = pcim_iomap_table(pdev)[0];
>> +       loongson_gmac = readl(res.addr + GMAC_VERSION) & 0xff;
> We can add a "gmac_version" in loongson_data, then we only need to
> read it once in the probe function.

Okay!


Thanks,

Yanteng


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

end of thread, other threads:[~2024-04-25  8:09 UTC | newest]

Thread overview: 36+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-04-12 11:28 [PATCH net-next v11 0/6] stmmac: Add Loongson platform support Yanteng Si
2024-04-12 11:28 ` [PATCH net-next v11 1/6] net: stmmac: Move all PHYLINK MAC capabilities initializations to MAC-specific setup methods Yanteng Si
2024-04-12 18:32   ` Serge Semin
2024-04-18  5:02     ` Yanteng Si
2024-04-18  9:53       ` Serge Semin
2024-04-19  7:01         ` Yanteng Si
2024-04-12 11:28 ` [PATCH net-next v11 2/6] net: stmmac: Add multi-channel support Yanteng Si
2024-04-18 11:02   ` Serge Semin
2024-04-19  9:02     ` Yanteng Si
2024-04-19  9:17       ` Serge Semin
2024-04-19  9:51         ` Yanteng Si
2024-04-12 11:28 ` [PATCH net-next v11 3/6] net: stmmac: dwmac-loongson: Use PCI_DEVICE_DATA() macro for device identification Yanteng Si
2024-04-13  1:49   ` Jakub Kicinski
2024-04-15  2:21     ` Yanteng Si
2024-04-18 11:14       ` Serge Semin
2024-04-18 12:31         ` Serge Semin
2024-04-19  9:40           ` Yanteng Si
2024-04-12 11:28 ` [PATCH net-next v11 4/6] net: stmmac: dwmac-loongson: Introduce GMAC setup Yanteng Si
2024-04-18 12:26   ` Serge Semin
2024-04-19 10:06     ` Yanteng Si
2024-04-22 10:17   ` Yanteng Si
2024-04-12 11:28 ` [PATCH net-next v11 5/6] net: stmmac: dwmac-loongson: Add full PCI support Yanteng Si
2024-04-18 13:08   ` Serge Semin
2024-04-20  2:41     ` Yanteng Si
2024-04-12 11:28 ` [PATCH net-next v11 6/6] net: stmmac: dwmac-loongson: Add Loongson GNET support Yanteng Si
2024-04-18 14:01   ` Serge Semin
2024-04-20 11:02     ` Yanteng Si
2024-04-21  5:35       ` Yanteng Si
2024-04-23 13:16     ` Yanteng Si
2024-04-24 14:11     ` Huacai Chen
2024-04-24 14:46       ` Russell King (Oracle)
2024-04-25  8:07       ` Yanteng Si
2024-04-24 13:37   ` Huacai Chen
2024-04-25  8:09     ` Yanteng Si
2024-04-12 18:34 ` [PATCH net-next v11 0/6] stmmac: Add Loongson platform support Serge Semin
2024-04-18  5:16   ` Yanteng Si

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