]> git.ipfire.org Git - thirdparty/openwrt.git/commitdiff
loongarch64: add upstream dwmac-loongson patches for 2K3000/3B6000M
authorxinmu <xinmu@loongfans.cn>
Thu, 14 May 2026 09:34:17 +0000 (17:34 +0800)
committerHauke Mehrtens <hauke@hauke-m.de>
Mon, 25 May 2026 22:58:05 +0000 (00:58 +0200)
Add three backported patches from Linux upstream to fix the onboard
Ethernet controller (dwmac-loongson) detection and driver issues on
Loongson 2K3000 and 3B6000M platforms.

These patches are taken from the upstream Linux kernel and retain the
original authorship and commit logs. No other modifications are made
to the loongarch64 target.

The patches address the following symptoms:
- Onboard network interface not recognized
- Driver probe failures on 2K3000/3B6000M boards

Signed-off-by: xinmu <xinmu@loongfans.cn>
Link: https://github.com/openwrt/openwrt/pull/23366
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
target/linux/loongarch64/patches-6.12/005-v6.16-LoongArch-dwmac-loongson-move-queue-number-init-to-common-function.patch [new file with mode: 0644]
target/linux/loongarch64/patches-6.12/006-v6.16-LoongArch-dwmac-loongson-add-new-multi-chan-ip-core-support.patch [new file with mode: 0644]
target/linux/loongarch64/patches-6.12/007-v6.16-LoongArch-dwmac-loongson-add-new-gmacs-pci-device-id-support.patch [new file with mode: 0644]

diff --git a/target/linux/loongarch64/patches-6.12/005-v6.16-LoongArch-dwmac-loongson-move-queue-number-init-to-common-function.patch b/target/linux/loongarch64/patches-6.12/005-v6.16-LoongArch-dwmac-loongson-move-queue-number-init-to-common-function.patch
new file mode 100644 (file)
index 0000000..7fa81bb
--- /dev/null
@@ -0,0 +1,98 @@
+From: Huacai Chen <chenhuacai@loongson.cn>
+Date: Thu, 24 Apr 2025 15:22:07 +0800
+Subject: [PATCH] net: stmmac: dwmac-loongson: Move queue number init to common
+ function
+
+Currently, the tx and rx queue number initialization is duplicated in
+loongson_gmac_data() and loongson_gnet_data(), so move it to the common
+function loongson_default_data().
+
+This is a preparation for later patches.
+
+Reviewed-by: Yanteng Si <si.yanteng@linux.dev>
+Tested-by: Henry Chen <chenx97@aosc.io>
+Tested-by: Biao Dong <dongbiao@loongson.cn>
+Signed-off-by: Baoqi Zhang <zhangbaoqi@loongson.cn>
+Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 40 +++++--------------
+ 1 file changed, 9 insertions(+), 31 deletions(-)
+
+--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
+@@ -83,6 +83,8 @@ struct stmmac_pci_info {
+ static void loongson_default_data(struct pci_dev *pdev,
+                                 struct plat_stmmacenet_data *plat)
+ {
++      struct loongson_data *ld = plat->bsp_priv;
++
+       /* Get bus_id, this can be overwritten later */
+       plat->bus_id = pci_dev_id(pdev);
+@@ -116,17 +118,6 @@ static void loongson_default_data(struct
+       plat->dma_cfg->pbl = 32;
+       plat->dma_cfg->pblx8 = true;
+-}
+-
+-static int loongson_gmac_data(struct pci_dev *pdev,
+-                            struct plat_stmmacenet_data *plat)
+-{
+-      struct loongson_data *ld;
+-      int i;
+-
+-      ld = plat->bsp_priv;
+-
+-      loongson_default_data(pdev, plat);
+       if (ld->loongson_id == DWMAC_CORE_LS_MULTICHAN) {
+               plat->rx_queues_to_use = CHANNEL_NUM;
+@@ -135,12 +126,18 @@ static int loongson_gmac_data(struct pci
+               /* Only channel 0 supports checksum,
+                * so turn off checksum to enable multiple channels.
+                */
+-              for (i = 1; i < CHANNEL_NUM; i++)
++              for (int i = 1; i < CHANNEL_NUM; i++)
+                       plat->tx_queues_cfg[i].coe_unsupported = 1;
+       } else {
+               plat->tx_queues_to_use = 1;
+               plat->rx_queues_to_use = 1;
+       }
++}
++
++static int loongson_gmac_data(struct pci_dev *pdev,
++                            struct plat_stmmacenet_data *plat)
++{
++      loongson_default_data(pdev, plat);
+       plat->phy_interface = PHY_INTERFACE_MODE_RGMII_ID;
+@@ -173,27 +170,8 @@ static void loongson_gnet_fix_speed(void
+ static int loongson_gnet_data(struct pci_dev *pdev,
+                             struct plat_stmmacenet_data *plat)
+ {
+-      struct loongson_data *ld;
+-      int i;
+-
+-      ld = plat->bsp_priv;
+-
+       loongson_default_data(pdev, plat);
+-      if (ld->loongson_id == DWMAC_CORE_LS_MULTICHAN) {
+-              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;
+-      } else {
+-              plat->tx_queues_to_use = 1;
+-              plat->rx_queues_to_use = 1;
+-      }
+-
+       plat->phy_interface = PHY_INTERFACE_MODE_GMII;
+       plat->mdio_bus_data->phy_mask = ~(u32)BIT(2);
+       plat->fix_mac_speed = loongson_gnet_fix_speed;
diff --git a/target/linux/loongarch64/patches-6.12/006-v6.16-LoongArch-dwmac-loongson-add-new-multi-chan-ip-core-support.patch b/target/linux/loongarch64/patches-6.12/006-v6.16-LoongArch-dwmac-loongson-add-new-multi-chan-ip-core-support.patch
new file mode 100644 (file)
index 0000000..e346f33
--- /dev/null
@@ -0,0 +1,174 @@
+From: Huacai Chen <chenhuacai@loongson.cn>
+Date: Thu, 24 Apr 2025 15:22:08 +0800
+Subject: [PATCH] net: stmmac: dwmac-loongson: Add new multi-chan IP core
+ support
+
+Add a new multi-chan IP core (0x12) support which is used in Loongson-
+2K3000/Loongson-3B6000M. Compared with the 0x10 core, the new 0x12 core
+reduces channel numbers from 8 to 4, but checksum is supported for all
+channels.
+
+Add a "multichan" flag to loongson_data, so that we can simply use a
+"if (ld->multichan)" condition rather than the complicated condition
+"if (ld->loongson_id == DWMAC_CORE_MULTICHAN_V1 || ld->loongson_id ==
+DWMAC_CORE_MULTICHAN_V2)".
+
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Tested-by: Henry Chen <chenx97@aosc.io>
+Tested-by: Biao Dong <dongbiao@loongson.cn>
+Signed-off-by: Baoqi Zhang <zhangbaoqi@loongson.cn>
+Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
+Reviewed-by: Yanteng Si <si.yanteng@linux.dev>
+Link: https://patch.msgid.link/20250424072209.3134762-3-chenhuacai@loongson.cn
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 62 +++++++++++--------
+ 1 file changed, 37 insertions(+), 25 deletions(-)
+
+--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
+@@ -68,10 +68,11 @@
+ #define PCI_DEVICE_ID_LOONGSON_GMAC   0x7a03
+ #define PCI_DEVICE_ID_LOONGSON_GNET   0x7a13
+-#define DWMAC_CORE_LS_MULTICHAN       0x10    /* Loongson custom ID */
+-#define CHANNEL_NUM                   8
++#define DWMAC_CORE_MULTICHAN_V1       0x10    /* Loongson custom ID 0x10 */
++#define DWMAC_CORE_MULTICHAN_V2       0x12    /* Loongson custom ID 0x12 */
+ struct loongson_data {
++      u32 multichan;
+       u32 loongson_id;
+       struct device *dev;
+ };
+@@ -119,18 +120,29 @@ static void loongson_default_data(struct
+       plat->dma_cfg->pbl = 32;
+       plat->dma_cfg->pblx8 = true;
+-      if (ld->loongson_id == DWMAC_CORE_LS_MULTICHAN) {
+-              plat->rx_queues_to_use = CHANNEL_NUM;
+-              plat->tx_queues_to_use = CHANNEL_NUM;
++      switch (ld->loongson_id) {
++      case DWMAC_CORE_MULTICHAN_V1:
++              ld->multichan = 1;
++              plat->rx_queues_to_use = 8;
++              plat->tx_queues_to_use = 8;
+               /* Only channel 0 supports checksum,
+                * so turn off checksum to enable multiple channels.
+                */
+-              for (int i = 1; i < CHANNEL_NUM; i++)
++              for (int i = 1; i < 8; i++)
+                       plat->tx_queues_cfg[i].coe_unsupported = 1;
+-      } else {
++
++              break;
++      case DWMAC_CORE_MULTICHAN_V2:
++              ld->multichan = 1;
++              plat->rx_queues_to_use = 4;
++              plat->tx_queues_to_use = 4;
++              break;
++      default:
++              ld->multichan = 0;
+               plat->tx_queues_to_use = 1;
+               plat->rx_queues_to_use = 1;
++              break;
+       }
+ }
+@@ -329,14 +341,14 @@ static struct mac_device_info *loongson_
+               return NULL;
+       /* The Loongson GMAC and GNET devices are based on the DW GMAC
+-       * v3.50a and v3.73a IP-cores. But the HW designers have changed the
+-       * GMAC_VERSION.SNPSVER field to the custom 0x10 value on the
+-       * network controllers with the multi-channels feature
++       * v3.50a and v3.73a IP-cores. But the HW designers have changed
++       * the GMAC_VERSION.SNPSVER field to the custom 0x10/0x12 value
++       * on the network controllers with the multi-channels feature
+        * available 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 (ld->loongson_id == DWMAC_CORE_LS_MULTICHAN) {
++      if (ld->multichan) {
+               priv->synopsys_id = DWMAC_CORE_3_70;
+               *dma = dwmac1000_dma_ops;
+               dma->init_chan = loongson_dwmac_dma_init_channel;
+@@ -357,13 +369,13 @@ static struct mac_device_info *loongson_
+       if (mac->multicast_filter_bins)
+               mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins);
+-      /* Loongson GMAC doesn't support the flow control. LS2K2000
+-       * GNET doesn't support the half-duplex link mode.
++      /* Loongson GMAC doesn't support the flow control. Loongson GNET
++       * without multi-channel doesn't support the half-duplex link mode.
+        */
+       if (pdev->device == PCI_DEVICE_ID_LOONGSON_GMAC) {
+               mac->link.caps = MAC_10 | MAC_100 | MAC_1000;
+       } else {
+-              if (ld->loongson_id == DWMAC_CORE_LS_MULTICHAN)
++              if (ld->multichan)
+                       mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
+                                        MAC_10 | MAC_100 | MAC_1000;
+               else
+@@ -392,9 +404,11 @@ static int loongson_dwmac_msi_config(str
+                                    struct plat_stmmacenet_data *plat,
+                                    struct stmmac_resources *res)
+ {
+-      int i, ret, vecs;
++      int i, ch_num, ret, vecs;
++
++      ch_num = min(plat->tx_queues_to_use, plat->rx_queues_to_use);
+-      vecs = roundup_pow_of_two(CHANNEL_NUM * 2 + 1);
++      vecs = roundup_pow_of_two(ch_num * 2 + 1);
+       ret = pci_alloc_irq_vectors(pdev, vecs, vecs, PCI_IRQ_MSI);
+       if (ret < 0) {
+               dev_warn(&pdev->dev, "Failed to allocate MSI IRQs\n");
+@@ -403,14 +417,12 @@ static int loongson_dwmac_msi_config(str
+       res->irq = pci_irq_vector(pdev, 0);
+-      for (i = 0; i < plat->rx_queues_to_use; i++) {
+-              res->rx_irq[CHANNEL_NUM - 1 - i] =
+-                      pci_irq_vector(pdev, 1 + i * 2);
++      for (i = 0; i < ch_num; i++) {
++              res->rx_irq[ch_num - 1 - i] = pci_irq_vector(pdev, 1 + i * 2);
+       }
+-      for (i = 0; i < plat->tx_queues_to_use; i++) {
+-              res->tx_irq[CHANNEL_NUM - 1 - i] =
+-                      pci_irq_vector(pdev, 2 + i * 2);
++      for (i = 0; i < ch_num; i++) {
++              res->tx_irq[ch_num - 1 - i] = pci_irq_vector(pdev, 2 + i * 2);
+       }
+       plat->flags |= STMMAC_FLAG_MULTI_MSI_EN;
+@@ -572,7 +584,7 @@ static int loongson_dwmac_probe(struct p
+               goto err_disable_device;
+       /* Use the common MAC IRQ if per-channel MSIs allocation failed */
+-      if (ld->loongson_id == DWMAC_CORE_LS_MULTICHAN)
++      if (ld->multichan)
+               loongson_dwmac_msi_config(pdev, plat, &res);
+       ret = stmmac_dvr_probe(&pdev->dev, plat, &res);
+@@ -584,7 +596,7 @@ static int loongson_dwmac_probe(struct p
+ err_plat_clear:
+       if (dev_of_node(&pdev->dev))
+               loongson_dwmac_dt_clear(pdev, plat);
+-      if (ld->loongson_id == DWMAC_CORE_LS_MULTICHAN)
++      if (ld->multichan)
+               loongson_dwmac_msi_clear(pdev);
+ err_disable_device:
+       pci_disable_device(pdev);
+@@ -604,7 +616,7 @@ static void loongson_dwmac_remove(struct
+       if (dev_of_node(&pdev->dev))
+               loongson_dwmac_dt_clear(pdev, priv->plat);
+-      if (ld->loongson_id == DWMAC_CORE_LS_MULTICHAN)
++      if (ld->multichan)
+               loongson_dwmac_msi_clear(pdev);
+       for (i = 0; i < PCI_STD_NUM_BARS; i++) {
diff --git a/target/linux/loongarch64/patches-6.12/007-v6.16-LoongArch-dwmac-loongson-add-new-gmacs-pci-device-id-support.patch b/target/linux/loongarch64/patches-6.12/007-v6.16-LoongArch-dwmac-loongson-add-new-gmacs-pci-device-id-support.patch
new file mode 100644 (file)
index 0000000..a015216
--- /dev/null
@@ -0,0 +1,53 @@
+From: Huacai Chen <chenhuacai@loongson.cn>
+Date: Thu, 24 Apr 2025 15:22:09 +0800
+Subject: [PATCH] net: stmmac: dwmac-loongson: Add new GMAC's PCI device ID
+ support
+
+Add a new GMAC's PCI device ID (0x7a23) support which is used in
+Loongson-2K3000/Loongson-3B6000M. The new GMAC device use external PHY,
+so it reuses loongson_gmac_data() as the old GMAC device (0x7a03), and
+the new GMAC device still doesn't support flow control now.
+
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Reviewed-by: Yanteng Si <si.yanteng@linux.dev>
+Tested-by: Henry Chen <chenx97@aosc.io>
+Tested-by: Biao Dong <dongbiao@loongson.cn>
+Signed-off-by: Baoqi Zhang <zhangbaoqi@loongson.cn>
+Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
+Link: https://patch.msgid.link/20250424072209.3134762-4-chenhuacai@loongson.cn
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
+@@ -66,7 +66,8 @@
+                                        DMA_STATUS_TPS | DMA_STATUS_TI  | \
+                                        DMA_STATUS_MSK_COMMON_LOONGSON)
+-#define PCI_DEVICE_ID_LOONGSON_GMAC   0x7a03
++#define PCI_DEVICE_ID_LOONGSON_GMAC1  0x7a03
++#define PCI_DEVICE_ID_LOONGSON_GMAC2  0x7a23
+ #define PCI_DEVICE_ID_LOONGSON_GNET   0x7a13
+ #define DWMAC_CORE_MULTICHAN_V1       0x10    /* Loongson custom ID 0x10 */
+ #define DWMAC_CORE_MULTICHAN_V2       0x12    /* Loongson custom ID 0x12 */
+@@ -372,7 +373,7 @@ static struct mac_device_info *loongson_
+       /* Loongson GMAC doesn't support the flow control. Loongson GNET
+        * without multi-channel doesn't support the half-duplex link mode.
+        */
+-      if (pdev->device == PCI_DEVICE_ID_LOONGSON_GMAC) {
++      if (pdev->device != PCI_DEVICE_ID_LOONGSON_GNET) {
+               mac->link.caps = MAC_10 | MAC_100 | MAC_1000;
+       } else {
+               if (ld->multichan)
+@@ -668,7 +669,8 @@ static SIMPLE_DEV_PM_OPS(loongson_dwmac_
+                        loongson_dwmac_resume);
+ static const struct pci_device_id loongson_dwmac_id_table[] = {
+-      { PCI_DEVICE_DATA(LOONGSON, GMAC, &loongson_gmac_pci_info) },
++      { PCI_DEVICE_DATA(LOONGSON, GMAC1, &loongson_gmac_pci_info) },
++      { PCI_DEVICE_DATA(LOONGSON, GMAC2, &loongson_gmac_pci_info) },
+       { PCI_DEVICE_DATA(LOONGSON, GNET, &loongson_gnet_pci_info) },
+       {}
+ };