* [PATCH 01/14] net/xsc: add FW version get support
2025-08-29 8:24 [PATCH 00/14] net/xsc: PMD updates Renyong Wan
@ 2025-08-29 8:24 ` Renyong Wan
2025-08-29 8:24 ` [PATCH 02/14] net/xsc: add TSO support Renyong Wan
` (12 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Renyong Wan @ 2025-08-29 8:24 UTC (permalink / raw)
To: dev; +Cc: thomas, stephen, qianr, nana, zhangxx, xudw, jacky, weihg, zhenghy
Add support for querying the firmware version of the xsc device.
Signed-off-by: Rong Qian <qianr@yunsilicon.com>
Signed-off-by: Renyong Wan <wanry@yunsilicon.com>
---
doc/guides/nics/features/xsc.ini | 1 +
drivers/net/xsc/xsc_dev.c | 13 +++++++++++++
drivers/net/xsc/xsc_dev.h | 4 ++++
drivers/net/xsc/xsc_ethdev.c | 9 +++++++++
drivers/net/xsc/xsc_vfio.c | 18 ++++++++++++++++++
5 files changed, 45 insertions(+)
diff --git a/doc/guides/nics/features/xsc.ini b/doc/guides/nics/features/xsc.ini
index 8d5c292b7f..e0f7b0bc1f 100644
--- a/doc/guides/nics/features/xsc.ini
+++ b/doc/guides/nics/features/xsc.ini
@@ -14,6 +14,7 @@ Inner L3 checksum = Y
Inner L4 checksum = Y
Basic stats = Y
Stats per queue = Y
+FW version = Y
Linux = Y
ARMv8 = Y
x86-64 = Y
diff --git a/drivers/net/xsc/xsc_dev.c b/drivers/net/xsc/xsc_dev.c
index fc9f1cddfc..66f98d2327 100644
--- a/drivers/net/xsc/xsc_dev.c
+++ b/drivers/net/xsc/xsc_dev.c
@@ -15,6 +15,7 @@
#include <rte_kvargs.h>
#include <rte_eal_paging.h>
#include <rte_bitops.h>
+#include <rte_string_fns.h>
#include "xsc_log.h"
#include "xsc_defs.h"
@@ -398,3 +399,15 @@ xsc_dev_is_vf(struct xsc_dev *xdev)
return false;
}
+
+int
+xsc_dev_fw_version_get(struct xsc_dev *xdev, char *fw_version, size_t fw_size)
+{
+ size_t size = strnlen(xdev->hwinfo.fw_ver, sizeof(xdev->hwinfo.fw_ver)) + 1;
+
+ if (fw_size < size)
+ return size;
+ rte_strlcpy(fw_version, xdev->hwinfo.fw_ver, fw_size);
+
+ return 0;
+}
diff --git a/drivers/net/xsc/xsc_dev.h b/drivers/net/xsc/xsc_dev.h
index cc5fa8aad8..274d6c6a2e 100644
--- a/drivers/net/xsc/xsc_dev.h
+++ b/drivers/net/xsc/xsc_dev.h
@@ -27,6 +27,8 @@
#define XSC_DEV_PCT_IDX_INVALID 0xFFFFFFFF
#define XSC_DEV_REPR_ID_INVALID 0x7FFFFFFF
+#define XSC_FW_VERS_LEN 64
+
enum xsc_queue_type {
XSC_QUEUE_TYPE_RDMA_RC = 0,
XSC_QUEUE_TYPE_RDMA_MAD = 1,
@@ -68,6 +70,7 @@ struct xsc_hwinfo {
uint8_t pct_compress_vld;
uint8_t mac_bit;
uint8_t esw_mode;
+ char fw_ver[XSC_FW_VERS_LEN];
};
struct xsc_devargs {
@@ -180,5 +183,6 @@ bool xsc_dev_is_vf(struct xsc_dev *xdev);
int xsc_dev_qp_set_id_get(struct xsc_dev *xdev, int repr_id);
int xsc_dev_set_mtu(struct xsc_dev *xdev, uint16_t mtu);
int xsc_dev_get_mac(struct xsc_dev *xdev, uint8_t *mac);
+int xsc_dev_fw_version_get(struct xsc_dev *xdev, char *fw_version, size_t fw_size);
#endif /* _XSC_DEV_H_ */
diff --git a/drivers/net/xsc/xsc_ethdev.c b/drivers/net/xsc/xsc_ethdev.c
index 3830c18c03..79c4e13cd4 100644
--- a/drivers/net/xsc/xsc_ethdev.c
+++ b/drivers/net/xsc/xsc_ethdev.c
@@ -674,6 +674,14 @@ xsc_ethdev_mac_addr_add(struct rte_eth_dev *dev, struct rte_ether_addr *mac, uin
return 0;
}
+static int
+xsc_ethdev_fw_version_get(struct rte_eth_dev *dev, char *fw_version, size_t fw_size)
+{
+ struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
+
+ return xsc_dev_fw_version_get(priv->xdev, fw_version, fw_size);
+}
+
const struct eth_dev_ops xsc_eth_dev_ops = {
.dev_configure = xsc_ethdev_configure,
.dev_start = xsc_ethdev_start,
@@ -692,6 +700,7 @@ const struct eth_dev_ops xsc_eth_dev_ops = {
.mtu_set = xsc_ethdev_set_mtu,
.rss_hash_update = xsc_ethdev_rss_hash_update,
.rss_hash_conf_get = xsc_ethdev_rss_hash_conf_get,
+ .fw_version_get = xsc_ethdev_fw_version_get,
};
static int
diff --git a/drivers/net/xsc/xsc_vfio.c b/drivers/net/xsc/xsc_vfio.c
index 422d30efb9..857fa449f0 100644
--- a/drivers/net/xsc/xsc_vfio.c
+++ b/drivers/net/xsc/xsc_vfio.c
@@ -61,6 +61,23 @@ xsc_vfio_pcie_no_init(struct xsc_hwinfo *hwinfo)
hwinfo->pcie_no = XSC_SOC_PCIE_NO_DEFAULT;
}
+static void
+xsc_vfio_fw_version_init(char *hw_fw_ver, struct xsc_cmd_fw_version *cmd_fw_ver)
+{
+ uint16_t patch = rte_be_to_cpu_16(cmd_fw_ver->patch);
+ uint32_t tweak = rte_be_to_cpu_32(cmd_fw_ver->tweak);
+
+ if (tweak == 0) {
+ snprintf(hw_fw_ver, XSC_FW_VERS_LEN, "v%hhu.%hhu.%hu",
+ cmd_fw_ver->major, cmd_fw_ver->minor,
+ patch);
+ } else {
+ snprintf(hw_fw_ver, XSC_FW_VERS_LEN, "v%hhu.%hhu.%hu+%u",
+ cmd_fw_ver->major, cmd_fw_ver->minor,
+ patch, tweak);
+ }
+}
+
static int
xsc_vfio_hwinfo_init(struct xsc_dev *xdev)
{
@@ -126,6 +143,7 @@ xsc_vfio_hwinfo_init(struct xsc_dev *xdev)
xdev->hwinfo.hca_core_clock = rte_be_to_cpu_32(hca_cap->hca_core_clock);
xdev->hwinfo.mac_bit = hca_cap->mac_bit;
xsc_vfio_pcie_no_init(&xdev->hwinfo);
+ xsc_vfio_fw_version_init(xdev->hwinfo.fw_ver, &hca_cap->fw_ver);
exit:
free(cmd_buf);
--
2.25.1
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 02/14] net/xsc: add TSO support
2025-08-29 8:24 [PATCH 00/14] net/xsc: PMD updates Renyong Wan
2025-08-29 8:24 ` [PATCH 01/14] net/xsc: add FW version get support Renyong Wan
@ 2025-08-29 8:24 ` Renyong Wan
2025-08-29 8:24 ` [PATCH 03/14] net/xsc: support module EEPROM dump Renyong Wan
` (11 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Renyong Wan @ 2025-08-29 8:24 UTC (permalink / raw)
To: dev; +Cc: thomas, stephen, qianr, nana, zhangxx, xudw, jacky, weihg, zhenghy
Introduce TCP segmentation offload (TSO) support for xsc PMD.
Signed-off-by: Rong Qian <qianr@yunsilicon.com>
Signed-off-by: Renyong Wan <wanry@yunsilicon.com>
---
doc/guides/nics/features/xsc.ini | 1 +
drivers/net/xsc/xsc_ethdev.c | 3 +--
drivers/net/xsc/xsc_tx.c | 12 +++++++-----
drivers/net/xsc/xsc_tx.h | 3 +--
drivers/net/xsc/xsc_vfio.c | 4 +++-
5 files changed, 13 insertions(+), 10 deletions(-)
diff --git a/doc/guides/nics/features/xsc.ini b/doc/guides/nics/features/xsc.ini
index e0f7b0bc1f..3b02289764 100644
--- a/doc/guides/nics/features/xsc.ini
+++ b/doc/guides/nics/features/xsc.ini
@@ -5,6 +5,7 @@
;
[Features]
MTU update = Y
+TSO = Y
RSS hash = Y
RSS key update = Y
RSS reta update = Y
diff --git a/drivers/net/xsc/xsc_ethdev.c b/drivers/net/xsc/xsc_ethdev.c
index 79c4e13cd4..9a70be0543 100644
--- a/drivers/net/xsc/xsc_ethdev.c
+++ b/drivers/net/xsc/xsc_ethdev.c
@@ -223,7 +223,6 @@ xsc_txq_start(struct xsc_ethdev_priv *priv)
{
struct xsc_txq_data *txq_data;
struct rte_eth_dev *dev = priv->eth_dev;
- uint64_t offloads = dev->data->dev_conf.txmode.offloads;
uint16_t i;
int ret;
size_t size;
@@ -239,7 +238,7 @@ xsc_txq_start(struct xsc_ethdev_priv *priv)
if (txq_data == NULL)
goto error;
xsc_txq_elts_alloc(txq_data);
- ret = xsc_txq_obj_new(priv->xdev, txq_data, offloads, i);
+ ret = xsc_txq_obj_new(priv->xdev, txq_data, i);
if (ret < 0)
goto error;
dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
diff --git a/drivers/net/xsc/xsc_tx.c b/drivers/net/xsc/xsc_tx.c
index d1a0f3284b..07888a5641 100644
--- a/drivers/net/xsc/xsc_tx.c
+++ b/drivers/net/xsc/xsc_tx.c
@@ -26,8 +26,7 @@ xsc_txq_elts_alloc(struct xsc_txq_data *txq_data)
}
int
-xsc_txq_obj_new(struct xsc_dev *xdev, struct xsc_txq_data *txq_data,
- uint64_t offloads, uint16_t idx)
+xsc_txq_obj_new(struct xsc_dev *xdev, struct xsc_txq_data *txq_data, uint16_t idx)
{
int ret = 0;
struct xsc_tx_cq_params cq_params = {0};
@@ -57,7 +56,7 @@ xsc_txq_obj_new(struct xsc_dev *xdev, struct xsc_txq_data *txq_data,
txq_data->cq_db, txq_data->cqn);
qp_params.cq = txq_data->cq;
- qp_params.tx_offloads = offloads;
+ qp_params.tx_offloads = txq_data->offloads;
qp_params.port_id = txq_data->port_id;
qp_params.qp_id = idx;
qp_params.elts_n = txq_data->elts_n;
@@ -76,6 +75,7 @@ xsc_txq_obj_new(struct xsc_dev *xdev, struct xsc_txq_data *txq_data,
txq_data->wqe_m = txq_data->wqe_s - 1;
txq_data->wqe_ds_n = rte_log2_u32(xdev->hwinfo.send_seg_num);
txq_data->qp_db = qp_info.qp_db;
+ txq_data->tso_en = qp_info.tso_en ? 1 : 0;
txq_data->cq_ci = 0;
txq_data->cq_pi = 0;
@@ -83,9 +83,11 @@ xsc_txq_obj_new(struct xsc_dev *xdev, struct xsc_txq_data *txq_data,
txq_data->wqe_pi = 0;
txq_data->wqe_comp = 0;
- PMD_DRV_LOG(INFO, "Create tx qp, wqe_s:%d, wqe_n:%d, qp_db=%p, qpn:%u",
+ PMD_DRV_LOG(INFO, "Create tx qp, wqe_s:%d, wqe_n:%d, qp_db=%p, qpn:%u, %s",
txq_data->wqe_s, txq_data->wqe_n,
- txq_data->qp_db, txq_data->qpn);
+ txq_data->qp_db, txq_data->qpn,
+ txq_data->tso_en ? "tso" : "non-tso");
+
return 0;
error:
diff --git a/drivers/net/xsc/xsc_tx.h b/drivers/net/xsc/xsc_tx.h
index 88419dd3a0..a6a034a8ea 100644
--- a/drivers/net/xsc/xsc_tx.h
+++ b/drivers/net/xsc/xsc_tx.h
@@ -53,8 +53,7 @@ struct __rte_cache_aligned xsc_txq_data {
};
uint16_t xsc_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n);
-int xsc_txq_obj_new(struct xsc_dev *xdev, struct xsc_txq_data *txq_data,
- uint64_t offloads, uint16_t idx);
+int xsc_txq_obj_new(struct xsc_dev *xdev, struct xsc_txq_data *txq_data, uint16_t idx);
void xsc_txq_elts_alloc(struct xsc_txq_data *txq_data);
void xsc_txq_obj_release(struct xsc_dev *xdev, struct xsc_txq_data *txq_data);
void xsc_txq_elts_free(struct xsc_txq_data *txq_data);
diff --git a/drivers/net/xsc/xsc_vfio.c b/drivers/net/xsc/xsc_vfio.c
index 857fa449f0..f61cf92569 100644
--- a/drivers/net/xsc/xsc_vfio.c
+++ b/drivers/net/xsc/xsc_vfio.c
@@ -649,6 +649,7 @@ xsc_vfio_tx_qp_create(struct xsc_dev *xdev, struct xsc_tx_qp_params *qp_params,
uint64_t iova;
char name[RTE_ETH_NAME_MAX_LEN] = {0};
void *cmd_buf = NULL;
+ bool tso_en = !!(qp_params->tx_offloads & RTE_ETH_TX_OFFLOAD_TCP_TSO);
qp = rte_zmalloc(NULL, sizeof(struct xsc_vfio_qp), 0);
if (qp == NULL) {
@@ -689,7 +690,7 @@ xsc_vfio_tx_qp_create(struct xsc_dev *xdev, struct xsc_tx_qp_params *qp_params,
in->hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_CREATE_QP);
in->req.input_qpn = 0;
in->req.pa_num = rte_cpu_to_be_16(pa_num);
- in->req.qp_type = XSC_QUEUE_TYPE_RAW_TX;
+ in->req.qp_type = tso_en ? XSC_QUEUE_TYPE_RAW_TSO : XSC_QUEUE_TYPE_RAW_TX;
in->req.log_sq_sz = log_sq_sz;
in->req.log_rq_sz = log_rq_sz;
in->req.dma_direct = 0;
@@ -717,6 +718,7 @@ xsc_vfio_tx_qp_create(struct xsc_dev *xdev, struct xsc_tx_qp_params *qp_params,
qp_info->qpn = qp->qpn;
qp_info->wqes = (struct xsc_wqe *)qp->mz->addr;
qp_info->wqe_n = rte_log2_u32(wqe_s);
+ qp_info->tso_en = tso_en ? 1 : 0;
if (xsc_dev_is_vf(xdev))
qp_info->qp_db = (uint32_t *)((uint8_t *)xdev->bar_addr + XSC_VF_TX_DB_ADDR);
--
2.25.1
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 03/14] net/xsc: support module EEPROM dump
2025-08-29 8:24 [PATCH 00/14] net/xsc: PMD updates Renyong Wan
2025-08-29 8:24 ` [PATCH 01/14] net/xsc: add FW version get support Renyong Wan
2025-08-29 8:24 ` [PATCH 02/14] net/xsc: add TSO support Renyong Wan
@ 2025-08-29 8:24 ` Renyong Wan
2025-08-29 8:24 ` [PATCH 04/14] net/xsc: support promiscuous mode Renyong Wan
` (10 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Renyong Wan @ 2025-08-29 8:24 UTC (permalink / raw)
To: dev; +Cc: thomas, stephen, qianr, nana, zhangxx, xudw, jacky, weihg, zhenghy
Add support for querying and reading the EEPROM of SFP/QSFP modules.
Signed-off-by: Rong Qian <qianr@yunsilicon.com>
Signed-off-by: Renyong Wan <wanry@yunsilicon.com>
---
doc/guides/nics/features/xsc.ini | 1 +
drivers/net/xsc/xsc_cmd.h | 15 +++
drivers/net/xsc/xsc_dev.c | 185 +++++++++++++++++++++++++++++++
drivers/net/xsc/xsc_dev.h | 63 +++++++++++
drivers/net/xsc/xsc_ethdev.c | 107 ++++++++++++++++++
5 files changed, 371 insertions(+)
diff --git a/doc/guides/nics/features/xsc.ini b/doc/guides/nics/features/xsc.ini
index 3b02289764..46c56fc921 100644
--- a/doc/guides/nics/features/xsc.ini
+++ b/doc/guides/nics/features/xsc.ini
@@ -16,6 +16,7 @@ Inner L4 checksum = Y
Basic stats = Y
Stats per queue = Y
FW version = Y
+Module EEPROM dump = Y
Linux = Y
ARMv8 = Y
x86-64 = Y
diff --git a/drivers/net/xsc/xsc_cmd.h b/drivers/net/xsc/xsc_cmd.h
index 433dcd0afa..82244d4011 100644
--- a/drivers/net/xsc/xsc_cmd.h
+++ b/drivers/net/xsc/xsc_cmd.h
@@ -23,6 +23,7 @@ enum xsc_cmd_opcode {
XSC_CMD_OP_RTR2RTS_QP = 0x504,
XSC_CMD_OP_QP_2RST = 0x50A,
XSC_CMD_OP_CREATE_MULTI_QP = 0x515,
+ XSC_CMD_OP_ACCESS_REG = 0x805,
XSC_CMD_OP_MODIFY_NIC_HCA = 0x812,
XSC_CMD_OP_MODIFY_RAW_QP = 0x81f,
XSC_CMD_OP_EXEC_NP = 0x900,
@@ -384,4 +385,18 @@ struct xsc_cmd_modify_nic_hca_mbox_out {
uint8_t rsvd[4];
};
+struct xsc_cmd_access_reg_mbox_in {
+ struct xsc_cmd_inbox_hdr hdr;
+ uint8_t rsvd0[2];
+ rte_be16_t register_id;
+ rte_be32_t arg;
+ rte_be32_t data[];
+};
+
+struct xsc_cmd_access_reg_mbox_out {
+ struct xsc_cmd_outbox_hdr hdr;
+ uint8_t rsvd[8];
+ rte_be32_t data[];
+};
+
#endif /* _XSC_CMD_H_ */
diff --git a/drivers/net/xsc/xsc_dev.c b/drivers/net/xsc/xsc_dev.c
index 66f98d2327..2c55306d35 100644
--- a/drivers/net/xsc/xsc_dev.c
+++ b/drivers/net/xsc/xsc_dev.c
@@ -411,3 +411,188 @@ xsc_dev_fw_version_get(struct xsc_dev *xdev, char *fw_version, size_t fw_size)
return 0;
}
+
+static int
+xsc_dev_access_reg(struct xsc_dev *xdev, void *data_in, int size_in,
+ void *data_out, int size_out, uint16_t reg_num)
+{
+ struct xsc_cmd_access_reg_mbox_in *in;
+ struct xsc_cmd_access_reg_mbox_out *out;
+ int ret = -1;
+
+ in = malloc(sizeof(*in) + size_in);
+ if (in == NULL) {
+ rte_errno = ENOMEM;
+ PMD_DRV_LOG(ERR, "Failed to malloc access reg mbox in memory");
+ return -rte_errno;
+ }
+ memset(in, 0, sizeof(*in) + size_in);
+
+ out = malloc(sizeof(*out) + size_out);
+ if (out == NULL) {
+ rte_errno = ENOMEM;
+ PMD_DRV_LOG(ERR, "Failed to malloc access reg mbox out memory");
+ goto alloc_out_fail;
+ }
+ memset(out, 0, sizeof(*out) + size_out);
+
+ memcpy(in->data, data_in, size_in);
+ in->hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_ACCESS_REG);
+ in->arg = 0;
+ in->register_id = rte_cpu_to_be_16(reg_num);
+
+ ret = xsc_dev_mailbox_exec(xdev, in, sizeof(*in) + size_in, out,
+ sizeof(*out) + size_out);
+ if (ret != 0 || out->hdr.status != 0) {
+ rte_errno = ENOEXEC;
+ PMD_DRV_LOG(ERR, "Failed to access reg");
+ goto exit;
+ }
+
+ memcpy(data_out, out->data, size_out);
+
+exit:
+ free(out);
+
+alloc_out_fail:
+ free(in);
+ return ret;
+}
+
+static int
+xsc_dev_query_mcia(struct xsc_dev *xdev,
+ struct xsc_module_eeprom_query_params *params,
+ uint8_t *data)
+{
+ struct xsc_dev_reg_mcia in = { };
+ struct xsc_dev_reg_mcia out = { };
+ int ret;
+ void *ptr;
+ uint16_t size;
+
+ size = RTE_MIN(params->size, XSC_EEPROM_MAX_BYTES);
+ in.i2c_device_address = params->i2c_address;
+ in.module = params->module_number & 0x000000FF;
+ in.device_address = params->offset;
+ in.page_number = params->page;
+ in.size = size;
+
+ ret = xsc_dev_access_reg(xdev, &in, sizeof(in), &out, sizeof(out), XSC_REG_MCIA);
+ if (ret != 0)
+ return ret;
+
+ ptr = out.dword_0;
+ memcpy(data, ptr, size);
+
+ return size;
+}
+
+static void
+xsc_dev_sfp_eeprom_params_set(uint16_t *i2c_addr, uint32_t *page_num, uint16_t *offset)
+{
+ *i2c_addr = XSC_I2C_ADDR_LOW;
+ *page_num = 0;
+
+ if (*offset < XSC_EEPROM_PAGE_LENGTH)
+ return;
+
+ *i2c_addr = XSC_I2C_ADDR_HIGH;
+ *offset -= XSC_EEPROM_PAGE_LENGTH;
+}
+
+static int
+xsc_dev_qsfp_eeprom_page(uint16_t offset)
+{
+ if (offset < XSC_EEPROM_PAGE_LENGTH)
+ /* Addresses between 0-255 - page 00 */
+ return 0;
+
+ /*
+ * Addresses between 256 - 639 belongs to pages 01, 02 and 03
+ * For example, offset = 400 belongs to page 02:
+ * 1 + ((400 - 256)/128) = 2
+ */
+ return 1 + ((offset - XSC_EEPROM_PAGE_LENGTH) / XSC_EEPROM_HIGH_PAGE_LENGTH);
+}
+
+static int
+xsc_dev_qsfp_eeprom_high_page_offset(int page_num)
+{
+ /* Page 0 always start from low page */
+ if (!page_num)
+ return 0;
+
+ /* High page */
+ return page_num * XSC_EEPROM_HIGH_PAGE_LENGTH;
+}
+
+static void
+xsc_dev_qsfp_eeprom_params_set(uint16_t *i2c_addr, uint32_t *page_num, uint16_t *offset)
+{
+ *i2c_addr = XSC_I2C_ADDR_LOW;
+ *page_num = xsc_dev_qsfp_eeprom_page(*offset);
+ *offset -= xsc_dev_qsfp_eeprom_high_page_offset(*page_num);
+}
+
+static int
+xsc_dev_query_module_id(struct xsc_dev *xdev, uint32_t module_num, uint8_t *module_id)
+{
+ struct xsc_dev_reg_mcia in = { 0 };
+ struct xsc_dev_reg_mcia out = { 0 };
+ int ret;
+ uint8_t *ptr;
+
+ in.i2c_device_address = XSC_I2C_ADDR_LOW;
+ in.module = module_num & 0x000000FF;
+ in.device_address = 0;
+ in.page_number = 0;
+ in.size = 1;
+
+ ret = xsc_dev_access_reg(xdev, &in, sizeof(in), &out, sizeof(out), XSC_REG_MCIA);
+ if (ret != 0)
+ return ret;
+
+ ptr = out.dword_0;
+ *module_id = ptr[0];
+ return 0;
+}
+
+int
+xsc_dev_query_module_eeprom(struct xsc_dev *xdev, uint16_t offset,
+ uint16_t size, uint8_t *data)
+{
+ struct xsc_module_eeprom_query_params query = { 0 };
+ uint8_t module_id;
+ int ret;
+
+ query.module_number = xdev->hwinfo.mac_phy_port;
+ ret = xsc_dev_query_module_id(xdev, query.module_number, &module_id);
+ if (ret != 0)
+ return ret;
+
+ switch (module_id) {
+ case XSC_MODULE_ID_SFP:
+ xsc_dev_sfp_eeprom_params_set(&query.i2c_address, &query.page, &offset);
+ break;
+ case XSC_MODULE_ID_QSFP:
+ case XSC_MODULE_ID_QSFP_PLUS:
+ case XSC_MODULE_ID_QSFP28:
+ case XSC_MODULE_ID_QSFP_DD:
+ case XSC_MODULE_ID_DSFP:
+ case XSC_MODULE_ID_QSFP_PLUS_CMIS:
+ xsc_dev_qsfp_eeprom_params_set(&query.i2c_address, &query.page, &offset);
+ break;
+ default:
+ PMD_DRV_LOG(ERR, "Module ID not recognized: 0x%x", module_id);
+ return -EINVAL;
+ }
+
+ if (offset + size > XSC_EEPROM_PAGE_LENGTH)
+ /* Cross pages read, read until offset 256 in low page */
+ size = XSC_EEPROM_PAGE_LENGTH - offset;
+
+ query.size = size;
+ query.offset = offset;
+
+ return xsc_dev_query_mcia(xdev, &query, data);
+}
diff --git a/drivers/net/xsc/xsc_dev.h b/drivers/net/xsc/xsc_dev.h
index 274d6c6a2e..5cf19aaf3d 100644
--- a/drivers/net/xsc/xsc_dev.h
+++ b/drivers/net/xsc/xsc_dev.h
@@ -28,6 +28,12 @@
#define XSC_DEV_REPR_ID_INVALID 0x7FFFFFFF
#define XSC_FW_VERS_LEN 64
+#define XSC_DWORD_LEN 0x20
+#define XSC_I2C_ADDR_LOW 0x50
+#define XSC_I2C_ADDR_HIGH 0x51
+#define XSC_EEPROM_PAGE_LENGTH 256
+#define XSC_EEPROM_HIGH_PAGE_LENGTH 128
+#define XSC_EEPROM_MAX_BYTES 32
enum xsc_queue_type {
XSC_QUEUE_TYPE_RDMA_RC = 0,
@@ -41,6 +47,31 @@ enum xsc_queue_type {
XSC_QUEUE_TYPE_INVALID = 0xFF,
};
+enum xsc_reg_type {
+ XSC_REG_PMLP = 0x0,
+ XSC_REG_PCAP = 0x5001,
+ XSC_REG_PMTU = 0x5003,
+ XSC_REG_PTYS = 0x5004,
+ XSC_REG_PAOS = 0x5006,
+ XSC_REG_PMAOS = 0x5012,
+ XSC_REG_PUDE = 0x5009,
+ XSC_REG_PMPE = 0x5010,
+ XSC_REG_PELC = 0x500e,
+ XSC_REG_NODE_DESC = 0x6001,
+ XSC_REG_HOST_ENDIANNESS = 0x7004,
+ XSC_REG_MCIA = 0x9014,
+};
+
+enum xsc_module_id {
+ XSC_MODULE_ID_SFP = 0x3,
+ XSC_MODULE_ID_QSFP = 0xC,
+ XSC_MODULE_ID_QSFP_PLUS = 0xD,
+ XSC_MODULE_ID_QSFP28 = 0x11,
+ XSC_MODULE_ID_QSFP_DD = 0x18,
+ XSC_MODULE_ID_DSFP = 0x1B,
+ XSC_MODULE_ID_QSFP_PLUS_CMIS = 0x1E,
+};
+
struct xsc_hwinfo {
uint32_t pcie_no; /* pcie number , 0 or 1 */
uint32_t func_id; /* pf glb func id */
@@ -132,6 +163,36 @@ struct xsc_dev {
int ctrl_fd;
};
+struct xsc_module_eeprom_query_params {
+ uint16_t size;
+ uint16_t offset;
+ uint16_t i2c_address;
+ uint32_t page;
+ uint32_t bank;
+ uint32_t module_number;
+};
+
+struct xsc_dev_reg_mcia {
+ uint8_t module;
+ uint8_t status;
+ uint8_t i2c_device_address;
+ uint8_t page_number;
+ uint8_t device_address;
+ uint8_t size;
+ uint8_t dword_0[XSC_DWORD_LEN];
+ uint8_t dword_1[XSC_DWORD_LEN];
+ uint8_t dword_2[XSC_DWORD_LEN];
+ uint8_t dword_3[XSC_DWORD_LEN];
+ uint8_t dword_4[XSC_DWORD_LEN];
+ uint8_t dword_5[XSC_DWORD_LEN];
+ uint8_t dword_6[XSC_DWORD_LEN];
+ uint8_t dword_7[XSC_DWORD_LEN];
+ uint8_t dword_8[XSC_DWORD_LEN];
+ uint8_t dword_9[XSC_DWORD_LEN];
+ uint8_t dword_10[XSC_DWORD_LEN];
+ uint8_t dword_11[XSC_DWORD_LEN];
+};
+
struct xsc_dev_ops {
TAILQ_ENTRY(xsc_dev_ops) entry;
enum rte_pci_kernel_driver kdrv;
@@ -184,5 +245,7 @@ int xsc_dev_qp_set_id_get(struct xsc_dev *xdev, int repr_id);
int xsc_dev_set_mtu(struct xsc_dev *xdev, uint16_t mtu);
int xsc_dev_get_mac(struct xsc_dev *xdev, uint8_t *mac);
int xsc_dev_fw_version_get(struct xsc_dev *xdev, char *fw_version, size_t fw_size);
+int xsc_dev_query_module_eeprom(struct xsc_dev *xdev, uint16_t offset,
+ uint16_t size, uint8_t *data);
#endif /* _XSC_DEV_H_ */
diff --git a/drivers/net/xsc/xsc_ethdev.c b/drivers/net/xsc/xsc_ethdev.c
index 9a70be0543..ffcf04a90c 100644
--- a/drivers/net/xsc/xsc_ethdev.c
+++ b/drivers/net/xsc/xsc_ethdev.c
@@ -2,6 +2,7 @@
* Copyright 2025 Yunsilicon Technology Co., Ltd.
*/
+#include <rte_dev_info.h>
#include <ethdev_pci.h>
#include "xsc_log.h"
@@ -681,6 +682,110 @@ xsc_ethdev_fw_version_get(struct rte_eth_dev *dev, char *fw_version, size_t fw_s
return xsc_dev_fw_version_get(priv->xdev, fw_version, fw_size);
}
+static int
+xsc_ethdev_get_module_info(struct rte_eth_dev *dev,
+ struct rte_eth_dev_module_info *modinfo)
+{
+ int size_read = 0;
+ uint8_t data[4] = { 0 };
+ struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
+
+ size_read = xsc_dev_query_module_eeprom(priv->xdev, 0, 3, data);
+ if (size_read < 3)
+ return -1;
+
+ /* data[0] = identifier byte */
+ switch (data[0]) {
+ case XSC_MODULE_ID_QSFP:
+ modinfo->type = RTE_ETH_MODULE_SFF_8436;
+ modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8436_MAX_LEN;
+ break;
+ case XSC_MODULE_ID_QSFP_PLUS:
+ case XSC_MODULE_ID_QSFP28:
+ /* data[1] = revision id */
+ if (data[0] == XSC_MODULE_ID_QSFP28 || data[1] >= 0x3) {
+ modinfo->type = RTE_ETH_MODULE_SFF_8636;
+ modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8636_MAX_LEN;
+ } else {
+ modinfo->type = RTE_ETH_MODULE_SFF_8436;
+ modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8436_MAX_LEN;
+ }
+ break;
+ case XSC_MODULE_ID_SFP:
+ modinfo->type = RTE_ETH_MODULE_SFF_8472;
+ modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8472_LEN;
+ break;
+ case XSC_MODULE_ID_QSFP_DD:
+ case XSC_MODULE_ID_DSFP:
+ case XSC_MODULE_ID_QSFP_PLUS_CMIS:
+ modinfo->type = RTE_ETH_MODULE_SFF_8636;
+ /* Verify if module EEPROM is a flat memory. In case of flat
+ * memory only page 00h (0-255 bytes) can be read. Otherwise
+ * upper pages 01h and 02h can also be read. Upper pages 10h
+ * and 11h are currently not supported by the driver.
+ */
+ if (data[2] & 0x80)
+ modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8636_LEN;
+ else
+ modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8472_LEN;
+ break;
+ default:
+ PMD_DRV_LOG(ERR, "Cable type 0x%x not recognized",
+ data[0]);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int
+xsc_ethdev_get_module_eeprom(struct rte_eth_dev *dev,
+ struct rte_dev_eeprom_info *info)
+{
+ uint32_t i = 0;
+ uint8_t *data;
+ int size_read;
+ uint32_t offset = info->offset;
+ struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
+
+ if (info->length == 0) {
+ PMD_DRV_LOG(ERR, "Failed to get module eeprom, eeprom length is 0");
+ rte_errno = EINVAL;
+ return -rte_errno;
+ }
+
+ data = malloc(info->length);
+ if (data == NULL) {
+ PMD_DRV_LOG(ERR, "Failed to get module eeprom, cannot allocate memory");
+ rte_errno = ENOMEM;
+ return -rte_errno;
+ }
+ memset(data, 0, info->length);
+
+ while (i < info->length) {
+ size_read = xsc_dev_query_module_eeprom(priv->xdev, offset,
+ info->length - i, data + i);
+ if (!size_read)
+ /* Done reading */
+ goto exit;
+
+ if (size_read < 0) {
+ PMD_DRV_LOG(ERR, "Failed to get module eeprom, size read=%d",
+ size_read);
+ goto exit;
+ }
+
+ i += size_read;
+ offset += size_read;
+ }
+
+ memcpy(info->data, data, info->length);
+
+exit:
+ free(data);
+ return 0;
+}
+
const struct eth_dev_ops xsc_eth_dev_ops = {
.dev_configure = xsc_ethdev_configure,
.dev_start = xsc_ethdev_start,
@@ -700,6 +805,8 @@ const struct eth_dev_ops xsc_eth_dev_ops = {
.rss_hash_update = xsc_ethdev_rss_hash_update,
.rss_hash_conf_get = xsc_ethdev_rss_hash_conf_get,
.fw_version_get = xsc_ethdev_fw_version_get,
+ .get_module_info = xsc_ethdev_get_module_info,
+ .get_module_eeprom = xsc_ethdev_get_module_eeprom,
};
static int
--
2.25.1
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 04/14] net/xsc: support promiscuous mode
2025-08-29 8:24 [PATCH 00/14] net/xsc: PMD updates Renyong Wan
` (2 preceding siblings ...)
2025-08-29 8:24 ` [PATCH 03/14] net/xsc: support module EEPROM dump Renyong Wan
@ 2025-08-29 8:24 ` Renyong Wan
2025-08-29 8:24 ` [PATCH 05/14] net/xsc: add link status support Renyong Wan
` (9 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Renyong Wan @ 2025-08-29 8:24 UTC (permalink / raw)
To: dev; +Cc: thomas, stephen, qianr, nana, zhangxx, xudw, jacky, weihg, zhenghy
Add support for enabling and disabling promiscuous mode on XSC NIC ports.
Signed-off-by: Rong Qian <qianr@yunsilicon.com>
Signed-off-by: Renyong Wan <wanry@yunsilicon.com>
---
doc/guides/nics/features/xsc.ini | 1 +
drivers/net/xsc/xsc_defs.h | 1 +
drivers/net/xsc/xsc_ethdev.c | 58 ++++++++++++++++++++++++++++++--
drivers/net/xsc/xsc_np.c | 28 +++++++++++++--
drivers/net/xsc/xsc_np.h | 24 ++++++++-----
5 files changed, 99 insertions(+), 13 deletions(-)
diff --git a/doc/guides/nics/features/xsc.ini b/doc/guides/nics/features/xsc.ini
index 46c56fc921..dfbfc88dbc 100644
--- a/doc/guides/nics/features/xsc.ini
+++ b/doc/guides/nics/features/xsc.ini
@@ -6,6 +6,7 @@
[Features]
MTU update = Y
TSO = Y
+Promiscuous mode = Y
RSS hash = Y
RSS key update = Y
RSS reta update = Y
diff --git a/drivers/net/xsc/xsc_defs.h b/drivers/net/xsc/xsc_defs.h
index 6497b53e1e..5b4e5b80d2 100644
--- a/drivers/net/xsc/xsc_defs.h
+++ b/drivers/net/xsc/xsc_defs.h
@@ -37,6 +37,7 @@
#define XSC_EPAT_RSS_HASH_TEMPLATE_FLAG (1ULL << 5)
#define XSC_EPAT_RSS_HASH_FUNC_FLAG (1ULL << 6)
#define XSC_EPAT_HAS_PPH_FLAG (1ULL << 9)
+#define XSC_EPAT_MAC_FILTER_EN_FLAG (1ULL << 15)
#define XSC_MAX_DESC_NUMBER 1024
#define XSC_SEND_WQE_DS 3
diff --git a/drivers/net/xsc/xsc_ethdev.c b/drivers/net/xsc/xsc_ethdev.c
index ffcf04a90c..efe1ad72f6 100644
--- a/drivers/net/xsc/xsc_ethdev.c
+++ b/drivers/net/xsc/xsc_ethdev.c
@@ -144,6 +144,7 @@ xsc_ethdev_enable(struct rte_eth_dev *dev)
struct xsc_txq_data *txq;
struct xsc_repr_port *repr;
struct xsc_repr_info *repr_info;
+ uint8_t mac_filter_en = !dev->data->promiscuous;
if (priv->funcid_type != XSC_PHYPORT_MAC_FUNCID)
return -ENODEV;
@@ -180,7 +181,8 @@ xsc_ethdev_enable(struct rte_eth_dev *dev)
xsc_dev_create_vfos_baselp(priv->xdev);
xsc_dev_create_epat(priv->xdev, local_dstinfo, pcie_logic_port,
rx_qpn - hwinfo->raw_rss_qp_id_base,
- priv->num_rq, &priv->rss_conf);
+ priv->num_rq, &priv->rss_conf,
+ mac_filter_en, priv->mac[0].addr_bytes);
xsc_dev_create_pct(priv->xdev, repr_id, logical_port, peer_dstinfo);
xsc_dev_create_pct(priv->xdev, repr_id, peer_logicalport, local_dstinfo);
} else {
@@ -189,7 +191,8 @@ xsc_ethdev_enable(struct rte_eth_dev *dev)
xsc_dev_create_ipat(priv->xdev, logical_port, peer_dstinfo);
xsc_dev_vf_modify_epat(priv->xdev, local_dstinfo,
rx_qpn - hwinfo->raw_rss_qp_id_base,
- priv->num_rq, &priv->rss_conf);
+ priv->num_rq, &priv->rss_conf,
+ mac_filter_en, priv->mac[0].addr_bytes);
}
return 0;
@@ -674,6 +677,55 @@ xsc_ethdev_mac_addr_add(struct rte_eth_dev *dev, struct rte_ether_addr *mac, uin
return 0;
}
+static int
+xsc_set_promiscuous(struct rte_eth_dev *dev, uint8_t mac_filter_en)
+{
+ int repr_id;
+ struct xsc_repr_port *repr;
+ struct xsc_repr_info *repr_info;
+ struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
+
+ repr_id = priv->representor_id;
+ repr = &priv->xdev->repr_ports[repr_id];
+ repr_info = &repr->info;
+
+ return xsc_dev_modify_epat_mac_filter(priv->xdev,
+ repr_info->local_dstinfo,
+ mac_filter_en);
+}
+
+static int
+xsc_ethdev_promiscuous_enable(struct rte_eth_dev *dev)
+{
+ int ret;
+
+ ret = xsc_set_promiscuous(dev, 0);
+ if (ret != 0) {
+ PMD_DRV_LOG(ERR, "Enable port %u promiscuous failure",
+ dev->data->port_id);
+ return ret;
+ }
+
+ dev->data->promiscuous = 1;
+ return 0;
+}
+
+static int
+xsc_ethdev_promiscuous_disable(struct rte_eth_dev *dev)
+{
+ int ret;
+
+ ret = xsc_set_promiscuous(dev, 1);
+ if (ret != 0) {
+ PMD_DRV_LOG(ERR, "Disable port %u promiscuous failure",
+ dev->data->port_id);
+ return ret;
+ }
+
+ dev->data->promiscuous = 0;
+ return 0;
+}
+
static int
xsc_ethdev_fw_version_get(struct rte_eth_dev *dev, char *fw_version, size_t fw_size)
{
@@ -794,6 +846,8 @@ const struct eth_dev_ops xsc_eth_dev_ops = {
.dev_set_link_down = xsc_ethdev_set_link_down,
.dev_close = xsc_ethdev_close,
.link_update = xsc_ethdev_link_update,
+ .promiscuous_enable = xsc_ethdev_promiscuous_enable,
+ .promiscuous_disable = xsc_ethdev_promiscuous_disable,
.stats_get = xsc_ethdev_stats_get,
.stats_reset = xsc_ethdev_stats_reset,
.dev_infos_get = xsc_ethdev_infos_get,
diff --git a/drivers/net/xsc/xsc_np.c b/drivers/net/xsc/xsc_np.c
index 543e6dba95..2b85fd93f8 100644
--- a/drivers/net/xsc/xsc_np.c
+++ b/drivers/net/xsc/xsc_np.c
@@ -292,8 +292,11 @@ xsc_dev_destroy_ipat(struct xsc_dev *xdev, uint16_t logic_in_port)
int
xsc_dev_create_epat(struct xsc_dev *xdev, uint16_t dst_info, uint8_t dst_port,
- uint16_t qpn_ofst, uint8_t qp_num, struct rte_eth_rss_conf *rss_conf)
+ uint16_t qpn_ofst, uint8_t qp_num,
+ struct rte_eth_rss_conf *rss_conf,
+ uint8_t mac_filter_en, uint8_t *mac)
{
+ int i;
struct xsc_np_epat_add add;
memset(&add, 0, sizeof(add));
@@ -305,14 +308,19 @@ xsc_dev_create_epat(struct xsc_dev *xdev, uint16_t dst_info, uint8_t dst_port,
add.action.rss_en = 1;
add.action.rss_hash_func = XSC_RSS_HASH_FUNC_TOPELIZ;
add.action.rss_hash_template = xsc_rss_hash_template_get(rss_conf);
+ add.action.mac_filter_en = mac_filter_en;
+ for (i = 0; i < RTE_ETHER_ADDR_LEN; i++)
+ add.action.mac_addr[i] = mac[RTE_ETHER_ADDR_LEN - i - 1];
return xsc_dev_np_exec(xdev, &add, sizeof(add), XSC_NP_EPAT, XSC_NP_OP_ADD);
}
int
xsc_dev_vf_modify_epat(struct xsc_dev *xdev, uint16_t dst_info, uint16_t qpn_ofst,
- uint8_t qp_num, struct rte_eth_rss_conf *rss_conf)
+ uint8_t qp_num, struct rte_eth_rss_conf *rss_conf,
+ uint8_t mac_filter_en, uint8_t *mac)
{
+ int i;
struct xsc_np_epat_mod mod;
memset(&mod, 0, sizeof(mod));
@@ -328,6 +336,22 @@ xsc_dev_vf_modify_epat(struct xsc_dev *xdev, uint16_t dst_info, uint16_t qpn_ofs
mod.action.rss_en = 1;
mod.action.rss_hash_func = XSC_RSS_HASH_FUNC_TOPELIZ;
mod.action.rss_hash_template = xsc_rss_hash_template_get(rss_conf);
+ mod.action.mac_filter_en = mac_filter_en;
+ for (i = 0; i < RTE_ETHER_ADDR_LEN; i++)
+ mod.action.mac_addr[i] = mac[RTE_ETHER_ADDR_LEN - i - 1];
+
+ return xsc_dev_np_exec(xdev, &mod, sizeof(mod), XSC_NP_EPAT, XSC_NP_OP_MOD);
+}
+
+int
+xsc_dev_modify_epat_mac_filter(struct xsc_dev *xdev, uint16_t dst_info, uint8_t mac_filter_en)
+{
+ struct xsc_np_epat_mod mod;
+
+ memset(&mod, 0, sizeof(mod));
+ mod.flags |= XSC_EPAT_MAC_FILTER_EN_FLAG;
+ mod.key.dst_info = dst_info;
+ mod.action.mac_filter_en = mac_filter_en;
return xsc_dev_np_exec(xdev, &mod, sizeof(mod), XSC_NP_EPAT, XSC_NP_OP_MOD);
}
diff --git a/drivers/net/xsc/xsc_np.h b/drivers/net/xsc/xsc_np.h
index 8933917036..ca185c0a59 100644
--- a/drivers/net/xsc/xsc_np.h
+++ b/drivers/net/xsc/xsc_np.h
@@ -35,13 +35,15 @@ struct __rte_packed_begin xsc_epat_key {
} __rte_packed_end;
struct __rte_packed_begin xsc_epat_action {
- uint8_t rsv0[14];
- uint8_t rsv1:4;
- uint8_t dst_port:4;
- uint8_t rss_hash_func:2;
- uint8_t rss_hash_template:5;
- uint8_t rss_en:1;
- uint8_t qp_num;
+ uint8_t rsv0[3];
+ uint8_t mac_addr[6];
+ uint64_t mac_filter_en:1;
+ uint64_t rsv1:43;
+ uint64_t dst_port:4;
+ uint64_t rss_hash_func:2;
+ uint64_t rss_hash_template:5;
+ uint64_t rss_en:1;
+ uint64_t qp_num:8;
uint16_t rx_qp_id_ofst:12;
uint16_t rsv3:4;
uint8_t rsv4:7;
@@ -136,9 +138,13 @@ int xsc_dev_create_ipat(struct xsc_dev *xdev, uint16_t logic_in_port, uint16_t d
int xsc_dev_get_ipat_vld(struct xsc_dev *xdev, uint16_t logic_in_port);
int xsc_dev_destroy_ipat(struct xsc_dev *xdev, uint16_t logic_in_port);
int xsc_dev_create_epat(struct xsc_dev *xdev, uint16_t dst_info, uint8_t dst_port,
- uint16_t qpn_ofst, uint8_t qp_num, struct rte_eth_rss_conf *rss_conf);
+ uint16_t qpn_ofst, uint8_t qp_num, struct rte_eth_rss_conf *rss_conf,
+ uint8_t mac_filter_en, uint8_t *mac);
int xsc_dev_vf_modify_epat(struct xsc_dev *xdev, uint16_t dst_info, uint16_t qpn_ofst,
- uint8_t qp_num, struct rte_eth_rss_conf *rss_conf);
+ uint8_t qp_num, struct rte_eth_rss_conf *rss_conf,
+ uint8_t mac_filter_en, uint8_t *mac);
+int xsc_dev_modify_epat_mac_filter(struct xsc_dev *xdev, uint16_t dst_info,
+ uint8_t mac_filter_en);
int xsc_dev_destroy_epat(struct xsc_dev *xdev, uint16_t dst_info);
int xsc_dev_set_qpsetid(struct xsc_dev *xdev, uint32_t txqpn, uint16_t qp_set_id);
int xsc_dev_create_vfos_baselp(struct xsc_dev *xdev);
--
2.25.1
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 05/14] net/xsc: add link status support
2025-08-29 8:24 [PATCH 00/14] net/xsc: PMD updates Renyong Wan
` (3 preceding siblings ...)
2025-08-29 8:24 ` [PATCH 04/14] net/xsc: support promiscuous mode Renyong Wan
@ 2025-08-29 8:24 ` Renyong Wan
2025-08-29 8:24 ` [PATCH 06/14] net/xsc: add link status event support Renyong Wan
` (8 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Renyong Wan @ 2025-08-29 8:24 UTC (permalink / raw)
To: dev; +Cc: thomas, stephen, qianr, nana, zhangxx, xudw, jacky, weihg, zhenghy
Add support for getting and setting the link state.
Signed-off-by: Rong Qian <qianr@yunsilicon.com>
Signed-off-by: Renyong Wan <wanry@yunsilicon.com>
---
doc/guides/nics/features/xsc.ini | 1 +
drivers/net/xsc/xsc_cmd.h | 73 +++++++++++++++++++-----
drivers/net/xsc/xsc_dev.c | 21 ++-----
drivers/net/xsc/xsc_dev.h | 11 ++--
drivers/net/xsc/xsc_ethdev.c | 34 +++++++----
drivers/net/xsc/xsc_vfio.c | 96 ++++++++++++++++++++++++++++++++
6 files changed, 189 insertions(+), 47 deletions(-)
diff --git a/doc/guides/nics/features/xsc.ini b/doc/guides/nics/features/xsc.ini
index dfbfc88dbc..0d98296973 100644
--- a/doc/guides/nics/features/xsc.ini
+++ b/doc/guides/nics/features/xsc.ini
@@ -4,6 +4,7 @@
; Refer to default.ini for the full list of available PMD features.
;
[Features]
+Link status = Y
MTU update = Y
TSO = Y
Promiscuous mode = Y
diff --git a/drivers/net/xsc/xsc_cmd.h b/drivers/net/xsc/xsc_cmd.h
index 82244d4011..207f4456d5 100644
--- a/drivers/net/xsc/xsc_cmd.h
+++ b/drivers/net/xsc/xsc_cmd.h
@@ -15,20 +15,22 @@
#define XSC_CMD_QUERY_HCA_CAP_V1 1
enum xsc_cmd_opcode {
- XSC_CMD_OP_QUERY_HCA_CAP = 0x100,
- XSC_CMD_OP_CREATE_CQ = 0x400,
- XSC_CMD_OP_DESTROY_CQ = 0x401,
- XSC_CMD_OP_CREATE_QP = 0x500,
- XSC_CMD_OP_DESTROY_QP = 0x501,
- XSC_CMD_OP_RTR2RTS_QP = 0x504,
- XSC_CMD_OP_QP_2RST = 0x50A,
- XSC_CMD_OP_CREATE_MULTI_QP = 0x515,
- XSC_CMD_OP_ACCESS_REG = 0x805,
- XSC_CMD_OP_MODIFY_NIC_HCA = 0x812,
- XSC_CMD_OP_MODIFY_RAW_QP = 0x81f,
- XSC_CMD_OP_EXEC_NP = 0x900,
- XSC_CMD_OP_SET_MTU = 0x1100,
- XSC_CMD_OP_QUERY_ETH_MAC = 0X1101,
+ XSC_CMD_OP_QUERY_HCA_CAP = 0x100,
+ XSC_CMD_OP_CREATE_CQ = 0x400,
+ XSC_CMD_OP_DESTROY_CQ = 0x401,
+ XSC_CMD_OP_CREATE_QP = 0x500,
+ XSC_CMD_OP_DESTROY_QP = 0x501,
+ XSC_CMD_OP_RTR2RTS_QP = 0x504,
+ XSC_CMD_OP_QP_2RST = 0x50A,
+ XSC_CMD_OP_CREATE_MULTI_QP = 0x515,
+ XSC_CMD_OP_ACCESS_REG = 0x805,
+ XSC_CMD_OP_MODIFY_NIC_HCA = 0x812,
+ XSC_CMD_OP_MODIFY_RAW_QP = 0x81f,
+ XSC_CMD_OP_QUERY_LINK_INFO = 0x832,
+ XSC_CMD_OP_EXEC_NP = 0x900,
+ XSC_CMD_OP_SET_MTU = 0x1100,
+ XSC_CMD_OP_QUERY_ETH_MAC = 0X1101,
+ XSC_CMD_OP_SET_PORT_ADMIN_STATUS = 0x1801,
XSC_CMD_OP_MAX
};
@@ -399,4 +401,47 @@ struct xsc_cmd_access_reg_mbox_out {
rte_be32_t data[];
};
+struct xsc_cmd_set_port_admin_status_mbox_in {
+ struct xsc_cmd_inbox_hdr hdr;
+ uint16_t admin_status;
+};
+
+struct xsc_cmd_set_port_admin_status_mbox_out {
+ struct xsc_cmd_outbox_hdr hdr;
+ uint32_t status;
+};
+
+struct xsc_cmd_query_linkinfo_mbox_in {
+ struct xsc_cmd_inbox_hdr hdr;
+};
+
+struct xsc_cmd_linkinfo {
+ uint8_t status; /*link status: 0-down, 1-up */
+ uint8_t port;
+ uint8_t duplex;
+ uint8_t autoneg;
+ rte_be32_t linkspeed;
+ rte_be64_t supported;
+ rte_be64_t advertising;
+ rte_be64_t supported_fec;
+ rte_be64_t advertised_fec;
+ rte_be64_t supported_speed[2];
+ rte_be64_t advertising_speed[2];
+};
+
+struct xsc_cmd_query_linkinfo_mbox_out {
+ struct xsc_cmd_outbox_hdr hdr;
+ struct xsc_cmd_linkinfo ctx;
+};
+
+struct xsc_cmd_modify_linkinfo_mbox_in {
+ struct xsc_cmd_inbox_hdr hdr;
+ struct xsc_cmd_linkinfo ctx;
+};
+
+struct xsc_cmd_modify_linkinfo_mbox_out {
+ struct xsc_cmd_outbox_hdr hdr;
+ uint32_t status;
+};
+
#endif /* _XSC_CMD_H_ */
diff --git a/drivers/net/xsc/xsc_dev.c b/drivers/net/xsc/xsc_dev.c
index 2c55306d35..28581459b9 100644
--- a/drivers/net/xsc/xsc_dev.c
+++ b/drivers/net/xsc/xsc_dev.c
@@ -64,30 +64,21 @@ xsc_dev_mailbox_exec(struct xsc_dev *xdev, void *data_in,
}
int
-xsc_dev_set_link_up(struct xsc_dev *xdev)
+xsc_dev_link_status_set(struct xsc_dev *xdev, uint16_t status)
{
- if (xdev->dev_ops->set_link_up == NULL)
+ if (xdev->dev_ops->link_status_set == NULL)
return -ENOTSUP;
- return xdev->dev_ops->set_link_up(xdev);
+ return xdev->dev_ops->link_status_set(xdev, status);
}
int
-xsc_dev_set_link_down(struct xsc_dev *xdev)
+xsc_dev_link_get(struct xsc_dev *xdev, struct rte_eth_link *link)
{
- if (xdev->dev_ops->set_link_down == NULL)
+ if (xdev->dev_ops->link_get == NULL)
return -ENOTSUP;
- return xdev->dev_ops->set_link_down(xdev);
-}
-
-int
-xsc_dev_link_update(struct xsc_dev *xdev, uint8_t funcid_type, int wait_to_complete)
-{
- if (xdev->dev_ops->link_update == NULL)
- return -ENOTSUP;
-
- return xdev->dev_ops->link_update(xdev, funcid_type, wait_to_complete);
+ return xdev->dev_ops->link_get(xdev, link);
}
int
diff --git a/drivers/net/xsc/xsc_dev.h b/drivers/net/xsc/xsc_dev.h
index 5cf19aaf3d..e543b6892d 100644
--- a/drivers/net/xsc/xsc_dev.h
+++ b/drivers/net/xsc/xsc_dev.h
@@ -144,7 +144,6 @@ struct xsc_dev {
const struct xsc_dev_ops *dev_ops;
struct xsc_devargs devargs;
struct xsc_hwinfo hwinfo;
- struct rte_eth_link pf_dev_link;
uint32_t link_speed_capa;
int vfos_logical_in_port;
int vfrep_offset;
@@ -199,9 +198,8 @@ struct xsc_dev_ops {
int (*dev_init)(struct xsc_dev *xdev);
int (*dev_close)(struct xsc_dev *xdev);
int (*get_mac)(struct xsc_dev *xdev, uint8_t *mac);
- int (*set_link_up)(struct xsc_dev *xdev);
- int (*set_link_down)(struct xsc_dev *xdev);
- int (*link_update)(struct xsc_dev *xdev, uint8_t funcid_type, int wait_to_complete);
+ int (*link_status_set)(struct xsc_dev *xdev, uint16_t status);
+ int (*link_get)(struct xsc_dev *xdev, struct rte_eth_link *link);
int (*set_mtu)(struct xsc_dev *xdev, uint16_t mtu);
int (*destroy_qp)(void *qp);
int (*destroy_cq)(void *cq);
@@ -222,9 +220,8 @@ struct xsc_dev_ops {
int xsc_dev_mailbox_exec(struct xsc_dev *xdev, void *data_in,
int in_len, void *data_out, int out_len);
void xsc_dev_ops_register(struct xsc_dev_ops *new_ops);
-int xsc_dev_set_link_up(struct xsc_dev *xdev);
-int xsc_dev_set_link_down(struct xsc_dev *xde);
-int xsc_dev_link_update(struct xsc_dev *xdev, uint8_t funcid_type, int wait_to_complete);
+int xsc_dev_link_status_set(struct xsc_dev *xdev, uint16_t status);
+int xsc_dev_link_get(struct xsc_dev *xdev, struct rte_eth_link *link);
int xsc_dev_destroy_qp(struct xsc_dev *xdev, void *qp);
int xsc_dev_destroy_cq(struct xsc_dev *xdev, void *cq);
int xsc_dev_modify_qp_status(struct xsc_dev *xdev, uint32_t qpn, int num, int opcode);
diff --git a/drivers/net/xsc/xsc_ethdev.c b/drivers/net/xsc/xsc_ethdev.c
index efe1ad72f6..3574da91eb 100644
--- a/drivers/net/xsc/xsc_ethdev.c
+++ b/drivers/net/xsc/xsc_ethdev.c
@@ -389,7 +389,9 @@ xsc_ethdev_set_link_up(struct rte_eth_dev *dev)
struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
struct xsc_dev *xdev = priv->xdev;
- return xsc_dev_set_link_up(xdev);
+ if (xsc_dev_is_vf(xdev))
+ return -ENOTSUP;
+ return xsc_dev_link_status_set(xdev, RTE_ETH_LINK_UP);
}
static int
@@ -398,24 +400,26 @@ xsc_ethdev_set_link_down(struct rte_eth_dev *dev)
struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
struct xsc_dev *xdev = priv->xdev;
- return xsc_dev_set_link_down(xdev);
+ if (xsc_dev_is_vf(xdev))
+ return -ENOTSUP;
+ return xsc_dev_link_status_set(xdev, RTE_ETH_LINK_DOWN);
}
static int
-xsc_ethdev_link_update(struct rte_eth_dev *dev,
- int wait_to_complete)
+xsc_ethdev_link_update(struct rte_eth_dev *dev, int wait_to_complete)
{
struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
struct xsc_dev *xdev = priv->xdev;
+ struct rte_eth_link link = { };
int ret = 0;
- ret = xsc_dev_link_update(xdev, priv->funcid_type, wait_to_complete);
- if (ret == 0) {
- dev->data->dev_link = xdev->pf_dev_link;
- dev->data->dev_link.link_autoneg = !(dev->data->dev_conf.link_speeds &
- RTE_ETH_LINK_SPEED_FIXED);
- }
- return ret;
+ RTE_SET_USED(wait_to_complete);
+ ret = xsc_dev_link_get(xdev, &link);
+ if (ret != 0)
+ return ret;
+ rte_eth_linkstatus_set(dev, &link);
+
+ return 0;
}
static uint64_t
@@ -980,6 +984,14 @@ xsc_ethdev_init_representors(struct rte_eth_dev *eth_dev)
}
}
+ if (!xsc_dev_is_vf(priv->xdev)) {
+ ret = xsc_ethdev_set_link_up(eth_dev);
+ if (ret != 0) {
+ PMD_DRV_LOG(ERR, "Failed to set port %u link up", eth_dev->data->port_id);
+ goto destroy_reprs;
+ }
+ }
+
return 0;
destroy_reprs:
diff --git a/drivers/net/xsc/xsc_vfio.c b/drivers/net/xsc/xsc_vfio.c
index f61cf92569..cc3660e259 100644
--- a/drivers/net/xsc/xsc_vfio.c
+++ b/drivers/net/xsc/xsc_vfio.c
@@ -31,6 +31,21 @@ enum xsc_cq_type {
XSC_CQ_TYPE_VIRTIO = 1,
};
+enum xsc_speed_mode {
+ XSC_MODULE_SPEED_UNKNOWN,
+ XSC_MODULE_SPEED_10G,
+ XSC_MODULE_SPEED_25G,
+ XSC_MODULE_SPEED_40G_R4,
+ XSC_MODULE_SPEED_50G_R,
+ XSC_MODULE_SPEED_50G_R2,
+ XSC_MODULE_SPEED_100G_R2,
+ XSC_MODULE_SPEED_100G_R4,
+ XSC_MODULE_SPEED_200G_R4,
+ XSC_MODULE_SPEED_200G_R8,
+ XSC_MODULE_SPEED_400G_R8,
+ XSC_MODULE_SPEED_MAX,
+};
+
struct xsc_vfio_cq {
const struct rte_memzone *mz;
struct xsc_dev *xdev;
@@ -43,6 +58,20 @@ struct xsc_vfio_qp {
uint32_t qpn;
};
+static const uint32_t xsc_link_speed[] = {
+ [XSC_MODULE_SPEED_UNKNOWN] = RTE_ETH_SPEED_NUM_UNKNOWN,
+ [XSC_MODULE_SPEED_10G] = RTE_ETH_SPEED_NUM_10G,
+ [XSC_MODULE_SPEED_25G] = RTE_ETH_SPEED_NUM_25G,
+ [XSC_MODULE_SPEED_40G_R4] = RTE_ETH_SPEED_NUM_40G,
+ [XSC_MODULE_SPEED_50G_R] = RTE_ETH_SPEED_NUM_50G,
+ [XSC_MODULE_SPEED_50G_R2] = RTE_ETH_SPEED_NUM_50G,
+ [XSC_MODULE_SPEED_100G_R2] = RTE_ETH_SPEED_NUM_100G,
+ [XSC_MODULE_SPEED_100G_R4] = RTE_ETH_SPEED_NUM_100G,
+ [XSC_MODULE_SPEED_200G_R4] = RTE_ETH_SPEED_NUM_200G,
+ [XSC_MODULE_SPEED_200G_R8] = RTE_ETH_SPEED_NUM_200G,
+ [XSC_MODULE_SPEED_400G_R8] = RTE_ETH_SPEED_NUM_400G,
+};
+
static void
xsc_vfio_pcie_no_init(struct xsc_hwinfo *hwinfo)
{
@@ -333,6 +362,71 @@ xsc_vfio_get_mac(struct xsc_dev *xdev, uint8_t *mac)
return 0;
}
+static int
+xsc_vfio_modify_link_status(struct xsc_dev *xdev, uint16_t status)
+{
+ struct xsc_cmd_set_port_admin_status_mbox_in in = { };
+ struct xsc_cmd_set_port_admin_status_mbox_out out = { };
+ int ret = 0;
+
+ in.hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_SET_PORT_ADMIN_STATUS);
+ in.admin_status = rte_cpu_to_be_16(status);
+
+ ret = xsc_vfio_mbox_exec(xdev, &in, sizeof(in), &out, sizeof(out));
+ if (ret != 0 || out.hdr.status != 0) {
+ PMD_DRV_LOG(ERR, "Failed to set link status, ret=%d, status=%d",
+ ret, out.hdr.status);
+ return -ENOEXEC;
+ }
+
+ return ret;
+}
+
+static int
+xsc_vfio_link_status_set(struct xsc_dev *xdev, uint16_t status)
+{
+ if (status != RTE_ETH_LINK_UP && status != RTE_ETH_LINK_DOWN)
+ return -EINVAL;
+
+ return xsc_vfio_modify_link_status(xdev, status);
+}
+
+static uint32_t
+xsc_vfio_link_speed_translate(uint32_t mode)
+{
+ if (mode >= XSC_MODULE_SPEED_MAX)
+ return RTE_ETH_SPEED_NUM_NONE;
+
+ return xsc_link_speed[mode];
+}
+
+static int
+xsc_vfio_link_get(struct xsc_dev *xdev, struct rte_eth_link *link)
+{
+ struct xsc_cmd_query_linkinfo_mbox_in in = { };
+ struct xsc_cmd_query_linkinfo_mbox_out out = { };
+ struct xsc_cmd_linkinfo linkinfo;
+ int ret;
+ uint32_t speed_mode;
+
+ in.hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_QUERY_LINK_INFO);
+ ret = xsc_vfio_mbox_exec(xdev, &in, sizeof(in), &out, sizeof(out));
+ if (ret != 0 || out.hdr.status != 0) {
+ PMD_DRV_LOG(ERR, "Failed to get link info, ret=%d, status=%d",
+ ret, out.hdr.status);
+ return -ENOEXEC;
+ }
+
+ linkinfo = out.ctx;
+ link->link_status = linkinfo.status ? RTE_ETH_LINK_UP : RTE_ETH_LINK_DOWN;
+ speed_mode = rte_be_to_cpu_32(linkinfo.linkspeed);
+ link->link_speed = xsc_vfio_link_speed_translate(speed_mode);
+ link->link_duplex = linkinfo.duplex;
+ link->link_autoneg = linkinfo.autoneg;
+
+ return 0;
+};
+
static int
xsc_vfio_modify_qp_status(struct xsc_dev *xdev, uint32_t qpn, int num, int opcode)
{
@@ -770,6 +864,8 @@ static struct xsc_dev_ops *xsc_vfio_ops = &(struct xsc_dev_ops) {
.dev_close = xsc_vfio_dev_close,
.set_mtu = xsc_vfio_set_mtu,
.get_mac = xsc_vfio_get_mac,
+ .link_status_set = xsc_vfio_link_status_set,
+ .link_get = xsc_vfio_link_get,
.destroy_qp = xsc_vfio_destroy_qp,
.destroy_cq = xsc_vfio_destroy_cq,
.modify_qp_status = xsc_vfio_modify_qp_status,
--
2.25.1
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 06/14] net/xsc: add link status event support
2025-08-29 8:24 [PATCH 00/14] net/xsc: PMD updates Renyong Wan
` (4 preceding siblings ...)
2025-08-29 8:24 ` [PATCH 05/14] net/xsc: add link status support Renyong Wan
@ 2025-08-29 8:24 ` Renyong Wan
2025-08-29 8:24 ` [PATCH 07/14] net/xsc: add FEC get and set support Renyong Wan
` (7 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Renyong Wan @ 2025-08-29 8:24 UTC (permalink / raw)
To: dev; +Cc: thomas, stephen, qianr, nana, zhangxx, xudw, jacky, weihg, zhenghy
Add VFIO MSI-X interrupt support and handle Link Status Change events.
Signed-off-by: Rong Qian <qianr@yunsilicon.com>
Signed-off-by: Renyong Wan <wanry@yunsilicon.com>
---
doc/guides/nics/features/xsc.ini | 1 +
drivers/net/xsc/xsc_cmd.h | 29 ++++
drivers/net/xsc/xsc_defs.h | 2 +
drivers/net/xsc/xsc_dev.c | 27 ++++
drivers/net/xsc/xsc_dev.h | 18 +++
drivers/net/xsc/xsc_ethdev.c | 30 ++++
drivers/net/xsc/xsc_vfio.c | 247 +++++++++++++++++++++++++++++++
7 files changed, 354 insertions(+)
diff --git a/doc/guides/nics/features/xsc.ini b/doc/guides/nics/features/xsc.ini
index 0d98296973..d4498ed0a0 100644
--- a/doc/guides/nics/features/xsc.ini
+++ b/doc/guides/nics/features/xsc.ini
@@ -5,6 +5,7 @@
;
[Features]
Link status = Y
+Link status event = Y
MTU update = Y
TSO = Y
Promiscuous mode = Y
diff --git a/drivers/net/xsc/xsc_cmd.h b/drivers/net/xsc/xsc_cmd.h
index 207f4456d5..777de1ce4a 100644
--- a/drivers/net/xsc/xsc_cmd.h
+++ b/drivers/net/xsc/xsc_cmd.h
@@ -26,7 +26,9 @@ enum xsc_cmd_opcode {
XSC_CMD_OP_ACCESS_REG = 0x805,
XSC_CMD_OP_MODIFY_NIC_HCA = 0x812,
XSC_CMD_OP_MODIFY_RAW_QP = 0x81f,
+ XSC_CMD_OP_QUERY_EVENT_TYPE = 0x831,
XSC_CMD_OP_QUERY_LINK_INFO = 0x832,
+ XSC_CMD_OP_ENABLE_MSIX = 0x850,
XSC_CMD_OP_EXEC_NP = 0x900,
XSC_CMD_OP_SET_MTU = 0x1100,
XSC_CMD_OP_QUERY_ETH_MAC = 0X1101,
@@ -444,4 +446,31 @@ struct xsc_cmd_modify_linkinfo_mbox_out {
uint32_t status;
};
+struct xsc_cmd_event_resp {
+ uint8_t event_type;
+};
+
+struct xsc_cmd_event_query_type_mbox_in {
+ struct xsc_cmd_inbox_hdr hdr;
+ uint8_t rsvd[2];
+};
+
+struct xsc_cmd_event_query_type_mbox_out {
+ struct xsc_cmd_outbox_hdr hdr;
+ struct xsc_cmd_event_resp ctx;
+};
+
+struct xsc_cmd_msix_table_info_mbox_in {
+ struct xsc_cmd_inbox_hdr hdr;
+ uint16_t index;
+ uint8_t rsvd[6];
+};
+
+struct xsc_cmd_msix_table_info_mbox_out {
+ struct xsc_cmd_outbox_hdr hdr;
+ uint32_t addr_lo;
+ uint32_t addr_hi;
+ uint32_t data;
+};
+
#endif /* _XSC_CMD_H_ */
diff --git a/drivers/net/xsc/xsc_defs.h b/drivers/net/xsc/xsc_defs.h
index 5b4e5b80d2..4b95a0521d 100644
--- a/drivers/net/xsc/xsc_defs.h
+++ b/drivers/net/xsc/xsc_defs.h
@@ -51,6 +51,8 @@
#define XSC_VF_TX_DB_ADDR 0x8d0
#define XSC_VF_CQ_DB_ADDR 0x8c4
+#define XSC_HIF_CMDQM_VECTOR_ID_MEM_ADDR 0x1034000
+
enum xsc_nic_mode {
XSC_NIC_MODE_LEGACY,
XSC_NIC_MODE_SWITCHDEV,
diff --git a/drivers/net/xsc/xsc_dev.c b/drivers/net/xsc/xsc_dev.c
index 28581459b9..815b67d7da 100644
--- a/drivers/net/xsc/xsc_dev.c
+++ b/drivers/net/xsc/xsc_dev.c
@@ -587,3 +587,30 @@ xsc_dev_query_module_eeprom(struct xsc_dev *xdev, uint16_t offset,
return xsc_dev_query_mcia(xdev, &query, data);
}
+
+int
+xsc_dev_intr_event_get(struct xsc_dev *xdev)
+{
+ if (xdev->dev_ops->intr_event_get == NULL)
+ return -ENOTSUP;
+
+ return xdev->dev_ops->intr_event_get(xdev);
+}
+
+int
+xsc_dev_intr_handler_install(struct xsc_dev *xdev, rte_intr_callback_fn cb, void *cb_arg)
+{
+ if (xdev->dev_ops->intr_handler_install == NULL)
+ return -ENOTSUP;
+
+ return xdev->dev_ops->intr_handler_install(xdev, cb, cb_arg);
+}
+
+int
+xsc_dev_intr_handler_uninstall(struct xsc_dev *xdev)
+{
+ if (xdev->dev_ops->intr_handler_uninstall == NULL)
+ return -ENOTSUP;
+
+ return xdev->dev_ops->intr_handler_uninstall(xdev);
+}
diff --git a/drivers/net/xsc/xsc_dev.h b/drivers/net/xsc/xsc_dev.h
index e543b6892d..86a0eee22e 100644
--- a/drivers/net/xsc/xsc_dev.h
+++ b/drivers/net/xsc/xsc_dev.h
@@ -72,6 +72,13 @@ enum xsc_module_id {
XSC_MODULE_ID_QSFP_PLUS_CMIS = 0x1E,
};
+enum xsc_intr_event_type {
+ XSC_EVENT_TYPE_NONE = 0x0,
+ XSC_EVENT_TYPE_CHANGE_LINK = 0x0001,
+ XSC_EVENT_TYPE_TEMP_WARN = 0x0002,
+ XSC_EVENT_TYPE_OVER_TEMP_PROTECTION = 0x0004,
+};
+
struct xsc_hwinfo {
uint32_t pcie_no; /* pcie number , 0 or 1 */
uint32_t func_id; /* pf glb func id */
@@ -93,6 +100,8 @@ struct xsc_hwinfo {
uint16_t pcie1_pf_funcid_top;
uint16_t lag_port_start;
uint16_t raw_tpe_qp_num;
+ uint16_t msix_base;
+ uint16_t msix_num;
uint8_t send_seg_num;
uint8_t recv_seg_num;
uint8_t valid; /* 1: current phy info is valid, 0 : invalid */
@@ -160,6 +169,8 @@ struct xsc_dev {
void *jumbo_buffer_va;
uint64_t bar_len;
int ctrl_fd;
+ rte_intr_callback_fn intr_cb;
+ void *intr_cb_arg;
};
struct xsc_module_eeprom_query_params {
@@ -215,6 +226,10 @@ struct xsc_dev_ops {
struct xsc_tx_qp_info *qp_info);
int (*mailbox_exec)(struct xsc_dev *xdev, void *data_in,
int in_len, void *data_out, int out_len);
+ int (*intr_event_get)(struct xsc_dev *xdev);
+ int (*intr_handler_install)(struct xsc_dev *xdev, rte_intr_callback_fn cb,
+ void *cb_arg);
+ int (*intr_handler_uninstall)(struct xsc_dev *xdev);
};
int xsc_dev_mailbox_exec(struct xsc_dev *xdev, void *data_in,
@@ -244,5 +259,8 @@ int xsc_dev_get_mac(struct xsc_dev *xdev, uint8_t *mac);
int xsc_dev_fw_version_get(struct xsc_dev *xdev, char *fw_version, size_t fw_size);
int xsc_dev_query_module_eeprom(struct xsc_dev *xdev, uint16_t offset,
uint16_t size, uint8_t *data);
+int xsc_dev_intr_event_get(struct xsc_dev *xdev);
+int xsc_dev_intr_handler_install(struct xsc_dev *xdev, rte_intr_callback_fn cb, void *cb_arg);
+int xsc_dev_intr_handler_uninstall(struct xsc_dev *xdev);
#endif /* _XSC_DEV_H_ */
diff --git a/drivers/net/xsc/xsc_ethdev.c b/drivers/net/xsc/xsc_ethdev.c
index 3574da91eb..0884894a9b 100644
--- a/drivers/net/xsc/xsc_ethdev.c
+++ b/drivers/net/xsc/xsc_ethdev.c
@@ -4,6 +4,7 @@
#include <rte_dev_info.h>
#include <ethdev_pci.h>
+#include <rte_interrupts.h>
#include "xsc_log.h"
#include "xsc_defs.h"
@@ -378,6 +379,8 @@ xsc_ethdev_close(struct rte_eth_dev *dev)
xsc_rxq_stop(dev);
rte_free(priv->rss_conf.rss_key);
+ if (!xsc_dev_is_vf(priv->xdev))
+ xsc_dev_intr_handler_uninstall(priv->xdev);
xsc_dev_close(priv->xdev, priv->representor_id);
dev->data->mac_addrs = NULL;
return 0;
@@ -1007,6 +1010,25 @@ xsc_ethdev_init_representors(struct rte_eth_dev *eth_dev)
return ret;
}
+static void
+xsc_ethdev_intr_handler(void *param)
+{
+ struct rte_eth_dev *eth_dev = param;
+ struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(eth_dev);
+ int event_type;
+
+ event_type = xsc_dev_intr_event_get(priv->xdev);
+ switch (event_type) {
+ case XSC_EVENT_TYPE_CHANGE_LINK:
+ PMD_DRV_LOG(DEBUG, "Get intr event type=%04x", event_type);
+ xsc_ethdev_link_update(eth_dev, 0);
+ rte_eth_dev_callback_process(eth_dev, RTE_ETH_EVENT_INTR_LSC, NULL);
+ break;
+ default:
+ break;
+ }
+}
+
static int
xsc_ethdev_init(struct rte_eth_dev *eth_dev)
{
@@ -1031,6 +1053,14 @@ xsc_ethdev_init(struct rte_eth_dev *eth_dev)
goto uninit_xsc_dev;
}
+ if (!xsc_dev_is_vf(priv->xdev)) {
+ ret = xsc_dev_intr_handler_install(priv->xdev, xsc_ethdev_intr_handler, eth_dev);
+ if (ret != 0) {
+ PMD_DRV_LOG(ERR, "Failed to install intr handler");
+ goto uninit_xsc_dev;
+ }
+ }
+
return 0;
uninit_xsc_dev:
diff --git a/drivers/net/xsc/xsc_vfio.c b/drivers/net/xsc/xsc_vfio.c
index cc3660e259..34b2a4c58b 100644
--- a/drivers/net/xsc/xsc_vfio.c
+++ b/drivers/net/xsc/xsc_vfio.c
@@ -6,11 +6,15 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
+#include <linux/vfio.h>
+#include <sys/eventfd.h>
+#include <sys/ioctl.h>
#include <rte_pci.h>
#include <ethdev_pci.h>
#include <rte_bus_pci.h>
#include <rte_bitops.h>
+#include <rte_interrupts.h>
#include "xsc_defs.h"
#include "xsc_vfio_mbox.h"
@@ -22,10 +26,21 @@
#define XSC_FEATURE_PCT_EXP_MASK RTE_BIT32(19)
#define XSC_HOST_PCIE_NO_DEFAULT 0
#define XSC_SOC_PCIE_NO_DEFAULT 1
+#define XSC_MSIX_CPU_NUM_DEFAULT 2
#define XSC_SW2HW_MTU(mtu) ((mtu) + 14 + 4)
#define XSC_SW2HW_RX_PKT_LEN(mtu) ((mtu) + 14 + 256)
+#define XSC_MAX_INTR_VEC_ID RTE_MAX_RXTX_INTR_VEC_ID
+#define XSC_MSIX_IRQ_SET_BUF_LEN (sizeof(struct vfio_irq_set) + \
+ sizeof(int) * (XSC_MAX_INTR_VEC_ID))
+
+enum xsc_vector {
+ XSC_VEC_CMD = 0,
+ XSC_VEC_CMD_EVENT = 1,
+ XSC_EQ_VEC_COMP_BASE,
+};
+
enum xsc_cq_type {
XSC_CQ_TYPE_NORMAL = 0,
XSC_CQ_TYPE_VIRTIO = 1,
@@ -133,6 +148,7 @@ xsc_vfio_hwinfo_init(struct xsc_dev *xdev)
memset(in, 0, cmd_len);
in->hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_QUERY_HCA_CAP);
in->hdr.ver = rte_cpu_to_be_16(XSC_CMD_QUERY_HCA_CAP_V1);
+ in->cpu_num = rte_cpu_to_be_16(XSC_MSIX_CPU_NUM_DEFAULT);
out = cmd_buf;
ret = xsc_vfio_mbox_exec(xdev, in, in_len, out, out_len);
@@ -171,6 +187,8 @@ xsc_vfio_hwinfo_init(struct xsc_dev *xdev)
xdev->hwinfo.chip_version = rte_be_to_cpu_32(hca_cap->chip_ver_l);
xdev->hwinfo.hca_core_clock = rte_be_to_cpu_32(hca_cap->hca_core_clock);
xdev->hwinfo.mac_bit = hca_cap->mac_bit;
+ xdev->hwinfo.msix_base = rte_be_to_cpu_16(hca_cap->msix_base);
+ xdev->hwinfo.msix_num = rte_be_to_cpu_16(hca_cap->msix_num);
xsc_vfio_pcie_no_init(&xdev->hwinfo);
xsc_vfio_fw_version_init(xdev->hwinfo.fw_ver, &hca_cap->fw_ver);
@@ -858,6 +876,232 @@ xsc_vfio_dev_init(struct xsc_dev *xdev)
return -1;
}
+static int
+xsc_vfio_irq_info_get(struct rte_intr_handle *intr_handle)
+{
+ struct vfio_irq_info irq = { .argsz = sizeof(irq) };
+ int rc, vfio_dev_fd;
+
+ irq.index = VFIO_PCI_MSIX_IRQ_INDEX;
+
+ vfio_dev_fd = rte_intr_dev_fd_get(intr_handle);
+ rc = ioctl(vfio_dev_fd, VFIO_DEVICE_GET_IRQ_INFO, &irq);
+ if (rc < 0) {
+ PMD_DRV_LOG(ERR, "Failed to get IRQ info rc=%d errno=%d", rc, errno);
+ return rc;
+ }
+
+ PMD_DRV_LOG(INFO, "Flags=0x%x index=0x%x count=0x%x max_intr_vec_id=0x%x",
+ irq.flags, irq.index, irq.count, XSC_MAX_INTR_VEC_ID);
+
+ if (rte_intr_max_intr_set(intr_handle, irq.count))
+ return -1;
+
+ return 0;
+}
+
+static int
+xsc_vfio_irq_init(struct rte_intr_handle *intr_handle)
+{
+ char irq_set_buf[XSC_MSIX_IRQ_SET_BUF_LEN];
+ struct vfio_irq_set *irq_set;
+ int len, rc, vfio_dev_fd;
+ int32_t *fd_ptr;
+ uint32_t i;
+
+ if (rte_intr_max_intr_get(intr_handle) > XSC_MAX_INTR_VEC_ID) {
+ PMD_DRV_LOG(ERR, "Max_intr=%d greater than XSC_MAX_INTR_VEC_ID=%d",
+ rte_intr_max_intr_get(intr_handle),
+ XSC_MAX_INTR_VEC_ID);
+ return -ERANGE;
+ }
+
+ len = sizeof(struct vfio_irq_set) +
+ sizeof(int32_t) * rte_intr_max_intr_get(intr_handle);
+
+ irq_set = (struct vfio_irq_set *)irq_set_buf;
+ irq_set->argsz = len;
+ irq_set->start = 0;
+ irq_set->count = 10;
+ irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD | VFIO_IRQ_SET_ACTION_TRIGGER;
+ irq_set->index = VFIO_PCI_MSIX_IRQ_INDEX;
+
+ fd_ptr = (int32_t *)&irq_set->data[0];
+ for (i = 0; i < irq_set->count; i++)
+ fd_ptr[i] = -1;
+
+ vfio_dev_fd = rte_intr_dev_fd_get(intr_handle);
+ rc = ioctl(vfio_dev_fd, VFIO_DEVICE_SET_IRQS, irq_set);
+ if (rc)
+ PMD_DRV_LOG(ERR, "Failed to set irqs vector rc=%d", rc);
+
+ return rc;
+}
+
+static int
+xsc_vfio_irq_config(struct rte_intr_handle *intr_handle, unsigned int vec)
+{
+ char irq_set_buf[XSC_MSIX_IRQ_SET_BUF_LEN];
+ struct vfio_irq_set *irq_set;
+ int len, rc, vfio_dev_fd;
+ int32_t *fd_ptr;
+
+ if (vec > (uint32_t)rte_intr_max_intr_get(intr_handle)) {
+ PMD_DRV_LOG(INFO, "Vector=%d greater than max_intr=%d", vec,
+ rte_intr_max_intr_get(intr_handle));
+ return -EINVAL;
+ }
+
+ len = sizeof(struct vfio_irq_set) + sizeof(int32_t);
+
+ irq_set = (struct vfio_irq_set *)irq_set_buf;
+ irq_set->argsz = len;
+
+ irq_set->start = vec;
+ irq_set->count = 1;
+ irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD | VFIO_IRQ_SET_ACTION_TRIGGER;
+ irq_set->index = VFIO_PCI_MSIX_IRQ_INDEX;
+
+ /* Use vec fd to set interrupt vectors */
+ fd_ptr = (int32_t *)&irq_set->data[0];
+ fd_ptr[0] = rte_intr_efds_index_get(intr_handle, vec);
+
+ vfio_dev_fd = rte_intr_dev_fd_get(intr_handle);
+ rc = ioctl(vfio_dev_fd, VFIO_DEVICE_SET_IRQS, irq_set);
+ if (rc)
+ PMD_DRV_LOG(INFO, "Failed to set_irqs vector=0x%x rc=%d", vec, rc);
+
+ return rc;
+}
+
+static int
+xsc_vfio_irq_register(struct rte_intr_handle *intr_handle,
+ rte_intr_callback_fn cb, void *data, unsigned int vec)
+{
+ struct rte_intr_handle *tmp_handle;
+ uint32_t nb_efd, tmp_nb_efd;
+ int rc, fd;
+
+ if (rte_intr_max_intr_get(intr_handle) == 0) {
+ xsc_vfio_irq_info_get(intr_handle);
+ xsc_vfio_irq_init(intr_handle);
+ }
+
+ if (vec > (uint32_t)rte_intr_max_intr_get(intr_handle)) {
+ PMD_DRV_LOG(INFO, "Vector=%d greater than max_intr=%d", vec,
+ rte_intr_max_intr_get(intr_handle));
+ return -EINVAL;
+ }
+
+ tmp_handle = intr_handle;
+ /* Create new eventfd for interrupt vector */
+ fd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
+ if (fd == -1)
+ return -ENODEV;
+
+ if (rte_intr_fd_set(tmp_handle, fd))
+ return errno;
+
+ /* Register vector interrupt callback */
+ rc = rte_intr_callback_register(tmp_handle, cb, data);
+ if (rc) {
+ PMD_DRV_LOG(INFO, "Failed to register vector:0x%x irq callback.", vec);
+ return rc;
+ }
+
+ rte_intr_efds_index_set(intr_handle, vec, fd);
+ nb_efd = (vec > (uint32_t)rte_intr_nb_efd_get(intr_handle)) ?
+ vec : (uint32_t)rte_intr_nb_efd_get(intr_handle);
+ rte_intr_nb_efd_set(intr_handle, nb_efd);
+
+ tmp_nb_efd = rte_intr_nb_efd_get(intr_handle) + 1;
+ if (tmp_nb_efd > (uint32_t)rte_intr_max_intr_get(intr_handle))
+ rte_intr_max_intr_set(intr_handle, tmp_nb_efd);
+
+ PMD_DRV_LOG(INFO, "Enable vector:0x%x for vfio (efds: %d, max:%d)",
+ vec,
+ rte_intr_nb_efd_get(intr_handle),
+ rte_intr_max_intr_get(intr_handle));
+
+ /* Enable MSIX vectors to VFIO */
+ return xsc_vfio_irq_config(intr_handle, vec);
+}
+
+static int
+xsc_vfio_msix_enable(struct xsc_dev *xdev)
+{
+ struct xsc_cmd_msix_table_info_mbox_in in = { };
+ struct xsc_cmd_msix_table_info_mbox_out out = { };
+ int ret;
+
+ in.hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_ENABLE_MSIX);
+ ret = xsc_vfio_mbox_exec(xdev, &in, sizeof(in), &out, sizeof(out));
+ if (ret != 0 || out.hdr.status != 0) {
+ PMD_DRV_LOG(ERR, "Failed to enable msix, ret=%d, stats=%d",
+ ret, out.hdr.status);
+ return ret;
+ }
+
+ rte_write32(xdev->hwinfo.msix_base,
+ (uint8_t *)xdev->bar_addr + XSC_HIF_CMDQM_VECTOR_ID_MEM_ADDR);
+
+ return 0;
+}
+
+static int
+xsc_vfio_event_get(struct xsc_dev *xdev)
+{
+ int ret;
+ struct xsc_cmd_event_query_type_mbox_in in = { };
+ struct xsc_cmd_event_query_type_mbox_out out = { };
+
+ in.hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_QUERY_EVENT_TYPE);
+ ret = xsc_vfio_mbox_exec(xdev, &in, sizeof(in), &out, sizeof(out));
+ if (ret != 0 || out.hdr.status != 0) {
+ PMD_DRV_LOG(ERR, "Failed to query event type, ret=%d, stats=%d",
+ ret, out.hdr.status);
+ return -1;
+ }
+
+ return out.ctx.event_type;
+}
+
+static int
+xsc_vfio_intr_handler_install(struct xsc_dev *xdev, rte_intr_callback_fn cb, void *cb_arg)
+{
+ int ret;
+ struct rte_intr_handle *intr_handle = xdev->pci_dev->intr_handle;
+
+ ret = xsc_vfio_irq_register(intr_handle, cb, cb_arg, XSC_VEC_CMD_EVENT);
+ if (ret != 0) {
+ PMD_DRV_LOG(ERR, "Failed to register vfio irq, ret=%d", ret);
+ return ret;
+ }
+
+ xdev->intr_cb = cb;
+ xdev->intr_cb_arg = cb_arg;
+
+ ret = xsc_vfio_msix_enable(xdev);
+ if (ret != 0) {
+ PMD_DRV_LOG(ERR, "Failed to enable vfio msix, ret=%d", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int
+xsc_vfio_intr_handler_uninstall(struct xsc_dev *xdev)
+{
+ if (rte_intr_fd_get(xdev->pci_dev->intr_handle) >= 0)
+ rte_intr_callback_unregister(xdev->pci_dev->intr_handle,
+ xdev->intr_cb, xdev->intr_cb_arg);
+
+ rte_intr_instance_free(xdev->intr_handle);
+
+ return 0;
+}
+
static struct xsc_dev_ops *xsc_vfio_ops = &(struct xsc_dev_ops) {
.kdrv = RTE_PCI_KDRV_VFIO,
.dev_init = xsc_vfio_dev_init,
@@ -874,6 +1118,9 @@ static struct xsc_dev_ops *xsc_vfio_ops = &(struct xsc_dev_ops) {
.tx_cq_create = xsc_vfio_tx_cq_create,
.tx_qp_create = xsc_vfio_tx_qp_create,
.mailbox_exec = xsc_vfio_mbox_exec,
+ .intr_event_get = xsc_vfio_event_get,
+ .intr_handler_install = xsc_vfio_intr_handler_install,
+ .intr_handler_uninstall = xsc_vfio_intr_handler_uninstall,
};
RTE_INIT(xsc_vfio_ops_reg)
--
2.25.1
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 07/14] net/xsc: add FEC get and set support
2025-08-29 8:24 [PATCH 00/14] net/xsc: PMD updates Renyong Wan
` (5 preceding siblings ...)
2025-08-29 8:24 ` [PATCH 06/14] net/xsc: add link status event support Renyong Wan
@ 2025-08-29 8:24 ` Renyong Wan
2025-08-29 8:24 ` [PATCH 08/14] net/xsc: optimize RSS queue creation Renyong Wan
` (6 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Renyong Wan @ 2025-08-29 8:24 UTC (permalink / raw)
To: dev; +Cc: thomas, stephen, qianr, nana, zhangxx, xudw, jacky, weihg, zhenghy
Add functions to get and set FEC mode for xsc PMD.
Signed-off-by: Rong Qian <qianr@yunsilicon.com>
Signed-off-by: Renyong Wan <wanry@yunsilicon.com>
---
doc/guides/nics/features/xsc.ini | 1 +
drivers/net/xsc/xsc_cmd.h | 24 ++++++++++
drivers/net/xsc/xsc_dev.c | 75 ++++++++++++++++++++++++++++++++
drivers/net/xsc/xsc_dev.h | 16 +++++++
drivers/net/xsc/xsc_ethdev.c | 18 ++++++++
5 files changed, 134 insertions(+)
diff --git a/doc/guides/nics/features/xsc.ini b/doc/guides/nics/features/xsc.ini
index d4498ed0a0..c6243c18df 100644
--- a/doc/guides/nics/features/xsc.ini
+++ b/doc/guides/nics/features/xsc.ini
@@ -12,6 +12,7 @@ Promiscuous mode = Y
RSS hash = Y
RSS key update = Y
RSS reta update = Y
+FEC = Y
L3 checksum offload = Y
L4 checksum offload = Y
Inner L3 checksum = Y
diff --git a/drivers/net/xsc/xsc_cmd.h b/drivers/net/xsc/xsc_cmd.h
index 777de1ce4a..2746131cf1 100644
--- a/drivers/net/xsc/xsc_cmd.h
+++ b/drivers/net/xsc/xsc_cmd.h
@@ -28,6 +28,8 @@ enum xsc_cmd_opcode {
XSC_CMD_OP_MODIFY_RAW_QP = 0x81f,
XSC_CMD_OP_QUERY_EVENT_TYPE = 0x831,
XSC_CMD_OP_QUERY_LINK_INFO = 0x832,
+ XSC_CMD_OP_QUERY_FEC_PARAM = 0x835,
+ XSC_CMD_OP_MODIFY_FEC_PARAM = 0x836,
XSC_CMD_OP_ENABLE_MSIX = 0x850,
XSC_CMD_OP_EXEC_NP = 0x900,
XSC_CMD_OP_SET_MTU = 0x1100,
@@ -473,4 +475,26 @@ struct xsc_cmd_msix_table_info_mbox_out {
uint32_t data;
};
+struct xsc_cmd_query_fecparam_mbox_in {
+ struct xsc_cmd_inbox_hdr hdr;
+ uint8_t rsvd[2];
+};
+
+struct xsc_cmd_query_fecparam_mbox_out {
+ struct xsc_cmd_outbox_hdr hdr;
+ uint32_t active_fec;
+ uint32_t fec_cfg;
+ uint32_t status;
+};
+
+struct xsc_cmd_modify_fecparam_mbox_in {
+ struct xsc_cmd_inbox_hdr hdr;
+ uint32_t fec;
+};
+
+struct xsc_cmd_modify_fecparam_mbox_out {
+ struct xsc_cmd_outbox_hdr hdr;
+ uint32_t status;
+};
+
#endif /* _XSC_CMD_H_ */
diff --git a/drivers/net/xsc/xsc_dev.c b/drivers/net/xsc/xsc_dev.c
index 815b67d7da..6b24ea98d0 100644
--- a/drivers/net/xsc/xsc_dev.c
+++ b/drivers/net/xsc/xsc_dev.c
@@ -614,3 +614,78 @@ xsc_dev_intr_handler_uninstall(struct xsc_dev *xdev)
return xdev->dev_ops->intr_handler_uninstall(xdev);
}
+
+int
+xsc_dev_fec_get(struct xsc_dev *xdev, uint32_t *fec_capa)
+{
+ struct xsc_cmd_query_fecparam_mbox_in in = { };
+ struct xsc_cmd_query_fecparam_mbox_out out = { };
+ int ret = 0, fec;
+
+ in.hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_QUERY_FEC_PARAM);
+ ret = xsc_dev_mailbox_exec(xdev, &in, sizeof(in), &out, sizeof(out));
+ if (ret != 0 || out.hdr.status != 0) {
+ PMD_DRV_LOG(ERR, "Failed to get fec, ret=%d, status=%u",
+ ret, out.hdr.status);
+ rte_errno = ENOEXEC;
+ return -rte_errno;
+ }
+
+ fec = rte_be_to_cpu_32(out.active_fec);
+ switch (fec) {
+ case XSC_DEV_FEC_OFF:
+ fec = RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC);
+ break;
+ case XSC_DEV_FEC_BASER:
+ fec = RTE_ETH_FEC_MODE_CAPA_MASK(BASER);
+ break;
+ case XSC_DEV_FEC_RS:
+ fec = RTE_ETH_FEC_MODE_CAPA_MASK(RS);
+ break;
+ default:
+ fec = RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC);
+ break;
+ }
+
+ *fec_capa = fec;
+
+ return 0;
+}
+
+int
+xsc_dev_fec_set(struct xsc_dev *xdev, uint32_t mode)
+{
+ struct xsc_cmd_modify_fecparam_mbox_in in = { };
+ struct xsc_cmd_modify_fecparam_mbox_out out = { };
+ int ret = 0;
+
+ in.hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_MODIFY_FEC_PARAM);
+ switch (mode) {
+ case RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC):
+ mode = XSC_DEV_FEC_OFF;
+ break;
+ case RTE_ETH_FEC_MODE_CAPA_MASK(AUTO):
+ mode = XSC_DEV_FEC_AUTO;
+ break;
+ case RTE_ETH_FEC_MODE_CAPA_MASK(BASER):
+ mode = XSC_DEV_FEC_BASER;
+ break;
+ case RTE_ETH_FEC_MODE_CAPA_MASK(RS):
+ mode = XSC_DEV_FEC_RS;
+ break;
+ default:
+ PMD_DRV_LOG(ERR, "Failed to set fec, fec mode %u not support", mode);
+ return 0;
+ }
+
+ in.fec = rte_cpu_to_be_32(mode);
+ ret = xsc_dev_mailbox_exec(xdev, &in, sizeof(in), &out, sizeof(out));
+ if (ret != 0 || out.hdr.status != 0) {
+ PMD_DRV_LOG(ERR, "Failed to set fec param, ret=%d, status=%u",
+ ret, out.hdr.status);
+ rte_errno = ENOEXEC;
+ return -rte_errno;
+ }
+
+ return 0;
+}
diff --git a/drivers/net/xsc/xsc_dev.h b/drivers/net/xsc/xsc_dev.h
index 86a0eee22e..e058ffdc21 100644
--- a/drivers/net/xsc/xsc_dev.h
+++ b/drivers/net/xsc/xsc_dev.h
@@ -35,6 +35,20 @@
#define XSC_EEPROM_HIGH_PAGE_LENGTH 128
#define XSC_EEPROM_MAX_BYTES 32
+enum xsc_dev_fec_config_bits {
+ XSC_DEV_FEC_NONE_BIT,
+ XSC_DEV_FEC_AUTO_BIT,
+ XSC_DEV_FEC_OFF_BIT,
+ XSC_DEV_FEC_RS_BIT,
+ XSC_DEV_FEC_BASER_BIT,
+};
+
+#define XSC_DEV_FEC_NONE (1 << XSC_DEV_FEC_NONE_BIT)
+#define XSC_DEV_FEC_AUTO (1 << XSC_DEV_FEC_AUTO_BIT)
+#define XSC_DEV_FEC_OFF (1 << XSC_DEV_FEC_OFF_BIT)
+#define XSC_DEV_FEC_RS (1 << XSC_DEV_FEC_RS_BIT)
+#define XSC_DEV_FEC_BASER (1 << XSC_DEV_FEC_BASER_BIT)
+
enum xsc_queue_type {
XSC_QUEUE_TYPE_RDMA_RC = 0,
XSC_QUEUE_TYPE_RDMA_MAD = 1,
@@ -262,5 +276,7 @@ int xsc_dev_query_module_eeprom(struct xsc_dev *xdev, uint16_t offset,
int xsc_dev_intr_event_get(struct xsc_dev *xdev);
int xsc_dev_intr_handler_install(struct xsc_dev *xdev, rte_intr_callback_fn cb, void *cb_arg);
int xsc_dev_intr_handler_uninstall(struct xsc_dev *xdev);
+int xsc_dev_fec_get(struct xsc_dev *xdev, uint32_t *fec_capa);
+int xsc_dev_fec_set(struct xsc_dev *xdev, uint32_t mode);
#endif /* _XSC_DEV_H_ */
diff --git a/drivers/net/xsc/xsc_ethdev.c b/drivers/net/xsc/xsc_ethdev.c
index 0884894a9b..261b49cff4 100644
--- a/drivers/net/xsc/xsc_ethdev.c
+++ b/drivers/net/xsc/xsc_ethdev.c
@@ -845,6 +845,22 @@ xsc_ethdev_get_module_eeprom(struct rte_eth_dev *dev,
return 0;
}
+static int
+xsc_ethdev_fec_get(struct rte_eth_dev *dev, uint32_t *fec_capa)
+{
+ struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
+
+ return xsc_dev_fec_get(priv->xdev, fec_capa);
+}
+
+static int
+xsc_ethdev_fec_set(struct rte_eth_dev *dev, uint32_t mode)
+{
+ struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
+
+ return xsc_dev_fec_set(priv->xdev, mode);
+}
+
const struct eth_dev_ops xsc_eth_dev_ops = {
.dev_configure = xsc_ethdev_configure,
.dev_start = xsc_ethdev_start,
@@ -868,6 +884,8 @@ const struct eth_dev_ops xsc_eth_dev_ops = {
.fw_version_get = xsc_ethdev_fw_version_get,
.get_module_info = xsc_ethdev_get_module_info,
.get_module_eeprom = xsc_ethdev_get_module_eeprom,
+ .fec_get = xsc_ethdev_fec_get,
+ .fec_set = xsc_ethdev_fec_set,
};
static int
--
2.25.1
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 08/14] net/xsc: optimize RSS queue creation
2025-08-29 8:24 [PATCH 00/14] net/xsc: PMD updates Renyong Wan
` (6 preceding siblings ...)
2025-08-29 8:24 ` [PATCH 07/14] net/xsc: add FEC get and set support Renyong Wan
@ 2025-08-29 8:24 ` Renyong Wan
2025-08-29 8:24 ` [PATCH 09/14] net/xsc: optimize QP and CQ memory allocation Renyong Wan
` (5 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Renyong Wan @ 2025-08-29 8:24 UTC (permalink / raw)
To: dev; +Cc: thomas, stephen, qianr, nana, zhangxx, xudw, jacky, weihg, zhenghy
Refactor RSS RX queue creation for the XSC PMD.
This patch introduces proper QPN allocation and per-QP info setup,
improving memory management and error handling. It makes RSS
queue creation more robust, avoiding partial resource leaks in
case of failures.
Signed-off-by: Rong Qian <qianr@yunsilicon.com>
Signed-off-by: Renyong Wan <wanry@yunsilicon.com>
---
drivers/net/xsc/xsc_cmd.h | 47 ++++++++
drivers/net/xsc/xsc_ethdev.c | 3 +
drivers/net/xsc/xsc_rx.c | 219 ++++++++++++++++++++++++++---------
3 files changed, 216 insertions(+), 53 deletions(-)
diff --git a/drivers/net/xsc/xsc_cmd.h b/drivers/net/xsc/xsc_cmd.h
index 2746131cf1..abf9d06197 100644
--- a/drivers/net/xsc/xsc_cmd.h
+++ b/drivers/net/xsc/xsc_cmd.h
@@ -23,6 +23,10 @@ enum xsc_cmd_opcode {
XSC_CMD_OP_RTR2RTS_QP = 0x504,
XSC_CMD_OP_QP_2RST = 0x50A,
XSC_CMD_OP_CREATE_MULTI_QP = 0x515,
+ XSC_CMD_OP_ALLOC_QPN = 0x519,
+ XSC_CMD_OP_FREE_QPN = 0x520,
+ XSC_CMD_OP_SET_QP_INFO = 0x521,
+ XSC_CMD_QP_UNSET_QP_INFO = 0x522,
XSC_CMD_OP_ACCESS_REG = 0x805,
XSC_CMD_OP_MODIFY_NIC_HCA = 0x812,
XSC_CMD_OP_MODIFY_RAW_QP = 0x81f,
@@ -497,4 +501,47 @@ struct xsc_cmd_modify_fecparam_mbox_out {
uint32_t status;
};
+struct xsc_cmd_alloc_qpn_mbox_in {
+ struct xsc_cmd_inbox_hdr hdr;
+ rte_be16_t qp_cnt;
+ uint8_t qp_type;
+ uint8_t rsvd[5];
+};
+
+struct xsc_cmd_alloc_qpn_mbox_out {
+ struct xsc_cmd_outbox_hdr hdr;
+ rte_be16_t qpn_base;
+};
+
+struct xsc_cmd_free_qpn_mbox_in {
+ struct xsc_cmd_inbox_hdr hdr;
+ rte_be16_t qpn_base;
+ rte_be16_t qp_cnt;
+ uint8_t qp_type;
+ uint8_t rsvd[3];
+};
+
+struct xsc_cmd_free_qpn_mbox_out {
+ struct xsc_cmd_outbox_hdr hdr;
+};
+
+struct xsc_cmd_set_qp_info_in {
+ struct xsc_cmd_inbox_hdr hdr;
+ struct xsc_cmd_create_qp_request qp_info;
+};
+
+struct xsc_cmd_set_qp_info_out {
+ struct xsc_cmd_outbox_hdr hdr;
+};
+
+struct xsc_cmd_unset_qp_info_in {
+ struct xsc_cmd_inbox_hdr hdr;
+ rte_be16_t qpn;
+ uint8_t rsvd[6];
+};
+
+struct xsc_cmd_unset_qp_info_out {
+ struct xsc_cmd_outbox_hdr hdr;
+};
+
#endif /* _XSC_CMD_H_ */
diff --git a/drivers/net/xsc/xsc_ethdev.c b/drivers/net/xsc/xsc_ethdev.c
index 261b49cff4..fc88caa9a2 100644
--- a/drivers/net/xsc/xsc_ethdev.c
+++ b/drivers/net/xsc/xsc_ethdev.c
@@ -296,6 +296,9 @@ xsc_rxq_start(struct xsc_ethdev_priv *priv)
if (ret != 0)
goto error;
+ for (i = 0; i != priv->num_rq; ++i)
+ priv->dev_data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
+
priv->flags |= XSC_FLAG_RX_QUEUE_INIT;
return 0;
error:
diff --git a/drivers/net/xsc/xsc_rx.c b/drivers/net/xsc/xsc_rx.c
index 65d63b94de..c65afab51d 100644
--- a/drivers/net/xsc/xsc_rx.c
+++ b/drivers/net/xsc/xsc_rx.c
@@ -256,31 +256,139 @@ xsc_rxq_initialize(struct xsc_dev *xdev, struct xsc_rxq_data *rxq_data)
rte_write32(rte_cpu_to_le_32(recv_db.recv_data), rxq_data->rq_db);
}
+static int
+xsc_alloc_qpn(struct xsc_dev *xdev, uint16_t *qpn_base, uint16_t qp_cnt)
+{
+ int ret;
+ struct xsc_cmd_alloc_qpn_mbox_in in = { };
+ struct xsc_cmd_alloc_qpn_mbox_out out = { };
+
+ in.hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_ALLOC_QPN);
+ in.qp_cnt = rte_cpu_to_be_16(qp_cnt);
+ in.qp_type = XSC_QUEUE_TYPE_RAW;
+
+ ret = xsc_dev_mailbox_exec(xdev, &in, sizeof(in), &out, sizeof(out));
+ if (ret != 0 || out.hdr.status != 0) {
+ PMD_DRV_LOG(ERR,
+ "Failed to allocate qpn, port id=%d, qp num=%d, "
+ "ret=%d, out.status=%u",
+ xdev->port_id, qp_cnt, ret, out.hdr.status);
+ rte_errno = ENOEXEC;
+ goto error;
+ }
+
+ *qpn_base = rte_be_to_cpu_16(out.qpn_base);
+ return 0;
+
+error:
+ return -rte_errno;
+}
+
+static int
+xsc_free_qpn(struct xsc_dev *xdev, uint16_t qpn_base, uint16_t qp_cnt)
+{
+ int ret;
+ struct xsc_cmd_free_qpn_mbox_in in = { };
+ struct xsc_cmd_free_qpn_mbox_out out = { };
+
+ in.hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_FREE_QPN);
+ in.qpn_base = rte_cpu_to_be_16(qpn_base);
+ in.qp_cnt = rte_cpu_to_be_16(qp_cnt);
+ in.qp_type = XSC_QUEUE_TYPE_RAW;
+
+ ret = xsc_dev_mailbox_exec(xdev, &in, sizeof(in), &out, sizeof(out));
+ if (ret != 0 || out.hdr.status != 0) {
+ PMD_DRV_LOG(ERR,
+ "Failed to free qpn, port id=%d, qpn base=%u, qp num=%d, "
+ "ret=%d, out.status=%u",
+ xdev->port_id, qpn_base, qp_cnt, ret, out.hdr.status);
+ rte_errno = ENOEXEC;
+ return -rte_errno;
+ }
+
+ return 0;
+}
+
+static int
+xsc_set_qp_info(struct xsc_dev *xdev, struct xsc_cmd_create_qp_request *qp_info, size_t pas_size)
+{
+ int ret;
+ size_t in_size;
+ struct xsc_cmd_set_qp_info_in *in;
+ struct xsc_cmd_set_qp_info_out out = { };
+
+ in_size = sizeof(*in) + pas_size;
+ in = malloc(in_size);
+ if (in == NULL) {
+ rte_errno = ENOMEM;
+ PMD_DRV_LOG(ERR, "Failed to allocate memory for setting qp info");
+ return -rte_errno;
+ }
+
+ in->hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_SET_QP_INFO);
+ memcpy(&in->qp_info, qp_info, sizeof(*qp_info) + pas_size);
+ ret = xsc_dev_mailbox_exec(xdev, in, in_size, &out, sizeof(out));
+ if (ret != 0 || out.hdr.status != 0) {
+ PMD_DRV_LOG(ERR,
+ "Failed to set qp info, port id=%d, ret=%d, out.status=%u",
+ xdev->port_id, ret, out.hdr.status);
+ rte_errno = ENOEXEC;
+ goto error;
+ }
+
+ free(in);
+ return 0;
+error:
+ free(in);
+ return -rte_errno;
+}
+
+static int
+xsc_unset_qp_info(struct xsc_dev *xdev, uint16_t qpn)
+{
+ int ret;
+ struct xsc_cmd_unset_qp_info_in in = { };
+ struct xsc_cmd_unset_qp_info_out out = { };
+
+ in.hdr.opcode = rte_cpu_to_be_16(XSC_CMD_QP_UNSET_QP_INFO);
+ in.qpn = rte_cpu_to_be_16(qpn);
+
+ ret = xsc_dev_mailbox_exec(xdev, &in, sizeof(in), &out, sizeof(out));
+ if (ret != 0 || out.hdr.status != 0) {
+ PMD_DRV_LOG(ERR,
+ "Failed to unset qp info, port id=%d, ret=%d, out.status=%u",
+ xdev->port_id, ret, out.hdr.status);
+ rte_errno = ENOEXEC;
+ return -rte_errno;
+ }
+
+ return 0;
+}
+
static int
xsc_rss_qp_create(struct xsc_ethdev_priv *priv, int port_id)
{
- struct xsc_cmd_create_multiqp_mbox_in *in;
- struct xsc_cmd_create_qp_request *req;
- struct xsc_cmd_create_multiqp_mbox_out *out;
- uint8_t log_ele;
- uint64_t iova;
+ int ret;
int wqe_n;
- int in_len, out_len, cmd_len;
int entry_total_len, entry_len;
- uint8_t log_rq_sz, log_sq_sz = 0;
uint32_t wqe_total_len;
- int j, ret;
- uint16_t i, pa_num;
- int rqn_base;
+ uint16_t rqn_base, pa_num;
+ uint16_t i, j;
+ uint16_t set_last_no = 0;
+ uint8_t log_ele, log_rq_sz, log_sq_sz = 0;
+ uint64_t iova;
+ size_t pas_size;
struct xsc_rxq_data *rxq_data;
struct xsc_dev *xdev = priv->xdev;
+ struct xsc_cmd_create_qp_request *req, *info;
struct xsc_hwinfo *hwinfo = &xdev->hwinfo;
char name[RTE_ETH_NAME_MAX_LEN] = { 0 };
- void *cmd_buf;
rxq_data = xsc_rxq_get(priv, 0);
- if (rxq_data == NULL)
- return -EINVAL;
+ if (rxq_data == NULL) {
+ rte_errno = EINVAL;
+ return -rte_errno;
+ }
log_ele = rte_log2_u32(sizeof(struct xsc_wqe_data_seg));
wqe_n = rxq_data->wqe_s;
@@ -291,37 +399,32 @@ xsc_rss_qp_create(struct xsc_ethdev_priv *priv, int port_id)
entry_len = sizeof(struct xsc_cmd_create_qp_request) + sizeof(uint64_t) * pa_num;
entry_total_len = entry_len * priv->num_rq;
- in_len = sizeof(struct xsc_cmd_create_multiqp_mbox_in) + entry_total_len;
- out_len = sizeof(struct xsc_cmd_create_multiqp_mbox_out) + entry_total_len;
- cmd_len = RTE_MAX(in_len, out_len);
- cmd_buf = malloc(cmd_len);
- if (cmd_buf == NULL) {
+ req = malloc(entry_total_len);
+ if (req == NULL) {
rte_errno = ENOMEM;
- PMD_DRV_LOG(ERR, "Alloc rss qp create cmd memory failed");
- goto error;
+ PMD_DRV_LOG(ERR, "Failed to alloc create qp request cmd memory");
+ return -rte_errno;
}
- in = cmd_buf;
- memset(in, 0, cmd_len);
- in->qp_num = rte_cpu_to_be_16((uint16_t)priv->num_rq);
- in->qp_type = XSC_QUEUE_TYPE_RAW;
- in->req_len = rte_cpu_to_be_32(cmd_len);
+ ret = xsc_alloc_qpn(xdev, &rqn_base, priv->num_rq);
+ if (ret != 0)
+ goto alloc_qpn_fail;
for (i = 0; i < priv->num_rq; i++) {
rxq_data = xsc_rxq_get(priv, i);
if (rxq_data == NULL) {
rte_errno = EINVAL;
- goto error;
+ goto set_qp_fail;
}
- req = (struct xsc_cmd_create_qp_request *)(&in->data[0] + entry_len * i);
- req->input_qpn = rte_cpu_to_be_16(0); /* useless for eth */
- req->pa_num = rte_cpu_to_be_16(pa_num);
- req->qp_type = XSC_QUEUE_TYPE_RAW;
- req->log_rq_sz = log_rq_sz;
- req->cqn_recv = rte_cpu_to_be_16((uint16_t)rxq_data->cqn);
- req->cqn_send = req->cqn_recv;
- req->glb_funcid = rte_cpu_to_be_16((uint16_t)hwinfo->func_id);
+ info = (struct xsc_cmd_create_qp_request *)((uint8_t *)req + entry_len * i);
+ info->input_qpn = rte_cpu_to_be_16(rqn_base + i);
+ info->pa_num = rte_cpu_to_be_16(pa_num);
+ info->qp_type = XSC_QUEUE_TYPE_RAW;
+ info->log_rq_sz = log_rq_sz;
+ info->cqn_recv = rte_cpu_to_be_16((uint16_t)rxq_data->cqn);
+ info->cqn_send = info->cqn_recv;
+ info->glb_funcid = rte_cpu_to_be_16((uint16_t)hwinfo->func_id);
/* Alloc pas addr */
snprintf(name, sizeof(name), "wqe_mem_rx_%d_%d", port_id, i);
rxq_data->rq_pas = rte_memzone_reserve_aligned(name,
@@ -330,32 +433,27 @@ xsc_rss_qp_create(struct xsc_ethdev_priv *priv, int port_id)
0, XSC_PAGE_SIZE);
if (rxq_data->rq_pas == NULL) {
rte_errno = ENOMEM;
- PMD_DRV_LOG(ERR, "Alloc rxq pas memory failed");
- goto error;
+ PMD_DRV_LOG(ERR, "Failed to alloc rxq pas memory");
+ goto set_qp_fail;
}
iova = rxq_data->rq_pas->iova;
for (j = 0; j < pa_num; j++)
- req->pas[j] = rte_cpu_to_be_64(iova + j * XSC_PAGE_SIZE);
- }
+ info->pas[j] = rte_cpu_to_be_64(iova + j * XSC_PAGE_SIZE);
- in->hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_CREATE_MULTI_QP);
- out = cmd_buf;
- ret = xsc_dev_mailbox_exec(xdev, in, in_len, out, out_len);
- if (ret != 0 || out->hdr.status != 0) {
- PMD_DRV_LOG(ERR,
- "Create rss rq failed, port id=%d, qp_num=%d, ret=%d, out.status=%u",
- port_id, priv->num_rq, ret, out->hdr.status);
- rte_errno = ENOEXEC;
- goto error;
+ pas_size = pa_num * sizeof(uint64_t);
+ ret = xsc_set_qp_info(xdev, info, pas_size);
+ if (ret != 0)
+ goto set_qp_fail;
+
+ set_last_no++;
}
- rqn_base = rte_be_to_cpu_32(out->qpn_base) & 0xffffff;
for (i = 0; i < priv->num_rq; i++) {
rxq_data = xsc_rxq_get(priv, i);
if (rxq_data == NULL) {
rte_errno = EINVAL;
- goto error;
+ goto set_qp_fail;
}
rxq_data->wqes = rxq_data->rq_pas->addr;
@@ -370,18 +468,33 @@ xsc_rss_qp_create(struct xsc_ethdev_priv *priv, int port_id)
xsc_dev_modify_qp_status(xdev, rxq_data->qpn, 1, XSC_CMD_OP_RTR2RTS_QP);
xsc_rxq_initialize(xdev, rxq_data);
rxq_data->cq_ci = 0;
- priv->dev_data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
PMD_DRV_LOG(INFO, "Port %d create rx qp, wqe_s:%d, wqe_n:%d, qp_db=%p, qpn:%u",
port_id,
rxq_data->wqe_s, rxq_data->wqe_n,
rxq_data->rq_db, rxq_data->qpn);
}
- free(cmd_buf);
+ free(req);
return 0;
-error:
- free(cmd_buf);
+set_qp_fail:
+ free(req);
+ for (i = 0; i < set_last_no; i++) {
+ xsc_unset_qp_info(xdev, rqn_base + i);
+ rxq_data = xsc_rxq_get(priv, i);
+ if (rxq_data == NULL) {
+ rte_errno = EINVAL;
+ goto set_qp_fail;
+ }
+ rte_memzone_free(rxq_data->rq_pas);
+ rxq_data->rq_pas = NULL;
+ }
+
+ xsc_free_qpn(xdev, rqn_base, priv->num_rq);
+ return -rte_errno;
+
+alloc_qpn_fail:
+ free(req);
return -rte_errno;
}
--
2.25.1
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 09/14] net/xsc: optimize QP and CQ memory allocation
2025-08-29 8:24 [PATCH 00/14] net/xsc: PMD updates Renyong Wan
` (7 preceding siblings ...)
2025-08-29 8:24 ` [PATCH 08/14] net/xsc: optimize RSS queue creation Renyong Wan
@ 2025-08-29 8:24 ` Renyong Wan
2025-08-29 8:24 ` [PATCH 10/14] net/xsc: optimize Rx path Renyong Wan
` (4 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Renyong Wan @ 2025-08-29 8:24 UTC (permalink / raw)
To: dev; +Cc: thomas, stephen, qianr, nana, zhangxx, xudw, jacky, weihg, zhenghy
Refactor memory allocation for XSC QP and CQ to use the local NUMA node.
Previously, allocations used SOCKET_ID_ANY, which could lead to remote
memory accesses. This patch ensures PAS and CQE memory are allocated
on the same NUMA node as the device, improving locality and performance.
Signed-off-by: Rong Qian <qianr@yunsilicon.com>
Signed-off-by: Renyong Wan <wanry@yunsilicon.com>
---
drivers/net/xsc/xsc_rx.c | 11 +++++++++--
drivers/net/xsc/xsc_rxtx.h | 3 +++
drivers/net/xsc/xsc_tx.c | 2 ++
drivers/net/xsc/xsc_vfio.c | 32 ++++++++++++++++++++++++++------
4 files changed, 40 insertions(+), 8 deletions(-)
diff --git a/drivers/net/xsc/xsc_rx.c b/drivers/net/xsc/xsc_rx.c
index c65afab51d..332ceb9606 100644
--- a/drivers/net/xsc/xsc_rx.c
+++ b/drivers/net/xsc/xsc_rx.c
@@ -383,6 +383,7 @@ xsc_rss_qp_create(struct xsc_ethdev_priv *priv, int port_id)
struct xsc_cmd_create_qp_request *req, *info;
struct xsc_hwinfo *hwinfo = &xdev->hwinfo;
char name[RTE_ETH_NAME_MAX_LEN] = { 0 };
+ uint32_t numa_node = priv->eth_dev->device->numa_node;
rxq_data = xsc_rxq_get(priv, 0);
if (rxq_data == NULL) {
@@ -390,6 +391,10 @@ xsc_rss_qp_create(struct xsc_ethdev_priv *priv, int port_id)
return -rte_errno;
}
+ if (numa_node != rxq_data->socket)
+ PMD_DRV_LOG(WARNING, "Port %u: rxq numa_node=%u, device numa_node=%u",
+ port_id, rxq_data->socket, numa_node);
+
log_ele = rte_log2_u32(sizeof(struct xsc_wqe_data_seg));
wqe_n = rxq_data->wqe_s;
log_rq_sz = rte_log2_u32(wqe_n * hwinfo->recv_seg_num);
@@ -429,8 +434,9 @@ xsc_rss_qp_create(struct xsc_ethdev_priv *priv, int port_id)
snprintf(name, sizeof(name), "wqe_mem_rx_%d_%d", port_id, i);
rxq_data->rq_pas = rte_memzone_reserve_aligned(name,
(XSC_PAGE_SIZE * pa_num),
- SOCKET_ID_ANY,
- 0, XSC_PAGE_SIZE);
+ rxq_data->socket,
+ RTE_MEMZONE_IOVA_CONTIG,
+ XSC_PAGE_SIZE);
if (rxq_data->rq_pas == NULL) {
rte_errno = ENOMEM;
PMD_DRV_LOG(ERR, "Failed to alloc rxq pas memory");
@@ -519,6 +525,7 @@ xsc_rxq_rss_obj_new(struct xsc_ethdev_priv *priv, uint16_t port_id)
cq_params.port_id = rxq_data->port_id;
cq_params.qp_id = rxq_data->idx;
cq_params.wqe_s = rxq_data->wqe_s;
+ cq_params.socket_id = rxq_data->socket;
ret = xsc_dev_rx_cq_create(xdev, &cq_params, &cq_info);
if (ret) {
diff --git a/drivers/net/xsc/xsc_rxtx.h b/drivers/net/xsc/xsc_rxtx.h
index 3606c151e6..129bbd2fa4 100644
--- a/drivers/net/xsc/xsc_rxtx.h
+++ b/drivers/net/xsc/xsc_rxtx.h
@@ -124,6 +124,7 @@ struct xsc_tx_cq_params {
uint16_t port_id;
uint16_t qp_id;
uint16_t elts_n;
+ int socket_id;
};
struct xsc_tx_cq_info {
@@ -141,6 +142,7 @@ struct xsc_tx_qp_params {
uint16_t port_id;
uint16_t qp_id;
uint16_t elts_n;
+ int socket_id;
};
struct xsc_tx_qp_info {
@@ -165,6 +167,7 @@ struct xsc_rx_cq_params {
uint16_t port_id;
uint16_t qp_id;
uint16_t wqe_s;
+ int socket_id;
};
struct xsc_rx_cq_info {
diff --git a/drivers/net/xsc/xsc_tx.c b/drivers/net/xsc/xsc_tx.c
index 07888a5641..265439fec0 100644
--- a/drivers/net/xsc/xsc_tx.c
+++ b/drivers/net/xsc/xsc_tx.c
@@ -37,6 +37,7 @@ xsc_txq_obj_new(struct xsc_dev *xdev, struct xsc_txq_data *txq_data, uint16_t id
cq_params.port_id = txq_data->port_id;
cq_params.qp_id = txq_data->idx;
cq_params.elts_n = txq_data->elts_n;
+ cq_params.socket_id = txq_data->socket;
ret = xsc_dev_tx_cq_create(xdev, &cq_params, &cq_info);
if (ret) {
rte_errno = errno;
@@ -60,6 +61,7 @@ xsc_txq_obj_new(struct xsc_dev *xdev, struct xsc_txq_data *txq_data, uint16_t id
qp_params.port_id = txq_data->port_id;
qp_params.qp_id = idx;
qp_params.elts_n = txq_data->elts_n;
+ qp_params.socket_id = txq_data->socket;
ret = xsc_dev_tx_qp_create(xdev, &qp_params, &qp_info);
if (ret != 0) {
diff --git a/drivers/net/xsc/xsc_vfio.c b/drivers/net/xsc/xsc_vfio.c
index 34b2a4c58b..1650a3ab2b 100644
--- a/drivers/net/xsc/xsc_vfio.c
+++ b/drivers/net/xsc/xsc_vfio.c
@@ -556,6 +556,11 @@ xsc_vfio_rx_cq_create(struct xsc_dev *xdev, struct xsc_rx_cq_params *cq_params,
struct xsc_cmd_create_cq_mbox_in *in = NULL;
struct xsc_cmd_create_cq_mbox_out *out = NULL;
void *cmd_buf;
+ int numa_node = xdev->pci_dev->device.numa_node;
+
+ if (numa_node != cq_params->socket_id)
+ PMD_DRV_LOG(WARNING, "Port %u rxq %u: cq numa_node=%u, device numa_node=%u",
+ port_id, idx, cq_params->socket_id, numa_node);
cqe_n = cq_params->wqe_s;
log_cq_sz = rte_log2_u32(cqe_n);
@@ -592,8 +597,9 @@ xsc_vfio_rx_cq_create(struct xsc_dev *xdev, struct xsc_rx_cq_params *cq_params,
snprintf(name, sizeof(name), "mz_cqe_mem_rx_%u_%u", port_id, idx);
cq_pas = rte_memzone_reserve_aligned(name,
(XSC_PAGE_SIZE * pa_num),
- SOCKET_ID_ANY,
- 0, XSC_PAGE_SIZE);
+ cq_params->socket_id,
+ RTE_MEMZONE_IOVA_CONTIG,
+ XSC_PAGE_SIZE);
if (cq_pas == NULL) {
rte_errno = ENOMEM;
PMD_DRV_LOG(ERR, "Failed to alloc rx cq pas memory");
@@ -658,6 +664,12 @@ xsc_vfio_tx_cq_create(struct xsc_dev *xdev, struct xsc_tx_cq_params *cq_params,
uint64_t iova;
int i;
void *cmd_buf = NULL;
+ int numa_node = xdev->pci_dev->device.numa_node;
+
+ if (numa_node != cq_params->socket_id)
+ PMD_DRV_LOG(WARNING, "Port %u txq %u: cq numa_node=%u, device numa_node=%u",
+ cq_params->port_id, cq_params->qp_id,
+ cq_params->socket_id, numa_node);
cq = rte_zmalloc(NULL, sizeof(struct xsc_vfio_cq), 0);
if (cq == NULL) {
@@ -672,8 +684,9 @@ xsc_vfio_tx_cq_create(struct xsc_dev *xdev, struct xsc_tx_cq_params *cq_params,
snprintf(name, sizeof(name), "mz_cqe_mem_tx_%u_%u", cq_params->port_id, cq_params->qp_id);
cq_pas = rte_memzone_reserve_aligned(name,
(XSC_PAGE_SIZE * pa_num),
- SOCKET_ID_ANY,
- 0, XSC_PAGE_SIZE);
+ cq_params->socket_id,
+ RTE_MEMZONE_IOVA_CONTIG,
+ XSC_PAGE_SIZE);
if (cq_pas == NULL) {
rte_errno = ENOMEM;
PMD_DRV_LOG(ERR, "Failed to alloc tx cq pas memory");
@@ -762,6 +775,12 @@ xsc_vfio_tx_qp_create(struct xsc_dev *xdev, struct xsc_tx_qp_params *qp_params,
char name[RTE_ETH_NAME_MAX_LEN] = {0};
void *cmd_buf = NULL;
bool tso_en = !!(qp_params->tx_offloads & RTE_ETH_TX_OFFLOAD_TCP_TSO);
+ int numa_node = xdev->pci_dev->device.numa_node;
+
+ if (numa_node != qp_params->socket_id)
+ PMD_DRV_LOG(WARNING, "Port %u: txq %u numa_node=%u, device numa_node=%u",
+ qp_params->port_id, qp_params->qp_id,
+ qp_params->socket_id, numa_node);
qp = rte_zmalloc(NULL, sizeof(struct xsc_vfio_qp), 0);
if (qp == NULL) {
@@ -777,8 +796,9 @@ xsc_vfio_tx_qp_create(struct xsc_dev *xdev, struct xsc_tx_qp_params *qp_params,
snprintf(name, sizeof(name), "mz_wqe_mem_tx_%u_%u", qp_params->port_id, qp_params->qp_id);
qp_pas = rte_memzone_reserve_aligned(name,
(XSC_PAGE_SIZE * pa_num),
- SOCKET_ID_ANY,
- 0, XSC_PAGE_SIZE);
+ qp_params->socket_id,
+ RTE_MEMZONE_IOVA_CONTIG,
+ XSC_PAGE_SIZE);
if (qp_pas == NULL) {
rte_errno = ENOMEM;
PMD_DRV_LOG(ERR, "Failed to alloc tx qp pas memory");
--
2.25.1
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 10/14] net/xsc: optimize Rx path
2025-08-29 8:24 [PATCH 00/14] net/xsc: PMD updates Renyong Wan
` (8 preceding siblings ...)
2025-08-29 8:24 ` [PATCH 09/14] net/xsc: optimize QP and CQ memory allocation Renyong Wan
@ 2025-08-29 8:24 ` Renyong Wan
2025-08-29 8:24 ` [PATCH 11/14] net/xsc: optimize stop and close Renyong Wan
` (3 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Renyong Wan @ 2025-08-29 8:24 UTC (permalink / raw)
To: dev; +Cc: thomas, stephen, qianr, nana, zhangxx, xudw, jacky, weihg, zhenghy
CQEs are not cache line aligned, which can cause cache conflicts when
polling Rx CQs under high-PPS load.
This patch checks CQ producer/consumer indices before processing packets,
reducing cache conflicts. The added MMIO read overhead is minor
compared to the latency caused by cache conflicts, improving observed
small-packet performance.
Signed-off-by: Rong Qian <qianr@yunsilicon.com>
Signed-off-by: Renyong Wan <wanry@yunsilicon.com>
---
drivers/net/xsc/xsc_defs.h | 2 ++
drivers/net/xsc/xsc_rx.c | 18 ++++++++++++++++--
drivers/net/xsc/xsc_rx.h | 1 +
drivers/net/xsc/xsc_vfio.c | 2 +-
4 files changed, 20 insertions(+), 3 deletions(-)
diff --git a/drivers/net/xsc/xsc_defs.h b/drivers/net/xsc/xsc_defs.h
index 4b95a0521d..73941901e7 100644
--- a/drivers/net/xsc/xsc_defs.h
+++ b/drivers/net/xsc/xsc_defs.h
@@ -46,10 +46,12 @@
#define XSC_PF_TX_DB_ADDR 0x4802000
#define XSC_PF_RX_DB_ADDR 0x4804000
#define XSC_PF_CQ_DB_ADDR 0x2120000
+#define XSC_PF_CQ_PID_START_ADDR 0x2080000
#define XSC_VF_RX_DB_ADDR 0x8d4
#define XSC_VF_TX_DB_ADDR 0x8d0
#define XSC_VF_CQ_DB_ADDR 0x8c4
+#define XSC_VF_CQ_PID_START_ADDR 0x60000
#define XSC_HIF_CMDQM_VECTOR_ID_MEM_ADDR 0x1034000
diff --git a/drivers/net/xsc/xsc_rx.c b/drivers/net/xsc/xsc_rx.c
index 332ceb9606..5f8003a1f6 100644
--- a/drivers/net/xsc/xsc_rx.c
+++ b/drivers/net/xsc/xsc_rx.c
@@ -83,6 +83,16 @@ xsc_rx_burst(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n)
int cqe_msg_len = 0;
volatile struct xsc_cqe_u64 *cqe_u64 = NULL;
struct rte_mbuf *rep;
+ uint16_t cq_pi;
+ uint16_t cqe_pkts_n = 0;
+
+ if (rxq->cq_pi != NULL) {
+ cq_pi = (*(volatile uint32_t *)(rxq->cq_pi)) & 0xFFFF;
+ if (cq_pi == rxq->cq_ci)
+ return 0;
+ cqe_pkts_n = (uint16_t)((cq_pi - rxq->cq_ci) & 0xFFFF);
+ pkts_n = pkts_n < cqe_pkts_n ? pkts_n : cqe_pkts_n;
+ }
while (pkts_n) {
uint32_t idx = rq_ci & wqe_m;
@@ -463,12 +473,16 @@ xsc_rss_qp_create(struct xsc_ethdev_priv *priv, int port_id)
}
rxq_data->wqes = rxq_data->rq_pas->addr;
- if (!xsc_dev_is_vf(xdev))
+ if (!xsc_dev_is_vf(xdev)) {
rxq_data->rq_db = (uint32_t *)((uint8_t *)xdev->bar_addr +
XSC_PF_RX_DB_ADDR);
- else
+ rxq_data->cq_pi = (uint32_t *)((uint8_t *)xdev->bar_addr +
+ XSC_PF_CQ_PID_START_ADDR + rxq_data->cqn * 4);
+ } else {
rxq_data->rq_db = (uint32_t *)((uint8_t *)xdev->bar_addr +
XSC_VF_RX_DB_ADDR);
+ rxq_data->cq_pi = NULL;
+ }
rxq_data->qpn = rqn_base + i;
xsc_dev_modify_qp_status(xdev, rxq_data->qpn, 1, XSC_CMD_OP_RTR2RTS_QP);
diff --git a/drivers/net/xsc/xsc_rx.h b/drivers/net/xsc/xsc_rx.h
index 90fbb89197..59cbbb5141 100644
--- a/drivers/net/xsc/xsc_rx.h
+++ b/drivers/net/xsc/xsc_rx.h
@@ -31,6 +31,7 @@ struct __rte_cache_aligned xsc_rxq_data {
uint16_t rsv0:4;
volatile uint32_t *rq_db;
volatile uint32_t *cq_db;
+ volatile uint32_t *cq_pi;
uint32_t rq_ci;
uint32_t rq_pi;
uint16_t cq_ci;
diff --git a/drivers/net/xsc/xsc_vfio.c b/drivers/net/xsc/xsc_vfio.c
index 1650a3ab2b..c233728c5f 100644
--- a/drivers/net/xsc/xsc_vfio.c
+++ b/drivers/net/xsc/xsc_vfio.c
@@ -562,7 +562,7 @@ xsc_vfio_rx_cq_create(struct xsc_dev *xdev, struct xsc_rx_cq_params *cq_params,
PMD_DRV_LOG(WARNING, "Port %u rxq %u: cq numa_node=%u, device numa_node=%u",
port_id, idx, cq_params->socket_id, numa_node);
- cqe_n = cq_params->wqe_s;
+ cqe_n = cq_params->wqe_s * 2;
log_cq_sz = rte_log2_u32(cqe_n);
cqe_total_sz = cqe_n * sizeof(struct xsc_cqe);
pa_num = (cqe_total_sz + XSC_PAGE_SIZE - 1) / XSC_PAGE_SIZE;
--
2.25.1
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 11/14] net/xsc: optimize stop and close
2025-08-29 8:24 [PATCH 00/14] net/xsc: PMD updates Renyong Wan
` (9 preceding siblings ...)
2025-08-29 8:24 ` [PATCH 10/14] net/xsc: optimize Rx path Renyong Wan
@ 2025-08-29 8:24 ` Renyong Wan
2025-08-29 8:24 ` [PATCH 12/14] net/xsc: support per port for multi-process Renyong Wan
` (2 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Renyong Wan @ 2025-08-29 8:24 UTC (permalink / raw)
To: dev; +Cc: thomas, stephen, qianr, nana, zhangxx, xudw, jacky, weihg, zhenghy
Refactor the stop and close paths for xsc PMD.
Previously, stopping or closing queues could leave partially freed
resources and relied on flags to track queue initialization.
This patch ensures all queue resources are properly released, improves
code clarity, and makes stop/close operations safer and more predictable.
Signed-off-by: Rong Qian <qianr@yunsilicon.com>
Signed-off-by: Renyong Wan <wanry@yunsilicon.com>
---
drivers/net/xsc/xsc_ethdev.c | 68 +++++++++++++++---------------------
drivers/net/xsc/xsc_ethdev.h | 4 ---
2 files changed, 28 insertions(+), 44 deletions(-)
diff --git a/drivers/net/xsc/xsc_ethdev.c b/drivers/net/xsc/xsc_ethdev.c
index fc88caa9a2..70417b2d5b 100644
--- a/drivers/net/xsc/xsc_ethdev.c
+++ b/drivers/net/xsc/xsc_ethdev.c
@@ -94,8 +94,9 @@ xsc_ethdev_txq_release(struct rte_eth_dev *dev, uint16_t idx)
{
struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
struct xsc_txq_data *txq_data = xsc_txq_get(priv, idx);
+ uint8_t txq_state = dev->data->tx_queue_state[idx];
- if (txq_data == NULL)
+ if (txq_data == NULL || txq_state == RTE_ETH_QUEUE_STATE_STOPPED)
return;
xsc_dev_set_qpsetid(priv->xdev, txq_data->qpn, 0);
@@ -103,10 +104,7 @@ xsc_ethdev_txq_release(struct rte_eth_dev *dev, uint16_t idx)
rte_free(txq_data->fcqs);
txq_data->fcqs = NULL;
xsc_txq_elts_free(txq_data);
- rte_free(txq_data);
- (*priv->txqs)[idx] = NULL;
- dev->data->tx_queues[idx] = NULL;
dev->data->tx_queue_state[idx] = RTE_ETH_QUEUE_STATE_STOPPED;
}
@@ -115,15 +113,14 @@ xsc_ethdev_rxq_release(struct rte_eth_dev *dev, uint16_t idx)
{
struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
struct xsc_rxq_data *rxq_data = xsc_rxq_get(priv, idx);
+ uint8_t rxq_state = dev->data->rx_queue_state[idx];
- if (rxq_data == NULL)
+ if (rxq_data == NULL || rxq_state == RTE_ETH_QUEUE_STATE_STOPPED)
return;
+
xsc_rxq_rss_obj_release(priv->xdev, rxq_data);
xsc_rxq_elts_free(rxq_data);
- rte_free(rxq_data);
- (*priv->rxqs)[idx] = NULL;
- dev->data->rx_queues[idx] = NULL;
dev->data->rx_queue_state[idx] = RTE_ETH_QUEUE_STATE_STOPPED;
}
@@ -207,8 +204,6 @@ xsc_rxq_stop(struct rte_eth_dev *dev)
for (i = 0; i != priv->num_rq; ++i)
xsc_ethdev_rxq_release(dev, i);
- priv->rxqs = NULL;
- priv->flags &= ~XSC_FLAG_RX_QUEUE_INIT;
}
static void
@@ -219,8 +214,6 @@ xsc_txq_stop(struct rte_eth_dev *dev)
for (i = 0; i != priv->num_sq; ++i)
xsc_ethdev_txq_release(dev, i);
- priv->txqs = NULL;
- priv->flags &= ~XSC_FLAG_TX_QUEUE_INIT;
}
static int
@@ -232,12 +225,6 @@ xsc_txq_start(struct xsc_ethdev_priv *priv)
int ret;
size_t size;
- if (priv->flags & XSC_FLAG_TX_QUEUE_INIT) {
- for (i = 0; i != priv->num_sq; ++i)
- dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
- return 0;
- }
-
for (i = 0; i != priv->num_sq; ++i) {
txq_data = xsc_txq_get(priv, i);
if (txq_data == NULL)
@@ -259,7 +246,6 @@ xsc_txq_start(struct xsc_ethdev_priv *priv)
}
}
- priv->flags |= XSC_FLAG_TX_QUEUE_INIT;
return 0;
error:
@@ -271,25 +257,16 @@ static int
xsc_rxq_start(struct xsc_ethdev_priv *priv)
{
struct xsc_rxq_data *rxq_data;
- struct rte_eth_dev *dev = priv->eth_dev;
uint16_t i;
int ret;
- if (priv->flags & XSC_FLAG_RX_QUEUE_INIT) {
- for (i = 0; i != priv->num_sq; ++i)
- dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
- return 0;
- }
-
for (i = 0; i != priv->num_rq; ++i) {
rxq_data = xsc_rxq_get(priv, i);
if (rxq_data == NULL)
goto error;
- if (dev->data->rx_queue_state[i] != RTE_ETH_QUEUE_STATE_STARTED) {
- ret = xsc_rxq_elts_alloc(rxq_data);
- if (ret != 0)
- goto error;
- }
+ ret = xsc_rxq_elts_alloc(rxq_data);
+ if (ret != 0)
+ goto error;
}
ret = xsc_rxq_rss_obj_new(priv, priv->dev_data->port_id);
@@ -299,7 +276,6 @@ xsc_rxq_start(struct xsc_ethdev_priv *priv)
for (i = 0; i != priv->num_rq; ++i)
priv->dev_data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
- priv->flags |= XSC_FLAG_RX_QUEUE_INIT;
return 0;
error:
/* Queue resources are released by xsc_ethdev_start calling the stop interface */
@@ -350,20 +326,14 @@ xsc_ethdev_start(struct rte_eth_dev *dev)
static int
xsc_ethdev_stop(struct rte_eth_dev *dev)
{
- struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
- uint16_t i;
-
PMD_DRV_LOG(DEBUG, "Port %u stopping", dev->data->port_id);
dev->data->dev_started = 0;
dev->rx_pkt_burst = rte_eth_pkt_burst_dummy;
dev->tx_pkt_burst = rte_eth_pkt_burst_dummy;
rte_wmb();
- rte_delay_us_sleep(1000 * priv->num_rq);
- for (i = 0; i < priv->num_rq; ++i)
- dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
- for (i = 0; i < priv->num_sq; ++i)
- dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
+ xsc_txq_stop(dev);
+ xsc_rxq_stop(dev);
return 0;
}
@@ -371,6 +341,9 @@ xsc_ethdev_stop(struct rte_eth_dev *dev)
static int
xsc_ethdev_close(struct rte_eth_dev *dev)
{
+ int idx;
+ struct xsc_rxq_data *rxq_data;
+ struct xsc_txq_data *txq_data;
struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(dev);
PMD_DRV_LOG(DEBUG, "Port %u closing", dev->data->port_id);
@@ -381,6 +354,21 @@ xsc_ethdev_close(struct rte_eth_dev *dev)
xsc_txq_stop(dev);
xsc_rxq_stop(dev);
+ for (idx = 0; idx < priv->num_rq; idx++) {
+ rxq_data = xsc_rxq_get(priv, idx);
+ rte_free(rxq_data);
+ dev->data->rx_queues[idx] = NULL;
+ }
+
+ for (idx = 0; idx < priv->num_sq; idx++) {
+ txq_data = xsc_txq_get(priv, idx);
+ rte_free(txq_data);
+ dev->data->tx_queues[idx] = NULL;
+ }
+
+ priv->rxqs = NULL;
+ priv->txqs = NULL;
+
rte_free(priv->rss_conf.rss_key);
if (!xsc_dev_is_vf(priv->xdev))
xsc_dev_intr_handler_uninstall(priv->xdev);
diff --git a/drivers/net/xsc/xsc_ethdev.h b/drivers/net/xsc/xsc_ethdev.h
index 0b307c2828..ed7d4ee60f 100644
--- a/drivers/net/xsc/xsc_ethdev.h
+++ b/drivers/net/xsc/xsc_ethdev.h
@@ -7,9 +7,6 @@
#include "xsc_dev.h"
-#define XSC_FLAG_RX_QUEUE_INIT 0x1
-#define XSC_FLAG_TX_QUEUE_INIT 0x2
-
struct xsc_ethdev_priv {
struct rte_eth_dev *eth_dev;
struct rte_pci_device *pci_dev;
@@ -37,7 +34,6 @@ struct xsc_ethdev_priv {
uint16_t num_sq;
uint16_t num_rq;
- uint16_t flags;
struct xsc_txq_data *(*txqs)[];
struct xsc_rxq_data *(*rxqs)[];
};
--
2.25.1
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 12/14] net/xsc: support per port for multi-process
2025-08-29 8:24 [PATCH 00/14] net/xsc: PMD updates Renyong Wan
` (10 preceding siblings ...)
2025-08-29 8:24 ` [PATCH 11/14] net/xsc: optimize stop and close Renyong Wan
@ 2025-08-29 8:24 ` Renyong Wan
2025-08-29 8:24 ` [PATCH 13/14] net/xsc: fix uninitialized value Renyong Wan
2025-08-29 8:24 ` [PATCH 14/14] net/xsc: update release notes for xsc PMD Renyong Wan
13 siblings, 0 replies; 15+ messages in thread
From: Renyong Wan @ 2025-08-29 8:24 UTC (permalink / raw)
To: dev; +Cc: thomas, stephen, qianr, nana, zhangxx, xudw, jacky, weihg, zhenghy
Previously, the PCT manager was shared across all ports, which prevented
two ports from operating independently in separate DPDK processes. This
patch makes the PCT manager per-port, allowing each port to manage its
resources separately.
Signed-off-by: Rong Qian <qianr@yunsilicon.com>
Signed-off-by: Renyong Wan <wanry@yunsilicon.com>
---
drivers/net/xsc/xsc_dev.c | 40 +++++++++++++++++++++--
drivers/net/xsc/xsc_dev.h | 4 +++
drivers/net/xsc/xsc_ethdev.c | 2 +-
drivers/net/xsc/xsc_np.c | 61 +++++++++++++++++++++---------------
drivers/net/xsc/xsc_np.h | 10 +++---
5 files changed, 83 insertions(+), 34 deletions(-)
diff --git a/drivers/net/xsc/xsc_dev.c b/drivers/net/xsc/xsc_dev.c
index 6b24ea98d0..b92bed3a40 100644
--- a/drivers/net/xsc/xsc_dev.c
+++ b/drivers/net/xsc/xsc_dev.c
@@ -324,7 +324,7 @@ void
xsc_dev_uninit(struct xsc_dev *xdev)
{
PMD_INIT_FUNC_TRACE();
- xsc_dev_pct_uninit();
+ xsc_dev_pct_uninit(xdev);
xsc_dev_close(xdev, XSC_DEV_REPR_ID_INVALID);
rte_free(xdev);
}
@@ -363,7 +363,11 @@ xsc_dev_init(struct rte_pci_device *pci_dev, struct xsc_dev **xdev)
goto hwinfo_init_fail;
}
- ret = xsc_dev_pct_init();
+ ret = xsc_dev_mac_port_init(d);
+ if (ret)
+ goto hwinfo_init_fail;
+
+ ret = xsc_dev_pct_init(d);
if (ret) {
PMD_DRV_LOG(ERR, "Failed to init xsc pct");
ret = -EINVAL;
@@ -689,3 +693,35 @@ xsc_dev_fec_set(struct xsc_dev *xdev, uint32_t mode)
return 0;
}
+
+int
+xsc_dev_mac_port_init(struct xsc_dev *xdev)
+{
+ uint32_t i;
+ uint8_t num = 0;
+ uint32_t mac_port = xdev->hwinfo.mac_phy_port;
+ uint8_t mac_bit = xdev->hwinfo.mac_bit;
+ uint8_t *mac_idx = &xdev->hwinfo.mac_port_idx;
+ uint8_t *mac_num = &xdev->hwinfo.mac_port_num;
+ uint8_t bit_sz = sizeof(mac_bit) * 8;
+
+ *mac_idx = 0xff;
+ for (i = 0; i < bit_sz; i++) {
+ if (mac_bit & (1U << i)) {
+ if (i == mac_port)
+ *mac_idx = num;
+ num++;
+ }
+ }
+ *mac_num = num;
+
+ if (*mac_num == 0 || *mac_idx == 0xff) {
+ PMD_DRV_LOG(ERR, "Failed to parse mac port %u index, mac bit 0x%x",
+ mac_port, mac_bit);
+ return -1;
+ }
+
+ PMD_DRV_LOG(DEBUG, "Mac port num %u, mac port %u, mac index %u",
+ *mac_num, mac_port, *mac_idx);
+ return 0;
+}
diff --git a/drivers/net/xsc/xsc_dev.h b/drivers/net/xsc/xsc_dev.h
index e058ffdc21..fc356375f1 100644
--- a/drivers/net/xsc/xsc_dev.h
+++ b/drivers/net/xsc/xsc_dev.h
@@ -124,6 +124,8 @@ struct xsc_hwinfo {
uint8_t pct_compress_vld;
uint8_t mac_bit;
uint8_t esw_mode;
+ uint8_t mac_port_idx;
+ uint8_t mac_port_num;
char fw_ver[XSC_FW_VERS_LEN];
};
@@ -185,6 +187,7 @@ struct xsc_dev {
int ctrl_fd;
rte_intr_callback_fn intr_cb;
void *intr_cb_arg;
+ struct xsc_dev_pct_mgr pct_mgr;
};
struct xsc_module_eeprom_query_params {
@@ -278,5 +281,6 @@ int xsc_dev_intr_handler_install(struct xsc_dev *xdev, rte_intr_callback_fn cb,
int xsc_dev_intr_handler_uninstall(struct xsc_dev *xdev);
int xsc_dev_fec_get(struct xsc_dev *xdev, uint32_t *fec_capa);
int xsc_dev_fec_set(struct xsc_dev *xdev, uint32_t mode);
+int xsc_dev_mac_port_init(struct xsc_dev *xdev);
#endif /* _XSC_DEV_H_ */
diff --git a/drivers/net/xsc/xsc_ethdev.c b/drivers/net/xsc/xsc_ethdev.c
index 70417b2d5b..6102c158e8 100644
--- a/drivers/net/xsc/xsc_ethdev.c
+++ b/drivers/net/xsc/xsc_ethdev.c
@@ -1091,7 +1091,7 @@ xsc_ethdev_uninit(struct rte_eth_dev *eth_dev)
}
ret |= xsc_ethdev_close(eth_dev);
- xsc_dev_pct_uninit();
+ xsc_dev_pct_uninit(priv->xdev);
rte_free(priv->xdev);
return ret == 0 ? 0 : -EIO;
diff --git a/drivers/net/xsc/xsc_np.c b/drivers/net/xsc/xsc_np.c
index 2b85fd93f8..4f872daec1 100644
--- a/drivers/net/xsc/xsc_np.c
+++ b/drivers/net/xsc/xsc_np.c
@@ -15,10 +15,8 @@
#define XSC_LOGIC_PORT_MASK 0x07FF
#define XSC_DEV_DEF_PCT_IDX_MIN 128
-#define XSC_DEV_DEF_PCT_IDX_MAX 138
-
-/* Each board has a PCT manager*/
-static struct xsc_dev_pct_mgr xsc_pct_mgr;
+#define XSC_DEV_DEF_PCT_IDX_MAX 191
+#define XSC_DEV_DEF_PCT_NUM (XSC_DEV_DEF_PCT_IDX_MAX - XSC_DEV_DEF_PCT_IDX_MIN + 1)
enum xsc_np_type {
XSC_NP_IPAT = 0,
@@ -207,13 +205,13 @@ xsc_dev_create_pct(struct xsc_dev *xdev, int repr_id,
add.key.logical_in_port = logical_in_port & XSC_LOGIC_PORT_MASK;
add.mask.logical_in_port = XSC_LOGIC_PORT_MASK;
add.action.dst_info = dst_info;
- add.pct_idx = xsc_dev_pct_idx_alloc();
+ add.pct_idx = xsc_dev_pct_idx_alloc(xdev);
if (add.pct_idx == XSC_DEV_PCT_IDX_INVALID)
return -1;
ret = xsc_dev_np_exec(xdev, &add, sizeof(add), XSC_NP_PCT_V4, XSC_NP_OP_ADD);
if (unlikely(ret != 0)) {
- xsc_dev_pct_idx_free(add.pct_idx);
+ xsc_dev_pct_idx_free(xdev, add.pct_idx);
return -1;
}
@@ -248,7 +246,7 @@ xsc_dev_clear_pct(struct xsc_dev *xdev, int repr_id)
while ((pct_entry = xsc_dev_pct_first_get(pct_list)) != NULL) {
xsc_dev_destroy_pct(xdev, pct_entry->logic_port, pct_entry->pct_idx);
- xsc_dev_pct_entry_remove(pct_entry);
+ xsc_dev_pct_entry_remove(xdev, pct_entry);
}
}
@@ -404,23 +402,23 @@ xsc_dev_create_vfos_baselp(struct xsc_dev *xdev)
}
void
-xsc_dev_pct_uninit(void)
+xsc_dev_pct_uninit(struct xsc_dev *xdev)
{
- rte_free(xsc_pct_mgr.bmp_mem);
- xsc_pct_mgr.bmp_mem = NULL;
+ rte_free(xdev->pct_mgr.bmp_mem);
+ xdev->pct_mgr.bmp_mem = NULL;
}
int
-xsc_dev_pct_init(void)
+xsc_dev_pct_init(struct xsc_dev *xdev)
{
int ret;
uint8_t *bmp_mem;
uint32_t pos, pct_sz, bmp_sz;
- if (xsc_pct_mgr.bmp_mem != NULL)
+ if (xdev->pct_mgr.bmp_mem != NULL)
return 0;
- pct_sz = XSC_DEV_DEF_PCT_IDX_MAX - XSC_DEV_DEF_PCT_IDX_MIN + 1;
+ pct_sz = XSC_DEV_DEF_PCT_NUM / xdev->hwinfo.mac_port_num;
bmp_sz = rte_bitmap_get_memory_footprint(pct_sz);
bmp_mem = rte_zmalloc(NULL, bmp_sz, RTE_CACHE_LINE_SIZE);
if (bmp_mem == NULL) {
@@ -429,9 +427,9 @@ xsc_dev_pct_init(void)
goto pct_init_fail;
}
- xsc_pct_mgr.bmp_mem = bmp_mem;
- xsc_pct_mgr.bmp_pct = rte_bitmap_init(pct_sz, bmp_mem, bmp_sz);
- if (xsc_pct_mgr.bmp_pct == NULL) {
+ xdev->pct_mgr.bmp_mem = bmp_mem;
+ xdev->pct_mgr.bmp_pct = rte_bitmap_init(pct_sz, bmp_mem, bmp_sz);
+ if (xdev->pct_mgr.bmp_pct == NULL) {
PMD_DRV_LOG(ERR, "Failed to init pct bitmap");
ret = -EINVAL;
goto pct_init_fail;
@@ -439,27 +437,32 @@ xsc_dev_pct_init(void)
/* Mark all pct bitmap available */
for (pos = 0; pos < pct_sz; pos++)
- rte_bitmap_set(xsc_pct_mgr.bmp_pct, pos);
+ rte_bitmap_set(xdev->pct_mgr.bmp_pct, pos);
return 0;
pct_init_fail:
- xsc_dev_pct_uninit();
+ xsc_dev_pct_uninit(xdev);
return ret;
}
uint32_t
-xsc_dev_pct_idx_alloc(void)
+xsc_dev_pct_idx_alloc(struct xsc_dev *xdev)
{
int ret;
uint64_t slab = 0;
uint32_t pos = 0;
+ uint8_t mac_num = xdev->hwinfo.mac_port_num;
+ uint8_t mac_idx = xdev->hwinfo.mac_port_idx;
+ struct rte_bitmap *bmp_pct = xdev->pct_mgr.bmp_pct;
+ uint32_t pct_range = XSC_DEV_DEF_PCT_NUM / mac_num;
+ uint32_t pct_base = XSC_DEV_DEF_PCT_IDX_MIN + mac_idx * pct_range;
- ret = rte_bitmap_scan(xsc_pct_mgr.bmp_pct, &pos, &slab);
+ ret = rte_bitmap_scan(bmp_pct, &pos, &slab);
if (ret != 0) {
pos += rte_bsf64(slab);
- rte_bitmap_clear(xsc_pct_mgr.bmp_pct, pos);
- return (pos + XSC_DEV_DEF_PCT_IDX_MIN);
+ rte_bitmap_clear(bmp_pct, pos);
+ return (pos + pct_base);
}
PMD_DRV_LOG(ERR, "Failed to alloc xsc pct idx");
@@ -467,9 +470,15 @@ xsc_dev_pct_idx_alloc(void)
}
void
-xsc_dev_pct_idx_free(uint32_t pct_idx)
+xsc_dev_pct_idx_free(struct xsc_dev *xdev, uint32_t pct_idx)
{
- rte_bitmap_set(xsc_pct_mgr.bmp_pct, pct_idx - XSC_DEV_DEF_PCT_IDX_MIN);
+ uint8_t mac_num = xdev->hwinfo.mac_port_num;
+ uint8_t mac_idx = xdev->hwinfo.mac_port_idx;
+ struct rte_bitmap *bmp_pct = xdev->pct_mgr.bmp_pct;
+ uint32_t pct_range = XSC_DEV_DEF_PCT_NUM / mac_num;
+ uint32_t pct_base = XSC_DEV_DEF_PCT_IDX_MIN + mac_idx * pct_range;
+
+ rte_bitmap_set(bmp_pct, pct_idx - pct_base);
}
int
@@ -501,12 +510,12 @@ xsc_dev_pct_first_get(struct xsc_dev_pct_list *pct_list)
}
int
-xsc_dev_pct_entry_remove(struct xsc_dev_pct_entry *pct_entry)
+xsc_dev_pct_entry_remove(struct xsc_dev *xdev, struct xsc_dev_pct_entry *pct_entry)
{
if (pct_entry == NULL)
return -1;
- xsc_dev_pct_idx_free(pct_entry->pct_idx);
+ xsc_dev_pct_idx_free(xdev, pct_entry->pct_idx);
LIST_REMOVE(pct_entry, next);
rte_free(pct_entry);
diff --git a/drivers/net/xsc/xsc_np.h b/drivers/net/xsc/xsc_np.h
index ca185c0a59..dadb24be46 100644
--- a/drivers/net/xsc/xsc_np.h
+++ b/drivers/net/xsc/xsc_np.h
@@ -148,13 +148,13 @@ int xsc_dev_modify_epat_mac_filter(struct xsc_dev *xdev, uint16_t dst_info,
int xsc_dev_destroy_epat(struct xsc_dev *xdev, uint16_t dst_info);
int xsc_dev_set_qpsetid(struct xsc_dev *xdev, uint32_t txqpn, uint16_t qp_set_id);
int xsc_dev_create_vfos_baselp(struct xsc_dev *xdev);
-void xsc_dev_pct_uninit(void);
-int xsc_dev_pct_init(void);
-uint32_t xsc_dev_pct_idx_alloc(void);
-void xsc_dev_pct_idx_free(uint32_t pct_idx);
+void xsc_dev_pct_uninit(struct xsc_dev *xdev);
+int xsc_dev_pct_init(struct xsc_dev *xdev);
+uint32_t xsc_dev_pct_idx_alloc(struct xsc_dev *xdev);
+void xsc_dev_pct_idx_free(struct xsc_dev *xdev, uint32_t pct_idx);
int xsc_dev_pct_entry_insert(struct xsc_dev_pct_list *pct_list,
uint32_t logic_port, uint32_t pct_idx);
struct xsc_dev_pct_entry *xsc_dev_pct_first_get(struct xsc_dev_pct_list *pct_list);
-int xsc_dev_pct_entry_remove(struct xsc_dev_pct_entry *pct_entry);
+int xsc_dev_pct_entry_remove(struct xsc_dev *xdev, struct xsc_dev_pct_entry *pct_entry);
#endif /* _XSC_NP_H_ */
--
2.25.1
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 13/14] net/xsc: fix uninitialized value
2025-08-29 8:24 [PATCH 00/14] net/xsc: PMD updates Renyong Wan
` (11 preceding siblings ...)
2025-08-29 8:24 ` [PATCH 12/14] net/xsc: support per port for multi-process Renyong Wan
@ 2025-08-29 8:24 ` Renyong Wan
2025-08-29 8:24 ` [PATCH 14/14] net/xsc: update release notes for xsc PMD Renyong Wan
13 siblings, 0 replies; 15+ messages in thread
From: Renyong Wan @ 2025-08-29 8:24 UTC (permalink / raw)
To: dev; +Cc: thomas, stephen, qianr, nana, zhangxx, xudw, jacky, weihg, zhenghy
Coverity reported this issue: Using uninitialized value mac when calling
xsc_ethdev_mac_addr_add.
Coverity issue: 456592
Fixes: 0b0f9c161e ("net/xsc: initialize representors")
Signed-off-by: Rong Qian <qianr@yunsilicon.com>
Signed-off-by: Renyong Wan <wanry@yunsilicon.com>
---
drivers/net/xsc/xsc_ethdev.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/xsc/xsc_ethdev.c b/drivers/net/xsc/xsc_ethdev.c
index 6102c158e8..988d734b5b 100644
--- a/drivers/net/xsc/xsc_ethdev.c
+++ b/drivers/net/xsc/xsc_ethdev.c
@@ -886,7 +886,7 @@ xsc_ethdev_init_one_representor(struct rte_eth_dev *eth_dev, void *init_params)
struct xsc_repr_port *repr_port = (struct xsc_repr_port *)init_params;
struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(eth_dev);
struct xsc_dev_config *config = &priv->config;
- struct rte_ether_addr mac;
+ struct rte_ether_addr mac = priv->mac[0];
priv->repr_port = repr_port;
repr_port->drv_data = eth_dev;
--
2.25.1
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 14/14] net/xsc: update release notes for xsc PMD
2025-08-29 8:24 [PATCH 00/14] net/xsc: PMD updates Renyong Wan
` (12 preceding siblings ...)
2025-08-29 8:24 ` [PATCH 13/14] net/xsc: fix uninitialized value Renyong Wan
@ 2025-08-29 8:24 ` Renyong Wan
13 siblings, 0 replies; 15+ messages in thread
From: Renyong Wan @ 2025-08-29 8:24 UTC (permalink / raw)
To: dev; +Cc: thomas, stephen, qianr, nana, zhangxx, xudw, jacky, weihg, zhenghy
Add recent updates of xsc PMD to 25.11 release notes.
Signed-off-by: Renyong Wan <wanry@yunsilicon.com>
---
doc/guides/rel_notes/release_25_11.rst | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/doc/guides/rel_notes/release_25_11.rst b/doc/guides/rel_notes/release_25_11.rst
index 122029b3c8..f1cb435689 100644
--- a/doc/guides/rel_notes/release_25_11.rst
+++ b/doc/guides/rel_notes/release_25_11.rst
@@ -64,6 +64,19 @@ New Features
* Enabled software taildrop for ordered queues.
+* **Updated Yunsilicon xsc ethernet driver.**
+
+ * Add FW version get
+ * Add TSO support
+ * Add module EEPROM dump
+ * Promiscuous mode support
+ * Link status support
+ * Link event support
+ * Add FEC get and set
+ * support per port for multi-process
+ * Code optimizations
+ * Coverity issue fix
+
Removed Items
-------------
--
2.25.1
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 00/14] net/xsc: PMD updates
@ 2025-08-29 8:24 Renyong Wan
2025-08-29 8:24 ` [PATCH 01/14] net/xsc: add FW version get support Renyong Wan
` (13 more replies)
0 siblings, 14 replies; 15+ messages in thread
From: Renyong Wan @ 2025-08-29 8:24 UTC (permalink / raw)
To: dev; +Cc: thomas, stephen, qianr, nana, zhangxx, xudw, jacky, weihg, zhenghy
This series introduces multiple updates to the Yunsilicon xsc PMD,
including new feature support, optimizations, bug fixes.
Highlights include:
* Firmware version query support
* TSO and FEC support
* EEPROM dump and promiscuous mode
* Link status and event support
* Optimizations for RSS, QP/CQ allocation, and Rx path
* Fix for Coverity-reported issue
Renyong Wan (14):
net/xsc: add FW version get support
net/xsc: add TSO support
net/xsc: support module EEPROM dump
net/xsc: support promiscuous mode
net/xsc: add link status support
net/xsc: add link status event support
net/xsc: add FEC get and set support
net/xsc: optimize RSS queue creation
net/xsc: optimize QP and CQ memory allocation
net/xsc: optimize Rx path
net/xsc: optimize stop and close
net/xsc: support per port for multi-process
net/xsc: fix uninitialized value
net/xsc: update release notes for xsc PMD
doc/guides/nics/features/xsc.ini | 7 +
doc/guides/rel_notes/release_25_11.rst | 13 +
drivers/net/xsc/xsc_cmd.h | 186 +++++++++++-
drivers/net/xsc/xsc_defs.h | 5 +
drivers/net/xsc/xsc_dev.c | 361 ++++++++++++++++++++--
drivers/net/xsc/xsc_dev.h | 116 ++++++-
drivers/net/xsc/xsc_ethdev.c | 334 +++++++++++++++++----
drivers/net/xsc/xsc_ethdev.h | 4 -
drivers/net/xsc/xsc_np.c | 89 ++++--
drivers/net/xsc/xsc_np.h | 34 ++-
drivers/net/xsc/xsc_rx.c | 248 +++++++++++----
drivers/net/xsc/xsc_rx.h | 1 +
drivers/net/xsc/xsc_rxtx.h | 3 +
drivers/net/xsc/xsc_tx.c | 14 +-
drivers/net/xsc/xsc_tx.h | 3 +-
drivers/net/xsc/xsc_vfio.c | 399 ++++++++++++++++++++++++-
16 files changed, 1605 insertions(+), 212 deletions(-)
--
2.25.1
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2025-08-29 8:25 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-08-29 8:24 [PATCH 00/14] net/xsc: PMD updates Renyong Wan
2025-08-29 8:24 ` [PATCH 01/14] net/xsc: add FW version get support Renyong Wan
2025-08-29 8:24 ` [PATCH 02/14] net/xsc: add TSO support Renyong Wan
2025-08-29 8:24 ` [PATCH 03/14] net/xsc: support module EEPROM dump Renyong Wan
2025-08-29 8:24 ` [PATCH 04/14] net/xsc: support promiscuous mode Renyong Wan
2025-08-29 8:24 ` [PATCH 05/14] net/xsc: add link status support Renyong Wan
2025-08-29 8:24 ` [PATCH 06/14] net/xsc: add link status event support Renyong Wan
2025-08-29 8:24 ` [PATCH 07/14] net/xsc: add FEC get and set support Renyong Wan
2025-08-29 8:24 ` [PATCH 08/14] net/xsc: optimize RSS queue creation Renyong Wan
2025-08-29 8:24 ` [PATCH 09/14] net/xsc: optimize QP and CQ memory allocation Renyong Wan
2025-08-29 8:24 ` [PATCH 10/14] net/xsc: optimize Rx path Renyong Wan
2025-08-29 8:24 ` [PATCH 11/14] net/xsc: optimize stop and close Renyong Wan
2025-08-29 8:24 ` [PATCH 12/14] net/xsc: support per port for multi-process Renyong Wan
2025-08-29 8:24 ` [PATCH 13/14] net/xsc: fix uninitialized value Renyong Wan
2025-08-29 8:24 ` [PATCH 14/14] net/xsc: update release notes for xsc PMD Renyong Wan
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).