Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'support-multi-channel-irqs-in-stmmac-platform-drivers'

Jan Petrous says:

====================
Support multi-channel IRQs in stmmac platform drivers

The stmmac core supports two interrupt modes, controlled by the
flag STMMAC_FLAG_MULTI_MSI_EN:

- When the flag is set, the driver uses multi-channel IRQ mode (Multi-IRQ).
- Otherwise, a single IRQ line is requested (aka MAC-IRQ):

static int stmmac_request_irq(struct net_device *dev)
{
/* Request the IRQ lines */
if (priv->plat->flags & STMMAC_FLAG_MULTI_MSI_EN)
ret = stmmac_request_irq_multi_msi(dev);
else
ret = stmmac_request_irq_single(dev);
}

At present, only PCI drivers (Intel and Loongson) make use of the Multi-IRQ
mode. This concept can be extended to DT-based embedded glue drivers
(dwmac-xxx.c).

This series adds support for reading per-channel IRQs from the DT node
and reuses the existing STMMAC_FLAG_MULTI_MSI_EN flag to enable multi-IRQ
operation in platform drivers.

The final decision if Multi-IRQ gets enabled remains on glue driver
to allow implementing any reguirements/limitions the focused platform
needs.

NXP S32G2/S32G3/S32R SoCs integrate the DWMAC IP with multi-channel
interrupt support. The dwmac-s32.c driver change is provided as an example of
enabling multi-IRQ mode for non-PCI drivers.
====================

Link: https://patch.msgid.link/20260313-dwmac_multi_irq-v12-0-b5c9d0aa13d6@oss.nxp.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+133 -7
+42 -5
Documentation/devicetree/bindings/net/nxp,s32-dwmac.yaml
··· 1 1 # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 - # Copyright 2021-2024 NXP 2 + # Copyright 2021-2026 NXP 3 3 %YAML 1.2 4 4 --- 5 5 $id: http://devicetree.org/schemas/net/nxp,s32-dwmac.yaml# ··· 16 16 the SoC S32R45 has two instances. The devices can use RGMII/RMII/MII 17 17 interface over Pinctrl device or the output can be routed 18 18 to the embedded SerDes for SGMII connectivity. 19 + The DWMAC instances have connected all RX/TX queues interrupts, 20 + enabling load balancing of data traffic across all CPU cores. 19 21 20 22 properties: 21 23 compatible: ··· 47 45 FlexTimer Modules connect to GMAC_0. 48 46 49 47 interrupts: 50 - maxItems: 1 48 + minItems: 1 49 + maxItems: 11 51 50 52 51 interrupt-names: 53 - const: macirq 52 + oneOf: 53 + - items: 54 + - const: macirq 55 + - items: 56 + - const: macirq 57 + - const: tx-queue-0 58 + - const: rx-queue-0 59 + - const: tx-queue-1 60 + - const: rx-queue-1 61 + - const: tx-queue-2 62 + - const: rx-queue-2 63 + - const: tx-queue-3 64 + - const: rx-queue-3 65 + - const: tx-queue-4 66 + - const: rx-queue-4 54 67 55 68 clocks: 56 69 items: ··· 105 88 <0x0 0x4007c004 0x0 0x4>; /* GMAC_0_CTRL_STS */ 106 89 nxp,phy-sel = <&gpr 0x4>; 107 90 interrupt-parent = <&gic>; 108 - interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>; 109 - interrupt-names = "macirq"; 91 + interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>, 92 + /* CHN 0: tx, rx */ 93 + <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>, 94 + <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>, 95 + /* CHN 1: tx, rx */ 96 + <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>, 97 + <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>, 98 + /* CHN 2: tx, rx */ 99 + <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>, 100 + <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>, 101 + /* CHN 3: tx, rx */ 102 + <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>, 103 + <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>, 104 + /* CHN 4: tx, rx */ 105 + <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>, 106 + <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>; 107 + interrupt-names = "macirq", 108 + "tx-queue-0", "rx-queue-0", 109 + "tx-queue-1", "rx-queue-1", 110 + "tx-queue-2", "rx-queue-2", 111 + "tx-queue-3", "rx-queue-3", 112 + "tx-queue-4", "rx-queue-4"; 110 113 snps,mtl-rx-config = <&mtl_rx_setup>; 111 114 snps,mtl-tx-config = <&mtl_tx_setup>; 112 115 clocks = <&clks 24>, <&clks 17>, <&clks 16>, <&clks 15>;
+35 -1
drivers/net/ethernet/stmicro/stmmac/dwmac-s32.c
··· 2 2 /* 3 3 * NXP S32G/R GMAC glue layer 4 4 * 5 - * Copyright 2019-2024 NXP 5 + * Copyright 2019-2026 NXP 6 6 * 7 7 */ 8 8 ··· 110 110 clk_disable_unprepare(gmac->rx_clk); 111 111 } 112 112 113 + static void s32_gmac_setup_multi_irq(struct device *dev, 114 + struct plat_stmmacenet_data *plat, 115 + struct stmmac_resources *res) 116 + { 117 + int i; 118 + 119 + /* RX IRQs */ 120 + for (i = 0; i < plat->rx_queues_to_use; i++) { 121 + if (res->rx_irq[i] <= 0) { 122 + dev_dbg(dev, "Missing RX queue %d interrupt\n", i); 123 + goto mac_irq_mode; 124 + } 125 + } 126 + 127 + /* TX IRQs */ 128 + for (i = 0; i < plat->tx_queues_to_use; i++) { 129 + if (res->tx_irq[i] <= 0) { 130 + dev_dbg(dev, "Missing TX queue %d interrupt\n", i); 131 + goto mac_irq_mode; 132 + } 133 + } 134 + 135 + plat->flags |= STMMAC_FLAG_MULTI_MSI_EN; 136 + dev_info(dev, "Multi-IRQ mode (per queue IRQs) selected\n"); 137 + return; 138 + 139 + mac_irq_mode: 140 + plat->flags &= ~STMMAC_FLAG_MULTI_MSI_EN; 141 + dev_info(dev, "MAC IRQ mode selected\n"); 142 + } 143 + 113 144 static int s32_dwmac_probe(struct platform_device *pdev) 114 145 { 115 146 struct plat_stmmacenet_data *plat; ··· 196 165 plat->core_type = DWMAC_CORE_GMAC4; 197 166 plat->pmt = true; 198 167 plat->flags |= STMMAC_FLAG_SPH_DISABLE; 168 + 169 + s32_gmac_setup_multi_irq(dev, plat, &res); 170 + 199 171 plat->rx_fifo_size = 20480; 200 172 plat->tx_fifo_size = 20480; 201 173
+56 -1
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
··· 695 695 } 696 696 EXPORT_SYMBOL_GPL(stmmac_pltfr_find_clk); 697 697 698 + /** 699 + * stmmac_pltfr_get_irq_array - Read per-channel IRQs from platform device 700 + * @pdev: platform device 701 + * @fmt: IRQ name format string (e.g., "tx-queue-%d") 702 + * @irqs: array to store IRQ numbers 703 + * @num: maximum number of IRQs to read 704 + * 705 + * Return: 0 on success, -EPROBE_DEFER if IRQ is deferred, -EINVAL on error. 706 + * Missing IRQs are set to 0 and iteration stops at first missing IRQ. 707 + */ 708 + static int stmmac_pltfr_get_irq_array(struct platform_device *pdev, 709 + const char *fmt, int *irqs, size_t num) 710 + { 711 + char name[16]; 712 + int i; 713 + 714 + for (i = 0; i < num; i++) { 715 + if (snprintf(name, sizeof(name), fmt, i) >= sizeof(name)) 716 + return -EINVAL; 717 + 718 + irqs[i] = platform_get_irq_byname_optional(pdev, name); 719 + if (irqs[i] == -EPROBE_DEFER) 720 + return -EPROBE_DEFER; 721 + 722 + if (irqs[i] <= 0) { 723 + dev_dbg(&pdev->dev, "IRQ %s not found\n", name); 724 + 725 + /* Stop silently on first unset irq */ 726 + irqs[i] = 0; 727 + break; 728 + } 729 + } 730 + 731 + return 0; 732 + } 733 + 698 734 int stmmac_get_platform_resources(struct platform_device *pdev, 699 735 struct stmmac_resources *stmmac_res) 700 736 { 737 + int ret; 738 + 701 739 memset(stmmac_res, 0, sizeof(*stmmac_res)); 702 740 703 741 /* Get IRQ information early to have an ability to ask for deferred ··· 771 733 772 734 stmmac_res->addr = devm_platform_ioremap_resource(pdev, 0); 773 735 774 - return PTR_ERR_OR_ZERO(stmmac_res->addr); 736 + if (IS_ERR(stmmac_res->addr)) 737 + return PTR_ERR(stmmac_res->addr); 738 + 739 + /* TX channels irq */ 740 + ret = stmmac_pltfr_get_irq_array(pdev, "tx-queue-%d", 741 + stmmac_res->tx_irq, 742 + MTL_MAX_TX_QUEUES); 743 + if (ret) 744 + return ret; 745 + 746 + /* RX channels irq */ 747 + ret = stmmac_pltfr_get_irq_array(pdev, "rx-queue-%d", 748 + stmmac_res->rx_irq, 749 + MTL_MAX_RX_QUEUES); 750 + if (ret) 751 + return ret; 752 + 753 + return 0; 775 754 } 776 755 EXPORT_SYMBOL_GPL(stmmac_get_platform_resources); 777 756