From patchwork Sun Sep 27 21:59:53 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 3531 Return-Path: X-Original-To: noreply@patchwork.local Delivered-To: noreply@patchwork.local Received: from sto.lore.kernel.org (sto.lore.kernel.org [172.232.135.74]) by mxe881.netcup.net (Postfix) with ESMTPS id 909511C308E for ; Mon, 28 Sep 2026 00:05:15 +0200 (CEST) Authentication-Results: mxe881; dkim=pass header.d=gmail.com; spf=pass (sender IP is 172.232.135.74) smtp.mailfrom=linux-sunxi+bounces-26367-noreply=patchwork.local@lists.linux.dev smtp.helo=sto.lore.kernel.org Received-SPF: pass (mxe881: domain of lists.linux.dev designates 172.232.135.74 as permitted sender) client-ip=172.232.135.74; envelope-from=linux-sunxi+bounces-26367-noreply=patchwork.local@lists.linux.dev; helo=sto.lore.kernel.org; Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org [100.90.174.1]) by sto.lore.kernel.org (Postfix) with ESMTP id 8807E6089F4 for ; Sun, 27 Sep 2026 22:02:47 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 1019C46EC98; Sun, 27 Sep 2026 22:00:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="YviFQqvX" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-oo2-f43.google.com (mail-oo2-f43.google.com [74.125.231.171]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 44B9F450410 for ; Sun, 27 Sep 2026 22:00:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.231.171 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790546444; cv=none; b=k9N2t6caqigbRHYcewcGw9Tj0FYK+x2XLh+/jAoi9E4wsv2irLhpw5rNY5RgVXJDMV6VeCgYffUwZUqoKUA2asyLW7vbajjM/eUewPAM7MN2bC7VDUrvf9gaR6CQn3agRPwwbLtfUvLhfMVy4loM+8EjrqbUGUVvNGZ7fIzDA5Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790546444; c=relaxed/simple; bh=U4LiS/1QhWXgAOWmd043vnNYlAj5iV4fmmuqnUtrYw0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=P2LnuVm5f1Z/+ehTCT6hRrSTBenVZGxUJjEl6IyMkLewnC2ZREvjsRXpyQTkIXISf2gKMbx4AoRx/0oyQlHtYbcER1nqcMIQ3ruoN9o9J8C8pXDvGiuNljesibIEIIIe/BDR8xHjhKJhiLhXbnRBG27tngQ/f/KJ3/OBC1m/UVs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=YviFQqvX; arc=none smtp.client-ip=74.125.231.171 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-oo2-f43.google.com with SMTP id 46e09a7af769-81b37951827so449050a34.1 for ; Sun, 27 Sep 2026 15:00:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1790546435; x=1791151235; darn=lists.linux.dev; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=30RkihLAQAAN+ek9RJOVBaHflsvDFgd1E0pCuaoqmxI=; b=YviFQqvX5l8a/or2KTr/qN+vOGA+oJeIJwZ97NsLYm4QZy6VZ9lfojaA9i5L33gD1P xKIftjaTqoidaUMpT0NqV2aiUNwsWjNJD2AHeUhThsr7NXhZjFr5LvAwTV3+v/QGFSha ricAFrRf9BfKVOTw735ots4VolwtunryUDJsc9GF/KRhh0MbCJqhBwRF4MfAyUuHTvVV OSXkgQGLq/5Mu36l1Zsc72XojSxUb5Zlzyex2JgkNZYriylx6fB+s1m3VWeusWFiGqcP qIpki3FivWGVk1Z9lWRrTzneGOUZmlv8Ma/veeVZG9BeXNwkmlWQszJTl4PWM/J2lyLu 1vMA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790546435; x=1791151235; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=30RkihLAQAAN+ek9RJOVBaHflsvDFgd1E0pCuaoqmxI=; b=wZ0DQBZMXb7G7UAOHNBbAkxrH/nMIlge9kYY4Xn3dlT8iwlI0+GGrqDchhAyvBYee4 dGxpyY4aZkFWCK/Q2lGQZg5o/7lPydzyB8hhqvVDmeTd7FkE9o89KN53+IG1Gxar4ra7 H1GkdkklR6VKxL04XgDAc4ce8nAadRf6ZKihcLvjxGmXpIG6Me+VCt1z2bMEBe7kSHJa Ge9o43rsA9OIVk+oIUb7gydm1/bS+ZCy6gJZHMFe8OVNBpErQd1eG/SStiVWMsjph7Db 3BlG93tA3FVqPRNKwpdgBXdu/juHVFJYSDLNOjhxlSKtrXGQhJABb5QRfVMzEgw4XZu8 AN7A== X-Forwarded-Encrypted: i=1; AKwUvBw0zsYO/RvafeotkPLRL5gzk5/Aw6sKHrT9YjwTwxuCKRefycmW03VvNmvdw01xkUadKsnVlxzE3RhAqw==@lists.linux.dev X-Gm-Message-State: AFuF++mQi3fiSfi63O+o45sqrBuSmQI7+9aW9cdzhfRECJp21D5VgmUG uOg+639075hZ1MUMZpUP8q6fbEcTwPyvIK3hwaBBZP1JlvgPi0KCZu3e X-Gm-Gg: AYBFou0JIXWE29sR7eufzfCMtksJd5C6LeOGq+e4/L1FKYQy+36RSDfAPYY6giIlCFr J1w83bocPTMBmx3LmW70NJ1uchX8MBpAY7/b+73rclCaE4P23bKLFkcGVhv3rHXnXnxj1IYUv4k 5JNO7tutdh+nKqLkxT4hbtFUrYfqLDAs4NFP5AjIZTpb6er+CXh/SoRFJ8NMs1WXrHnvySWqqlh qbe3OrrXXJKTT5LfsergipO2AXlZyRHcGO0d67ptAS61QRJnZ7IvppmXWItw80D0j2emUuh27KN 0T3VuFb6mo1Tn7nidUS9EN529P7fO9/PrOpY1ev0oxC3o65gKNW/C4ml/MX62yEs9oCb+SUmUXZ xI3nARlXiiQUqU6pzlEWyYHqqGMkUY2fUaECNir55fF3VlK8IIwWH94R/L/14PVZSPdHPAdnSeL 9ZVuwX++xxf3mY547oCqeNIeiPX6yu8xZj0sbJM39JIYgShWgigWhdntNMZftH22jwFJzQK0R9y HKx4rHlkww6JuM2KjeUA6fr1TKx9wiMc6BPh4WXjGz/0Pa4eepv93ahu9hITP3QljT9uU0iIB9J QFwZ9zv7MiWJRQAEMlQ7DZY8iV9dhMF62miTeqfSkQMZoNjEJz4CMSzs+5RFKyEtzwyKJ61GJMK DW151VAvWigBIziC8rgpcjTjd52+IgiM= X-Received: by 2002:a05:6830:2708:b0:81a:adf1:ae71 with SMTP id 46e09a7af769-81aadf1b046mr5285934a34.4.1790546434869; Sun, 27 Sep 2026 15:00:34 -0700 (PDT) Received: from [127.0.1.1] (174-29-1-49.hlrn.qwest.net. [174.29.1.49]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-81b3de6f7e1sm4874147a34.22.2026.09.27.15.00.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 27 Sep 2026 15:00:34 -0700 (PDT) From: James Hilliard Date: Sun, 27 Sep 2026 15:59:53 -0600 Subject: [PATCH net-next v5 18/19] net: stmmac: prepare device-local DMA interrupt quiescence Precedence: bulk X-Mailing-List: linux-sunxi@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20260927-submit-stmmac-reset-fixes-v1-v5-18-feec6c14dd06@gmail.com> References: <20260927-submit-stmmac-reset-fixes-v1-v5-0-feec6c14dd06@gmail.com> In-Reply-To: <20260927-submit-stmmac-reset-fixes-v1-v5-0-feec6c14dd06@gmail.com> To: Russell King , Andrew Lunn , Heiner Kallweit , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , "Russell King (Oracle)" , Maxime Chevallier , Andrew Lunn , Maxime Coquelin , Alexandre Torgue , Christian Marangi , Tiezhu Yang , Huacai Chen , Alexei Starovoitov , Daniel Borkmann , Jesper Dangaard Brouer , John Fastabend , Stanislav Fomichev , Serge Semin , Suraj Jaiswal , Richard Cochran , Joao Pinto , Vladimir Oltean , Ong Boon Leong , Voon Weifeng , "Song, Yoong Siang" , Linus Walleij , Martin Blumenstingl , Magnus Karlsson , Maciej Fijalkowski , Simon Horman , =?utf-8?b?QmrDtnJuIFTDtnBlbA==?= , Thierry Reding , Jonathan Hunter , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Jose Abreu , Yao Zi , Philipp Zabel Cc: Richard Genoud , Alastair D'Silva , Maxime Ripard , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, linux-arm-kernel@lists.infradead.org, bpf@vger.kernel.org, ZhaoJinming , Lorenzo Bianconi , Ding Hui , Linkui Xiao , Linkui Xiao , linux-tegra@vger.kernel.org, linux-sunxi@lists.linux.dev, James Hilliard X-Mailer: b4 0.15.2 X-MORS-Enabled: yes X-MORS-DOMAIN: patchwork.local X-MORS-HOSTING: hosting172546 X-MORS-USER: hosting172546 X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= Add DMA interrupt-mask accessors for the supported cores and a per-channel gate protected by the channel lock. A handler invoked on a shared IRQ can then mask newly enabled device sources without acknowledging pending events or touching rings being replaced. The retained-ring MTU transaction will save and restore these masks and synchronize the registered handlers. No interrupt-controller line needs to be disabled, so other devices sharing the IRQ remain serviceable. Signed-off-by: James Hilliard --- drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 11 ++++++++ .../net/ethernet/stmicro/stmmac/dwmac1000_dma.c | 1 + drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c | 1 + drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c | 2 ++ drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h | 2 ++ drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c | 11 ++++++++ drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h | 2 ++ drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c | 10 ++++++++ drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c | 11 ++++++++ drivers/net/ethernet/stmicro/stmmac/hwif.h | 5 ++++ drivers/net/ethernet/stmicro/stmmac/stmmac.h | 2 ++ drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 30 ++++++++++++++++------ 12 files changed, 80 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c index c9145441aab0..8a3f15134402 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c @@ -374,6 +374,16 @@ static void sun8i_dwmac_disable_dma_irq(struct stmmac_priv *priv, writel(value, ioaddr + EMAC_INT_EN); } +static u32 sun8i_dwmac_set_dma_irq_mask(struct stmmac_priv *priv, + void __iomem *ioaddr, u32 chan, u32 mask) +{ + u32 old_mask = readl(ioaddr + EMAC_INT_EN); + + writel(mask, ioaddr + EMAC_INT_EN); + readl(ioaddr + EMAC_INT_EN); + return old_mask; +} + static void sun8i_dwmac_dma_start_tx(struct stmmac_priv *priv, void __iomem *ioaddr, u32 chan) { @@ -579,6 +589,7 @@ static const struct stmmac_dma_ops sun8i_dwmac_dma_ops = { .enable_dma_transmission = sun8i_dwmac_enable_dma_transmission, .enable_dma_irq = sun8i_dwmac_enable_dma_irq, .disable_dma_irq = sun8i_dwmac_disable_dma_irq, + .set_irq_mask = sun8i_dwmac_set_dma_irq_mask, .start_tx = sun8i_dwmac_dma_start_tx, .stop_tx = sun8i_dwmac_dma_stop_tx, .start_rx = sun8i_dwmac_dma_start_rx, diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c index 4cb7e6c16bdd..2285eac69071 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c @@ -264,6 +264,7 @@ const struct stmmac_dma_ops dwmac1000_dma_ops = { .enable_dma_reception = dwmac_enable_dma_reception, .enable_dma_irq = dwmac_enable_dma_irq, .disable_dma_irq = dwmac_disable_dma_irq, + .set_irq_mask = dwmac_set_dma_irq_mask, .start_tx = dwmac_dma_start_tx, .stop_tx = dwmac_dma_stop_tx, .start_rx = dwmac_dma_start_rx, diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c index 5ffd3c1471c4..41579d10af3c 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c @@ -118,6 +118,7 @@ const struct stmmac_dma_ops dwmac100_dma_ops = { .enable_dma_transmission = dwmac_enable_dma_transmission, .enable_dma_irq = dwmac_enable_dma_irq, .disable_dma_irq = dwmac_disable_dma_irq, + .set_irq_mask = dwmac_set_dma_irq_mask, .start_tx = dwmac_dma_start_tx, .stop_tx = dwmac_dma_stop_tx, .start_rx = dwmac_dma_start_rx, diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c index d7928678dee1..d5f0cc8b851d 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c @@ -582,6 +582,7 @@ const struct stmmac_dma_ops dwmac4_dma_ops = { .dma_tx_mode = dwmac4_dma_tx_chan_op_mode, .enable_dma_irq = dwmac4_enable_dma_irq, .disable_dma_irq = dwmac4_disable_dma_irq, + .set_irq_mask = dwmac4_set_dma_irq_mask, .start_tx = dwmac4_dma_start_tx, .stop_tx = dwmac4_dma_stop_tx, .start_rx = dwmac4_dma_start_rx, @@ -613,6 +614,7 @@ const struct stmmac_dma_ops dwmac410_dma_ops = { .dma_tx_mode = dwmac4_dma_tx_chan_op_mode, .enable_dma_irq = dwmac4_enable_dma_irq, .disable_dma_irq = dwmac4_disable_dma_irq, + .set_irq_mask = dwmac4_set_dma_irq_mask, .start_tx = dwmac4_dma_start_tx, .stop_tx = dwmac4_dma_stop_tx, .start_rx = dwmac4_dma_start_rx, diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h index 9352107204eb..edccc09f0b03 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h @@ -184,6 +184,8 @@ void dwmac4_enable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr, u32 chan, bool rx, bool tx); void dwmac4_disable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr, u32 chan, bool rx, bool tx); +u32 dwmac4_set_dma_irq_mask(struct stmmac_priv *priv, void __iomem *ioaddr, + u32 chan, u32 mask); void dwmac4_dma_start_tx(struct stmmac_priv *priv, void __iomem *ioaddr, u32 chan); void dwmac4_dma_stop_tx(struct stmmac_priv *priv, void __iomem *ioaddr, diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c index 9af0565a9bca..477bdb081c52 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c @@ -155,6 +155,17 @@ void dwmac4_disable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr, writel(value, ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan)); } +u32 dwmac4_set_dma_irq_mask(struct stmmac_priv *priv, void __iomem *ioaddr, + u32 chan, u32 mask) +{ + const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs; + u32 old_mask = readl(ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan)); + + writel(mask, ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan)); + readl(ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan)); + return old_mask; +} + int dwmac4_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr, struct stmmac_extra_stats *x, u32 chan, u32 dir) { diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h index 970495bccfd2..4726801253f5 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h @@ -150,6 +150,8 @@ void dwmac_enable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr, u32 chan, bool rx, bool tx); void dwmac_disable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr, u32 chan, bool rx, bool tx); +u32 dwmac_set_dma_irq_mask(struct stmmac_priv *priv, void __iomem *ioaddr, + u32 chan, u32 mask); void dwmac_dma_start_tx(struct stmmac_priv *priv, void __iomem *ioaddr, u32 chan); void dwmac_dma_stop_tx(struct stmmac_priv *priv, void __iomem *ioaddr, diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c index bb907db8fca1..88d904ed4685 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c @@ -84,6 +84,16 @@ void dwmac_disable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr, writel(value, ioaddr + DMA_CHAN_INTR_ENA(chan)); } +u32 dwmac_set_dma_irq_mask(struct stmmac_priv *priv, void __iomem *ioaddr, + u32 chan, u32 mask) +{ + u32 old_mask = readl(ioaddr + DMA_CHAN_INTR_ENA(chan)); + + writel(mask, ioaddr + DMA_CHAN_INTR_ENA(chan)); + readl(ioaddr + DMA_CHAN_INTR_ENA(chan)); + return old_mask; +} + void dwmac_dma_start_tx(struct stmmac_priv *priv, void __iomem *ioaddr, u32 chan) { diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c index ff83858ebc1f..30915d3f5230 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c @@ -256,6 +256,16 @@ static void dwxgmac2_disable_dma_irq(struct stmmac_priv *priv, writel(value, ioaddr + XGMAC_DMA_CH_INT_EN(chan)); } +static u32 dwxgmac2_set_dma_irq_mask(struct stmmac_priv *priv, + void __iomem *ioaddr, u32 chan, u32 mask) +{ + u32 old_mask = readl(ioaddr + XGMAC_DMA_CH_INT_EN(chan)); + + writel(mask, ioaddr + XGMAC_DMA_CH_INT_EN(chan)); + readl(ioaddr + XGMAC_DMA_CH_INT_EN(chan)); + return old_mask; +} + static void dwxgmac2_dma_start_tx(struct stmmac_priv *priv, void __iomem *ioaddr, u32 chan) { @@ -604,6 +614,7 @@ const struct stmmac_dma_ops dwxgmac210_dma_ops = { .dma_tx_mode = dwxgmac2_dma_tx_mode, .enable_dma_irq = dwxgmac2_enable_dma_irq, .disable_dma_irq = dwxgmac2_disable_dma_irq, + .set_irq_mask = dwxgmac2_set_dma_irq_mask, .start_tx = dwxgmac2_dma_start_tx, .stop_tx = dwxgmac2_dma_stop_tx, .start_rx = dwxgmac2_dma_start_rx, diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h index 4b7381a6fcce..20de97ac011a 100644 --- a/drivers/net/ethernet/stmicro/stmmac/hwif.h +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h @@ -197,6 +197,9 @@ struct stmmac_dma_ops { u32 chan, bool rx, bool tx); void (*disable_dma_irq)(struct stmmac_priv *priv, void __iomem *ioaddr, u32 chan, bool rx, bool tx); + /* Replace and flush the full interrupt enable mask; return the old mask. */ + u32 (*set_irq_mask)(struct stmmac_priv *priv, void __iomem *ioaddr, + u32 chan, u32 mask); void (*start_tx)(struct stmmac_priv *priv, void __iomem *ioaddr, u32 chan); void (*stop_tx)(struct stmmac_priv *priv, void __iomem *ioaddr, @@ -263,6 +266,8 @@ struct stmmac_dma_ops { stmmac_do_void_callback(__priv, dma, enable_dma_irq, __priv, __args) #define stmmac_disable_dma_irq(__priv, __args...) \ stmmac_do_void_callback(__priv, dma, disable_dma_irq, __priv, __args) +#define stmmac_set_dma_irq_mask(__priv, __args...) \ + stmmac_do_callback(__priv, dma, set_irq_mask, __priv, __args) #define stmmac_start_tx(__priv, __args...) \ stmmac_do_void_callback(__priv, dma, start_tx, __priv, __args) #define stmmac_stop_tx(__priv, __args...) \ diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h index 090d79aeb2ad..06fe750624b6 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h @@ -146,6 +146,8 @@ struct stmmac_channel { struct stmmac_priv *priv_data; spinlock_t lock; u32 index; + /* Protected by lock; IRQ handlers must not access the DMA rings. */ + bool irq_quiesced; }; struct stmmac_fpe_cfg { diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 98dbc873e1c8..435c76b7db30 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -3370,14 +3370,30 @@ static bool stmmac_safety_feat_interrupt(struct stmmac_priv *priv) static int stmmac_napi_check(struct stmmac_priv *priv, u32 chan, u32 dir) { - int status = stmmac_dma_interrupt_status(priv, priv->ioaddr, - &priv->xstats, chan, dir); - struct stmmac_rx_queue *rx_q = &priv->dma_conf->rx_queue[chan]; - struct stmmac_tx_queue *tx_q = &priv->dma_conf->tx_queue[chan]; struct stmmac_channel *ch = &priv->channel[chan]; + struct stmmac_rx_queue *rx_q; + struct stmmac_tx_queue *tx_q; struct napi_struct *rx_napi; struct napi_struct *tx_napi; unsigned long flags; + int status; + + spin_lock_irqsave(&ch->lock, flags); + if (unlikely(ch->irq_quiesced)) { + /* A shared IRQ may still invoke us, and DMA initialization can + * restore interrupt enables. Mask them again without acknowledging + * pending events or accessing the configuration being replaced. + */ + stmmac_set_dma_irq_mask(priv, priv->ioaddr, chan, 0); + spin_unlock_irqrestore(&ch->lock, flags); + return 0; + } + spin_unlock_irqrestore(&ch->lock, flags); + + status = stmmac_dma_interrupt_status(priv, priv->ioaddr, + &priv->xstats, chan, dir); + rx_q = &priv->dma_conf->rx_queue[chan]; + tx_q = &priv->dma_conf->tx_queue[chan]; rx_napi = rx_q->xsk_pool ? &ch->rxtx_napi : &ch->rx_napi; tx_napi = tx_q->xsk_pool ? &ch->rxtx_napi : &ch->tx_napi; @@ -4096,8 +4112,7 @@ static void stmmac_free_irq(struct net_device *dev, for (j = irq_idx - 1; msi && j >= 0; j--) { if (msi->tx_irq[j] > 0) { irq_set_affinity_hint(msi->tx_irq[j], NULL); - free_irq(msi->tx_irq[j], - &priv->channel[j]); + free_irq(msi->tx_irq[j], &priv->channel[j]); } } irq_idx = priv->plat->rx_queues_to_use; @@ -4106,8 +4121,7 @@ static void stmmac_free_irq(struct net_device *dev, for (j = irq_idx - 1; msi && j >= 0; j--) { if (msi->rx_irq[j] > 0) { irq_set_affinity_hint(msi->rx_irq[j], NULL); - free_irq(msi->rx_irq[j], - &priv->channel[j]); + free_irq(msi->rx_irq[j], &priv->channel[j]); } }