From: wei.fang@oss.nxp.com
To: claudiu.manoil@nxp.com, vladimir.oltean@nxp.com,
xiaoning.wang@nxp.com, andrew+netdev@lunn.ch,
davem@davemloft.net, edumazet@google.com, kuba@kernel.org,
pabeni@redhat.com, linux@armlinux.org.uk, wei.fang@nxp.com,
chleroy@kernel.org
Cc: 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 net-next 04/14] net: enetc: improve MAFT entry management with bitmap tracking
Date: Tue, 30 Jun 2026 15:20:26 +0800 [thread overview]
Message-ID: <20260630072036.382761-5-wei.fang@oss.nxp.com> (raw)
In-Reply-To: <20260630072036.382761-1-wei.fang@oss.nxp.com>
From: Wei Fang <wei.fang@nxp.com>
Replace the counter-based MAFT entry tracking (num_mfe/mac_filter_num)
with a bitmap (maft_eid_bitmap) stored in struct ntmp_user, which is a
more appropriate place for NTMP resource management.
The bitmap approach brings two improvements. First, the entry deletion
in enetc4_pf_clear_maft_entries() now checks the return value of
ntmp_maft_delete_entry() and only clears the corresponding bit on
success, keeping hardware and software state in sync. Previously, the
counter was reset unconditionally regardless of whether the hardware
deletion actually succeeded.
Second, entry allocation in enetc4_pf_add_maft_entries() uses
ntmp_lookup_free_eid() to find available IDs dynamically, with an
upfront capacity check via bitmap_weight() to avoid partial failures.
The MAFT entry count is moved into ntmp_user.maft_num_entries and
initialized once during enetc4_init_ntmp_user(). Helper functions
enetc4_ntmp_bitmap_init() and enetc4_ntmp_bitmap_free() manage the
bitmap lifetime. The debugfs show function is updated accordingly to
iterate over set bits under rtnl_lock().
Signed-off-by: Wei Fang <wei.fang@nxp.com>
---
.../ethernet/freescale/enetc/enetc4_debugfs.c | 30 ++++--
.../net/ethernet/freescale/enetc/enetc4_pf.c | 95 ++++++++++++++-----
.../net/ethernet/freescale/enetc/enetc_pf.h | 3 -
include/linux/fsl/ntmp.h | 2 +
4 files changed, 95 insertions(+), 35 deletions(-)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c b/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c
index 1b1591dce73d..4a769d9e5679 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c
@@ -31,9 +31,11 @@ static int enetc_mac_filter_show(struct seq_file *s, void *data)
struct enetc_si *si = s->private;
struct enetc_hw *hw = &si->hw;
struct maft_entry_data maft;
+ struct ntmp_user *user;
struct enetc_pf *pf;
- int i, err, num_si;
- u32 val;
+ u32 val, entry_id;
+ int i, num_si;
+ int err = 0;
pf = enetc_si_priv(si);
num_si = pf->caps.num_vsi + 1;
@@ -50,22 +52,30 @@ static int enetc_mac_filter_show(struct seq_file *s, void *data)
for (i = 0; i < num_si; i++)
enetc_show_si_mac_hash_filter(s, i);
- if (!pf->num_mfe)
- return 0;
+ user = &si->ntmp_user;
+ rtnl_lock();
+
+ if (bitmap_empty(user->maft_eid_bitmap, user->maft_num_entries))
+ goto unlock_rtnl;
/* MAC address filter table */
seq_puts(s, "MAC address filter table\n");
- for (i = 0; i < pf->num_mfe; i++) {
+ for_each_set_bit(entry_id, user->maft_eid_bitmap,
+ user->maft_num_entries) {
memset(&maft, 0, sizeof(maft));
- err = ntmp_maft_query_entry(&si->ntmp_user, i, &maft);
+ err = ntmp_maft_query_entry(user, entry_id, &maft);
if (err)
- return err;
+ goto unlock_rtnl;
- seq_printf(s, "Entry %d, MAC: %pM, SI bitmap: 0x%04x\n", i,
- maft.keye.mac_addr, le16_to_cpu(maft.cfge.si_bitmap));
+ seq_printf(s, "Entry %d, MAC: %pM, SI bitmap: 0x%04x\n",
+ entry_id, maft.keye.mac_addr,
+ le16_to_cpu(maft.cfge.si_bitmap));
}
- return 0;
+unlock_rtnl:
+ rtnl_unlock();
+
+ return err;
}
DEFINE_SHOW_ATTRIBUTE(enetc_mac_filter);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
index a02b01753ff2..4143438ea7a7 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -32,9 +32,6 @@ static void enetc4_get_port_caps(struct enetc_pf *pf)
val = enetc_port_rd(hw, ENETC4_PMCAPR);
pf->caps.half_duplex = (val & PMCAPR_HD) ? 1 : 0;
-
- val = enetc_port_rd(hw, ENETC4_PSIMAFCAPR);
- pf->caps.mac_filter_num = val & PSIMAFCAPR_NUM_MAC_AFTE;
}
static void enetc4_get_psi_hw_features(struct enetc_si *si)
@@ -92,31 +89,45 @@ static void enetc4_pf_set_loopback(struct net_device *ndev, bool en)
static void enetc4_pf_clear_maft_entries(struct enetc_pf *pf)
{
- int i;
+ struct ntmp_user *user = &pf->si->ntmp_user;
+ u32 entry_id;
- for (i = 0; i < pf->num_mfe; i++)
- ntmp_maft_delete_entry(&pf->si->ntmp_user, i);
-
- pf->num_mfe = 0;
+ for_each_set_bit(entry_id, user->maft_eid_bitmap,
+ user->maft_num_entries) {
+ if (!ntmp_maft_delete_entry(user, entry_id))
+ ntmp_clear_eid_bitmap(user->maft_eid_bitmap, entry_id);
+ }
}
static int enetc4_pf_add_maft_entries(struct enetc_pf *pf,
struct netdev_hw_addr_list *uc)
{
+ struct ntmp_user *user = &pf->si->ntmp_user;
+ int mac_cnt = netdev_hw_addr_list_count(uc);
struct maft_entry_data maft = {};
struct netdev_hw_addr *ha;
+ u32 available_entries;
u16 si_bit = BIT(0);
+ u32 entry_id;
int err;
+ available_entries = user->maft_num_entries -
+ bitmap_weight(user->maft_eid_bitmap,
+ user->maft_num_entries);
+
+ if (mac_cnt > available_entries)
+ return -ENOSPC;
+
maft.cfge.si_bitmap = cpu_to_le16(si_bit);
netdev_hw_addr_list_for_each(ha, uc) {
+ entry_id = ntmp_lookup_free_eid(user->maft_eid_bitmap,
+ user->maft_num_entries);
ether_addr_copy(maft.keye.mac_addr, ha->addr);
- err = ntmp_maft_add_entry(&pf->si->ntmp_user, pf->num_mfe,
- &maft);
- if (unlikely(err))
+ err = ntmp_maft_add_entry(user, entry_id, &maft);
+ if (unlikely(err)) {
+ ntmp_clear_eid_bitmap(user->maft_eid_bitmap, entry_id);
goto clear_maft_entries;
-
- pf->num_mfe++;
+ }
}
return 0;
@@ -146,10 +157,10 @@ static void enetc4_pf_set_uc_hash_filter(struct enetc_pf *pf,
static int enetc4_pf_set_uc_exact_filter(struct enetc_pf *pf,
struct netdev_hw_addr_list *uc)
{
- int mac_cnt = netdev_hw_addr_list_count(uc);
struct enetc_si *si = pf->si;
+ int err;
- if (!mac_cnt) {
+ if (netdev_hw_addr_list_empty(uc)) {
/* clear both MAC hash and exact filters */
enetc_set_si_uc_hash_filter(si, 0, 0);
enetc4_pf_clear_maft_entries(pf);
@@ -157,21 +168,19 @@ static int enetc4_pf_set_uc_exact_filter(struct enetc_pf *pf,
return 0;
}
- if (mac_cnt > pf->caps.mac_filter_num)
- return -ENOSPC;
-
- /* Set temporary unicast hash filters in case of Rx loss when
+ /* Set temporary unicast hash filter in case of Rx loss when
* updating MAC address filter table
*/
enetc4_pf_set_uc_hash_filter(pf, uc);
enetc4_pf_clear_maft_entries(pf);
- if (!enetc4_pf_add_maft_entries(pf, uc)) {
+ err = enetc4_pf_add_maft_entries(pf, uc);
+ if (!err) {
enetc_reset_mac_addr_filter(&pf->mac_filter[UC]);
enetc_set_si_uc_hash_filter(si, 0, 0);
}
- return 0;
+ return err;
}
static void enetc4_pf_set_mc_hash_filter(struct enetc_pf *pf,
@@ -393,18 +402,60 @@ static void enetc4_configure_port(struct enetc_pf *pf)
enetc_set_default_rss_key(pf);
}
+static void enetc4_get_ntmp_caps(struct enetc_si *si)
+{
+ struct ntmp_user *user = &si->ntmp_user;
+ struct enetc_hw *hw = &si->hw;
+ u32 val;
+
+ val = enetc_port_rd(hw, ENETC4_PSIMAFCAPR);
+ user->maft_num_entries = FIELD_GET(PSIMAFCAPR_NUM_MAC_AFTE, val);
+}
+
+static int enetc4_ntmp_bitmap_init(struct ntmp_user *user)
+{
+ user->maft_eid_bitmap = bitmap_zalloc(user->maft_num_entries,
+ GFP_KERNEL);
+ if (!user->maft_eid_bitmap)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static void enetc4_ntmp_bitmap_free(struct ntmp_user *user)
+{
+ bitmap_free(user->maft_eid_bitmap);
+ user->maft_eid_bitmap = NULL;
+}
+
static int enetc4_init_ntmp_user(struct enetc_si *si)
{
struct ntmp_user *user = &si->ntmp_user;
+ int err;
/* For ENETC 4.1, all table versions are 0 */
memset(&user->tbl, 0, sizeof(user->tbl));
- return enetc4_setup_cbdr(si);
+ err = enetc4_setup_cbdr(si);
+ if (err)
+ return err;
+
+ enetc4_get_ntmp_caps(si);
+ err = enetc4_ntmp_bitmap_init(user);
+ if (err)
+ goto teardown_cbdr;
+
+ return 0;
+
+teardown_cbdr:
+ enetc4_teardown_cbdr(si);
+
+ return err;
}
static void enetc4_free_ntmp_user(struct enetc_si *si)
{
+ enetc4_ntmp_bitmap_free(&si->ntmp_user);
enetc4_teardown_cbdr(si);
}
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.h b/drivers/net/ethernet/freescale/enetc/enetc_pf.h
index 285b7e5c48fd..6f15f9ea1664 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.h
@@ -22,7 +22,6 @@ struct enetc_port_caps {
int num_msix;
int num_rx_bdr;
int num_tx_bdr;
- int mac_filter_num;
};
struct enetc_pf;
@@ -60,8 +59,6 @@ struct enetc_pf {
struct enetc_port_caps caps;
const struct enetc_pf_ops *ops;
-
- int num_mfe; /* number of mac address filter table entries */
};
#define phylink_to_enetc_pf(config) \
diff --git a/include/linux/fsl/ntmp.h b/include/linux/fsl/ntmp.h
index d3b6c476b91a..764ef2892608 100644
--- a/include/linux/fsl/ntmp.h
+++ b/include/linux/fsl/ntmp.h
@@ -75,8 +75,10 @@ struct ntmp_user {
/* NTMP table bitmaps for resource management */
u32 ett_bitmap_size;
u32 ect_bitmap_size;
+ u16 maft_num_entries;
unsigned long *ett_gid_bitmap; /* only valid for switch */
unsigned long *ect_gid_bitmap; /* only valid for switch */
+ unsigned long *maft_eid_bitmap; /* only valid for ENETC */
};
struct maft_entry_data {
--
2.34.1
next prev parent reply other threads:[~2026-06-30 7:49 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-30 7:20 [PATCH net-next 00/14] net: enetc: cleanups and improvements wei.fang
2026-06-30 7:20 ` [PATCH net-next 01/14] net: enetc: extract common helpers for MAC promiscuous mode setting wei.fang
2026-06-30 7:20 ` [PATCH net-next 02/14] net: enetc: extract common helpers for MAC hash filter configuration wei.fang
2026-06-30 7:20 ` [PATCH net-next 03/14] net: enetc: convert ndo_set_rx_mode() to ndo_set_rx_mode_async() wei.fang
2026-06-30 7:20 ` wei.fang [this message]
2026-06-30 7:20 ` [PATCH net-next 05/14] net: enetc: use PCI device name for debugfs directory wei.fang
2026-06-30 7:20 ` [PATCH net-next 06/14] net: enetc: simplify enetc4_set_port_speed() wei.fang
2026-06-30 7:20 ` [PATCH net-next 07/14] net: enetc: differentiate phylink capabilities for pseudo-MAC and standalone MAC wei.fang
2026-06-30 7:20 ` [PATCH net-next 08/14] net: enetc: remove invalid code from enetc4_pl_mac_link_up() wei.fang
2026-06-30 7:20 ` [PATCH net-next 09/14] net: enetc: remove enetc4_set_default_si_vlan_promisc() wei.fang
2026-06-30 7:20 ` [PATCH net-next 10/14] net: enetc: refactor SI VLAN promiscuous mode configuration wei.fang
2026-06-30 7:20 ` [PATCH net-next 11/14] net: enetc: move enetc_set_si_vlan_promisc() to enetc_pf_common.c wei.fang
2026-06-30 7:20 ` [PATCH net-next 12/14] net: enetc: remove redundant num_vsi field from enetc_port_caps wei.fang
2026-06-30 7:20 ` [PATCH net-next 13/14] net: enetc: use alloc_etherdev_mqs() to create netdev for VF driver wei.fang
2026-06-30 7:20 ` [PATCH net-next 14/14] net: enetc: use kzalloc_flex() for enetc_psfp_gate allocation 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=20260630072036.382761-5-wei.fang@oss.nxp.com \
--to=wei.fang@oss.nxp.com \
--cc=andrew+netdev@lunn.ch \
--cc=chleroy@kernel.org \
--cc=claudiu.manoil@nxp.com \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=imx@lists.linux.dev \
--cc=kuba@kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux@armlinux.org.uk \
--cc=linuxppc-dev@lists.ozlabs.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=vladimir.oltean@nxp.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