]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
net: stmmac: add stmmac_mac_irq_modify()
authorRussell King (Oracle) <rmk+kernel@armlinux.org.uk>
Thu, 23 Oct 2025 09:46:20 +0000 (10:46 +0100)
committerJakub Kicinski <kuba@kernel.org>
Sat, 25 Oct 2025 01:56:34 +0000 (18:56 -0700)
Add a function to allow interrupts to be enabled and disabled in a
core independent manner.

Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
Link: https://patch.msgid.link/E1vBrtk-0000000BMYm-3CV5@rmk-PC.armlinux.org.uk
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/stmicro/stmmac/common.h
drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
drivers/net/ethernet/stmicro/stmmac/hwif.c
drivers/net/ethernet/stmicro/stmmac/hwif.h
drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.c

index 31254ba525d56bd70fffdeb8082e1c322d8fd9bb..553a8897b005b121f2cf595ac9143d4fb1e319cb 100644 (file)
@@ -611,6 +611,11 @@ struct mac_device_info {
        u8 vlan_fail_q;
        bool hw_vlan_en;
        bool reverse_sgmii_enable;
+
+       /* This spinlock protects read-modify-write of the interrupt
+        * mask/enable registers.
+        */
+       spinlock_t irq_ctrl_lock;
 };
 
 struct stmmac_rx_routing {
index 571e4836244420c7a19004735756e402d953144b..2ca94bfd3f718607a08edc7028d5c26c480b6c5e 100644 (file)
@@ -61,6 +61,20 @@ static void dwmac1000_core_init(struct mac_device_info *hw,
 #endif
 }
 
+static void dwmac1000_irq_modify(struct mac_device_info *hw, u32 disable,
+                                u32 enable)
+{
+       void __iomem *int_mask = hw->pcsr + GMAC_INT_MASK;
+       unsigned long flags;
+       u32 value;
+
+       spin_lock_irqsave(&hw->irq_ctrl_lock, flags);
+       value = readl(int_mask) | disable;
+       value &= ~enable;
+       writel(value, int_mask);
+       spin_unlock_irqrestore(&hw->irq_ctrl_lock, flags);
+}
+
 static int dwmac1000_rx_ipc_enable(struct mac_device_info *hw)
 {
        void __iomem *ioaddr = hw->pcsr;
@@ -445,6 +459,7 @@ static void dwmac1000_set_mac_loopback(void __iomem *ioaddr, bool enable)
 const struct stmmac_ops dwmac1000_ops = {
        .pcs_init = dwmac1000_pcs_init,
        .core_init = dwmac1000_core_init,
+       .irq_modify = dwmac1000_irq_modify,
        .set_mac = stmmac_set_mac,
        .rx_ipc = dwmac1000_rx_ipc_enable,
        .dump_regs = dwmac1000_dump_regs,
index 0b785389b7eff0dc19d796d7fcd8ee4f42f563b2..6269407d70cd22a61adef2b509b082a48d966e75 100644 (file)
@@ -57,6 +57,20 @@ static void dwmac4_core_init(struct mac_device_info *hw,
                init_waitqueue_head(&priv->tstamp_busy_wait);
 }
 
+static void dwmac4_irq_modify(struct mac_device_info *hw, u32 disable,
+                             u32 enable)
+{
+       void __iomem *int_mask = hw->pcsr + GMAC_INT_EN;
+       unsigned long flags;
+       u32 value;
+
+       spin_lock_irqsave(&hw->irq_ctrl_lock, flags);
+       value = readl(int_mask) & ~disable;
+       value |= enable;
+       writel(value, int_mask);
+       spin_unlock_irqrestore(&hw->irq_ctrl_lock, flags);
+}
+
 static void dwmac4_update_caps(struct stmmac_priv *priv)
 {
        if (priv->plat->tx_queues_to_use > 1)
@@ -885,6 +899,7 @@ static int dwmac4_config_l4_filter(struct mac_device_info *hw, u32 filter_no,
 const struct stmmac_ops dwmac4_ops = {
        .pcs_init = dwmac4_pcs_init,
        .core_init = dwmac4_core_init,
+       .irq_modify = dwmac4_irq_modify,
        .update_caps = dwmac4_update_caps,
        .set_mac = stmmac_set_mac,
        .rx_ipc = dwmac4_rx_ipc_enable,
@@ -920,6 +935,7 @@ const struct stmmac_ops dwmac4_ops = {
 const struct stmmac_ops dwmac410_ops = {
        .pcs_init = dwmac4_pcs_init,
        .core_init = dwmac4_core_init,
+       .irq_modify = dwmac4_irq_modify,
        .update_caps = dwmac4_update_caps,
        .set_mac = stmmac_dwmac4_set_mac,
        .rx_ipc = dwmac4_rx_ipc_enable,
@@ -957,6 +973,7 @@ const struct stmmac_ops dwmac410_ops = {
 const struct stmmac_ops dwmac510_ops = {
        .pcs_init = dwmac4_pcs_init,
        .core_init = dwmac4_core_init,
+       .irq_modify = dwmac4_irq_modify,
        .update_caps = dwmac4_update_caps,
        .set_mac = stmmac_dwmac4_set_mac,
        .rx_ipc = dwmac4_rx_ipc_enable,
index 0430af27da407e94a8513b58133789b6da04ff94..b40b3ea50e2536a9ee9dcd46d1b2e19c80fa025e 100644 (file)
@@ -28,6 +28,20 @@ static void dwxgmac2_core_init(struct mac_device_info *hw,
        writel(XGMAC_INT_DEFAULT_EN, ioaddr + XGMAC_INT_EN);
 }
 
+static void dwxgmac2_irq_modify(struct mac_device_info *hw, u32 disable,
+                               u32 enable)
+{
+       void __iomem *int_mask = hw->pcsr + XGMAC_INT_EN;
+       unsigned long flags;
+       u32 value;
+
+       spin_lock_irqsave(&hw->irq_ctrl_lock, flags);
+       value = readl(int_mask) & ~disable;
+       value |= enable;
+       writel(value, int_mask);
+       spin_unlock_irqrestore(&hw->irq_ctrl_lock, flags);
+}
+
 static void dwxgmac2_update_caps(struct stmmac_priv *priv)
 {
        if (!priv->dma_cap.mbps_10_100)
@@ -1411,6 +1425,7 @@ static void dwxgmac2_set_arp_offload(struct mac_device_info *hw, bool en,
 
 const struct stmmac_ops dwxgmac210_ops = {
        .core_init = dwxgmac2_core_init,
+       .irq_modify = dwxgmac2_irq_modify,
        .update_caps = dwxgmac2_update_caps,
        .set_mac = dwxgmac2_set_mac,
        .rx_ipc = dwxgmac2_rx_ipc,
@@ -1466,6 +1481,7 @@ static void dwxlgmac2_rx_queue_enable(struct mac_device_info *hw, u8 mode,
 
 const struct stmmac_ops dwxlgmac2_ops = {
        .core_init = dwxgmac2_core_init,
+       .irq_modify = dwxgmac2_irq_modify,
        .set_mac = dwxgmac2_set_mac,
        .rx_ipc = dwxgmac2_rx_ipc,
        .rx_queue_enable = dwxlgmac2_rx_queue_enable,
index 00083ce525492e1bd113385d1c0cc1f3c53fc7ec..41a7e18412276bcfde45a6f76785a51975a1dd5d 100644 (file)
@@ -333,6 +333,8 @@ int stmmac_hwif_init(struct stmmac_priv *priv)
        if (!mac)
                return -ENOMEM;
 
+       spin_lock_init(&mac->irq_ctrl_lock);
+
        /* Fallback to generic HW */
        for (i = ARRAY_SIZE(stmmac_hw) - 1; i >= 0; i--) {
                entry = &stmmac_hw[i];
index 82cfb6bec334aa0bfe48842ee00f0d70aff52db4..cb8fc09caf86b653c3167f7b1f2fe9f00990373c 100644 (file)
@@ -319,6 +319,8 @@ struct stmmac_ops {
        void (*core_init)(struct mac_device_info *hw, struct net_device *dev);
        /* Update MAC capabilities */
        void (*update_caps)(struct stmmac_priv *priv);
+       /* Change the interrupt enable setting. Enable takes precedence. */
+       void (*irq_modify)(struct mac_device_info *hw, u32 disable, u32 enable);
        /* Enable the MAC RX/TX */
        void (*set_mac)(void __iomem *ioaddr, bool enable);
        /* Enable and verify that the IPC module is supported */
@@ -421,6 +423,8 @@ struct stmmac_ops {
        stmmac_do_void_callback(__priv, mac, core_init, __args)
 #define stmmac_mac_update_caps(__priv) \
        stmmac_do_void_callback(__priv, mac, update_caps, __priv)
+#define stmmac_mac_irq_modify(__priv, __args...) \
+       stmmac_do_void_callback(__priv, mac, irq_modify, (__priv)->hw, __args)
 #define stmmac_mac_set(__priv, __args...) \
        stmmac_do_void_callback(__priv, mac, set_mac, __args)
 #define stmmac_rx_ipc(__priv, __args...) \
index 75b470ee621a39cf17eccd98b4d37ba055e9df00..c54c702243517d502c1e14641cf859b35f508681 100644 (file)
@@ -70,8 +70,10 @@ static void stmmac_fpe_configure_pmac(struct ethtool_mmsv *mmsv, bool pmac_enabl
        struct stmmac_priv *priv = container_of(cfg, struct stmmac_priv, fpe_cfg);
        const struct stmmac_fpe_reg *reg = cfg->reg;
        void __iomem *ioaddr = priv->ioaddr;
+       unsigned long flags;
        u32 value;
 
+       spin_lock_irqsave(&priv->hw->irq_ctrl_lock, flags);
        value = readl(ioaddr + reg->int_en_reg);
 
        if (pmac_enable) {
@@ -86,6 +88,7 @@ static void stmmac_fpe_configure_pmac(struct ethtool_mmsv *mmsv, bool pmac_enabl
        }
 
        writel(value, ioaddr + reg->int_en_reg);
+       spin_unlock_irqrestore(&priv->hw->irq_ctrl_lock, flags);
 }
 
 static void stmmac_fpe_send_mpacket(struct ethtool_mmsv *mmsv,