Netdev List
 help / color / mirror / Atom feed
From: wei.fang@oss.nxp.com
To: xiaoning.wang@nxp.com, andrew@lunn.ch, olteanv@gmail.com,
	andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com,
	kuba@kernel.org, pabeni@redhat.com, horms@kernel.org,
	richardcochran@gmail.com
Cc: wei.fang@nxp.com, imx@lists.linux.dev, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org, linuxppc-dev@lists.ozlabs.org,
	linux-arm-kernel@lists.infradead.org
Subject: [PATCH v3 net-next 5/8] net: dsa: netc: check return value of ntmp_ipft_delete_entry()
Date: Mon, 31 Aug 2026 16:23:32 +0800	[thread overview]
Message-ID: <20260831082335.1184605-6-wei.fang@oss.nxp.com> (raw)
In-Reply-To: <20260831082335.1184605-1-wei.fang@oss.nxp.com>

From: Wei Fang <wei.fang@nxp.com>

ntmp_ipft_delete_entry() can fail, e.g. when DMA memory allocation fails.
The driver previously ignored the return value, so a failed deletion
would leave the IPFT entry untracked and impossible to clean up later.

Convert netc_port_remove_host_flood() from void to int and propagate the
error to all callers. In netc_port_add_host_flood_rule(), delete the old
entry before adding the new one, and guard against adding a new entry
when the old one still exists. In netc_port_set_host_flood() and
netc_port_bridge_join(), handle deletion failures and add rollback paths
to restore the host flood entry on error.

Note that the rollback itself may also fail, in which case there is
nothing more the driver can do. This is an acceptable limitation because
such failures only occur under resource exhaustion conditions that are
already abnormal, and the host flood feature is not critical to basic
packet forwarding.

Signed-off-by: Wei Fang <wei.fang@nxp.com>
---
 drivers/net/dsa/netc/netc_main.c | 93 ++++++++++++++++++++++----------
 1 file changed, 64 insertions(+), 29 deletions(-)

diff --git a/drivers/net/dsa/netc/netc_main.c b/drivers/net/dsa/netc/netc_main.c
index d326a00104e1..2171c83f3640 100644
--- a/drivers/net/dsa/netc/netc_main.c
+++ b/drivers/net/dsa/netc/netc_main.c
@@ -1707,15 +1707,23 @@ static int netc_port_add_host_flood_rule(struct netc_port *np,
 	u32 cfg;
 	int err;
 
-	if (!uc && !mc) {
-		/* Disable ingress port filter table lookup */
-		netc_port_wr(np, NETC_PIPFCR, 0);
-		np->uc = false;
-		np->mc = false;
+	if (np->ipft_hf_eid != NTMP_NULL_ENTRY_ID) {
+		/* The old rule is the same as the new rule, return directly.
+		 * But if the existing rule differs from the requested one,
+		 * return an error.
+		 */
+		if (np->uc == uc && np->mc == mc)
+			return 0;
 
-		return 0;
+		dev_err(priv->dev,
+			"The old host flood rule has not been removed from port %u\n",
+			np->dp->index);
+		return -EINVAL;
 	}
 
+	if (!uc && !mc)
+		return 0;
+
 	host_flood = kzalloc_obj(*host_flood);
 	if (!host_flood)
 		return -ENOMEM;
@@ -1762,32 +1770,33 @@ static int netc_port_add_host_flood_rule(struct netc_port *np,
 	return err;
 }
 
-static void netc_port_remove_host_flood(struct netc_port *np, u32 entry_id)
+static int netc_port_remove_host_flood(struct netc_port *np)
 {
 	struct netc_switch *priv = np->switch_priv;
-	bool disable_host_flood = false;
+	u32 entry_id = np->ipft_hf_eid;
+	int err;
 
 	if (entry_id == NTMP_NULL_ENTRY_ID)
-		return;
+		return 0;
 
-	if (np->ipft_hf_eid == entry_id)
-		disable_host_flood = true;
+	err = ntmp_ipft_delete_entry(&priv->ntmp, entry_id);
+	if (err)
+		return err;
 
-	ntmp_ipft_delete_entry(&priv->ntmp, entry_id);
+	np->ipft_hf_eid = NTMP_NULL_ENTRY_ID;
+	np->uc = false;
+	np->mc = false;
+	netc_port_wr(np, NETC_PIPFCR, 0);
 
-	if (disable_host_flood) {
-		np->ipft_hf_eid = NTMP_NULL_ENTRY_ID;
-		np->uc = false;
-		np->mc = false;
-		netc_port_wr(np, NETC_PIPFCR, 0);
-	}
+	return 0;
 }
 
 static void netc_port_set_host_flood(struct dsa_switch *ds, int port,
 				     bool uc, bool mc)
 {
 	struct netc_port *np = NETC_PORT(ds, port);
-	u32 old_entry_id;
+	bool old_uc = np->uc;
+	bool old_mc = np->mc;
 
 	/* Do not add host flood rule to ingress port filter table when
 	 * the port has joined a bridge. Otherwise, the ingress frames
@@ -1795,7 +1804,12 @@ static void netc_port_set_host_flood(struct dsa_switch *ds, int port,
 	 * will be redirected directly to the CPU port.
 	 */
 	if (dsa_port_bridge_dev_get(np->dp)) {
-		netc_port_remove_host_flood(np, np->ipft_hf_eid);
+		if (!netc_port_remove_host_flood(np))
+			return;
+
+		dev_err(ds->dev,
+			"Failed to delete host flood rule on bridge port %u\n",
+			port);
 
 		return;
 	}
@@ -1804,19 +1818,29 @@ static void netc_port_set_host_flood(struct dsa_switch *ds, int port,
 		return;
 
 	/* IPFT does not support in-place updates to the KEYE element,
-	 * we need to add a new entry and then delete the old one. So
-	 * save the old entry ID first.
+	 * we need to delete the old one and then add the new rule. If
+	 * the deletion fails, return immediately.
 	 */
-	old_entry_id = np->ipft_hf_eid;
+	if (netc_port_remove_host_flood(np)) {
+		dev_err(ds->dev,
+			"Failed to delete old host flood rule on port %u\n",
+			port);
+
+		return;
+	}
 
 	if (netc_port_add_host_flood_rule(np, uc, mc)) {
 		dev_err(ds->dev, "Failed to add host flood rule on port %d\n",
 			port);
-		return;
-	}
 
-	/* Remove the old host flood entry */
-	netc_port_remove_host_flood(np, old_entry_id);
+		/* Try to restore the old flood rule, if the recovery fails,
+		 * there is nothing else we can do; this is a limitation.
+		 */
+		if (netc_port_add_host_flood_rule(np, old_uc, old_mc))
+			dev_err(ds->dev,
+				"Failed to restore host flood rule on port %d\n",
+				port);
+	}
 }
 
 static int netc_single_vlan_aware_bridge(struct dsa_switch *ds,
@@ -1981,6 +2005,8 @@ static int netc_port_bridge_join(struct dsa_switch *ds, int port,
 	struct netc_port *np = NETC_PORT(ds, port);
 	struct netc_switch *priv = ds->priv;
 	u16 vlan_unaware_pvid;
+	bool uc = np->uc;
+	bool mc = np->mc;
 	int err;
 
 	if (!bridge.num) {
@@ -1992,6 +2018,12 @@ static int netc_port_bridge_join(struct dsa_switch *ds, int port,
 	if (err)
 		return err;
 
+	err = netc_port_remove_host_flood(np);
+	if (err) {
+		NL_SET_ERR_MSG_MOD(extack, "Failed to delete host flood rule");
+		return err;
+	}
+
 	netc_port_set_mlo(np, MLO_NOT_OVERRIDE);
 
 	if (br_vlan_enabled(bridge.dev))
@@ -2005,8 +2037,6 @@ static int netc_port_bridge_join(struct dsa_switch *ds, int port,
 	netc_port_set_pvid(np, vlan_unaware_pvid);
 
 out:
-	netc_port_remove_host_flood(np, np->ipft_hf_eid);
-
 	if (atomic_inc_return(&priv->br_cnt) == 1)
 		schedule_delayed_work(&priv->fdbt_ageing_work,
 				      READ_ONCE(priv->fdbt_ageing_delay));
@@ -2016,6 +2046,11 @@ static int netc_port_bridge_join(struct dsa_switch *ds, int port,
 disable_mlo:
 	netc_port_set_mlo(np, MLO_DISABLE);
 
+	if (netc_port_add_host_flood_rule(np, uc, mc))
+		dev_err(ds->dev,
+			"Failed to restore host flood rule on port %u\n",
+			port);
+
 	return err;
 }
 
-- 
2.34.1


  parent reply	other threads:[~2026-08-31  8:20 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-31  8:23 [PATCH v3 net-next 0/8] net: dsa: netc: add PTP support for NETC switch wei.fang
2026-08-31  8:23 ` [PATCH v3 net-next 1/8] ptp: netc: use ioread64_lo_hi/iowrite64_lo_hi for 64-bit register access wei.fang
     [not found]   ` <20260901082024.E6F931F000E9@smtp.kernel.org>
2026-09-02  1:56     ` Wei Fang (OSS)
2026-08-31  8:23 ` [PATCH v3 net-next 2/8] ptp: netc: remove unnecessary pcie_flr() call in probe wei.fang
2026-08-31  8:23 ` [PATCH v3 net-next 3/8] ptp: netc: export netc_timer_get_current_time() for cross-driver use wei.fang
     [not found]   ` <20260901082025.AF94B1F00A3D@smtp.kernel.org>
2026-09-02  2:02     ` Wei Fang (OSS)
2026-08-31  8:23 ` [PATCH v3 net-next 4/8] net: dsa: netc: use entry ID instead of pointer to track host flood rule wei.fang
2026-08-31  8:23 ` wei.fang [this message]
2026-08-31  8:23 ` [PATCH v3 net-next 6/8] net: dsa: netc: enable ingress port filtering lookup by default wei.fang
2026-08-31  8:23 ` [PATCH v3 net-next 7/8] net: dsa: netc: add PTP two-step timestamping support wei.fang
     [not found]   ` <20260901082026.7F3911F00A3E@smtp.kernel.org>
2026-09-02  2:12     ` Wei Fang (OSS)
2026-08-31  8:23 ` [PATCH v3 net-next 8/8] net: dsa: netc: add PTP one-step " wei.fang
     [not found]   ` <20260901082027.461281F00A3F@smtp.kernel.org>
2026-09-02  3:00     ` Wei Fang (OSS)
2026-09-02  3:05     ` Wei Fang (OSS)
2026-09-01 15:09 ` [PATCH v3 net-next 0/8] net: dsa: netc: add PTP support for NETC switch Jakub Kicinski
2026-09-02  1:43   ` Wei Fang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260831082335.1184605-6-wei.fang@oss.nxp.com \
    --to=wei.fang@oss.nxp.com \
    --cc=andrew+netdev@lunn.ch \
    --cc=andrew@lunn.ch \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=horms@kernel.org \
    --cc=imx@lists.linux.dev \
    --cc=kuba@kernel.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linuxppc-dev@lists.ozlabs.org \
    --cc=netdev@vger.kernel.org \
    --cc=olteanv@gmail.com \
    --cc=pabeni@redhat.com \
    --cc=richardcochran@gmail.com \
    --cc=wei.fang@nxp.com \
    --cc=xiaoning.wang@nxp.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox