* [PATCH v5 net-next 00/14] Add more features for ENETC v4 - round 2
@ 2025-04-11 9:57 Wei Fang
2025-04-11 9:57 ` [PATCH v5 net-next 01/14] net: enetc: add initial netc-lib driver to support NTMP Wei Fang
` (13 more replies)
0 siblings, 14 replies; 29+ messages in thread
From: Wei Fang @ 2025-04-11 9:57 UTC (permalink / raw)
To: claudiu.manoil, vladimir.oltean, xiaoning.wang, andrew+netdev,
davem, edumazet, kuba, pabeni
Cc: christophe.leroy, netdev, linux-kernel, imx, linuxppc-dev,
linux-arm-kernel
This patch set adds the following features.
1. Compared with ENETC v1, the formats of tables and command BD of ENETC
v4 have changed significantly, and the two are not compatible. Therefore,
in order to support the NETC Table Management Protocol (NTMP) v2.0, we
introduced the netc-lib driver and added support for MAC address filter
table and RSS table.
2. Add MAC filter and VLAN filter support for i.MX95 ENETC PF.
3. Add RSS support for i.MX95 ENETC PF.
4. Add loopback support for i.MX95 ENETC PF.
---
v1 Link: https://lore.kernel.org/imx/20250103060610.2233908-1-wei.fang@nxp.com/
v2 Link: https://lore.kernel.org/imx/20250113082245.2332775-1-wei.fang@nxp.com/
v3 Link: https://lore.kernel.org/imx/20250304072201.1332603-1-wei.fang@nxp.com/
v4 Link: https://lore.kernel.org/imx/20250311053830.1516523-1-wei.fang@nxp.com/
---
Wei Fang (14):
net: enetc: add initial netc-lib driver to support NTMP
net: enetc: add command BD ring support for i.MX95 ENETC
net: enetc: move generic MAC filtering interfaces to enetc-core
net: enetc: add MAC filtering for i.MX95 ENETC PF
net: enetc: add debugfs interface to dump MAC filter
net: enetc: add set/get_rss_table() hooks to enetc_si_ops
net: enetc: make enetc_set_rss_key() reusable
net: enetc: add RSS support for i.MX95 ENETC PF
net: enetc: change enetc_set_rss() to void type
net: enetc: enable RSS feature by default
net: enetc: extract enetc_refresh_vlan_ht_filter()
net: enetc: move generic VLAN hash filter functions to
enetc_pf_common.c
net: enetc: add VLAN filtering support for i.MX95 ENETC PF
net: enetc: add loopback support for i.MX95 ENETC PF
MAINTAINERS | 1 +
drivers/net/ethernet/freescale/enetc/Kconfig | 8 +
drivers/net/ethernet/freescale/enetc/Makefile | 4 +
drivers/net/ethernet/freescale/enetc/enetc.c | 76 ++-
drivers/net/ethernet/freescale/enetc/enetc.h | 45 +-
.../ethernet/freescale/enetc/enetc4_debugfs.c | 90 ++++
.../ethernet/freescale/enetc/enetc4_debugfs.h | 20 +
.../net/ethernet/freescale/enetc/enetc4_hw.h | 12 +
.../net/ethernet/freescale/enetc/enetc4_pf.c | 359 +++++++++++++-
.../net/ethernet/freescale/enetc/enetc_cbdr.c | 51 ++
.../ethernet/freescale/enetc/enetc_ethtool.c | 74 ++-
.../net/ethernet/freescale/enetc/enetc_pf.c | 105 +----
.../net/ethernet/freescale/enetc/enetc_pf.h | 14 +-
.../freescale/enetc/enetc_pf_common.c | 93 +++-
.../freescale/enetc/enetc_pf_common.h | 3 +
.../net/ethernet/freescale/enetc/enetc_vf.c | 10 +-
drivers/net/ethernet/freescale/enetc/ntmp.c | 442 ++++++++++++++++++
.../ethernet/freescale/enetc/ntmp_private.h | 106 +++++
include/linux/fsl/ntmp.h | 126 +++++
19 files changed, 1464 insertions(+), 175 deletions(-)
create mode 100644 drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c
create mode 100644 drivers/net/ethernet/freescale/enetc/enetc4_debugfs.h
create mode 100644 drivers/net/ethernet/freescale/enetc/ntmp.c
create mode 100644 drivers/net/ethernet/freescale/enetc/ntmp_private.h
create mode 100644 include/linux/fsl/ntmp.h
--
2.34.1
^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH v5 net-next 01/14] net: enetc: add initial netc-lib driver to support NTMP
2025-04-11 9:57 [PATCH v5 net-next 00/14] Add more features for ENETC v4 - round 2 Wei Fang
@ 2025-04-11 9:57 ` Wei Fang
2025-04-18 12:49 ` Vladimir Oltean
2025-04-11 9:57 ` [PATCH v5 net-next 02/14] net: enetc: add command BD ring support for i.MX95 ENETC Wei Fang
` (12 subsequent siblings)
13 siblings, 1 reply; 29+ messages in thread
From: Wei Fang @ 2025-04-11 9:57 UTC (permalink / raw)
To: claudiu.manoil, vladimir.oltean, xiaoning.wang, andrew+netdev,
davem, edumazet, kuba, pabeni
Cc: christophe.leroy, netdev, linux-kernel, imx, linuxppc-dev,
linux-arm-kernel
Some NETC functionality is controlled using control messages sent to the
hardware using BD ring interface with 32B descriptor similar to transmit
BD ring used on ENETC. This BD ring interface is referred to as command
BD ring. It is used to configure functionality where the underlying
resources may be shared between different entities or being too large to
configure using direct registers. Therefore, a messaging protocol called
NETC Table Management Protocol (NTMP) is provided for exchanging
configuration and management information between the software and the
hardware using the command BD ring interface.
For i.MX95, NTMP has been upgraded to version 2.0, which is incompatible
with LS1028A, because the message formats have been changed. Therefore,
add the netc-lib driver to support NTMP 2.0 to operate various tables.
Note that, only MAC address filter table and RSS table are supported at
the moment. More tables will be supported in subsequent patches.
It is worth mentioning that the purpose of the netc-lib driver is to
provide some NTMP-based generic interfaces for ENETC and NETC Switch
drivers. Currently, it only supports the configurations of some tables.
Interfaces such as tc flower and debugfs will be added in the future.
Signed-off-by: Wei Fang <wei.fang@nxp.com>
---
v5 changes:
1. Add the change of MAINTAINERS to this patch
2. Rename ntmp_fill_request_headr() to ntmp_fill_request_hdr()
3. Split ntmp_rsst_query_or_update_entry() into
ntmp_rsst_query_or_update_entry() and ntmp_rsst_query_entry()
4. Add "ntmp_" prefix to struct cmn_resp_query and cmn_req_data.
5. Remove struct common_resp_nq and netc_dev_type
6. Correct the definition of NTMP_TBL_VER
7. Remove struct netc_cbdrs and rename ntmp_priv to ntmp_user
8. Improve the error log
9. Remove NTMP_NULL_ENTRY_ID check from ntmp_delete_entry_by_id()
10. Remove netc_select_cbdr()
11. Move union netc_cbd from ntmp.h to ntmp_private.h
---
MAINTAINERS | 1 +
drivers/net/ethernet/freescale/enetc/Kconfig | 8 +
drivers/net/ethernet/freescale/enetc/Makefile | 3 +
drivers/net/ethernet/freescale/enetc/ntmp.c | 442 ++++++++++++++++++
.../ethernet/freescale/enetc/ntmp_private.h | 106 +++++
include/linux/fsl/ntmp.h | 126 +++++
6 files changed, 686 insertions(+)
create mode 100644 drivers/net/ethernet/freescale/enetc/ntmp.c
create mode 100644 drivers/net/ethernet/freescale/enetc/ntmp_private.h
create mode 100644 include/linux/fsl/ntmp.h
diff --git a/MAINTAINERS b/MAINTAINERS
index 4c5c2e2c1278..2ae3fb3a0297 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9374,6 +9374,7 @@ F: Documentation/devicetree/bindings/net/nxp,netc-blk-ctrl.yaml
F: drivers/net/ethernet/freescale/enetc/
F: include/linux/fsl/enetc_mdio.h
F: include/linux/fsl/netc_global.h
+F: include/linux/fsl/ntmp.h
FREESCALE eTSEC ETHERNET DRIVER (GIANFAR)
M: Claudiu Manoil <claudiu.manoil@nxp.com>
diff --git a/drivers/net/ethernet/freescale/enetc/Kconfig b/drivers/net/ethernet/freescale/enetc/Kconfig
index 6c2779047dcd..c8efbb6f2055 100644
--- a/drivers/net/ethernet/freescale/enetc/Kconfig
+++ b/drivers/net/ethernet/freescale/enetc/Kconfig
@@ -15,6 +15,13 @@ config NXP_ENETC_PF_COMMON
If compiled as module (M), the module name is nxp-enetc-pf-common.
+config NXP_NETC_LIB
+ tristate
+ help
+ This module provides common functionalities for both ENETC and NETC
+ Switch, such as NETC Table Management Protocol (NTMP) 2.0, common tc
+ flower and debugfs interfaces and so on.
+
config FSL_ENETC
tristate "ENETC PF driver"
depends on PCI_MSI
@@ -40,6 +47,7 @@ config NXP_ENETC4
select FSL_ENETC_CORE
select FSL_ENETC_MDIO
select NXP_ENETC_PF_COMMON
+ select NXP_NETC_LIB
select PHYLINK
select DIMLIB
help
diff --git a/drivers/net/ethernet/freescale/enetc/Makefile b/drivers/net/ethernet/freescale/enetc/Makefile
index 6fd27ee4fcd1..707a68e26971 100644
--- a/drivers/net/ethernet/freescale/enetc/Makefile
+++ b/drivers/net/ethernet/freescale/enetc/Makefile
@@ -6,6 +6,9 @@ fsl-enetc-core-y := enetc.o enetc_cbdr.o enetc_ethtool.o
obj-$(CONFIG_NXP_ENETC_PF_COMMON) += nxp-enetc-pf-common.o
nxp-enetc-pf-common-y := enetc_pf_common.o
+obj-$(CONFIG_NXP_NETC_LIB) += nxp-netc-lib.o
+nxp-netc-lib-y := ntmp.o
+
obj-$(CONFIG_FSL_ENETC) += fsl-enetc.o
fsl-enetc-y := enetc_pf.o
fsl-enetc-$(CONFIG_PCI_IOV) += enetc_msg.o
diff --git a/drivers/net/ethernet/freescale/enetc/ntmp.c b/drivers/net/ethernet/freescale/enetc/ntmp.c
new file mode 100644
index 000000000000..07cf88968d5e
--- /dev/null
+++ b/drivers/net/ethernet/freescale/enetc/ntmp.c
@@ -0,0 +1,442 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * NETC NTMP (NETC Table Management Protocol) 2.0 Library
+ * Copyright 2025 NXP
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/fsl/netc_global.h>
+#include <linux/iopoll.h>
+
+#include "ntmp_private.h"
+
+#define NETC_CBDR_TIMEOUT 1000 /* us */
+#define NETC_CBDR_MR_EN BIT(31)
+
+#define NTMP_BASE_ADDR_ALIGN 128
+#define NTMP_DATA_ADDR_ALIGN 32
+
+/* Define NTMP Table ID */
+#define NTMP_MAFT_ID 1
+#define NTMP_RSST_ID 3
+
+/* Generic Update Actions for most tables */
+#define NTMP_GEN_UA_CFGEU BIT(0)
+#define NTMP_GEN_UA_STSEU BIT(1)
+
+#define NTMP_ENTRY_ID_SIZE 4
+#define RSST_ENTRY_NUM 64
+#define RSST_STSE_DATA_SIZE(n) ((n) * 8)
+#define RSST_CFGE_DATA_SIZE(n) (n)
+
+int netc_setup_cbdr(struct device *dev, int cbd_num,
+ struct netc_cbdr_regs *regs,
+ struct netc_cbdr *cbdr)
+{
+ size_t size;
+
+ size = cbd_num * sizeof(union netc_cbd) + NTMP_BASE_ADDR_ALIGN;
+ cbdr->addr_base = dma_alloc_coherent(dev, size, &cbdr->dma_base,
+ GFP_KERNEL);
+ if (!cbdr->addr_base)
+ return -ENOMEM;
+
+ cbdr->dma_size = size;
+ cbdr->bd_num = cbd_num;
+ cbdr->regs = *regs;
+
+ /* The base address of the Control BD Ring must be 128 bytes aligned */
+ cbdr->dma_base_align = ALIGN(cbdr->dma_base, NTMP_BASE_ADDR_ALIGN);
+ cbdr->addr_base_align = PTR_ALIGN(cbdr->addr_base,
+ NTMP_BASE_ADDR_ALIGN);
+
+ cbdr->next_to_clean = 0;
+ cbdr->next_to_use = 0;
+ spin_lock_init(&cbdr->ring_lock);
+
+ /* Step 1: Configure the base address of the Control BD Ring */
+ netc_write(cbdr->regs.bar0, lower_32_bits(cbdr->dma_base_align));
+ netc_write(cbdr->regs.bar1, upper_32_bits(cbdr->dma_base_align));
+
+ /* Step 2: Configure the producer index register */
+ netc_write(cbdr->regs.pir, cbdr->next_to_clean);
+
+ /* Step 3: Configure the consumer index register */
+ netc_write(cbdr->regs.cir, cbdr->next_to_use);
+
+ /* Step4: Configure the number of BDs of the Control BD Ring */
+ netc_write(cbdr->regs.lenr, cbdr->bd_num);
+
+ /* Step 5: Enable the Control BD Ring */
+ netc_write(cbdr->regs.mr, NETC_CBDR_MR_EN);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(netc_setup_cbdr);
+
+void netc_teardown_cbdr(struct device *dev, struct netc_cbdr *cbdr)
+{
+ /* Disable the Control BD Ring */
+ netc_write(cbdr->regs.mr, 0);
+ dma_free_coherent(dev, cbdr->dma_size, cbdr->addr_base,
+ cbdr->dma_base);
+ memset(cbdr, 0, sizeof(*cbdr));
+}
+EXPORT_SYMBOL_GPL(netc_teardown_cbdr);
+
+static int netc_get_free_cbd_num(struct netc_cbdr *cbdr)
+{
+ return (cbdr->next_to_clean - cbdr->next_to_use - 1 +
+ cbdr->bd_num) % cbdr->bd_num;
+}
+
+static union netc_cbd *netc_get_cbd(struct netc_cbdr *cbdr, int index)
+{
+ return &((union netc_cbd *)(cbdr->addr_base_align))[index];
+}
+
+static void netc_clean_cbdr(struct netc_cbdr *cbdr)
+{
+ union netc_cbd *cbd;
+ int i;
+
+ i = cbdr->next_to_clean;
+ while (netc_read(cbdr->regs.cir) != i) {
+ cbd = netc_get_cbd(cbdr, i);
+ memset(cbd, 0, sizeof(*cbd));
+ i = (i + 1) % cbdr->bd_num;
+ }
+
+ cbdr->next_to_clean = i;
+}
+
+static int netc_xmit_ntmp_cmd(struct ntmp_user *user, union netc_cbd *cbd)
+{
+ union netc_cbd *cur_cbd;
+ struct netc_cbdr *cbdr;
+ int i, err;
+ u16 status;
+ u32 val;
+
+ /* Currently only i.MX95 ENETC is supported, and it only has one
+ * command BD ring
+ */
+ cbdr = &user->ring[0];
+
+ spin_lock_bh(&cbdr->ring_lock);
+
+ if (unlikely(!netc_get_free_cbd_num(cbdr)))
+ netc_clean_cbdr(cbdr);
+
+ i = cbdr->next_to_use;
+ cur_cbd = netc_get_cbd(cbdr, i);
+ *cur_cbd = *cbd;
+ dma_wmb();
+
+ /* Update producer index of both software and hardware */
+ i = (i + 1) % cbdr->bd_num;
+ cbdr->next_to_use = i;
+ netc_write(cbdr->regs.pir, i);
+
+ err = read_poll_timeout_atomic(netc_read, val, val == i,
+ 10, NETC_CBDR_TIMEOUT, true,
+ cbdr->regs.cir);
+ if (unlikely(err))
+ goto cbdr_unlock;
+
+ dma_rmb();
+ /* Get the writeback command BD, because the caller may need
+ * to check some other fields of the response header.
+ */
+ *cbd = *cur_cbd;
+
+ /* Check the writeback error status */
+ status = le16_to_cpu(cbd->resp_hdr.error_rr) & NTMP_RESP_ERROR;
+ if (unlikely(status)) {
+ err = -EIO;
+ dev_err(user->dev, "Command BD error: 0x%04x\n", status);
+ }
+
+ netc_clean_cbdr(cbdr);
+ dma_wmb();
+
+cbdr_unlock:
+ spin_unlock_bh(&cbdr->ring_lock);
+
+ return err;
+}
+
+static int ntmp_alloc_data_mem(struct ntmp_dma_buf *data, void **buf_align)
+{
+ void *buf;
+
+ buf = dma_alloc_coherent(data->dev, data->size + NTMP_DATA_ADDR_ALIGN,
+ &data->dma, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ data->buf = buf;
+ *buf_align = PTR_ALIGN(buf, NTMP_DATA_ADDR_ALIGN);
+
+ return 0;
+}
+
+static void ntmp_free_data_mem(struct ntmp_dma_buf *data)
+{
+ dma_free_coherent(data->dev, data->size + NTMP_DATA_ADDR_ALIGN,
+ data->buf, data->dma);
+}
+
+static void ntmp_fill_request_hdr(union netc_cbd *cbd, dma_addr_t dma,
+ int len, int table_id, int cmd,
+ int access_method)
+{
+ dma_addr_t dma_align;
+
+ memset(cbd, 0, sizeof(*cbd));
+ dma_align = ALIGN(dma, NTMP_DATA_ADDR_ALIGN);
+ cbd->req_hdr.addr = cpu_to_le64(dma_align);
+ cbd->req_hdr.len = cpu_to_le32(len);
+ cbd->req_hdr.cmd = cmd;
+ cbd->req_hdr.access_method = FIELD_PREP(NTMP_ACCESS_METHOD,
+ access_method);
+ cbd->req_hdr.table_id = table_id;
+ cbd->req_hdr.ver_cci_rr = FIELD_PREP(NTMP_HDR_VERSION,
+ NTMP_HDR_VER2);
+ /* For NTMP version 2.0 or later version */
+ cbd->req_hdr.npf = cpu_to_le32(NTMP_NPF);
+}
+
+static void ntmp_fill_crd(struct ntmp_cmn_req_data *crd, u8 tblv,
+ u8 qa, u16 ua)
+{
+ crd->update_act = cpu_to_le16(ua);
+ crd->tblv_qact = NTMP_TBLV_QACT(tblv, qa);
+}
+
+static void ntmp_fill_crd_eid(struct ntmp_req_by_eid *rbe, u8 tblv,
+ u8 qa, u16 ua, u32 entry_id)
+{
+ ntmp_fill_crd(&rbe->crd, tblv, qa, ua);
+ rbe->entry_id = cpu_to_le32(entry_id);
+}
+
+static int ntmp_delete_entry_by_id(struct ntmp_user *user, int tbl_id,
+ u8 tbl_ver, u32 entry_id, u32 req_len,
+ u32 resp_len)
+{
+ struct ntmp_dma_buf data = {.dev = user->dev};
+ struct ntmp_req_by_eid *req;
+ union netc_cbd cbd;
+ u32 len;
+ int err;
+
+ data.size = req_len >= resp_len ? req_len : resp_len;
+ err = ntmp_alloc_data_mem(&data, (void **)&req);
+ if (err)
+ return err;
+
+ ntmp_fill_crd_eid(req, tbl_ver, 0, 0, entry_id);
+ len = NTMP_LEN(req_len, resp_len);
+ ntmp_fill_request_hdr(&cbd, data.dma, len, tbl_id,
+ NTMP_CMD_DELETE, NTMP_AM_ENTRY_ID);
+
+ err = netc_xmit_ntmp_cmd(user, &cbd);
+ if (err)
+ dev_err(user->dev, "Delete table (id: %d) entry failed: %pe",
+ tbl_id, ERR_PTR(err));
+
+ ntmp_free_data_mem(&data);
+
+ return err;
+}
+
+static int ntmp_query_entry_by_id(struct ntmp_user *user, int tbl_id,
+ u32 len, struct ntmp_req_by_eid *req,
+ dma_addr_t dma, bool compare_eid)
+{
+ struct device *dev = user->dev;
+ struct ntmp_cmn_resp_query *resp;
+ int cmd = NTMP_CMD_QUERY;
+ union netc_cbd cbd;
+ u32 entry_id;
+ int err;
+
+ entry_id = le32_to_cpu(req->entry_id);
+ if (le16_to_cpu(req->crd.update_act))
+ cmd = NTMP_CMD_QU;
+
+ /* Request header */
+ ntmp_fill_request_hdr(&cbd, dma, len, tbl_id, cmd, NTMP_AM_ENTRY_ID);
+ err = netc_xmit_ntmp_cmd(user, &cbd);
+ if (err) {
+ dev_err(dev, "Query table (id: %d) entry failed: %pe\n",
+ tbl_id, ERR_PTR(err));
+ return err;
+ }
+
+ /* For a few tables, the first field of their response data is not
+ * entry_id, so directly return success.
+ */
+ if (!compare_eid)
+ return 0;
+
+ resp = (struct ntmp_cmn_resp_query *)req;
+ if (unlikely(le32_to_cpu(resp->entry_id) != entry_id)) {
+ dev_err(dev, "Table (id: %d) query EID: 0x%x, response EID: 0x%x\n",
+ tbl_id, entry_id, le32_to_cpu(resp->entry_id));
+ return -EIO;
+ }
+
+ return 0;
+}
+
+int ntmp_maft_add_entry(struct ntmp_user *user, u32 entry_id,
+ struct maft_entry_data *maft)
+{
+ struct ntmp_dma_buf data = {.dev = user->dev};
+ struct maft_req_add *req;
+ union netc_cbd cbd;
+ int err;
+
+ data.size = sizeof(*req);
+ err = ntmp_alloc_data_mem(&data, (void **)&req);
+ if (err)
+ return err;
+
+ /* Set mac address filter table request data buffer */
+ ntmp_fill_crd_eid(&req->rbe, user->tbl.maft_ver, 0, 0, entry_id);
+ req->keye = maft->keye;
+ req->cfge = maft->cfge;
+
+ ntmp_fill_request_hdr(&cbd, data.dma, NTMP_LEN(data.size, 0),
+ NTMP_MAFT_ID, NTMP_CMD_ADD, NTMP_AM_ENTRY_ID);
+ err = netc_xmit_ntmp_cmd(user, &cbd);
+ if (err)
+ dev_err(user->dev, "Add MAFT entry failed (%pe)\n",
+ ERR_PTR(err));
+
+ ntmp_free_data_mem(&data);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(ntmp_maft_add_entry);
+
+int ntmp_maft_query_entry(struct ntmp_user *user, u32 entry_id,
+ struct maft_entry_data *maft)
+{
+ struct ntmp_dma_buf data = {.dev = user->dev};
+ struct maft_resp_query *resp;
+ struct ntmp_req_by_eid *req;
+ int err;
+
+ data.size = sizeof(*resp);
+ err = ntmp_alloc_data_mem(&data, (void **)&req);
+ if (err)
+ return err;
+
+ ntmp_fill_crd_eid(req, user->tbl.maft_ver, 0, 0, entry_id);
+ err = ntmp_query_entry_by_id(user, NTMP_MAFT_ID,
+ NTMP_LEN(sizeof(*req), data.size),
+ req, data.dma, true);
+ if (err)
+ goto end;
+
+ resp = (struct maft_resp_query *)req;
+ maft->keye = resp->keye;
+ maft->cfge = resp->cfge;
+
+end:
+ ntmp_free_data_mem(&data);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(ntmp_maft_query_entry);
+
+int ntmp_maft_delete_entry(struct ntmp_user *user, u32 entry_id)
+{
+ return ntmp_delete_entry_by_id(user, NTMP_MAFT_ID, user->tbl.maft_ver,
+ entry_id, NTMP_EID_REQ_LEN, 0);
+}
+EXPORT_SYMBOL_GPL(ntmp_maft_delete_entry);
+
+int ntmp_rsst_update_entry(struct ntmp_user *user, const u32 *table,
+ int count)
+{
+ struct ntmp_dma_buf data = {.dev = user->dev};
+ struct rsst_req_update *req;
+ union netc_cbd cbd;
+ int err, i;
+
+ if (count != RSST_ENTRY_NUM)
+ /* HW only takes in a full 64 entry table */
+ return -EINVAL;
+
+ data.size = struct_size(req, groups, count);
+ err = ntmp_alloc_data_mem(&data, (void **)&req);
+ if (err)
+ return err;
+
+ /* Set the request data buffer */
+ ntmp_fill_crd_eid(&req->rbe, user->tbl.rsst_ver, 0,
+ NTMP_GEN_UA_CFGEU | NTMP_GEN_UA_STSEU, 0);
+ for (i = 0; i < count; i++)
+ req->groups[i] = (u8)(table[i]);
+
+ ntmp_fill_request_hdr(&cbd, data.dma, NTMP_LEN(data.size, 0),
+ NTMP_RSST_ID, NTMP_CMD_UPDATE, NTMP_AM_ENTRY_ID);
+
+ err = netc_xmit_ntmp_cmd(user, &cbd);
+ if (err)
+ dev_err(user->dev,
+ "Update RSS table entry failed (%pe)\n", ERR_PTR(err));
+
+ ntmp_free_data_mem(&data);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(ntmp_rsst_update_entry);
+
+int ntmp_rsst_query_entry(struct ntmp_user *user, u32 *table, int count)
+{
+ struct ntmp_dma_buf data = {.dev = user->dev};
+ struct ntmp_req_by_eid *req;
+ union netc_cbd cbd;
+ int err, i;
+ u8 *group;
+
+ if (count != RSST_ENTRY_NUM)
+ /* HW only takes in a full 64 entry table */
+ return -EINVAL;
+
+ data.size = NTMP_ENTRY_ID_SIZE + RSST_STSE_DATA_SIZE(count) +
+ RSST_CFGE_DATA_SIZE(count);
+ err = ntmp_alloc_data_mem(&data, (void **)&req);
+ if (err)
+ return err;
+
+ /* Set the request data buffer */
+ ntmp_fill_crd_eid(req, user->tbl.rsst_ver, 0, 0, 0);
+ ntmp_fill_request_hdr(&cbd, data.dma, NTMP_LEN(sizeof(*req), data.size),
+ NTMP_RSST_ID, NTMP_CMD_QUERY, NTMP_AM_ENTRY_ID);
+ err = netc_xmit_ntmp_cmd(user, &cbd);
+ if (err) {
+ dev_err(user->dev,
+ "Query RSS table entry failed (%pe)\n", ERR_PTR(err));
+ goto end;
+ }
+
+ group = (u8 *)req;
+ group += NTMP_ENTRY_ID_SIZE + RSST_STSE_DATA_SIZE(count);
+ for (i = 0; i < count; i++)
+ table[i] = group[i];
+
+end:
+ ntmp_free_data_mem(&data);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(ntmp_rsst_query_entry);
+
+MODULE_DESCRIPTION("NXP NETC Library");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/ethernet/freescale/enetc/ntmp_private.h b/drivers/net/ethernet/freescale/enetc/ntmp_private.h
new file mode 100644
index 000000000000..039ab9c8fdda
--- /dev/null
+++ b/drivers/net/ethernet/freescale/enetc/ntmp_private.h
@@ -0,0 +1,106 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
+/*
+ * NTMP table request and response data buffer formats
+ * Copyright 2025 NXP
+ */
+
+#ifndef __NTMP_PRIVATE_H
+#define __NTMP_PRIVATE_H
+
+#include <linux/fsl/ntmp.h>
+
+#define NTMP_EID_REQ_LEN 8
+
+union netc_cbd {
+ struct {
+ __le64 addr;
+ __le32 len;
+#define NTMP_RESP_LEN GENMASK(19, 0)
+#define NTMP_REQ_LEN GENMASK(31, 20)
+#define NTMP_LEN(req, resp) (FIELD_PREP(NTMP_REQ_LEN, (req)) | \
+ ((resp) & NTMP_RESP_LEN))
+ u8 cmd;
+#define NTMP_CMD_DELETE BIT(0)
+#define NTMP_CMD_UPDATE BIT(1)
+#define NTMP_CMD_QUERY BIT(2)
+#define NTMP_CMD_ADD BIT(3)
+#define NTMP_CMD_QD (NTMP_CMD_QUERY | NTMP_CMD_DELETE)
+#define NTMP_CMD_QU (NTMP_CMD_QUERY | NTMP_CMD_UPDATE)
+#define NTMP_CMD_AU (NTMP_CMD_ADD | NTMP_CMD_UPDATE)
+#define NTMP_CMD_AQ (NTMP_CMD_ADD | NTMP_CMD_QUERY)
+#define NTMP_CMD_AQU (NTMP_CMD_AQ | NTMP_CMD_UPDATE)
+ u8 access_method;
+#define NTMP_ACCESS_METHOD GENMASK(7, 4)
+#define NTMP_AM_ENTRY_ID 0
+#define NTMP_AM_EXACT_KEY 1
+#define NTMP_AM_SEARCH 2
+#define NTMP_AM_TERNARY_KEY 3
+ u8 table_id;
+ u8 ver_cci_rr;
+#define NTMP_HDR_VERSION GENMASK(5, 0)
+#define NTMP_HDR_VER2 2
+#define NTMP_CCI BIT(6)
+#define NTMP_RR BIT(7)
+ __le32 resv[3];
+ __le32 npf;
+#define NTMP_NPF BIT(15)
+ } req_hdr; /* NTMP Request Message Header Format */
+
+ struct {
+ __le32 resv0[3];
+ __le16 num_matched;
+ __le16 error_rr;
+#define NTMP_RESP_ERROR GENMASK(11, 0)
+#define NTMP_RESP_RR BIT(15)
+ __le32 resv1[4];
+ } resp_hdr; /* NTMP Response Message Header Format */
+};
+
+struct ntmp_dma_buf {
+ struct device *dev;
+ size_t size;
+ void *buf;
+ dma_addr_t dma;
+};
+
+struct ntmp_cmn_req_data {
+ __le16 update_act;
+ u8 dbg_opt;
+ u8 tblv_qact;
+#define NTMP_QUERY_ACT GENMASK(3, 0)
+#define NTMP_TBL_VER GENMASK(7, 4)
+#define NTMP_TBLV_QACT(v, a) (FIELD_PREP(NTMP_TBL_VER, (v)) | \
+ ((a) & NTMP_QUERY_ACT))
+};
+
+struct ntmp_cmn_resp_query {
+ __le32 entry_id;
+};
+
+/* Generic structure for request data by entry ID */
+struct ntmp_req_by_eid {
+ struct ntmp_cmn_req_data crd;
+ __le32 entry_id;
+};
+
+/* MAC Address Filter Table Request Data Buffer Format of Add action */
+struct maft_req_add {
+ struct ntmp_req_by_eid rbe;
+ struct maft_keye_data keye;
+ struct maft_cfge_data cfge;
+};
+
+/* MAC Address Filter Table Response Data Buffer Format of Query action */
+struct maft_resp_query {
+ __le32 entry_id;
+ struct maft_keye_data keye;
+ struct maft_cfge_data cfge;
+};
+
+/* RSS Table Request Data Buffer Format of Update action */
+struct rsst_req_update {
+ struct ntmp_req_by_eid rbe;
+ u8 groups[];
+};
+
+#endif
diff --git a/include/linux/fsl/ntmp.h b/include/linux/fsl/ntmp.h
new file mode 100644
index 000000000000..c64da8364c39
--- /dev/null
+++ b/include/linux/fsl/ntmp.h
@@ -0,0 +1,126 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
+/* Copyright 2025 NXP */
+#ifndef __NETC_NTMP_H
+#define __NETC_NTMP_H
+
+#include <linux/bitops.h>
+#include <linux/if_ether.h>
+
+#define NETC_CBDR_BD_NUM 256
+
+struct maft_keye_data {
+ u8 mac_addr[ETH_ALEN];
+ __le16 resv;
+};
+
+struct maft_cfge_data {
+ __le16 si_bitmap;
+ __le16 resv;
+};
+
+struct netc_cbdr_regs {
+ void __iomem *pir;
+ void __iomem *cir;
+ void __iomem *mr;
+
+ void __iomem *bar0;
+ void __iomem *bar1;
+ void __iomem *lenr;
+};
+
+struct netc_tbl_vers {
+ u8 maft_ver;
+ u8 rsst_ver;
+};
+
+struct netc_cbdr {
+ struct netc_cbdr_regs regs;
+
+ int bd_num;
+ int next_to_use;
+ int next_to_clean;
+
+ int dma_size;
+ void *addr_base;
+ void *addr_base_align;
+ dma_addr_t dma_base;
+ dma_addr_t dma_base_align;
+
+ /* Serialize the order of command BD ring */
+ spinlock_t ring_lock;
+};
+
+struct ntmp_user {
+ int cbdr_num; /* number of control BD ring */
+ int cbdr_size; /* number of BDs per control BD ring */
+ struct device *dev;
+ struct netc_cbdr *ring;
+ struct netc_tbl_vers tbl;
+};
+
+struct maft_entry_data {
+ struct maft_keye_data keye;
+ struct maft_cfge_data cfge;
+};
+
+#if IS_ENABLED(CONFIG_NXP_NETC_LIB)
+int netc_setup_cbdr(struct device *dev, int cbd_num,
+ struct netc_cbdr_regs *regs,
+ struct netc_cbdr *cbdr);
+void netc_teardown_cbdr(struct device *dev, struct netc_cbdr *cbdr);
+
+/* NTMP APIs */
+int ntmp_maft_add_entry(struct ntmp_user *user, u32 entry_id,
+ struct maft_entry_data *maft);
+int ntmp_maft_query_entry(struct ntmp_user *user, u32 entry_id,
+ struct maft_entry_data *maft);
+int ntmp_maft_delete_entry(struct ntmp_user *user, u32 entry_id);
+int ntmp_rsst_update_entry(struct ntmp_user *user, const u32 *table,
+ int count);
+int ntmp_rsst_query_entry(struct ntmp_user *user,
+ u32 *table, int count);
+#else
+static inline int netc_setup_cbdr(struct device *dev, int cbd_num,
+ struct netc_cbdr_regs *regs,
+ struct netc_cbdr *cbdr)
+{
+ return 0;
+}
+
+static inline void netc_teardown_cbdr(struct device *dev,
+ struct netc_cbdr *cbdr)
+{
+}
+
+static inline int ntmp_maft_add_entry(struct ntmp_user *user, u32 entry_id,
+ struct maft_entry_data *maft)
+{
+ return 0;
+}
+
+static inline int ntmp_maft_query_entry(struct ntmp_user *user, u32 entry_id,
+ struct maft_entry_data *maft)
+{
+ return 0;
+}
+
+static inline int ntmp_maft_delete_entry(struct ntmp_user *user, u32 entry_id)
+{
+ return 0;
+}
+
+static inline int ntmp_rsst_update_entry(struct ntmp_user *user,
+ const u32 *table, int count)
+{
+ return 0;
+}
+
+static inline int ntmp_rsst_query_entry(struct ntmp_user *user,
+ u32 *table, int count)
+{
+ return 0;
+}
+
+#endif
+
+#endif
--
2.34.1
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH v5 net-next 02/14] net: enetc: add command BD ring support for i.MX95 ENETC
2025-04-11 9:57 [PATCH v5 net-next 00/14] Add more features for ENETC v4 - round 2 Wei Fang
2025-04-11 9:57 ` [PATCH v5 net-next 01/14] net: enetc: add initial netc-lib driver to support NTMP Wei Fang
@ 2025-04-11 9:57 ` Wei Fang
2025-04-18 13:25 ` Vladimir Oltean
2025-04-11 9:57 ` [PATCH v5 net-next 03/14] net: enetc: move generic MAC filtering interfaces to enetc-core Wei Fang
` (11 subsequent siblings)
13 siblings, 1 reply; 29+ messages in thread
From: Wei Fang @ 2025-04-11 9:57 UTC (permalink / raw)
To: claudiu.manoil, vladimir.oltean, xiaoning.wang, andrew+netdev,
davem, edumazet, kuba, pabeni
Cc: christophe.leroy, netdev, linux-kernel, imx, linuxppc-dev,
linux-arm-kernel
The command BD ring is used to configure functionality where the
underlying resources may be shared between different entities or being
too large to configure using direct registers (such as lookup tables).
Because the command BD and table formats of i.MX95 and LS1028A are very
different, the software processing logic is also different. So add
enetc4_setup_cbdr() and enetc4_teardown_cbdr() for ENETC v4 drivers.
Signed-off-by: Wei Fang <wei.fang@nxp.com>
---
v5 changes:
1. Remove setup_cbdr() and teardown_cbdr() hooks
2. Rename enetc4_init_ntmp_priv() to enetc4_init_ntmp_user()
3. Modify the commit message
---
drivers/net/ethernet/freescale/enetc/enetc.h | 9 ++++-
.../net/ethernet/freescale/enetc/enetc4_pf.c | 39 ++++++++++++++++++-
.../net/ethernet/freescale/enetc/enetc_cbdr.c | 39 +++++++++++++++++++
3 files changed, 85 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h
index 4ad4eb5c5a74..384e0bded87f 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -8,6 +8,7 @@
#include <linux/dma-mapping.h>
#include <linux/skbuff.h>
#include <linux/ethtool.h>
+#include <linux/fsl/ntmp.h>
#include <linux/if_vlan.h>
#include <linux/phylink.h>
#include <linux/dim.h>
@@ -274,7 +275,10 @@ struct enetc_si {
struct net_device *ndev; /* back ref. */
- struct enetc_cbdr cbd_ring;
+ union {
+ struct enetc_cbdr cbd_ring; /* Only ENETC 1.0 */
+ struct ntmp_user ntmp_user; /* ENETC 4.1 and later */
+ };
int num_rx_rings; /* how many rings are available in the SI */
int num_tx_rings;
@@ -284,6 +288,7 @@ struct enetc_si {
u16 revision;
int hw_features;
const struct enetc_drvdata *drvdata;
+ const struct enetc_si_ops *ops;
};
#define ENETC_SI_ALIGN 32
@@ -493,6 +498,8 @@ void enetc_mm_commit_preemptible_tcs(struct enetc_ndev_priv *priv);
int enetc_setup_cbdr(struct device *dev, struct enetc_hw *hw, int bd_count,
struct enetc_cbdr *cbdr);
void enetc_teardown_cbdr(struct enetc_cbdr *cbdr);
+int enetc4_setup_cbdr(struct enetc_si *si);
+void enetc4_teardown_cbdr(struct enetc_si *si);
int enetc_set_mac_flt_entry(struct enetc_si *si, int index,
char *mac_addr, int si_map);
int enetc_clear_mac_flt_entry(struct enetc_si *si, int index);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
index 73ac8c6afb3a..175eebadde76 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -260,6 +260,21 @@ static void enetc4_configure_port(struct enetc_pf *pf)
enetc4_enable_trx(pf);
}
+static int enetc4_init_ntmp_user(struct enetc_si *si)
+{
+ struct ntmp_user *user = &si->ntmp_user;
+
+ /* For ENETC 4.1, all table versions are 0 */
+ memset(&user->tbl, 0, sizeof(user->tbl));
+
+ return enetc4_setup_cbdr(si);
+}
+
+static void enetc4_free_ntmp_user(struct enetc_si *si)
+{
+ enetc4_teardown_cbdr(si);
+}
+
static int enetc4_pf_init(struct enetc_pf *pf)
{
struct device *dev = &pf->si->pdev->dev;
@@ -272,11 +287,22 @@ static int enetc4_pf_init(struct enetc_pf *pf)
return err;
}
+ err = enetc4_init_ntmp_user(pf->si);
+ if (err) {
+ dev_err(dev, "Failed to init CBDR\n");
+ return err;
+ }
+
enetc4_configure_port(pf);
return 0;
}
+static void enetc4_pf_free(struct enetc_pf *pf)
+{
+ enetc4_free_ntmp_user(pf->si);
+}
+
static const struct net_device_ops enetc4_ndev_ops = {
.ndo_open = enetc_open,
.ndo_stop = enetc_close,
@@ -728,14 +754,25 @@ static int enetc4_pf_probe(struct pci_dev *pdev,
enetc_get_si_caps(si);
- return enetc4_pf_netdev_create(si);
+ err = enetc4_pf_netdev_create(si);
+ if (err)
+ goto err_netdev_create;
+
+ return 0;
+
+err_netdev_create:
+ enetc4_pf_free(pf);
+
+ return err;
}
static void enetc4_pf_remove(struct pci_dev *pdev)
{
struct enetc_si *si = pci_get_drvdata(pdev);
+ struct enetc_pf *pf = enetc_si_priv(si);
enetc4_pf_netdev_destroy(si);
+ enetc4_pf_free(pf);
}
static const struct pci_device_id enetc4_pf_id_table[] = {
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c b/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
index 20bfdf7fb4b4..ecb571e5ea50 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
@@ -60,6 +60,45 @@ void enetc_teardown_cbdr(struct enetc_cbdr *cbdr)
}
EXPORT_SYMBOL_GPL(enetc_teardown_cbdr);
+int enetc4_setup_cbdr(struct enetc_si *si)
+{
+ struct ntmp_user *user = &si->ntmp_user;
+ struct device *dev = &si->pdev->dev;
+ struct enetc_hw *hw = &si->hw;
+ struct netc_cbdr_regs regs;
+
+ user->cbdr_num = 1;
+ user->cbdr_size = NETC_CBDR_BD_NUM;
+ user->dev = dev;
+ user->ring = devm_kcalloc(dev, user->cbdr_num,
+ sizeof(struct netc_cbdr), GFP_KERNEL);
+ if (!user->ring)
+ return -ENOMEM;
+
+ /* set CBDR cache attributes */
+ enetc_wr(hw, ENETC_SICAR2,
+ ENETC_SICAR_RD_COHERENT | ENETC_SICAR_WR_COHERENT);
+
+ regs.pir = hw->reg + ENETC_SICBDRPIR;
+ regs.cir = hw->reg + ENETC_SICBDRCIR;
+ regs.mr = hw->reg + ENETC_SICBDRMR;
+ regs.bar0 = hw->reg + ENETC_SICBDRBAR0;
+ regs.bar1 = hw->reg + ENETC_SICBDRBAR1;
+ regs.lenr = hw->reg + ENETC_SICBDRLENR;
+
+ return netc_setup_cbdr(dev, user->cbdr_size, ®s, user->ring);
+}
+EXPORT_SYMBOL_GPL(enetc4_setup_cbdr);
+
+void enetc4_teardown_cbdr(struct enetc_si *si)
+{
+ struct ntmp_user *user = &si->ntmp_user;
+
+ netc_teardown_cbdr(user->dev, user->ring);
+ user->dev = NULL;
+}
+EXPORT_SYMBOL_GPL(enetc4_teardown_cbdr);
+
static void enetc_clean_cbdr(struct enetc_cbdr *ring)
{
struct enetc_cbd *dest_cbd;
--
2.34.1
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH v5 net-next 03/14] net: enetc: move generic MAC filtering interfaces to enetc-core
2025-04-11 9:57 [PATCH v5 net-next 00/14] Add more features for ENETC v4 - round 2 Wei Fang
2025-04-11 9:57 ` [PATCH v5 net-next 01/14] net: enetc: add initial netc-lib driver to support NTMP Wei Fang
2025-04-11 9:57 ` [PATCH v5 net-next 02/14] net: enetc: add command BD ring support for i.MX95 ENETC Wei Fang
@ 2025-04-11 9:57 ` Wei Fang
2025-04-18 13:37 ` Vladimir Oltean
2025-04-11 9:57 ` [PATCH v5 net-next 04/14] net: enetc: add MAC filtering for i.MX95 ENETC PF Wei Fang
` (10 subsequent siblings)
13 siblings, 1 reply; 29+ messages in thread
From: Wei Fang @ 2025-04-11 9:57 UTC (permalink / raw)
To: claudiu.manoil, vladimir.oltean, xiaoning.wang, andrew+netdev,
davem, edumazet, kuba, pabeni
Cc: christophe.leroy, netdev, linux-kernel, imx, linuxppc-dev,
linux-arm-kernel
Although only ENETC PF can access the MAC address filter table, the table
entries can specify MAC address filtering for one or more SIs based on
SI_BITMAP, which means that the table also supports MAC address filtering
for VFs.
Currently, only the ENETC v1 PF driver supports MAC address filtering. In
order to add the MAC address filtering support for the ENETC v4 PF driver
and VF driver in the future, the relevant generic interfaces are moved to
the enetc-core driver. This lays the basis for i.MX95 ENETC PF and VFs to
support MAC address filtering.
Signed-off-by: Wei Fang <wei.fang@nxp.com>
---
v5 changes:
1. Keep mac_filter in struct enetc_pf
2. Modify the commit message
---
drivers/net/ethernet/freescale/enetc/enetc.c | 36 +++++++++++++++++++
drivers/net/ethernet/freescale/enetc/enetc.h | 15 ++++++++
.../net/ethernet/freescale/enetc/enetc_pf.c | 34 ------------------
.../net/ethernet/freescale/enetc/enetc_pf.h | 11 ------
4 files changed, 51 insertions(+), 45 deletions(-)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c
index 2106861463e4..3832d2cd91ba 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -36,6 +36,42 @@ static void enetc_change_preemptible_tcs(struct enetc_ndev_priv *priv,
enetc_mm_commit_preemptible_tcs(priv);
}
+static int enetc_mac_addr_hash_idx(const u8 *addr)
+{
+ u64 fold = __swab64(ether_addr_to_u64(addr)) >> 16;
+ u64 mask = 0;
+ int res = 0;
+ int i;
+
+ for (i = 0; i < 8; i++)
+ mask |= BIT_ULL(i * 6);
+
+ for (i = 0; i < 6; i++)
+ res |= (hweight64(fold & (mask << i)) & 0x1) << i;
+
+ return res;
+}
+
+void enetc_add_mac_addr_ht_filter(struct enetc_mac_filter *filter,
+ const unsigned char *addr)
+{
+ int idx = enetc_mac_addr_hash_idx(addr);
+
+ /* add hash table entry */
+ __set_bit(idx, filter->mac_hash_table);
+ filter->mac_addr_cnt++;
+}
+EXPORT_SYMBOL_GPL(enetc_add_mac_addr_ht_filter);
+
+void enetc_reset_mac_addr_filter(struct enetc_mac_filter *filter)
+{
+ filter->mac_addr_cnt = 0;
+
+ bitmap_zero(filter->mac_hash_table,
+ ENETC_MADDR_HASH_TBL_SZ);
+}
+EXPORT_SYMBOL_GPL(enetc_reset_mac_addr_filter);
+
static int enetc_num_stack_tx_queues(struct enetc_ndev_priv *priv)
{
int num_tx_rings = priv->num_tx_rings;
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h
index 384e0bded87f..c3ebb32ce50c 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -23,6 +23,18 @@
#define ENETC_CBD_DATA_MEM_ALIGN 64
+#define ENETC_MADDR_HASH_TBL_SZ 64
+
+enum enetc_mac_addr_type {UC, MC, MADDR_TYPE};
+
+struct enetc_mac_filter {
+ union {
+ char mac_addr[ETH_ALEN];
+ DECLARE_BITMAP(mac_hash_table, ENETC_MADDR_HASH_TBL_SZ);
+ };
+ int mac_addr_cnt;
+};
+
struct enetc_tx_swbd {
union {
struct sk_buff *skb;
@@ -471,6 +483,9 @@ int enetc_alloc_si_resources(struct enetc_ndev_priv *priv);
void enetc_free_si_resources(struct enetc_ndev_priv *priv);
int enetc_configure_si(struct enetc_ndev_priv *priv);
int enetc_get_driver_data(struct enetc_si *si);
+void enetc_add_mac_addr_ht_filter(struct enetc_mac_filter *filter,
+ const unsigned char *addr);
+void enetc_reset_mac_addr_filter(struct enetc_mac_filter *filter);
int enetc_open(struct net_device *ndev);
int enetc_close(struct net_device *ndev);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index 203862ec1114..f76403f7aee8 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -72,30 +72,6 @@ static void enetc_set_isol_vlan(struct enetc_hw *hw, int si, u16 vlan, u8 qos)
enetc_port_wr(hw, ENETC_PSIVLANR(si), val);
}
-static int enetc_mac_addr_hash_idx(const u8 *addr)
-{
- u64 fold = __swab64(ether_addr_to_u64(addr)) >> 16;
- u64 mask = 0;
- int res = 0;
- int i;
-
- for (i = 0; i < 8; i++)
- mask |= BIT_ULL(i * 6);
-
- for (i = 0; i < 6; i++)
- res |= (hweight64(fold & (mask << i)) & 0x1) << i;
-
- return res;
-}
-
-static void enetc_reset_mac_addr_filter(struct enetc_mac_filter *filter)
-{
- filter->mac_addr_cnt = 0;
-
- bitmap_zero(filter->mac_hash_table,
- ENETC_MADDR_HASH_TBL_SZ);
-}
-
static void enetc_add_mac_addr_em_filter(struct enetc_mac_filter *filter,
const unsigned char *addr)
{
@@ -104,16 +80,6 @@ static void enetc_add_mac_addr_em_filter(struct enetc_mac_filter *filter,
filter->mac_addr_cnt++;
}
-static void enetc_add_mac_addr_ht_filter(struct enetc_mac_filter *filter,
- const unsigned char *addr)
-{
- int idx = enetc_mac_addr_hash_idx(addr);
-
- /* add hash table entry */
- __set_bit(idx, filter->mac_hash_table);
- 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;
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.h b/drivers/net/ethernet/freescale/enetc/enetc_pf.h
index a26a12863855..a8b3c8d14254 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.h
@@ -5,19 +5,8 @@
#include <linux/phylink.h>
#define ENETC_PF_NUM_RINGS 8
-
-enum enetc_mac_addr_type {UC, MC, MADDR_TYPE};
#define ENETC_MAX_NUM_MAC_FLT ((ENETC_MAX_NUM_VFS + 1) * MADDR_TYPE)
-#define ENETC_MADDR_HASH_TBL_SZ 64
-struct enetc_mac_filter {
- union {
- char mac_addr[ETH_ALEN];
- DECLARE_BITMAP(mac_hash_table, ENETC_MADDR_HASH_TBL_SZ);
- };
- int mac_addr_cnt;
-};
-
#define ENETC_VLAN_HT_SIZE 64
enum enetc_vf_flags {
--
2.34.1
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH v5 net-next 04/14] net: enetc: add MAC filtering for i.MX95 ENETC PF
2025-04-11 9:57 [PATCH v5 net-next 00/14] Add more features for ENETC v4 - round 2 Wei Fang
` (2 preceding siblings ...)
2025-04-11 9:57 ` [PATCH v5 net-next 03/14] net: enetc: move generic MAC filtering interfaces to enetc-core Wei Fang
@ 2025-04-11 9:57 ` Wei Fang
2025-04-16 3:42 ` Jakub Kicinski
2025-04-18 15:41 ` Vladimir Oltean
2025-04-11 9:57 ` [PATCH v5 net-next 05/14] net: enetc: add debugfs interface to dump MAC filter Wei Fang
` (9 subsequent siblings)
13 siblings, 2 replies; 29+ messages in thread
From: Wei Fang @ 2025-04-11 9:57 UTC (permalink / raw)
To: claudiu.manoil, vladimir.oltean, xiaoning.wang, andrew+netdev,
davem, edumazet, kuba, pabeni
Cc: christophe.leroy, netdev, linux-kernel, imx, linuxppc-dev,
linux-arm-kernel
The i.MX95 ENETC supports both MAC hash filter and MAC exact filter. MAC
hash filter is implenented through a 64-bit hash table to match against
the hashed addresses, PF and VFs each have two MAC hash tables, one is
for unicast and the other one is for multicast. But MAC exact filter is
shared between SIs (PF and VFs), each table entry contains a MAC address
that may be unicast or multicast and the entry also contains an SI bitmap
field that indicates for which SIs the entry is valid.
For i.MX95 ENETC, MAC exact filter only has 4 entries. According to the
observation of the system default network configuration, the MAC filter
will be configured with multiple multicast addresses, so MAC exact filter
does not have enough entries to implement multicast filtering. Therefore,
the current MAC exact filter is only used for unicast filtering. If the
number of unicast addresses exceeds 4, then MAC hash filter is used.
Note that both MAC hash filter and MAC exact filter can only be accessed
by PF, VFs can notify PF to set its corresponding MAC filter through the
mailbox mechanism of ENETC. But currently MAC filter is only added for
i.MX95 ENETC PF. The MAC filter support of ENETC VFs will be supported in
subsequent patches.
Signed-off-by: Wei Fang <wei.fang@nxp.com>
---
v5 changes:
1. Refactor enetc4_pf_set_si_mac_promisc()
2. Split enetc4_pf_set_si_mac_hash_filter() into
enetc4_pf_set_si_uc_hash_filter() and enetc4_pf_set_si_mc_hash_filter()
3. Rename enetc4_pf_wq_task_init() to enetc4_psi_wq_task_init()
4. Rename enetc4_pf_do_set_rx_mode() to enetc4_psi_do_set_rx_mode()
5. Remove mac_list_lock and mac_list related functions
6. Add enetc4_pf_clear_maft_entries() and enetc4_pf_add_maft_entries()
7. Refactor enetc4_pf_set_mac_exact_filter() and rename it to
enetc4_pf_set_uc_exact_filter()
---
drivers/net/ethernet/freescale/enetc/enetc.h | 3 +
.../net/ethernet/freescale/enetc/enetc4_hw.h | 8 +
.../net/ethernet/freescale/enetc/enetc4_pf.c | 251 +++++++++++++++++-
.../net/ethernet/freescale/enetc/enetc_pf.h | 3 +
4 files changed, 264 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h
index c3ebb32ce50c..1573ff06fcf4 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -301,6 +301,9 @@ struct enetc_si {
int hw_features;
const struct enetc_drvdata *drvdata;
const struct enetc_si_ops *ops;
+
+ struct workqueue_struct *workqueue;
+ struct work_struct rx_mode_task;
};
#define ENETC_SI_ALIGN 32
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_hw.h b/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
index 695cb07c74bc..826359004850 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
@@ -99,6 +99,14 @@
#define ENETC4_PSICFGR2(a) ((a) * 0x80 + 0x2018)
#define PSICFGR2_NUM_MSIX GENMASK(5, 0)
+/* Port station interface a unicast MAC hash filter register 0/1 */
+#define ENETC4_PSIUMHFR0(a) ((a) * 0x80 + 0x2050)
+#define ENETC4_PSIUMHFR1(a) ((a) * 0x80 + 0x2054)
+
+/* Port station interface a multicast MAC hash filter register 0/1 */
+#define ENETC4_PSIMMHFR0(a) ((a) * 0x80 + 0x2058)
+#define ENETC4_PSIMMHFR1(a) ((a) * 0x80 + 0x205c)
+
#define ENETC4_PMCAPR 0x4004
#define PMCAPR_HD BIT(8)
#define PMCAPR_FP GENMASK(10, 9)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
index 175eebadde76..4c2d944d6b05 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -11,6 +11,15 @@
#define ENETC_SI_MAX_RING_NUM 8
+#define ENETC_MAC_FILTER_TYPE_UC BIT(0)
+#define ENETC_MAC_FILTER_TYPE_MC BIT(1)
+#define ENETC_MAC_FILTER_TYPE_ALL (ENETC_MAC_FILTER_TYPE_UC | \
+ ENETC_MAC_FILTER_TYPE_MC)
+
+struct enetc_mac_addr {
+ u8 addr[ETH_ALEN];
+};
+
static void enetc4_get_port_caps(struct enetc_pf *pf)
{
struct enetc_hw *hw = &pf->si->hw;
@@ -26,6 +35,9 @@ static void enetc4_get_port_caps(struct enetc_pf *pf)
val = enetc_port_rd(hw, ENETC4_PMCAPR);
pf->caps.half_duplex = (val & PMCAPR_HD) ? 1 : 0;
+
+ val = enetc_port_rd(hw, ENETC4_PSIMAFCAPR);
+ pf->caps.mac_filter_num = val & PSIMAFCAPR_NUM_MAC_AFTE;
}
static void enetc4_pf_set_si_primary_mac(struct enetc_hw *hw, int si,
@@ -56,6 +68,180 @@ 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_clear_maft_entries(struct enetc_pf *pf)
+{
+ int i;
+
+ for (i = 0; i < pf->num_mfe; i++)
+ ntmp_maft_delete_entry(&pf->si->ntmp_user, i);
+
+ pf->num_mfe = 0;
+}
+
+static int enetc4_pf_add_maft_entries(struct enetc_pf *pf,
+ struct enetc_mac_addr *mac,
+ int mac_cnt)
+{
+ struct maft_entry_data maft = {};
+ u16 si_bit = BIT(0);
+ int i, err;
+
+ 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);
+ if (unlikely(err)) {
+ pf->num_mfe = i;
+ goto clear_maft_entries;
+ }
+ }
+
+ pf->num_mfe = mac_cnt;
+
+ return 0;
+
+clear_maft_entries:
+ enetc4_pf_clear_maft_entries(pf);
+
+ return err;
+}
+
+static int enetc4_pf_set_uc_exact_filter(struct enetc_pf *pf)
+{
+ 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 netdev_hw_addr *ha;
+ int i = 0, err = 0;
+ int mac_cnt;
+
+ netif_addr_lock_bh(ndev);
+
+ mac_cnt = netdev_uc_count(ndev);
+ if (mac_cnt > max_num_mfe) {
+ err = -ENOSPC;
+ goto unlock_netif_addr;
+ }
+
+ /* No need to set MAC exact filter */
+ if (!mac_cnt)
+ goto unlock_netif_addr;
+
+ mac_tbl = kcalloc(mac_cnt, sizeof(*mac_tbl), 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
+ * updating MAC address filter table
+ */
+ enetc4_pf_set_si_uc_hash_filter(hw, 0, *mac_filter.mac_hash_table);
+ 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);
+
+ return err;
+}
+
+static void enetc4_pf_set_mac_hash_filter(struct enetc_pf *pf, int type)
+{
+ struct net_device *ndev = pf->si->ndev;
+ struct enetc_mac_filter *mac_filter;
+ struct enetc_hw *hw = &pf->si->hw;
+ struct netdev_hw_addr *ha;
+
+ 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);
+ }
+
+ 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);
+}
+
+static void enetc4_pf_set_mac_filter(struct enetc_pf *pf, int type)
+{
+ /* Currently, the MAC address filter table (MAFT) only has 4 entries,
+ * and multiple multicast addresses for filtering will be configured
+ * in the default network configuration, so MAFT is only suitable for
+ * 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)) {
+ /* Clear the old MAC exact filter */
+ enetc4_pf_clear_maft_entries(pf);
+ /* Fall back to the MAC hash filter */
+ enetc4_pf_set_mac_hash_filter(pf, ENETC_MAC_FILTER_TYPE_UC);
+ }
+
+ if (type & ENETC_MAC_FILTER_TYPE_MC)
+ enetc4_pf_set_mac_hash_filter(pf, ENETC_MAC_FILTER_TYPE_MC);
+}
+
static const struct enetc_pf_ops enetc4_pf_ops = {
.set_si_primary_mac = enetc4_pf_set_si_primary_mac,
.get_si_primary_mac = enetc4_pf_get_si_primary_mac,
@@ -303,12 +489,55 @@ 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)
+{
+ 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;
+ bool uc_promisc = false;
+ bool mc_promisc = false;
+ int type = 0;
+
+ if (ndev->flags & IFF_PROMISC) {
+ uc_promisc = true;
+ mc_promisc = true;
+ } else if (ndev->flags & IFF_ALLMULTI) {
+ mc_promisc = true;
+ type = ENETC_MAC_FILTER_TYPE_UC;
+ } else {
+ type = ENETC_MAC_FILTER_TYPE_ALL;
+ }
+
+ enetc4_pf_set_si_mac_promisc(hw, 0, uc_promisc, mc_promisc);
+
+ if (uc_promisc) {
+ enetc4_pf_set_si_uc_hash_filter(hw, 0, 0);
+ enetc4_pf_clear_maft_entries(pf);
+ }
+
+ if (mc_promisc)
+ enetc4_pf_set_si_mc_hash_filter(hw, 0, 0);
+
+ /* Set new MAC filter */
+ enetc4_pf_set_mac_filter(pf, type);
+}
+
+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);
+}
+
static const struct net_device_ops enetc4_ndev_ops = {
.ndo_open = enetc_open,
.ndo_stop = enetc_close,
.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,
};
static struct phylink_pcs *
@@ -714,6 +943,19 @@ static void enetc4_pf_netdev_destroy(struct enetc_si *si)
free_netdev(ndev);
}
+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_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
@@ -748,10 +990,14 @@ static int enetc4_pf_probe(struct pci_dev *pdev,
return err;
pf = enetc_si_priv(si);
- err = enetc4_pf_init(pf);
+ err = enetc4_psi_wq_task_init(si);
if (err)
return err;
+ err = enetc4_pf_init(pf);
+ if (err)
+ goto err_pf_init;
+
enetc_get_si_caps(si);
err = enetc4_pf_netdev_create(si);
@@ -762,6 +1008,8 @@ static int enetc4_pf_probe(struct pci_dev *pdev,
err_netdev_create:
enetc4_pf_free(pf);
+err_pf_init:
+ destroy_workqueue(si->workqueue);
return err;
}
@@ -773,6 +1021,7 @@ static void enetc4_pf_remove(struct pci_dev *pdev)
enetc4_pf_netdev_destroy(si);
enetc4_pf_free(pf);
+ destroy_workqueue(si->workqueue);
}
static const struct pci_device_id enetc4_pf_id_table[] = {
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.h b/drivers/net/ethernet/freescale/enetc/enetc_pf.h
index a8b3c8d14254..ae407e9e9ee7 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.h
@@ -23,6 +23,7 @@ struct enetc_port_caps {
int num_msix;
int num_rx_bdr;
int num_tx_bdr;
+ int mac_filter_num;
};
struct enetc_pf;
@@ -60,6 +61,8 @@ 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) \
--
2.34.1
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH v5 net-next 05/14] net: enetc: add debugfs interface to dump MAC filter
2025-04-11 9:57 [PATCH v5 net-next 00/14] Add more features for ENETC v4 - round 2 Wei Fang
` (3 preceding siblings ...)
2025-04-11 9:57 ` [PATCH v5 net-next 04/14] net: enetc: add MAC filtering for i.MX95 ENETC PF Wei Fang
@ 2025-04-11 9:57 ` Wei Fang
2025-04-11 9:57 ` [PATCH v5 net-next 06/14] net: enetc: add set/get_rss_table() hooks to enetc_si_ops Wei Fang
` (8 subsequent siblings)
13 siblings, 0 replies; 29+ messages in thread
From: Wei Fang @ 2025-04-11 9:57 UTC (permalink / raw)
To: claudiu.manoil, vladimir.oltean, xiaoning.wang, andrew+netdev,
davem, edumazet, kuba, pabeni
Cc: christophe.leroy, netdev, linux-kernel, imx, linuxppc-dev,
linux-arm-kernel
ENETC's MAC filter consists of hash MAC filter and exact MAC filter.
Hash MAC filter is a 64-bit entry hash table consisting of two 32-bit
registers. Exact MAC filter is implemented by configuring MAC address
filter table through command BD ring. The table is stored in ENETC's
internal memory and needs to be read through command BD ring. In order
to facilitate debugging, added a debugfs interface to get the relevant
information about MAC filter.
Signed-off-by: Wei Fang <wei.fang@nxp.com>
---
v5 changes:
1. Replace is_en() with str_enabled_disabled()
2. Remove superfluous "Show" in the debug log
3. Remove keye variable from enetc_mac_filter_show()
---
drivers/net/ethernet/freescale/enetc/Makefile | 1 +
drivers/net/ethernet/freescale/enetc/enetc.h | 1 +
.../ethernet/freescale/enetc/enetc4_debugfs.c | 90 +++++++++++++++++++
.../ethernet/freescale/enetc/enetc4_debugfs.h | 20 +++++
.../net/ethernet/freescale/enetc/enetc4_pf.c | 4 +
5 files changed, 116 insertions(+)
create mode 100644 drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c
create mode 100644 drivers/net/ethernet/freescale/enetc/enetc4_debugfs.h
diff --git a/drivers/net/ethernet/freescale/enetc/Makefile b/drivers/net/ethernet/freescale/enetc/Makefile
index 707a68e26971..f1c5ad45fd76 100644
--- a/drivers/net/ethernet/freescale/enetc/Makefile
+++ b/drivers/net/ethernet/freescale/enetc/Makefile
@@ -16,6 +16,7 @@ fsl-enetc-$(CONFIG_FSL_ENETC_QOS) += enetc_qos.o
obj-$(CONFIG_NXP_ENETC4) += nxp-enetc4.o
nxp-enetc4-y := enetc4_pf.o
+nxp-enetc4-$(CONFIG_DEBUG_FS) += enetc4_debugfs.o
obj-$(CONFIG_FSL_ENETC_VF) += fsl-enetc-vf.o
fsl-enetc-vf-y := enetc_vf.o
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h
index 1573ff06fcf4..b53ecc882a90 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -304,6 +304,7 @@ struct enetc_si {
struct workqueue_struct *workqueue;
struct work_struct rx_mode_task;
+ struct dentry *debugfs_root;
};
#define ENETC_SI_ALIGN 32
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c b/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c
new file mode 100644
index 000000000000..3479c0abe9e6
--- /dev/null
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright 2025 NXP */
+
+#include <linux/device.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/string_choices.h>
+
+#include "enetc_pf.h"
+#include "enetc4_debugfs.h"
+
+static void enetc_show_si_mac_hash_filter(struct seq_file *s, int i)
+{
+ struct enetc_si *si = s->private;
+ struct enetc_hw *hw = &si->hw;
+ u32 hash_h, hash_l;
+
+ hash_l = enetc_port_rd(hw, ENETC4_PSIUMHFR0(i));
+ hash_h = enetc_port_rd(hw, ENETC4_PSIUMHFR1(i));
+ seq_printf(s, "SI %d unicast MAC hash filter: 0x%08x%08x\n",
+ i, hash_h, hash_l);
+
+ hash_l = enetc_port_rd(hw, ENETC4_PSIMMHFR0(i));
+ hash_h = enetc_port_rd(hw, ENETC4_PSIMMHFR1(i));
+ seq_printf(s, "SI %d multicast MAC hash filter: 0x%08x%08x\n",
+ i, hash_h, hash_l);
+}
+
+static int enetc_mac_filter_show(struct seq_file *s, void *data)
+{
+ struct enetc_si *si = s->private;
+ struct enetc_hw *hw = &si->hw;
+ struct maft_entry_data maft;
+ struct enetc_pf *pf;
+ int i, err, num_si;
+ u32 val;
+
+ pf = enetc_si_priv(si);
+ num_si = pf->caps.num_vsi + 1;
+
+ val = enetc_port_rd(hw, ENETC4_PSIPMMR);
+ for (i = 0; i < num_si; i++) {
+ seq_printf(s, "SI %d Unicast Promiscuous mode: %s\n", i,
+ str_enabled_disabled(PSIPMMR_SI_MAC_UP(i) & val));
+ seq_printf(s, "SI %d Multicast Promiscuous mode: %s\n", i,
+ str_enabled_disabled(PSIPMMR_SI_MAC_MP(i) & val));
+ }
+
+ /* MAC hash filter table */
+ for (i = 0; i < num_si; i++)
+ enetc_show_si_mac_hash_filter(s, i);
+
+ if (!pf->num_mfe)
+ return 0;
+
+ /* MAC address filter table */
+ seq_puts(s, "MAC address filter table\n");
+ for (i = 0; i < pf->num_mfe; i++) {
+ memset(&maft, 0, sizeof(maft));
+ err = ntmp_maft_query_entry(&si->ntmp_user, i, &maft);
+ if (err)
+ return err;
+
+ seq_printf(s, "Entry %d, MAC: %pM, SI bitmap: 0x%04x\n", i,
+ maft.keye.mac_addr, le16_to_cpu(maft.cfge.si_bitmap));
+ }
+
+ return 0;
+}
+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);
+ if (IS_ERR(root))
+ return;
+
+ si->debugfs_root = root;
+
+ debugfs_create_file("mac_filter", 0444, root, si, &enetc_mac_filter_fops);
+}
+
+void enetc_remove_debugfs(struct enetc_si *si)
+{
+ debugfs_remove_recursive(si->debugfs_root);
+ si->debugfs_root = NULL;
+}
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.h b/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.h
new file mode 100644
index 000000000000..96caca35f79d
--- /dev/null
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
+/* Copyright 2025 NXP */
+
+#ifndef __ENETC4_DEBUGFS_H
+#define __ENETC4_DEBUGFS_H
+
+#if IS_ENABLED(CONFIG_DEBUG_FS)
+void enetc_create_debugfs(struct enetc_si *si);
+void enetc_remove_debugfs(struct enetc_si *si);
+#else
+static inline void enetc_create_debugfs(struct enetc_si *si)
+{
+}
+
+static inline void enetc_remove_debugfs(struct enetc_si *si)
+{
+}
+#endif
+
+#endif
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
index 4c2d944d6b05..bbe16c140875 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -8,6 +8,7 @@
#include <linux/unaligned.h>
#include "enetc_pf_common.h"
+#include "enetc4_debugfs.h"
#define ENETC_SI_MAX_RING_NUM 8
@@ -1004,6 +1005,8 @@ static int enetc4_pf_probe(struct pci_dev *pdev,
if (err)
goto err_netdev_create;
+ enetc_create_debugfs(si);
+
return 0;
err_netdev_create:
@@ -1019,6 +1022,7 @@ static void enetc4_pf_remove(struct pci_dev *pdev)
struct enetc_si *si = pci_get_drvdata(pdev);
struct enetc_pf *pf = enetc_si_priv(si);
+ enetc_remove_debugfs(si);
enetc4_pf_netdev_destroy(si);
enetc4_pf_free(pf);
destroy_workqueue(si->workqueue);
--
2.34.1
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH v5 net-next 06/14] net: enetc: add set/get_rss_table() hooks to enetc_si_ops
2025-04-11 9:57 [PATCH v5 net-next 00/14] Add more features for ENETC v4 - round 2 Wei Fang
` (4 preceding siblings ...)
2025-04-11 9:57 ` [PATCH v5 net-next 05/14] net: enetc: add debugfs interface to dump MAC filter Wei Fang
@ 2025-04-11 9:57 ` Wei Fang
2025-04-15 13:43 ` Paolo Abeni
2025-04-11 9:57 ` [PATCH v5 net-next 07/14] net: enetc: make enetc_set_rss_key() reusable Wei Fang
` (7 subsequent siblings)
13 siblings, 1 reply; 29+ messages in thread
From: Wei Fang @ 2025-04-11 9:57 UTC (permalink / raw)
To: claudiu.manoil, vladimir.oltean, xiaoning.wang, andrew+netdev,
davem, edumazet, kuba, pabeni
Cc: christophe.leroy, netdev, linux-kernel, imx, linuxppc-dev,
linux-arm-kernel
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=y, Size: 5476 bytes --]
Since i.MX95 ENETC (v4) uses NTMP 2.0 to manage the RSS table, which is
different from LS1028A ENETC (v1). In order to reuse some functions
related to the RSS table, so add .get_rss_table() and .set_rss_table()
hooks to enetc_si_ops.
Signed-off-by: Wei Fang <wei.fang@nxp.com>
---
v5 changes:
Add enetc_set_default_rss_key() to enetc_pf_common.c and use it in both
enetc v1 and v4 drivers
---
drivers/net/ethernet/freescale/enetc/enetc.c | 2 +-
drivers/net/ethernet/freescale/enetc/enetc.h | 13 +++++++++++++
.../net/ethernet/freescale/enetc/enetc_ethtool.c | 12 ++++++------
drivers/net/ethernet/freescale/enetc/enetc_pf.c | 6 ++++++
drivers/net/ethernet/freescale/enetc/enetc_vf.c | 6 ++++++
5 files changed, 32 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c
index 3832d2cd91ba..2a8fa455e96b 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -2405,7 +2405,7 @@ static int enetc_setup_default_rss_table(struct enetc_si *si, int num_groups)
for (i = 0; i < si->num_rss; i++)
rss_table[i] = i % num_groups;
- enetc_set_rss_table(si, rss_table, si->num_rss);
+ si->ops->set_rss_table(si, rss_table, si->num_rss);
kfree(rss_table);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h
index b53ecc882a90..786042029b1e 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -279,6 +279,19 @@ struct enetc_platform_info {
const struct enetc_drvdata *data;
};
+struct enetc_si;
+
+/*
+ * This structure defines the some common hooks for ENETC PSI and VSI.
+ * In addition, since VSI only uses the struct enetc_si as its private
+ * driver data, so this structure also define some hooks specifically
+ * for VSI. For VSI-specific hooks, the format is ‘vf_*()’.
+ */
+struct enetc_si_ops {
+ int (*get_rss_table)(struct enetc_si *si, u32 *table, int count);
+ int (*set_rss_table)(struct enetc_si *si, const u32 *table, int count);
+};
+
/* PCI IEP device data */
struct enetc_si {
struct pci_dev *pdev;
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
index ece3ae28ba82..d14182401d81 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
@@ -681,7 +681,8 @@ static int enetc_get_rxfh(struct net_device *ndev,
struct ethtool_rxfh_param *rxfh)
{
struct enetc_ndev_priv *priv = netdev_priv(ndev);
- struct enetc_hw *hw = &priv->si->hw;
+ struct enetc_si *si = priv->si;
+ struct enetc_hw *hw = &si->hw;
int err = 0, i;
/* return hash function */
@@ -695,8 +696,7 @@ static int enetc_get_rxfh(struct net_device *ndev,
/* return RSS table */
if (rxfh->indir)
- err = enetc_get_rss_table(priv->si, rxfh->indir,
- priv->si->num_rss);
+ err = si->ops->get_rss_table(si, rxfh->indir, si->num_rss);
return err;
}
@@ -715,7 +715,8 @@ static int enetc_set_rxfh(struct net_device *ndev,
struct netlink_ext_ack *extack)
{
struct enetc_ndev_priv *priv = netdev_priv(ndev);
- struct enetc_hw *hw = &priv->si->hw;
+ struct enetc_si *si = priv->si;
+ struct enetc_hw *hw = &si->hw;
int err = 0;
/* set hash key, if PF */
@@ -724,8 +725,7 @@ static int enetc_set_rxfh(struct net_device *ndev,
/* set RSS table */
if (rxfh->indir)
- err = enetc_set_rss_table(priv->si, rxfh->indir,
- priv->si->num_rss);
+ err = si->ops->set_rss_table(si, rxfh->indir, si->num_rss);
return err;
}
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index f76403f7aee8..8dabb80ec04c 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -905,6 +905,11 @@ static int enetc_pf_register_with_ierb(struct pci_dev *pdev)
return enetc_ierb_register_pf(ierb_pdev, pdev);
}
+static const struct enetc_si_ops enetc_psi_ops = {
+ .get_rss_table = enetc_get_rss_table,
+ .set_rss_table = enetc_set_rss_table,
+};
+
static struct enetc_si *enetc_psi_create(struct pci_dev *pdev)
{
struct enetc_si *si;
@@ -924,6 +929,7 @@ static struct enetc_si *enetc_psi_create(struct pci_dev *pdev)
}
si->revision = enetc_get_ip_revision(&si->hw);
+ si->ops = &enetc_psi_ops;
err = enetc_get_driver_data(si);
if (err) {
dev_err(&pdev->dev, "Could not get PF driver data\n");
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_vf.c b/drivers/net/ethernet/freescale/enetc/enetc_vf.c
index 3768752b6008..4fafe4e18a37 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_vf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_vf.c
@@ -162,6 +162,11 @@ static void enetc_vf_netdev_setup(struct enetc_si *si, struct net_device *ndev,
enetc_load_primary_mac_addr(&si->hw, ndev);
}
+static const struct enetc_si_ops enetc_vsi_ops = {
+ .get_rss_table = enetc_get_rss_table,
+ .set_rss_table = enetc_set_rss_table,
+};
+
static int enetc_vf_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
@@ -176,6 +181,7 @@ static int enetc_vf_probe(struct pci_dev *pdev,
si = pci_get_drvdata(pdev);
si->revision = ENETC_REV_1_0;
+ si->ops = &enetc_vsi_ops;
err = enetc_get_driver_data(si);
if (err) {
dev_err_probe(&pdev->dev, err,
--
2.34.1
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH v5 net-next 07/14] net: enetc: make enetc_set_rss_key() reusable
2025-04-11 9:57 [PATCH v5 net-next 00/14] Add more features for ENETC v4 - round 2 Wei Fang
` (5 preceding siblings ...)
2025-04-11 9:57 ` [PATCH v5 net-next 06/14] net: enetc: add set/get_rss_table() hooks to enetc_si_ops Wei Fang
@ 2025-04-11 9:57 ` Wei Fang
2025-04-11 9:57 ` [PATCH v5 net-next 08/14] net: enetc: add RSS support for i.MX95 ENETC PF Wei Fang
` (6 subsequent siblings)
13 siblings, 0 replies; 29+ messages in thread
From: Wei Fang @ 2025-04-11 9:57 UTC (permalink / raw)
To: claudiu.manoil, vladimir.oltean, xiaoning.wang, andrew+netdev,
davem, edumazet, kuba, pabeni
Cc: christophe.leroy, netdev, linux-kernel, imx, linuxppc-dev,
linux-arm-kernel
Since the offset of the RSS key registers of i.MX95 ENETC is different
from that of LS1028A, so add enetc_get_rss_key_base() to get the base
offset for the different chips, so that enetc_set_rss_key() can be
reused for this trivial thing.
Signed-off-by: Wei Fang <wei.fang@nxp.com>
---
drivers/net/ethernet/freescale/enetc/enetc.h | 2 +-
.../net/ethernet/freescale/enetc/enetc4_pf.c | 20 +------------------
.../ethernet/freescale/enetc/enetc_ethtool.c | 19 +++++++++++++-----
.../net/ethernet/freescale/enetc/enetc_pf.c | 4 +---
.../freescale/enetc/enetc_pf_common.c | 10 ++++++++++
.../freescale/enetc/enetc_pf_common.h | 1 +
6 files changed, 28 insertions(+), 28 deletions(-)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h
index 786042029b1e..e49c1626e7e5 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -537,7 +537,7 @@ int enetc_set_mac_flt_entry(struct enetc_si *si, int index,
int enetc_clear_mac_flt_entry(struct enetc_si *si, int index);
int enetc_set_fs_entry(struct enetc_si *si, struct enetc_cmd_rfse *rfse,
int index);
-void enetc_set_rss_key(struct enetc_hw *hw, const u8 *bytes);
+void enetc_set_rss_key(struct enetc_si *si, const u8 *bytes);
int enetc_get_rss_table(struct enetc_si *si, u32 *table, int count);
int enetc_set_rss_table(struct enetc_si *si, const u32 *table, int count);
int enetc_send_cmd(struct enetc_si *si, struct enetc_cbd *cbd);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
index bbe16c140875..b72a365625d2 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -413,24 +413,6 @@ static void enetc4_set_trx_frame_size(struct enetc_pf *pf)
enetc4_pf_reset_tc_msdu(&si->hw);
}
-static void enetc4_set_rss_key(struct enetc_hw *hw, const u8 *bytes)
-{
- int i;
-
- for (i = 0; i < ENETC_RSSHASH_KEY_SIZE / 4; i++)
- enetc_port_wr(hw, ENETC4_PRSSKR(i), ((u32 *)bytes)[i]);
-}
-
-static void enetc4_set_default_rss_key(struct enetc_pf *pf)
-{
- u8 hash_key[ENETC_RSSHASH_KEY_SIZE] = {0};
- struct enetc_hw *hw = &pf->si->hw;
-
- /* set up hash key */
- get_random_bytes(hash_key, ENETC_RSSHASH_KEY_SIZE);
- enetc4_set_rss_key(hw, hash_key);
-}
-
static void enetc4_enable_trx(struct enetc_pf *pf)
{
struct enetc_hw *hw = &pf->si->hw;
@@ -443,7 +425,7 @@ static void enetc4_configure_port(struct enetc_pf *pf)
{
enetc4_configure_port_si(pf);
enetc4_set_trx_frame_size(pf);
- enetc4_set_default_rss_key(pf);
+ enetc_set_default_rss_key(pf);
enetc4_enable_trx(pf);
}
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
index d14182401d81..1a8fae3c406b 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
@@ -677,6 +677,14 @@ static u32 enetc_get_rxfh_indir_size(struct net_device *ndev)
return priv->si->num_rss;
}
+static int enetc_get_rss_key_base(struct enetc_si *si)
+{
+ if (is_enetc_rev1(si))
+ return ENETC_PRSSK(0);
+
+ return ENETC4_PRSSKR(0);
+}
+
static int enetc_get_rxfh(struct net_device *ndev,
struct ethtool_rxfh_param *rxfh)
{
@@ -701,12 +709,14 @@ static int enetc_get_rxfh(struct net_device *ndev,
return err;
}
-void enetc_set_rss_key(struct enetc_hw *hw, const u8 *bytes)
+void enetc_set_rss_key(struct enetc_si *si, const u8 *bytes)
{
+ int base = enetc_get_rss_key_base(si);
+ struct enetc_hw *hw = &si->hw;
int i;
for (i = 0; i < ENETC_RSSHASH_KEY_SIZE / 4; i++)
- enetc_port_wr(hw, ENETC_PRSSK(i), ((u32 *)bytes)[i]);
+ enetc_port_wr(hw, base + i * 4, ((u32 *)bytes)[i]);
}
EXPORT_SYMBOL_GPL(enetc_set_rss_key);
@@ -716,12 +726,11 @@ static int enetc_set_rxfh(struct net_device *ndev,
{
struct enetc_ndev_priv *priv = netdev_priv(ndev);
struct enetc_si *si = priv->si;
- struct enetc_hw *hw = &si->hw;
int err = 0;
/* set hash key, if PF */
- if (rxfh->key && hw->port)
- enetc_set_rss_key(hw, rxfh->key);
+ if (rxfh->key && enetc_si_is_pf(si))
+ enetc_set_rss_key(si, rxfh->key);
/* set RSS table */
if (rxfh->indir)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index 8dabb80ec04c..8f2616fd83d2 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -515,7 +515,6 @@ static void enetc_mac_enable(struct enetc_si *si, bool en)
static void enetc_configure_port(struct enetc_pf *pf)
{
- u8 hash_key[ENETC_RSSHASH_KEY_SIZE];
struct enetc_hw *hw = &pf->si->hw;
enetc_configure_port_mac(pf->si);
@@ -523,8 +522,7 @@ static void enetc_configure_port(struct enetc_pf *pf)
enetc_port_si_configure(pf->si);
/* set up hash key */
- get_random_bytes(hash_key, ENETC_RSSHASH_KEY_SIZE);
- enetc_set_rss_key(hw, hash_key);
+ enetc_set_default_rss_key(pf);
/* split up RFS entries */
enetc_port_assign_rfs_entries(pf->si);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
index 3fd9b0727875..0a95f2ac781a 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
@@ -341,5 +341,15 @@ void enetc_phylink_destroy(struct enetc_ndev_priv *priv)
}
EXPORT_SYMBOL_GPL(enetc_phylink_destroy);
+void enetc_set_default_rss_key(struct enetc_pf *pf)
+{
+ u8 hash_key[ENETC_RSSHASH_KEY_SIZE] = {0};
+
+ /* set up hash key */
+ get_random_bytes(hash_key, ENETC_RSSHASH_KEY_SIZE);
+ enetc_set_rss_key(pf->si, hash_key);
+}
+EXPORT_SYMBOL_GPL(enetc_set_default_rss_key);
+
MODULE_DESCRIPTION("NXP ENETC PF common functionality driver");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.h b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.h
index 48f55ee743ad..e07cf3c35001 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.h
@@ -12,6 +12,7 @@ void enetc_mdiobus_destroy(struct enetc_pf *pf);
int enetc_phylink_create(struct enetc_ndev_priv *priv, struct device_node *node,
const struct phylink_mac_ops *ops);
void enetc_phylink_destroy(struct enetc_ndev_priv *priv);
+void enetc_set_default_rss_key(struct enetc_pf *pf);
static inline u16 enetc_get_ip_revision(struct enetc_hw *hw)
{
--
2.34.1
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH v5 net-next 08/14] net: enetc: add RSS support for i.MX95 ENETC PF
2025-04-11 9:57 [PATCH v5 net-next 00/14] Add more features for ENETC v4 - round 2 Wei Fang
` (6 preceding siblings ...)
2025-04-11 9:57 ` [PATCH v5 net-next 07/14] net: enetc: make enetc_set_rss_key() reusable Wei Fang
@ 2025-04-11 9:57 ` Wei Fang
2025-04-11 9:57 ` [PATCH v5 net-next 09/14] net: enetc: change enetc_set_rss() to void type Wei Fang
` (5 subsequent siblings)
13 siblings, 0 replies; 29+ messages in thread
From: Wei Fang @ 2025-04-11 9:57 UTC (permalink / raw)
To: claudiu.manoil, vladimir.oltean, xiaoning.wang, andrew+netdev,
davem, edumazet, kuba, pabeni
Cc: christophe.leroy, netdev, linux-kernel, imx, linuxppc-dev,
linux-arm-kernel
Compared with LS1028A, there are two main differences: first, i.MX95
ENETC uses NTMP 2.0 to manage the RSS table, and second, the offset
of the RSS Key registers is different. Some modifications have been
made in the previous patches based on these differences to ensure that
the relevant interfaces are compatible with i.MX95. So it's time to
add RSS support to i.MX95 ENETC PF.
Signed-off-by: Wei Fang <wei.fang@nxp.com>
---
1. Add comments for enetc4_get_rxnfc()
2. Modify enetc4_set_rss_table() and enetc4_get_rss_table()
---
drivers/net/ethernet/freescale/enetc/enetc.c | 5 +-
drivers/net/ethernet/freescale/enetc/enetc.h | 2 +
.../net/ethernet/freescale/enetc/enetc4_pf.c | 15 ++++++
.../net/ethernet/freescale/enetc/enetc_cbdr.c | 12 +++++
.../ethernet/freescale/enetc/enetc_ethtool.c | 47 ++++++++++++++++---
.../freescale/enetc/enetc_pf_common.c | 6 +--
6 files changed, 74 insertions(+), 13 deletions(-)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c
index 2a8fa455e96b..5b5e65ac8fab 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -2436,10 +2436,7 @@ int enetc_configure_si(struct enetc_ndev_priv *priv)
if (si->hw_features & ENETC_SI_F_LSO)
enetc_set_lso_flags_mask(hw);
- /* TODO: RSS support for i.MX95 will be supported later, and the
- * is_enetc_rev1() condition will be removed
- */
- if (si->num_rss && is_enetc_rev1(si)) {
+ if (si->num_rss) {
err = enetc_setup_default_rss_table(si, priv->num_rx_rings);
if (err)
return err;
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h
index e49c1626e7e5..7b24f1a5969a 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -541,6 +541,8 @@ void enetc_set_rss_key(struct enetc_si *si, const u8 *bytes);
int enetc_get_rss_table(struct enetc_si *si, u32 *table, int count);
int enetc_set_rss_table(struct enetc_si *si, const u32 *table, int count);
int enetc_send_cmd(struct enetc_si *si, struct enetc_cbd *cbd);
+int enetc4_get_rss_table(struct enetc_si *si, u32 *table, int count);
+int enetc4_set_rss_table(struct enetc_si *si, const u32 *table, int count);
static inline void *enetc_cbd_alloc_data_mem(struct enetc_si *si,
struct enetc_cbd *cbd,
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
index b72a365625d2..e164e1a3f44b 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -514,6 +514,14 @@ static void enetc4_pf_set_rx_mode(struct net_device *ndev)
queue_work(si->workqueue, &si->rx_mode_task);
}
+static int enetc4_pf_set_features(struct net_device *ndev,
+ netdev_features_t features)
+{
+ enetc_set_features(ndev, features);
+
+ return 0;
+}
+
static const struct net_device_ops enetc4_ndev_ops = {
.ndo_open = enetc_open,
.ndo_stop = enetc_close,
@@ -521,6 +529,7 @@ static const struct net_device_ops enetc4_ndev_ops = {
.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_features = enetc4_pf_set_features,
};
static struct phylink_pcs *
@@ -926,6 +935,11 @@ static void enetc4_pf_netdev_destroy(struct enetc_si *si)
free_netdev(ndev);
}
+static const struct enetc_si_ops enetc4_psi_ops = {
+ .get_rss_table = enetc4_get_rss_table,
+ .set_rss_table = enetc4_set_rss_table,
+};
+
static int enetc4_psi_wq_task_init(struct enetc_si *si)
{
char wq_name[24];
@@ -963,6 +977,7 @@ static int enetc4_pf_probe(struct pci_dev *pdev,
"Couldn't map PF only space\n");
si->revision = enetc_get_ip_revision(&si->hw);
+ si->ops = &enetc4_psi_ops;
err = enetc_get_driver_data(si);
if (err)
return dev_err_probe(dev, err,
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c b/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
index ecb571e5ea50..fcfff908f7c1 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
@@ -295,3 +295,15 @@ int enetc_set_rss_table(struct enetc_si *si, const u32 *table, int count)
return enetc_cmd_rss_table(si, (u32 *)table, count, false);
}
EXPORT_SYMBOL_GPL(enetc_set_rss_table);
+
+int enetc4_get_rss_table(struct enetc_si *si, u32 *table, int count)
+{
+ return ntmp_rsst_query_entry(&si->ntmp_user, table, count);
+}
+EXPORT_SYMBOL_GPL(enetc4_get_rss_table);
+
+int enetc4_set_rss_table(struct enetc_si *si, const u32 *table, int count)
+{
+ return ntmp_rsst_update_entry(&si->ntmp_user, table, count);
+}
+EXPORT_SYMBOL_GPL(enetc4_set_rss_table);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
index 1a8fae3c406b..e22124363184 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
@@ -625,6 +625,29 @@ static int enetc_get_rxnfc(struct net_device *ndev, struct ethtool_rxnfc *rxnfc,
return 0;
}
+/* i.MX95 ENETC does not support RFS table, but we can use ingress port
+ * filter table to implement Wake-on-LAN filter or drop the matched flow,
+ * so the implementation will be different from enetc_get_rxnfc() and
+ * enetc_set_rxnfc(). Therefore, add enetc4_get_rxnfc() for ENETC v4 PF.
+ */
+static int enetc4_get_rxnfc(struct net_device *ndev, struct ethtool_rxnfc *rxnfc,
+ u32 *rule_locs)
+{
+ struct enetc_ndev_priv *priv = netdev_priv(ndev);
+
+ switch (rxnfc->cmd) {
+ case ETHTOOL_GRXRINGS:
+ rxnfc->data = priv->num_rx_rings;
+ break;
+ case ETHTOOL_GRXFH:
+ return enetc_get_rsshash(rxnfc);
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
static int enetc_set_rxnfc(struct net_device *ndev, struct ethtool_rxnfc *rxnfc)
{
struct enetc_ndev_priv *priv = netdev_priv(ndev);
@@ -685,22 +708,29 @@ static int enetc_get_rss_key_base(struct enetc_si *si)
return ENETC4_PRSSKR(0);
}
+static void enetc_get_rss_key(struct enetc_si *si, const u8 *key)
+{
+ int base = enetc_get_rss_key_base(si);
+ struct enetc_hw *hw = &si->hw;
+ int i;
+
+ for (i = 0; i < ENETC_RSSHASH_KEY_SIZE / 4; i++)
+ ((u32 *)key)[i] = enetc_port_rd(hw, base + i * 4);
+}
+
static int enetc_get_rxfh(struct net_device *ndev,
struct ethtool_rxfh_param *rxfh)
{
struct enetc_ndev_priv *priv = netdev_priv(ndev);
struct enetc_si *si = priv->si;
- struct enetc_hw *hw = &si->hw;
- int err = 0, i;
+ int err = 0;
/* return hash function */
rxfh->hfunc = ETH_RSS_HASH_TOP;
/* return hash key */
- if (rxfh->key && hw->port)
- for (i = 0; i < ENETC_RSSHASH_KEY_SIZE / 4; i++)
- ((u32 *)rxfh->key)[i] = enetc_port_rd(hw,
- ENETC_PRSSK(i));
+ if (rxfh->key && enetc_si_is_pf(si))
+ enetc_get_rss_key(si, rxfh->key);
/* return RSS table */
if (rxfh->indir)
@@ -1249,6 +1279,11 @@ const struct ethtool_ops enetc4_pf_ethtool_ops = {
.set_wol = enetc_set_wol,
.get_pauseparam = enetc_get_pauseparam,
.set_pauseparam = enetc_set_pauseparam,
+ .get_rxnfc = enetc4_get_rxnfc,
+ .get_rxfh_key_size = enetc_get_rxfh_key_size,
+ .get_rxfh_indir_size = enetc_get_rxfh_indir_size,
+ .get_rxfh = enetc_get_rxfh,
+ .set_rxfh = enetc_set_rxfh,
};
void enetc_set_ethtool_ops(struct net_device *ndev)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
index 0a95f2ac781a..a302477c4de4 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
@@ -128,15 +128,15 @@ void enetc_pf_netdev_setup(struct enetc_si *si, struct net_device *ndev,
if (si->hw_features & ENETC_SI_F_LSO)
priv->active_offloads |= ENETC_F_LSO;
+ if (si->num_rss)
+ ndev->hw_features |= NETIF_F_RXHASH;
+
/* TODO: currently, i.MX95 ENETC driver does not support advanced features */
if (!is_enetc_rev1(si)) {
ndev->hw_features &= ~(NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_LOOPBACK);
goto end;
}
- if (si->num_rss)
- ndev->hw_features |= NETIF_F_RXHASH;
-
ndev->xdp_features = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT |
NETDEV_XDP_ACT_NDO_XMIT | NETDEV_XDP_ACT_RX_SG |
NETDEV_XDP_ACT_NDO_XMIT_SG;
--
2.34.1
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH v5 net-next 09/14] net: enetc: change enetc_set_rss() to void type
2025-04-11 9:57 [PATCH v5 net-next 00/14] Add more features for ENETC v4 - round 2 Wei Fang
` (7 preceding siblings ...)
2025-04-11 9:57 ` [PATCH v5 net-next 08/14] net: enetc: add RSS support for i.MX95 ENETC PF Wei Fang
@ 2025-04-11 9:57 ` Wei Fang
2025-04-11 9:57 ` [PATCH v5 net-next 10/14] net: enetc: enable RSS feature by default Wei Fang
` (4 subsequent siblings)
13 siblings, 0 replies; 29+ messages in thread
From: Wei Fang @ 2025-04-11 9:57 UTC (permalink / raw)
To: claudiu.manoil, vladimir.oltean, xiaoning.wang, andrew+netdev,
davem, edumazet, kuba, pabeni
Cc: christophe.leroy, netdev, linux-kernel, imx, linuxppc-dev,
linux-arm-kernel
Actually enetc_set_rss() does not need a return value, so change its
type to void.
Signed-off-by: Wei Fang <wei.fang@nxp.com>
Acked-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
v5 changes:
New patch, suggested by Vladimir
---
drivers/net/ethernet/freescale/enetc/enetc.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c
index 5b5e65ac8fab..a389d5089734 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -3232,7 +3232,7 @@ struct net_device_stats *enetc_get_stats(struct net_device *ndev)
}
EXPORT_SYMBOL_GPL(enetc_get_stats);
-static int enetc_set_rss(struct net_device *ndev, int en)
+static void enetc_set_rss(struct net_device *ndev, int en)
{
struct enetc_ndev_priv *priv = netdev_priv(ndev);
struct enetc_hw *hw = &priv->si->hw;
@@ -3244,8 +3244,6 @@ static int enetc_set_rss(struct net_device *ndev, int en)
reg &= ~ENETC_SIMR_RSSE;
reg |= (en) ? ENETC_SIMR_RSSE : 0;
enetc_wr(hw, ENETC_SIMR, reg);
-
- return 0;
}
static void enetc_enable_rxvlan(struct net_device *ndev, bool en)
--
2.34.1
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH v5 net-next 10/14] net: enetc: enable RSS feature by default
2025-04-11 9:57 [PATCH v5 net-next 00/14] Add more features for ENETC v4 - round 2 Wei Fang
` (8 preceding siblings ...)
2025-04-11 9:57 ` [PATCH v5 net-next 09/14] net: enetc: change enetc_set_rss() to void type Wei Fang
@ 2025-04-11 9:57 ` Wei Fang
2025-04-11 9:57 ` [PATCH v5 net-next 11/14] net: enetc: extract enetc_refresh_vlan_ht_filter() Wei Fang
` (3 subsequent siblings)
13 siblings, 0 replies; 29+ messages in thread
From: Wei Fang @ 2025-04-11 9:57 UTC (permalink / raw)
To: claudiu.manoil, vladimir.oltean, xiaoning.wang, andrew+netdev,
davem, edumazet, kuba, pabeni
Cc: christophe.leroy, netdev, linux-kernel, imx, linuxppc-dev,
linux-arm-kernel
Receive side scaling (RSS) is a network driver technology that enables
the efficient distribution of network receive processing across multiple
CPUs in multiprocessor systems. Therefore, it is better to enable RSS by
default so that the CPU load can be balanced and network performance can
be improved when then network is enabled.
Signed-off-by: Wei Fang <wei.fang@nxp.com>
---
v5 changes:
Just rebase it based on patch 9.
---
drivers/net/ethernet/freescale/enetc/enetc.c | 31 ++++++++++---------
.../freescale/enetc/enetc_pf_common.c | 4 ++-
.../net/ethernet/freescale/enetc/enetc_vf.c | 4 ++-
3 files changed, 23 insertions(+), 16 deletions(-)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c
index a389d5089734..d686baeb1aa8 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -2420,6 +2420,20 @@ static void enetc_set_lso_flags_mask(struct enetc_hw *hw)
enetc_wr(hw, ENETC4_SILSOSFMR1, 0);
}
+static void enetc_set_rss(struct net_device *ndev, int en)
+{
+ struct enetc_ndev_priv *priv = netdev_priv(ndev);
+ struct enetc_hw *hw = &priv->si->hw;
+ u32 reg;
+
+ enetc_wr(hw, ENETC_SIRBGCR, priv->num_rx_rings);
+
+ reg = enetc_rd(hw, ENETC_SIMR);
+ reg &= ~ENETC_SIMR_RSSE;
+ reg |= (en) ? ENETC_SIMR_RSSE : 0;
+ enetc_wr(hw, ENETC_SIMR, reg);
+}
+
int enetc_configure_si(struct enetc_ndev_priv *priv)
{
struct enetc_si *si = priv->si;
@@ -2440,6 +2454,9 @@ int enetc_configure_si(struct enetc_ndev_priv *priv)
err = enetc_setup_default_rss_table(si, priv->num_rx_rings);
if (err)
return err;
+
+ if (priv->ndev->features & NETIF_F_RXHASH)
+ enetc_set_rss(priv->ndev, true);
}
return 0;
@@ -3232,20 +3249,6 @@ struct net_device_stats *enetc_get_stats(struct net_device *ndev)
}
EXPORT_SYMBOL_GPL(enetc_get_stats);
-static void enetc_set_rss(struct net_device *ndev, int en)
-{
- struct enetc_ndev_priv *priv = netdev_priv(ndev);
- struct enetc_hw *hw = &priv->si->hw;
- u32 reg;
-
- enetc_wr(hw, ENETC_SIRBGCR, priv->num_rx_rings);
-
- reg = enetc_rd(hw, ENETC_SIMR);
- reg &= ~ENETC_SIMR_RSSE;
- reg |= (en) ? ENETC_SIMR_RSSE : 0;
- enetc_wr(hw, ENETC_SIMR, reg);
-}
-
static void enetc_enable_rxvlan(struct net_device *ndev, bool en)
{
struct enetc_ndev_priv *priv = netdev_priv(ndev);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
index a302477c4de4..a751862a70b1 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
@@ -128,8 +128,10 @@ void enetc_pf_netdev_setup(struct enetc_si *si, struct net_device *ndev,
if (si->hw_features & ENETC_SI_F_LSO)
priv->active_offloads |= ENETC_F_LSO;
- if (si->num_rss)
+ if (si->num_rss) {
ndev->hw_features |= NETIF_F_RXHASH;
+ ndev->features |= NETIF_F_RXHASH;
+ }
/* TODO: currently, i.MX95 ENETC driver does not support advanced features */
if (!is_enetc_rev1(si)) {
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_vf.c b/drivers/net/ethernet/freescale/enetc/enetc_vf.c
index 4fafe4e18a37..f6aed0a1ad1e 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_vf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_vf.c
@@ -155,8 +155,10 @@ static void enetc_vf_netdev_setup(struct enetc_si *si, struct net_device *ndev,
ndev->vlan_features = NETIF_F_SG | NETIF_F_HW_CSUM |
NETIF_F_TSO | NETIF_F_TSO6;
- if (si->num_rss)
+ if (si->num_rss) {
ndev->hw_features |= NETIF_F_RXHASH;
+ ndev->features |= NETIF_F_RXHASH;
+ }
/* pick up primary MAC address from SI */
enetc_load_primary_mac_addr(&si->hw, ndev);
--
2.34.1
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH v5 net-next 11/14] net: enetc: extract enetc_refresh_vlan_ht_filter()
2025-04-11 9:57 [PATCH v5 net-next 00/14] Add more features for ENETC v4 - round 2 Wei Fang
` (9 preceding siblings ...)
2025-04-11 9:57 ` [PATCH v5 net-next 10/14] net: enetc: enable RSS feature by default Wei Fang
@ 2025-04-11 9:57 ` Wei Fang
2025-04-11 9:57 ` [PATCH v5 net-next 12/14] net: enetc: move generic VLAN hash filter functions to enetc_pf_common.c Wei Fang
` (2 subsequent siblings)
13 siblings, 0 replies; 29+ messages in thread
From: Wei Fang @ 2025-04-11 9:57 UTC (permalink / raw)
To: claudiu.manoil, vladimir.oltean, xiaoning.wang, andrew+netdev,
davem, edumazet, kuba, pabeni
Cc: christophe.leroy, netdev, linux-kernel, imx, linuxppc-dev,
linux-arm-kernel
Extract the common function enetc_refresh_vlan_ht_filter() from
enetc_sync_vlan_ht_filter() so that it can be reused by the ENETC
v4 PF and VF drivers in the future.
Signed-off-by: Wei Fang <wei.fang@nxp.com>
---
v5 changes
New patch
---
.../net/ethernet/freescale/enetc/enetc_pf.c | 20 ++++++++-----------
1 file changed, 8 insertions(+), 12 deletions(-)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index 8f2616fd83d2..ae2dbd159ab4 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -234,21 +234,16 @@ static int enetc_vid_hash_idx(unsigned int vid)
return res;
}
-static void enetc_sync_vlan_ht_filter(struct enetc_pf *pf, bool rehash)
+static void enetc_refresh_vlan_ht_filter(struct enetc_pf *pf)
{
int i;
- if (rehash) {
- bitmap_zero(pf->vlan_ht_filter, ENETC_VLAN_HT_SIZE);
+ bitmap_zero(pf->vlan_ht_filter, ENETC_VLAN_HT_SIZE);
+ for_each_set_bit(i, pf->active_vlans, VLAN_N_VID) {
+ int hidx = enetc_vid_hash_idx(i);
- for_each_set_bit(i, pf->active_vlans, VLAN_N_VID) {
- int hidx = enetc_vid_hash_idx(i);
-
- __set_bit(hidx, pf->vlan_ht_filter);
- }
+ __set_bit(hidx, pf->vlan_ht_filter);
}
-
- enetc_set_vlan_ht_filter(&pf->si->hw, 0, *pf->vlan_ht_filter);
}
static int enetc_vlan_rx_add_vid(struct net_device *ndev, __be16 prot, u16 vid)
@@ -261,7 +256,7 @@ static int enetc_vlan_rx_add_vid(struct net_device *ndev, __be16 prot, u16 vid)
idx = enetc_vid_hash_idx(vid);
if (!__test_and_set_bit(idx, pf->vlan_ht_filter))
- enetc_sync_vlan_ht_filter(pf, false);
+ enetc_set_vlan_ht_filter(&pf->si->hw, 0, *pf->vlan_ht_filter);
return 0;
}
@@ -272,7 +267,8 @@ static int enetc_vlan_rx_del_vid(struct net_device *ndev, __be16 prot, u16 vid)
struct enetc_pf *pf = enetc_si_priv(priv->si);
__clear_bit(vid, pf->active_vlans);
- enetc_sync_vlan_ht_filter(pf, true);
+ enetc_refresh_vlan_ht_filter(pf);
+ enetc_set_vlan_ht_filter(&pf->si->hw, 0, *pf->vlan_ht_filter);
return 0;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH v5 net-next 12/14] net: enetc: move generic VLAN hash filter functions to enetc_pf_common.c
2025-04-11 9:57 [PATCH v5 net-next 00/14] Add more features for ENETC v4 - round 2 Wei Fang
` (10 preceding siblings ...)
2025-04-11 9:57 ` [PATCH v5 net-next 11/14] net: enetc: extract enetc_refresh_vlan_ht_filter() Wei Fang
@ 2025-04-11 9:57 ` Wei Fang
2025-04-11 9:57 ` [PATCH v5 net-next 13/14] net: enetc: add VLAN filtering support for i.MX95 ENETC PF Wei Fang
2025-04-11 9:57 ` [PATCH v5 net-next 14/14] net: enetc: add loopback " Wei Fang
13 siblings, 0 replies; 29+ messages in thread
From: Wei Fang @ 2025-04-11 9:57 UTC (permalink / raw)
To: claudiu.manoil, vladimir.oltean, xiaoning.wang, andrew+netdev,
davem, edumazet, kuba, pabeni
Cc: christophe.leroy, netdev, linux-kernel, imx, linuxppc-dev,
linux-arm-kernel
The VLAN hash filters of ENETC v1 and v4 are basically the same, the only
difference is that the offset of the VLAN hash filter registers has been
changed in ENETC v4. So some functions like enetc_vlan_rx_add_vid() and
enetc_vlan_rx_del_vid() only need to be slightly modified to be reused
by ENETC v4. Currently, we just move these functions from enetc_pf.c to
enetc_pf_common.c. Appropriate modifications will be made for ENETC4 in
a subsequent patch.
Signed-off-by: Wei Fang <wei.fang@nxp.com>
---
v5 changes
Remove set_si_vlan_hash_filter() hook
---
.../net/ethernet/freescale/enetc/enetc_pf.c | 57 ------------------
.../freescale/enetc/enetc_pf_common.c | 60 +++++++++++++++++++
.../freescale/enetc/enetc_pf_common.h | 2 +
3 files changed, 62 insertions(+), 57 deletions(-)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index ae2dbd159ab4..6560bdbff287 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -216,63 +216,6 @@ static void enetc_pf_set_rx_mode(struct net_device *ndev)
enetc_port_wr(hw, ENETC_PSIPMR, psipmr);
}
-static void enetc_set_vlan_ht_filter(struct enetc_hw *hw, int si_idx,
- unsigned long hash)
-{
- enetc_port_wr(hw, ENETC_PSIVHFR0(si_idx), lower_32_bits(hash));
- enetc_port_wr(hw, ENETC_PSIVHFR1(si_idx), upper_32_bits(hash));
-}
-
-static int enetc_vid_hash_idx(unsigned int vid)
-{
- int res = 0;
- int i;
-
- for (i = 0; i < 6; i++)
- res |= (hweight8(vid & (BIT(i) | BIT(i + 6))) & 0x1) << i;
-
- return res;
-}
-
-static void enetc_refresh_vlan_ht_filter(struct enetc_pf *pf)
-{
- int i;
-
- bitmap_zero(pf->vlan_ht_filter, ENETC_VLAN_HT_SIZE);
- for_each_set_bit(i, pf->active_vlans, VLAN_N_VID) {
- int hidx = enetc_vid_hash_idx(i);
-
- __set_bit(hidx, pf->vlan_ht_filter);
- }
-}
-
-static int enetc_vlan_rx_add_vid(struct net_device *ndev, __be16 prot, u16 vid)
-{
- struct enetc_ndev_priv *priv = netdev_priv(ndev);
- struct enetc_pf *pf = enetc_si_priv(priv->si);
- int idx;
-
- __set_bit(vid, pf->active_vlans);
-
- idx = enetc_vid_hash_idx(vid);
- if (!__test_and_set_bit(idx, pf->vlan_ht_filter))
- enetc_set_vlan_ht_filter(&pf->si->hw, 0, *pf->vlan_ht_filter);
-
- return 0;
-}
-
-static int enetc_vlan_rx_del_vid(struct net_device *ndev, __be16 prot, u16 vid)
-{
- struct enetc_ndev_priv *priv = netdev_priv(ndev);
- struct enetc_pf *pf = enetc_si_priv(priv->si);
-
- __clear_bit(vid, pf->active_vlans);
- enetc_refresh_vlan_ht_filter(pf);
- enetc_set_vlan_ht_filter(&pf->si->hw, 0, *pf->vlan_ht_filter);
-
- return 0;
-}
-
static void enetc_set_loopback(struct net_device *ndev, bool en)
{
struct enetc_ndev_priv *priv = netdev_priv(ndev);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
index a751862a70b1..ed8afd174c9e 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
@@ -353,5 +353,65 @@ void enetc_set_default_rss_key(struct enetc_pf *pf)
}
EXPORT_SYMBOL_GPL(enetc_set_default_rss_key);
+static int enetc_vid_hash_idx(unsigned int vid)
+{
+ int res = 0;
+ int i;
+
+ for (i = 0; i < 6; i++)
+ res |= (hweight8(vid & (BIT(i) | BIT(i + 6))) & 0x1) << i;
+
+ return res;
+}
+
+static void enetc_refresh_vlan_ht_filter(struct enetc_pf *pf)
+{
+ int i;
+
+ bitmap_zero(pf->vlan_ht_filter, ENETC_VLAN_HT_SIZE);
+ for_each_set_bit(i, pf->active_vlans, VLAN_N_VID) {
+ int hidx = enetc_vid_hash_idx(i);
+
+ __set_bit(hidx, pf->vlan_ht_filter);
+ }
+}
+
+static void enetc_set_vlan_ht_filter(struct enetc_hw *hw, int si_idx,
+ unsigned long hash)
+{
+ enetc_port_wr(hw, ENETC_PSIVHFR0(si_idx), lower_32_bits(hash));
+ enetc_port_wr(hw, ENETC_PSIVHFR1(si_idx), upper_32_bits(hash));
+}
+
+int enetc_vlan_rx_add_vid(struct net_device *ndev, __be16 prot, u16 vid)
+{
+ struct enetc_ndev_priv *priv = netdev_priv(ndev);
+ struct enetc_pf *pf = enetc_si_priv(priv->si);
+ int idx;
+
+ __set_bit(vid, pf->active_vlans);
+
+ idx = enetc_vid_hash_idx(vid);
+ if (!__test_and_set_bit(idx, pf->vlan_ht_filter))
+ enetc_set_vlan_ht_filter(&pf->si->hw, 0, *pf->vlan_ht_filter);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(enetc_vlan_rx_add_vid);
+
+int enetc_vlan_rx_del_vid(struct net_device *ndev, __be16 prot, u16 vid)
+{
+ struct enetc_ndev_priv *priv = netdev_priv(ndev);
+ struct enetc_pf *pf = enetc_si_priv(priv->si);
+
+ if (__test_and_clear_bit(vid, pf->active_vlans)) {
+ enetc_refresh_vlan_ht_filter(pf);
+ enetc_set_vlan_ht_filter(&pf->si->hw, 0, *pf->vlan_ht_filter);
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(enetc_vlan_rx_del_vid);
+
MODULE_DESCRIPTION("NXP ENETC PF common functionality driver");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.h b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.h
index e07cf3c35001..96d4840a3107 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.h
@@ -13,6 +13,8 @@ int enetc_phylink_create(struct enetc_ndev_priv *priv, struct device_node *node,
const struct phylink_mac_ops *ops);
void enetc_phylink_destroy(struct enetc_ndev_priv *priv);
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);
static inline u16 enetc_get_ip_revision(struct enetc_hw *hw)
{
--
2.34.1
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH v5 net-next 13/14] net: enetc: add VLAN filtering support for i.MX95 ENETC PF
2025-04-11 9:57 [PATCH v5 net-next 00/14] Add more features for ENETC v4 - round 2 Wei Fang
` (11 preceding siblings ...)
2025-04-11 9:57 ` [PATCH v5 net-next 12/14] net: enetc: move generic VLAN hash filter functions to enetc_pf_common.c Wei Fang
@ 2025-04-11 9:57 ` Wei Fang
2025-04-11 9:57 ` [PATCH v5 net-next 14/14] net: enetc: add loopback " Wei Fang
13 siblings, 0 replies; 29+ messages in thread
From: Wei Fang @ 2025-04-11 9:57 UTC (permalink / raw)
To: claudiu.manoil, vladimir.oltean, xiaoning.wang, andrew+netdev,
davem, edumazet, kuba, pabeni
Cc: christophe.leroy, netdev, linux-kernel, imx, linuxppc-dev,
linux-arm-kernel
Since the offsets of the VLAN hash filter registers of ENETC v4 are
different from ENETC v1. Therefore, enetc_set_si_vlan_ht_filter() is
added to set the correct VLAN hash filter based on the SI ID and ENETC
revision, so that ENETC v4 PF driver can reuse enetc_vlan_rx_add_vid()
and enetc_vlan_rx_del_vid(). In addition, the VLAN promiscuous mode will
be enabled if VLAN filtering is disabled, which means that PF qualifies
for reception of all VLAN tags.
Signed-off-by: Wei Fang <wei.fang@nxp.com>
---
v5 changes
1. Remove set_si_vlan_hash_filter() hook
2. Refator enetc_set_vlan_ht_filter() and rename it to
enetc_set_si_vlan_ht_filter()
---
.../net/ethernet/freescale/enetc/enetc4_hw.h | 4 +++
.../net/ethernet/freescale/enetc/enetc4_pf.c | 12 +++++++++
.../freescale/enetc/enetc_pf_common.c | 25 +++++++++++++------
3 files changed, 34 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_hw.h b/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
index 826359004850..aa25b445d301 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
@@ -107,6 +107,10 @@
#define ENETC4_PSIMMHFR0(a) ((a) * 0x80 + 0x2058)
#define ENETC4_PSIMMHFR1(a) ((a) * 0x80 + 0x205c)
+/* Port station interface a VLAN hash filter register 0/1 */
+#define ENETC4_PSIVHFR0(a) ((a) * 0x80 + 0x2060)
+#define ENETC4_PSIVHFR1(a) ((a) * 0x80 + 0x2064)
+
#define ENETC4_PMCAPR 0x4004
#define PMCAPR_HD BIT(8)
#define PMCAPR_FP GENMASK(10, 9)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
index e164e1a3f44b..421378212a73 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -517,6 +517,16 @@ static void enetc4_pf_set_rx_mode(struct net_device *ndev)
static int enetc4_pf_set_features(struct net_device *ndev,
netdev_features_t features)
{
+ 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_features(ndev, features);
return 0;
@@ -530,6 +540,8 @@ static const struct net_device_ops enetc4_ndev_ops = {
.ndo_set_mac_address = enetc_pf_set_mac_addr,
.ndo_set_rx_mode = 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,
};
static struct phylink_pcs *
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
index ed8afd174c9e..8c563e552021 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
@@ -135,7 +135,7 @@ void enetc_pf_netdev_setup(struct enetc_si *si, struct net_device *ndev,
/* TODO: currently, i.MX95 ENETC driver does not support advanced features */
if (!is_enetc_rev1(si)) {
- ndev->hw_features &= ~(NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_LOOPBACK);
+ ndev->hw_features &= ~NETIF_F_LOOPBACK;
goto end;
}
@@ -376,11 +376,22 @@ static void enetc_refresh_vlan_ht_filter(struct enetc_pf *pf)
}
}
-static void enetc_set_vlan_ht_filter(struct enetc_hw *hw, int si_idx,
- unsigned long hash)
+static void enetc_set_si_vlan_ht_filter(struct enetc_si *si,
+ int si_id, u64 hash)
{
- enetc_port_wr(hw, ENETC_PSIVHFR0(si_idx), lower_32_bits(hash));
- enetc_port_wr(hw, ENETC_PSIVHFR1(si_idx), upper_32_bits(hash));
+ struct enetc_hw *hw = &si->hw;
+ int high_reg_off, low_reg_off;
+
+ if (is_enetc_rev1(si)) {
+ low_reg_off = ENETC_PSIVHFR0(si_id);
+ high_reg_off = ENETC_PSIVHFR1(si_id);
+ } else {
+ low_reg_off = ENETC4_PSIVHFR0(si_id);
+ high_reg_off = ENETC4_PSIVHFR1(si_id);
+ }
+
+ enetc_port_wr(hw, low_reg_off, lower_32_bits(hash));
+ enetc_port_wr(hw, high_reg_off, upper_32_bits(hash));
}
int enetc_vlan_rx_add_vid(struct net_device *ndev, __be16 prot, u16 vid)
@@ -393,7 +404,7 @@ int enetc_vlan_rx_add_vid(struct net_device *ndev, __be16 prot, u16 vid)
idx = enetc_vid_hash_idx(vid);
if (!__test_and_set_bit(idx, pf->vlan_ht_filter))
- enetc_set_vlan_ht_filter(&pf->si->hw, 0, *pf->vlan_ht_filter);
+ enetc_set_si_vlan_ht_filter(pf->si, 0, *pf->vlan_ht_filter);
return 0;
}
@@ -406,7 +417,7 @@ int enetc_vlan_rx_del_vid(struct net_device *ndev, __be16 prot, u16 vid)
if (__test_and_clear_bit(vid, pf->active_vlans)) {
enetc_refresh_vlan_ht_filter(pf);
- enetc_set_vlan_ht_filter(&pf->si->hw, 0, *pf->vlan_ht_filter);
+ enetc_set_si_vlan_ht_filter(pf->si, 0, *pf->vlan_ht_filter);
}
return 0;
--
2.34.1
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH v5 net-next 14/14] net: enetc: add loopback support for i.MX95 ENETC PF
2025-04-11 9:57 [PATCH v5 net-next 00/14] Add more features for ENETC v4 - round 2 Wei Fang
` (12 preceding siblings ...)
2025-04-11 9:57 ` [PATCH v5 net-next 13/14] net: enetc: add VLAN filtering support for i.MX95 ENETC PF Wei Fang
@ 2025-04-11 9:57 ` Wei Fang
13 siblings, 0 replies; 29+ messages in thread
From: Wei Fang @ 2025-04-11 9:57 UTC (permalink / raw)
To: claudiu.manoil, vladimir.oltean, xiaoning.wang, andrew+netdev,
davem, edumazet, kuba, pabeni
Cc: christophe.leroy, netdev, linux-kernel, imx, linuxppc-dev,
linux-arm-kernel
Add internal loopback support for i.MX95 ENETC PF, the default loopback
mode is MAC level loopback, the MAC Tx data is looped back onto the Rx.
The MAC interface runs at a fixed 1:8 ratio of NETC clock in MAC-level
loopback mode, with no dependency on Tx clock.
Signed-off-by: Wei Fang <wei.fang@nxp.com>
---
v5: no changes
---
.../net/ethernet/freescale/enetc/enetc4_pf.c | 18 ++++++++++++++++++
.../ethernet/freescale/enetc/enetc_pf_common.c | 4 +---
2 files changed, 19 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
index 421378212a73..711047f7074b 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -101,6 +101,21 @@ static void enetc4_pf_set_si_mc_hash_filter(struct enetc_hw *hw, int si,
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);
+ struct enetc_si *si = priv->si;
+ u32 val;
+
+ val = enetc_port_mac_rd(si, ENETC4_PM_CMD_CFG(0));
+ val = u32_replace_bits(val, en ? 1 : 0, PM_CMD_CFG_LOOP_EN);
+ /* Default to select MAC level loopback mode if loopback is enabled. */
+ val = u32_replace_bits(val, en ? LPBCK_MODE_MAC_LEVEL : 0,
+ PM_CMD_CFG_LPBK_MODE);
+
+ enetc_port_mac_wr(si, ENETC4_PM_CMD_CFG(0), val);
+}
+
static void enetc4_pf_clear_maft_entries(struct enetc_pf *pf)
{
int i;
@@ -527,6 +542,9 @@ static int enetc4_pf_set_features(struct net_device *ndev,
enetc4_pf_set_si_vlan_promisc(hw, 0, promisc_en);
}
+ if (changed & NETIF_F_LOOPBACK)
+ enetc4_pf_set_loopback(ndev, !!(features & NETIF_F_LOOPBACK));
+
enetc_set_features(ndev, features);
return 0;
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
index 8c563e552021..edf14a95cab7 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
@@ -134,10 +134,8 @@ void enetc_pf_netdev_setup(struct enetc_si *si, struct net_device *ndev,
}
/* TODO: currently, i.MX95 ENETC driver does not support advanced features */
- if (!is_enetc_rev1(si)) {
- ndev->hw_features &= ~NETIF_F_LOOPBACK;
+ if (!is_enetc_rev1(si))
goto end;
- }
ndev->xdp_features = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT |
NETDEV_XDP_ACT_NDO_XMIT | NETDEV_XDP_ACT_RX_SG |
--
2.34.1
^ permalink raw reply related [flat|nested] 29+ messages in thread
* Re: [PATCH v5 net-next 06/14] net: enetc: add set/get_rss_table() hooks to enetc_si_ops
2025-04-11 9:57 ` [PATCH v5 net-next 06/14] net: enetc: add set/get_rss_table() hooks to enetc_si_ops Wei Fang
@ 2025-04-15 13:43 ` Paolo Abeni
2025-04-16 2:31 ` Wei Fang
0 siblings, 1 reply; 29+ messages in thread
From: Paolo Abeni @ 2025-04-15 13:43 UTC (permalink / raw)
To: Wei Fang, claudiu.manoil, vladimir.oltean, xiaoning.wang,
andrew+netdev, davem, edumazet, kuba
Cc: christophe.leroy, netdev, linux-kernel, imx, linuxppc-dev,
linux-arm-kernel
On 4/11/25 11:57 AM, Wei Fang wrote:
> Since i.MX95 ENETC (v4) uses NTMP 2.0 to manage the RSS table, which is
> different from LS1028A ENETC (v1). In order to reuse some functions
> related to the RSS table, so add .get_rss_table() and .set_rss_table()
> hooks to enetc_si_ops.
>
> Signed-off-by: Wei Fang <wei.fang@nxp.com>
> ---
> v5 changes:
> Add enetc_set_default_rss_key() to enetc_pf_common.c and use it in both
> enetc v1 and v4 drivers
Note for the reviewers: this changelog actually applies to the next
(07/14) patch.
/P
^ permalink raw reply [flat|nested] 29+ messages in thread
* RE: [PATCH v5 net-next 06/14] net: enetc: add set/get_rss_table() hooks to enetc_si_ops
2025-04-15 13:43 ` Paolo Abeni
@ 2025-04-16 2:31 ` Wei Fang
0 siblings, 0 replies; 29+ messages in thread
From: Wei Fang @ 2025-04-16 2:31 UTC (permalink / raw)
To: Paolo Abeni, Claudiu Manoil, Vladimir Oltean, Clark Wang,
andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com,
kuba@kernel.org
Cc: christophe.leroy@csgroup.eu, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org, imx@lists.linux.dev,
linuxppc-dev@lists.ozlabs.org,
linux-arm-kernel@lists.infradead.org
> On 4/11/25 11:57 AM, Wei Fang wrote:
> > Since i.MX95 ENETC (v4) uses NTMP 2.0 to manage the RSS table, which
> > is different from LS1028A ENETC (v1). In order to reuse some functions
> > related to the RSS table, so add .get_rss_table() and .set_rss_table()
> > hooks to enetc_si_ops.
> >
> > Signed-off-by: Wei Fang <wei.fang@nxp.com>
> > ---
> > v5 changes:
> > Add enetc_set_default_rss_key() to enetc_pf_common.c and use it in
> > both enetc v1 and v4 drivers
>
> Note for the reviewers: this changelog actually applies to the next
> (07/14) patch.
>
> /P
Thanks for pointing out this mistake of changelog.
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH v5 net-next 04/14] net: enetc: add MAC filtering for i.MX95 ENETC PF
2025-04-11 9:57 ` [PATCH v5 net-next 04/14] net: enetc: add MAC filtering for i.MX95 ENETC PF Wei Fang
@ 2025-04-16 3:42 ` Jakub Kicinski
2025-04-16 5:16 ` Wei Fang
2025-04-18 15:41 ` Vladimir Oltean
1 sibling, 1 reply; 29+ messages in thread
From: Jakub Kicinski @ 2025-04-16 3:42 UTC (permalink / raw)
To: Wei Fang
Cc: claudiu.manoil, vladimir.oltean, xiaoning.wang, andrew+netdev,
davem, edumazet, pabeni, christophe.leroy, netdev, linux-kernel,
imx, linuxppc-dev, linux-arm-kernel
On Fri, 11 Apr 2025 17:57:42 +0800 Wei Fang wrote:
> enetc4_pf_netdev_destroy(si);
> enetc4_pf_free(pf);
> + destroy_workqueue(si->workqueue);
I think that you need to flush or cancel the work after unregistering
the netdev but before freeing it? The work may access netdev after its
freed.
^ permalink raw reply [flat|nested] 29+ messages in thread
* RE: [PATCH v5 net-next 04/14] net: enetc: add MAC filtering for i.MX95 ENETC PF
2025-04-16 3:42 ` Jakub Kicinski
@ 2025-04-16 5:16 ` Wei Fang
2025-04-18 14:29 ` Vladimir Oltean
0 siblings, 1 reply; 29+ messages in thread
From: Wei Fang @ 2025-04-16 5:16 UTC (permalink / raw)
To: Jakub Kicinski
Cc: Claudiu Manoil, Vladimir Oltean, Clark Wang,
andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com,
pabeni@redhat.com, christophe.leroy@csgroup.eu,
netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
imx@lists.linux.dev, linuxppc-dev@lists.ozlabs.org,
linux-arm-kernel@lists.infradead.org
> -----Original Message-----
> From: Jakub Kicinski <kuba@kernel.org>
> Sent: 2025年4月16日 11:43
> To: Wei Fang <wei.fang@nxp.com>
> Cc: Claudiu Manoil <claudiu.manoil@nxp.com>; Vladimir Oltean
> <vladimir.oltean@nxp.com>; Clark Wang <xiaoning.wang@nxp.com>;
> andrew+netdev@lunn.ch; davem@davemloft.net; edumazet@google.com;
> pabeni@redhat.com; christophe.leroy@csgroup.eu; netdev@vger.kernel.org;
> linux-kernel@vger.kernel.org; imx@lists.linux.dev; linuxppc-dev@lists.ozlabs.org;
> linux-arm-kernel@lists.infradead.org
> Subject: Re: [PATCH v5 net-next 04/14] net: enetc: add MAC filtering for i.MX95
> ENETC PF
>
> On Fri, 11 Apr 2025 17:57:42 +0800 Wei Fang wrote:
> > enetc4_pf_netdev_destroy(si);
> > enetc4_pf_free(pf);
> > + destroy_workqueue(si->workqueue);
>
> I think that you need to flush or cancel the work after unregistering
> the netdev but before freeing it? The work may access netdev after its
> freed.
Yes, you are right, I will improve it. thanks.
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH v5 net-next 01/14] net: enetc: add initial netc-lib driver to support NTMP
2025-04-11 9:57 ` [PATCH v5 net-next 01/14] net: enetc: add initial netc-lib driver to support NTMP Wei Fang
@ 2025-04-18 12:49 ` Vladimir Oltean
2025-04-18 13:38 ` Wei Fang
0 siblings, 1 reply; 29+ messages in thread
From: Vladimir Oltean @ 2025-04-18 12:49 UTC (permalink / raw)
To: Wei Fang
Cc: claudiu.manoil, vladimir.oltean, xiaoning.wang, andrew+netdev,
davem, edumazet, kuba, pabeni, christophe.leroy, netdev,
linux-kernel, imx, linuxppc-dev, linux-arm-kernel
I see this is "Changes requested", so here are some more nitpicks from me.
On Fri, Apr 11, 2025 at 05:57:39PM +0800, Wei Fang wrote:
> Some NETC functionality is controlled using control messages sent to the
> hardware using BD ring interface with 32B descriptor similar to transmit
> BD ring used on ENETC. This BD ring interface is referred to as command
> BD ring. It is used to configure functionality where the underlying
> resources may be shared between different entities or being too large to
> configure using direct registers. Therefore, a messaging protocol called
> NETC Table Management Protocol (NTMP) is provided for exchanging
> configuration and management information between the software and the
> hardware using the command BD ring interface.
>
> For i.MX95, NTMP has been upgraded to version 2.0, which is incompatible
> with LS1028A, because the message formats have been changed.
Can you please add one more sentence clarifying that the LS1028A
management protocol has been retroactively named NTMP 1.0 and its
implementation is in enetc_cbdr.c and enetc_tsn.c? The driver, like new
NETC documentation, refers to NTMP 2.0 as simply "NTMP".
> Therefore, add the netc-lib driver to support NTMP 2.0 to operate various tables.
> Note that, only MAC address filter table and RSS table are supported at
> the moment. More tables will be supported in subsequent patches.
>
> It is worth mentioning that the purpose of the netc-lib driver is to
> provide some NTMP-based generic interfaces for ENETC and NETC Switch
> drivers. Currently, it only supports the configurations of some tables.
> Interfaces such as tc flower and debugfs will be added in the future.
>
> Signed-off-by: Wei Fang <wei.fang@nxp.com>
> ---
> +static int netc_xmit_ntmp_cmd(struct ntmp_user *user, union netc_cbd *cbd)
> +{
> + union netc_cbd *cur_cbd;
> + struct netc_cbdr *cbdr;
> + int i, err;
> + u16 status;
> + u32 val;
> +
> + /* Currently only i.MX95 ENETC is supported, and it only has one
> + * command BD ring
> + */
> + cbdr = &user->ring[0];
> +
> + spin_lock_bh(&cbdr->ring_lock);
> +
> + if (unlikely(!netc_get_free_cbd_num(cbdr)))
> + netc_clean_cbdr(cbdr);
> +
> + i = cbdr->next_to_use;
> + cur_cbd = netc_get_cbd(cbdr, i);
> + *cur_cbd = *cbd;
> + dma_wmb();
> +
> + /* Update producer index of both software and hardware */
> + i = (i + 1) % cbdr->bd_num;
> + cbdr->next_to_use = i;
> + netc_write(cbdr->regs.pir, i);
> +
> + err = read_poll_timeout_atomic(netc_read, val, val == i,
> + 10, NETC_CBDR_TIMEOUT, true,
Please create a #define for NETC_CBDR_SLEEP_US too.
> + cbdr->regs.cir);
> + if (unlikely(err))
> + goto cbdr_unlock;
> +
> + dma_rmb();
> + /* Get the writeback command BD, because the caller may need
> + * to check some other fields of the response header.
> + */
> + *cbd = *cur_cbd;
> +
> + /* Check the writeback error status */
> + status = le16_to_cpu(cbd->resp_hdr.error_rr) & NTMP_RESP_ERROR;
> + if (unlikely(status)) {
> + err = -EIO;
> + dev_err(user->dev, "Command BD error: 0x%04x\n", status);
> + }
> +
> + netc_clean_cbdr(cbdr);
> + dma_wmb();
> +
> +cbdr_unlock:
> + spin_unlock_bh(&cbdr->ring_lock);
> +
> + return err;
> +}
> +
> +static int ntmp_alloc_data_mem(struct ntmp_dma_buf *data, void **buf_align)
> +{
> + void *buf;
> +
> + buf = dma_alloc_coherent(data->dev, data->size + NTMP_DATA_ADDR_ALIGN,
> + &data->dma, GFP_KERNEL);
> + if (!buf)
> + return -ENOMEM;
> +
> + data->buf = buf;
> + *buf_align = PTR_ALIGN(buf, NTMP_DATA_ADDR_ALIGN);
> +
> + return 0;
> +}
> +
> +static void ntmp_free_data_mem(struct ntmp_dma_buf *data)
> +{
> + dma_free_coherent(data->dev, data->size + NTMP_DATA_ADDR_ALIGN,
> + data->buf, data->dma);
> +}
> +
> +static void ntmp_fill_request_hdr(union netc_cbd *cbd, dma_addr_t dma,
> + int len, int table_id, int cmd,
> + int access_method)
> +{
> + dma_addr_t dma_align;
> +
> + memset(cbd, 0, sizeof(*cbd));
> + dma_align = ALIGN(dma, NTMP_DATA_ADDR_ALIGN);
> + cbd->req_hdr.addr = cpu_to_le64(dma_align);
> + cbd->req_hdr.len = cpu_to_le32(len);
> + cbd->req_hdr.cmd = cmd;
> + cbd->req_hdr.access_method = FIELD_PREP(NTMP_ACCESS_METHOD,
> + access_method);
> + cbd->req_hdr.table_id = table_id;
> + cbd->req_hdr.ver_cci_rr = FIELD_PREP(NTMP_HDR_VERSION,
> + NTMP_HDR_VER2);
> + /* For NTMP version 2.0 or later version */
> + cbd->req_hdr.npf = cpu_to_le32(NTMP_NPF);
> +}
> +
> +static void ntmp_fill_crd(struct ntmp_cmn_req_data *crd, u8 tblv,
> + u8 qa, u16 ua)
> +{
> + crd->update_act = cpu_to_le16(ua);
> + crd->tblv_qact = NTMP_TBLV_QACT(tblv, qa);
> +}
> +
> +static void ntmp_fill_crd_eid(struct ntmp_req_by_eid *rbe, u8 tblv,
> + u8 qa, u16 ua, u32 entry_id)
> +{
> + ntmp_fill_crd(&rbe->crd, tblv, qa, ua);
> + rbe->entry_id = cpu_to_le32(entry_id);
> +}
> +
> +static int ntmp_delete_entry_by_id(struct ntmp_user *user, int tbl_id,
> + u8 tbl_ver, u32 entry_id, u32 req_len,
> + u32 resp_len)
> +{
> + struct ntmp_dma_buf data = {.dev = user->dev};
> + struct ntmp_req_by_eid *req;
> + union netc_cbd cbd;
> + u32 len;
> + int err;
> +
> + data.size = req_len >= resp_len ? req_len : resp_len;
max(req_len, resp_len)
It can also be placed as part of the "data" initializer:
struct ntmp_dma_buf data = {
.dev = user->dev,
.size = max(req_len, resp_len),
};
> + err = ntmp_alloc_data_mem(&data, (void **)&req);
> + if (err)
> + return err;
> +
> + ntmp_fill_crd_eid(req, tbl_ver, 0, 0, entry_id);
> + len = NTMP_LEN(req_len, resp_len);
> + ntmp_fill_request_hdr(&cbd, data.dma, len, tbl_id,
> + NTMP_CMD_DELETE, NTMP_AM_ENTRY_ID);
> +
> + err = netc_xmit_ntmp_cmd(user, &cbd);
> + if (err)
> + dev_err(user->dev, "Delete table (id: %d) entry failed: %pe",
> + tbl_id, ERR_PTR(err));
Could you also print the entry_id?
> +
> + ntmp_free_data_mem(&data);
> +
> + return err;
> +}
> +
> +static int ntmp_query_entry_by_id(struct ntmp_user *user, int tbl_id,
> + u32 len, struct ntmp_req_by_eid *req,
> + dma_addr_t dma, bool compare_eid)
> +{
> + struct device *dev = user->dev;
> + struct ntmp_cmn_resp_query *resp;
> + int cmd = NTMP_CMD_QUERY;
> + union netc_cbd cbd;
> + u32 entry_id;
> + int err;
> +
> + entry_id = le32_to_cpu(req->entry_id);
> + if (le16_to_cpu(req->crd.update_act))
> + cmd = NTMP_CMD_QU;
> +
> + /* Request header */
> + ntmp_fill_request_hdr(&cbd, dma, len, tbl_id, cmd, NTMP_AM_ENTRY_ID);
> + err = netc_xmit_ntmp_cmd(user, &cbd);
> + if (err) {
> + dev_err(dev, "Query table (id: %d) entry failed: %pe\n",
> + tbl_id, ERR_PTR(err));
Could you print a string representation of the tbl_id instead? It should
be more user-friendly if something fails.
static const char *ntmp_table_name(enum ntmp_tbl_id tbl_id)
{
switch (tbl_id) {
case NTMP_MAFT_ID:
return "MAC Address Filtering";
case NTMP_RSST_ID:
return "RSS";
default:
return "unknown";
}
}
Also, similar comment about entry_id being absent here.
> + return err;
> + }
> +
> + /* For a few tables, the first field of their response data is not
> + * entry_id, so directly return success.
> + */
> + if (!compare_eid)
> + return 0;
> +
> + resp = (struct ntmp_cmn_resp_query *)req;
> + if (unlikely(le32_to_cpu(resp->entry_id) != entry_id)) {
> + dev_err(dev, "Table (id: %d) query EID: 0x%x, response EID: 0x%x\n",
> + tbl_id, entry_id, le32_to_cpu(resp->entry_id));
> + return -EIO;
> + }
> +
> + return 0;
> +}
> +
> +int ntmp_maft_add_entry(struct ntmp_user *user, u32 entry_id,
> + struct maft_entry_data *maft)
> +{
> + struct ntmp_dma_buf data = {.dev = user->dev};
> + struct maft_req_add *req;
> + union netc_cbd cbd;
> + int err;
> +
> + data.size = sizeof(*req);
Same comment about wrapping this into the struct initializer.
> + err = ntmp_alloc_data_mem(&data, (void **)&req);
> + if (err)
> + return err;
> +
> + /* Set mac address filter table request data buffer */
> + ntmp_fill_crd_eid(&req->rbe, user->tbl.maft_ver, 0, 0, entry_id);
> + req->keye = maft->keye;
> + req->cfge = maft->cfge;
> +
> + ntmp_fill_request_hdr(&cbd, data.dma, NTMP_LEN(data.size, 0),
> + NTMP_MAFT_ID, NTMP_CMD_ADD, NTMP_AM_ENTRY_ID);
> + err = netc_xmit_ntmp_cmd(user, &cbd);
> + if (err)
> + dev_err(user->dev, "Add MAFT entry failed (%pe)\n",
> + ERR_PTR(err));
> +
> + ntmp_free_data_mem(&data);
> +
> + return err;
> +}
> +EXPORT_SYMBOL_GPL(ntmp_maft_add_entry);
> +
> +int ntmp_maft_query_entry(struct ntmp_user *user, u32 entry_id,
> + struct maft_entry_data *maft)
> +{
> + struct ntmp_dma_buf data = {.dev = user->dev};
> + struct maft_resp_query *resp;
> + struct ntmp_req_by_eid *req;
> + int err;
> +
> + data.size = sizeof(*resp);
Same comment about struct initializer.
> + err = ntmp_alloc_data_mem(&data, (void **)&req);
> + if (err)
> + return err;
> +
> + ntmp_fill_crd_eid(req, user->tbl.maft_ver, 0, 0, entry_id);
> + err = ntmp_query_entry_by_id(user, NTMP_MAFT_ID,
> + NTMP_LEN(sizeof(*req), data.size),
> + req, data.dma, true);
> + if (err)
> + goto end;
> +
> + resp = (struct maft_resp_query *)req;
> + maft->keye = resp->keye;
> + maft->cfge = resp->cfge;
> +
> +end:
> + ntmp_free_data_mem(&data);
> +
> + return err;
> +}
> +EXPORT_SYMBOL_GPL(ntmp_maft_query_entry);
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH v5 net-next 02/14] net: enetc: add command BD ring support for i.MX95 ENETC
2025-04-11 9:57 ` [PATCH v5 net-next 02/14] net: enetc: add command BD ring support for i.MX95 ENETC Wei Fang
@ 2025-04-18 13:25 ` Vladimir Oltean
2025-04-18 13:49 ` Wei Fang
0 siblings, 1 reply; 29+ messages in thread
From: Vladimir Oltean @ 2025-04-18 13:25 UTC (permalink / raw)
To: Wei Fang
Cc: claudiu.manoil, vladimir.oltean, xiaoning.wang, andrew+netdev,
davem, edumazet, kuba, pabeni, christophe.leroy, netdev,
linux-kernel, imx, linuxppc-dev, linux-arm-kernel
On Fri, Apr 11, 2025 at 05:57:40PM +0800, Wei Fang wrote:
> diff --git a/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c b/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
> index 20bfdf7fb4b4..ecb571e5ea50 100644
> --- a/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
> +++ b/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
> @@ -60,6 +60,45 @@ void enetc_teardown_cbdr(struct enetc_cbdr *cbdr)
> }
> EXPORT_SYMBOL_GPL(enetc_teardown_cbdr);
>
> +int enetc4_setup_cbdr(struct enetc_si *si)
> +{
> + struct ntmp_user *user = &si->ntmp_user;
> + struct device *dev = &si->pdev->dev;
> + struct enetc_hw *hw = &si->hw;
> + struct netc_cbdr_regs regs;
> +
> + user->cbdr_num = 1;
> + user->cbdr_size = NETC_CBDR_BD_NUM;
> + user->dev = dev;
> + user->ring = devm_kcalloc(dev, user->cbdr_num,
> + sizeof(struct netc_cbdr), GFP_KERNEL);
> + if (!user->ring)
> + return -ENOMEM;
> +
> + /* set CBDR cache attributes */
> + enetc_wr(hw, ENETC_SICAR2,
> + ENETC_SICAR_RD_COHERENT | ENETC_SICAR_WR_COHERENT);
> +
> + regs.pir = hw->reg + ENETC_SICBDRPIR;
> + regs.cir = hw->reg + ENETC_SICBDRCIR;
> + regs.mr = hw->reg + ENETC_SICBDRMR;
> + regs.bar0 = hw->reg + ENETC_SICBDRBAR0;
> + regs.bar1 = hw->reg + ENETC_SICBDRBAR1;
> + regs.lenr = hw->reg + ENETC_SICBDRLENR;
> +
> + return netc_setup_cbdr(dev, user->cbdr_size, ®s, user->ring);
> +}
> +EXPORT_SYMBOL_GPL(enetc4_setup_cbdr);
> +
> +void enetc4_teardown_cbdr(struct enetc_si *si)
> +{
> + struct ntmp_user *user = &si->ntmp_user;
> +
> + netc_teardown_cbdr(user->dev, user->ring);
> + user->dev = NULL;
> +}
> +EXPORT_SYMBOL_GPL(enetc4_teardown_cbdr);
I wanted to ask why isn't netc_setup_cbdr() merged into enetc4_setup_cbdr()
(and likewise for teardown_cbdr), because they sound very similar, and
they operate on the same data - one is literally a continuation of the
other. Then I looked downstream where the netc_switch is another API
user of netc_setup_cbdr() and netc_teardown_cbdr().
Do you think you could rename netc_setup_cbdr() into something like below:
struct ntmp_user *ntmp_user_create(struct device *dev, size_t num_cbdr,
const struct netc_cbdr_regs *regs);
void ntmp_user_destroy(struct ntmp_user *user);
From a data encapsulation perspective, it would be great if the outside
world only worked with an opaque struct ntmp_user * pointer.
Hide NETC_CBDR_BD_NUM from include/linux/fsl/ntmp.h if API users don't
need to customize it, and let ntmp_user_create() set it.
Move even more initialization into ntmp_user_create(), like the
allocation of "user->ring", and reduce the number of arguments.
In my opinion this would be a more natural organization of the code.
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH v5 net-next 03/14] net: enetc: move generic MAC filtering interfaces to enetc-core
2025-04-11 9:57 ` [PATCH v5 net-next 03/14] net: enetc: move generic MAC filtering interfaces to enetc-core Wei Fang
@ 2025-04-18 13:37 ` Vladimir Oltean
0 siblings, 0 replies; 29+ messages in thread
From: Vladimir Oltean @ 2025-04-18 13:37 UTC (permalink / raw)
To: Wei Fang
Cc: claudiu.manoil, vladimir.oltean, xiaoning.wang, andrew+netdev,
davem, edumazet, kuba, pabeni, christophe.leroy, netdev,
linux-kernel, imx, linuxppc-dev, linux-arm-kernel
On Fri, Apr 11, 2025 at 05:57:41PM +0800, Wei Fang wrote:
> Although only ENETC PF can access the MAC address filter table, the table
> entries can specify MAC address filtering for one or more SIs based on
> SI_BITMAP, which means that the table also supports MAC address filtering
> for VFs.
>
> Currently, only the ENETC v1 PF driver supports MAC address filtering. In
> order to add the MAC address filtering support for the ENETC v4 PF driver
> and VF driver in the future, the relevant generic interfaces are moved to
> the enetc-core driver. This lays the basis for i.MX95 ENETC PF and VFs to
> support MAC address filtering.
>
> Signed-off-by: Wei Fang <wei.fang@nxp.com>
> ---
Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>
^ permalink raw reply [flat|nested] 29+ messages in thread
* RE: [PATCH v5 net-next 01/14] net: enetc: add initial netc-lib driver to support NTMP
2025-04-18 12:49 ` Vladimir Oltean
@ 2025-04-18 13:38 ` Wei Fang
2025-04-18 13:49 ` Vladimir Oltean
0 siblings, 1 reply; 29+ messages in thread
From: Wei Fang @ 2025-04-18 13:38 UTC (permalink / raw)
To: Vladimir Oltean
Cc: Claudiu Manoil, Vladimir Oltean, Clark Wang,
andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com,
kuba@kernel.org, pabeni@redhat.com, christophe.leroy@csgroup.eu,
netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
imx@lists.linux.dev, linuxppc-dev@lists.ozlabs.org,
linux-arm-kernel@lists.infradead.org
> I see this is "Changes requested", so here are some more nitpicks from me.
>
> On Fri, Apr 11, 2025 at 05:57:39PM +0800, Wei Fang wrote:
> > Some NETC functionality is controlled using control messages sent to the
> > hardware using BD ring interface with 32B descriptor similar to transmit
> > BD ring used on ENETC. This BD ring interface is referred to as command
> > BD ring. It is used to configure functionality where the underlying
> > resources may be shared between different entities or being too large to
> > configure using direct registers. Therefore, a messaging protocol called
> > NETC Table Management Protocol (NTMP) is provided for exchanging
> > configuration and management information between the software and the
> > hardware using the command BD ring interface.
> >
> > For i.MX95, NTMP has been upgraded to version 2.0, which is incompatible
> > with LS1028A, because the message formats have been changed.
>
> Can you please add one more sentence clarifying that the LS1028A
> management protocol has been retroactively named NTMP 1.0 and its
> implementation is in enetc_cbdr.c and enetc_tsn.c? The driver, like new
> NETC documentation, refers to NTMP 2.0 as simply "NTMP".
>
Okay, but enetc_tsn.c is only existed in downstream, so it will not be
added here.
^ permalink raw reply [flat|nested] 29+ messages in thread
* RE: [PATCH v5 net-next 02/14] net: enetc: add command BD ring support for i.MX95 ENETC
2025-04-18 13:25 ` Vladimir Oltean
@ 2025-04-18 13:49 ` Wei Fang
2025-04-18 13:52 ` Vladimir Oltean
0 siblings, 1 reply; 29+ messages in thread
From: Wei Fang @ 2025-04-18 13:49 UTC (permalink / raw)
To: Vladimir Oltean
Cc: Claudiu Manoil, Vladimir Oltean, Clark Wang,
andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com,
kuba@kernel.org, pabeni@redhat.com, christophe.leroy@csgroup.eu,
netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
imx@lists.linux.dev, linuxppc-dev@lists.ozlabs.org,
linux-arm-kernel@lists.infradead.org
> -----Original Message-----
> From: Vladimir Oltean <olteanv@gmail.com>
> Sent: 2025年4月18日 21:25
> To: Wei Fang <wei.fang@nxp.com>
> Cc: Claudiu Manoil <claudiu.manoil@nxp.com>; Vladimir Oltean
> <vladimir.oltean@nxp.com>; Clark Wang <xiaoning.wang@nxp.com>;
> andrew+netdev@lunn.ch; davem@davemloft.net; edumazet@google.com;
> kuba@kernel.org; pabeni@redhat.com; christophe.leroy@csgroup.eu;
> netdev@vger.kernel.org; linux-kernel@vger.kernel.org; imx@lists.linux.dev;
> linuxppc-dev@lists.ozlabs.org; linux-arm-kernel@lists.infradead.org
> Subject: Re: [PATCH v5 net-next 02/14] net: enetc: add command BD ring
> support for i.MX95 ENETC
>
> On Fri, Apr 11, 2025 at 05:57:40PM +0800, Wei Fang wrote:
> > diff --git a/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
> b/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
> > index 20bfdf7fb4b4..ecb571e5ea50 100644
> > --- a/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
> > +++ b/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
> > @@ -60,6 +60,45 @@ void enetc_teardown_cbdr(struct enetc_cbdr *cbdr)
> > }
> > EXPORT_SYMBOL_GPL(enetc_teardown_cbdr);
> >
> > +int enetc4_setup_cbdr(struct enetc_si *si)
> > +{
> > + struct ntmp_user *user = &si->ntmp_user;
> > + struct device *dev = &si->pdev->dev;
> > + struct enetc_hw *hw = &si->hw;
> > + struct netc_cbdr_regs regs;
> > +
> > + user->cbdr_num = 1;
> > + user->cbdr_size = NETC_CBDR_BD_NUM;
> > + user->dev = dev;
> > + user->ring = devm_kcalloc(dev, user->cbdr_num,
> > + sizeof(struct netc_cbdr), GFP_KERNEL);
> > + if (!user->ring)
> > + return -ENOMEM;
> > +
> > + /* set CBDR cache attributes */
> > + enetc_wr(hw, ENETC_SICAR2,
> > + ENETC_SICAR_RD_COHERENT | ENETC_SICAR_WR_COHERENT);
> > +
> > + regs.pir = hw->reg + ENETC_SICBDRPIR;
> > + regs.cir = hw->reg + ENETC_SICBDRCIR;
> > + regs.mr = hw->reg + ENETC_SICBDRMR;
> > + regs.bar0 = hw->reg + ENETC_SICBDRBAR0;
> > + regs.bar1 = hw->reg + ENETC_SICBDRBAR1;
> > + regs.lenr = hw->reg + ENETC_SICBDRLENR;
> > +
> > + return netc_setup_cbdr(dev, user->cbdr_size, ®s, user->ring);
> > +}
> > +EXPORT_SYMBOL_GPL(enetc4_setup_cbdr);
> > +
> > +void enetc4_teardown_cbdr(struct enetc_si *si)
> > +{
> > + struct ntmp_user *user = &si->ntmp_user;
> > +
> > + netc_teardown_cbdr(user->dev, user->ring);
> > + user->dev = NULL;
> > +}
> > +EXPORT_SYMBOL_GPL(enetc4_teardown_cbdr);
>
> I wanted to ask why isn't netc_setup_cbdr() merged into enetc4_setup_cbdr()
> (and likewise for teardown_cbdr), because they sound very similar, and
> they operate on the same data - one is literally a continuation of the
> other. Then I looked downstream where the netc_switch is another API
> user of netc_setup_cbdr() and netc_teardown_cbdr().
>
> Do you think you could rename netc_setup_cbdr() into something like below:
Sure, I will rename them.
>
> struct ntmp_user *ntmp_user_create(struct device *dev, size_t num_cbdr,
> const struct netc_cbdr_regs *regs);
> void ntmp_user_destroy(struct ntmp_user *user);
>
> From a data encapsulation perspective, it would be great if the outside
> world only worked with an opaque struct ntmp_user * pointer.
>
> Hide NETC_CBDR_BD_NUM from include/linux/fsl/ntmp.h if API users don't
> need to customize it, and let ntmp_user_create() set it.
>
Do we need to retain cbdr_size in struct ntmp_user? Or just remove it in
next version?
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH v5 net-next 01/14] net: enetc: add initial netc-lib driver to support NTMP
2025-04-18 13:38 ` Wei Fang
@ 2025-04-18 13:49 ` Vladimir Oltean
0 siblings, 0 replies; 29+ messages in thread
From: Vladimir Oltean @ 2025-04-18 13:49 UTC (permalink / raw)
To: Wei Fang
Cc: Claudiu Manoil, Vladimir Oltean, Clark Wang,
andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com,
kuba@kernel.org, pabeni@redhat.com, christophe.leroy@csgroup.eu,
netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
imx@lists.linux.dev, linuxppc-dev@lists.ozlabs.org,
linux-arm-kernel@lists.infradead.org
On Fri, Apr 18, 2025 at 01:38:31PM +0000, Wei Fang wrote:
> > Can you please add one more sentence clarifying that the LS1028A
> > management protocol has been retroactively named NTMP 1.0 and its
> > implementation is in enetc_cbdr.c and enetc_tsn.c? The driver, like new
> > NETC documentation, refers to NTMP 2.0 as simply "NTMP".
> >
>
> Okay, but enetc_tsn.c is only existed in downstream, so it will not be
> added here.
enetc_qos.c, sorry.
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH v5 net-next 02/14] net: enetc: add command BD ring support for i.MX95 ENETC
2025-04-18 13:49 ` Wei Fang
@ 2025-04-18 13:52 ` Vladimir Oltean
0 siblings, 0 replies; 29+ messages in thread
From: Vladimir Oltean @ 2025-04-18 13:52 UTC (permalink / raw)
To: Wei Fang
Cc: Claudiu Manoil, Vladimir Oltean, Clark Wang,
andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com,
kuba@kernel.org, pabeni@redhat.com, christophe.leroy@csgroup.eu,
netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
imx@lists.linux.dev, linuxppc-dev@lists.ozlabs.org,
linux-arm-kernel@lists.infradead.org
On Fri, Apr 18, 2025 at 01:49:25PM +0000, Wei Fang wrote:
> Do we need to retain cbdr_size in struct ntmp_user? Or just remove it in
> next version?
It seems redundant with cbdr->bd_num, so yes, please remove it.
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH v5 net-next 04/14] net: enetc: add MAC filtering for i.MX95 ENETC PF
2025-04-16 5:16 ` Wei Fang
@ 2025-04-18 14:29 ` Vladimir Oltean
0 siblings, 0 replies; 29+ messages in thread
From: Vladimir Oltean @ 2025-04-18 14:29 UTC (permalink / raw)
To: Wei Fang
Cc: Jakub Kicinski, Claudiu Manoil, Vladimir Oltean, Clark Wang,
andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com,
pabeni@redhat.com, christophe.leroy@csgroup.eu,
netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
imx@lists.linux.dev, linuxppc-dev@lists.ozlabs.org,
linux-arm-kernel@lists.infradead.org
On Wed, Apr 16, 2025 at 05:16:15AM +0000, Wei Fang wrote:
> > -----Original Message-----
> > From: Jakub Kicinski <kuba@kernel.org>
> > Sent: 2025年4月16日 11:43
> > To: Wei Fang <wei.fang@nxp.com>
> > Cc: Claudiu Manoil <claudiu.manoil@nxp.com>; Vladimir Oltean
> > <vladimir.oltean@nxp.com>; Clark Wang <xiaoning.wang@nxp.com>;
> > andrew+netdev@lunn.ch; davem@davemloft.net; edumazet@google.com;
> > pabeni@redhat.com; christophe.leroy@csgroup.eu; netdev@vger.kernel.org;
> > linux-kernel@vger.kernel.org; imx@lists.linux.dev; linuxppc-dev@lists.ozlabs.org;
> > linux-arm-kernel@lists.infradead.org
> > Subject: Re: [PATCH v5 net-next 04/14] net: enetc: add MAC filtering for i.MX95
> > ENETC PF
> >
> > On Fri, 11 Apr 2025 17:57:42 +0800 Wei Fang wrote:
> > > enetc4_pf_netdev_destroy(si);
> > > enetc4_pf_free(pf);
> > > + destroy_workqueue(si->workqueue);
> >
> > I think that you need to flush or cancel the work after unregistering
> > the netdev but before freeing it? The work may access netdev after its
> > freed.
>
> Yes, you are right, I will improve it. thanks.
I think the workqueue creation needs to be handled in
enetc4_pf_netdev_create() somewhere in between alloc_etherdev_mqs() and
register_netdev(), so that the workqueue is available as soon as the
interface is registered, but also so that the workqueue teardown takes
places naturally where Jakub indicated.
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH v5 net-next 04/14] net: enetc: add MAC filtering for i.MX95 ENETC PF
2025-04-11 9:57 ` [PATCH v5 net-next 04/14] net: enetc: add MAC filtering for i.MX95 ENETC PF Wei Fang
2025-04-16 3:42 ` Jakub Kicinski
@ 2025-04-18 15:41 ` Vladimir Oltean
2025-04-21 3:14 ` Wei Fang
1 sibling, 1 reply; 29+ messages in thread
From: Vladimir Oltean @ 2025-04-18 15:41 UTC (permalink / raw)
To: Wei Fang
Cc: claudiu.manoil, vladimir.oltean, xiaoning.wang, andrew+netdev,
davem, edumazet, kuba, pabeni, christophe.leroy, netdev,
linux-kernel, imx, linuxppc-dev, linux-arm-kernel
On Fri, Apr 11, 2025 at 05:57:42PM +0800, Wei Fang wrote:
> static const struct enetc_pf_ops enetc4_pf_ops = {
> .set_si_primary_mac = enetc4_pf_set_si_primary_mac,
> .get_si_primary_mac = enetc4_pf_get_si_primary_mac,
> @@ -303,12 +489,55 @@ 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)
> +{
> + 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;
> + bool uc_promisc = false;
> + bool mc_promisc = false;
> + int type = 0;
> +
> + if (ndev->flags & IFF_PROMISC) {
> + uc_promisc = true;
> + mc_promisc = true;
> + } else if (ndev->flags & IFF_ALLMULTI) {
enetc4_psi_do_set_rx_mode() runs unlocked relative to changes made
to ndev->flags, so could you at least read it just once to avoid
inconsistencies?
Speaking of running unlocked: if I'm not mistaken, this code design
might lose consecutive updates to ndev->flags, as well as to the address
lists, if queue_work() is executed while si->rx_mode_task is still
running. There is a difference between statically allocating and
continuously queuing the same work item, vs allocating one work item
per each ndo_set_rx_mode() call.
In practice it might be hard to trigger an actual issue, because the
call sites serialize under rtnl_lock() which is so bulky that
si->rx_mode_task should have time to finish by the time ndo_set_rx_mode()
has a chance to be called again.
I can't tell you exactly how, but my gut feeling is that the combination
of these 2 things is going to be problematic.
^ permalink raw reply [flat|nested] 29+ messages in thread
* RE: [PATCH v5 net-next 04/14] net: enetc: add MAC filtering for i.MX95 ENETC PF
2025-04-18 15:41 ` Vladimir Oltean
@ 2025-04-21 3:14 ` Wei Fang
0 siblings, 0 replies; 29+ messages in thread
From: Wei Fang @ 2025-04-21 3:14 UTC (permalink / raw)
To: Vladimir Oltean
Cc: Claudiu Manoil, Vladimir Oltean, Clark Wang,
andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com,
kuba@kernel.org, pabeni@redhat.com, christophe.leroy@csgroup.eu,
netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
imx@lists.linux.dev, linuxppc-dev@lists.ozlabs.org,
linux-arm-kernel@lists.infradead.org
> On Fri, Apr 11, 2025 at 05:57:42PM +0800, Wei Fang wrote:
> > static const struct enetc_pf_ops enetc4_pf_ops = {
> > .set_si_primary_mac = enetc4_pf_set_si_primary_mac,
> > .get_si_primary_mac = enetc4_pf_get_si_primary_mac,
> > @@ -303,12 +489,55 @@ 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)
> > +{
> > + 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;
> > + bool uc_promisc = false;
> > + bool mc_promisc = false;
> > + int type = 0;
> > +
> > + if (ndev->flags & IFF_PROMISC) {
> > + uc_promisc = true;
> > + mc_promisc = true;
> > + } else if (ndev->flags & IFF_ALLMULTI) {
>
> enetc4_psi_do_set_rx_mode() runs unlocked relative to changes made
> to ndev->flags, so could you at least read it just once to avoid
> inconsistencies?
>
> Speaking of running unlocked: if I'm not mistaken, this code design
> might lose consecutive updates to ndev->flags, as well as to the address
> lists, if queue_work() is executed while si->rx_mode_task is still
> running. There is a difference between statically allocating and
> continuously queuing the same work item, vs allocating one work item
> per each ndo_set_rx_mode() call.
>
> In practice it might be hard to trigger an actual issue, because the
> call sites serialize under rtnl_lock() which is so bulky that
> si->rx_mode_task should have time to finish by the time ndo_set_rx_mode()
> has a chance to be called again.
>
> I can't tell you exactly how, but my gut feeling is that the combination
> of these 2 things is going to be problematic.
I think we can add rtnl_lock() to enetc4_psi_do_set_rx_mode() to keep
consistency, as shown below.
--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -497,6 +497,8 @@ static void enetc4_psi_do_set_rx_mode(struct work_struct *work)
bool mc_promisc = false;
int type = 0;
+ rtnl_lock();
+
if (ndev->flags & IFF_PROMISC) {
uc_promisc = true;
mc_promisc = true;
@@ -519,6 +521,8 @@ static void enetc4_psi_do_set_rx_mode(struct work_struct *work)
/* Set new MAC filter */
enetc4_pf_set_mac_filter(pf, type);
+
+ rtnl_unlock();
}
^ permalink raw reply [flat|nested] 29+ messages in thread
end of thread, other threads:[~2025-04-21 3:14 UTC | newest]
Thread overview: 29+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-04-11 9:57 [PATCH v5 net-next 00/14] Add more features for ENETC v4 - round 2 Wei Fang
2025-04-11 9:57 ` [PATCH v5 net-next 01/14] net: enetc: add initial netc-lib driver to support NTMP Wei Fang
2025-04-18 12:49 ` Vladimir Oltean
2025-04-18 13:38 ` Wei Fang
2025-04-18 13:49 ` Vladimir Oltean
2025-04-11 9:57 ` [PATCH v5 net-next 02/14] net: enetc: add command BD ring support for i.MX95 ENETC Wei Fang
2025-04-18 13:25 ` Vladimir Oltean
2025-04-18 13:49 ` Wei Fang
2025-04-18 13:52 ` Vladimir Oltean
2025-04-11 9:57 ` [PATCH v5 net-next 03/14] net: enetc: move generic MAC filtering interfaces to enetc-core Wei Fang
2025-04-18 13:37 ` Vladimir Oltean
2025-04-11 9:57 ` [PATCH v5 net-next 04/14] net: enetc: add MAC filtering for i.MX95 ENETC PF Wei Fang
2025-04-16 3:42 ` Jakub Kicinski
2025-04-16 5:16 ` Wei Fang
2025-04-18 14:29 ` Vladimir Oltean
2025-04-18 15:41 ` Vladimir Oltean
2025-04-21 3:14 ` Wei Fang
2025-04-11 9:57 ` [PATCH v5 net-next 05/14] net: enetc: add debugfs interface to dump MAC filter Wei Fang
2025-04-11 9:57 ` [PATCH v5 net-next 06/14] net: enetc: add set/get_rss_table() hooks to enetc_si_ops Wei Fang
2025-04-15 13:43 ` Paolo Abeni
2025-04-16 2:31 ` Wei Fang
2025-04-11 9:57 ` [PATCH v5 net-next 07/14] net: enetc: make enetc_set_rss_key() reusable Wei Fang
2025-04-11 9:57 ` [PATCH v5 net-next 08/14] net: enetc: add RSS support for i.MX95 ENETC PF Wei Fang
2025-04-11 9:57 ` [PATCH v5 net-next 09/14] net: enetc: change enetc_set_rss() to void type Wei Fang
2025-04-11 9:57 ` [PATCH v5 net-next 10/14] net: enetc: enable RSS feature by default Wei Fang
2025-04-11 9:57 ` [PATCH v5 net-next 11/14] net: enetc: extract enetc_refresh_vlan_ht_filter() Wei Fang
2025-04-11 9:57 ` [PATCH v5 net-next 12/14] net: enetc: move generic VLAN hash filter functions to enetc_pf_common.c Wei Fang
2025-04-11 9:57 ` [PATCH v5 net-next 13/14] net: enetc: add VLAN filtering support for i.MX95 ENETC PF Wei Fang
2025-04-11 9:57 ` [PATCH v5 net-next 14/14] net: enetc: add loopback " Wei Fang
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).