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>
175 lines
6.1 KiB
Diff
175 lines
6.1 KiB
Diff
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++) {
|