[PATCH v2 net-next 09/13] net: enetc: move generic VLAN filter interfaces to enetc-core

Wei Fang
2025-01-13T08:40:27Z

For ENETC, each SI has a corresponding VLAN hash table. That is to say,
both PF and VFs can support VLAN filter. However, currently only ENETC v1
PF driver supports VLAN filter. In order to make i.MX95 ENETC (v4) PF and
VF drivers also support VLAN filter, some related macros are moved from
enetc_pf.h to enetc.h, and the related structure variables are moved from
enetc_pf to enetc_si.

Besides, enetc_vid_hash_idx() as a generic function is moved to enetc.c.
Extract enetc_refresh_vlan_ht_filter() from enetc_sync_vlan_ht_filter()
so that it can be shared by PF and VF drivers. This will make it easier
to add VLAN filter support for i.MX95 ENETC later.

Signed-off-by: Wei Fang <wei.fang@nxp.com>
---
drivers/net/ethernet/freescale/enetc/enetc.c | 25 ++++++++++
drivers/net/ethernet/freescale/enetc/enetc.h | 6 +++
.../net/ethernet/freescale/enetc/enetc_pf.c | 46 +++++--------------
.../net/ethernet/freescale/enetc/enetc_pf.h | 4 --
4 files changed, 42 insertions(+), 39 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c
index e27b031c4f46..8b4a004f51a4 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -72,6 +72,31 @@ void enetc_reset_mac_addr_filter(struct enetc_mac_filter *filter)
}
EXPORT_SYMBOL_GPL(enetc_reset_mac_addr_filter);

+int enetc_vid_hash_idx(unsigned int vid)
+{
+ int res = 0;
+ int i;
+
+ for (i = 0; i < 6; i++)
+ res |= (hweight8(vid & (BIT(i) | BIT(i + 6))) & 0x1) << i;
+
+ return res;
+}
+EXPORT_SYMBOL_GPL(enetc_vid_hash_idx);
+
+void enetc_refresh_vlan_ht_filter(struct enetc_si *si)
+{
+ int i;
+
+ bitmap_zero(si->vlan_ht_filter, ENETC_VLAN_HT_SIZE);
+ for_each_set_bit(i, si->active_vlans, VLAN_N_VID) {
+ int hidx = enetc_vid_hash_idx(i);
+
+ __set_bit(hidx, si->vlan_ht_filter);
+ }
+}
+EXPORT_SYMBOL_GPL(enetc_refresh_vlan_ht_filter);
+
static int enetc_num_stack_tx_queues(struct enetc_ndev_priv *priv)
{
int num_tx_rings = priv->num_tx_rings;
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h
index 2b0d27ed924d..0ecec9da6148 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -24,6 +24,7 @@
#define ENETC_CBD_DATA_MEM_ALIGN 64

#define ENETC_MADDR_HASH_TBL_SZ 64
+#define ENETC_VLAN_HT_SIZE 64

enum enetc_mac_addr_type {UC, MC, MADDR_TYPE};

@@ -321,6 +322,9 @@ struct enetc_si {
struct workqueue_struct *workqueue;
struct work_struct rx_mode_task;
struct dentry *debugfs_root;
+
+ DECLARE_BITMAP(vlan_ht_filter, ENETC_VLAN_HT_SIZE);
+ DECLARE_BITMAP(active_vlans, VLAN_N_VID);
};

#define ENETC_SI_ALIGN 32
@@ -506,6 +510,8 @@ int enetc_get_driver_data(struct enetc_si *si);
void enetc_add_mac_addr_ht_filter(struct enetc_mac_filter *filter,
const unsigned char *addr);
void enetc_reset_mac_addr_filter(struct enetc_mac_filter *filter);
+int enetc_vid_hash_idx(unsigned int vid);
+void enetc_refresh_vlan_ht_filter(struct enetc_si *si);

int enetc_open(struct net_device *ndev);
int enetc_close(struct net_device *ndev);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index 59039d087695..c0aaf6349b0b 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -222,45 +222,18 @@ static void enetc_set_vlan_ht_filter(struct enetc_hw *hw, int si_idx,
enetc_port_wr(hw, ENETC_PSIVHFR1(si_idx), upper_32_bits(hash));
}

-static int enetc_vid_hash_idx(unsigned int vid)
-{
- int res = 0;
- int i;
-
- for (i = 0; i < 6; i++)
- res |= (hweight8(vid & (BIT(i) | BIT(i + 6))) & 0x1) << i;
-
- return res;
-}
-
-static void enetc_sync_vlan_ht_filter(struct enetc_pf *pf, bool rehash)
-{
- int i;
-
- if (rehash) {
- bitmap_zero(pf->vlan_ht_filter, ENETC_VLAN_HT_SIZE);
-
- for_each_set_bit(i, pf->active_vlans, VLAN_N_VID) {
- int hidx = enetc_vid_hash_idx(i);
-
- __set_bit(hidx, pf->vlan_ht_filter);
- }
- }
-
- enetc_set_vlan_ht_filter(&pf->si->hw, 0, *pf->vlan_ht_filter);
-}
-
static int enetc_vlan_rx_add_vid(struct net_device *ndev, __be16 prot, u16 vid)
{
struct enetc_ndev_priv *priv = netdev_priv(ndev);
- struct enetc_pf *pf = enetc_si_priv(priv->si);
+ struct enetc_si *si = priv->si;
+ struct enetc_hw *hw = &si->hw;
int idx;

- __set_bit(vid, pf->active_vlans);
+ __set_bit(vid, si->active_vlans);

idx = enetc_vid_hash_idx(vid);
- if (!__test_and_set_bit(idx, pf->vlan_ht_filter))
- enetc_sync_vlan_ht_filter(pf, false);
+ if (!__test_and_set_bit(idx, si->vlan_ht_filter))
+ enetc_set_vlan_ht_filter(hw, 0, *si->vlan_ht_filter);

return 0;
}
@@ -268,10 +241,13 @@ static int enetc_vlan_rx_add_vid(struct net_device *ndev, __be16 prot, u16 vid)
static int enetc_vlan_rx_del_vid(struct net_device *ndev, __be16 prot, u16 vid)
{
struct enetc_ndev_priv *priv = netdev_priv(ndev);
- struct enetc_pf *pf = enetc_si_priv(priv->si);
+ struct enetc_si *si = priv->si;
+ struct enetc_hw *hw = &si->hw;

- __clear_bit(vid, pf->active_vlans);
- enetc_sync_vlan_ht_filter(pf, true);
+ if (__test_and_clear_bit(vid, si->active_vlans)) {
+ enetc_refresh_vlan_ht_filter(si);
+ enetc_set_vlan_ht_filter(hw, 0, *si->vlan_ht_filter);
+ }

return 0;
}
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.h b/drivers/net/ethernet/freescale/enetc/enetc_pf.h
index 916818d2fdb5..d56b381b9da9 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.h
@@ -6,8 +6,6 @@

#define ENETC_PF_NUM_RINGS 8

-#define ENETC_VLAN_HT_SIZE 64
-
enum enetc_vf_flags {
ENETC_VF_FLAG_PF_SET_MAC = BIT(0),
};
@@ -54,8 +52,6 @@ struct enetc_pf {
char msg_int_name[ENETC_INT_NAME_MAX];

char vlan_promisc_simap; /* bitmap of SIs in VLAN promisc mode */
- DECLARE_BITMAP(vlan_ht_filter, ENETC_VLAN_HT_SIZE);
- DECLARE_BITMAP(active_vlans, VLAN_N_VID);

struct mii_bus *mdio; /* saved for cleanup */
struct mii_bus *imdio;
--
2.34.1