[PATCH v2 09/10] net: stmmac: dwmac-loongson: Add 64-bit DMA and multi-vector support
From: Feiyang Chen <hidden>
Date: 2023-07-27 07:18:59
Also in:
loongarch
Subsystem:
networking drivers, stmmac ethernet driver, the rest · Maintainers:
Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds
Set 64-Bit DMA for specific versions. Request allocation for multi- vector interrupts for DWLGMAC_CORE_1_00. If it fails, fallback to request allocation for single interrupts. Signed-off-by: Feiyang Chen <redacted> --- .../ethernet/stmicro/stmmac/dwmac-loongson.c | 54 ++++++++++++++++++- 1 file changed, 52 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
index 439a5f8bcabe..2d6567f0da23 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c@@ -73,11 +73,12 @@ static struct stmmac_pci_info loongson_gmac_pci_info = { static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id *id) { - int ret, i, bus_id, phy_mode; + int ret, i, bus_id, phy_mode, ch_cnt, vecs; struct plat_stmmacenet_data *plat; struct stmmac_pci_info *info; struct stmmac_resources res; struct device_node *np; + u32 version; plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL); if (!plat)
@@ -167,12 +168,60 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, res.wol_irq = pdev->irq; } + version = readl(res.addr + GMAC_VERSION); + switch (version & 0xff) { + case DWLGMAC_CORE_1_00: + ch_cnt = 8; + plat->multi_msi_en = 1; + break; + case DWMAC_CORE_3_50: + fallthrough; + case DWMAC_CORE_3_70: + plat->multi_msi_en = 0; + if (version & 0x00008000) { + plat->host_dma_width = 64; + plat->dma_cfg->dma64 = true; + } + break; + default: + break; + } + + if (plat->multi_msi_en) { + plat->rx_queues_to_use = ch_cnt; + plat->tx_queues_to_use = ch_cnt; + + pci_disable_msi(pdev); + + res.irq = pci_irq_vector(pdev, 0); + res.wol_irq = res.irq; + vecs = roundup_pow_of_two(ch_cnt * 2 + 1); + if (pci_alloc_irq_vectors(pdev, vecs, vecs, PCI_IRQ_MSI) < 0) { + dev_info(&pdev->dev, + "MSI enable failed, Fallback to line interrupt\n"); + plat->multi_msi_en = 0; + } else { + /* + * INT NAME | MAC | CH7 rx | CH7 tx | ... | CH0 rx | CH0 tx | + * --------- ----- -------- -------- ... -------- -------- + * IRQ NUM | 0 | 1 | 2 | ... | 15 | 16 | + */ + for (i = 0; i < ch_cnt; i++) { + res.rx_irq[ch_cnt - 1 - i] = pci_irq_vector(pdev, 1 + i * 2); + res.tx_irq[ch_cnt - 1 - i] = pci_irq_vector(pdev, 2 + i * 2); + } + } + } + ret = stmmac_dvr_probe(&pdev->dev, plat, &res); if (ret) - goto err_disable_msi; + goto err_free_irq_vectors; return ret; +err_free_irq_vectors: + if (plat->multi_msi_en) + pci_free_irq_vectors(pdev); err_disable_msi: pci_disable_msi(pdev); err_disable_device:
@@ -198,6 +247,7 @@ static void loongson_dwmac_remove(struct pci_dev *pdev) break; } + pci_free_irq_vectors(pdev); pci_disable_msi(pdev); pci_disable_device(pdev); }
--
2.39.3