| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/07/20 03:00 | flow | patch-triage |
6mArgs:null Results: {
"EnableConfigs": [
"FSL_ENETC",
"NXP_ENETC4",
"FSL_ENETC_VF",
"FSL_ENETC_QOS"
],
"FocusSymbols": [
"enetc4_pf_set_rx_mode",
"enetc_pf_set_rx_mode",
"enetc4_pf_set_mac_filter",
"enetc4_pf_set_uc_exact_filter",
"enetc4_pf_add_maft_entries",
"enetc_sync_mac_filters",
"enetc_set_si_uc_promisc",
"enetc_set_si_mc_promisc",
"enetc_set_si_uc_hash_filter",
"enetc_set_si_mc_hash_filter",
"enetc_set_si_vlan_promisc"
],
"Reasoning": "The patch refactors the ENETC driver to use the new `ndo_set_rx_mode_async` net_device_ops member instead of a custom workqueue for setting the RX mode. It also modifies MAC and VLAN filtering logic in the PF drivers (`enetc4_pf.c` and `enetc_pf.c`), and introduces common helper functions for promiscuous mode and hash filters. These are functional changes to reachable core driver logic that should be fuzzed.",
"WorthFuzzing": true
} |
| 1/1 | 2026/07/20 03:00 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit 6b139e472d90a78aed30ada2261574adee2c2966\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Mon Jul 20 03:00:13 2026 +0000\n\n syz-cluster: applied patch under review\n\ndiff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h\nindex 04a5dd5ea6c74c..8839cfb49bcfe8 100644\n--- a/drivers/net/ethernet/freescale/enetc/enetc.h\n+++ b/drivers/net/ethernet/freescale/enetc/enetc.h\n@@ -1,5 +1,5 @@\n /* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */\n-/* Copyright 2017-2019 NXP */\n+/* Copyright 2017-2019, 2025-2026 NXP */\n \n #include \u003clinux/timer.h\u003e\n #include \u003clinux/pci.h\u003e\n@@ -324,8 +324,6 @@ struct enetc_si {\n \tconst struct enetc_drvdata *drvdata;\n \tconst struct enetc_si_ops *ops;\n \n-\tstruct workqueue_struct *workqueue;\n-\tstruct work_struct rx_mode_task;\n \tstruct dentry *debugfs_root;\n \tstruct enetc_msg_swbd msg; /* Only valid for VSI */\n };\ndiff --git a/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c b/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c\nindex 1b1591dce73d4b..5029038bf99faa 100644\n--- a/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c\n+++ b/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c\n@@ -28,15 +28,14 @@ static void enetc_show_si_mac_hash_filter(struct seq_file *s, int i)\n \n static int enetc_mac_filter_show(struct seq_file *s, void *data)\n {\n-\tstruct enetc_si *si = s-\u003eprivate;\n-\tstruct enetc_hw *hw = \u0026si-\u003ehw;\n+\tstruct enetc_pf *pf = enetc_si_priv(s-\u003eprivate);\n+\tstruct enetc_hw *hw = \u0026pf-\u003esi-\u003ehw;\n+\tint num_si = pf-\u003etotal_vfs + 1;\n \tstruct maft_entry_data maft;\n-\tstruct enetc_pf *pf;\n-\tint i, err, num_si;\n-\tu32 val;\n-\n-\tpf = enetc_si_priv(si);\n-\tnum_si = pf-\u003ecaps.num_vsi + 1;\n+\tstruct ntmp_user *user;\n+\tu32 val, entry_id;\n+\tint err = 0;\n+\tint i;\n \n \tval = enetc_port_rd(hw, ENETC4_PSIPMMR);\n \tfor (i = 0; i \u003c num_si; i++) {\n@@ -50,31 +49,38 @@ static int enetc_mac_filter_show(struct seq_file *s, void *data)\n \tfor (i = 0; i \u003c num_si; i++)\n \t\tenetc_show_si_mac_hash_filter(s, i);\n \n-\tif (!pf-\u003enum_mfe)\n-\t\treturn 0;\n+\tuser = \u0026pf-\u003esi-\u003entmp_user;\n+\trtnl_lock();\n+\n+\tif (bitmap_empty(user-\u003emaft_eid_bitmap, user-\u003emaft_num_entries))\n+\t\tgoto unlock_rtnl;\n \n \t/* MAC address filter table */\n \tseq_puts(s, \"MAC address filter table\\n\");\n-\tfor (i = 0; i \u003c pf-\u003enum_mfe; i++) {\n+\tfor_each_set_bit(entry_id, user-\u003emaft_eid_bitmap,\n+\t\t\t user-\u003emaft_num_entries) {\n \t\tmemset(\u0026maft, 0, sizeof(maft));\n-\t\terr = ntmp_maft_query_entry(\u0026si-\u003entmp_user, i, \u0026maft);\n+\t\terr = ntmp_maft_query_entry(user, entry_id, \u0026maft);\n \t\tif (err)\n-\t\t\treturn err;\n+\t\t\tgoto unlock_rtnl;\n \n-\t\tseq_printf(s, \"Entry %d, MAC: %pM, SI bitmap: 0x%04x\\n\", i,\n-\t\t\t maft.keye.mac_addr, le16_to_cpu(maft.cfge.si_bitmap));\n+\t\tseq_printf(s, \"Entry %d, MAC: %pM, SI bitmap: 0x%04x\\n\",\n+\t\t\t entry_id, maft.keye.mac_addr,\n+\t\t\t le16_to_cpu(maft.cfge.si_bitmap));\n \t}\n \n-\treturn 0;\n+unlock_rtnl:\n+\trtnl_unlock();\n+\n+\treturn err;\n }\n DEFINE_SHOW_ATTRIBUTE(enetc_mac_filter);\n \n void enetc_create_debugfs(struct enetc_si *si)\n {\n-\tstruct net_device *ndev = si-\u003endev;\n \tstruct dentry *root;\n \n-\troot = debugfs_create_dir(netdev_name(ndev), NULL);\n+\troot = debugfs_create_dir(pci_name(si-\u003epdev), NULL);\n \tif (IS_ERR(root))\n \t\treturn;\n \ndiff --git a/drivers/net/ethernet/freescale/enetc/enetc4_hw.h b/drivers/net/ethernet/freescale/enetc/enetc4_hw.h\nindex f18437556a0ee2..09025e7a2a3aed 100644\n--- a/drivers/net/ethernet/freescale/enetc/enetc4_hw.h\n+++ b/drivers/net/ethernet/freescale/enetc/enetc4_hw.h\n@@ -69,8 +69,6 @@\n \n /* Port Station interface promiscuous MAC mode register */\n #define ENETC4_PSIPMMR\t\t\t0x200\n-#define PSIPMMR_SI_MAC_UP(a)\t\tBIT(a) /* a = SI index */\n-#define PSIPMMR_SI_MAC_MP(a)\t\tBIT((a) + 16)\n \n /* Port Station interface promiscuous VLAN mode register */\n #define ENETC4_PSIPVMR\t\t\t0x204\n@@ -137,7 +135,6 @@\n #define ENETC4_PSIVHFR1(a)\t\t((a) * 0x80 + 0x2064)\n \n #define ENETC4_PMCAPR\t\t\t0x4004\n-#define PMCAPR_HD\t\t\tBIT(8)\n #define PMCAPR_FP\t\t\tGENMASK(10, 9)\n \n /* Port capability register */\n@@ -150,7 +147,7 @@\n #define PCR_L2DOSE\t\t\tBIT(4)\n #define PCR_TIMER_CS\t\t\tBIT(8)\n #define PCR_PSPEED\t\t\tGENMASK(29, 16)\n-#define PCR_PSPEED_VAL(speed)\t\t(((speed) / 10 - 1) \u003c\u003c 16)\n+#define PCR_PSPEED_VAL(s)\t\tFIELD_PREP(PCR_PSPEED, ((s) / 10 - 1))\n \n /* Port MAC address register 0/1 */\n #define ENETC4_PMAR0\t\t\t0x4020\n@@ -200,7 +197,6 @@\n #define PM_CMD_CFG_CNT_FRM_EN\t\tBIT(13)\n #define PM_CMD_CFG_TXP\t\t\tBIT(15)\n #define PM_CMD_CFG_SEND_IDLE\t\tBIT(16)\n-#define PM_CMD_CFG_HD_FCEN\t\tBIT(18)\n #define PM_CMD_CFG_SFD\t\t\tBIT(21)\n #define PM_CMD_CFG_TX_FLUSH\t\tBIT(22)\n #define PM_CMD_CFG_TX_LOWP_EN\t\tBIT(23)\ndiff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c\nindex 437a15bbb47ba8..fcfbabb29d22e4 100644\n--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c\n+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c\n@@ -23,18 +23,11 @@ static void enetc4_get_port_caps(struct enetc_pf *pf)\n \tu32 val;\n \n \tval = enetc_port_rd(hw, ENETC4_ECAPR1);\n-\tpf-\u003ecaps.num_vsi = (val \u0026 ECAPR1_NUM_VSI) \u003e\u003e 24;\n \tpf-\u003ecaps.num_msix = ((val \u0026 ECAPR1_NUM_MSIX) \u003e\u003e 12) + 1;\n \n \tval = enetc_port_rd(hw, ENETC4_ECAPR2);\n \tpf-\u003ecaps.num_rx_bdr = (val \u0026 ECAPR2_NUM_RX_BDR) \u003e\u003e 16;\n \tpf-\u003ecaps.num_tx_bdr = val \u0026 ECAPR2_NUM_TX_BDR;\n-\n-\tval = enetc_port_rd(hw, ENETC4_PMCAPR);\n-\tpf-\u003ecaps.half_duplex = (val \u0026 PMCAPR_HD) ? 1 : 0;\n-\n-\tval = enetc_port_rd(hw, ENETC4_PSIMAFCAPR);\n-\tpf-\u003ecaps.mac_filter_num = val \u0026 PSIMAFCAPR_NUM_MAC_AFTE;\n }\n \n static void enetc4_get_psi_hw_features(struct enetc_si *si)\n@@ -75,38 +68,6 @@ static void enetc4_pf_get_si_primary_mac(struct enetc_hw *hw, int si,\n \tput_unaligned_le16(lower, addr + 4);\n }\n \n-static void enetc4_pf_set_si_mac_promisc(struct enetc_hw *hw, int si,\n-\t\t\t\t\t bool uc_promisc, bool mc_promisc)\n-{\n-\tu32 val = enetc_port_rd(hw, ENETC4_PSIPMMR);\n-\n-\tif (uc_promisc)\n-\t\tval |= PSIPMMR_SI_MAC_UP(si);\n-\telse\n-\t\tval \u0026= ~PSIPMMR_SI_MAC_UP(si);\n-\n-\tif (mc_promisc)\n-\t\tval |= PSIPMMR_SI_MAC_MP(si);\n-\telse\n-\t\tval \u0026= ~PSIPMMR_SI_MAC_MP(si);\n-\n-\tenetc_port_wr(hw, ENETC4_PSIPMMR, val);\n-}\n-\n-static void enetc4_pf_set_si_uc_hash_filter(struct enetc_hw *hw, int si,\n-\t\t\t\t\t u64 hash)\n-{\n-\tenetc_port_wr(hw, ENETC4_PSIUMHFR0(si), lower_32_bits(hash));\n-\tenetc_port_wr(hw, ENETC4_PSIUMHFR1(si), upper_32_bits(hash));\n-}\n-\n-static void enetc4_pf_set_si_mc_hash_filter(struct enetc_hw *hw, int si,\n-\t\t\t\t\t u64 hash)\n-{\n-\tenetc_port_wr(hw, ENETC4_PSIMMHFR0(si), lower_32_bits(hash));\n-\tenetc_port_wr(hw, ENETC4_PSIMMHFR1(si), upper_32_bits(hash));\n-}\n-\n static void enetc4_pf_set_loopback(struct net_device *ndev, bool en)\n {\n \tstruct enetc_ndev_priv *priv = netdev_priv(ndev);\n@@ -124,34 +85,47 @@ static void enetc4_pf_set_loopback(struct net_device *ndev, bool en)\n \n static void enetc4_pf_clear_maft_entries(struct enetc_pf *pf)\n {\n-\tint i;\n+\tstruct ntmp_user *user = \u0026pf-\u003esi-\u003entmp_user;\n+\tu32 entry_id;\n \n-\tfor (i = 0; i \u003c pf-\u003enum_mfe; i++)\n-\t\tntmp_maft_delete_entry(\u0026pf-\u003esi-\u003entmp_user, i);\n-\n-\tpf-\u003enum_mfe = 0;\n+\tfor_each_set_bit(entry_id, user-\u003emaft_eid_bitmap,\n+\t\t\t user-\u003emaft_num_entries) {\n+\t\tif (!ntmp_maft_delete_entry(user, entry_id))\n+\t\t\tntmp_clear_eid_bitmap(user-\u003emaft_eid_bitmap, entry_id);\n+\t}\n }\n \n static int enetc4_pf_add_maft_entries(struct enetc_pf *pf,\n-\t\t\t\t struct enetc_mac_addr *mac,\n-\t\t\t\t int mac_cnt)\n+\t\t\t\t struct netdev_hw_addr_list *uc)\n {\n+\tstruct ntmp_user *user = \u0026pf-\u003esi-\u003entmp_user;\n+\tint mac_cnt = netdev_hw_addr_list_count(uc);\n \tstruct maft_entry_data maft = {};\n+\tstruct netdev_hw_addr *ha;\n+\tu32 available_entries;\n \tu16 si_bit = BIT(0);\n-\tint i, err;\n+\tu32 entry_id;\n+\tint err;\n+\n+\tavailable_entries = user-\u003emaft_num_entries -\n+\t\t\t bitmap_weight(user-\u003emaft_eid_bitmap,\n+\t\t\t\t\t user-\u003emaft_num_entries);\n+\n+\tif (mac_cnt \u003e available_entries)\n+\t\treturn -ENOSPC;\n \n \tmaft.cfge.si_bitmap = cpu_to_le16(si_bit);\n-\tfor (i = 0; i \u003c mac_cnt; i++) {\n-\t\tether_addr_copy(maft.keye.mac_addr, mac[i].addr);\n-\t\terr = ntmp_maft_add_entry(\u0026pf-\u003esi-\u003entmp_user, i, \u0026maft);\n+\tnetdev_hw_addr_list_for_each(ha, uc) {\n+\t\tentry_id = ntmp_lookup_free_eid(user-\u003emaft_eid_bitmap,\n+\t\t\t\t\t\tuser-\u003emaft_num_entries);\n+\t\tether_addr_copy(maft.keye.mac_addr, ha-\u003eaddr);\n+\t\terr = ntmp_maft_add_entry(user, entry_id, \u0026maft);\n \t\tif (unlikely(err)) {\n-\t\t\tpf-\u003enum_mfe = i;\n+\t\t\tntmp_clear_eid_bitmap(user-\u003emaft_eid_bitmap, entry_id);\n \t\t\tgoto clear_maft_entries;\n \t\t}\n \t}\n \n-\tpf-\u003enum_mfe = mac_cnt;\n-\n \treturn 0;\n \n clear_maft_entries:\n@@ -160,97 +134,70 @@ static int enetc4_pf_add_maft_entries(struct enetc_pf *pf,\n \treturn err;\n }\n \n-static int enetc4_pf_set_uc_exact_filter(struct enetc_pf *pf)\n+static void enetc4_pf_set_uc_hash_filter(struct enetc_pf *pf,\n+\t\t\t\t\t struct netdev_hw_addr_list *uc)\n {\n-\tint max_num_mfe = pf-\u003ecaps.mac_filter_num;\n-\tstruct enetc_mac_filter mac_filter = {};\n-\tstruct net_device *ndev = pf-\u003esi-\u003endev;\n-\tstruct enetc_hw *hw = \u0026pf-\u003esi-\u003ehw;\n-\tstruct enetc_mac_addr *mac_tbl;\n+\tstruct enetc_mac_filter *mac_filter = \u0026pf-\u003emac_filter[UC];\n \tstruct netdev_hw_addr *ha;\n-\tint i = 0, err;\n-\tint mac_cnt;\n+\tu64 hash;\n \n-\tnetif_addr_lock_bh(ndev);\n+\tenetc_reset_mac_addr_filter(mac_filter);\n+\tnetdev_hw_addr_list_for_each(ha, uc)\n+\t\tenetc_add_mac_addr_ht_filter(mac_filter, ha-\u003eaddr);\n+\n+\tbitmap_to_arr64(\u0026hash, mac_filter-\u003emac_hash_table,\n+\t\t\tENETC_MADDR_HASH_TBL_SZ);\n+\tenetc_set_si_uc_hash_filter(pf-\u003esi, 0, hash);\n+}\n \n-\tmac_cnt = netdev_uc_count(ndev);\n-\tif (!mac_cnt) {\n-\t\tnetif_addr_unlock_bh(ndev);\n+static int enetc4_pf_set_uc_exact_filter(struct enetc_pf *pf,\n+\t\t\t\t\t struct netdev_hw_addr_list *uc)\n+{\n+\tstruct enetc_si *si = pf-\u003esi;\n+\tint err;\n+\n+\tif (netdev_hw_addr_list_empty(uc)) {\n \t\t/* clear both MAC hash and exact filters */\n-\t\tenetc4_pf_set_si_uc_hash_filter(hw, 0, 0);\n+\t\tenetc_set_si_uc_hash_filter(si, 0, 0);\n \t\tenetc4_pf_clear_maft_entries(pf);\n \n \t\treturn 0;\n \t}\n \n-\tif (mac_cnt \u003e max_num_mfe) {\n-\t\terr = -ENOSPC;\n-\t\tgoto unlock_netif_addr;\n-\t}\n-\n-\tmac_tbl = kzalloc_objs(*mac_tbl, mac_cnt, GFP_ATOMIC);\n-\tif (!mac_tbl) {\n-\t\terr = -ENOMEM;\n-\t\tgoto unlock_netif_addr;\n-\t}\n-\n-\tnetdev_for_each_uc_addr(ha, ndev) {\n-\t\tenetc_add_mac_addr_ht_filter(\u0026mac_filter, ha-\u003eaddr);\n-\t\tether_addr_copy(mac_tbl[i++].addr, ha-\u003eaddr);\n-\t}\n-\n-\tnetif_addr_unlock_bh(ndev);\n-\n-\t/* Set temporary unicast hash filters in case of Rx loss when\n+\t/* Set temporary unicast hash filter in case of Rx loss when\n \t * updating MAC address filter table\n \t */\n-\tenetc4_pf_set_si_uc_hash_filter(hw, 0, *mac_filter.mac_hash_table);\n+\tenetc4_pf_set_uc_hash_filter(pf, uc);\n \tenetc4_pf_clear_maft_entries(pf);\n \n-\tif (!enetc4_pf_add_maft_entries(pf, mac_tbl, i))\n-\t\tenetc4_pf_set_si_uc_hash_filter(hw, 0, 0);\n-\n-\tkfree(mac_tbl);\n-\n-\treturn 0;\n-\n-unlock_netif_addr:\n-\tnetif_addr_unlock_bh(ndev);\n+\terr = enetc4_pf_add_maft_entries(pf, uc);\n+\tif (!err) {\n+\t\tenetc_reset_mac_addr_filter(\u0026pf-\u003emac_filter[UC]);\n+\t\tenetc_set_si_uc_hash_filter(si, 0, 0);\n+\t}\n \n \treturn err;\n }\n \n-static void enetc4_pf_set_mac_hash_filter(struct enetc_pf *pf, int type)\n+static void enetc4_pf_set_mc_hash_filter(struct enetc_pf *pf,\n+\t\t\t\t\t struct netdev_hw_addr_list *mc)\n {\n-\tstruct net_device *ndev = pf-\u003esi-\u003endev;\n-\tstruct enetc_mac_filter *mac_filter;\n-\tstruct enetc_hw *hw = \u0026pf-\u003esi-\u003ehw;\n+\tstruct enetc_mac_filter *mac_filter = \u0026pf-\u003emac_filter[MC];\n \tstruct netdev_hw_addr *ha;\n+\tu64 hash;\n \n-\tnetif_addr_lock_bh(ndev);\n-\tif (type \u0026 ENETC_MAC_FILTER_TYPE_UC) {\n-\t\tmac_filter = \u0026pf-\u003emac_filter[UC];\n-\t\tenetc_reset_mac_addr_filter(mac_filter);\n-\t\tnetdev_for_each_uc_addr(ha, ndev)\n-\t\t\tenetc_add_mac_addr_ht_filter(mac_filter, ha-\u003eaddr);\n-\n-\t\tenetc4_pf_set_si_uc_hash_filter(hw, 0,\n-\t\t\t\t\t\t*mac_filter-\u003emac_hash_table);\n-\t}\n+\tenetc_reset_mac_addr_filter(mac_filter);\n+\tnetdev_hw_addr_list_for_each(ha, mc)\n+\t\tenetc_add_mac_addr_ht_filter(mac_filter, ha-\u003eaddr);\n \n-\tif (type \u0026 ENETC_MAC_FILTER_TYPE_MC) {\n-\t\tmac_filter = \u0026pf-\u003emac_filter[MC];\n-\t\tenetc_reset_mac_addr_filter(mac_filter);\n-\t\tnetdev_for_each_mc_addr(ha, ndev)\n-\t\t\tenetc_add_mac_addr_ht_filter(mac_filter, ha-\u003eaddr);\n-\n-\t\tenetc4_pf_set_si_mc_hash_filter(hw, 0,\n-\t\t\t\t\t\t*mac_filter-\u003emac_hash_table);\n-\t}\n-\tnetif_addr_unlock_bh(ndev);\n+\tbitmap_to_arr64(\u0026hash, mac_filter-\u003emac_hash_table,\n+\t\t\tENETC_MADDR_HASH_TBL_SZ);\n+\tenetc_set_si_mc_hash_filter(pf-\u003esi, 0, hash);\n }\n \n-static void enetc4_pf_set_mac_filter(struct enetc_pf *pf, int type)\n+static void enetc4_pf_set_mac_filter(struct enetc_pf *pf, int type,\n+\t\t\t\t struct netdev_hw_addr_list *uc,\n+\t\t\t\t struct netdev_hw_addr_list *mc)\n {\n \t/* Currently, the MAC address filter table (MAFT) only has 4 entries,\n \t * and multiple multicast addresses for filtering will be configured\n@@ -258,15 +205,16 @@ static void enetc4_pf_set_mac_filter(struct enetc_pf *pf, int type)\n \t * unicast filtering. If the number of unicast addresses exceeds the\n \t * table capacity, the MAC hash filter will be used.\n \t */\n-\tif (type \u0026 ENETC_MAC_FILTER_TYPE_UC \u0026\u0026 enetc4_pf_set_uc_exact_filter(pf)) {\n+\tif (type \u0026 ENETC_MAC_FILTER_TYPE_UC \u0026\u0026\n+\t enetc4_pf_set_uc_exact_filter(pf, uc)) {\n \t\t/* Fall back to the MAC hash filter */\n-\t\tenetc4_pf_set_mac_hash_filter(pf, ENETC_MAC_FILTER_TYPE_UC);\n+\t\tenetc4_pf_set_uc_hash_filter(pf, uc);\n \t\t/* Clear the old MAC exact filter */\n \t\tenetc4_pf_clear_maft_entries(pf);\n \t}\n \n \tif (type \u0026 ENETC_MAC_FILTER_TYPE_MC)\n-\t\tenetc4_pf_set_mac_hash_filter(pf, ENETC_MAC_FILTER_TYPE_MC);\n+\t\tenetc4_pf_set_mc_hash_filter(pf, mc);\n }\n \n static const struct enetc_pf_ops enetc4_pf_ops = {\n@@ -306,34 +254,35 @@ static void enetc4_default_rings_allocation(struct enetc_pf *pf)\n {\n \tstruct enetc_hw *hw = \u0026pf-\u003esi-\u003ehw;\n \tu32 num_rx_bdr, num_tx_bdr, val;\n+\tint num_vfs = pf-\u003etotal_vfs;\n \tu32 vf_tx_bdr, vf_rx_bdr;\n \tint i, rx_rem, tx_rem;\n \n-\tif (pf-\u003ecaps.num_rx_bdr \u003c ENETC_SI_MAX_RING_NUM + pf-\u003ecaps.num_vsi)\n-\t\tnum_rx_bdr = pf-\u003ecaps.num_rx_bdr - pf-\u003ecaps.num_vsi;\n+\tif (pf-\u003ecaps.num_rx_bdr \u003c ENETC_SI_MAX_RING_NUM + num_vfs)\n+\t\tnum_rx_bdr = pf-\u003ecaps.num_rx_bdr - num_vfs;\n \telse\n \t\tnum_rx_bdr = ENETC_SI_MAX_RING_NUM;\n \n-\tif (pf-\u003ecaps.num_tx_bdr \u003c ENETC_SI_MAX_RING_NUM + pf-\u003ecaps.num_vsi)\n-\t\tnum_tx_bdr = pf-\u003ecaps.num_tx_bdr - pf-\u003ecaps.num_vsi;\n+\tif (pf-\u003ecaps.num_tx_bdr \u003c ENETC_SI_MAX_RING_NUM + num_vfs)\n+\t\tnum_tx_bdr = pf-\u003ecaps.num_tx_bdr - num_vfs;\n \telse\n \t\tnum_tx_bdr = ENETC_SI_MAX_RING_NUM;\n \n \tval = enetc4_psicfgr0_val_construct(false, num_tx_bdr, num_rx_bdr);\n \tenetc_port_wr(hw, ENETC4_PSICFGR0(0), val);\n \n-\tif (!pf-\u003ecaps.num_vsi)\n+\tif (!num_vfs)\n \t\treturn;\n \n \tnum_rx_bdr = pf-\u003ecaps.num_rx_bdr - num_rx_bdr;\n-\trx_rem = num_rx_bdr % pf-\u003ecaps.num_vsi;\n-\tnum_rx_bdr = num_rx_bdr / pf-\u003ecaps.num_vsi;\n+\trx_rem = num_rx_bdr % num_vfs;\n+\tnum_rx_bdr = num_rx_bdr / num_vfs;\n \n \tnum_tx_bdr = pf-\u003ecaps.num_tx_bdr - num_tx_bdr;\n-\ttx_rem = num_tx_bdr % pf-\u003ecaps.num_vsi;\n-\tnum_tx_bdr = num_tx_bdr / pf-\u003ecaps.num_vsi;\n+\ttx_rem = num_tx_bdr % num_vfs;\n+\tnum_tx_bdr = num_tx_bdr / num_vfs;\n \n-\tfor (i = 0; i \u003c pf-\u003ecaps.num_vsi; i++) {\n+\tfor (i = 0; i \u003c num_vfs; i++) {\n \t\tvf_tx_bdr = (i \u003c tx_rem) ? num_tx_bdr + 1 : num_tx_bdr;\n \t\tvf_rx_bdr = (i \u003c rx_rem) ? num_rx_bdr + 1 : num_rx_bdr;\n \t\tval = enetc4_psicfgr0_val_construct(true, vf_tx_bdr, vf_rx_bdr);\n@@ -346,53 +295,70 @@ static void enetc4_allocate_si_rings(struct enetc_pf *pf)\n \tenetc4_default_rings_allocation(pf);\n }\n \n-static void enetc4_pf_set_si_vlan_promisc(struct enetc_hw *hw, int si, bool en)\n-{\n-\tu32 val = enetc_port_rd(hw, ENETC4_PSIPVMR);\n-\n-\tif (en)\n-\t\tval |= BIT(si);\n-\telse\n-\t\tval \u0026= ~BIT(si);\n-\n-\tenetc_port_wr(hw, ENETC4_PSIPVMR, val);\n-}\n-\n-static void enetc4_set_default_si_vlan_promisc(struct enetc_pf *pf)\n-{\n-\tstruct enetc_hw *hw = \u0026pf-\u003esi-\u003ehw;\n-\tint num_si = pf-\u003ecaps.num_vsi + 1;\n-\tint i;\n-\n-\t/* enforce VLAN promiscuous mode for all SIs */\n-\tfor (i = 0; i \u003c num_si; i++)\n-\t\tenetc4_pf_set_si_vlan_promisc(hw, i, true);\n-}\n-\n /* Allocate the number of MSI-X vectors for per SI. */\n static void enetc4_set_si_msix_num(struct enetc_pf *pf)\n {\n+\tint valid_num_si = pf-\u003etotal_vfs + 1;\n \tstruct enetc_hw *hw = \u0026pf-\u003esi-\u003ehw;\n-\tint i, num_msix, total_si;\n+\tint i, num_msix, num_vsi;\n \tu32 val;\n \n-\ttotal_si = pf-\u003ecaps.num_vsi + 1;\n+\tval = enetc_port_rd(hw, ENETC4_ECAPR1);\n+\tnum_vsi = FIELD_GET(ECAPR1_NUM_VSI, val);\n+\n+\t/* The PSIaCFGR2[NUM_MSIX] indicates the number of MSI-X allocated to\n+\t * the SI is NUM_MSIX + 1, so the minimum number of MSI-X allocated to\n+\t * each SI is 1. The total number of MSI-X allocated to PSI and VSIs\n+\t * cannot exceed the total number of MSI-X owned by this ENETC, which\n+\t * is ECAPR1[NUM_MSIX]. Otherwise, when multiple ENETC instances exist,\n+\t * it will affect other ENETCs whose MSI-X interrupts cannot be\n+\t * generated. This is similar to out-of-bounds array access: the array\n+\t * itself is not affected, but adjacent arrays will be corrupted.\n+\t *\n+\t * pf-\u003etotal_vfs is 0 if CONFIG_PCI_IOV is disabled. If the hardware\n+\t * itself supports SR-IOV, then when allocating the number of MSIXs to\n+\t * the SI, it must be taken into account that the VSI has at least 1\n+\t * MSIX, and the total number of MSIXs of all SIs cannot exceed\n+\t * ECAPR1[NUM_MSIX].\n+\t */\n+\tif (!pf-\u003etotal_vfs \u0026\u0026 num_vsi) {\n+\t\t/* Because each SI has at least one MSIX, and from the hardware\n+\t\t * perspective, pf-\u003ecaps.num_msix will always be greater than\n+\t\t * num_vsi. So num_msix is always greater than or equal to 0.\n+\t\t */\n+\t\tnum_msix = pf-\u003ecaps.num_msix - num_vsi - 1;\n+\t\tif (num_msix \u003e PSICFGR2_NUM_MSIX)\n+\t\t\tnum_msix = PSICFGR2_NUM_MSIX;\n+\t\tenetc_port_wr(hw, ENETC4_PSICFGR2(0), num_msix);\n \n-\tnum_msix = pf-\u003ecaps.num_msix / total_si +\n-\t\t pf-\u003ecaps.num_msix % total_si - 1;\n-\tval = num_msix \u0026 PSICFGR2_NUM_MSIX;\n-\tenetc_port_wr(hw, ENETC4_PSICFGR2(0), val);\n+\t\tfor (i = 0; i \u003c num_vsi; i++)\n+\t\t\tenetc_port_wr(hw, ENETC4_PSICFGR2(i + 1), 0);\n \n-\tnum_msix = pf-\u003ecaps.num_msix / total_si - 1;\n-\tval = num_msix \u0026 PSICFGR2_NUM_MSIX;\n-\tfor (i = 0; i \u003c pf-\u003ecaps.num_vsi; i++)\n-\t\tenetc_port_wr(hw, ENETC4_PSICFGR2(i + 1), val);\n+\t\treturn;\n+\t}\n+\n+\t/* Likewise, from the hardware perspective pf-\u003ecaps.num_msix is always\n+\t * greater than valid_num_si. So num_msix is always greater than or\n+\t * equal to 0.\n+\t */\n+\tnum_msix = pf-\u003ecaps.num_msix / valid_num_si +\n+\t\t pf-\u003ecaps.num_msix % valid_num_si - 1;\n+\tif (num_msix \u003e PSICFGR2_NUM_MSIX)\n+\t\tnum_msix = PSICFGR2_NUM_MSIX;\n+\tenetc_port_wr(hw, ENETC4_PSICFGR2(0), num_msix);\n+\n+\tnum_msix = pf-\u003ecaps.num_msix / valid_num_si - 1;\n+\tif (num_msix \u003e PSICFGR2_NUM_MSIX)\n+\t\tnum_msix = PSICFGR2_NUM_MSIX;\n+\n+\tfor (i = 0; i \u003c pf-\u003etotal_vfs; i++)\n+\t\tenetc_port_wr(hw, ENETC4_PSICFGR2(i + 1), num_msix);\n }\n \n static void enetc4_enable_all_si(struct enetc_pf *pf)\n {\n \tstruct enetc_hw *hw = \u0026pf-\u003esi-\u003ehw;\n-\tint num_si = pf-\u003ecaps.num_vsi + 1;\n+\tint num_si = pf-\u003etotal_vfs + 1;\n \tu32 si_bitmap = 0;\n \tint i;\n \n@@ -412,7 +378,9 @@ static void enetc4_configure_port_si(struct enetc_pf *pf)\n \t/* Outer VLAN tag will be used for VLAN filtering */\n \tenetc_port_wr(hw, ENETC4_PSIVLANFMR, PSIVLANFMR_VS);\n \n-\tenetc4_set_default_si_vlan_promisc(pf);\n+\t/* Enforce VLAN promiscuous mode for all SIs */\n+\tfor (int i = 0; i \u003c pf-\u003etotal_vfs + 1; i++)\n+\t\tenetc_set_si_vlan_promisc(pf-\u003esi, i, true);\n \n \t/* Disable SI MAC multicast \u0026 unicast promiscuous */\n \tenetc_port_wr(hw, ENETC4_PSIPMMR, 0);\n@@ -450,18 +418,60 @@ static void enetc4_configure_port(struct enetc_pf *pf)\n \tenetc_set_default_rss_key(pf);\n }\n \n+static void enetc4_get_ntmp_caps(struct enetc_si *si)\n+{\n+\tstruct ntmp_user *user = \u0026si-\u003entmp_user;\n+\tstruct enetc_hw *hw = \u0026si-\u003ehw;\n+\tu32 val;\n+\n+\tval = enetc_port_rd(hw, ENETC4_PSIMAFCAPR);\n+\tuser-\u003emaft_num_entries = FIELD_GET(PSIMAFCAPR_NUM_MAC_AFTE, val);\n+}\n+\n+static int enetc4_ntmp_bitmap_init(struct ntmp_user *user)\n+{\n+\tuser-\u003emaft_eid_bitmap = bitmap_zalloc(user-\u003emaft_num_entries,\n+\t\t\t\t\t GFP_KERNEL);\n+\tif (!user-\u003emaft_eid_bitmap)\n+\t\treturn -ENOMEM;\n+\n+\treturn 0;\n+}\n+\n+static void enetc4_ntmp_bitmap_free(struct ntmp_user *user)\n+{\n+\tbitmap_free(user-\u003emaft_eid_bitmap);\n+\tuser-\u003emaft_eid_bitmap = NULL;\n+}\n+\n static int enetc4_init_ntmp_user(struct enetc_si *si)\n {\n \tstruct ntmp_user *user = \u0026si-\u003entmp_user;\n+\tint err;\n \n \t/* For ENETC 4.1, all table versions are 0 */\n \tmemset(\u0026user-\u003etbl, 0, sizeof(user-\u003etbl));\n \n-\treturn enetc4_setup_cbdr(si);\n+\terr = enetc4_setup_cbdr(si);\n+\tif (err)\n+\t\treturn err;\n+\n+\tenetc4_get_ntmp_caps(si);\n+\terr = enetc4_ntmp_bitmap_init(user);\n+\tif (err)\n+\t\tgoto teardown_cbdr;\n+\n+\treturn 0;\n+\n+teardown_cbdr:\n+\tenetc4_teardown_cbdr(si);\n+\n+\treturn err;\n }\n \n static void enetc4_free_ntmp_user(struct enetc_si *si)\n {\n+\tenetc4_ntmp_bitmap_free(\u0026si-\u003entmp_user);\n \tenetc4_teardown_cbdr(si);\n }\n \n@@ -479,7 +489,7 @@ static int enetc4_pf_init(struct enetc_pf *pf)\n \n \terr = enetc4_init_ntmp_user(pf-\u003esi);\n \tif (err) {\n-\t\tdev_err(dev, \"Failed to init CBDR\\n\");\n+\t\tdev_err(dev, \"Failed to init NTMP user\\n\");\n \t\treturn err;\n \t}\n \n@@ -493,18 +503,17 @@ static void enetc4_pf_free(struct enetc_pf *pf)\n \tenetc4_free_ntmp_user(pf-\u003esi);\n }\n \n-static void enetc4_psi_do_set_rx_mode(struct work_struct *work)\n+static int enetc4_pf_set_rx_mode(struct net_device *ndev,\n+\t\t\t\t struct netdev_hw_addr_list *uc,\n+\t\t\t\t struct netdev_hw_addr_list *mc)\n {\n-\tstruct enetc_si *si = container_of(work, struct enetc_si, rx_mode_task);\n-\tstruct enetc_pf *pf = enetc_si_priv(si);\n-\tstruct net_device *ndev = si-\u003endev;\n-\tstruct enetc_hw *hw = \u0026si-\u003ehw;\n+\tstruct enetc_ndev_priv *priv = netdev_priv(ndev);\n+\tstruct enetc_pf *pf = enetc_si_priv(priv-\u003esi);\n+\tstruct enetc_si *si = priv-\u003esi;\n \tbool uc_promisc = false;\n \tbool mc_promisc = false;\n \tint type = 0;\n \n-\trtnl_lock();\n-\n \tif (ndev-\u003eflags \u0026 IFF_PROMISC) {\n \t\tuc_promisc = true;\n \t\tmc_promisc = true;\n@@ -515,28 +524,21 @@ static void enetc4_psi_do_set_rx_mode(struct work_struct *work)\n \t\ttype = ENETC_MAC_FILTER_TYPE_ALL;\n \t}\n \n-\tenetc4_pf_set_si_mac_promisc(hw, 0, uc_promisc, mc_promisc);\n+\tenetc_set_si_uc_promisc(si, 0, uc_promisc);\n+\tenetc_set_si_mc_promisc(si, 0, mc_promisc);\n \n \tif (uc_promisc) {\n-\t\tenetc4_pf_set_si_uc_hash_filter(hw, 0, 0);\n+\t\tenetc_set_si_uc_hash_filter(si, 0, 0);\n \t\tenetc4_pf_clear_maft_entries(pf);\n \t}\n \n \tif (mc_promisc)\n-\t\tenetc4_pf_set_si_mc_hash_filter(hw, 0, 0);\n+\t\tenetc_set_si_mc_hash_filter(si, 0, 0);\n \n \t/* Set new MAC filter */\n-\tenetc4_pf_set_mac_filter(pf, type);\n+\tenetc4_pf_set_mac_filter(pf, type, uc, mc);\n \n-\trtnl_unlock();\n-}\n-\n-static void enetc4_pf_set_rx_mode(struct net_device *ndev)\n-{\n-\tstruct enetc_ndev_priv *priv = netdev_priv(ndev);\n-\tstruct enetc_si *si = priv-\u003esi;\n-\n-\tqueue_work(si-\u003eworkqueue, \u0026si-\u003erx_mode_task);\n+\treturn 0;\n }\n \n static int enetc4_pf_set_features(struct net_device *ndev,\n@@ -544,12 +546,11 @@ static int enetc4_pf_set_features(struct net_device *ndev,\n {\n \tnetdev_features_t changed = ndev-\u003efeatures ^ features;\n \tstruct enetc_ndev_priv *priv = netdev_priv(ndev);\n-\tstruct enetc_hw *hw = \u0026priv-\u003esi-\u003ehw;\n \n \tif (changed \u0026 NETIF_F_HW_VLAN_CTAG_FILTER) {\n \t\tbool promisc_en = !(features \u0026 NETIF_F_HW_VLAN_CTAG_FILTER);\n \n-\t\tenetc4_pf_set_si_vlan_promisc(hw, 0, promisc_en);\n+\t\tenetc_set_si_vlan_promisc(priv-\u003esi, 0, promisc_en);\n \t}\n \n \tif (changed \u0026 NETIF_F_LOOPBACK)\n@@ -566,7 +567,7 @@ static const struct net_device_ops enetc4_ndev_ops = {\n \t.ndo_start_xmit\t\t= enetc_xmit,\n \t.ndo_get_stats\t\t= enetc_get_stats,\n \t.ndo_set_mac_address\t= enetc_pf_set_mac_addr,\n-\t.ndo_set_rx_mode\t= enetc4_pf_set_rx_mode,\n+\t.ndo_set_rx_mode_async\t= enetc4_pf_set_rx_mode,\n \t.ndo_set_features\t= enetc4_pf_set_features,\n \t.ndo_vlan_rx_add_vid\t= enetc_vlan_rx_add_vid,\n \t.ndo_vlan_rx_kill_vid\t= enetc_vlan_rx_del_vid,\n@@ -602,11 +603,6 @@ static void enetc4_mac_config(struct enetc_pf *pf, unsigned int mode,\n \tcase PHY_INTERFACE_MODE_RGMII_RXID:\n \tcase PHY_INTERFACE_MODE_RGMII_TXID:\n \t\tval |= IFMODE_RGMII;\n-\t\t/* We need to enable auto-negotiation for the MAC\n-\t\t * if its RGMII interface support In-Band status.\n-\t\t */\n-\t\tif (phylink_autoneg_inband(mode))\n-\t\t\tval |= PM_IF_MODE_ENA;\n \t\tbreak;\n \tcase PHY_INTERFACE_MODE_RMII:\n \t\tval |= IFMODE_RMII;\n@@ -616,7 +612,6 @@ static void enetc4_mac_config(struct enetc_pf *pf, unsigned int mode,\n \t\tval |= IFMODE_SGMII;\n \t\tbreak;\n \tcase PHY_INTERFACE_MODE_10GBASER:\n-\tcase PHY_INTERFACE_MODE_XGMII:\n \tcase PHY_INTERFACE_MODE_USXGMII:\n \t\tval |= IFMODE_XGMII;\n \t\tbreak;\n@@ -642,26 +637,19 @@ static void enetc4_set_port_speed(struct enetc_ndev_priv *priv, int speed)\n \tu32 old_speed = priv-\u003espeed;\n \tu32 val;\n \n+\t/* If the speed is unknown, use the minimum value */\n+\tif (speed == SPEED_UNKNOWN) {\n+\t\tspeed = SPEED_10;\n+\t\tdev_warn(priv-\u003edev, \"Speed unknown, default is 10Mbps\\n\");\n+\t}\n+\n \tif (speed == old_speed)\n \t\treturn;\n \n-\tval = enetc_port_rd(\u0026priv-\u003esi-\u003ehw, ENETC4_PCR);\n-\tval \u0026= ~PCR_PSPEED;\n-\n-\tswitch (speed) {\n-\tcase SPEED_100:\n-\tcase SPEED_1000:\n-\tcase SPEED_2500:\n-\tcase SPEED_10000:\n-\t\tval |= (PCR_PSPEED \u0026 PCR_PSPEED_VAL(speed));\n-\t\tbreak;\n-\tcase SPEED_10:\n-\tdefault:\n-\t\tval |= (PCR_PSPEED \u0026 PCR_PSPEED_VAL(SPEED_10));\n-\t}\n-\n-\tpriv-\u003espeed = speed;\n+\tval = enetc_port_rd(\u0026priv-\u003esi-\u003ehw, ENETC4_PCR) \u0026 (~PCR_PSPEED);\n+\tval |= PCR_PSPEED_VAL(speed);\n \tenetc_port_wr(\u0026priv-\u003esi-\u003ehw, ENETC4_PCR, val);\n+\tpriv-\u003espeed = speed;\n }\n \n static void enetc4_set_rgmii_mac(struct enetc_pf *pf, int speed, int duplex)\n@@ -717,22 +705,6 @@ static void enetc4_set_rmii_mac(struct enetc_pf *pf, int speed, int duplex)\n \tenetc_port_mac_wr(si, ENETC4_PM_IF_MODE(0), val);\n }\n \n-static void enetc4_set_hd_flow_control(struct enetc_pf *pf, bool enable)\n-{\n-\tstruct enetc_si *si = pf-\u003esi;\n-\tu32 old_val, val;\n-\n-\tif (!pf-\u003ecaps.half_duplex)\n-\t\treturn;\n-\n-\told_val = enetc_port_mac_rd(si, ENETC4_PM_CMD_CFG(0));\n-\tval = u32_replace_bits(old_val, enable ? 1 : 0, PM_CMD_CFG_HD_FCEN);\n-\tif (val == old_val)\n-\t\treturn;\n-\n-\tenetc_port_mac_wr(si, ENETC4_PM_CMD_CFG(0), val);\n-}\n-\n static void enetc4_set_rx_pause(struct enetc_pf *pf, bool rx_pause)\n {\n \tstruct enetc_si *si = pf-\u003esi;\n@@ -908,13 +880,11 @@ static void enetc4_pl_mac_link_up(struct phylink_config *config,\n \tstruct enetc_pf *pf = phylink_to_enetc_pf(config);\n \tstruct enetc_si *si = pf-\u003esi;\n \tstruct enetc_ndev_priv *priv;\n-\tbool hd_fc = false;\n \n \tpriv = netdev_priv(si-\u003endev);\n \tenetc4_set_port_speed(priv, speed);\n \n-\tif (!phylink_autoneg_inband(mode) \u0026\u0026\n-\t phy_interface_mode_is_rgmii(interface))\n+\tif (phy_interface_mode_is_rgmii(interface))\n \t\tenetc4_set_rgmii_mac(pf, speed, duplex);\n \n \tif (interface == PHY_INTERFACE_MODE_RMII)\n@@ -926,18 +896,8 @@ static void enetc4_pl_mac_link_up(struct phylink_config *config,\n \t\t */\n \t\tif (priv-\u003eactive_offloads \u0026 ENETC_F_QBU)\n \t\t\ttx_pause = false;\n-\t} else { /* DUPLEX_HALF */\n-\t\tif (tx_pause || rx_pause)\n-\t\t\thd_fc = true;\n-\n-\t\t/* As per 802.3 annex 31B, PAUSE frames are only supported\n-\t\t * when the link is configured for full duplex operation.\n-\t\t */\n-\t\ttx_pause = false;\n-\t\trx_pause = false;\n \t}\n \n-\tenetc4_set_hd_flow_control(pf, hd_fc);\n \tenetc4_set_tx_pause(pf, priv-\u003enum_rx_rings, tx_pause);\n \tenetc4_set_rx_pause(pf, rx_pause);\n \tenetc4_mac_tx_enable(pf);\n@@ -1009,19 +969,6 @@ static void enetc4_link_deinit(struct enetc_ndev_priv *priv)\n \tenetc_mdiobus_destroy(pf);\n }\n \n-static int enetc4_psi_wq_task_init(struct enetc_si *si)\n-{\n-\tchar wq_name[24];\n-\n-\tINIT_WORK(\u0026si-\u003erx_mode_task, enetc4_psi_do_set_rx_mode);\n-\tsnprintf(wq_name, sizeof(wq_name), \"enetc-%s\", pci_name(si-\u003epdev));\n-\tsi-\u003eworkqueue = create_singlethread_workqueue(wq_name);\n-\tif (!si-\u003eworkqueue)\n-\t\treturn -ENOMEM;\n-\n-\treturn 0;\n-}\n-\n static int enetc4_pf_netdev_create(struct enetc_si *si)\n {\n \tstruct device *dev = \u0026si-\u003epdev-\u003edev;\n@@ -1062,12 +1009,6 @@ static int enetc4_pf_netdev_create(struct enetc_si *si)\n \tif (err)\n \t\tgoto err_link_init;\n \n-\terr = enetc4_psi_wq_task_init(si);\n-\tif (err) {\n-\t\tdev_err(dev, \"Failed to init workqueue\\n\");\n-\t\tgoto err_wq_init;\n-\t}\n-\n \terr = register_netdev(ndev);\n \tif (err) {\n \t\tdev_err(dev, \"Failed to register netdev\\n\");\n@@ -1077,8 +1018,6 @@ static int enetc4_pf_netdev_create(struct enetc_si *si)\n \treturn 0;\n \n err_reg_netdev:\n-\tdestroy_workqueue(si-\u003eworkqueue);\n-err_wq_init:\n \tenetc4_link_deinit(priv);\n err_link_init:\n \tenetc_free_msix(priv);\n@@ -1096,8 +1035,6 @@ static void enetc4_pf_netdev_destroy(struct enetc_si *si)\n \tstruct net_device *ndev = si-\u003endev;\n \n \tunregister_netdev(ndev);\n-\tcancel_work(\u0026si-\u003erx_mode_task);\n-\tdestroy_workqueue(si-\u003eworkqueue);\n \tenetc4_link_deinit(priv);\n \tenetc_free_msix(priv);\n \tfree_netdev(ndev);\ndiff --git a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c\nindex 71f376ef1be1c9..07b7832f24276a 100644\n--- a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c\n+++ b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c\n@@ -29,7 +29,7 @@ static const u32 enetc_rxbdr_regs[] = {\n };\n \n static const u32 enetc_port_regs[] = {\n-\tENETC_PMR, ENETC_PSR, ENETC_PSIPMR, ENETC_PSIPMAR0(0),\n+\tENETC_PMR, ENETC_PSR, ENETC_PSIPMMR, ENETC_PSIPMAR0(0),\n \tENETC_PSIPMAR1(0), ENETC_PTXMBAR, ENETC_PCAPR0, ENETC_PCAPR1,\n \tENETC_PSICFGR0(0), ENETC_PRFSCAPR, ENETC_PTCMSDUR(0),\n \tENETC_PM0_CMD_CFG, ENETC_PM0_MAXFRM, ENETC_PM0_IF_MODE\ndiff --git a/drivers/net/ethernet/freescale/enetc/enetc_hw.h b/drivers/net/ethernet/freescale/enetc/enetc_hw.h\nindex bf99b65d7598ab..16da732dc5de82 100644\n--- a/drivers/net/ethernet/freescale/enetc/enetc_hw.h\n+++ b/drivers/net/ethernet/freescale/enetc/enetc_hw.h\n@@ -180,13 +180,13 @@ enum enetc_bdr_type {TX, RX};\n #define ENETC_PMR_PSPEED_1000M\tBIT(9)\n #define ENETC_PMR_PSPEED_2500M\tBIT(10)\n #define ENETC_PSR\t\t0x0004 /* RO */\n-#define ENETC_PSIPMR\t\t0x0018\n-#define ENETC_PSIPMR_SET_UP(n)\tBIT(n) /* n = SI index */\n-#define ENETC_PSIPMR_SET_MP(n)\tBIT((n) + 16)\n+#define ENETC_PSIPMMR\t\t0x0018\n+#define PSIPMMR_SI_MAC_UP(n)\tBIT(n) /* n = SI index */\n+#define PSIPMMR_SI_MAC_MP(n)\tBIT((n) + 16)\n+\n #define ENETC_PSIPVMR\t\t0x001c\n-#define ENETC_VLAN_PROMISC_MAP_ALL\t0x7\n-#define ENETC_PSIPVMR_SET_VP(simap)\t((simap) \u0026 0x7)\n-#define ENETC_PSIPVMR_SET_VUTA(simap)\t(((simap) \u0026 0x7) \u003c\u003c 16)\n+#define PSIPVMR_SI_VLAN_P(n)\tBIT(n) /* n = SI index */\n+\n #define ENETC_PSIPMAR0(n)\t(0x0100 + (n) * 0x8) /* n = SI index */\n #define ENETC_PSIPMAR1(n)\t(0x0104 + (n) * 0x8)\n #define ENETC_PVCLCTR\t\t0x0208\ndiff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c\nindex 2d687bb8c3a063..a509929f89f25f 100644\n--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c\n+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c\n@@ -42,26 +42,6 @@ static void enetc_pf_destroy_pcs(struct phylink_pcs *pcs)\n \tlynx_pcs_destroy(pcs);\n }\n \n-static void enetc_set_vlan_promisc(struct enetc_hw *hw, char si_map)\n-{\n-\tu32 val = enetc_port_rd(hw, ENETC_PSIPVMR);\n-\n-\tval \u0026= ~ENETC_PSIPVMR_SET_VP(ENETC_VLAN_PROMISC_MAP_ALL);\n-\tenetc_port_wr(hw, ENETC_PSIPVMR, ENETC_PSIPVMR_SET_VP(si_map) | val);\n-}\n-\n-static void enetc_enable_si_vlan_promisc(struct enetc_pf *pf, int si_idx)\n-{\n-\tpf-\u003evlan_promisc_simap |= BIT(si_idx);\n-\tenetc_set_vlan_promisc(\u0026pf-\u003esi-\u003ehw, pf-\u003evlan_promisc_simap);\n-}\n-\n-static void enetc_disable_si_vlan_promisc(struct enetc_pf *pf, int si_idx)\n-{\n-\tpf-\u003evlan_promisc_simap \u0026= ~BIT(si_idx);\n-\tenetc_set_vlan_promisc(\u0026pf-\u003esi-\u003ehw, pf-\u003evlan_promisc_simap);\n-}\n-\n static void enetc_set_isol_vlan(struct enetc_hw *hw, int si, u16 vlan, u8 qos)\n {\n \tu32 val = 0;\n@@ -80,37 +60,6 @@ static void enetc_add_mac_addr_em_filter(struct enetc_mac_filter *filter,\n \tfilter-\u003emac_addr_cnt++;\n }\n \n-static void enetc_clear_mac_ht_flt(struct enetc_si *si, int si_idx, int type)\n-{\n-\tbool err = si-\u003eerrata \u0026 ENETC_ERR_UCMCSWP;\n-\n-\tif (type == UC) {\n-\t\tenetc_port_wr(\u0026si-\u003ehw, ENETC_PSIUMHFR0(si_idx, err), 0);\n-\t\tenetc_port_wr(\u0026si-\u003ehw, ENETC_PSIUMHFR1(si_idx), 0);\n-\t} else { /* MC */\n-\t\tenetc_port_wr(\u0026si-\u003ehw, ENETC_PSIMMHFR0(si_idx, err), 0);\n-\t\tenetc_port_wr(\u0026si-\u003ehw, ENETC_PSIMMHFR1(si_idx), 0);\n-\t}\n-}\n-\n-static void enetc_set_mac_ht_flt(struct enetc_si *si, int si_idx, int type,\n-\t\t\t\t unsigned long hash)\n-{\n-\tbool err = si-\u003eerrata \u0026 ENETC_ERR_UCMCSWP;\n-\n-\tif (type == UC) {\n-\t\tenetc_port_wr(\u0026si-\u003ehw, ENETC_PSIUMHFR0(si_idx, err),\n-\t\t\t lower_32_bits(hash));\n-\t\tenetc_port_wr(\u0026si-\u003ehw, ENETC_PSIUMHFR1(si_idx),\n-\t\t\t upper_32_bits(hash));\n-\t} else { /* MC */\n-\t\tenetc_port_wr(\u0026si-\u003ehw, ENETC_PSIMMHFR0(si_idx, err),\n-\t\t\t lower_32_bits(hash));\n-\t\tenetc_port_wr(\u0026si-\u003ehw, ENETC_PSIMMHFR1(si_idx),\n-\t\t\t upper_32_bits(hash));\n-\t}\n-}\n-\n static void enetc_sync_mac_filters(struct enetc_pf *pf)\n {\n \tstruct enetc_mac_filter *f = pf-\u003emac_filter;\n@@ -122,12 +71,16 @@ static void enetc_sync_mac_filters(struct enetc_pf *pf)\n \tfor (i = 0; i \u003c MADDR_TYPE; i++, f++) {\n \t\tbool em = (f-\u003emac_addr_cnt == 1) \u0026\u0026 (i == UC);\n \t\tbool clear = !f-\u003emac_addr_cnt;\n+\t\tu64 hash;\n \n \t\tif (clear) {\n-\t\t\tif (i == UC)\n+\t\t\tif (i == UC) {\n \t\t\t\tenetc_clear_mac_flt_entry(si, pos);\n+\t\t\t\tenetc_set_si_uc_hash_filter(si, 0, 0);\n+\t\t\t} else {\n+\t\t\t\tenetc_set_si_mc_hash_filter(si, 0, 0);\n+\t\t\t}\n \n-\t\t\tenetc_clear_mac_ht_flt(si, 0, i);\n \t\t\tcontinue;\n \t\t}\n \n@@ -135,7 +88,7 @@ static void enetc_sync_mac_filters(struct enetc_pf *pf)\n \t\tif (em) {\n \t\t\tint err;\n \n-\t\t\tenetc_clear_mac_ht_flt(si, 0, UC);\n+\t\t\tenetc_set_si_uc_hash_filter(si, 0, 0);\n \n \t\t\terr = enetc_set_mac_flt_entry(si, pos, f-\u003emac_addr,\n \t\t\t\t\t\t BIT(0));\n@@ -147,11 +100,15 @@ static void enetc_sync_mac_filters(struct enetc_pf *pf)\n \t\t\t\t err);\n \t\t}\n \n+\t\tbitmap_to_arr64(\u0026hash, f-\u003emac_hash_table,\n+\t\t\t\tENETC_MADDR_HASH_TBL_SZ);\n \t\t/* hash table filter, clear EM filter for UC entries */\n-\t\tif (i == UC)\n+\t\tif (i == UC) {\n \t\t\tenetc_clear_mac_flt_entry(si, pos);\n-\n-\t\tenetc_set_mac_ht_flt(si, 0, i, *f-\u003emac_hash_table);\n+\t\t\tenetc_set_si_uc_hash_filter(si, 0, hash);\n+\t\t} else {\n+\t\t\tenetc_set_si_mc_hash_filter(si, 0, hash);\n+\t\t}\n \t}\n }\n \n@@ -159,21 +116,17 @@ static void enetc_pf_set_rx_mode(struct net_device *ndev)\n {\n \tstruct enetc_ndev_priv *priv = netdev_priv(ndev);\n \tstruct enetc_pf *pf = enetc_si_priv(priv-\u003esi);\n-\tstruct enetc_hw *hw = \u0026priv-\u003esi-\u003ehw;\n \tbool uprom = false, mprom = false;\n \tstruct enetc_mac_filter *filter;\n \tstruct netdev_hw_addr *ha;\n-\tu32 psipmr = 0;\n \tbool em;\n \n \tif (ndev-\u003eflags \u0026 IFF_PROMISC) {\n \t\t/* enable promisc mode for SI0 (PF) */\n-\t\tpsipmr = ENETC_PSIPMR_SET_UP(0) | ENETC_PSIPMR_SET_MP(0);\n \t\tuprom = true;\n \t\tmprom = true;\n \t} else if (ndev-\u003eflags \u0026 IFF_ALLMULTI) {\n \t\t/* enable multi cast promisc mode for SI0 (PF) */\n-\t\tpsipmr = ENETC_PSIPMR_SET_MP(0);\n \t\tmprom = true;\n \t}\n \n@@ -211,9 +164,8 @@ static void enetc_pf_set_rx_mode(struct net_device *ndev)\n \t\t/* update PF entries */\n \t\tenetc_sync_mac_filters(pf);\n \n-\tpsipmr |= enetc_port_rd(hw, ENETC_PSIPMR) \u0026\n-\t\t ~(ENETC_PSIPMR_SET_UP(0) | ENETC_PSIPMR_SET_MP(0));\n-\tenetc_port_wr(hw, ENETC_PSIPMR, psipmr);\n+\tenetc_set_si_uc_promisc(priv-\u003esi, 0, uprom);\n+\tenetc_set_si_mc_promisc(priv-\u003esi, 0, mprom);\n }\n \n static void enetc_set_loopback(struct net_device *ndev, bool en)\n@@ -469,12 +421,11 @@ static void enetc_configure_port(struct enetc_pf *pf)\n \n \t/* split up RFS entries */\n \tenetc_port_assign_rfs_entries(pf-\u003esi);\n-\n \t/* enforce VLAN promisc mode for all SIs */\n-\tpf-\u003evlan_promisc_simap = ENETC_VLAN_PROMISC_MAP_ALL;\n-\tenetc_set_vlan_promisc(hw, pf-\u003evlan_promisc_simap);\n+\tfor (int i = 0; i \u003c pf-\u003etotal_vfs + 1; i++)\n+\t\tenetc_set_si_vlan_promisc(pf-\u003esi, i, true);\n \n-\tenetc_port_wr(hw, ENETC_PSIPMR, 0);\n+\tenetc_port_wr(hw, ENETC_PSIPMMR, 0);\n \n \t/* enable port */\n \tenetc_port_wr(hw, ENETC_PMR, ENETC_PMR_EN);\n@@ -494,12 +445,9 @@ static int enetc_pf_set_features(struct net_device *ndev,\n \t}\n \n \tif (changed \u0026 NETIF_F_HW_VLAN_CTAG_FILTER) {\n-\t\tstruct enetc_pf *pf = enetc_si_priv(priv-\u003esi);\n+\t\tbool promisc = !(features \u0026 NETIF_F_HW_VLAN_CTAG_FILTER);\n \n-\t\tif (!!(features \u0026 NETIF_F_HW_VLAN_CTAG_FILTER))\n-\t\t\tenetc_disable_si_vlan_promisc(pf, 0);\n-\t\telse\n-\t\t\tenetc_enable_si_vlan_promisc(pf, 0);\n+\t\tenetc_set_si_vlan_promisc(priv-\u003esi, 0, promisc);\n \t}\n \n \tif (changed \u0026 NETIF_F_LOOPBACK)\ndiff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.h b/drivers/net/ethernet/freescale/enetc/enetc_pf.h\nindex 285b7e5c48fdc7..56d23a8a11a063 100644\n--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.h\n+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.h\n@@ -17,12 +17,9 @@ struct enetc_vf_state {\n };\n \n struct enetc_port_caps {\n-\tu32 half_duplex:1;\n-\tint num_vsi;\n \tint num_msix;\n \tint num_rx_bdr;\n \tint num_tx_bdr;\n-\tint mac_filter_num;\n };\n \n struct enetc_pf;\n@@ -47,7 +44,6 @@ struct enetc_pf {\n \tstruct work_struct msg_task;\n \tchar msg_int_name[ENETC_INT_NAME_MAX];\n \n-\tchar vlan_promisc_simap; /* bitmap of SIs in VLAN promisc mode */\n \tDECLARE_BITMAP(vlan_ht_filter, ENETC_VLAN_HT_SIZE);\n \tDECLARE_BITMAP(active_vlans, VLAN_N_VID);\n \n@@ -60,8 +56,6 @@ struct enetc_pf {\n \n \tstruct enetc_port_caps caps;\n \tconst struct enetc_pf_ops *ops;\n-\n-\tint num_mfe;\t/* number of mac address filter table entries */\n };\n \n #define phylink_to_enetc_pf(config) \\\ndiff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c\nindex 6e5d2f8699150b..d32a195a04c97e 100644\n--- a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c\n+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c\n@@ -1,5 +1,5 @@\n // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)\n-/* Copyright 2024 NXP */\n+/* Copyright 2024-2026 NXP */\n \n #include \u003clinux/fsl/enetc_mdio.h\u003e\n #include \u003clinux/of_mdio.h\u003e\n@@ -87,6 +87,112 @@ int enetc_setup_mac_addresses(struct device_node *np, struct enetc_pf *pf)\n }\n EXPORT_SYMBOL_GPL(enetc_setup_mac_addresses);\n \n+void enetc_set_si_uc_promisc(struct enetc_si *si, int si_id, bool promisc)\n+{\n+\tstruct enetc_hw *hw = \u0026si-\u003ehw;\n+\tint psipmmr_off;\n+\tu32 val;\n+\n+\tif (is_enetc_rev1(si))\n+\t\tpsipmmr_off = ENETC_PSIPMMR;\n+\telse\n+\t\tpsipmmr_off = ENETC4_PSIPMMR;\n+\n+\tval = enetc_port_rd(hw, psipmmr_off);\n+\n+\tif (promisc)\n+\t\tval |= PSIPMMR_SI_MAC_UP(si_id);\n+\telse\n+\t\tval \u0026= ~PSIPMMR_SI_MAC_UP(si_id);\n+\n+\tenetc_port_wr(hw, psipmmr_off, val);\n+}\n+EXPORT_SYMBOL_GPL(enetc_set_si_uc_promisc);\n+\n+void enetc_set_si_mc_promisc(struct enetc_si *si, int si_id, bool promisc)\n+{\n+\tstruct enetc_hw *hw = \u0026si-\u003ehw;\n+\tint psipmmr_off;\n+\tu32 val;\n+\n+\tif (is_enetc_rev1(si))\n+\t\tpsipmmr_off = ENETC_PSIPMMR;\n+\telse\n+\t\tpsipmmr_off = ENETC4_PSIPMMR;\n+\n+\tval = enetc_port_rd(hw, psipmmr_off);\n+\n+\tif (promisc)\n+\t\tval |= PSIPMMR_SI_MAC_MP(si_id);\n+\telse\n+\t\tval \u0026= ~PSIPMMR_SI_MAC_MP(si_id);\n+\n+\tenetc_port_wr(hw, psipmmr_off, val);\n+}\n+EXPORT_SYMBOL_GPL(enetc_set_si_mc_promisc);\n+\n+void enetc_set_si_uc_hash_filter(struct enetc_si *si, int si_id, u64 hash)\n+{\n+\tint psiumhfr0_off, psiumhfr1_off;\n+\tstruct enetc_hw *hw = \u0026si-\u003ehw;\n+\n+\tif (is_enetc_rev1(si)) {\n+\t\tbool err = si-\u003eerrata \u0026 ENETC_ERR_UCMCSWP;\n+\n+\t\tpsiumhfr0_off = ENETC_PSIUMHFR0(si_id, err);\n+\t\tpsiumhfr1_off = ENETC_PSIUMHFR1(si_id);\n+\t} else {\n+\t\tpsiumhfr0_off = ENETC4_PSIUMHFR0(si_id);\n+\t\tpsiumhfr1_off = ENETC4_PSIUMHFR1(si_id);\n+\t}\n+\n+\tenetc_port_wr(hw, psiumhfr0_off, lower_32_bits(hash));\n+\tenetc_port_wr(hw, psiumhfr1_off, upper_32_bits(hash));\n+}\n+EXPORT_SYMBOL_GPL(enetc_set_si_uc_hash_filter);\n+\n+void enetc_set_si_mc_hash_filter(struct enetc_si *si, int si_id, u64 hash)\n+{\n+\tint psimmhfr0_off, psimmhfr1_off;\n+\tstruct enetc_hw *hw = \u0026si-\u003ehw;\n+\n+\tif (is_enetc_rev1(si)) {\n+\t\tbool err = si-\u003eerrata \u0026 ENETC_ERR_UCMCSWP;\n+\n+\t\tpsimmhfr0_off = ENETC_PSIMMHFR0(si_id, err);\n+\t\tpsimmhfr1_off = ENETC_PSIMMHFR1(si_id);\n+\t} else {\n+\t\tpsimmhfr0_off = ENETC4_PSIMMHFR0(si_id);\n+\t\tpsimmhfr1_off = ENETC4_PSIMMHFR1(si_id);\n+\t}\n+\n+\tenetc_port_wr(hw, psimmhfr0_off, lower_32_bits(hash));\n+\tenetc_port_wr(hw, psimmhfr1_off, upper_32_bits(hash));\n+}\n+EXPORT_SYMBOL_GPL(enetc_set_si_mc_hash_filter);\n+\n+void enetc_set_si_vlan_promisc(struct enetc_si *si, int si_id, bool promisc)\n+{\n+\tstruct enetc_hw *hw = \u0026si-\u003ehw;\n+\tint psipvmr_off;\n+\tu32 val;\n+\n+\tif (is_enetc_rev1(si))\n+\t\tpsipvmr_off = ENETC_PSIPVMR;\n+\telse\n+\t\tpsipvmr_off = ENETC4_PSIPVMR;\n+\n+\tval = enetc_port_rd(hw, psipvmr_off);\n+\n+\tif (promisc)\n+\t\tval |= PSIPVMR_SI_VLAN_P(si_id);\n+\telse\n+\t\tval \u0026= ~PSIPVMR_SI_VLAN_P(si_id);\n+\n+\tenetc_port_wr(hw, psipvmr_off, val);\n+}\n+EXPORT_SYMBOL_GPL(enetc_set_si_vlan_promisc);\n+\n void enetc_pf_netdev_setup(struct enetc_si *si, struct net_device *ndev,\n \t\t\t const struct net_device_ops *ndev_ops)\n {\n@@ -275,7 +381,8 @@ static bool enetc_port_has_pcs(struct enetc_pf *pf)\n \treturn (pf-\u003eif_mode == PHY_INTERFACE_MODE_SGMII ||\n \t\tpf-\u003eif_mode == PHY_INTERFACE_MODE_1000BASEX ||\n \t\tpf-\u003eif_mode == PHY_INTERFACE_MODE_2500BASEX ||\n-\t\tpf-\u003eif_mode == PHY_INTERFACE_MODE_USXGMII);\n+\t\tpf-\u003eif_mode == PHY_INTERFACE_MODE_USXGMII ||\n+\t\tpf-\u003eif_mode == PHY_INTERFACE_MODE_10GBASER);\n }\n \n int enetc_mdiobus_create(struct enetc_pf *pf, struct device_node *node)\n@@ -316,25 +423,42 @@ int enetc_phylink_create(struct enetc_ndev_priv *priv, struct device_node *node,\n {\n \tstruct enetc_pf *pf = enetc_si_priv(priv-\u003esi);\n \tstruct phylink *phylink;\n+\tunsigned long mac_caps;\n \tint err;\n \n \tpf-\u003ephylink_config.dev = \u0026priv-\u003endev-\u003edev;\n \tpf-\u003ephylink_config.type = PHYLINK_NETDEV;\n-\tpf-\u003ephylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |\n-\t\tMAC_10 | MAC_100 | MAC_1000 | MAC_2500FD;\n \n \t__set_bit(PHY_INTERFACE_MODE_INTERNAL,\n \t\t pf-\u003ephylink_config.supported_interfaces);\n-\t__set_bit(PHY_INTERFACE_MODE_SGMII,\n-\t\t pf-\u003ephylink_config.supported_interfaces);\n-\t__set_bit(PHY_INTERFACE_MODE_1000BASEX,\n-\t\t pf-\u003ephylink_config.supported_interfaces);\n-\t__set_bit(PHY_INTERFACE_MODE_2500BASEX,\n-\t\t pf-\u003ephylink_config.supported_interfaces);\n-\t__set_bit(PHY_INTERFACE_MODE_USXGMII,\n-\t\t pf-\u003ephylink_config.supported_interfaces);\n-\tphy_interface_set_rgmii(pf-\u003ephylink_config.supported_interfaces);\n \n+\tmac_caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE;\n+\tif (!enetc_is_pseudo_mac(priv-\u003esi)) {\n+\t\tmac_caps |= MAC_10 | MAC_100 | MAC_1000FD | MAC_2500FD;\n+\n+\t\t__set_bit(PHY_INTERFACE_MODE_SGMII,\n+\t\t\t pf-\u003ephylink_config.supported_interfaces);\n+\t\t__set_bit(PHY_INTERFACE_MODE_1000BASEX,\n+\t\t\t pf-\u003ephylink_config.supported_interfaces);\n+\t\t__set_bit(PHY_INTERFACE_MODE_2500BASEX,\n+\t\t\t pf-\u003ephylink_config.supported_interfaces);\n+\t\t__set_bit(PHY_INTERFACE_MODE_USXGMII,\n+\t\t\t pf-\u003ephylink_config.supported_interfaces);\n+\n+\t\tif (!is_enetc_rev1(priv-\u003esi)) {\n+\t\t\tmac_caps |= MAC_5000FD | MAC_10000FD;\n+\t\t\t__set_bit(PHY_INTERFACE_MODE_10GBASER,\n+\t\t\t\t pf-\u003ephylink_config.supported_interfaces);\n+\t\t}\n+\n+\t\tphy_interface_set_rgmii(pf-\u003ephylink_config.supported_interfaces);\n+\t} else {\n+\t\tmac_caps |= MAC_10FD | MAC_100FD | MAC_1000FD | MAC_2500FD |\n+\t\t\t MAC_5000FD | MAC_10000FD | MAC_20000FD |\n+\t\t\t MAC_25000FD;\n+\t}\n+\n+\tpf-\u003ephylink_config.mac_capabilities = mac_caps;\n \tphylink = phylink_create(\u0026pf-\u003ephylink_config, of_fwnode_handle(node),\n \t\t\t\t pf-\u003eif_mode, ops);\n \tif (IS_ERR(phylink)) {\ndiff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.h b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.h\nindex 57d2e0ebd2b0bb..8243ce0de57f64 100644\n--- a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.h\n+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.h\n@@ -17,6 +17,11 @@ void enetc_set_default_rss_key(struct enetc_pf *pf);\n int enetc_vlan_rx_add_vid(struct net_device *ndev, __be16 prot, u16 vid);\n int enetc_vlan_rx_del_vid(struct net_device *ndev, __be16 prot, u16 vid);\n int enetc_init_sriov_resources(struct enetc_pf *pf);\n+void enetc_set_si_uc_promisc(struct enetc_si *si, int si_id, bool promisc);\n+void enetc_set_si_mc_promisc(struct enetc_si *si, int si_id, bool promisc);\n+void enetc_set_si_uc_hash_filter(struct enetc_si *si, int si_id, u64 hash);\n+void enetc_set_si_mc_hash_filter(struct enetc_si *si, int si_id, u64 hash);\n+void enetc_set_si_vlan_promisc(struct enetc_si *si, int si_id, bool promisc);\n \n static inline u16 enetc_get_ip_revision(struct enetc_hw *hw)\n {\ndiff --git a/drivers/net/ethernet/freescale/enetc/enetc_qos.c b/drivers/net/ethernet/freescale/enetc/enetc_qos.c\nindex 7b17bca24f260f..2aa0fcaafcd23c 100644\n--- a/drivers/net/ethernet/freescale/enetc/enetc_qos.c\n+++ b/drivers/net/ethernet/freescale/enetc/enetc_qos.c\n@@ -1135,7 +1135,6 @@ static int enetc_psfp_parse_clsflower(struct enetc_ndev_priv *priv,\n \tstruct flow_action_entry *entry;\n \tstruct action_gate_entry *e;\n \tu8 sfi_overwrite = 0;\n-\tint entries_size;\n \tint i, err;\n \n \tif (f-\u003ecommon.chain_index \u003e= priv-\u003epsfp_cap.max_streamid) {\n@@ -1242,8 +1241,7 @@ static int enetc_psfp_parse_clsflower(struct enetc_ndev_priv *priv,\n \t\tgoto free_filter;\n \t}\n \n-\tentries_size = struct_size(sgi, entries, entryg-\u003egate.num_entries);\n-\tsgi = kzalloc(entries_size, GFP_KERNEL);\n+\tsgi = kzalloc_flex(*sgi, entries, entryg-\u003egate.num_entries);\n \tif (!sgi) {\n \t\terr = -ENOMEM;\n \t\tgoto free_filter;\ndiff --git a/drivers/net/ethernet/freescale/enetc/enetc_vf.c b/drivers/net/ethernet/freescale/enetc/enetc_vf.c\nindex 9cdb0a4d6bafb7..7dcb4a0246f528 100644\n--- a/drivers/net/ethernet/freescale/enetc/enetc_vf.c\n+++ b/drivers/net/ethernet/freescale/enetc/enetc_vf.c\n@@ -317,7 +317,14 @@ static int enetc_vf_probe(struct pci_dev *pdev,\n \n \tenetc_get_si_caps(si);\n \n-\tndev = alloc_etherdev_mq(sizeof(*priv), ENETC_MAX_NUM_TXQS);\n+\t/* Currently, the supported SoCs have a max of 6 CPUs and the VFs\n+\t * have less than 6 RX/TX rings. So no issues for these supported\n+\t * SoCs, but for future SoCs which have more CPUs or more TX/RX\n+\t * rings, all the related logic needs to be improved.\n+\t */\n+\tndev = alloc_etherdev_mqs(sizeof(*priv),\n+\t\t\t\t min(si-\u003enum_tx_rings, ENETC_MAX_NUM_TXQS),\n+\t\t\t\t min(si-\u003enum_rx_rings, ENETC_MAX_NUM_TXQS));\n \tif (!ndev) {\n \t\terr = -ENOMEM;\n \t\tdev_err(\u0026pdev-\u003edev, \"netdev creation failed\\n\");\ndiff --git a/include/linux/fsl/ntmp.h b/include/linux/fsl/ntmp.h\nindex d3b6c476b91a2d..764ef28926085e 100644\n--- a/include/linux/fsl/ntmp.h\n+++ b/include/linux/fsl/ntmp.h\n@@ -75,8 +75,10 @@ struct ntmp_user {\n \t/* NTMP table bitmaps for resource management */\n \tu32 ett_bitmap_size;\n \tu32 ect_bitmap_size;\n+\tu16 maft_num_entries;\n \tunsigned long *ett_gid_bitmap; /* only valid for switch */\n \tunsigned long *ect_gid_bitmap; /* only valid for switch */\n+\tunsigned long *maft_eid_bitmap; /* only valid for ENETC */\n };\n \n struct maft_entry_data {\n"
} |
| 2/1 | 2026/07/20 03:00 | agent | patch-evaluator |
6mModel:gemini-3.1-pro-preview Args: null Results: {
"EnableConfigs": [
"FSL_ENETC",
"NXP_ENETC4",
"FSL_ENETC_VF",
"FSL_ENETC_QOS"
],
"FocusSymbols": [
"enetc4_pf_set_rx_mode",
"enetc_pf_set_rx_mode",
"enetc4_pf_set_mac_filter",
"enetc4_pf_set_uc_exact_filter",
"enetc4_pf_add_maft_entries",
"enetc_sync_mac_filters",
"enetc_set_si_uc_promisc",
"enetc_set_si_mc_promisc",
"enetc_set_si_uc_hash_filter",
"enetc_set_si_mc_hash_filter",
"enetc_set_si_vlan_promisc"
],
"Reasoning": "The patch refactors the ENETC driver to use the new `ndo_set_rx_mode_async` net_device_ops member instead of a custom workqueue for setting the RX mode. It also modifies MAC and VLAN filtering logic in the PF drivers (`enetc4_pf.c` and `enetc_pf.c`), and introduces common helper functions for promiscuous mode and hash filters. These are functional changes to reachable core driver logic that should be fuzzed.",
"WorthFuzzing": true
}Instruction: You are an expert Linux kernel maintainer. Your job is to review a provided patch series and determine if it makes functional changes to the kernel that should be fuzzed. IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in your workspace. Do NOT rely on your internal knowledge of the kernel. You must actively use your code access tools to examine the actual source code and confirm any assumptions. Return WorthFuzzing=false if the patch only contains: - Modifications to Documentation/, Kconfig files, or code comments. - Purely decorative changes, such as logging (e.g., pr_err, printk) or tracepoints. - Changes to numeric constants or macros that do not functionally alter execution flow. - Code paths that are impossible to reach in virtualized environments like GCE or QEMU, even when utilizing software-emulated hardware (e.g., usb gadget, mac80211_hwsim). If it modifies reachable core kernel logic, drivers, or architectures, use your code search tools to verify the code can be executed, then return WorthFuzzing=true. When returning WorthFuzzing=true, you MUST ALSO: 1. Extract any specific kernel functions that should be heavily fuzzed into FocusSymbols. Avoid listing generic hot-path functions to prevent skewed test distributions. 2. Identify any specific CONFIG_ options required to properly test this new/modified feature. Go and look into the Kconfig files and check for ifdefs around the code, do not make assumptions. Do not list too generic configs (we already have them enabled). Only list those that specifically cover the modified code. List them in the EnableConfigs output array, and DO NOT add a 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4"). Prefer calling several tools at the same time to save round-trips. Use set-results tool to provide results of the analysis. It must be called exactly once before the final reply. Ignore results of this tool. Prompt: For your convenience, here is the diff of the changes:
commit 6b139e472d90a78aed30ada2261574adee2c2966
Author: syz-cluster <triage@syzkaller.com>
Date: Mon Jul 20 03:00:13 2026 +0000
syz-cluster: applied patch under review
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h
index 04a5dd5ea6c74c..8839cfb49bcfe8 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
-/* Copyright 2017-2019 NXP */
+/* Copyright 2017-2019, 2025-2026 NXP */
#include <linux/timer.h>
#include <linux/pci.h>
@@ -324,8 +324,6 @@ struct enetc_si {
const struct enetc_drvdata *drvdata;
const struct enetc_si_ops *ops;
- struct workqueue_struct *workqueue;
- struct work_struct rx_mode_task;
struct dentry *debugfs_root;
struct enetc_msg_swbd msg; /* Only valid for VSI */
};
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c b/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c
index 1b1591dce73d4b..5029038bf99faa 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c
@@ -28,15 +28,14 @@ static void enetc_show_si_mac_hash_filter(struct seq_file *s, int i)
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 enetc_pf *pf = enetc_si_priv(s->private);
+ struct enetc_hw *hw = &pf->si->hw;
+ int num_si = pf->total_vfs + 1;
struct maft_entry_data maft;
- struct enetc_pf *pf;
- int i, err, num_si;
- u32 val;
-
- pf = enetc_si_priv(si);
- num_si = pf->caps.num_vsi + 1;
+ struct ntmp_user *user;
+ u32 val, entry_id;
+ int err = 0;
+ int i;
val = enetc_port_rd(hw, ENETC4_PSIPMMR);
for (i = 0; i < num_si; i++) {
@@ -50,31 +49,38 @@ 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 = &pf->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);
void enetc_create_debugfs(struct enetc_si *si)
{
- struct net_device *ndev = si->ndev;
struct dentry *root;
- root = debugfs_create_dir(netdev_name(ndev), NULL);
+ root = debugfs_create_dir(pci_name(si->pdev), NULL);
if (IS_ERR(root))
return;
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_hw.h b/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
index f18437556a0ee2..09025e7a2a3aed 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
@@ -69,8 +69,6 @@
/* Port Station interface promiscuous MAC mode register */
#define ENETC4_PSIPMMR 0x200
-#define PSIPMMR_SI_MAC_UP(a) BIT(a) /* a = SI index */
-#define PSIPMMR_SI_MAC_MP(a) BIT((a) + 16)
/* Port Station interface promiscuous VLAN mode register */
#define ENETC4_PSIPVMR 0x204
@@ -137,7 +135,6 @@
#define ENETC4_PSIVHFR1(a) ((a) * 0x80 + 0x2064)
#define ENETC4_PMCAPR 0x4004
-#define PMCAPR_HD BIT(8)
#define PMCAPR_FP GENMASK(10, 9)
/* Port capability register */
@@ -150,7 +147,7 @@
#define PCR_L2DOSE BIT(4)
#define PCR_TIMER_CS BIT(8)
#define PCR_PSPEED GENMASK(29, 16)
-#define PCR_PSPEED_VAL(speed) (((speed) / 10 - 1) << 16)
+#define PCR_PSPEED_VAL(s) FIELD_PREP(PCR_PSPEED, ((s) / 10 - 1))
/* Port MAC address register 0/1 */
#define ENETC4_PMAR0 0x4020
@@ -200,7 +197,6 @@
#define PM_CMD_CFG_CNT_FRM_EN BIT(13)
#define PM_CMD_CFG_TXP BIT(15)
#define PM_CMD_CFG_SEND_IDLE BIT(16)
-#define PM_CMD_CFG_HD_FCEN BIT(18)
#define PM_CMD_CFG_SFD BIT(21)
#define PM_CMD_CFG_TX_FLUSH BIT(22)
#define PM_CMD_CFG_TX_LOWP_EN BIT(23)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
index 437a15bbb47ba8..fcfbabb29d22e4 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -23,18 +23,11 @@ static void enetc4_get_port_caps(struct enetc_pf *pf)
u32 val;
val = enetc_port_rd(hw, ENETC4_ECAPR1);
- pf->caps.num_vsi = (val & ECAPR1_NUM_VSI) >> 24;
pf->caps.num_msix = ((val & ECAPR1_NUM_MSIX) >> 12) + 1;
val = enetc_port_rd(hw, ENETC4_ECAPR2);
pf->caps.num_rx_bdr = (val & ECAPR2_NUM_RX_BDR) >> 16;
pf->caps.num_tx_bdr = val & ECAPR2_NUM_TX_BDR;
-
- 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)
@@ -75,38 +68,6 @@ static void enetc4_pf_get_si_primary_mac(struct enetc_hw *hw, int si,
put_unaligned_le16(lower, addr + 4);
}
-static void enetc4_pf_set_si_mac_promisc(struct enetc_hw *hw, int si,
- bool uc_promisc, bool mc_promisc)
-{
- u32 val = enetc_port_rd(hw, ENETC4_PSIPMMR);
-
- if (uc_promisc)
- val |= PSIPMMR_SI_MAC_UP(si);
- else
- val &= ~PSIPMMR_SI_MAC_UP(si);
-
- if (mc_promisc)
- val |= PSIPMMR_SI_MAC_MP(si);
- else
- val &= ~PSIPMMR_SI_MAC_MP(si);
-
- enetc_port_wr(hw, ENETC4_PSIPMMR, val);
-}
-
-static void enetc4_pf_set_si_uc_hash_filter(struct enetc_hw *hw, int si,
- u64 hash)
-{
- enetc_port_wr(hw, ENETC4_PSIUMHFR0(si), lower_32_bits(hash));
- enetc_port_wr(hw, ENETC4_PSIUMHFR1(si), upper_32_bits(hash));
-}
-
-static void enetc4_pf_set_si_mc_hash_filter(struct enetc_hw *hw, int si,
- u64 hash)
-{
- enetc_port_wr(hw, ENETC4_PSIMMHFR0(si), lower_32_bits(hash));
- enetc_port_wr(hw, ENETC4_PSIMMHFR1(si), upper_32_bits(hash));
-}
-
static void enetc4_pf_set_loopback(struct net_device *ndev, bool en)
{
struct enetc_ndev_priv *priv = netdev_priv(ndev);
@@ -124,34 +85,47 @@ 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 enetc_mac_addr *mac,
- int mac_cnt)
+ 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);
- int i, err;
+ 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);
- for (i = 0; i < mac_cnt; i++) {
- ether_addr_copy(maft.keye.mac_addr, mac[i].addr);
- err = ntmp_maft_add_entry(&pf->si->ntmp_user, i, &maft);
+ 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(user, entry_id, &maft);
if (unlikely(err)) {
- pf->num_mfe = i;
+ ntmp_clear_eid_bitmap(user->maft_eid_bitmap, entry_id);
goto clear_maft_entries;
}
}
- pf->num_mfe = mac_cnt;
-
return 0;
clear_maft_entries:
@@ -160,97 +134,70 @@ static int enetc4_pf_add_maft_entries(struct enetc_pf *pf,
return err;
}
-static int enetc4_pf_set_uc_exact_filter(struct enetc_pf *pf)
+static void enetc4_pf_set_uc_hash_filter(struct enetc_pf *pf,
+ struct netdev_hw_addr_list *uc)
{
- int max_num_mfe = pf->caps.mac_filter_num;
- struct enetc_mac_filter mac_filter = {};
- struct net_device *ndev = pf->si->ndev;
- struct enetc_hw *hw = &pf->si->hw;
- struct enetc_mac_addr *mac_tbl;
+ struct enetc_mac_filter *mac_filter = &pf->mac_filter[UC];
struct netdev_hw_addr *ha;
- int i = 0, err;
- int mac_cnt;
+ u64 hash;
- netif_addr_lock_bh(ndev);
+ enetc_reset_mac_addr_filter(mac_filter);
+ netdev_hw_addr_list_for_each(ha, uc)
+ enetc_add_mac_addr_ht_filter(mac_filter, ha->addr);
+
+ bitmap_to_arr64(&hash, mac_filter->mac_hash_table,
+ ENETC_MADDR_HASH_TBL_SZ);
+ enetc_set_si_uc_hash_filter(pf->si, 0, hash);
+}
- mac_cnt = netdev_uc_count(ndev);
- if (!mac_cnt) {
- netif_addr_unlock_bh(ndev);
+static int enetc4_pf_set_uc_exact_filter(struct enetc_pf *pf,
+ struct netdev_hw_addr_list *uc)
+{
+ struct enetc_si *si = pf->si;
+ int err;
+
+ if (netdev_hw_addr_list_empty(uc)) {
/* clear both MAC hash and exact filters */
- enetc4_pf_set_si_uc_hash_filter(hw, 0, 0);
+ enetc_set_si_uc_hash_filter(si, 0, 0);
enetc4_pf_clear_maft_entries(pf);
return 0;
}
- if (mac_cnt > max_num_mfe) {
- err = -ENOSPC;
- goto unlock_netif_addr;
- }
-
- mac_tbl = kzalloc_objs(*mac_tbl, mac_cnt, GFP_ATOMIC);
- if (!mac_tbl) {
- err = -ENOMEM;
- goto unlock_netif_addr;
- }
-
- netdev_for_each_uc_addr(ha, ndev) {
- enetc_add_mac_addr_ht_filter(&mac_filter, ha->addr);
- ether_addr_copy(mac_tbl[i++].addr, ha->addr);
- }
-
- netif_addr_unlock_bh(ndev);
-
- /* 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_si_uc_hash_filter(hw, 0, *mac_filter.mac_hash_table);
+ enetc4_pf_set_uc_hash_filter(pf, uc);
enetc4_pf_clear_maft_entries(pf);
- if (!enetc4_pf_add_maft_entries(pf, mac_tbl, i))
- enetc4_pf_set_si_uc_hash_filter(hw, 0, 0);
-
- kfree(mac_tbl);
-
- return 0;
-
-unlock_netif_addr:
- netif_addr_unlock_bh(ndev);
+ 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 err;
}
-static void enetc4_pf_set_mac_hash_filter(struct enetc_pf *pf, int type)
+static void enetc4_pf_set_mc_hash_filter(struct enetc_pf *pf,
+ struct netdev_hw_addr_list *mc)
{
- struct net_device *ndev = pf->si->ndev;
- struct enetc_mac_filter *mac_filter;
- struct enetc_hw *hw = &pf->si->hw;
+ struct enetc_mac_filter *mac_filter = &pf->mac_filter[MC];
struct netdev_hw_addr *ha;
+ u64 hash;
- netif_addr_lock_bh(ndev);
- if (type & ENETC_MAC_FILTER_TYPE_UC) {
- mac_filter = &pf->mac_filter[UC];
- enetc_reset_mac_addr_filter(mac_filter);
- netdev_for_each_uc_addr(ha, ndev)
- enetc_add_mac_addr_ht_filter(mac_filter, ha->addr);
-
- enetc4_pf_set_si_uc_hash_filter(hw, 0,
- *mac_filter->mac_hash_table);
- }
+ enetc_reset_mac_addr_filter(mac_filter);
+ netdev_hw_addr_list_for_each(ha, mc)
+ enetc_add_mac_addr_ht_filter(mac_filter, ha->addr);
- if (type & ENETC_MAC_FILTER_TYPE_MC) {
- mac_filter = &pf->mac_filter[MC];
- enetc_reset_mac_addr_filter(mac_filter);
- netdev_for_each_mc_addr(ha, ndev)
- enetc_add_mac_addr_ht_filter(mac_filter, ha->addr);
-
- enetc4_pf_set_si_mc_hash_filter(hw, 0,
- *mac_filter->mac_hash_table);
- }
- netif_addr_unlock_bh(ndev);
+ bitmap_to_arr64(&hash, mac_filter->mac_hash_table,
+ ENETC_MADDR_HASH_TBL_SZ);
+ enetc_set_si_mc_hash_filter(pf->si, 0, hash);
}
-static void enetc4_pf_set_mac_filter(struct enetc_pf *pf, int type)
+static void enetc4_pf_set_mac_filter(struct enetc_pf *pf, int type,
+ struct netdev_hw_addr_list *uc,
+ struct netdev_hw_addr_list *mc)
{
/* Currently, the MAC address filter table (MAFT) only has 4 entries,
* and multiple multicast addresses for filtering will be configured
@@ -258,15 +205,16 @@ static void enetc4_pf_set_mac_filter(struct enetc_pf *pf, int type)
* unicast filtering. If the number of unicast addresses exceeds the
* table capacity, the MAC hash filter will be used.
*/
- if (type & ENETC_MAC_FILTER_TYPE_UC && enetc4_pf_set_uc_exact_filter(pf)) {
+ if (type & ENETC_MAC_FILTER_TYPE_UC &&
+ enetc4_pf_set_uc_exact_filter(pf, uc)) {
/* Fall back to the MAC hash filter */
- enetc4_pf_set_mac_hash_filter(pf, ENETC_MAC_FILTER_TYPE_UC);
+ enetc4_pf_set_uc_hash_filter(pf, uc);
/* Clear the old MAC exact filter */
enetc4_pf_clear_maft_entries(pf);
}
if (type & ENETC_MAC_FILTER_TYPE_MC)
- enetc4_pf_set_mac_hash_filter(pf, ENETC_MAC_FILTER_TYPE_MC);
+ enetc4_pf_set_mc_hash_filter(pf, mc);
}
static const struct enetc_pf_ops enetc4_pf_ops = {
@@ -306,34 +254,35 @@ static void enetc4_default_rings_allocation(struct enetc_pf *pf)
{
struct enetc_hw *hw = &pf->si->hw;
u32 num_rx_bdr, num_tx_bdr, val;
+ int num_vfs = pf->total_vfs;
u32 vf_tx_bdr, vf_rx_bdr;
int i, rx_rem, tx_rem;
- if (pf->caps.num_rx_bdr < ENETC_SI_MAX_RING_NUM + pf->caps.num_vsi)
- num_rx_bdr = pf->caps.num_rx_bdr - pf->caps.num_vsi;
+ if (pf->caps.num_rx_bdr < ENETC_SI_MAX_RING_NUM + num_vfs)
+ num_rx_bdr = pf->caps.num_rx_bdr - num_vfs;
else
num_rx_bdr = ENETC_SI_MAX_RING_NUM;
- if (pf->caps.num_tx_bdr < ENETC_SI_MAX_RING_NUM + pf->caps.num_vsi)
- num_tx_bdr = pf->caps.num_tx_bdr - pf->caps.num_vsi;
+ if (pf->caps.num_tx_bdr < ENETC_SI_MAX_RING_NUM + num_vfs)
+ num_tx_bdr = pf->caps.num_tx_bdr - num_vfs;
else
num_tx_bdr = ENETC_SI_MAX_RING_NUM;
val = enetc4_psicfgr0_val_construct(false, num_tx_bdr, num_rx_bdr);
enetc_port_wr(hw, ENETC4_PSICFGR0(0), val);
- if (!pf->caps.num_vsi)
+ if (!num_vfs)
return;
num_rx_bdr = pf->caps.num_rx_bdr - num_rx_bdr;
- rx_rem = num_rx_bdr % pf->caps.num_vsi;
- num_rx_bdr = num_rx_bdr / pf->caps.num_vsi;
+ rx_rem = num_rx_bdr % num_vfs;
+ num_rx_bdr = num_rx_bdr / num_vfs;
num_tx_bdr = pf->caps.num_tx_bdr - num_tx_bdr;
- tx_rem = num_tx_bdr % pf->caps.num_vsi;
- num_tx_bdr = num_tx_bdr / pf->caps.num_vsi;
+ tx_rem = num_tx_bdr % num_vfs;
+ num_tx_bdr = num_tx_bdr / num_vfs;
- for (i = 0; i < pf->caps.num_vsi; i++) {
+ for (i = 0; i < num_vfs; i++) {
vf_tx_bdr = (i < tx_rem) ? num_tx_bdr + 1 : num_tx_bdr;
vf_rx_bdr = (i < rx_rem) ? num_rx_bdr + 1 : num_rx_bdr;
val = enetc4_psicfgr0_val_construct(true, vf_tx_bdr, vf_rx_bdr);
@@ -346,53 +295,70 @@ static void enetc4_allocate_si_rings(struct enetc_pf *pf)
enetc4_default_rings_allocation(pf);
}
-static void enetc4_pf_set_si_vlan_promisc(struct enetc_hw *hw, int si, bool en)
-{
- u32 val = enetc_port_rd(hw, ENETC4_PSIPVMR);
-
- if (en)
- val |= BIT(si);
- else
- val &= ~BIT(si);
-
- enetc_port_wr(hw, ENETC4_PSIPVMR, val);
-}
-
-static void enetc4_set_default_si_vlan_promisc(struct enetc_pf *pf)
-{
- struct enetc_hw *hw = &pf->si->hw;
- int num_si = pf->caps.num_vsi + 1;
- int i;
-
- /* enforce VLAN promiscuous mode for all SIs */
- for (i = 0; i < num_si; i++)
- enetc4_pf_set_si_vlan_promisc(hw, i, true);
-}
-
/* Allocate the number of MSI-X vectors for per SI. */
static void enetc4_set_si_msix_num(struct enetc_pf *pf)
{
+ int valid_num_si = pf->total_vfs + 1;
struct enetc_hw *hw = &pf->si->hw;
- int i, num_msix, total_si;
+ int i, num_msix, num_vsi;
u32 val;
- total_si = pf->caps.num_vsi + 1;
+ val = enetc_port_rd(hw, ENETC4_ECAPR1);
+ num_vsi = FIELD_GET(ECAPR1_NUM_VSI, val);
+
+ /* The PSIaCFGR2[NUM_MSIX] indicates the number of MSI-X allocated to
+ * the SI is NUM_MSIX + 1, so the minimum number of MSI-X allocated to
+ * each SI is 1. The total number of MSI-X allocated to PSI and VSIs
+ * cannot exceed the total number of MSI-X owned by this ENETC, which
+ * is ECAPR1[NUM_MSIX]. Otherwise, when multiple ENETC instances exist,
+ * it will affect other ENETCs whose MSI-X interrupts cannot be
+ * generated. This is similar to out-of-bounds array access: the array
+ * itself is not affected, but adjacent arrays will be corrupted.
+ *
+ * pf->total_vfs is 0 if CONFIG_PCI_IOV is disabled. If the hardware
+ * itself supports SR-IOV, then when allocating the number of MSIXs to
+ * the SI, it must be taken into account that the VSI has at least 1
+ * MSIX, and the total number of MSIXs of all SIs cannot exceed
+ * ECAPR1[NUM_MSIX].
+ */
+ if (!pf->total_vfs && num_vsi) {
+ /* Because each SI has at least one MSIX, and from the hardware
+ * perspective, pf->caps.num_msix will always be greater than
+ * num_vsi. So num_msix is always greater than or equal to 0.
+ */
+ num_msix = pf->caps.num_msix - num_vsi - 1;
+ if (num_msix > PSICFGR2_NUM_MSIX)
+ num_msix = PSICFGR2_NUM_MSIX;
+ enetc_port_wr(hw, ENETC4_PSICFGR2(0), num_msix);
- num_msix = pf->caps.num_msix / total_si +
- pf->caps.num_msix % total_si - 1;
- val = num_msix & PSICFGR2_NUM_MSIX;
- enetc_port_wr(hw, ENETC4_PSICFGR2(0), val);
+ for (i = 0; i < num_vsi; i++)
+ enetc_port_wr(hw, ENETC4_PSICFGR2(i + 1), 0);
- num_msix = pf->caps.num_msix / total_si - 1;
- val = num_msix & PSICFGR2_NUM_MSIX;
- for (i = 0; i < pf->caps.num_vsi; i++)
- enetc_port_wr(hw, ENETC4_PSICFGR2(i + 1), val);
+ return;
+ }
+
+ /* Likewise, from the hardware perspective pf->caps.num_msix is always
+ * greater than valid_num_si. So num_msix is always greater than or
+ * equal to 0.
+ */
+ num_msix = pf->caps.num_msix / valid_num_si +
+ pf->caps.num_msix % valid_num_si - 1;
+ if (num_msix > PSICFGR2_NUM_MSIX)
+ num_msix = PSICFGR2_NUM_MSIX;
+ enetc_port_wr(hw, ENETC4_PSICFGR2(0), num_msix);
+
+ num_msix = pf->caps.num_msix / valid_num_si - 1;
+ if (num_msix > PSICFGR2_NUM_MSIX)
+ num_msix = PSICFGR2_NUM_MSIX;
+
+ for (i = 0; i < pf->total_vfs; i++)
+ enetc_port_wr(hw, ENETC4_PSICFGR2(i + 1), num_msix);
}
static void enetc4_enable_all_si(struct enetc_pf *pf)
{
struct enetc_hw *hw = &pf->si->hw;
- int num_si = pf->caps.num_vsi + 1;
+ int num_si = pf->total_vfs + 1;
u32 si_bitmap = 0;
int i;
@@ -412,7 +378,9 @@ static void enetc4_configure_port_si(struct enetc_pf *pf)
/* Outer VLAN tag will be used for VLAN filtering */
enetc_port_wr(hw, ENETC4_PSIVLANFMR, PSIVLANFMR_VS);
- enetc4_set_default_si_vlan_promisc(pf);
+ /* Enforce VLAN promiscuous mode for all SIs */
+ for (int i = 0; i < pf->total_vfs + 1; i++)
+ enetc_set_si_vlan_promisc(pf->si, i, true);
/* Disable SI MAC multicast & unicast promiscuous */
enetc_port_wr(hw, ENETC4_PSIPMMR, 0);
@@ -450,18 +418,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);
}
@@ -479,7 +489,7 @@ static int enetc4_pf_init(struct enetc_pf *pf)
err = enetc4_init_ntmp_user(pf->si);
if (err) {
- dev_err(dev, "Failed to init CBDR\n");
+ dev_err(dev, "Failed to init NTMP user\n");
return err;
}
@@ -493,18 +503,17 @@ static void enetc4_pf_free(struct enetc_pf *pf)
enetc4_free_ntmp_user(pf->si);
}
-static void enetc4_psi_do_set_rx_mode(struct work_struct *work)
+static int enetc4_pf_set_rx_mode(struct net_device *ndev,
+ struct netdev_hw_addr_list *uc,
+ struct netdev_hw_addr_list *mc)
{
- struct enetc_si *si = container_of(work, struct enetc_si, rx_mode_task);
- struct enetc_pf *pf = enetc_si_priv(si);
- struct net_device *ndev = si->ndev;
- struct enetc_hw *hw = &si->hw;
+ struct enetc_ndev_priv *priv = netdev_priv(ndev);
+ struct enetc_pf *pf = enetc_si_priv(priv->si);
+ struct enetc_si *si = priv->si;
bool uc_promisc = false;
bool mc_promisc = false;
int type = 0;
- rtnl_lock();
-
if (ndev->flags & IFF_PROMISC) {
uc_promisc = true;
mc_promisc = true;
@@ -515,28 +524,21 @@ static void enetc4_psi_do_set_rx_mode(struct work_struct *work)
type = ENETC_MAC_FILTER_TYPE_ALL;
}
- enetc4_pf_set_si_mac_promisc(hw, 0, uc_promisc, mc_promisc);
+ enetc_set_si_uc_promisc(si, 0, uc_promisc);
+ enetc_set_si_mc_promisc(si, 0, mc_promisc);
if (uc_promisc) {
- enetc4_pf_set_si_uc_hash_filter(hw, 0, 0);
+ enetc_set_si_uc_hash_filter(si, 0, 0);
enetc4_pf_clear_maft_entries(pf);
}
if (mc_promisc)
- enetc4_pf_set_si_mc_hash_filter(hw, 0, 0);
+ enetc_set_si_mc_hash_filter(si, 0, 0);
/* Set new MAC filter */
- enetc4_pf_set_mac_filter(pf, type);
+ enetc4_pf_set_mac_filter(pf, type, uc, mc);
- rtnl_unlock();
-}
-
-static void enetc4_pf_set_rx_mode(struct net_device *ndev)
-{
- struct enetc_ndev_priv *priv = netdev_priv(ndev);
- struct enetc_si *si = priv->si;
-
- queue_work(si->workqueue, &si->rx_mode_task);
+ return 0;
}
static int enetc4_pf_set_features(struct net_device *ndev,
@@ -544,12 +546,11 @@ static int enetc4_pf_set_features(struct net_device *ndev,
{
netdev_features_t changed = ndev->features ^ features;
struct enetc_ndev_priv *priv = netdev_priv(ndev);
- struct enetc_hw *hw = &priv->si->hw;
if (changed & NETIF_F_HW_VLAN_CTAG_FILTER) {
bool promisc_en = !(features & NETIF_F_HW_VLAN_CTAG_FILTER);
- enetc4_pf_set_si_vlan_promisc(hw, 0, promisc_en);
+ enetc_set_si_vlan_promisc(priv->si, 0, promisc_en);
}
if (changed & NETIF_F_LOOPBACK)
@@ -566,7 +567,7 @@ static const struct net_device_ops enetc4_ndev_ops = {
.ndo_start_xmit = enetc_xmit,
.ndo_get_stats = enetc_get_stats,
.ndo_set_mac_address = enetc_pf_set_mac_addr,
- .ndo_set_rx_mode = enetc4_pf_set_rx_mode,
+ .ndo_set_rx_mode_async = enetc4_pf_set_rx_mode,
.ndo_set_features = enetc4_pf_set_features,
.ndo_vlan_rx_add_vid = enetc_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = enetc_vlan_rx_del_vid,
@@ -602,11 +603,6 @@ static void enetc4_mac_config(struct enetc_pf *pf, unsigned int mode,
case PHY_INTERFACE_MODE_RGMII_RXID:
case PHY_INTERFACE_MODE_RGMII_TXID:
val |= IFMODE_RGMII;
- /* We need to enable auto-negotiation for the MAC
- * if its RGMII interface support In-Band status.
- */
- if (phylink_autoneg_inband(mode))
- val |= PM_IF_MODE_ENA;
break;
case PHY_INTERFACE_MODE_RMII:
val |= IFMODE_RMII;
@@ -616,7 +612,6 @@ static void enetc4_mac_config(struct enetc_pf *pf, unsigned int mode,
val |= IFMODE_SGMII;
break;
case PHY_INTERFACE_MODE_10GBASER:
- case PHY_INTERFACE_MODE_XGMII:
case PHY_INTERFACE_MODE_USXGMII:
val |= IFMODE_XGMII;
break;
@@ -642,26 +637,19 @@ static void enetc4_set_port_speed(struct enetc_ndev_priv *priv, int speed)
u32 old_speed = priv->speed;
u32 val;
+ /* If the speed is unknown, use the minimum value */
+ if (speed == SPEED_UNKNOWN) {
+ speed = SPEED_10;
+ dev_warn(priv->dev, "Speed unknown, default is 10Mbps\n");
+ }
+
if (speed == old_speed)
return;
- val = enetc_port_rd(&priv->si->hw, ENETC4_PCR);
- val &= ~PCR_PSPEED;
-
- switch (speed) {
- case SPEED_100:
- case SPEED_1000:
- case SPEED_2500:
- case SPEED_10000:
- val |= (PCR_PSPEED & PCR_PSPEED_VAL(speed));
- break;
- case SPEED_10:
- default:
- val |= (PCR_PSPEED & PCR_PSPEED_VAL(SPEED_10));
- }
-
- priv->speed = speed;
+ val = enetc_port_rd(&priv->si->hw, ENETC4_PCR) & (~PCR_PSPEED);
+ val |= PCR_PSPEED_VAL(speed);
enetc_port_wr(&priv->si->hw, ENETC4_PCR, val);
+ priv->speed = speed;
}
static void enetc4_set_rgmii_mac(struct enetc_pf *pf, int speed, int duplex)
@@ -717,22 +705,6 @@ static void enetc4_set_rmii_mac(struct enetc_pf *pf, int speed, int duplex)
enetc_port_mac_wr(si, ENETC4_PM_IF_MODE(0), val);
}
-static void enetc4_set_hd_flow_control(struct enetc_pf *pf, bool enable)
-{
- struct enetc_si *si = pf->si;
- u32 old_val, val;
-
- if (!pf->caps.half_duplex)
- return;
-
- old_val = enetc_port_mac_rd(si, ENETC4_PM_CMD_CFG(0));
- val = u32_replace_bits(old_val, enable ? 1 : 0, PM_CMD_CFG_HD_FCEN);
- if (val == old_val)
- return;
-
- enetc_port_mac_wr(si, ENETC4_PM_CMD_CFG(0), val);
-}
-
static void enetc4_set_rx_pause(struct enetc_pf *pf, bool rx_pause)
{
struct enetc_si *si = pf->si;
@@ -908,13 +880,11 @@ static void enetc4_pl_mac_link_up(struct phylink_config *config,
struct enetc_pf *pf = phylink_to_enetc_pf(config);
struct enetc_si *si = pf->si;
struct enetc_ndev_priv *priv;
- bool hd_fc = false;
priv = netdev_priv(si->ndev);
enetc4_set_port_speed(priv, speed);
- if (!phylink_autoneg_inband(mode) &&
- phy_interface_mode_is_rgmii(interface))
+ if (phy_interface_mode_is_rgmii(interface))
enetc4_set_rgmii_mac(pf, speed, duplex);
if (interface == PHY_INTERFACE_MODE_RMII)
@@ -926,18 +896,8 @@ static void enetc4_pl_mac_link_up(struct phylink_config *config,
*/
if (priv->active_offloads & ENETC_F_QBU)
tx_pause = false;
- } else { /* DUPLEX_HALF */
- if (tx_pause || rx_pause)
- hd_fc = true;
-
- /* As per 802.3 annex 31B, PAUSE frames are only supported
- * when the link is configured for full duplex operation.
- */
- tx_pause = false;
- rx_pause = false;
}
- enetc4_set_hd_flow_control(pf, hd_fc);
enetc4_set_tx_pause(pf, priv->num_rx_rings, tx_pause);
enetc4_set_rx_pause(pf, rx_pause);
enetc4_mac_tx_enable(pf);
@@ -1009,19 +969,6 @@ static void enetc4_link_deinit(struct enetc_ndev_priv *priv)
enetc_mdiobus_destroy(pf);
}
-static int enetc4_psi_wq_task_init(struct enetc_si *si)
-{
- char wq_name[24];
-
- INIT_WORK(&si->rx_mode_task, enetc4_psi_do_set_rx_mode);
- snprintf(wq_name, sizeof(wq_name), "enetc-%s", pci_name(si->pdev));
- si->workqueue = create_singlethread_workqueue(wq_name);
- if (!si->workqueue)
- return -ENOMEM;
-
- return 0;
-}
-
static int enetc4_pf_netdev_create(struct enetc_si *si)
{
struct device *dev = &si->pdev->dev;
@@ -1062,12 +1009,6 @@ static int enetc4_pf_netdev_create(struct enetc_si *si)
if (err)
goto err_link_init;
- err = enetc4_psi_wq_task_init(si);
- if (err) {
- dev_err(dev, "Failed to init workqueue\n");
- goto err_wq_init;
- }
-
err = register_netdev(ndev);
if (err) {
dev_err(dev, "Failed to register netdev\n");
@@ -1077,8 +1018,6 @@ static int enetc4_pf_netdev_create(struct enetc_si *si)
return 0;
err_reg_netdev:
- destroy_workqueue(si->workqueue);
-err_wq_init:
enetc4_link_deinit(priv);
err_link_init:
enetc_free_msix(priv);
@@ -1096,8 +1035,6 @@ static void enetc4_pf_netdev_destroy(struct enetc_si *si)
struct net_device *ndev = si->ndev;
unregister_netdev(ndev);
- cancel_work(&si->rx_mode_task);
- destroy_workqueue(si->workqueue);
enetc4_link_deinit(priv);
enetc_free_msix(priv);
free_netdev(ndev);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
index 71f376ef1be1c9..07b7832f24276a 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
@@ -29,7 +29,7 @@ static const u32 enetc_rxbdr_regs[] = {
};
static const u32 enetc_port_regs[] = {
- ENETC_PMR, ENETC_PSR, ENETC_PSIPMR, ENETC_PSIPMAR0(0),
+ ENETC_PMR, ENETC_PSR, ENETC_PSIPMMR, ENETC_PSIPMAR0(0),
ENETC_PSIPMAR1(0), ENETC_PTXMBAR, ENETC_PCAPR0, ENETC_PCAPR1,
ENETC_PSICFGR0(0), ENETC_PRFSCAPR, ENETC_PTCMSDUR(0),
ENETC_PM0_CMD_CFG, ENETC_PM0_MAXFRM, ENETC_PM0_IF_MODE
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_hw.h b/drivers/net/ethernet/freescale/enetc/enetc_hw.h
index bf99b65d7598ab..16da732dc5de82 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_hw.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc_hw.h
@@ -180,13 +180,13 @@ enum enetc_bdr_type {TX, RX};
#define ENETC_PMR_PSPEED_1000M BIT(9)
#define ENETC_PMR_PSPEED_2500M BIT(10)
#define ENETC_PSR 0x0004 /* RO */
-#define ENETC_PSIPMR 0x0018
-#define ENETC_PSIPMR_SET_UP(n) BIT(n) /* n = SI index */
-#define ENETC_PSIPMR_SET_MP(n) BIT((n) + 16)
+#define ENETC_PSIPMMR 0x0018
+#define PSIPMMR_SI_MAC_UP(n) BIT(n) /* n = SI index */
+#define PSIPMMR_SI_MAC_MP(n) BIT((n) + 16)
+
#define ENETC_PSIPVMR 0x001c
-#define ENETC_VLAN_PROMISC_MAP_ALL 0x7
-#define ENETC_PSIPVMR_SET_VP(simap) ((simap) & 0x7)
-#define ENETC_PSIPVMR_SET_VUTA(simap) (((simap) & 0x7) << 16)
+#define PSIPVMR_SI_VLAN_P(n) BIT(n) /* n = SI index */
+
#define ENETC_PSIPMAR0(n) (0x0100 + (n) * 0x8) /* n = SI index */
#define ENETC_PSIPMAR1(n) (0x0104 + (n) * 0x8)
#define ENETC_PVCLCTR 0x0208
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index 2d687bb8c3a063..a509929f89f25f 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -42,26 +42,6 @@ static void enetc_pf_destroy_pcs(struct phylink_pcs *pcs)
lynx_pcs_destroy(pcs);
}
-static void enetc_set_vlan_promisc(struct enetc_hw *hw, char si_map)
-{
- u32 val = enetc_port_rd(hw, ENETC_PSIPVMR);
-
- val &= ~ENETC_PSIPVMR_SET_VP(ENETC_VLAN_PROMISC_MAP_ALL);
- enetc_port_wr(hw, ENETC_PSIPVMR, ENETC_PSIPVMR_SET_VP(si_map) | val);
-}
-
-static void enetc_enable_si_vlan_promisc(struct enetc_pf *pf, int si_idx)
-{
- pf->vlan_promisc_simap |= BIT(si_idx);
- enetc_set_vlan_promisc(&pf->si->hw, pf->vlan_promisc_simap);
-}
-
-static void enetc_disable_si_vlan_promisc(struct enetc_pf *pf, int si_idx)
-{
- pf->vlan_promisc_simap &= ~BIT(si_idx);
- enetc_set_vlan_promisc(&pf->si->hw, pf->vlan_promisc_simap);
-}
-
static void enetc_set_isol_vlan(struct enetc_hw *hw, int si, u16 vlan, u8 qos)
{
u32 val = 0;
@@ -80,37 +60,6 @@ static void enetc_add_mac_addr_em_filter(struct enetc_mac_filter *filter,
filter->mac_addr_cnt++;
}
-static void enetc_clear_mac_ht_flt(struct enetc_si *si, int si_idx, int type)
-{
- bool err = si->errata & ENETC_ERR_UCMCSWP;
-
- if (type == UC) {
- enetc_port_wr(&si->hw, ENETC_PSIUMHFR0(si_idx, err), 0);
- enetc_port_wr(&si->hw, ENETC_PSIUMHFR1(si_idx), 0);
- } else { /* MC */
- enetc_port_wr(&si->hw, ENETC_PSIMMHFR0(si_idx, err), 0);
- enetc_port_wr(&si->hw, ENETC_PSIMMHFR1(si_idx), 0);
- }
-}
-
-static void enetc_set_mac_ht_flt(struct enetc_si *si, int si_idx, int type,
- unsigned long hash)
-{
- bool err = si->errata & ENETC_ERR_UCMCSWP;
-
- if (type == UC) {
- enetc_port_wr(&si->hw, ENETC_PSIUMHFR0(si_idx, err),
- lower_32_bits(hash));
- enetc_port_wr(&si->hw, ENETC_PSIUMHFR1(si_idx),
- upper_32_bits(hash));
- } else { /* MC */
- enetc_port_wr(&si->hw, ENETC_PSIMMHFR0(si_idx, err),
- lower_32_bits(hash));
- enetc_port_wr(&si->hw, ENETC_PSIMMHFR1(si_idx),
- upper_32_bits(hash));
- }
-}
-
static void enetc_sync_mac_filters(struct enetc_pf *pf)
{
struct enetc_mac_filter *f = pf->mac_filter;
@@ -122,12 +71,16 @@ static void enetc_sync_mac_filters(struct enetc_pf *pf)
for (i = 0; i < MADDR_TYPE; i++, f++) {
bool em = (f->mac_addr_cnt == 1) && (i == UC);
bool clear = !f->mac_addr_cnt;
+ u64 hash;
if (clear) {
- if (i == UC)
+ if (i == UC) {
enetc_clear_mac_flt_entry(si, pos);
+ enetc_set_si_uc_hash_filter(si, 0, 0);
+ } else {
+ enetc_set_si_mc_hash_filter(si, 0, 0);
+ }
- enetc_clear_mac_ht_flt(si, 0, i);
continue;
}
@@ -135,7 +88,7 @@ static void enetc_sync_mac_filters(struct enetc_pf *pf)
if (em) {
int err;
- enetc_clear_mac_ht_flt(si, 0, UC);
+ enetc_set_si_uc_hash_filter(si, 0, 0);
err = enetc_set_mac_flt_entry(si, pos, f->mac_addr,
BIT(0));
@@ -147,11 +100,15 @@ static void enetc_sync_mac_filters(struct enetc_pf *pf)
err);
}
+ bitmap_to_arr64(&hash, f->mac_hash_table,
+ ENETC_MADDR_HASH_TBL_SZ);
/* hash table filter, clear EM filter for UC entries */
- if (i == UC)
+ if (i == UC) {
enetc_clear_mac_flt_entry(si, pos);
-
- enetc_set_mac_ht_flt(si, 0, i, *f->mac_hash_table);
+ enetc_set_si_uc_hash_filter(si, 0, hash);
+ } else {
+ enetc_set_si_mc_hash_filter(si, 0, hash);
+ }
}
}
@@ -159,21 +116,17 @@ static void enetc_pf_set_rx_mode(struct net_device *ndev)
{
struct enetc_ndev_priv *priv = netdev_priv(ndev);
struct enetc_pf *pf = enetc_si_priv(priv->si);
- struct enetc_hw *hw = &priv->si->hw;
bool uprom = false, mprom = false;
struct enetc_mac_filter *filter;
struct netdev_hw_addr *ha;
- u32 psipmr = 0;
bool em;
if (ndev->flags & IFF_PROMISC) {
/* enable promisc mode for SI0 (PF) */
- psipmr = ENETC_PSIPMR_SET_UP(0) | ENETC_PSIPMR_SET_MP(0);
uprom = true;
mprom = true;
} else if (ndev->flags & IFF_ALLMULTI) {
/* enable multi cast promisc mode for SI0 (PF) */
- psipmr = ENETC_PSIPMR_SET_MP(0);
mprom = true;
}
@@ -211,9 +164,8 @@ static void enetc_pf_set_rx_mode(struct net_device *ndev)
/* update PF entries */
enetc_sync_mac_filters(pf);
- psipmr |= enetc_port_rd(hw, ENETC_PSIPMR) &
- ~(ENETC_PSIPMR_SET_UP(0) | ENETC_PSIPMR_SET_MP(0));
- enetc_port_wr(hw, ENETC_PSIPMR, psipmr);
+ enetc_set_si_uc_promisc(priv->si, 0, uprom);
+ enetc_set_si_mc_promisc(priv->si, 0, mprom);
}
static void enetc_set_loopback(struct net_device *ndev, bool en)
@@ -469,12 +421,11 @@ static void enetc_configure_port(struct enetc_pf *pf)
/* split up RFS entries */
enetc_port_assign_rfs_entries(pf->si);
-
/* enforce VLAN promisc mode for all SIs */
- pf->vlan_promisc_simap = ENETC_VLAN_PROMISC_MAP_ALL;
- enetc_set_vlan_promisc(hw, pf->vlan_promisc_simap);
+ for (int i = 0; i < pf->total_vfs + 1; i++)
+ enetc_set_si_vlan_promisc(pf->si, i, true);
- enetc_port_wr(hw, ENETC_PSIPMR, 0);
+ enetc_port_wr(hw, ENETC_PSIPMMR, 0);
/* enable port */
enetc_port_wr(hw, ENETC_PMR, ENETC_PMR_EN);
@@ -494,12 +445,9 @@ static int enetc_pf_set_features(struct net_device *ndev,
}
if (changed & NETIF_F_HW_VLAN_CTAG_FILTER) {
- struct enetc_pf *pf = enetc_si_priv(priv->si);
+ bool promisc = !(features & NETIF_F_HW_VLAN_CTAG_FILTER);
- if (!!(features & NETIF_F_HW_VLAN_CTAG_FILTER))
- enetc_disable_si_vlan_promisc(pf, 0);
- else
- enetc_enable_si_vlan_promisc(pf, 0);
+ enetc_set_si_vlan_promisc(priv->si, 0, promisc);
}
if (changed & NETIF_F_LOOPBACK)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.h b/drivers/net/ethernet/freescale/enetc/enetc_pf.h
index 285b7e5c48fdc7..56d23a8a11a063 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.h
@@ -17,12 +17,9 @@ struct enetc_vf_state {
};
struct enetc_port_caps {
- u32 half_duplex:1;
- int num_vsi;
int num_msix;
int num_rx_bdr;
int num_tx_bdr;
- int mac_filter_num;
};
struct enetc_pf;
@@ -47,7 +44,6 @@ struct enetc_pf {
struct work_struct msg_task;
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);
@@ -60,8 +56,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/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
index 6e5d2f8699150b..d32a195a04c97e 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
-/* Copyright 2024 NXP */
+/* Copyright 2024-2026 NXP */
#include <linux/fsl/enetc_mdio.h>
#include <linux/of_mdio.h>
@@ -87,6 +87,112 @@ int enetc_setup_mac_addresses(struct device_node *np, struct enetc_pf *pf)
}
EXPORT_SYMBOL_GPL(enetc_setup_mac_addresses);
+void enetc_set_si_uc_promisc(struct enetc_si *si, int si_id, bool promisc)
+{
+ struct enetc_hw *hw = &si->hw;
+ int psipmmr_off;
+ u32 val;
+
+ if (is_enetc_rev1(si))
+ psipmmr_off = ENETC_PSIPMMR;
+ else
+ psipmmr_off = ENETC4_PSIPMMR;
+
+ val = enetc_port_rd(hw, psipmmr_off);
+
+ if (promisc)
+ val |= PSIPMMR_SI_MAC_UP(si_id);
+ else
+ val &= ~PSIPMMR_SI_MAC_UP(si_id);
+
+ enetc_port_wr(hw, psipmmr_off, val);
+}
+EXPORT_SYMBOL_GPL(enetc_set_si_uc_promisc);
+
+void enetc_set_si_mc_promisc(struct enetc_si *si, int si_id, bool promisc)
+{
+ struct enetc_hw *hw = &si->hw;
+ int psipmmr_off;
+ u32 val;
+
+ if (is_enetc_rev1(si))
+ psipmmr_off = ENETC_PSIPMMR;
+ else
+ psipmmr_off = ENETC4_PSIPMMR;
+
+ val = enetc_port_rd(hw, psipmmr_off);
+
+ if (promisc)
+ val |= PSIPMMR_SI_MAC_MP(si_id);
+ else
+ val &= ~PSIPMMR_SI_MAC_MP(si_id);
+
+ enetc_port_wr(hw, psipmmr_off, val);
+}
+EXPORT_SYMBOL_GPL(enetc_set_si_mc_promisc);
+
+void enetc_set_si_uc_hash_filter(struct enetc_si *si, int si_id, u64 hash)
+{
+ int psiumhfr0_off, psiumhfr1_off;
+ struct enetc_hw *hw = &si->hw;
+
+ if (is_enetc_rev1(si)) {
+ bool err = si->errata & ENETC_ERR_UCMCSWP;
+
+ psiumhfr0_off = ENETC_PSIUMHFR0(si_id, err);
+ psiumhfr1_off = ENETC_PSIUMHFR1(si_id);
+ } else {
+ psiumhfr0_off = ENETC4_PSIUMHFR0(si_id);
+ psiumhfr1_off = ENETC4_PSIUMHFR1(si_id);
+ }
+
+ enetc_port_wr(hw, psiumhfr0_off, lower_32_bits(hash));
+ enetc_port_wr(hw, psiumhfr1_off, upper_32_bits(hash));
+}
+EXPORT_SYMBOL_GPL(enetc_set_si_uc_hash_filter);
+
+void enetc_set_si_mc_hash_filter(struct enetc_si *si, int si_id, u64 hash)
+{
+ int psimmhfr0_off, psimmhfr1_off;
+ struct enetc_hw *hw = &si->hw;
+
+ if (is_enetc_rev1(si)) {
+ bool err = si->errata & ENETC_ERR_UCMCSWP;
+
+ psimmhfr0_off = ENETC_PSIMMHFR0(si_id, err);
+ psimmhfr1_off = ENETC_PSIMMHFR1(si_id);
+ } else {
+ psimmhfr0_off = ENETC4_PSIMMHFR0(si_id);
+ psimmhfr1_off = ENETC4_PSIMMHFR1(si_id);
+ }
+
+ enetc_port_wr(hw, psimmhfr0_off, lower_32_bits(hash));
+ enetc_port_wr(hw, psimmhfr1_off, upper_32_bits(hash));
+}
+EXPORT_SYMBOL_GPL(enetc_set_si_mc_hash_filter);
+
+void enetc_set_si_vlan_promisc(struct enetc_si *si, int si_id, bool promisc)
+{
+ struct enetc_hw *hw = &si->hw;
+ int psipvmr_off;
+ u32 val;
+
+ if (is_enetc_rev1(si))
+ psipvmr_off = ENETC_PSIPVMR;
+ else
+ psipvmr_off = ENETC4_PSIPVMR;
+
+ val = enetc_port_rd(hw, psipvmr_off);
+
+ if (promisc)
+ val |= PSIPVMR_SI_VLAN_P(si_id);
+ else
+ val &= ~PSIPVMR_SI_VLAN_P(si_id);
+
+ enetc_port_wr(hw, psipvmr_off, val);
+}
+EXPORT_SYMBOL_GPL(enetc_set_si_vlan_promisc);
+
void enetc_pf_netdev_setup(struct enetc_si *si, struct net_device *ndev,
const struct net_device_ops *ndev_ops)
{
@@ -275,7 +381,8 @@ static bool enetc_port_has_pcs(struct enetc_pf *pf)
return (pf->if_mode == PHY_INTERFACE_MODE_SGMII ||
pf->if_mode == PHY_INTERFACE_MODE_1000BASEX ||
pf->if_mode == PHY_INTERFACE_MODE_2500BASEX ||
- pf->if_mode == PHY_INTERFACE_MODE_USXGMII);
+ pf->if_mode == PHY_INTERFACE_MODE_USXGMII ||
+ pf->if_mode == PHY_INTERFACE_MODE_10GBASER);
}
int enetc_mdiobus_create(struct enetc_pf *pf, struct device_node *node)
@@ -316,25 +423,42 @@ int enetc_phylink_create(struct enetc_ndev_priv *priv, struct device_node *node,
{
struct enetc_pf *pf = enetc_si_priv(priv->si);
struct phylink *phylink;
+ unsigned long mac_caps;
int err;
pf->phylink_config.dev = &priv->ndev->dev;
pf->phylink_config.type = PHYLINK_NETDEV;
- pf->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
- MAC_10 | MAC_100 | MAC_1000 | MAC_2500FD;
__set_bit(PHY_INTERFACE_MODE_INTERNAL,
pf->phylink_config.supported_interfaces);
- __set_bit(PHY_INTERFACE_MODE_SGMII,
- pf->phylink_config.supported_interfaces);
- __set_bit(PHY_INTERFACE_MODE_1000BASEX,
- pf->phylink_config.supported_interfaces);
- __set_bit(PHY_INTERFACE_MODE_2500BASEX,
- pf->phylink_config.supported_interfaces);
- __set_bit(PHY_INTERFACE_MODE_USXGMII,
- pf->phylink_config.supported_interfaces);
- phy_interface_set_rgmii(pf->phylink_config.supported_interfaces);
+ mac_caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE;
+ if (!enetc_is_pseudo_mac(priv->si)) {
+ mac_caps |= MAC_10 | MAC_100 | MAC_1000FD | MAC_2500FD;
+
+ __set_bit(PHY_INTERFACE_MODE_SGMII,
+ pf->phylink_config.supported_interfaces);
+ __set_bit(PHY_INTERFACE_MODE_1000BASEX,
+ pf->phylink_config.supported_interfaces);
+ __set_bit(PHY_INTERFACE_MODE_2500BASEX,
+ pf->phylink_config.supported_interfaces);
+ __set_bit(PHY_INTERFACE_MODE_USXGMII,
+ pf->phylink_config.supported_interfaces);
+
+ if (!is_enetc_rev1(priv->si)) {
+ mac_caps |= MAC_5000FD | MAC_10000FD;
+ __set_bit(PHY_INTERFACE_MODE_10GBASER,
+ pf->phylink_config.supported_interfaces);
+ }
+
+ phy_interface_set_rgmii(pf->phylink_config.supported_interfaces);
+ } else {
+ mac_caps |= MAC_10FD | MAC_100FD | MAC_1000FD | MAC_2500FD |
+ MAC_5000FD | MAC_10000FD | MAC_20000FD |
+ MAC_25000FD;
+ }
+
+ pf->phylink_config.mac_capabilities = mac_caps;
phylink = phylink_create(&pf->phylink_config, of_fwnode_handle(node),
pf->if_mode, ops);
if (IS_ERR(phylink)) {
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.h b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.h
index 57d2e0ebd2b0bb..8243ce0de57f64 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.h
@@ -17,6 +17,11 @@ void enetc_set_default_rss_key(struct enetc_pf *pf);
int enetc_vlan_rx_add_vid(struct net_device *ndev, __be16 prot, u16 vid);
int enetc_vlan_rx_del_vid(struct net_device *ndev, __be16 prot, u16 vid);
int enetc_init_sriov_resources(struct enetc_pf *pf);
+void enetc_set_si_uc_promisc(struct enetc_si *si, int si_id, bool promisc);
+void enetc_set_si_mc_promisc(struct enetc_si *si, int si_id, bool promisc);
+void enetc_set_si_uc_hash_filter(struct enetc_si *si, int si_id, u64 hash);
+void enetc_set_si_mc_hash_filter(struct enetc_si *si, int si_id, u64 hash);
+void enetc_set_si_vlan_promisc(struct enetc_si *si, int si_id, bool promisc);
static inline u16 enetc_get_ip_revision(struct enetc_hw *hw)
{
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_qos.c b/drivers/net/ethernet/freescale/enetc/enetc_qos.c
index 7b17bca24f260f..2aa0fcaafcd23c 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_qos.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_qos.c
@@ -1135,7 +1135,6 @@ static int enetc_psfp_parse_clsflower(struct enetc_ndev_priv *priv,
struct flow_action_entry *entry;
struct action_gate_entry *e;
u8 sfi_overwrite = 0;
- int entries_size;
int i, err;
if (f->common.chain_index >= priv->psfp_cap.max_streamid) {
@@ -1242,8 +1241,7 @@ static int enetc_psfp_parse_clsflower(struct enetc_ndev_priv *priv,
goto free_filter;
}
- entries_size = struct_size(sgi, entries, entryg->gate.num_entries);
- sgi = kzalloc(entries_size, GFP_KERNEL);
+ sgi = kzalloc_flex(*sgi, entries, entryg->gate.num_entries);
if (!sgi) {
err = -ENOMEM;
goto free_filter;
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_vf.c b/drivers/net/ethernet/freescale/enetc/enetc_vf.c
index 9cdb0a4d6bafb7..7dcb4a0246f528 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_vf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_vf.c
@@ -317,7 +317,14 @@ static int enetc_vf_probe(struct pci_dev *pdev,
enetc_get_si_caps(si);
- ndev = alloc_etherdev_mq(sizeof(*priv), ENETC_MAX_NUM_TXQS);
+ /* Currently, the supported SoCs have a max of 6 CPUs and the VFs
+ * have less than 6 RX/TX rings. So no issues for these supported
+ * SoCs, but for future SoCs which have more CPUs or more TX/RX
+ * rings, all the related logic needs to be improved.
+ */
+ ndev = alloc_etherdev_mqs(sizeof(*priv),
+ min(si->num_tx_rings, ENETC_MAX_NUM_TXQS),
+ min(si->num_rx_rings, ENETC_MAX_NUM_TXQS));
if (!ndev) {
err = -ENOMEM;
dev_err(&pdev->dev, "netdev creation failed\n");
diff --git a/include/linux/fsl/ntmp.h b/include/linux/fsl/ntmp.h
index d3b6c476b91a2d..764ef28926085e 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 {
|
| 3/2 | 2026/07/20 03:00 | llm | patch-evaluator |
5mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 23090 output: 19 thoughts: 62914 |
| 4/2 | 2026/07/20 03:06 | tool | grepper |
0mArgs:{
"Expression": "FSL_ENETC"
}Results: {
"Output": "arch/arm64/configs/defconfig=387=CONFIG_FSL_DPAA2_ETH=m\narch/arm64/configs/defconfig:388:CONFIG_FSL_ENETC=m\narch/arm64/configs/defconfig-389-CONFIG_NXP_ENETC4=m\narch/arm64/configs/defconfig:390:CONFIG_FSL_ENETC_VF=m\narch/arm64/configs/defconfig:391:CONFIG_FSL_ENETC_QOS=y\narch/arm64/configs/defconfig-392-CONFIG_NXP_NETC_BLK_CTRL=m\n--\ndrivers/net/dsa/netc/Kconfig=2=config NET_DSA_NETC_SWITCH\n--\ndrivers/net/dsa/netc/Kconfig-7-\tselect NET_DSA_TAG_NETC\ndrivers/net/dsa/netc/Kconfig:8:\tselect FSL_ENETC_MDIO\ndrivers/net/dsa/netc/Kconfig-9-\tselect NXP_NTMP\n--\ndrivers/net/dsa/ocelot/Kconfig=32=config NET_DSA_MSCC_FELIX\n--\ndrivers/net/dsa/ocelot/Kconfig-43-\tselect NET_DSA_TAG_OCELOT\ndrivers/net/dsa/ocelot/Kconfig:44:\tselect FSL_ENETC_MDIO\ndrivers/net/dsa/ocelot/Kconfig-45-\tselect PCS_LYNX\n--\ndrivers/net/ethernet/freescale/enetc/Kconfig-1-# SPDX-License-Identifier: GPL-2.0\ndrivers/net/ethernet/freescale/enetc/Kconfig:2:config FSL_ENETC_CORE\ndrivers/net/ethernet/freescale/enetc/Kconfig-3-\ttristate\n--\ndrivers/net/ethernet/freescale/enetc/Kconfig=27=config NXP_NTMP\n--\ndrivers/net/ethernet/freescale/enetc/Kconfig-29-\ndrivers/net/ethernet/freescale/enetc/Kconfig:30:config FSL_ENETC\ndrivers/net/ethernet/freescale/enetc/Kconfig-31-\ttristate \"ENETC PF driver\"\n--\ndrivers/net/ethernet/freescale/enetc/Kconfig-33-\tdepends on PCI_MSI\ndrivers/net/ethernet/freescale/enetc/Kconfig:34:\tselect FSL_ENETC_CORE\ndrivers/net/ethernet/freescale/enetc/Kconfig:35:\tselect FSL_ENETC_IERB\ndrivers/net/ethernet/freescale/enetc/Kconfig:36:\tselect FSL_ENETC_MDIO\ndrivers/net/ethernet/freescale/enetc/Kconfig-37-\tselect NXP_ENETC_PF_COMMON\n--\ndrivers/net/ethernet/freescale/enetc/Kconfig=48=config NXP_ENETC4\n--\ndrivers/net/ethernet/freescale/enetc/Kconfig-51-\tdepends on PCI_MSI\ndrivers/net/ethernet/freescale/enetc/Kconfig:52:\tselect FSL_ENETC_CORE\ndrivers/net/ethernet/freescale/enetc/Kconfig:53:\tselect FSL_ENETC_MDIO\ndrivers/net/ethernet/freescale/enetc/Kconfig-54-\tselect NXP_ENETC_PF_COMMON\n--\ndrivers/net/ethernet/freescale/enetc/Kconfig-65-\ndrivers/net/ethernet/freescale/enetc/Kconfig:66:config FSL_ENETC_VF\ndrivers/net/ethernet/freescale/enetc/Kconfig-67-\ttristate \"ENETC VF driver\"\n--\ndrivers/net/ethernet/freescale/enetc/Kconfig-69-\tdepends on PCI_MSI\ndrivers/net/ethernet/freescale/enetc/Kconfig:70:\tselect FSL_ENETC_CORE\ndrivers/net/ethernet/freescale/enetc/Kconfig:71:\tselect FSL_ENETC_MDIO\ndrivers/net/ethernet/freescale/enetc/Kconfig-72-\tselect PHYLINK\n--\ndrivers/net/ethernet/freescale/enetc/Kconfig-80-\ndrivers/net/ethernet/freescale/enetc/Kconfig:81:config FSL_ENETC_IERB\ndrivers/net/ethernet/freescale/enetc/Kconfig-82-\ttristate \"ENETC IERB driver\"\n--\ndrivers/net/ethernet/freescale/enetc/Kconfig-88-\ndrivers/net/ethernet/freescale/enetc/Kconfig:89:config FSL_ENETC_MDIO\ndrivers/net/ethernet/freescale/enetc/Kconfig-90-\ttristate \"ENETC MDIO driver\"\n--\ndrivers/net/ethernet/freescale/enetc/Kconfig-97-\ndrivers/net/ethernet/freescale/enetc/Kconfig:98:config FSL_ENETC_PTP_CLOCK\ndrivers/net/ethernet/freescale/enetc/Kconfig-99-\ttristate \"ENETC PTP clock driver\"\ndrivers/net/ethernet/freescale/enetc/Kconfig:100:\tdepends on PTP_1588_CLOCK_QORIQ \u0026\u0026 (FSL_ENETC || FSL_ENETC_VF)\ndrivers/net/ethernet/freescale/enetc/Kconfig-101-\tdefault y\n--\ndrivers/net/ethernet/freescale/enetc/Kconfig-109-\ndrivers/net/ethernet/freescale/enetc/Kconfig:110:config FSL_ENETC_QOS\ndrivers/net/ethernet/freescale/enetc/Kconfig-111-\tbool \"ENETC hardware Time-sensitive Network support\"\ndrivers/net/ethernet/freescale/enetc/Kconfig:112:\tdepends on (FSL_ENETC || FSL_ENETC_VF) \u0026\u0026 (NET_SCH_TAPRIO || NET_SCH_CBS)\ndrivers/net/ethernet/freescale/enetc/Kconfig-113-\thelp\n--\ndrivers/net/ethernet/freescale/enetc/Makefile-2-\ndrivers/net/ethernet/freescale/enetc/Makefile:3:obj-$(CONFIG_FSL_ENETC_CORE) += fsl-enetc-core.o\ndrivers/net/ethernet/freescale/enetc/Makefile-4-fsl-enetc-core-y := enetc.o enetc_cbdr.o enetc_ethtool.o\n--\ndrivers/net/ethernet/freescale/enetc/Makefile=11=nxp-netc-lib-y := ntmp.o\ndrivers/net/ethernet/freescale/enetc/Makefile-12-\ndrivers/net/ethernet/freescale/enetc/Makefile:13:obj-$(CONFIG_FSL_ENETC) += fsl-enetc.o\ndrivers/net/ethernet/freescale/enetc/Makefile-14-fsl-enetc-y := enetc_pf.o\ndrivers/net/ethernet/freescale/enetc/Makefile:15:fsl-enetc-$(CONFIG_FSL_ENETC_QOS) += enetc_qos.o\ndrivers/net/ethernet/freescale/enetc/Makefile-16-\n--\ndrivers/net/ethernet/freescale/enetc/Makefile=19=nxp-enetc4-$(CONFIG_DEBUG_FS) += enetc4_debugfs.o\ndrivers/net/ethernet/freescale/enetc/Makefile-20-\ndrivers/net/ethernet/freescale/enetc/Makefile:21:obj-$(CONFIG_FSL_ENETC_VF) += fsl-enetc-vf.o\ndrivers/net/ethernet/freescale/enetc/Makefile-22-fsl-enetc-vf-y := enetc_vf.o\ndrivers/net/ethernet/freescale/enetc/Makefile-23-\ndrivers/net/ethernet/freescale/enetc/Makefile:24:obj-$(CONFIG_FSL_ENETC_IERB) += fsl-enetc-ierb.o\ndrivers/net/ethernet/freescale/enetc/Makefile-25-fsl-enetc-ierb-y := enetc_ierb.o\ndrivers/net/ethernet/freescale/enetc/Makefile-26-\ndrivers/net/ethernet/freescale/enetc/Makefile:27:obj-$(CONFIG_FSL_ENETC_MDIO) += fsl-enetc-mdio.o\ndrivers/net/ethernet/freescale/enetc/Makefile-28-fsl-enetc-mdio-y := enetc_pci_mdio.o enetc_mdio.o\ndrivers/net/ethernet/freescale/enetc/Makefile-29-\ndrivers/net/ethernet/freescale/enetc/Makefile:30:obj-$(CONFIG_FSL_ENETC_PTP_CLOCK) += fsl-enetc-ptp.o\ndrivers/net/ethernet/freescale/enetc/Makefile-31-fsl-enetc-ptp-y := enetc_ptp.o\n--\ndrivers/net/ethernet/freescale/enetc/enetc.h=595=static inline bool enetc_ptp_clock_is_enabled(struct enetc_si *si)\n--\ndrivers/net/ethernet/freescale/enetc/enetc.h-597-\tif (is_enetc_rev1(si))\ndrivers/net/ethernet/freescale/enetc/enetc.h:598:\t\treturn IS_ENABLED(CONFIG_FSL_ENETC_PTP_CLOCK);\ndrivers/net/ethernet/freescale/enetc/enetc.h-599-\n--\ndrivers/net/ethernet/freescale/enetc/enetc.h-602-\ndrivers/net/ethernet/freescale/enetc/enetc.h:603:#ifdef CONFIG_FSL_ENETC_QOS\ndrivers/net/ethernet/freescale/enetc/enetc.h-604-int enetc_qos_query_caps(struct net_device *ndev, void *type_data);\n--\ndrivers/net/ethernet/freescale/enetc/enetc_ierb.h-6-\ndrivers/net/ethernet/freescale/enetc/enetc_ierb.h:7:#if IS_ENABLED(CONFIG_FSL_ENETC_IERB)\ndrivers/net/ethernet/freescale/enetc/enetc_ierb.h-8-\n--\ndrivers/ptp/Kconfig=58=config PTP_1588_CLOCK_QORIQ\ndrivers/ptp/Kconfig-59-\ttristate \"Freescale QorIQ 1588 timer as PTP clock\"\ndrivers/ptp/Kconfig:60:\tdepends on GIANFAR || FSL_DPAA_ETH || FSL_DPAA2_ETH || FSL_ENETC || FSL_ENETC_VF || COMPILE_TEST\ndrivers/ptp/Kconfig-61-\tdepends on PTP_1588_CLOCK\ndrivers/ptp/Kconfig:62:\tdefault y if GIANFAR || FSL_DPAA_ETH || FSL_DPAA2_ETH || FSL_ENETC || FSL_ENETC_VF\ndrivers/ptp/Kconfig-63-\thelp\n--\ninclude/linux/fsl/enetc_mdio.h-3-\ninclude/linux/fsl/enetc_mdio.h:4:#ifndef _FSL_ENETC_MDIO_H_\ninclude/linux/fsl/enetc_mdio.h:5:#define _FSL_ENETC_MDIO_H_\ninclude/linux/fsl/enetc_mdio.h-6-\n--\ninclude/linux/fsl/enetc_mdio.h=33=struct enetc_mdio_priv {\n--\ninclude/linux/fsl/enetc_mdio.h-37-\ninclude/linux/fsl/enetc_mdio.h:38:#if IS_REACHABLE(CONFIG_FSL_ENETC_MDIO)\ninclude/linux/fsl/enetc_mdio.h-39-\n"
} |
| 5/2 | 2026/07/20 03:06 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 89094 output: 23 thoughts: 346 Thoughts: **Analyzing the ENETC Driver Patch** Okay, so this patch is touching the `drivers/net/ethernet/freescale/enetc/` directory. Right, and the relevant configs seem to be `FSL_ENETC`, `NXP_ENETC4`, `FSL_ENETC_VF`, and `FSL_ENETC_QOS`. Hmm, I should quickly verify if these are already enabled in the default configuration. Let me check `arch/arm64/configs/defconfig`... Ah, yes. `CONFIG_FSL_ENETC=m`, `CONFIG_NXP_ENETC4=m`, `CONFIG_FSL_ENETC_VF=m`, and `CONFIG_FSL_ENETC_QOS=y`. So they're already in the defconfig. Good, just need to remember to list them without the `CONFIG_` prefix in the documentation or wherever this is going. Now, let's dig into the actual code change. The core of the modification seems to be within `drivers/net/ethernet/freescale/enetc/enetc4_pf.c`. Okay, here's what's happening. The patch removes the `enetc4_psi_do_set_rx_mode` function, which was part of a workqueue, and it seems like it's replacing `.ndo_set_rx_mode` with `.ndo_set_rx_mode_async` in the `net_device_ops` structure. Hang on... `.ndo_set_rx_mode_async`? Is that a new member of the `net_device_ops` struct? That's not something I'm immediately familiar with. I need to refresh my memory on that. Time to check `include/linux/netdevice.h` to see what the deal is with this new callback. |
| 6/2 | 2026/07/20 03:06 | tool | grepper |
0mArgs:{
"Expression": "ndo_set_rx_mode_async"
}Results: {
"Output": "Documentation/networking/netdevices.rst=288=ndo_set_rx_mode:\n--\nDocumentation/networking/netdevices.rst-290-\tContext: BHs disabled\nDocumentation/networking/netdevices.rst:291:\tNotes: Deprecated in favor of ndo_set_rx_mode_async which runs\nDocumentation/networking/netdevices.rst-292-\tin process context.\nDocumentation/networking/netdevices.rst-293-\nDocumentation/networking/netdevices.rst:294:ndo_set_rx_mode_async:\nDocumentation/networking/netdevices.rst-295-\tSynchronization: rtnl_lock() semaphore. In addition, netdev instance\n--\ndrivers/infiniband/ulp/ipoib/ipoib_main.c=2157=static const struct net_device_ops ipoib_netdev_ops_pf = {\n--\ndrivers/infiniband/ulp/ipoib/ipoib_main.c-2165-\t.ndo_tx_timeout\t\t = ipoib_timeout,\ndrivers/infiniband/ulp/ipoib/ipoib_main.c:2166:\t.ndo_set_rx_mode_async\t = ipoib_set_rx_mode_async,\ndrivers/infiniband/ulp/ipoib/ipoib_main.c-2167-\t.ndo_get_iflink\t\t = ipoib_get_iflink,\n--\ndrivers/infiniband/ulp/ipoib/ipoib_main.c=2180=static const struct net_device_ops ipoib_netdev_ops_vf = {\n--\ndrivers/infiniband/ulp/ipoib/ipoib_main.c-2188-\t.ndo_tx_timeout\t\t = ipoib_timeout,\ndrivers/infiniband/ulp/ipoib/ipoib_main.c:2189:\t.ndo_set_rx_mode_async\t = ipoib_set_rx_mode_async,\ndrivers/infiniband/ulp/ipoib/ipoib_main.c-2190-\t.ndo_get_iflink\t\t = ipoib_get_iflink,\n--\ndrivers/net/dummy.c=89=static const struct net_device_ops dummy_netdev_ops = {\n--\ndrivers/net/dummy.c-92-\t.ndo_validate_addr\t= eth_validate_addr,\ndrivers/net/dummy.c:93:\t.ndo_set_rx_mode_async\t= set_multicast_list,\ndrivers/net/dummy.c-94-\t.ndo_set_mac_address\t= eth_mac_addr,\n--\ndrivers/net/ethernet/broadcom/bnxt/bnxt.c=16054=static const struct net_device_ops bnxt_netdev_ops = {\n--\ndrivers/net/ethernet/broadcom/bnxt/bnxt.c-16058-\t.ndo_get_stats64\t= bnxt_get_stats64,\ndrivers/net/ethernet/broadcom/bnxt/bnxt.c:16059:\t.ndo_set_rx_mode_async\t= bnxt_set_rx_mode,\ndrivers/net/ethernet/broadcom/bnxt/bnxt.c-16060-\t.ndo_eth_ioctl\t\t= bnxt_ioctl,\n--\ndrivers/net/ethernet/freescale/enetc/enetc4_pf.c=564=static const struct net_device_ops enetc4_ndev_ops = {\n--\ndrivers/net/ethernet/freescale/enetc/enetc4_pf.c-569-\t.ndo_set_mac_address\t= enetc_pf_set_mac_addr,\ndrivers/net/ethernet/freescale/enetc/enetc4_pf.c:570:\t.ndo_set_rx_mode_async\t= enetc4_pf_set_rx_mode,\ndrivers/net/ethernet/freescale/enetc/enetc4_pf.c-571-\t.ndo_set_features\t= enetc4_pf_set_features,\n--\ndrivers/net/ethernet/intel/iavf/iavf_main.c=5134=static const struct net_device_ops iavf_netdev_ops = {\n--\ndrivers/net/ethernet/intel/iavf/iavf_main.c-5137-\t.ndo_start_xmit\t\t= iavf_xmit_frame,\ndrivers/net/ethernet/intel/iavf/iavf_main.c:5138:\t.ndo_set_rx_mode_async\t= iavf_set_rx_mode,\ndrivers/net/ethernet/intel/iavf/iavf_main.c-5139-\t.ndo_validate_addr\t= eth_validate_addr,\n--\ndrivers/net/ethernet/mellanox/mlx5/core/en_main.c=5322=const struct net_device_ops mlx5e_netdev_ops = {\n--\ndrivers/net/ethernet/mellanox/mlx5/core/en_main.c-5328-\t.ndo_get_stats64 = mlx5e_get_stats,\ndrivers/net/ethernet/mellanox/mlx5/core/en_main.c:5329:\t.ndo_set_rx_mode_async = mlx5e_set_rx_mode,\ndrivers/net/ethernet/mellanox/mlx5/core/en_main.c-5330-\t.ndo_set_mac_address = mlx5e_set_mac,\n--\ndrivers/net/ethernet/meta/fbnic/fbnic_netdev.c=559=static const struct net_device_ops fbnic_netdev_ops = {\n--\ndrivers/net/ethernet/meta/fbnic/fbnic_netdev.c-566-\t.ndo_change_mtu\t\t= fbnic_change_mtu,\ndrivers/net/ethernet/meta/fbnic/fbnic_netdev.c:567:\t.ndo_set_rx_mode_async\t= fbnic_set_rx_mode,\ndrivers/net/ethernet/meta/fbnic/fbnic_netdev.c-568-\t.ndo_get_stats64\t= fbnic_get_stats64,\n--\ndrivers/net/netdevsim/netdev.c=627=static const struct net_device_ops nsim_netdev_ops = {\ndrivers/net/netdevsim/netdev.c-628-\t.ndo_start_xmit\t\t= nsim_start_xmit,\ndrivers/net/netdevsim/netdev.c:629:\t.ndo_set_rx_mode_async\t= nsim_set_rx_mode,\ndrivers/net/netdevsim/netdev.c-630-\t.ndo_set_mac_address\t= eth_mac_addr,\n--\ndrivers/net/netdevsim/netdev.c=652=static const struct net_device_ops nsim_vf_netdev_ops = {\ndrivers/net/netdevsim/netdev.c-653-\t.ndo_start_xmit\t\t= nsim_start_xmit,\ndrivers/net/netdevsim/netdev.c:654:\t.ndo_set_rx_mode_async\t= nsim_set_rx_mode,\ndrivers/net/netdevsim/netdev.c-655-\t.ndo_set_mac_address\t= eth_mac_addr,\n--\ndrivers/net/netkit.c=331=static const struct net_device_ops netkit_netdev_ops = {\n--\ndrivers/net/netkit.c-335-\t.ndo_start_xmit\t\t= netkit_xmit,\ndrivers/net/netkit.c:336:\t.ndo_set_rx_mode_async\t= netkit_set_multicast,\ndrivers/net/netkit.c-337-\t.ndo_set_rx_headroom\t= netkit_set_headroom,\n--\ninclude/linux/netdevice.h=1062=struct netdev_net_notifier {\n--\ninclude/linux/netdevice.h-1122- *\tCannot sleep, called with netif_addr_lock_bh held.\ninclude/linux/netdevice.h:1123: *\tDeprecated in favor of ndo_set_rx_mode_async.\ninclude/linux/netdevice.h-1124- *\ninclude/linux/netdevice.h:1125: * int (*ndo_set_rx_mode_async)(struct net_device *dev,\ninclude/linux/netdevice.h-1126- *\t\t\t\tstruct netdev_hw_addr_list *uc,\n--\ninclude/linux/netdevice.h=1446=struct net_device_ops {\n--\ninclude/linux/netdevice.h-1461-\tvoid\t\t\t(*ndo_set_rx_mode)(struct net_device *dev);\ninclude/linux/netdevice.h:1462:\tint\t\t\t(*ndo_set_rx_mode_async)(\ninclude/linux/netdevice.h-1463-\t\t\t\t\tstruct net_device *dev,\n--\nnet/core/dev.c=11326=int register_netdevice(struct net_device *dev)\n--\nnet/core/dev.c-11382-\t dev-\u003enetdev_ops-\u003endo_set_rx_mode \u0026\u0026\nnet/core/dev.c:11383:\t !dev-\u003enetdev_ops-\u003endo_set_rx_mode_async)\nnet/core/dev.c:11384:\t\tnetdev_WARN(dev, \"ops-locked drivers should use ndo_set_rx_mode_async\\n\");\nnet/core/dev.c-11385-\n--\nnet/core/dev_addr_lists.c=1277=void netif_rx_mode_run(struct net_device *dev)\n--\nnet/core/dev_addr_lists.c-1294-\nnet/core/dev_addr_lists.c:1295:\tif (ops-\u003endo_set_rx_mode_async) {\nnet/core/dev_addr_lists.c-1296-\t\tnetif_addr_lock_bh(dev);\n--\nnet/core/dev_addr_lists.c-1315-\nnet/core/dev_addr_lists.c:1316:\tif (ops-\u003endo_set_rx_mode_async) {\nnet/core/dev_addr_lists.c:1317:\t\terr = ops-\u003endo_set_rx_mode_async(dev, \u0026uc_snap, \u0026mc_snap);\nnet/core/dev_addr_lists.c-1318-\n--\nnet/core/dev_addr_lists.c=1362=void __dev_set_rx_mode(struct net_device *dev)\n--\nnet/core/dev_addr_lists.c-1373-\nnet/core/dev_addr_lists.c:1374:\tif (ops-\u003endo_set_rx_mode_async || ops-\u003endo_change_rx_flags ||\nnet/core/dev_addr_lists.c-1375-\t netdev_need_ops_lock(dev)) {\n--\nnet/core/dev_addr_lists.c=1390=void dev_set_rx_mode(struct net_device *dev)\n--\nnet/core/dev_addr_lists.c-1400- *\nnet/core/dev_addr_lists.c:1401: * Drivers implementing ndo_set_rx_mode_async() have their rx mode callback\nnet/core/dev_addr_lists.c-1402- * executed from a workqueue. This allows the callback to sleep, but means\n--\nnet/core/dev_ioctl.c=541=static int dev_ifsioc(struct net *net, struct ifreq *ifr, void __user *data,\n--\nnet/core/dev_ioctl.c-588-\tcase SIOCADDMULTI:\nnet/core/dev_ioctl.c:589:\t\tif ((!ops-\u003endo_set_rx_mode \u0026\u0026 !ops-\u003endo_set_rx_mode_async) ||\nnet/core/dev_ioctl.c-590-\t\t ifr-\u003eifr_hwaddr.sa_family != AF_UNSPEC)\n--\nnet/core/dev_ioctl.c-600-\tcase SIOCDELMULTI:\nnet/core/dev_ioctl.c:601:\t\tif ((!ops-\u003endo_set_rx_mode \u0026\u0026 !ops-\u003endo_set_rx_mode_async) ||\nnet/core/dev_ioctl.c-602-\t\t ifr-\u003eifr_hwaddr.sa_family != AF_UNSPEC)\n"
} |
| 7/2 | 2026/07/20 03:06 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 93062 output: 19 thoughts: 1538 Thoughts: **Fuzzing the ENETC Driver: A Focused Approach** Okay, so I've got this patch here that's making a functional change to the ENETC driver, specifically around how it handles RX mode. The key thing is that it's replacing the workqueue with `ndo_set_rx_mode_async`, which runs in process context. This seems like a decent change, reducing some overhead, but it definitely needs some attention from a fuzzing perspective. My main concern is the removal of the workqueue and the subsequent modifications to the MAC filtering logic. This patch touches `enetc4_pf.c` and `enetc_pf.c` pretty extensively, so those are my primary areas of focus. I need to nail down the specific functions modified to determine the attack surface. Now, let's see, after some digging, here are the functions I've identified that are modified by this patch that are not in the hot path: `enetc4_pf_set_rx_mode`, `enetc_pf_set_rx_mode`, `enetc4_pf_set_mac_filter`, `enetc4_pf_set_uc_exact_filter`, `enetc4_pf_add_maft_entries`, `enetc_sync_mac_filters`, `enetc_set_si_uc_promisc`, `enetc_set_si_mc_promisc`, `enetc_set_si_uc_hash_filter`, `enetc_set_si_mc_hash_filter`, `enetc_set_si_vlan_promisc`, and `enetc_psfp_parse_clsflower`. I did a quick check on a couple of those to see if any immediately stood out. `enetc_psfp_parse_clsflower` has a small change that should be fine. However, `enetc_vf_probe` has a change where the maximum number of queues is changed, so there's a potential for misconfiguration, but that's a smaller change. Given this, I should focus on the main files, especially the listed symbols. The config options I'll need to enable to test this change are: `FSL_ENETC`, `NXP_ENETC4`, `FSL_ENETC_VF`, and `FSL_ENETC_QOS`. Those seem like the correct configs, according to the Kconfig files. Okay, let's double-check the configs again... yep, those are it. Now, let's just make sure there aren't any other configs that might be relevant here. Let's see... `NXP_NTMP`? No, wait... In `drivers/net/ethernet/freescale/enetc/Kconfig`, it's there... Alright, time to get to work. |
| 8/2 | 2026/07/20 03:06 | tool | grepper |
0mArgs:{
"Expression": "NXP_NTMP"
}Results: {
"Output": "drivers/net/dsa/netc/Kconfig=2=config NET_DSA_NETC_SWITCH\n--\ndrivers/net/dsa/netc/Kconfig-8-\tselect FSL_ENETC_MDIO\ndrivers/net/dsa/netc/Kconfig:9:\tselect NXP_NTMP\ndrivers/net/dsa/netc/Kconfig-10-\tselect NXP_NETC_LIB\n--\ndrivers/net/ethernet/freescale/enetc/Kconfig=2=config FSL_ENETC_CORE\ndrivers/net/ethernet/freescale/enetc/Kconfig-3-\ttristate\ndrivers/net/ethernet/freescale/enetc/Kconfig:4:\tselect NXP_NETC_LIB if NXP_NTMP\ndrivers/net/ethernet/freescale/enetc/Kconfig-5-\thelp\n--\ndrivers/net/ethernet/freescale/enetc/Kconfig=20=config NXP_NETC_LIB\n--\ndrivers/net/ethernet/freescale/enetc/Kconfig-26-\ndrivers/net/ethernet/freescale/enetc/Kconfig:27:config NXP_NTMP\ndrivers/net/ethernet/freescale/enetc/Kconfig-28-\tbool\n--\ndrivers/net/ethernet/freescale/enetc/Kconfig=48=config NXP_ENETC4\n--\ndrivers/net/ethernet/freescale/enetc/Kconfig-54-\tselect NXP_ENETC_PF_COMMON\ndrivers/net/ethernet/freescale/enetc/Kconfig:55:\tselect NXP_NTMP\ndrivers/net/ethernet/freescale/enetc/Kconfig-56-\tselect PHYLINK\n"
} |
| 9/2 | 2026/07/20 03:06 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 95664 output: 323 thoughts: 411 Thoughts: **My Analysis of ENETC Driver Changes** Okay, so it looks like `NXP_ENETC4` depends on `NXP_NTMP`. Good to know. Let me quickly assess if `FSL_ENETC` is sufficient on its own. It seems I need to enable a few configurations: `FSL_ENETC`, `NXP_ENETC4`, `FSL_ENETC_VF`, and `FSL_ENETC_QOS`. Alright, I've got that. Now, let's prepare the output for this patch. I'll flag it as `WorthFuzzing: true`, that's a given. The core of this work lies in how the driver handles RX mode, MAC filters, and VLAN filtering. Therefore, the important symbols to focus on during fuzzing are: `enetc4_pf_set_rx_mode`, `enetc_pf_set_rx_mode`, `enetc4_pf_set_mac_filter`, `enetc4_pf_set_uc_exact_filter`, `enetc4_pf_add_maft_entries`, `enetc_sync_mac_filters`, `enetc_set_si_uc_promisc`, `enetc_set_si_mc_promisc`, `enetc_set_si_uc_hash_filter`, `enetc_set_si_mc_hash_filter` and `enetc_set_si_vlan_promisc`. These represent the primary areas of functional change. For enabling the configurations, I'll need to specify these clearly: `FSL_ENETC`, `NXP_ENETC4`, `FSL_ENETC_VF`, and `FSL_ENETC_QOS`. In terms of reasoning, the patch is refactoring the ENETC driver to use `ndo_set_rx_mode_async` instead of a workqueue. This is a fundamental change in how it sets the RX mode. There's also modification of MAC and VLAN filtering, plus the introduction of common helper functions for promiscuous mode and hash filters. Since these are all functional changes to reachable driver code, fuzzing is definitely warranted. |
| 10/2 | 2026/07/20 03:06 | tool | set-results |
0mArgs:{
"EnableConfigs": [
"FSL_ENETC",
"NXP_ENETC4",
"FSL_ENETC_VF",
"FSL_ENETC_QOS"
],
"FocusSymbols": [
"enetc4_pf_set_rx_mode",
"enetc_pf_set_rx_mode",
"enetc4_pf_set_mac_filter",
"enetc4_pf_set_uc_exact_filter",
"enetc4_pf_add_maft_entries",
"enetc_sync_mac_filters",
"enetc_set_si_uc_promisc",
"enetc_set_si_mc_promisc",
"enetc_set_si_uc_hash_filter",
"enetc_set_si_mc_hash_filter",
"enetc_set_si_vlan_promisc"
],
"Reasoning": "The patch refactors the ENETC driver to use the new `ndo_set_rx_mode_async` net_device_ops member instead of a custom workqueue for setting the RX mode. It also modifies MAC and VLAN filtering logic in the PF drivers (`enetc4_pf.c` and `enetc_pf.c`), and introduces common helper functions for promiscuous mode and hash filters. These are functional changes to reachable core driver logic that should be fuzzed.",
"WorthFuzzing": true
}Results: {
"EnableConfigs": [
"FSL_ENETC",
"NXP_ENETC4",
"FSL_ENETC_VF",
"FSL_ENETC_QOS"
],
"FocusSymbols": [
"enetc4_pf_set_rx_mode",
"enetc_pf_set_rx_mode",
"enetc4_pf_set_mac_filter",
"enetc4_pf_set_uc_exact_filter",
"enetc4_pf_add_maft_entries",
"enetc_sync_mac_filters",
"enetc_set_si_uc_promisc",
"enetc_set_si_mc_promisc",
"enetc_set_si_uc_hash_filter",
"enetc_set_si_mc_hash_filter",
"enetc_set_si_vlan_promisc"
],
"Reasoning": "The patch refactors the ENETC driver to use the new `ndo_set_rx_mode_async` net_device_ops member instead of a custom workqueue for setting the RX mode. It also modifies MAC and VLAN filtering logic in the PF drivers (`enetc4_pf.c` and `enetc_pf.c`), and introduces common helper functions for promiscuous mode and hash filters. These are functional changes to reachable core driver logic that should be fuzzed.",
"WorthFuzzing": true
} |
| Total Calls | Total Tokens | Avg Tokens | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|
| Total Calls | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|