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, linusw@kernel.org
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 v5 net-next 6/9] net: dsa: netc: check return value of ntmp_ipft_delete_entry()
Date: Mon, 12 Oct 2026 17:59:21 +0800 [thread overview]
Message-ID: <20261012095924.1129312-7-wei.fang@oss.nxp.com> (raw)
In-Reply-To: <20261012095924.1129312-1-wei.fang@oss.nxp.com>
From: Wei Fang <wei.fang@nxp.com>
The driver ignored the return value of ntmp_ipft_delete_entry(), so a
failed deletion left the IPFT entry untracked and impossible to clean
up later. IPFT is going to serve more features, such as trapping PTP
packets and flow policing, so make the deletion path robust to prepare
for these future uses.
To this end, propagate the error to the callers and update the driver
state only after the entry has really been deleted, so that the
software state always stays consistent with the hardware.
Once the deletion can fail, the order in which a rule is replaced also
needs to change. Since IPFT does not support in-place updates to the
KEYE element, replacing an existing rule requires deleting the old
entry and then adding the new one. Keeping the previous add-then-delete
order means that if the delete fails, a port would have to track two or
more stale host flood rules, which needlessly complicates the driver.
So switch to a delete-then-add order instead. This order is not
perfect: between the delete and the add there is a brief window in
which packets that would have matched the rule find no match and are
dropped. The window is very short and its impact is acceptable, so this
is a deliberate trade-off in favour of simpler software.
Note that, a delete failure has never been observed in practice and
is highly unlikely to happen, so this patch is an improvement over the
previous approach rather than a fix for an issue seen in the field.
Signed-off-by: Wei Fang <wei.fang@nxp.com>
---
drivers/net/dsa/netc/netc_main.c | 86 ++++++++++++++++++++------------
1 file changed, 55 insertions(+), 31 deletions(-)
diff --git a/drivers/net/dsa/netc/netc_main.c b/drivers/net/dsa/netc/netc_main.c
index e33a184fd005..09154781df7a 100644
--- a/drivers/net/dsa/netc/netc_main.c
+++ b/drivers/net/dsa/netc/netc_main.c
@@ -1796,14 +1796,8 @@ 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 (!uc && !mc)
return 0;
- }
host_flood = kzalloc_obj(*host_flood);
if (!host_flood)
@@ -1851,32 +1845,32 @@ 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;
+ int retry_num = 0;
/* Do not add host flood rule to ingress port filter table when
* the port has joined a bridge. Otherwise, the ingress frames
@@ -1884,7 +1878,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 %d\n",
+ port);
return;
}
@@ -1893,19 +1892,33 @@ 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_add_host_flood_rule(np, uc, mc)) {
- dev_err(ds->dev, "Failed to add host flood rule on port %d\n",
+ if (netc_port_remove_host_flood(np)) {
+ dev_err(ds->dev,
+ "Failed to delete old host flood rule on port %d\n",
port);
+
return;
}
- /* Remove the old host flood entry */
- netc_port_remove_host_flood(np, old_entry_id);
+ /* Restoring the previous configuration is pointless because
+ * .port_set_host_flood() returns void, so the upper layer cannot
+ * detect the error and the RX flags have changed. Furthermore, we
+ * cannot guarantee that we can successfully restore the previous
+ * state.
+ */
+retry:
+ if (netc_port_add_host_flood_rule(np, uc, mc)) {
+ if (retry_num++ < 2) {
+ usleep_range(100, 110);
+ goto retry;
+ }
+
+ dev_err(ds->dev,
+ "Failed to add host flood rule on port %d\n", port);
+ }
}
static int netc_single_vlan_aware_bridge(struct dsa_switch *ds,
@@ -2070,6 +2083,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) {
@@ -2081,6 +2096,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))
@@ -2094,8 +2115,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));
@@ -2105,6 +2124,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 %d\n",
+ port);
+
return err;
}
--
2.34.1
next prev parent reply other threads:[~2026-10-12 9:55 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-12 9:59 [PATCH v5 net-next 0/9] net: dsa: netc: add PTP support for NETC switch wei.fang
2026-10-12 9:59 ` [PATCH v5 net-next 1/9] ptp: netc: use ioread64_lo_hi/iowrite64_lo_hi for 64-bit register access wei.fang
2026-10-12 9:59 ` [PATCH v5 net-next 2/9] ptp: netc: remove unnecessary pcie_flr() call in probe wei.fang
2026-10-12 9:59 ` [PATCH v5 net-next 3/9] ptp: netc: export netc_timer_get_current_time() for cross-driver use wei.fang
2026-10-12 9:59 ` [PATCH v5 net-next 4/9] net: dsa: netc: tie setup resources and reset to DSA setup/teardown wei.fang
2026-10-12 9:59 ` [PATCH v5 net-next 5/9] net: dsa: netc: use entry ID instead of pointer to track host flood rule wei.fang
2026-10-12 9:59 ` wei.fang [this message]
2026-10-12 9:59 ` [PATCH v5 net-next 7/9] net: dsa: netc: enable ingress port filtering lookup by default wei.fang
2026-10-12 9:59 ` [PATCH v5 net-next 8/9] net: dsa: netc: add PTP two-step timestamping support wei.fang
2026-10-12 9:59 ` [PATCH v5 net-next 9/9] net: dsa: netc: add PTP one-step " 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=20261012095924.1129312-7-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=linusw@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
all inboxes | Powered by JetHome®