@@ -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;
@@ -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);
@@ -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;
}
@@ -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;
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(-)