From nobody Tue Apr 7 12:38:52 2026 Received: from relmlie6.idc.renesas.com (relmlor2.renesas.com [210.160.252.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 7A2EA3D3485; Wed, 25 Feb 2026 14:24:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=210.160.252.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772029477; cv=none; b=aA1Cm3s4QVkGiGbHUMyg+75DHvIcvubgt7+9pXvoB3M4JYLPSVBVxH1jwxx6DL8RbcYEubO22gGgZKTc88ThVisP77hpZbATlr6SPqiki758W1oZkMCeV3FK+Uz6G/f987vDxqyKpSlFh3+lU8s+qv7DGcXsfr95O/zWy1H7Ta8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772029477; c=relaxed/simple; bh=/j+KKokPmqND21UBiNjdIW9ARxpHY/OtdFIFrZnogdU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=V4utqL3s6hTtHgQ9T7yCPAcH1m7nvdMwk6IB0weQu1yznPumfJSBxkd1IL0B32DWzqsB4CAzaMYIeqLTtw+VaJfWHPA5t9SF+opklAWMHuSZlOJ3tKAMxRRnEWlXk0Z6kfOGHL4riEmTfQtgeUj18Onb7kSz+B0oHqsf/wg6iXk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=renesas.com; spf=pass smtp.mailfrom=renesas.com; arc=none smtp.client-ip=210.160.252.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=renesas.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=renesas.com X-CSE-ConnectionGUID: onbCMC7XSyWtP4f3YSZ8Uw== X-CSE-MsgGUID: fx56hqT+ToOjKXfaFqOYPQ== Received: from unknown (HELO relmlir5.idc.renesas.com) ([10.200.68.151]) by relmlie6.idc.renesas.com with ESMTP; 25 Feb 2026 23:24:28 +0900 Received: from vm01.adwin.renesas.com (unknown [10.226.92.192]) by relmlir5.idc.renesas.com (Postfix) with ESMTP id 661CC4017D8D; Wed, 25 Feb 2026 23:24:22 +0900 (JST) From: Ovidiu Panait To: andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, mcoquelin.stm32@gmail.com, alexandre.torgue@foss.st.com, linux@armlinux.org.uk, rmk+kernel@armlinux.org.uk, maxime.chevallier@bootlin.com, boon.khai.ng@altera.com, rohan.g.thomas@altera.com, vladimir.oltean@nxp.com, hayashi.kunihiko@socionext.com, boon.leong.ong@intel.com, kim.tatt.chuah@intel.com Cc: netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-stm32@st-md-mailman.stormreply.com, linux-kernel@vger.kernel.org Subject: [PATCH net-next v2 1/5] net: stmmac: Fix error handling in VLAN add and delete paths Date: Wed, 25 Feb 2026 14:24:10 +0000 Message-ID: <20260225142414.130144-2-ovidiu.panait.rb@renesas.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260225142414.130144-1-ovidiu.panait.rb@renesas.com> References: <20260225142414.130144-1-ovidiu.panait.rb@renesas.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" stmmac_vlan_rx_add_vid() updates active_vlans and the VLAN hash register before writing the HW filter entry. If the filter write fails, it leaves a stale VID in active_vlans and the hash register. stmmac_vlan_rx_kill_vid() has the reverse problem: it clears active_vlans before removing the HW filter. On failure, the VID is gone from active_vlans but still present in the HW filter table. To fix this, reorder the operations to update the hash table first, then attempt the HW filter operation. If the HW filter fails, roll back both the active_vlans bitmap and the hash table by calling stmmac_vlan_update() again. Fixes: ed64639bc1e0 ("net: stmmac: Add support for VLAN Rx filtering") Signed-off-by: Ovidiu Panait --- v2 changes: none. .../net/ethernet/stmicro/stmmac/stmmac_main.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/ne= t/ethernet/stmicro/stmmac/stmmac_main.c index 82375d34ad57..f2f120ddba46 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -6798,9 +6798,13 @@ static int stmmac_vlan_rx_add_vid(struct net_device = *ndev, __be16 proto, u16 vid =20 if (priv->hw->num_vlan) { ret =3D stmmac_add_hw_vlan_rx_fltr(priv, ndev, priv->hw, proto, vid); - if (ret) + if (ret) { + clear_bit(vid, priv->active_vlans); + stmmac_vlan_update(priv, is_double); goto err_pm_put; + } } + err_pm_put: pm_runtime_put(priv->device); =20 @@ -6824,15 +6828,21 @@ static int stmmac_vlan_rx_kill_vid(struct net_devic= e *ndev, __be16 proto, u16 vi is_double =3D true; =20 clear_bit(vid, priv->active_vlans); + ret =3D stmmac_vlan_update(priv, is_double); + if (ret) { + set_bit(vid, priv->active_vlans); + goto del_vlan_error; + } =20 if (priv->hw->num_vlan) { ret =3D stmmac_del_hw_vlan_rx_fltr(priv, ndev, priv->hw, proto, vid); - if (ret) + if (ret) { + set_bit(vid, priv->active_vlans); + stmmac_vlan_update(priv, is_double); goto del_vlan_error; + } } =20 - ret =3D stmmac_vlan_update(priv, is_double); - del_vlan_error: pm_runtime_put(priv->device); =20 --=20 2.51.0 From nobody Tue Apr 7 12:38:52 2026 Received: from relmlie6.idc.renesas.com (relmlor2.renesas.com [210.160.252.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 6E7AB3B8BBE; Wed, 25 Feb 2026 14:24:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=210.160.252.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772029478; cv=none; b=VS+zUIIcPDjmFl1wN/RzKhUY6feBhZP3uWu71OxSPLUC6H7b9FIFwawAuS99R7PgaPzT8qw8gHFz9ZKSG/u/HYKRYg9Edwcm4qknh1+mJouuuwvjRLjbSJS5hlouvAe8EdTkBtZOAwnvD3W3r11g4P+Yfu9Db4uTj40nFjg9h+k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772029478; c=relaxed/simple; bh=iZiRYPlbKKYB65h0penxpaWaXSDVfsnxkBDJgCThSxM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=s1nIdxc3DSl2lSehRXF9b8i996cFdCNMD+quWmNHqvcf/2KtaqcUBuDsVmU+jF3neD8EnmXceolxeEQeFuWbsvw6KFxkNDg/M9LJY9UTZUlsh0T9XRJihQ+Kto+O79pP/YLBc3ppUPtijiS+WW1Zamcx/lO5qwFZIb/y2hmqMSM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=renesas.com; spf=pass smtp.mailfrom=renesas.com; arc=none smtp.client-ip=210.160.252.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=renesas.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=renesas.com X-CSE-ConnectionGUID: LVII5tWxSmyv/yfO/AUg+g== X-CSE-MsgGUID: cswNqotXT5a0/Ds7dT1xwQ== Received: from unknown (HELO relmlir5.idc.renesas.com) ([10.200.68.151]) by relmlie6.idc.renesas.com with ESMTP; 25 Feb 2026 23:24:35 +0900 Received: from vm01.adwin.renesas.com (unknown [10.226.92.192]) by relmlir5.idc.renesas.com (Postfix) with ESMTP id 3468A4017D8D; Wed, 25 Feb 2026 23:24:28 +0900 (JST) From: Ovidiu Panait To: andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, mcoquelin.stm32@gmail.com, alexandre.torgue@foss.st.com, linux@armlinux.org.uk, rmk+kernel@armlinux.org.uk, maxime.chevallier@bootlin.com, boon.khai.ng@altera.com, rohan.g.thomas@altera.com, vladimir.oltean@nxp.com, hayashi.kunihiko@socionext.com, boon.leong.ong@intel.com, kim.tatt.chuah@intel.com Cc: netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-stm32@st-md-mailman.stormreply.com, linux-kernel@vger.kernel.org Subject: [PATCH net-next v2 2/5] net: stmmac: Improve double VLAN handling Date: Wed, 25 Feb 2026 14:24:11 +0000 Message-ID: <20260225142414.130144-3-ovidiu.panait.rb@renesas.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260225142414.130144-1-ovidiu.panait.rb@renesas.com> References: <20260225142414.130144-1-ovidiu.panait.rb@renesas.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The double VLAN bits (EDVLP, ESVL, DOVLTC) are handled inconsistently between the two vlan_update_hash() implementations: - dwxgmac2_update_vlan_hash() explicitly clears the double VLAN bits when is_double is false, meaning that adding a 802.1Q VLAN will disable double VLAN mode: $ ip link add link eth0 name eth0.200 type vlan id 200 protocol 802.1ad $ ip link add link eth0 name eth0.100 type vlan id 100 # Double VLAN bits no longer set - vlan_update_hash() sets these bits and only clears them when the last VLAN has been removed, so double VLAN mode remains enabled even after all 802.1AD VLANs are removed. Address both issues by tracking the number of active 802.1AD VLANs in priv->num_double_vlans. Pass this count to stmmac_vlan_update() so both implementations correctly set the double VLAN bits when any 802.1AD VLAN is active, and clear them only when none remain. Also update vlan_update_hash() to explicitly clear the double VLAN bits when is_double is false, matching the dwxgmac2 behavior. Signed-off-by: Ovidiu Panait --- v2 changes: none. drivers/net/ethernet/stmicro/stmmac/stmmac.h | 1 + .../net/ethernet/stmicro/stmmac/stmmac_main.c | 16 ++++++++++++---- .../net/ethernet/stmicro/stmmac/stmmac_vlan.c | 8 ++++++++ 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/eth= ernet/stmicro/stmmac/stmmac.h index 51c96a738151..33667a26708c 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h @@ -323,6 +323,7 @@ struct stmmac_priv { void __iomem *ptpaddr; void __iomem *estaddr; unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)]; + unsigned int num_double_vlans; int sfty_irq; int sfty_ce_irq; int sfty_ue_irq; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/ne= t/ethernet/stmicro/stmmac/stmmac_main.c index f2f120ddba46..45f2f3492dbd 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -6779,6 +6779,7 @@ static int stmmac_vlan_update(struct stmmac_priv *pri= v, bool is_double) static int stmmac_vlan_rx_add_vid(struct net_device *ndev, __be16 proto, u= 16 vid) { struct stmmac_priv *priv =3D netdev_priv(ndev); + unsigned int num_double_vlans; bool is_double =3D false; int ret; =20 @@ -6790,7 +6791,8 @@ static int stmmac_vlan_rx_add_vid(struct net_device *= ndev, __be16 proto, u16 vid is_double =3D true; =20 set_bit(vid, priv->active_vlans); - ret =3D stmmac_vlan_update(priv, is_double); + num_double_vlans =3D priv->num_double_vlans + is_double; + ret =3D stmmac_vlan_update(priv, num_double_vlans); if (ret) { clear_bit(vid, priv->active_vlans); goto err_pm_put; @@ -6800,11 +6802,13 @@ static int stmmac_vlan_rx_add_vid(struct net_device= *ndev, __be16 proto, u16 vid ret =3D stmmac_add_hw_vlan_rx_fltr(priv, ndev, priv->hw, proto, vid); if (ret) { clear_bit(vid, priv->active_vlans); - stmmac_vlan_update(priv, is_double); + stmmac_vlan_update(priv, priv->num_double_vlans); goto err_pm_put; } } =20 + priv->num_double_vlans =3D num_double_vlans; + err_pm_put: pm_runtime_put(priv->device); =20 @@ -6817,6 +6821,7 @@ static int stmmac_vlan_rx_add_vid(struct net_device *= ndev, __be16 proto, u16 vid static int stmmac_vlan_rx_kill_vid(struct net_device *ndev, __be16 proto, = u16 vid) { struct stmmac_priv *priv =3D netdev_priv(ndev); + unsigned int num_double_vlans; bool is_double =3D false; int ret; =20 @@ -6828,7 +6833,8 @@ static int stmmac_vlan_rx_kill_vid(struct net_device = *ndev, __be16 proto, u16 vi is_double =3D true; =20 clear_bit(vid, priv->active_vlans); - ret =3D stmmac_vlan_update(priv, is_double); + num_double_vlans =3D priv->num_double_vlans - is_double; + ret =3D stmmac_vlan_update(priv, num_double_vlans); if (ret) { set_bit(vid, priv->active_vlans); goto del_vlan_error; @@ -6838,11 +6844,13 @@ static int stmmac_vlan_rx_kill_vid(struct net_devic= e *ndev, __be16 proto, u16 vi ret =3D stmmac_del_hw_vlan_rx_fltr(priv, ndev, priv->hw, proto, vid); if (ret) { set_bit(vid, priv->active_vlans); - stmmac_vlan_update(priv, is_double); + stmmac_vlan_update(priv, priv->num_double_vlans); goto del_vlan_error; } } =20 + priv->num_double_vlans =3D num_double_vlans; + del_vlan_error: pm_runtime_put(priv->device); =20 diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c b/drivers/ne= t/ethernet/stmicro/stmmac/stmmac_vlan.c index b18404dd5a8b..de1a70e1c86e 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c @@ -183,6 +183,10 @@ static void vlan_update_hash(struct mac_device_info *h= w, u32 hash, value |=3D VLAN_EDVLP; value |=3D VLAN_ESVL; value |=3D VLAN_DOVLTC; + } else { + value &=3D ~VLAN_EDVLP; + value &=3D ~VLAN_ESVL; + value &=3D ~VLAN_DOVLTC; } =20 writel(value, ioaddr + VLAN_TAG); @@ -193,6 +197,10 @@ static void vlan_update_hash(struct mac_device_info *h= w, u32 hash, value |=3D VLAN_EDVLP; value |=3D VLAN_ESVL; value |=3D VLAN_DOVLTC; + } else { + value &=3D ~VLAN_EDVLP; + value &=3D ~VLAN_ESVL; + value &=3D ~VLAN_DOVLTC; } =20 writel(value | perfect_match, ioaddr + VLAN_TAG); --=20 2.51.0 From nobody Tue Apr 7 12:38:52 2026 Received: from relmlie6.idc.renesas.com (relmlor2.renesas.com [210.160.252.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 60D53392822; Wed, 25 Feb 2026 14:24:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=210.160.252.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772029485; cv=none; b=W7dA0aX/9GR/HQip1rAMqKg00dBLiFet32YOZUpAgFzTZGlCXIqXjkoAQszU3TLRaqp8EORpetnGp30gXfnzyJfQD8puIwWFF6jZMczWo5Eg0pz7+gPE7aSoRbL3BQkwR8VOVjxn0Bhg3f7PfJwFlTdaR0Nw/6O1sCtw6hfMLg8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772029485; c=relaxed/simple; bh=1CJuv1XMQNz8naG5Ty1dEzPH1ns2iXK9o6JES9iIrRU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=SbBXz3GXFLdScFI0kswiGhJwaBw1wxmtKNaNTFsZkn3SWybCdmE+p747OSNH2JABeLVyR/AnicqPxKfYICrjrO3to+QUzRp9ijugZ3F2F+CPEUAXHzF87liKSRy3umSGe+gKVNPU1PX8pNT4P28RIKWmTJkelz3z9cBGpu3MuUM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=renesas.com; spf=pass smtp.mailfrom=renesas.com; arc=none smtp.client-ip=210.160.252.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=renesas.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=renesas.com X-CSE-ConnectionGUID: 1F5aL7fnRvmwWTMmby5hJg== X-CSE-MsgGUID: mbhJ6JdbQmaEysDv/2t5cw== Received: from unknown (HELO relmlir5.idc.renesas.com) ([10.200.68.151]) by relmlie6.idc.renesas.com with ESMTP; 25 Feb 2026 23:24:42 +0900 Received: from vm01.adwin.renesas.com (unknown [10.226.92.192]) by relmlir5.idc.renesas.com (Postfix) with ESMTP id 03E174017D8D; Wed, 25 Feb 2026 23:24:35 +0900 (JST) From: Ovidiu Panait To: andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, mcoquelin.stm32@gmail.com, alexandre.torgue@foss.st.com, linux@armlinux.org.uk, rmk+kernel@armlinux.org.uk, maxime.chevallier@bootlin.com, boon.khai.ng@altera.com, rohan.g.thomas@altera.com, vladimir.oltean@nxp.com, hayashi.kunihiko@socionext.com, boon.leong.ong@intel.com, kim.tatt.chuah@intel.com Cc: netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-stm32@st-md-mailman.stormreply.com, linux-kernel@vger.kernel.org Subject: [PATCH net-next v2 3/5] net: stmmac: Fix VLAN HW state restore Date: Wed, 25 Feb 2026 14:24:12 +0000 Message-ID: <20260225142414.130144-4-ovidiu.panait.rb@renesas.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260225142414.130144-1-ovidiu.panait.rb@renesas.com> References: <20260225142414.130144-1-ovidiu.panait.rb@renesas.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" When the network interface is opened or resumed, a DMA reset is performed, which resets all hardware state, including VLAN state. Currently, only the resume path is restoring the VLAN state via stmmac_restore_hw_vlan_rx_fltr(), but that is incomplete: the VLAN hash table and the VLAN_TAG control bits are not restored. Therefore, add stmmac_vlan_restore(), which restores the full VLAN state by updating both the HW filter entries and the hash table, and call it from both the open and resume paths. The VLAN restore is moved outside of phylink_rx_clk_stop_block/unblock in the resume path because receive clock stop is already disabled when stmmac supports VLAN. Also, remove the hash readback code in vlan_restore_hw_rx_fltr() that attempts to restore VTHM by reading VLAN_HASH_TABLE, as it always reads zero after DMA reset, making it dead code. Fixes: 3cd1cfcba26e ("net: stmmac: Implement VLAN Hash Filtering in XGMAC") Fixes: ed64639bc1e0 ("net: stmmac: Add support for VLAN Rx filtering") Signed-off-by: Ovidiu Panait --- v2 changes: new patch. .../net/ethernet/stmicro/stmmac/stmmac_main.c | 24 +++++++++++++++++-- .../net/ethernet/stmicro/stmmac/stmmac_vlan.c | 10 -------- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/ne= t/ethernet/stmicro/stmmac/stmmac_main.c index 45f2f3492dbd..a02575f67057 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -156,6 +156,7 @@ static void stmmac_tx_timer_arm(struct stmmac_priv *pri= v, u32 queue); static void stmmac_flush_tx_descriptors(struct stmmac_priv *priv, int queu= e); static void stmmac_set_dma_operation_mode(struct stmmac_priv *priv, u32 tx= mode, u32 rxmode, u32 chan); +static int stmmac_vlan_restore(struct stmmac_priv *priv); =20 #ifdef CONFIG_DEBUG_FS static const struct net_device_ops stmmac_netdev_ops; @@ -4111,6 +4112,8 @@ static int __stmmac_open(struct net_device *dev, =20 phylink_start(priv->phylink); =20 + stmmac_vlan_restore(priv); + ret =3D stmmac_request_irq(dev); if (ret) goto irq_error; @@ -6857,6 +6860,23 @@ static int stmmac_vlan_rx_kill_vid(struct net_device= *ndev, __be16 proto, u16 vi return ret; } =20 +static int stmmac_vlan_restore(struct stmmac_priv *priv) +{ + int ret; + + if (!(priv->dev->features & NETIF_F_VLAN_FEATURES)) + return 0; + + if (priv->hw->num_vlan) + stmmac_restore_hw_vlan_rx_fltr(priv, priv->dev, priv->hw); + + ret =3D stmmac_vlan_update(priv, priv->num_double_vlans); + if (ret) + netdev_err(priv->dev, "Failed to restore VLANs\n"); + + return ret; +} + static int stmmac_bpf(struct net_device *dev, struct netdev_bpf *bpf) { struct stmmac_priv *priv =3D netdev_priv(dev); @@ -8281,10 +8301,10 @@ int stmmac_resume(struct device *dev) stmmac_init_coalesce(priv); phylink_rx_clk_stop_block(priv->phylink); stmmac_set_rx_mode(ndev); - - stmmac_restore_hw_vlan_rx_fltr(priv, ndev, priv->hw); phylink_rx_clk_stop_unblock(priv->phylink); =20 + stmmac_vlan_restore(priv); + stmmac_enable_all_queues(priv); stmmac_enable_all_dma_irq(priv); =20 diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c b/drivers/ne= t/ethernet/stmicro/stmmac/stmmac_vlan.c index de1a70e1c86e..fcc34867405e 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c @@ -139,9 +139,6 @@ static int vlan_del_hw_rx_fltr(struct net_device *dev, static void vlan_restore_hw_rx_fltr(struct net_device *dev, struct mac_device_info *hw) { - void __iomem *ioaddr =3D hw->pcsr; - u32 value; - u32 hash; u32 val; int i; =20 @@ -158,13 +155,6 @@ static void vlan_restore_hw_rx_fltr(struct net_device = *dev, vlan_write_filter(dev, hw, i, val); } } - - hash =3D readl(ioaddr + VLAN_HASH_TABLE); - if (hash & VLAN_VLHT) { - value =3D readl(ioaddr + VLAN_TAG); - value |=3D VLAN_VTHM; - writel(value, ioaddr + VLAN_TAG); - } } =20 static void vlan_update_hash(struct mac_device_info *hw, u32 hash, --=20 2.51.0 From nobody Tue Apr 7 12:38:52 2026 Received: from relmlie5.idc.renesas.com (relmlor1.renesas.com [210.160.252.171]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 4059D392822; Wed, 25 Feb 2026 14:24:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=210.160.252.171 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772029492; cv=none; b=UY8un1aUfdYTaBlPnUvnvM7qeTRLFAa7dvmcmOWEDmpSKrZCEHWmD0W0YJcTusf6U4ZlMImbX1wx5WredXRQMF63auFRmZXVPxlRI52+1LoVBzW9vajOJTuIwWL/Q9pjlHVIHe6ycopbGxLwYxw4FCfdEpZf73q5VAeE61+Nm0c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772029492; c=relaxed/simple; bh=90v2V3edTeUdWM0oAbEoX+Yh7zyuJt/oEpYWh3miwjQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=OwPM/wwlb8jXwo7QORy4TR5qre9evxKWRP2W4ByWVZ3iPZXCocWmD8ZYUGJzTLlLqYLvhOK/Ls4yWDSdH3u5oow85BQJmTvSe3jgG5iG7AzOxTxWPA1xSZP2IbaHaqQBV8laA46nqUfuXPQcAYYmm1LKxaWmC0rmOq3iFbcM4ls= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=renesas.com; spf=pass smtp.mailfrom=renesas.com; arc=none smtp.client-ip=210.160.252.171 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=renesas.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=renesas.com X-CSE-ConnectionGUID: L+IALaWDRBO0q4YalVUyWw== X-CSE-MsgGUID: cCWN2MKST6q+m7KfE0ELWQ== Received: from unknown (HELO relmlir5.idc.renesas.com) ([10.200.68.151]) by relmlie5.idc.renesas.com with ESMTP; 25 Feb 2026 23:24:49 +0900 Received: from vm01.adwin.renesas.com (unknown [10.226.92.192]) by relmlir5.idc.renesas.com (Postfix) with ESMTP id D25B14017D8D; Wed, 25 Feb 2026 23:24:42 +0900 (JST) From: Ovidiu Panait To: andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, mcoquelin.stm32@gmail.com, alexandre.torgue@foss.st.com, linux@armlinux.org.uk, rmk+kernel@armlinux.org.uk, maxime.chevallier@bootlin.com, boon.khai.ng@altera.com, rohan.g.thomas@altera.com, vladimir.oltean@nxp.com, hayashi.kunihiko@socionext.com, boon.leong.ong@intel.com, kim.tatt.chuah@intel.com Cc: netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-stm32@st-md-mailman.stormreply.com, linux-kernel@vger.kernel.org Subject: [PATCH net-next v2 4/5] net: stmmac: Add write_hw parameter to VLAN filter operations Date: Wed, 25 Feb 2026 14:24:13 +0000 Message-ID: <20260225142414.130144-5-ovidiu.panait.rb@renesas.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260225142414.130144-1-ovidiu.panait.rb@renesas.com> References: <20260225142414.130144-1-ovidiu.panait.rb@renesas.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add a write_hw parameter to the VLAN add/delete HW filter functions and to stmmac_vlan_update(). This flag controls whether the actual hardware register accesses are performed. When set to false, only the software state is updated. The next commit will use this to defer hardware writes when the interface is down. No functional change. Signed-off-by: Ovidiu Panait --- v2 changes: none. drivers/net/ethernet/stmicro/stmmac/hwif.h | 6 ++-- .../net/ethernet/stmicro/stmmac/stmmac_main.c | 25 +++++++++----- .../net/ethernet/stmicro/stmmac/stmmac_vlan.c | 34 ++++++++++++------- 3 files changed, 41 insertions(+), 24 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ether= net/stmicro/stmmac/hwif.h index 0db96a387259..d7598c76251f 100644 --- a/drivers/net/ethernet/stmicro/stmmac/hwif.h +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h @@ -647,10 +647,12 @@ struct stmmac_vlan_ops { void (*set_hw_vlan_mode)(struct mac_device_info *hw); int (*add_hw_vlan_rx_fltr)(struct net_device *dev, struct mac_device_info *hw, - __be16 proto, u16 vid); + __be16 proto, u16 vid, + bool write_hw); int (*del_hw_vlan_rx_fltr)(struct net_device *dev, struct mac_device_info *hw, - __be16 proto, u16 vid); + __be16 proto, u16 vid, + bool write_hw); void (*restore_hw_vlan_rx_fltr)(struct net_device *dev, struct mac_device_info *hw); }; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/ne= t/ethernet/stmicro/stmmac/stmmac_main.c index a02575f67057..19c86e3b42cc 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -6751,7 +6751,8 @@ static u32 stmmac_vid_crc32_le(__le16 vid_le) return crc; } =20 -static int stmmac_vlan_update(struct stmmac_priv *priv, bool is_double) +static int stmmac_vlan_update(struct stmmac_priv *priv, bool is_double, + bool write_hw) { u32 crc, hash =3D 0; u16 pmatch =3D 0; @@ -6773,7 +6774,11 @@ static int stmmac_vlan_update(struct stmmac_priv *pr= iv, bool is_double) hash =3D 0; } =20 - return stmmac_update_vlan_hash(priv, priv->hw, hash, pmatch, is_double); + if (write_hw) + return stmmac_update_vlan_hash(priv, priv->hw, hash, pmatch, + is_double); + + return 0; } =20 /* FIXME: This may need RXC to be running, but it may be called with BH @@ -6795,17 +6800,18 @@ static int stmmac_vlan_rx_add_vid(struct net_device= *ndev, __be16 proto, u16 vid =20 set_bit(vid, priv->active_vlans); num_double_vlans =3D priv->num_double_vlans + is_double; - ret =3D stmmac_vlan_update(priv, num_double_vlans); + ret =3D stmmac_vlan_update(priv, num_double_vlans, true); if (ret) { clear_bit(vid, priv->active_vlans); goto err_pm_put; } =20 if (priv->hw->num_vlan) { - ret =3D stmmac_add_hw_vlan_rx_fltr(priv, ndev, priv->hw, proto, vid); + ret =3D stmmac_add_hw_vlan_rx_fltr(priv, ndev, priv->hw, proto, + vid, true); if (ret) { clear_bit(vid, priv->active_vlans); - stmmac_vlan_update(priv, priv->num_double_vlans); + stmmac_vlan_update(priv, priv->num_double_vlans, true); goto err_pm_put; } } @@ -6837,17 +6843,18 @@ static int stmmac_vlan_rx_kill_vid(struct net_devic= e *ndev, __be16 proto, u16 vi =20 clear_bit(vid, priv->active_vlans); num_double_vlans =3D priv->num_double_vlans - is_double; - ret =3D stmmac_vlan_update(priv, num_double_vlans); + ret =3D stmmac_vlan_update(priv, num_double_vlans, true); if (ret) { set_bit(vid, priv->active_vlans); goto del_vlan_error; } =20 if (priv->hw->num_vlan) { - ret =3D stmmac_del_hw_vlan_rx_fltr(priv, ndev, priv->hw, proto, vid); + ret =3D stmmac_del_hw_vlan_rx_fltr(priv, ndev, priv->hw, proto, + vid, true); if (ret) { set_bit(vid, priv->active_vlans); - stmmac_vlan_update(priv, priv->num_double_vlans); + stmmac_vlan_update(priv, priv->num_double_vlans, true); goto del_vlan_error; } } @@ -6870,7 +6877,7 @@ static int stmmac_vlan_restore(struct stmmac_priv *pr= iv) if (priv->hw->num_vlan) stmmac_restore_hw_vlan_rx_fltr(priv, priv->dev, priv->hw); =20 - ret =3D stmmac_vlan_update(priv, priv->num_double_vlans); + ret =3D stmmac_vlan_update(priv, priv->num_double_vlans, true); if (ret) netdev_err(priv->dev, "Failed to restore VLANs\n"); =20 diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c b/drivers/ne= t/ethernet/stmicro/stmmac/stmmac_vlan.c index fcc34867405e..f81015179d04 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c @@ -53,7 +53,8 @@ static int vlan_write_filter(struct net_device *dev, =20 static int vlan_add_hw_rx_fltr(struct net_device *dev, struct mac_device_info *hw, - __be16 proto, u16 vid) + __be16 proto, u16 vid, + bool write_hw) { int index =3D -1; u32 val =3D 0; @@ -76,7 +77,8 @@ static int vlan_add_hw_rx_fltr(struct net_device *dev, } =20 hw->vlan_filter[0] =3D vid; - vlan_write_single(dev, vid); + if (write_hw) + vlan_write_single(dev, vid); =20 return 0; } @@ -97,17 +99,21 @@ static int vlan_add_hw_rx_fltr(struct net_device *dev, return -EPERM; } =20 - ret =3D vlan_write_filter(dev, hw, index, val); + if (write_hw) { + ret =3D vlan_write_filter(dev, hw, index, val); + if (ret) + return ret; + } =20 - if (!ret) - hw->vlan_filter[index] =3D val; + hw->vlan_filter[index] =3D val; =20 - return ret; + return 0; } =20 static int vlan_del_hw_rx_fltr(struct net_device *dev, struct mac_device_info *hw, - __be16 proto, u16 vid) + __be16 proto, u16 vid, + bool write_hw) { int i, ret =3D 0; =20 @@ -115,7 +121,8 @@ static int vlan_del_hw_rx_fltr(struct net_device *dev, if (hw->num_vlan =3D=3D 1) { if ((hw->vlan_filter[0] & VLAN_TAG_VID) =3D=3D vid) { hw->vlan_filter[0] =3D 0; - vlan_write_single(dev, 0); + if (write_hw) + vlan_write_single(dev, 0); } return 0; } @@ -124,12 +131,13 @@ static int vlan_del_hw_rx_fltr(struct net_device *dev, for (i =3D 0; i < hw->num_vlan; i++) { if ((hw->vlan_filter[i] & VLAN_TAG_DATA_VEN) && ((hw->vlan_filter[i] & VLAN_TAG_DATA_VID) =3D=3D vid)) { - ret =3D vlan_write_filter(dev, hw, i, 0); + if (write_hw) { + ret =3D vlan_write_filter(dev, hw, i, 0); + if (ret) + return ret; + } =20 - if (!ret) - hw->vlan_filter[i] =3D 0; - else - return ret; + hw->vlan_filter[i] =3D 0; } } =20 --=20 2.51.0 From nobody Tue Apr 7 12:38:52 2026 Received: from relmlie5.idc.renesas.com (relmlor1.renesas.com [210.160.252.171]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 2D5983D349B; Wed, 25 Feb 2026 14:24:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=210.160.252.171 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772029497; cv=none; b=QLCmP6DIZuNbyFbYwrlgQDkV4lYc41vmjrDQm2XXx8BCJJt1sEp54SzQbnmn3eSAhiXGJD2nSZGIVJK3ShGhPd5v7kMJv0JAelj30X4nSeKOS6U6VzutL9RYR10AXEc4MwhYD80zJxXPZhwXedPWKp/Xj4upXaJ3MeCAgIT+cqc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772029497; c=relaxed/simple; bh=+RmBZM1X2mmeQ5E0ux8AhVEjIHMn5mMEsxCjHMYhfOU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=TqL2ZpZGLivHnkTK0At7IaB4kUr5hZqcsNXOhdEVfMuo6AW5bZbEn/F1cIEni1/JGfG348hRe3KQOBqzlnBIm5vHYCb6FpJ6ML2jFNZz7pFIzrlkw8IVJ11fzu/hR3fsnZZovwkMh6smzoRD1TkztP/r3UMBqE70VM8Iq3IRKVI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=renesas.com; spf=pass smtp.mailfrom=renesas.com; arc=none smtp.client-ip=210.160.252.171 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=renesas.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=renesas.com X-CSE-ConnectionGUID: wjXg1zDVTHaep9JmLwo6EA== X-CSE-MsgGUID: pbnM9QIVQWudH1d9Ob5JRQ== Received: from unknown (HELO relmlir5.idc.renesas.com) ([10.200.68.151]) by relmlie5.idc.renesas.com with ESMTP; 25 Feb 2026 23:24:55 +0900 Received: from vm01.adwin.renesas.com (unknown [10.226.92.192]) by relmlir5.idc.renesas.com (Postfix) with ESMTP id B10104017D8D; Wed, 25 Feb 2026 23:24:49 +0900 (JST) From: Ovidiu Panait To: andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, mcoquelin.stm32@gmail.com, alexandre.torgue@foss.st.com, linux@armlinux.org.uk, rmk+kernel@armlinux.org.uk, maxime.chevallier@bootlin.com, boon.khai.ng@altera.com, rohan.g.thomas@altera.com, vladimir.oltean@nxp.com, hayashi.kunihiko@socionext.com, boon.leong.ong@intel.com, kim.tatt.chuah@intel.com Cc: netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-stm32@st-md-mailman.stormreply.com, linux-kernel@vger.kernel.org Subject: [PATCH net-next v2 5/5] net: stmmac: Defer VLAN HW configuration when interface is down Date: Wed, 25 Feb 2026 14:24:14 +0000 Message-ID: <20260225142414.130144-6-ovidiu.panait.rb@renesas.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260225142414.130144-1-ovidiu.panait.rb@renesas.com> References: <20260225142414.130144-1-ovidiu.panait.rb@renesas.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" VLAN register accesses on the MAC side require the PHY RX clock to be active. When the network interface is down, the PHY is suspended and the RX clock is unavailable, causing VLAN operations to fail with timeouts. The VLAN core automatically removes VID 0 after the interface goes down and re-adds it when it comes back up, so these timeouts happen during normal interface down/up: # ip link set end1 down renesas-gbeth 15c40000.ethernet end1: Timeout accessing MAC_VLAN_Tag_Fi= lter renesas-gbeth 15c40000.ethernet end1: failed to kill vid 0081/0 Adding VLANs while the interface is down also fails: # ip link add link end1 name end1.10 type vlan id 10 renesas-gbeth 15c40000.ethernet end1: Timeout accessing MAC_VLAN_Tag_Fi= lter RTNETLINK answers: Device or resource busy Use the write_hw parameter introduced in the previous commit to skip hardware register writes when the interface is down. The software state is always kept up to date regardless of interface state. When the interface is brought up, stmmac_vlan_restore() is called to write the VLAN state to hardware. Signed-off-by: Ovidiu Panait --- v2 changes: - Split this commit - added a new commit (3/5) which fixes VLAN restore on resume and open paths. - Dropped phylink_rx_clk_stop_block()/unblock() calls around VLAN restore. .../net/ethernet/stmicro/stmmac/stmmac_main.c | 16 ++++++++++------ .../net/ethernet/stmicro/stmmac/stmmac_vlan.c | 9 ++------- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/ne= t/ethernet/stmicro/stmmac/stmmac_main.c index 19c86e3b42cc..1098227272ed 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -6787,6 +6787,7 @@ static int stmmac_vlan_update(struct stmmac_priv *pri= v, bool is_double, static int stmmac_vlan_rx_add_vid(struct net_device *ndev, __be16 proto, u= 16 vid) { struct stmmac_priv *priv =3D netdev_priv(ndev); + bool write_hw =3D netif_running(ndev); unsigned int num_double_vlans; bool is_double =3D false; int ret; @@ -6800,7 +6801,7 @@ static int stmmac_vlan_rx_add_vid(struct net_device *= ndev, __be16 proto, u16 vid =20 set_bit(vid, priv->active_vlans); num_double_vlans =3D priv->num_double_vlans + is_double; - ret =3D stmmac_vlan_update(priv, num_double_vlans, true); + ret =3D stmmac_vlan_update(priv, num_double_vlans, write_hw); if (ret) { clear_bit(vid, priv->active_vlans); goto err_pm_put; @@ -6808,10 +6809,11 @@ static int stmmac_vlan_rx_add_vid(struct net_device= *ndev, __be16 proto, u16 vid =20 if (priv->hw->num_vlan) { ret =3D stmmac_add_hw_vlan_rx_fltr(priv, ndev, priv->hw, proto, - vid, true); + vid, write_hw); if (ret) { clear_bit(vid, priv->active_vlans); - stmmac_vlan_update(priv, priv->num_double_vlans, true); + stmmac_vlan_update(priv, priv->num_double_vlans, + write_hw); goto err_pm_put; } } @@ -6830,6 +6832,7 @@ static int stmmac_vlan_rx_add_vid(struct net_device *= ndev, __be16 proto, u16 vid static int stmmac_vlan_rx_kill_vid(struct net_device *ndev, __be16 proto, = u16 vid) { struct stmmac_priv *priv =3D netdev_priv(ndev); + bool write_hw =3D netif_running(ndev); unsigned int num_double_vlans; bool is_double =3D false; int ret; @@ -6843,7 +6846,7 @@ static int stmmac_vlan_rx_kill_vid(struct net_device = *ndev, __be16 proto, u16 vi =20 clear_bit(vid, priv->active_vlans); num_double_vlans =3D priv->num_double_vlans - is_double; - ret =3D stmmac_vlan_update(priv, num_double_vlans, true); + ret =3D stmmac_vlan_update(priv, num_double_vlans, write_hw); if (ret) { set_bit(vid, priv->active_vlans); goto del_vlan_error; @@ -6851,10 +6854,11 @@ static int stmmac_vlan_rx_kill_vid(struct net_devic= e *ndev, __be16 proto, u16 vi =20 if (priv->hw->num_vlan) { ret =3D stmmac_del_hw_vlan_rx_fltr(priv, ndev, priv->hw, proto, - vid, true); + vid, write_hw); if (ret) { set_bit(vid, priv->active_vlans); - stmmac_vlan_update(priv, priv->num_double_vlans, true); + stmmac_vlan_update(priv, priv->num_double_vlans, + write_hw); goto del_vlan_error; } } diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c b/drivers/ne= t/ethernet/stmicro/stmmac/stmmac_vlan.c index f81015179d04..261bc751ade2 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c @@ -147,7 +147,6 @@ static int vlan_del_hw_rx_fltr(struct net_device *dev, static void vlan_restore_hw_rx_fltr(struct net_device *dev, struct mac_device_info *hw) { - u32 val; int i; =20 /* Single Rx VLAN Filter */ @@ -157,12 +156,8 @@ static void vlan_restore_hw_rx_fltr(struct net_device = *dev, } =20 /* Extended Rx VLAN Filter Enable */ - for (i =3D 0; i < hw->num_vlan; i++) { - if (hw->vlan_filter[i] & VLAN_TAG_DATA_VEN) { - val =3D hw->vlan_filter[i]; - vlan_write_filter(dev, hw, i, val); - } - } + for (i =3D 0; i < hw->num_vlan; i++) + vlan_write_filter(dev, hw, i, hw->vlan_filter[i]); } =20 static void vlan_update_hash(struct mac_device_info *hw, u32 hash, --=20 2.51.0