* [PATCH v5 10/24] bus/dpaa: replace rte_atomic16 with stdatomic
From: Stephen Hemminger @ 2026-06-20 2:28 UTC (permalink / raw)
To: dev; +Cc: Stephen Hemminger, Hemant Agrawal, Sachin Saxena
In-Reply-To: <20260620023134.42877-1-stephen@networkplumber.org>
This is simple inuse flag which can be done with stdatomic
exchange logic.
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
drivers/bus/dpaa/base/qbman/qman.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/drivers/bus/dpaa/base/qbman/qman.c b/drivers/bus/dpaa/base/qbman/qman.c
index 5534e1846c..82a976141a 100644
--- a/drivers/bus/dpaa/base/qbman/qman.c
+++ b/drivers/bus/dpaa/base/qbman/qman.c
@@ -11,6 +11,7 @@
#include <rte_eventdev.h>
#include <rte_byteorder.h>
#include <rte_dpaa_logs.h>
+#include <rte_stdatomic.h>
#include <eal_export.h>
#include <dpaa_bits.h>
@@ -683,7 +684,7 @@ qman_init_portal(struct qman_portal *portal,
#define MAX_GLOBAL_PORTALS 8
static struct qman_portal global_portals[MAX_GLOBAL_PORTALS];
-static rte_atomic16_t global_portals_used[MAX_GLOBAL_PORTALS];
+static RTE_ATOMIC(bool) global_portals_used[MAX_GLOBAL_PORTALS];
struct qman_portal *
qman_alloc_global_portal(struct qm_portal_config *q_pcfg)
@@ -691,7 +692,8 @@ qman_alloc_global_portal(struct qm_portal_config *q_pcfg)
unsigned int i;
for (i = 0; i < MAX_GLOBAL_PORTALS; i++) {
- if (rte_atomic16_test_and_set(&global_portals_used[i])) {
+ if (!rte_atomic_exchange_explicit(&global_portals_used[i], true,
+ rte_memory_order_acquire)) {
global_portals[i].config = q_pcfg;
return &global_portals[i];
}
@@ -708,7 +710,8 @@ qman_free_global_portal(struct qman_portal *portal)
for (i = 0; i < MAX_GLOBAL_PORTALS; i++) {
if (&global_portals[i] == portal) {
- rte_atomic16_clear(&global_portals_used[i]);
+ rte_atomic_store_explicit(&global_portals_used[i], false,
+ rte_memory_order_release);
return 0;
}
}
--
2.53.0
^ permalink raw reply related
* [PATCH v5 09/24] crypto/ccp: replace use of rte_atomic64 with stdatomic
From: Stephen Hemminger @ 2026-06-20 2:28 UTC (permalink / raw)
To: dev; +Cc: Stephen Hemminger, Sunil Uttarwar
In-Reply-To: <20260620023134.42877-1-stephen@networkplumber.org>
The rte_atomicNN functions are deprecated. Replace the free
count with stdatomic.
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
drivers/crypto/ccp/ccp_crypto.c | 11 +++++++----
drivers/crypto/ccp/ccp_crypto.h | 2 +-
drivers/crypto/ccp/ccp_dev.c | 10 ++++++----
drivers/crypto/ccp/ccp_dev.h | 4 ++--
4 files changed, 16 insertions(+), 11 deletions(-)
diff --git a/drivers/crypto/ccp/ccp_crypto.c b/drivers/crypto/ccp/ccp_crypto.c
index 5899d83bae..1800ad41c9 100644
--- a/drivers/crypto/ccp/ccp_crypto.c
+++ b/drivers/crypto/ccp/ccp_crypto.c
@@ -2683,7 +2683,8 @@ process_ops_to_enqueue(struct ccp_qp *qp,
b_info->cmd_q = cmd_q;
b_info->lsb_buf_phys = (phys_addr_t)rte_mem_virt2iova((void *)b_info->lsb_buf);
- rte_atomic64_sub(&b_info->cmd_q->free_slots, slots_req);
+ rte_atomic_fetch_sub_explicit(&b_info->cmd_q->free_slots, slots_req,
+ rte_memory_order_seq_cst);
b_info->head_offset = (uint32_t)(cmd_q->qbase_phys_addr + cmd_q->qidx *
Q_DESC_SIZE);
@@ -2729,8 +2730,9 @@ process_ops_to_enqueue(struct ccp_qp *qp,
result = -1;
}
if (unlikely(result < 0)) {
- rte_atomic64_add(&b_info->cmd_q->free_slots,
- (slots_req - b_info->desccnt));
+ rte_atomic_fetch_add_explicit(&b_info->cmd_q->free_slots,
+ slots_req - b_info->desccnt,
+ rte_memory_order_seq_cst);
break;
}
b_info->op[i] = op[i];
@@ -2914,7 +2916,8 @@ process_ops_to_dequeue(struct ccp_qp *qp,
success:
*total_nb_ops = b_info->total_nb_ops;
nb_ops = ccp_prepare_ops(qp, op, b_info, nb_ops);
- rte_atomic64_add(&b_info->cmd_q->free_slots, b_info->desccnt);
+ rte_atomic_fetch_add_explicit(&b_info->cmd_q->free_slots, b_info->desccnt,
+ rte_memory_order_seq_cst);
b_info->desccnt = 0;
if (b_info->opcnt > 0) {
qp->b_info = b_info;
diff --git a/drivers/crypto/ccp/ccp_crypto.h b/drivers/crypto/ccp/ccp_crypto.h
index d0b417ca29..5c61b1582d 100644
--- a/drivers/crypto/ccp/ccp_crypto.h
+++ b/drivers/crypto/ccp/ccp_crypto.h
@@ -10,7 +10,7 @@
#include <stdint.h>
#include <string.h>
-#include <rte_atomic.h>
+#include <rte_stdatomic.h>
#include <rte_byteorder.h>
#include <rte_io.h>
#include <rte_pci.h>
diff --git a/drivers/crypto/ccp/ccp_dev.c b/drivers/crypto/ccp/ccp_dev.c
index 5088d8ded6..a75816cdfc 100644
--- a/drivers/crypto/ccp/ccp_dev.c
+++ b/drivers/crypto/ccp/ccp_dev.c
@@ -47,14 +47,15 @@ ccp_allot_queue(struct rte_cryptodev *cdev, int slot_req)
priv->last_dev = dev;
if (dev->qidx >= dev->cmd_q_count)
dev->qidx = 0;
- ret = rte_atomic64_read(&dev->cmd_q[dev->qidx].free_slots);
+ ret = rte_atomic_load_explicit(&dev->cmd_q[dev->qidx].free_slots, rte_memory_order_relaxed);
if (ret >= slot_req)
return &dev->cmd_q[dev->qidx];
for (i = 0; i < dev->cmd_q_count; i++) {
dev->qidx++;
if (dev->qidx >= dev->cmd_q_count)
dev->qidx = 0;
- ret = rte_atomic64_read(&dev->cmd_q[dev->qidx].free_slots);
+ ret = rte_atomic_load_explicit(&dev->cmd_q[dev->qidx].free_slots,
+ rte_memory_order_relaxed);
if (ret >= slot_req)
return &dev->cmd_q[dev->qidx];
}
@@ -583,8 +584,9 @@ ccp_add_device(struct ccp_device *dev)
CCP_LOG_ERR("queue doesn't have lsb regions");
cmd_q->lsb = -1;
- rte_atomic64_init(&cmd_q->free_slots);
- rte_atomic64_set(&cmd_q->free_slots, (COMMANDS_PER_QUEUE - 1));
+ rte_atomic_store_explicit(&cmd_q->free_slots,
+ COMMANDS_PER_QUEUE - 1,
+ rte_memory_order_seq_cst);
/* unused slot barrier b/w H&T */
}
diff --git a/drivers/crypto/ccp/ccp_dev.h b/drivers/crypto/ccp/ccp_dev.h
index cd63830759..8c408ac8d3 100644
--- a/drivers/crypto/ccp/ccp_dev.h
+++ b/drivers/crypto/ccp/ccp_dev.h
@@ -11,7 +11,7 @@
#include <string.h>
#include <bus_pci_driver.h>
-#include <rte_atomic.h>
+#include <rte_stdatomic.h>
#include <rte_byteorder.h>
#include <rte_io.h>
#include <rte_pci.h>
@@ -182,7 +182,7 @@ struct __rte_cache_aligned ccp_queue {
struct ccp_device *dev;
char memz_name[RTE_MEMZONE_NAMESIZE];
- rte_atomic64_t free_slots;
+ RTE_ATOMIC(int64_t) free_slots;
/**< available free slots updated from enq/deq calls */
/* Queue identifier */
--
2.53.0
^ permalink raw reply related
* [PATCH v5 08/24] net/sfc: replace rte_atomic with stdatomic
From: Stephen Hemminger @ 2026-06-20 2:28 UTC (permalink / raw)
To: dev; +Cc: Stephen Hemminger, Andrew Rybchenko
In-Reply-To: <20260620023134.42877-1-stephen@networkplumber.org>
The rte_atomicNN functions are deprecated and need to be replaced.
Use stdatomic for the restart required flag.
Use existing ethdev helper to set link status.
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
Reviewed-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
---
drivers/net/sfc/sfc.c | 9 +++++----
drivers/net/sfc/sfc.h | 4 ++--
drivers/net/sfc/sfc_port.c | 7 +------
drivers/net/sfc/sfc_stats.h | 2 +-
4 files changed, 9 insertions(+), 13 deletions(-)
diff --git a/drivers/net/sfc/sfc.c b/drivers/net/sfc/sfc.c
index 39cd8d519a..f13c5e2460 100644
--- a/drivers/net/sfc/sfc.c
+++ b/drivers/net/sfc/sfc.c
@@ -670,8 +670,8 @@ sfc_restart_if_required(void *arg)
struct sfc_adapter *sa = arg;
/* If restart is scheduled, clear the flag and do it */
- if (rte_atomic32_cmpset((volatile uint32_t *)&sa->restart_required,
- 1, 0)) {
+ if (rte_atomic_exchange_explicit(&sa->restart_required, false,
+ rte_memory_order_seq_cst)) {
sfc_adapter_lock(sa);
if (sa->state == SFC_ETHDEV_STARTED)
(void)sfc_restart(sa);
@@ -685,7 +685,8 @@ sfc_schedule_restart(struct sfc_adapter *sa)
int rc;
/* Schedule restart alarm if it is not scheduled yet */
- if (!rte_atomic32_test_and_set(&sa->restart_required))
+ if (rte_atomic_exchange_explicit(&sa->restart_required, true,
+ rte_memory_order_seq_cst))
return;
rc = rte_eal_alarm_set(1, sfc_restart_if_required, sa);
@@ -1292,7 +1293,7 @@ sfc_probe(struct sfc_adapter *sa)
SFC_ASSERT(sfc_adapter_is_locked(sa));
sa->socket_id = rte_socket_id();
- rte_atomic32_init(&sa->restart_required);
+ sa->restart_required = false;
sfc_log_init(sa, "get family");
rc = sfc_efx_family(pci_dev, &mem_ebrp, &sa->family);
diff --git a/drivers/net/sfc/sfc.h b/drivers/net/sfc/sfc.h
index 629578549f..515e1e708d 100644
--- a/drivers/net/sfc/sfc.h
+++ b/drivers/net/sfc/sfc.h
@@ -17,7 +17,7 @@
#include <ethdev_driver.h>
#include <rte_kvargs.h>
#include <rte_spinlock.h>
-#include <rte_atomic.h>
+#include <rte_stdatomic.h>
#include "efx.h"
@@ -239,7 +239,7 @@ struct sfc_adapter {
efx_family_t family;
efx_nic_t *nic;
rte_spinlock_t nic_lock;
- rte_atomic32_t restart_required;
+ RTE_ATOMIC(bool) restart_required;
struct sfc_efx_mcdi mcdi;
struct sfc_sriov sriov;
diff --git a/drivers/net/sfc/sfc_port.c b/drivers/net/sfc/sfc_port.c
index 33b53f7ac8..d84648d454 100644
--- a/drivers/net/sfc/sfc_port.c
+++ b/drivers/net/sfc/sfc_port.c
@@ -121,7 +121,6 @@ sfc_port_reset_mac_stats(struct sfc_adapter *sa)
static int
sfc_port_init_dev_link(struct sfc_adapter *sa)
{
- struct rte_eth_link *dev_link = &sa->eth_dev->data->dev_link;
int rc;
efx_link_mode_t link_mode;
struct rte_eth_link current_link;
@@ -132,11 +131,7 @@ sfc_port_init_dev_link(struct sfc_adapter *sa)
sfc_port_link_mode_to_info(link_mode, sa->port.phy_adv_cap,
¤t_link);
-
- EFX_STATIC_ASSERT(sizeof(*dev_link) == sizeof(rte_atomic64_t));
- rte_atomic64_set((rte_atomic64_t *)dev_link,
- *(uint64_t *)¤t_link);
-
+ rte_eth_linkstatus_set(sa->eth_dev, ¤t_link);
return 0;
}
diff --git a/drivers/net/sfc/sfc_stats.h b/drivers/net/sfc/sfc_stats.h
index 597e14dab3..eaa2afd3fe 100644
--- a/drivers/net/sfc/sfc_stats.h
+++ b/drivers/net/sfc/sfc_stats.h
@@ -12,7 +12,7 @@
#include <stdint.h>
-#include <rte_atomic.h>
+#include <rte_stdatomic.h>
#include "sfc_tweak.h"
--
2.53.0
^ permalink raw reply related
* [PATCH v5 07/24] net/pfe: use ethdev linkstatus helpers
From: Stephen Hemminger @ 2026-06-20 2:28 UTC (permalink / raw)
To: dev; +Cc: Stephen Hemminger, Gagandeep Singh
In-Reply-To: <20260620023134.42877-1-stephen@networkplumber.org>
Rather than open coding with deprecated rte_atomic64,
use the existing ethdev helpers to get and set link status.
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
drivers/net/pfe/pfe_ethdev.c | 32 ++------------------------------
1 file changed, 2 insertions(+), 30 deletions(-)
diff --git a/drivers/net/pfe/pfe_ethdev.c b/drivers/net/pfe/pfe_ethdev.c
index 1efa17539e..1b183ab1f3 100644
--- a/drivers/net/pfe/pfe_ethdev.c
+++ b/drivers/net/pfe/pfe_ethdev.c
@@ -531,34 +531,6 @@ pfe_supported_ptypes_get(struct rte_eth_dev *dev, size_t *no_of_elements)
return NULL;
}
-static inline int
-pfe_eth_atomic_read_link_status(struct rte_eth_dev *dev,
- struct rte_eth_link *link)
-{
- struct rte_eth_link *dst = link;
- struct rte_eth_link *src = &dev->data->dev_link;
-
- if (rte_atomic64_cmpset((uint64_t *)dst, *(uint64_t *)dst,
- *(uint64_t *)src) == 0)
- return -1;
-
- return 0;
-}
-
-static inline int
-pfe_eth_atomic_write_link_status(struct rte_eth_dev *dev,
- struct rte_eth_link *link)
-{
- struct rte_eth_link *dst = &dev->data->dev_link;
- struct rte_eth_link *src = link;
-
- if (rte_atomic64_cmpset((uint64_t *)dst, *(uint64_t *)dst,
- *(uint64_t *)src) == 0)
- return -1;
-
- return 0;
-}
-
static int
pfe_eth_link_update(struct rte_eth_dev *dev, int wait_to_complete __rte_unused)
{
@@ -570,7 +542,7 @@ pfe_eth_link_update(struct rte_eth_dev *dev, int wait_to_complete __rte_unused)
memset(&old, 0, sizeof(old));
memset(&link, 0, sizeof(struct rte_eth_link));
- pfe_eth_atomic_read_link_status(dev, &old);
+ rte_eth_linkstatus_get(dev, &old);
/* Read from PFE CDEV, status of link, if file was successfully
* opened.
@@ -601,7 +573,7 @@ pfe_eth_link_update(struct rte_eth_dev *dev, int wait_to_complete __rte_unused)
link.link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
link.link_autoneg = RTE_ETH_LINK_AUTONEG;
- pfe_eth_atomic_write_link_status(dev, &link);
+ rte_eth_linkstatus_set(dev, &link);
PFE_PMD_INFO("Port (%d) link is %s", dev->data->port_id,
link.link_status ? "up" : "down");
--
2.53.0
^ permalink raw reply related
* [PATCH v5 06/24] net/enic: do not use deprecated rte_atomic64
From: Stephen Hemminger @ 2026-06-20 2:28 UTC (permalink / raw)
To: dev
Cc: Stephen Hemminger, John Daley, Hyong Youb Kim, Bruce Richardson,
Konstantin Ananyev
In-Reply-To: <20260620023134.42877-1-stephen@networkplumber.org>
The rte_atomic64 datatype and functions are deprecated.
This driver was only using it for error statistics where atomic
is not necessary. The DPDK PMD model is that statistics do
not have to be exact in face of contention.
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
drivers/net/enic/enic.h | 6 +++---
drivers/net/enic/enic_compat.h | 1 -
drivers/net/enic/enic_main.c | 17 +++++++----------
drivers/net/enic/enic_rxtx.c | 14 ++++++--------
drivers/net/enic/enic_rxtx_vec_avx2.c | 4 ++--
5 files changed, 18 insertions(+), 24 deletions(-)
diff --git a/drivers/net/enic/enic.h b/drivers/net/enic/enic.h
index 87f6b35fcd..0a8d4a29ca 100644
--- a/drivers/net/enic/enic.h
+++ b/drivers/net/enic/enic.h
@@ -59,9 +59,9 @@
#define ENICPMD_RXQ_INTR_OFFSET 1
struct enic_soft_stats {
- rte_atomic64_t rx_nombuf;
- rte_atomic64_t rx_packet_errors;
- rte_atomic64_t tx_oversized;
+ uint64_t rx_nombuf;
+ uint64_t rx_packet_errors;
+ uint64_t tx_oversized;
};
struct enic_memzone_entry {
diff --git a/drivers/net/enic/enic_compat.h b/drivers/net/enic/enic_compat.h
index 7cff6831b9..3ce4299e81 100644
--- a/drivers/net/enic/enic_compat.h
+++ b/drivers/net/enic/enic_compat.h
@@ -9,7 +9,6 @@
#include <stdio.h>
#include <unistd.h>
-#include <rte_atomic.h>
#include <rte_malloc.h>
#include <rte_log.h>
#include <rte_io.h>
diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c
index 2696fa77d4..fb9a5754c9 100644
--- a/drivers/net/enic/enic_main.c
+++ b/drivers/net/enic/enic_main.c
@@ -83,17 +83,15 @@ static void enic_log_q_error(struct enic *enic)
static void enic_clear_soft_stats(struct enic *enic)
{
struct enic_soft_stats *soft_stats = &enic->soft_stats;
- rte_atomic64_clear(&soft_stats->rx_nombuf);
- rte_atomic64_clear(&soft_stats->rx_packet_errors);
- rte_atomic64_clear(&soft_stats->tx_oversized);
+
+ memset(soft_stats, 0, sizeof(*soft_stats));
}
static void enic_init_soft_stats(struct enic *enic)
{
struct enic_soft_stats *soft_stats = &enic->soft_stats;
- rte_atomic64_init(&soft_stats->rx_nombuf);
- rte_atomic64_init(&soft_stats->rx_packet_errors);
- rte_atomic64_init(&soft_stats->tx_oversized);
+
+ memset(soft_stats, 0, sizeof(*soft_stats));
enic_clear_soft_stats(enic);
}
@@ -132,7 +130,7 @@ int enic_dev_stats_get(struct enic *enic, struct rte_eth_stats *r_stats,
* counted in ibytes even though truncated packets are dropped
* which can make ibytes be slightly higher than it should be.
*/
- rx_packet_errors = rte_atomic64_read(&soft_stats->rx_packet_errors);
+ rx_packet_errors = soft_stats->rx_packet_errors;
rx_truncated = rx_packet_errors - stats->rx.rx_errors;
r_stats->ipackets = stats->rx.rx_frames_ok - rx_truncated;
@@ -142,12 +140,11 @@ int enic_dev_stats_get(struct enic *enic, struct rte_eth_stats *r_stats,
r_stats->obytes = stats->tx.tx_bytes_ok;
r_stats->ierrors = stats->rx.rx_errors + stats->rx.rx_drop;
- r_stats->oerrors = stats->tx.tx_errors
- + rte_atomic64_read(&soft_stats->tx_oversized);
+ r_stats->oerrors = stats->tx.tx_errors + soft_stats->tx_oversized;
r_stats->imissed = stats->rx.rx_no_bufs + rx_truncated;
- r_stats->rx_nombuf = rte_atomic64_read(&soft_stats->rx_nombuf);
+ r_stats->rx_nombuf = soft_stats->rx_nombuf;
return 0;
}
diff --git a/drivers/net/enic/enic_rxtx.c b/drivers/net/enic/enic_rxtx.c
index 549a153332..c87d947b93 100644
--- a/drivers/net/enic/enic_rxtx.c
+++ b/drivers/net/enic/enic_rxtx.c
@@ -112,7 +112,7 @@ enic_recv_pkts_common(void *rx_queue, struct rte_mbuf **rx_pkts,
/* allocate a new mbuf */
nmb = rte_mbuf_raw_alloc(rq->mp);
if (nmb == NULL) {
- rte_atomic64_inc(&enic->soft_stats.rx_nombuf);
+ ++enic->soft_stats.rx_nombuf;
break;
}
@@ -185,7 +185,7 @@ enic_recv_pkts_common(void *rx_queue, struct rte_mbuf **rx_pkts,
}
if (unlikely(packet_error)) {
rte_pktmbuf_free(first_seg);
- rte_atomic64_inc(&enic->soft_stats.rx_packet_errors);
+ ++enic->soft_stats.rx_packet_errors;
continue;
}
@@ -303,7 +303,7 @@ enic_noscatter_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
if (unlikely(cqd->bytes_written_flags &
CQ_ENET_RQ_DESC_FLAGS_TRUNCATED)) {
rte_pktmbuf_free(*rxmb++);
- rte_atomic64_inc(&enic->soft_stats.rx_packet_errors);
+ ++enic->soft_stats.rx_packet_errors;
cqd++;
continue;
}
@@ -505,14 +505,12 @@ uint16_t enic_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
uint8_t offload_mode;
uint16_t header_len;
uint64_t tso;
- rte_atomic64_t *tx_oversized;
enic_cleanup_wq(enic, wq);
wq_desc_avail = vnic_wq_desc_avail(wq);
head_idx = wq->head_idx;
desc_count = wq->ring.desc_count;
ol_flags_mask = RTE_MBUF_F_TX_VLAN | RTE_MBUF_F_TX_IP_CKSUM | RTE_MBUF_F_TX_L4_MASK;
- tx_oversized = &enic->soft_stats.tx_oversized;
nb_pkts = RTE_MIN(nb_pkts, ENIC_TX_XMIT_MAX);
@@ -527,7 +525,7 @@ uint16_t enic_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
/* drop packet if it's too big to send */
if (unlikely(!tso && pkt_len > ENIC_TX_MAX_PKT_SIZE)) {
rte_pktmbuf_free(tx_pkt);
- rte_atomic64_inc(tx_oversized);
+ ++enic->soft_stats.tx_oversized;
continue;
}
@@ -558,7 +556,7 @@ uint16_t enic_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
if (unlikely(header_len == 0 || ((tx_pkt->tso_segsz +
header_len) > ENIC_TX_MAX_PKT_SIZE))) {
rte_pktmbuf_free(tx_pkt);
- rte_atomic64_inc(tx_oversized);
+ ++enic->soft_stats.tx_oversized;
continue;
}
@@ -681,7 +679,7 @@ static void enqueue_simple_pkts(struct rte_mbuf **pkts,
*/
if (unlikely(p->pkt_len > ENIC_TX_MAX_PKT_SIZE)) {
desc->length = ENIC_TX_MAX_PKT_SIZE;
- rte_atomic64_inc(&enic->soft_stats.tx_oversized);
+ ++enic->soft_stats.tx_oversized;
}
desc++;
}
diff --git a/drivers/net/enic/enic_rxtx_vec_avx2.c b/drivers/net/enic/enic_rxtx_vec_avx2.c
index 600efff270..53589ab788 100644
--- a/drivers/net/enic/enic_rxtx_vec_avx2.c
+++ b/drivers/net/enic/enic_rxtx_vec_avx2.c
@@ -81,7 +81,7 @@ enic_noscatter_vec_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
if (unlikely(cqd->bytes_written_flags &
CQ_ENET_RQ_DESC_FLAGS_TRUNCATED)) {
rte_pktmbuf_free(*rxmb++);
- rte_atomic64_inc(&enic->soft_stats.rx_packet_errors);
+ ++enic->soft_stats.rx_packet_errors;
} else {
*rx++ = rx_one(cqd, *rxmb++, enic);
}
@@ -761,7 +761,7 @@ enic_noscatter_vec_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
if (unlikely(cqd->bytes_written_flags &
CQ_ENET_RQ_DESC_FLAGS_TRUNCATED)) {
rte_pktmbuf_free(*rxmb++);
- rte_atomic64_inc(&enic->soft_stats.rx_packet_errors);
+ ++enic->soft_stats.rx_packet_errors;
} else {
*rx++ = rx_one(cqd, *rxmb++, enic);
}
--
2.53.0
^ permalink raw reply related
* [PATCH v5 05/24] net/failsafe: convert to stdatomic
From: Stephen Hemminger @ 2026-06-20 2:28 UTC (permalink / raw)
To: dev; +Cc: Stephen Hemminger, Gaetan Rivet
In-Reply-To: <20260620023134.42877-1-stephen@networkplumber.org>
The functions rte_atomic64 are deprecated, convert this
code to use stdatomic for reference count. Use the memory
order implied by naming P/V.
No need for initialization since refcnt is in space
allocated with rte_zmalloc().
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
drivers/net/failsafe/failsafe_ops.c | 12 +++++-----
drivers/net/failsafe/failsafe_private.h | 29 ++++++++++++++-----------
drivers/net/failsafe/failsafe_rxtx.c | 2 +-
3 files changed, 22 insertions(+), 21 deletions(-)
diff --git a/drivers/net/failsafe/failsafe_ops.c b/drivers/net/failsafe/failsafe_ops.c
index ddc8808ebe..fcb0051777 100644
--- a/drivers/net/failsafe/failsafe_ops.c
+++ b/drivers/net/failsafe/failsafe_ops.c
@@ -11,7 +11,7 @@
#endif
#include <rte_debug.h>
-#include <rte_atomic.h>
+#include <rte_stdatomic.h>
#include <ethdev_driver.h>
#include <rte_malloc.h>
#include <rte_flow.h>
@@ -440,14 +440,13 @@ fs_rx_queue_setup(struct rte_eth_dev *dev,
}
rxq = rte_zmalloc(NULL,
sizeof(*rxq) +
- sizeof(rte_atomic64_t) * PRIV(dev)->subs_tail,
+ sizeof(uint64_t) * PRIV(dev)->subs_tail,
RTE_CACHE_LINE_SIZE);
if (rxq == NULL) {
fs_unlock(dev, 0);
return -ENOMEM;
}
- FOREACH_SUBDEV(sdev, i, dev)
- rte_atomic64_init(&rxq->refcnt[i]);
+
rxq->qid = rx_queue_id;
rxq->socket_id = socket_id;
rxq->info.mp = mb_pool;
@@ -617,14 +616,13 @@ fs_tx_queue_setup(struct rte_eth_dev *dev,
}
txq = rte_zmalloc("ethdev TX queue",
sizeof(*txq) +
- sizeof(rte_atomic64_t) * PRIV(dev)->subs_tail,
+ sizeof(uint64_t) * PRIV(dev)->subs_tail,
RTE_CACHE_LINE_SIZE);
if (txq == NULL) {
fs_unlock(dev, 0);
return -ENOMEM;
}
- FOREACH_SUBDEV(sdev, i, dev)
- rte_atomic64_init(&txq->refcnt[i]);
+
txq->qid = tx_queue_id;
txq->socket_id = socket_id;
txq->info.conf = *tx_conf;
diff --git a/drivers/net/failsafe/failsafe_private.h b/drivers/net/failsafe/failsafe_private.h
index babea6016e..89b06f9756 100644
--- a/drivers/net/failsafe/failsafe_private.h
+++ b/drivers/net/failsafe/failsafe_private.h
@@ -10,7 +10,7 @@
#include <sys/queue.h>
#include <pthread.h>
-#include <rte_atomic.h>
+#include <rte_stdatomic.h>
#include <dev_driver.h>
#include <ethdev_driver.h>
#include <rte_devargs.h>
@@ -75,7 +75,7 @@ struct rxq {
int event_fd;
unsigned int enable_events:1;
struct rte_eth_rxq_info info;
- rte_atomic64_t refcnt[];
+ RTE_ATOMIC(uint64_t) refcnt[];
};
struct txq {
@@ -83,7 +83,7 @@ struct txq {
uint16_t qid;
unsigned int socket_id;
struct rte_eth_txq_info info;
- rte_atomic64_t refcnt[];
+ RTE_ATOMIC(uint64_t) refcnt[];
};
struct rte_flow {
@@ -320,33 +320,36 @@ extern int failsafe_mac_from_arg;
*/
/**
- * a: (rte_atomic64_t)
+ * a: _Atomic uint64_t
*/
#define FS_ATOMIC_P(a) \
- rte_atomic64_set(&(a), 1)
+ rte_atomic_exchange_explicit(&(a), 1, rte_memory_order_acquire)
/**
- * a: (rte_atomic64_t)
+ * a: _Atomic uint64_t
*/
#define FS_ATOMIC_V(a) \
- rte_atomic64_set(&(a), 0)
+ rte_atomic_store_explicit(&(a), 0, rte_memory_order_release)
/**
* s: (struct sub_device *)
* i: uint16_t qid
*/
#define FS_ATOMIC_RX(s, i) \
- rte_atomic64_read( \
- &((struct rxq *) \
- (fs_dev(s)->data->rx_queues[i]))->refcnt[(s)->sid])
+ rte_atomic_load_explicit( \
+ &((struct rxq *) \
+ (fs_dev(s)->data->rx_queues[i]))->refcnt[(s)->sid], \
+ rte_memory_order_seq_cst)
+
/**
* s: (struct sub_device *)
* i: uint16_t qid
*/
#define FS_ATOMIC_TX(s, i) \
- rte_atomic64_read( \
- &((struct txq *) \
- (fs_dev(s)->data->tx_queues[i]))->refcnt[(s)->sid])
+ rte_atomic_load_explicit( \
+ &((struct txq *) \
+ (fs_dev(s)->data->tx_queues[i]))->refcnt[(s)->sid], \
+ rte_memory_order_seq_cst)
#ifdef RTE_EXEC_ENV_FREEBSD
#define FS_THREADID_TYPE void*
diff --git a/drivers/net/failsafe/failsafe_rxtx.c b/drivers/net/failsafe/failsafe_rxtx.c
index fe67293299..500483bda3 100644
--- a/drivers/net/failsafe/failsafe_rxtx.c
+++ b/drivers/net/failsafe/failsafe_rxtx.c
@@ -3,7 +3,7 @@
* Copyright 2017 Mellanox Technologies, Ltd
*/
-#include <rte_atomic.h>
+#include <rte_stdatomic.h>
#include <rte_debug.h>
#include <rte_mbuf.h>
#include <ethdev_driver.h>
--
2.53.0
^ permalink raw reply related
* [PATCH v5 04/24] net/ena: replace use of rte_atomicNN
From: Stephen Hemminger @ 2026-06-20 2:28 UTC (permalink / raw)
To: dev
Cc: Stephen Hemminger, Shai Brandes, Evgeny Schemeilin, Ron Beider,
Amit Bernstein, Wajeeh Atrash
In-Reply-To: <20260620023134.42877-1-stephen@networkplumber.org>
Convert the legacy rte_atomicNN operations to stdatomic.
* Remove variable ena_alloc_cnt is defined by not used.
It is a leftover from previous memzone naming scheme.
* Convert the legacy rte_atomic32_t and rte_atomic32_{inc,dec,set,read}
macros to C11 stdatomic equivalents.
Memory ordering is kept at seq_cst,
matching the implicit ordering of the legacy API.
* Do not use rte_atomic for statistics
The DPDK PMD model is that statistics do not have to be exact
in face of contention.
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
drivers/net/ena/base/ena_plat_dpdk.h | 14 +++++++++-----
drivers/net/ena/ena_ethdev.c | 21 ++++++---------------
drivers/net/ena/ena_ethdev.h | 7 +++----
3 files changed, 18 insertions(+), 24 deletions(-)
diff --git a/drivers/net/ena/base/ena_plat_dpdk.h b/drivers/net/ena/base/ena_plat_dpdk.h
index c84420de22..83b354d9da 100644
--- a/drivers/net/ena/base/ena_plat_dpdk.h
+++ b/drivers/net/ena/base/ena_plat_dpdk.h
@@ -40,7 +40,7 @@ typedef uint64_t dma_addr_t;
#endif
#define ENA_PRIu64 PRIu64
-#define ena_atomic32_t rte_atomic32_t
+typedef RTE_ATOMIC(int32_t) ena_atomic32_t;
#define ena_mem_handle_t const struct rte_memzone *
#define SZ_256 (256U)
@@ -267,10 +267,14 @@ ena_mem_alloc_coherent(struct rte_eth_dev_data *data, size_t size,
#define ENA_REG_READ32(bus, reg) \
__extension__ ({ (void)(bus); rte_read32_relaxed((reg)); })
-#define ATOMIC32_INC(i32_ptr) rte_atomic32_inc(i32_ptr)
-#define ATOMIC32_DEC(i32_ptr) rte_atomic32_dec(i32_ptr)
-#define ATOMIC32_SET(i32_ptr, val) rte_atomic32_set(i32_ptr, val)
-#define ATOMIC32_READ(i32_ptr) rte_atomic32_read(i32_ptr)
+#define ATOMIC32_INC(i32_ptr) \
+ rte_atomic_fetch_add_explicit((i32_ptr), 1, rte_memory_order_seq_cst)
+#define ATOMIC32_DEC(i32_ptr) \
+ rte_atomic_fetch_sub_explicit((i32_ptr), 1, rte_memory_order_seq_cst)
+#define ATOMIC32_SET(i32_ptr, val) \
+ rte_atomic_store_explicit((i32_ptr), (val), rte_memory_order_seq_cst)
+#define ATOMIC32_READ(i32_ptr) \
+ rte_atomic_load_explicit((i32_ptr), rte_memory_order_seq_cst)
#define msleep(x) rte_delay_us(x * 1000)
#define udelay(x) rte_delay_us(x)
diff --git a/drivers/net/ena/ena_ethdev.c b/drivers/net/ena/ena_ethdev.c
index ad2ac6dbbf..e874f264b4 100644
--- a/drivers/net/ena/ena_ethdev.c
+++ b/drivers/net/ena/ena_ethdev.c
@@ -121,12 +121,6 @@ struct ena_stats {
*/
#define ENA_DEVARG_ENABLE_FRAG_BYPASS "enable_frag_bypass"
-/*
- * Each rte_memzone should have unique name.
- * To satisfy it, count number of allocation and add it to name.
- */
-rte_atomic64_t ena_alloc_cnt;
-
static const struct ena_stats ena_stats_global_strings[] = {
ENA_STAT_GLOBAL_ENTRY(wd_expired),
ENA_STAT_GLOBAL_ENTRY(dev_start),
@@ -1249,10 +1243,7 @@ static void ena_stats_restart(struct rte_eth_dev *dev)
{
struct ena_adapter *adapter = dev->data->dev_private;
- rte_atomic64_init(&adapter->drv_stats->ierrors);
- rte_atomic64_init(&adapter->drv_stats->oerrors);
- rte_atomic64_init(&adapter->drv_stats->rx_nombuf);
- adapter->drv_stats->rx_drops = 0;
+ memset(adapter->drv_stats, 0, sizeof(struct ena_driver_stats));
}
static int ena_stats_get(struct rte_eth_dev *dev,
@@ -1289,9 +1280,9 @@ static int ena_stats_get(struct rte_eth_dev *dev,
/* Driver related stats */
stats->imissed = adapter->drv_stats->rx_drops;
- stats->ierrors = rte_atomic64_read(&adapter->drv_stats->ierrors);
- stats->oerrors = rte_atomic64_read(&adapter->drv_stats->oerrors);
- stats->rx_nombuf = rte_atomic64_read(&adapter->drv_stats->rx_nombuf);
+ stats->ierrors = adapter->drv_stats->ierrors;
+ stats->oerrors = adapter->drv_stats->oerrors;
+ stats->rx_nombuf = adapter->drv_stats->rx_nombuf;
/* Queue statistics */
if (qstats) {
@@ -1887,7 +1878,7 @@ static int ena_populate_rx_queue(struct ena_ring *rxq, unsigned int count)
/* get resources for incoming packets */
rc = rte_pktmbuf_alloc_bulk(rxq->mb_pool, mbufs, count);
if (unlikely(rc < 0)) {
- rte_atomic64_inc(&rxq->adapter->drv_stats->rx_nombuf);
+ ++rxq->adapter->drv_stats->rx_nombuf;
++rxq->rx_stats.mbuf_alloc_fail;
PMD_RX_LOG_LINE(DEBUG, "There are not enough free buffers");
return 0;
@@ -3014,7 +3005,7 @@ static uint16_t eth_ena_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
if (unlikely(mbuf->ol_flags &
(RTE_MBUF_F_RX_IP_CKSUM_BAD | RTE_MBUF_F_RX_L4_CKSUM_BAD)))
- rte_atomic64_inc(&rx_ring->adapter->drv_stats->ierrors);
+ ++rx_ring->adapter->drv_stats->ierrors;
rx_pkts[completed] = mbuf;
rx_ring->rx_stats.bytes += mbuf->pkt_len;
diff --git a/drivers/net/ena/ena_ethdev.h b/drivers/net/ena/ena_ethdev.h
index 3a66d79384..b204b07767 100644
--- a/drivers/net/ena/ena_ethdev.h
+++ b/drivers/net/ena/ena_ethdev.h
@@ -6,7 +6,6 @@
#ifndef _ENA_ETHDEV_H_
#define _ENA_ETHDEV_H_
-#include <rte_atomic.h>
#include <rte_ether.h>
#include <ethdev_driver.h>
#include <ethdev_pci.h>
@@ -225,9 +224,9 @@ enum ena_adapter_state {
};
struct ena_driver_stats {
- rte_atomic64_t ierrors;
- rte_atomic64_t oerrors;
- rte_atomic64_t rx_nombuf;
+ u64 ierrors;
+ u64 oerrors;
+ u64 rx_nombuf;
u64 rx_drops;
};
--
2.53.0
^ permalink raw reply related
* [PATCH v5 03/24] net/nbl: remove unused rte_atomic16 field
From: Stephen Hemminger @ 2026-06-20 2:28 UTC (permalink / raw)
To: dev; +Cc: Stephen Hemminger, Dimon Zhao, Leon Yu, Sam Chen
In-Reply-To: <20260620023134.42877-1-stephen@networkplumber.org>
The tx_current_queue was defined as rte_atomic16_t which
is deprecated. Remove it since it was never used.
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
drivers/net/nbl/nbl_hw/nbl_resource.h | 1 -
1 file changed, 1 deletion(-)
diff --git a/drivers/net/nbl/nbl_hw/nbl_resource.h b/drivers/net/nbl/nbl_hw/nbl_resource.h
index bf5a9461f5..f2182ba6bc 100644
--- a/drivers/net/nbl/nbl_hw/nbl_resource.h
+++ b/drivers/net/nbl/nbl_hw/nbl_resource.h
@@ -225,7 +225,6 @@ struct nbl_res_info {
u16 base_qid;
u16 lcore_max;
u16 *pf_qid_to_lcore_id;
- rte_atomic16_t tx_current_queue;
};
struct nbl_resource_mgt {
--
2.53.0
^ permalink raw reply related
* [PATCH v5 02/24] net/bonding: use stdatomic
From: Stephen Hemminger @ 2026-06-20 2:28 UTC (permalink / raw)
To: dev; +Cc: Stephen Hemminger, Chas Williams, Min Hu (Connor)
In-Reply-To: <20260620023134.42877-1-stephen@networkplumber.org>
The old rte_atomic16 and rte_atomic64 functions are deprecated.
Replace with rte_stdatomic for managing warning and timer flags.
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
drivers/net/bonding/eth_bond_8023ad_private.h | 6 ++--
drivers/net/bonding/rte_eth_bond_8023ad.c | 35 ++++++++-----------
2 files changed, 17 insertions(+), 24 deletions(-)
diff --git a/drivers/net/bonding/eth_bond_8023ad_private.h b/drivers/net/bonding/eth_bond_8023ad_private.h
index ab7d15f81a..dd3cf3ed26 100644
--- a/drivers/net/bonding/eth_bond_8023ad_private.h
+++ b/drivers/net/bonding/eth_bond_8023ad_private.h
@@ -9,7 +9,7 @@
#include <rte_ether.h>
#include <rte_byteorder.h>
-#include <rte_atomic.h>
+#include <rte_stdatomic.h>
#include <rte_flow.h>
#include "rte_eth_bond_8023ad.h"
@@ -140,10 +140,10 @@ struct port {
/** Timer which is also used as mutex. If is 0 (not running) RX marker
* packet might be responded. Otherwise shall be dropped. It is zeroed in
* mode 4 callback function after expire. */
- volatile uint64_t rx_marker_timer;
+ RTE_ATOMIC(uint64_t) rx_marker_timer;
uint64_t warning_timer;
- volatile uint16_t warnings_to_show;
+ RTE_ATOMIC(uint16_t) warnings_to_show;
/** Memory pool used to allocate slow queues */
struct rte_mempool *slow_pool;
diff --git a/drivers/net/bonding/rte_eth_bond_8023ad.c b/drivers/net/bonding/rte_eth_bond_8023ad.c
index ba88f6d261..cc7e4af2b9 100644
--- a/drivers/net/bonding/rte_eth_bond_8023ad.c
+++ b/drivers/net/bonding/rte_eth_bond_8023ad.c
@@ -171,27 +171,17 @@ timer_is_running(uint64_t *timer)
static void
set_warning_flags(struct port *port, uint16_t flags)
{
- int retval;
- uint16_t old;
- uint16_t new_flag = 0;
-
- do {
- old = port->warnings_to_show;
- new_flag = old | flags;
- retval = rte_atomic16_cmpset(&port->warnings_to_show, old, new_flag);
- } while (unlikely(retval == 0));
+ rte_atomic_fetch_or_explicit(&port->warnings_to_show, flags, rte_memory_order_relaxed);
}
static void
show_warnings(uint16_t member_id)
{
struct port *port = &bond_mode_8023ad_ports[member_id];
- uint8_t warnings;
-
- do {
- warnings = port->warnings_to_show;
- } while (rte_atomic16_cmpset(&port->warnings_to_show, warnings, 0) == 0);
+ uint16_t warnings;
+ warnings = rte_atomic_exchange_explicit(&port->warnings_to_show, 0,
+ rte_memory_order_relaxed);
if (!warnings)
return;
@@ -1337,7 +1327,6 @@ bond_mode_8023ad_handle_slow_pkt(struct bond_dev_private *internals,
struct port *port = &bond_mode_8023ad_ports[member_id];
struct marker_header *m_hdr;
uint64_t marker_timer, old_marker_timer;
- int retval;
uint8_t wrn, subtype;
/* If packet is a marker, we send response now by reusing given packet
* and update only source MAC, destination MAC is multicast so don't
@@ -1354,17 +1343,19 @@ bond_mode_8023ad_handle_slow_pkt(struct bond_dev_private *internals,
}
/* Setup marker timer. Do it in loop in case concurrent access. */
+ old_marker_timer = rte_atomic_load_explicit(&port->rx_marker_timer,
+ rte_memory_order_relaxed);
do {
- old_marker_timer = port->rx_marker_timer;
if (!timer_is_expired(&old_marker_timer)) {
wrn = WRN_RX_MARKER_TO_FAST;
goto free_out;
}
timer_set(&marker_timer, mode4->rx_marker_timeout);
- retval = rte_atomic64_cmpset(&port->rx_marker_timer,
- old_marker_timer, marker_timer);
- } while (unlikely(retval == 0));
+
+ } while (!rte_atomic_compare_exchange_weak_explicit(&port->rx_marker_timer,
+ &old_marker_timer, marker_timer,
+ rte_memory_order_seq_cst, rte_memory_order_relaxed));
m_hdr->marker.tlv_type_marker = MARKER_TLV_TYPE_RESP;
rte_eth_macaddr_get(member_id, &m_hdr->eth_hdr.src_addr);
@@ -1372,7 +1363,8 @@ bond_mode_8023ad_handle_slow_pkt(struct bond_dev_private *internals,
if (internals->mode4.dedicated_queues.enabled == 0) {
if (rte_ring_enqueue(port->tx_ring, pkt) != 0) {
/* reset timer */
- port->rx_marker_timer = 0;
+ rte_atomic_store_explicit(&port->rx_marker_timer, 0,
+ rte_memory_order_release);
wrn = WRN_TX_QUEUE_FULL;
goto free_out;
}
@@ -1386,7 +1378,8 @@ bond_mode_8023ad_handle_slow_pkt(struct bond_dev_private *internals,
&pkt, tx_count);
if (tx_count != 1) {
/* reset timer */
- port->rx_marker_timer = 0;
+ rte_atomic_store_explicit(&port->rx_marker_timer, 0,
+ rte_memory_order_release);
wrn = WRN_TX_QUEUE_FULL;
goto free_out;
}
--
2.53.0
^ permalink raw reply related
* [PATCH v5 01/24] bpf: use C11 atomics in BPF_ST_ATOMIC_REG
From: Stephen Hemminger @ 2026-06-20 2:28 UTC (permalink / raw)
To: dev; +Cc: Stephen Hemminger, Marat Khalili, Konstantin Ananyev
In-Reply-To: <20260620023134.42877-1-stephen@networkplumber.org>
The BPF_ST_ATOMIC_REG macro generated code with deprecated
rte_atomicNN_add and rte_atomicNN_exchange.
Replace this with the equivalent rte_stdatomic definitions.
Use memory order seq_cst to preserve the previous behavior of
rte_atomicNN_add() / rte_atomicNN_exchange() and matches
the Linux kernel BPF interpreter for these opcodes.
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
Reviewed-by: Marat Khalili <marat.khalili@huawei.com>
---
lib/bpf/bpf_exec.c | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/lib/bpf/bpf_exec.c b/lib/bpf/bpf_exec.c
index 18013753b1..ee6ec7516f 100644
--- a/lib/bpf/bpf_exec.c
+++ b/lib/bpf/bpf_exec.c
@@ -10,6 +10,7 @@
#include <rte_log.h>
#include <rte_debug.h>
#include <rte_byteorder.h>
+#include <rte_stdatomic.h>
#include "bpf_impl.h"
@@ -65,16 +66,16 @@
(type)(reg)[(ins)->src_reg])
#define BPF_ST_ATOMIC_REG(reg, ins, tp) do { \
+ RTE_ATOMIC(uint##tp##_t) *dst = (RTE_ATOMIC(uint##tp##_t) *) \
+ (uintptr_t)((reg)[(ins)->dst_reg] + (ins)->off); \
switch (ins->imm) { \
case BPF_ATOMIC_ADD: \
- rte_atomic##tp##_add((rte_atomic##tp##_t *) \
- (uintptr_t)((reg)[(ins)->dst_reg] + (ins)->off), \
- (reg)[(ins)->src_reg]); \
+ rte_atomic_fetch_add_explicit(dst, \
+ (reg)[(ins)->src_reg], rte_memory_order_seq_cst); \
break; \
case BPF_ATOMIC_XCHG: \
- (reg)[(ins)->src_reg] = rte_atomic##tp##_exchange((uint##tp##_t *) \
- (uintptr_t)((reg)[(ins)->dst_reg] + (ins)->off), \
- (reg)[(ins)->src_reg]); \
+ (reg)[(ins)->src_reg] = rte_atomic_exchange_explicit(dst, \
+ (reg)[(ins)->src_reg], rte_memory_order_seq_cst); \
break; \
default: \
/* this should be caught by validator and never reach here */ \
--
2.53.0
^ permalink raw reply related
* [PATCH v5 00/24] deprecate rte_atomic functions
From: Stephen Hemminger @ 2026-06-20 2:28 UTC (permalink / raw)
To: dev; +Cc: Stephen Hemminger
In-Reply-To: <https://inbox.dpdk.org/dev/20260521042043.1590536-1-stephen@networkplumber.org>
The rte_atomicNN_* family was flagged for deprecation in 2021 by
commit 3ec965b6de12 ("doc: update atomic operation deprecation")
but enforcement never landed and in-tree usage continued to grow.
This series finishes converting every remaining in-tree caller to
the C11-style rte_atomic_*_explicit() / RTE_ATOMIC() API, then
marks the legacy functions __rte_deprecated so future in-tree and
out-of-tree uses are caught at compile time.
The goal of this series is to get driver writers to review and
test each change.
v5 - rebase now that ring changes are merged.
- drop the barrier (rte_smp_mb) patch not required.
Stephen Hemminger (24):
bpf: use C11 atomics in BPF_ST_ATOMIC_REG
net/bonding: use stdatomic
net/nbl: remove unused rte_atomic16 field
net/ena: replace use of rte_atomicNN
net/failsafe: convert to stdatomic
net/enic: do not use deprecated rte_atomic64
net/pfe: use ethdev linkstatus helpers
net/sfc: replace rte_atomic with stdatomic
crypto/ccp: replace use of rte_atomic64 with stdatomic
bus/dpaa: replace rte_atomic16 with stdatomic
drivers: replace rte_atomic16 with stdatomic
net/netvsc: replace rte_atomic32 with stdatomic
event/sw: convert from rte_atomic32 to stdatomic
bus/vmbus: convert from rte_atomic to stdatomic
common/dpaax: use stdatomic instead of rte_atomic
net/bnx2x: convert from rte_atomic32 to stdatomic
bus/fslmc: replace rte_atomic32 with stdatomic
drivers/event: replace rte_atomic32 in selftests
net/hinic: replace rte_atomic32 with stdatomic
net/txgbe: replace rte_atomic32 with stdatomic
net/vhost: use stdatomic instead of rte_atomic32
vdpa/ifc: replace rte_atomic32 with stdatomic
test/atomic: suppress deprecation warnings for legacy APIs
eal: deprecate rte_atomicNN functions
app/test/test_atomic.c | 12 +
devtools/checkpatches.sh | 8 -
doc/guides/rel_notes/deprecation.rst | 4 +-
doc/guides/rel_notes/release_26_07.rst | 5 +
drivers/bus/dpaa/base/qbman/qman.c | 9 +-
drivers/bus/fslmc/portal/dpaa2_hw_dpbp.c | 10 +-
drivers/bus/fslmc/portal/dpaa2_hw_dpci.c | 10 +-
drivers/bus/fslmc/portal/dpaa2_hw_dpio.c | 12 +-
drivers/bus/fslmc/portal/dpaa2_hw_pvt.h | 8 +-
drivers/bus/fslmc/qbman/include/compat.h | 21 +-
drivers/bus/vmbus/private.h | 2 +-
drivers/bus/vmbus/vmbus_bufring.c | 39 +--
drivers/common/dpaax/compat.h | 21 +-
drivers/crypto/ccp/ccp_crypto.c | 11 +-
drivers/crypto/ccp/ccp_crypto.h | 2 +-
drivers/crypto/ccp/ccp_dev.c | 10 +-
drivers/crypto/ccp/ccp_dev.h | 4 +-
drivers/event/dpaa2/dpaa2_eventdev_selftest.c | 26 +-
drivers/event/dpaa2/dpaa2_hw_dpcon.c | 11 +-
drivers/event/octeontx/ssovf_evdev_selftest.c | 61 +++--
drivers/event/sw/sw_evdev.c | 8 +-
drivers/event/sw/sw_evdev.h | 4 +-
drivers/event/sw/sw_evdev_worker.c | 16 +-
drivers/net/bnx2x/bnx2x.c | 6 +-
drivers/net/bnx2x/bnx2x.h | 2 +-
drivers/net/bnx2x/ecore_sp.c | 6 +-
drivers/net/bonding/eth_bond_8023ad_private.h | 6 +-
drivers/net/bonding/rte_eth_bond_8023ad.c | 35 +--
drivers/net/ena/base/ena_plat_dpdk.h | 14 +-
drivers/net/ena/ena_ethdev.c | 21 +-
drivers/net/ena/ena_ethdev.h | 7 +-
drivers/net/enic/enic.h | 6 +-
drivers/net/enic/enic_compat.h | 1 -
drivers/net/enic/enic_main.c | 17 +-
drivers/net/enic/enic_rxtx.c | 14 +-
drivers/net/enic/enic_rxtx_vec_avx2.c | 4 +-
drivers/net/failsafe/failsafe_ops.c | 12 +-
drivers/net/failsafe/failsafe_private.h | 29 ++-
drivers/net/failsafe/failsafe_rxtx.c | 2 +-
drivers/net/hinic/base/hinic_compat.h | 2 +-
drivers/net/hinic/base/hinic_pmd_hwdev.c | 24 +-
drivers/net/hinic/base/hinic_pmd_hwdev.h | 4 +-
drivers/net/nbl/nbl_hw/nbl_resource.h | 1 -
drivers/net/netvsc/hn_rndis.c | 28 +-
drivers/net/netvsc/hn_rxtx.c | 12 +-
drivers/net/netvsc/hn_var.h | 6 +-
drivers/net/pfe/pfe_ethdev.c | 32 +--
drivers/net/sfc/sfc.c | 9 +-
drivers/net/sfc/sfc.h | 4 +-
drivers/net/sfc/sfc_port.c | 7 +-
drivers/net/sfc/sfc_stats.h | 2 +-
drivers/net/txgbe/base/txgbe_mng.c | 4 +-
drivers/net/txgbe/base/txgbe_type.h | 2 +-
drivers/net/vhost/rte_eth_vhost.c | 103 +++++---
drivers/vdpa/ifc/ifcvf_vdpa.c | 37 +--
lib/bpf/bpf_exec.c | 13 +-
lib/eal/arm/include/rte_atomic_32.h | 4 -
lib/eal/arm/include/rte_atomic_64.h | 4 -
lib/eal/include/generic/rte_atomic.h | 243 +++++-------------
lib/eal/include/rte_common.h | 2 +
lib/eal/loongarch/include/rte_atomic.h | 4 -
lib/eal/ppc/include/rte_atomic.h | 173 -------------
lib/eal/riscv/include/rte_atomic.h | 4 -
lib/eal/x86/include/rte_atomic.h | 172 -------------
lib/eal/x86/include/rte_atomic_32.h | 188 --------------
lib/eal/x86/include/rte_atomic_64.h | 157 -----------
66 files changed, 472 insertions(+), 1265 deletions(-)
--
2.53.0
^ permalink raw reply
* RE: [EXTERNAL] [PATCH v2 06/10] bus/vmbus: allocate interrupt during probing
From: Long Li @ 2026-06-19 22:05 UTC (permalink / raw)
To: David Marchand, dev@dpdk.org
Cc: thomas@monjalon.net, stephen@networkplumber.org,
bruce.richardson@intel.com, fengchengwen@huawei.com,
hemant.agrawal@nxp.com, Wei Hu
In-Reply-To: <20260618152826.490569-7-david.marchand@redhat.com>
> Allocating the interrupt handle is a waste of memory if no device is probed
> later (like for example, if a allowlist is passed).
> Instead, allocate this handle at the time probe_device is called.
>
> Signed-off-by: David Marchand <david.marchand@redhat.com>
Reviewed-by: Long Li <longli@microsoft.com>
> ---
> Changes since v1:
> - fixed/reordered interrupt handle allocation,
>
> ---
> drivers/bus/vmbus/linux/vmbus_bus.c | 6 ------
> drivers/bus/vmbus/vmbus_common.c | 18 ++++++++++++++++--
> 2 files changed, 16 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/bus/vmbus/linux/vmbus_bus.c
> b/drivers/bus/vmbus/linux/vmbus_bus.c
> index 0af10f6a69..77d904ad6d 100644
> --- a/drivers/bus/vmbus/linux/vmbus_bus.c
> +++ b/drivers/bus/vmbus/linux/vmbus_bus.c
> @@ -345,12 +345,6 @@ vmbus_scan_one(const char *name)
> }
> }
>
> - /* Allocate interrupt handle instance */
> - dev->intr_handle =
> - rte_intr_instance_alloc(RTE_INTR_INSTANCE_F_PRIVATE);
> - if (dev->intr_handle == NULL)
> - goto error;
> -
> /* device is valid, add in list (sorted) */
> VMBUS_LOG(DEBUG, "Adding vmbus device %s", name);
>
> diff --git a/drivers/bus/vmbus/vmbus_common.c
> b/drivers/bus/vmbus/vmbus_common.c
> index 74c1ddff69..bfb45e963c 100644
> --- a/drivers/bus/vmbus/vmbus_common.c
> +++ b/drivers/bus/vmbus/vmbus_common.c
> @@ -100,10 +100,16 @@ vmbus_probe_device(struct rte_driver *drv, struct
> rte_device *dev)
> return 1;
> }
>
> + /* allocate interrupt handle instance */
> + vmbus_dev->intr_handle =
> + rte_intr_instance_alloc(RTE_INTR_INSTANCE_F_PRIVATE);
> + if (vmbus_dev->intr_handle == NULL)
> + return -ENOMEM;
> +
> /* map resources for device */
> ret = rte_vmbus_map_device(vmbus_dev);
> if (ret != 0)
> - return ret;
> + goto free_intr;
>
> if (vmbus_dev->device.numa_node < 0 && rte_socket_count() > 1)
> VMBUS_LOG(INFO, "Device %s is not NUMA-aware", guid); @@
> -112,7 +118,15 @@ vmbus_probe_device(struct rte_driver *drv, struct
> rte_device *dev)
> VMBUS_LOG(INFO, " probe driver: %s", vmbus_drv->driver.name);
> ret = vmbus_drv->probe(vmbus_drv, vmbus_dev);
> if (ret != 0)
> - rte_vmbus_unmap_device(vmbus_dev);
> + goto unmap;
> +
> + return 0;
> +
> +unmap:
> + rte_vmbus_unmap_device(vmbus_dev);
> +free_intr:
> + rte_intr_instance_free(vmbus_dev->intr_handle);
> + vmbus_dev->intr_handle = NULL;
>
> return ret;
> }
> --
> 2.53.0
^ permalink raw reply
* RE: [EXTERNAL] [PATCH v2 05/10] bus/vmbus: fix interrupt leak in cleanup
From: Long Li @ 2026-06-19 22:04 UTC (permalink / raw)
To: David Marchand, dev@dpdk.org
Cc: thomas@monjalon.net, stephen@networkplumber.org,
bruce.richardson@intel.com, fengchengwen@huawei.com,
hemant.agrawal@nxp.com, stable@dpdk.org, Wei Hu
In-Reply-To: <20260618152826.490569-6-david.marchand@redhat.com>
> When calling this bus cleanup, interrupt handle was not released.
>
> Fixes: 65780eada9d9 ("bus/vmbus: support cleanup")
> Cc: stable@dpdk.org
>
> Signed-off-by: David Marchand <david.marchand@redhat.com>
Reviewed-by: Long Li <longli@microsoft.com>
> ---
> drivers/bus/vmbus/vmbus_common.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/drivers/bus/vmbus/vmbus_common.c
> b/drivers/bus/vmbus/vmbus_common.c
> index 01573927ce..74c1ddff69 100644
> --- a/drivers/bus/vmbus/vmbus_common.c
> +++ b/drivers/bus/vmbus/vmbus_common.c
> @@ -150,6 +150,7 @@ rte_vmbus_cleanup(void)
> error = -1;
>
> rte_vmbus_unmap_device(dev);
> + rte_intr_instance_free(dev->intr_handle);
>
> dev->device.driver = NULL;
> rte_bus_remove_device(&rte_vmbus_bus, &dev->device);
> --
> 2.53.0
^ permalink raw reply
* Re: [PATCH 00/10] NXP ENETC driver related changes
From: Stephen Hemminger @ 2026-06-19 21:43 UTC (permalink / raw)
To: Gagandeep Singh; +Cc: dev, hemant.agrawal
In-Reply-To: <20260619184427.522518-1-g.singh@nxp.com>
On Sat, 20 Jun 2026 00:14:17 +0530
Gagandeep Singh <g.singh@nxp.com> wrote:
> ENETC driver related changes series
>
> Gagandeep Singh (8):
> net/enetc: fix TX BD structure
> net/enetc: fix TX BDs flag overwrite issue
> net/enetc: fix queue initialization
> net/enetc: support ESP packet type in packet parsing
> net/enetc: update random MAC generation code
> net/enetc: add option to disable VSI messaging
> net/enetc: add devargs to control VSI-PSI timeout and delay
> net/enetc4: add cacheable BD ring support with SW cache maintenance
>
> Vanshika Shukla (2):
> net/enetc: support scatter-gather
> net/enetc: set user configurable priority to TX rings
>
> drivers/net/enetc/base/enetc_hw.h | 13 +-
> drivers/net/enetc/enetc.h | 28 +-
> drivers/net/enetc/enetc4_ethdev.c | 123 +++++++--
> drivers/net/enetc/enetc4_vf.c | 159 ++++++++++--
> drivers/net/enetc/enetc_ethdev.c | 26 +-
> drivers/net/enetc/enetc_rxtx.c | 411 ++++++++++++++++++++++++++----
> 6 files changed, 649 insertions(+), 111 deletions(-)
>
The AI review shows some thing that need to be addressed before merging.
[PATCH 04/10] net/enetc: support ESP packet type
Info: enetc_supported_ptypes_get() adds RTE_PTYPE_TUNNEL_ESP and a
trailing RTE_PTYPE_UNKNOWN. *no_of_elements is RTE_DIM(ptypes), so the
0 entry is counted (not used as a sentinel). It is filtered out by the
mask test in rte_eth_dev_get_supported_ptypes(), so harmless, but the
RTE_PTYPE_UNKNOWN line is unnecessary and should be dropped.
[PATCH 06/10] net/enetc: support scatter-gather
Warning: scatter Rx reassembly state (first_seg/cur_seg) is held in
local variables and reset on every call. rx_frm_cnt only advances on
the F bit, so work_limit won't cut a frame, but the
"!(bd_status & LSTATUS_R)" break can exit mid-frame if HW has written
the leading segments of a multi-segment frame but not yet the segment
carrying F. On the next call first_seg is NULL again, next_to_clean has
already advanced past the consumed leading segments, and those mbufs
are leaked while the tail segments are mis-assembled as a new frame.
Persist the partial chain across bursts in the ring (e.g.
rx_ring->pkt_first_seg / pkt_last_seg) instead of locals. (Same pattern
is reproduced in enetc_clean_rx_ring_cacheable in patch 10.)
Warning: enetc4 now advertises RTE_ETH_RX_OFFLOAD_SCATTER and
RTE_ETH_TX_OFFLOAD_MULTI_SEGS (VF) but doc/guides/nics/features/
enetc4.ini is not updated (Scattered Rx / Multi segment rows).
Info: the VF dev_info now advertises L3/L4 RX checksum offload, but
enetc_dev_rx_parse() unconditionally sets
RTE_MBUF_F_RX_IP_CKSUM_GOOD | RTE_MBUF_F_RX_L4_CKSUM_GOOD and never
reports *_BAD. With the offload now advertised, an application relying
on it will never see a bad-checksum indication.
Info: dccivac(data + (data_len - 1)) / dcbf(data + (seg_len - 1))
underflow to data-1 when the segment length is 0 (uint16_t promotes to
int). The preceding loop already covers the final cache line, so the
extra op is redundant as well as unsafe for len==0.
[PATCH 07/10] net/enetc: add option to disable VSI messaging
Warning: new devarg "enetc4_vsi_disable" is registered but not
documented in doc/guides/nics/enetc.rst.
[PATCH 08/10] net/enetc: add devargs to control VSI-PSI timeout/delay
Warning: new devargs "enetc4_vsi_timeout" / "enetc4_vsi_delay" are not
documented in doc/guides/nics/enetc.rst.
[PATCH 09/10] net/enetc: set user configurable priority to TX rings
Error: hw->txq_prior is allocated in parse_txq_prior() with
rte_zmalloc() but never freed. It leaks on dev_close / re-probe. Free
it in the close/uninit path (and note it is re-allocated every time the
handler runs, so a repeated key would leak the prior allocation too).
Warning: txq_prior is control-path, CPU-only data; rte_zmalloc()
consumes hugepage memory unnecessarily. Use calloc()/malloc().
Warning: the parsed value is OR'd straight into TBMR:
tx_en |= priv->hw.txq_prior[tx_ring->index];
with no mask. ENETC_TBMR_EN is BIT(31) and there is no TBMR priority
mask defined. A user value with high bits set can corrupt unrelated
TBMR control bits. Mask the input to the valid TBMR priority field.
Info: strdup(value) return is not checked; on failure
strtok(input_str, "|") is called with a NULL first argument, which
resumes from strtok's stale internal state rather than erroring.
Warning: new devarg "enetc4_txq_prior" not documented in
doc/guides/nics/enetc.rst.
[PATCH 10/10] net/enetc4: add cacheable BD ring support with SW cache
Warning: enetc4_dev_hw_init() switches rx_pkt_burst/tx_pkt_burst to the
cache-maintenance variants unconditionally for every enetc4 device
(PF and VF). The commit message scopes this to non-cache-coherent
parts (i.MX95), but the code applies it everywhere, adding dcbf/dccivac
cost on cache-coherent platforms that previously used the _nc fast
path. Gate it on a devarg or coherency/platform check.
Warning: the RX payload invalidation uses dccivac (dc civac =
clean+invalidate). The comment justifies clean-then-invalidate for the
BD ring (refill dcbf leaves BD lines clean), but payload buffers are
not cleaned before being handed to HW. If a payload cache line is dirty
(stale CPU data from a prior use of the mbuf), the clean phase writes
it back over the HW-DMA'd data in DDR before invalidating -> silent RX
corruption on a non-coherent part. Please confirm payload lines can
never be dirty here, or use invalidate-only.
Info: struct enetc_bdr gains "uint64_t bd_base_p" but it is never
referenced anywhere. Remove the dead field.
Info: the 64-bit BD fast copy
__uint128_t *dst128 = (__uint128_t *)&rxbd_temp;
*dst128 = *(const __uint128_t *)rxbd;
takes the address of an 8-byte-aligned stack union (rxbd_temp) as
__uint128_t*. That is an under-aligned 128-bit access (UB); aarch64
tolerates it via ldp/stp but it is fragile. Force 16-byte alignment on
rxbd_temp or copy as two u64.
General (series-wide)
Warning: no release notes. The series adds user-visible features
(scatter-gather, cacheable BD ring support, four new devargs) with no
entry in doc/guides/rel_notes/. New driver capabilities and devargs
need release-note coverage.
^ permalink raw reply
* Re: [PATCH v4 00/23] et/sxe2: added Linkdata sxe2 ethernet driver
From: Stephen Hemminger @ 2026-06-19 20:58 UTC (permalink / raw)
To: liujie5; +Cc: dev
In-Reply-To: <20260619080156.1539964-1-liujie5@linkdatatechnology.com>
On Fri, 19 Jun 2026 16:01:56 +0800
liujie5@linkdatatechnology.com wrote:
> From: Jie Liu <liujie5@linkdatatechnology.com>
>
> This patch set implements core functionality for the SXE2 PMD,
> including basic driver framework, data path setup, and advanced
> offload features (VLAN, RSS,TM, PTP etc.).
Looking over the driver overall, I noticed you are adding cflags for -g.
This is not necessary, meson supports this via -Dbuildtype=debug or -Dbuildtype=debugoptimized
Remove this in meson.build
cflags += ['-g']
^ permalink raw reply
* [PATCH v3] graph: add optional profiling stats
From: Morten Brørup @ 2026-06-19 20:56 UTC (permalink / raw)
To: dev, Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram, Zhirun Yan
Cc: Morten Brørup
In-Reply-To: <20260619202047.2809165-1-mb@smartsharesystems.com>
graph: add optional profiling stats
Added graph node profiling stats, build time configurable by enabling
RTE_GRAPH_PROFILE in rte_config.h.
Signed-off-by: Morten Brørup <mb@smartsharesystems.com>
---
v3:
* Debug shows cycles/obj instead of cycles/call.
* Fixed missing --in-reply-to.
v2:
* Fix indentation.
---
config/rte_config.h | 1 +
lib/graph/graph_debug.c | 29 ++++++++++++++++++++++++++++-
lib/graph/node.c | 2 ++
lib/graph/rte_graph_worker_common.h | 23 ++++++++++++++++++++---
4 files changed, 51 insertions(+), 4 deletions(-)
diff --git a/config/rte_config.h b/config/rte_config.h
index 0447cdf2ad..1942c1b1ec 100644
--- a/config/rte_config.h
+++ b/config/rte_config.h
@@ -106,6 +106,7 @@
/* rte_graph defines */
#define RTE_GRAPH_BURST_SIZE 256
#define RTE_LIBRTE_GRAPH_STATS 1
+/* RTE_GRAPH_PROFILE is not set */
/****** driver defines ********/
diff --git a/lib/graph/graph_debug.c b/lib/graph/graph_debug.c
index e3b8cccdc1..1110b43c6a 100644
--- a/lib/graph/graph_debug.c
+++ b/lib/graph/graph_debug.c
@@ -92,7 +92,34 @@ rte_graph_obj_dump(FILE *f, struct rte_graph *g, bool all)
fprintf(f, " total_sched_fail=%" PRId64 "\n",
n->dispatch.total_sched_fail);
}
- fprintf(f, " total_calls=%" PRId64 "\n", n->total_calls);
+ fprintf(f, " total_calls=%" PRIu64 "\n", n->total_calls);
+ fprintf(f, " total_cycles=%" PRIu64 "\n", n->total_cycles);
+#ifdef RTE_GRAPH_PROFILE
+ uint64_t calls_2_or_more = n->total_calls -
+ (n->usage_stats[0].calls + n->usage_stats[1].calls);
+ double avg_objs_2_or_more = calls_2_or_more == 0 ? (double)2 :
+ (double)(n->total_objs - n->usage_stats[1].calls) /
+ (double)calls_2_or_more;
+ fprintf(f, " calls_0=%" PRIu64 ", _1=%" PRIu64 ", _%.1f=%" PRIu64 "\n",
+ n->usage_stats[0].calls,
+ n->usage_stats[1].calls,
+ avg_objs_2_or_more,
+ calls_2_or_more);
+ fprintf(f, " cycles_0=%" PRIu64 ", _1=%" PRIu64 ", _%.1f=%" PRIu64 "\n",
+ n->usage_stats[0].cycles,
+ n->usage_stats[1].cycles,
+ avg_objs_2_or_more,
+ n->total_cycles -
+ (n->usage_stats[0].cycles + n->usage_stats[1].cycles));
+ fprintf(f, " cycles_per_obj_1=%.1f, _%.1f=%.1f\n",
+ n->usage_stats[1].calls == 0 ? (double)0 :
+ (double)n->usage_stats[1].cycles / (double)n->usage_stats[1].calls,
+ avg_objs_2_or_more,
+ calls_2_or_more == 0 ? (double)0 :
+ (double)(n->total_cycles -
+ (n->usage_stats[0].cycles + n->usage_stats[1].cycles)) /
+ (double)calls_2_or_more / avg_objs_2_or_more);
+#endif
for (i = 0; i < n->nb_edges; i++)
fprintf(f, " edge[%d] <%s>\n", i,
n->nodes[i]->name);
diff --git a/lib/graph/node.c b/lib/graph/node.c
index 1fce3e6632..19b38881ae 100644
--- a/lib/graph/node.c
+++ b/lib/graph/node.c
@@ -110,10 +110,12 @@ __rte_node_register(const struct rte_node_register *reg)
rte_edge_t i;
size_t sz;
+#ifndef RTE_GRAPH_PROFILE
/* Limit Node specific metadata to one cacheline on 64B CL machine */
RTE_BUILD_BUG_ON((offsetof(struct rte_node, nodes) -
offsetof(struct rte_node, ctx)) !=
RTE_CACHE_LINE_MIN_SIZE);
+#endif
graph_spinlock_lock();
diff --git a/lib/graph/rte_graph_worker_common.h b/lib/graph/rte_graph_worker_common.h
index 4ab53a533e..43ce23765b 100644
--- a/lib/graph/rte_graph_worker_common.h
+++ b/lib/graph/rte_graph_worker_common.h
@@ -144,12 +144,22 @@ struct __rte_cache_aligned rte_node {
rte_node_process_t process; /**< Process function. */
uint64_t process_u64;
};
+ /** Fast path area cache line 3. */
+#ifdef RTE_GRAPH_PROFILE
+ struct {
+ uint64_t calls;
+ uint64_t cycles;
+ } usage_stats[2]; /**< Usage when this node processed 0 or 1 objects. */
+ /** Fast path area cache line 4. */
+#endif
alignas(RTE_CACHE_LINE_MIN_SIZE) struct rte_node *nodes[]; /**< Next nodes. */
};
};
+#ifndef RTE_GRAPH_PROFILE
static_assert(offsetof(struct rte_node, nodes) - offsetof(struct rte_node, ctx)
== RTE_CACHE_LINE_MIN_SIZE, "rte_node fast path area must fit in 64 bytes");
+#endif
/**
* @internal
@@ -197,7 +207,7 @@ void __rte_node_stream_alloc_size(struct rte_graph *graph,
static __rte_always_inline void
__rte_node_process(struct rte_graph *graph, struct rte_node *node)
{
- uint64_t start;
+ uint64_t cycles;
uint16_t rc;
void **objs;
@@ -206,11 +216,18 @@ __rte_node_process(struct rte_graph *graph, struct rte_node *node)
rte_prefetch0(objs);
if (rte_graph_has_stats_feature()) {
- start = rte_rdtsc();
+ cycles = -rte_rdtsc();
rc = node->process(graph, node, objs, node->idx);
- node->total_cycles += rte_rdtsc() - start;
+ cycles += rte_rdtsc();
+ node->total_cycles += cycles;
node->total_calls++;
node->total_objs += rc;
+#ifdef RTE_GRAPH_PROFILE
+ if (rc <= 1) {
+ node->usage_stats[rc].calls++;
+ node->usage_stats[rc].cycles += cycles;
+ }
+#endif
} else {
node->process(graph, node, objs, node->idx);
}
--
2.43.0
^ permalink raw reply related
* Re: [PATCH v4 09/23] net/sxe2: support IPsec inline protocol offload
From: Stephen Hemminger @ 2026-06-19 20:54 UTC (permalink / raw)
To: liujie5; +Cc: dev
In-Reply-To: <20260619080812.1543972-1-liujie5@linkdatatechnology.com>
On Fri, 19 Jun 2026 16:08:12 +0800
liujie5@linkdatatechnology.com wrote:
> diff --git a/drivers/net/sxe2/sxe2_cmd_chnl.c b/drivers/net/sxe2/sxe2_cmd_chnl.c
> index 19323ffcc4..7711e8e57d 100644
> --- a/drivers/net/sxe2/sxe2_cmd_chnl.c
> +++ b/drivers/net/sxe2/sxe2_cmd_chnl.c
> @@ -877,3 +877,200 @@ int32_t sxe2_drv_tm_commit(struct sxe2_adapter *adapter)
> l_end:
...
> +int32_t sxe2_drv_ipsec_txsa_delete(struct sxe2_adapter *adapter,
> + uint16_t sa_id)
> +{
> + struct sxe2_drv_ipsec_txsa_del_req req = { 0 };
> + struct sxe2_drv_cmd_params cmd = { 0 };
> + struct sxe2_common_device *cdev = adapter->cdev;
> + int32_t ret = -1;
> +
> + req.sa_idx = rte_cpu_to_le_16(sa_id);
> + sxe2_drv_cmd_params_fill(adapter, &cmd, SXE2_DRV_CMD_IPSEC_TXSA_DEL,
> + &req, sizeof(req),
> + NULL, 0);
> + ret = sxe2_drv_cmd_exec(cdev, &cmd);
> + if (ret)
> + PMD_DEV_LOG_ERR(adapter, DRV,
> + "Failed to delete tx sa, sa id: %u, ret: %d.",
> + sa_id, ret);
> +
> + return ret;
> +}
> +
git merge doesn't like extra blank lines at end of file.
Applying: net/sxe2: support IPsec inline protocol offload
/home/shemminger/DPDK/main/.git/worktrees/sxe2/rebase-apply/patch:236: new blank line at EOF.
+
warning: 1 line adds whitespace errors.
^ permalink raw reply
* [PATCH v2] graph: add optional profiling stats
From: Morten Brørup @ 2026-06-19 20:25 UTC (permalink / raw)
To: dev, Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram, Zhirun Yan
Cc: Morten Brørup
Added graph node profiling stats, build time configurable by enabling
RTE_GRAPH_PROFILE in rte_config.h.
Signed-off-by: Morten Brørup <mb@smartsharesystems.com>
---
v2:
* Fix indentation.
---
config/rte_config.h | 1 +
lib/graph/graph_debug.c | 29 ++++++++++++++++++++++++++++-
lib/graph/node.c | 2 ++
lib/graph/rte_graph_worker_common.h | 23 ++++++++++++++++++++---
4 files changed, 51 insertions(+), 4 deletions(-)
diff --git a/config/rte_config.h b/config/rte_config.h
index 0447cdf2ad..1942c1b1ec 100644
--- a/config/rte_config.h
+++ b/config/rte_config.h
@@ -106,6 +106,7 @@
/* rte_graph defines */
#define RTE_GRAPH_BURST_SIZE 256
#define RTE_LIBRTE_GRAPH_STATS 1
+/* RTE_GRAPH_PROFILE is not set */
/****** driver defines ********/
diff --git a/lib/graph/graph_debug.c b/lib/graph/graph_debug.c
index e3b8cccdc1..b1028f88ed 100644
--- a/lib/graph/graph_debug.c
+++ b/lib/graph/graph_debug.c
@@ -92,7 +92,34 @@ rte_graph_obj_dump(FILE *f, struct rte_graph *g, bool all)
fprintf(f, " total_sched_fail=%" PRId64 "\n",
n->dispatch.total_sched_fail);
}
- fprintf(f, " total_calls=%" PRId64 "\n", n->total_calls);
+ fprintf(f, " total_calls=%" PRIu64 "\n", n->total_calls);
+ fprintf(f, " total_cycles=%" PRIu64 "\n", n->total_cycles);
+#ifdef RTE_GRAPH_PROFILE
+ uint64_t calls_2_or_more = n->total_calls -
+ (n->usage_stats[0].calls + n->usage_stats[1].calls);
+ double avg_objs_2_or_more = calls_2_or_more == 0 ? (double)2 :
+ (double)(n->total_objs - n->usage_stats[1].calls) /
+ (double)calls_2_or_more;
+ fprintf(f, " calls_0=%" PRIu64 ", _1=%" PRIu64 ", _%.1f=%" PRIu64 "\n",
+ n->usage_stats[0].calls,
+ n->usage_stats[1].calls,
+ avg_objs_2_or_more,
+ calls_2_or_more);
+ fprintf(f, " cycles_0=%" PRIu64 ", _1=%" PRIu64 ", _%.1f=%" PRIu64 "\n",
+ n->usage_stats[0].cycles,
+ n->usage_stats[1].cycles,
+ avg_objs_2_or_more,
+ n->total_cycles -
+ (n->usage_stats[0].cycles + n->usage_stats[1].cycles));
+ fprintf(f, " cycles_per_call_1=%.1f, _%.1f=%.1f\n",
+ n->usage_stats[1].calls == 0 ? (double)0 :
+ (double)n->usage_stats[1].cycles / (double)n->usage_stats[1].calls,
+ avg_objs_2_or_more,
+ calls_2_or_more == 0 ? (double)0 :
+ (double)(n->total_cycles -
+ (n->usage_stats[0].cycles + n->usage_stats[1].cycles)) /
+ (double)calls_2_or_more);
+#endif
for (i = 0; i < n->nb_edges; i++)
fprintf(f, " edge[%d] <%s>\n", i,
n->nodes[i]->name);
diff --git a/lib/graph/node.c b/lib/graph/node.c
index 1fce3e6632..19b38881ae 100644
--- a/lib/graph/node.c
+++ b/lib/graph/node.c
@@ -110,10 +110,12 @@ __rte_node_register(const struct rte_node_register *reg)
rte_edge_t i;
size_t sz;
+#ifndef RTE_GRAPH_PROFILE
/* Limit Node specific metadata to one cacheline on 64B CL machine */
RTE_BUILD_BUG_ON((offsetof(struct rte_node, nodes) -
offsetof(struct rte_node, ctx)) !=
RTE_CACHE_LINE_MIN_SIZE);
+#endif
graph_spinlock_lock();
diff --git a/lib/graph/rte_graph_worker_common.h b/lib/graph/rte_graph_worker_common.h
index 4ab53a533e..43ce23765b 100644
--- a/lib/graph/rte_graph_worker_common.h
+++ b/lib/graph/rte_graph_worker_common.h
@@ -144,12 +144,22 @@ struct __rte_cache_aligned rte_node {
rte_node_process_t process; /**< Process function. */
uint64_t process_u64;
};
+ /** Fast path area cache line 3. */
+#ifdef RTE_GRAPH_PROFILE
+ struct {
+ uint64_t calls;
+ uint64_t cycles;
+ } usage_stats[2]; /**< Usage when this node processed 0 or 1 objects. */
+ /** Fast path area cache line 4. */
+#endif
alignas(RTE_CACHE_LINE_MIN_SIZE) struct rte_node *nodes[]; /**< Next nodes. */
};
};
+#ifndef RTE_GRAPH_PROFILE
static_assert(offsetof(struct rte_node, nodes) - offsetof(struct rte_node, ctx)
== RTE_CACHE_LINE_MIN_SIZE, "rte_node fast path area must fit in 64 bytes");
+#endif
/**
* @internal
@@ -197,7 +207,7 @@ void __rte_node_stream_alloc_size(struct rte_graph *graph,
static __rte_always_inline void
__rte_node_process(struct rte_graph *graph, struct rte_node *node)
{
- uint64_t start;
+ uint64_t cycles;
uint16_t rc;
void **objs;
@@ -206,11 +216,18 @@ __rte_node_process(struct rte_graph *graph, struct rte_node *node)
rte_prefetch0(objs);
if (rte_graph_has_stats_feature()) {
- start = rte_rdtsc();
+ cycles = -rte_rdtsc();
rc = node->process(graph, node, objs, node->idx);
- node->total_cycles += rte_rdtsc() - start;
+ cycles += rte_rdtsc();
+ node->total_cycles += cycles;
node->total_calls++;
node->total_objs += rc;
+#ifdef RTE_GRAPH_PROFILE
+ if (rc <= 1) {
+ node->usage_stats[rc].calls++;
+ node->usage_stats[rc].cycles += cycles;
+ }
+#endif
} else {
node->process(graph, node, objs, node->idx);
}
--
2.43.0
^ permalink raw reply related
* [PATCH] graph: add optional profiling stats
From: Morten Brørup @ 2026-06-19 20:20 UTC (permalink / raw)
To: dev, Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram, Zhirun Yan
Cc: Morten Brørup
Added graph node profiling stats, build time configurable by enabling
RTE_GRAPH_PROFILE in rte_config.h.
Signed-off-by: Morten Brørup <mb@smartsharesystems.com>
---
config/rte_config.h | 1 +
lib/graph/graph_debug.c | 29 ++++++++++++++++++++++++++++-
lib/graph/node.c | 2 ++
lib/graph/rte_graph_worker_common.h | 23 ++++++++++++++++++++---
4 files changed, 51 insertions(+), 4 deletions(-)
diff --git a/config/rte_config.h b/config/rte_config.h
index 0447cdf2ad..1942c1b1ec 100644
--- a/config/rte_config.h
+++ b/config/rte_config.h
@@ -106,6 +106,7 @@
/* rte_graph defines */
#define RTE_GRAPH_BURST_SIZE 256
#define RTE_LIBRTE_GRAPH_STATS 1
+/* RTE_GRAPH_PROFILE is not set */
/****** driver defines ********/
diff --git a/lib/graph/graph_debug.c b/lib/graph/graph_debug.c
index e3b8cccdc1..883e37707c 100644
--- a/lib/graph/graph_debug.c
+++ b/lib/graph/graph_debug.c
@@ -92,7 +92,34 @@ rte_graph_obj_dump(FILE *f, struct rte_graph *g, bool all)
fprintf(f, " total_sched_fail=%" PRId64 "\n",
n->dispatch.total_sched_fail);
}
- fprintf(f, " total_calls=%" PRId64 "\n", n->total_calls);
+ fprintf(f, " total_calls=%" PRIu64 "\n", n->total_calls);
+ fprintf(f, " total_cycles=%" PRIu64 "\n", n->total_cycles);
+#ifdef RTE_GRAPH_PROFILE
+ uint64_t calls_2_or_more = n->total_calls -
+ (n->usage_stats[0].calls + n->usage_stats[1].calls);
+ double avg_objs_2_or_more = calls_2_or_more == 0 ? (double)2 :
+ (double)(n->total_objs - n->usage_stats[1].calls) /
+ (double)calls_2_or_more;
+ fprintf(f, " calls_0=%" PRIu64 ", _1=%" PRIu64 ", _%.1f=%" PRIu64 "\n",
+ n->usage_stats[0].calls,
+ n->usage_stats[1].calls,
+ avg_objs_2_or_more,
+ calls_2_or_more);
+ fprintf(f, " cycles_0=%" PRIu64 ", _1=%" PRIu64 ", _%.1f=%" PRIu64 "\n",
+ n->usage_stats[0].cycles,
+ n->usage_stats[1].cycles,
+ avg_objs_2_or_more,
+ n->total_cycles -
+ (n->usage_stats[0].cycles + n->usage_stats[1].cycles));
+ fprintf(f, " cycles_per_call_1=%.1f, _%.1f=%.1f\n",
+ n->usage_stats[1].calls == 0 ? (double)0 :
+ (double)n->usage_stats[1].cycles / (double)n->usage_stats[1].calls,
+ avg_objs_2_or_more,
+ calls_2_or_more == 0 ? (double)0 :
+ (double)(n->total_cycles -
+ (n->usage_stats[0].cycles + n->usage_stats[1].cycles)) /
+ (double)calls_2_or_more);
+#endif
for (i = 0; i < n->nb_edges; i++)
fprintf(f, " edge[%d] <%s>\n", i,
n->nodes[i]->name);
diff --git a/lib/graph/node.c b/lib/graph/node.c
index 1fce3e6632..19b38881ae 100644
--- a/lib/graph/node.c
+++ b/lib/graph/node.c
@@ -110,10 +110,12 @@ __rte_node_register(const struct rte_node_register *reg)
rte_edge_t i;
size_t sz;
+#ifndef RTE_GRAPH_PROFILE
/* Limit Node specific metadata to one cacheline on 64B CL machine */
RTE_BUILD_BUG_ON((offsetof(struct rte_node, nodes) -
offsetof(struct rte_node, ctx)) !=
RTE_CACHE_LINE_MIN_SIZE);
+#endif
graph_spinlock_lock();
diff --git a/lib/graph/rte_graph_worker_common.h b/lib/graph/rte_graph_worker_common.h
index 4ab53a533e..43ce23765b 100644
--- a/lib/graph/rte_graph_worker_common.h
+++ b/lib/graph/rte_graph_worker_common.h
@@ -144,12 +144,22 @@ struct __rte_cache_aligned rte_node {
rte_node_process_t process; /**< Process function. */
uint64_t process_u64;
};
+ /** Fast path area cache line 3. */
+#ifdef RTE_GRAPH_PROFILE
+ struct {
+ uint64_t calls;
+ uint64_t cycles;
+ } usage_stats[2]; /**< Usage when this node processed 0 or 1 objects. */
+ /** Fast path area cache line 4. */
+#endif
alignas(RTE_CACHE_LINE_MIN_SIZE) struct rte_node *nodes[]; /**< Next nodes. */
};
};
+#ifndef RTE_GRAPH_PROFILE
static_assert(offsetof(struct rte_node, nodes) - offsetof(struct rte_node, ctx)
== RTE_CACHE_LINE_MIN_SIZE, "rte_node fast path area must fit in 64 bytes");
+#endif
/**
* @internal
@@ -197,7 +207,7 @@ void __rte_node_stream_alloc_size(struct rte_graph *graph,
static __rte_always_inline void
__rte_node_process(struct rte_graph *graph, struct rte_node *node)
{
- uint64_t start;
+ uint64_t cycles;
uint16_t rc;
void **objs;
@@ -206,11 +216,18 @@ __rte_node_process(struct rte_graph *graph, struct rte_node *node)
rte_prefetch0(objs);
if (rte_graph_has_stats_feature()) {
- start = rte_rdtsc();
+ cycles = -rte_rdtsc();
rc = node->process(graph, node, objs, node->idx);
- node->total_cycles += rte_rdtsc() - start;
+ cycles += rte_rdtsc();
+ node->total_cycles += cycles;
node->total_calls++;
node->total_objs += rc;
+#ifdef RTE_GRAPH_PROFILE
+ if (rc <= 1) {
+ node->usage_stats[rc].calls++;
+ node->usage_stats[rc].cycles += cycles;
+ }
+#endif
} else {
node->process(graph, node, objs, node->idx);
}
--
2.43.0
^ permalink raw reply related
* RE: [PATCH v1 0/5] prefix lcore role enum values
From: Morten Brørup @ 2026-06-19 20:11 UTC (permalink / raw)
To: Stephen Hemminger
Cc: Thomas Monjalon, Huisong Li, andrew.rybchenko, dev, zhanjie9
In-Reply-To: <20260619083934.510bd2d4@phoenix.local>
> From: Stephen Hemminger [mailto:stephen@networkplumber.org]
> Sent: Friday, 19 June 2026 17.40
>
> On Fri, 19 Jun 2026 09:54:51 +0200
> Morten Brørup <mb@smartsharesystems.com> wrote:
>
> > > > The problem with this patch it causes build failures now with abi
> > > diff.
> > >
> > > It is probably a bug of an old version of abidiff.
> > > I recommend updating.
> >
> > With the #define's the ABI has not changed. It's probably too
> indirect for abidiff to understand.
> > If we absolutely want to please abidiff, we could keep the existing
> enums and #define RTE_LCORE_ROLE_RTE ROLE_RTE for now.
> > But I'm in favor of what was done already.
>
> The build failures on github, not in my local builds.
> https://github.com/ovsrobot/dpdk/actions/runs/27789889172/job/822359650
> 90
>
> It makes looking at patchwork dashboard difficult, all patches show up
> with red mark
So maybe we can choose the path of pleasing abidiff...
Keep the existing enums, and #define the new RTE_LCORE_ prefixed variants, and use those in the code.
Later, with an ABI breaking release, we can swap.
Or maybe we just wait until an ABI breaking release to fix this.
^ permalink raw reply
* [PATCH 10/10] net/enetc4: add cacheable BD ring support with SW cache maintenance
From: Gagandeep Singh @ 2026-06-19 18:44 UTC (permalink / raw)
To: dev; +Cc: hemant.agrawal
In-Reply-To: <20260619184427.522518-1-g.singh@nxp.com>
On non-cache-coherent platforms such as i.MX95, the BD ring memory
may be mapped as cacheable (normal memory) while the ENETC hardware
DMA engine writes and reads descriptors without CPU cache snooping.
SW must therefore perform explicit cache maintenance to keep CPU
caches and DDR coherent.
TX path (enetc_xmit_pkts_cacheable):
- Flush each segment's payload cache lines to PoC (dcbf) before
the BD is handed to HW, so HW DMA reads the correct data.
- After all BDs for a burst are written, flush the BD cache lines
(dcbf, one per 64-byte group of 4 BDs) so HW can read the
updated descriptors.
RX refill (enetc_refill_rx_ring):
- After writing each full 4-BD cache-line group, dcbf that group
so HW sees the buffer addresses and cleared lstatus fields.
- Flush any partial trailing group before updating the ring tail.
RX receive (enetc_recv_pkts_cacheable via enetc_clean_rx_ring_cacheable):
- Before reading BD status, dccivac the current BD cache line so
stale CPU-cached BD data is discarded and fresh HW-written
content is fetched from DDR.
- After a BD is consumed, dccivac each payload cache line so the
CPU reads the DMA'd packet data, not stale cached bytes.
Signed-off-by: Gagandeep Singh <g.singh@nxp.com>
---
drivers/net/enetc/enetc.h | 21 +++
drivers/net/enetc/enetc4_ethdev.c | 40 +++--
drivers/net/enetc/enetc_rxtx.c | 274 ++++++++++++++++++++++++++++++
3 files changed, 320 insertions(+), 15 deletions(-)
diff --git a/drivers/net/enetc/enetc.h b/drivers/net/enetc/enetc.h
index 99b1e91..9f98480 100644
--- a/drivers/net/enetc/enetc.h
+++ b/drivers/net/enetc/enetc.h
@@ -96,6 +96,7 @@ struct enetc_bdr {
uint64_t ierrors;
uint8_t rx_deferred_start;
uint8_t tx_deferred_start;
+ uint64_t bd_base_p;
};
struct enetc_eth_hw {
@@ -312,8 +313,28 @@ uint16_t enetc_recv_pkts(void *rxq, struct rte_mbuf **rx_pkts,
uint16_t nb_pkts);
uint16_t enetc_recv_pkts_nc(void *rxq, struct rte_mbuf **rx_pkts,
uint16_t nb_pkts);
+uint16_t enetc_xmit_pkts_cacheable(void *txq, struct rte_mbuf **tx_pkts,
+ uint16_t nb_pkts);
+uint16_t enetc_recv_pkts_cacheable(void *rxq, struct rte_mbuf **rx_pkts,
+ uint16_t nb_pkts);
int enetc_refill_rx_ring(struct enetc_bdr *rx_ring, const int buff_cnt);
+
+/*
+ * Cache-maintenance constants for cacheable BD ring mode.
+ *
+ * BD = 16 bytes, cache line = 64 bytes => 4 BDs per cache line.
+ * Every dcbf in enetc_refill_rx_ring() flushes a full 64-byte cache line.
+ * To ensure each dcbf covers only fully-written BDs the caller
+ * must pass a count rounded DOWN to a multiple of ENETC_BD_PER_CL so that
+ * the last partial group is left in cache to be completed and flushed in
+ * the next call.
+ */
+#define ENETC_BD_PER_CL (RTE_CACHE_LINE_SIZE / sizeof(union enetc_rx_bd))
+#define ENETC_BD_PER_CL_MASK (ENETC_BD_PER_CL - 1)
+/* Round n DOWN to the nearest multiple of ENETC_BD_PER_CL. */
+#define ENETC_BD_ALIGN_DOWN(n) ((n) & ~(unsigned int)ENETC_BD_PER_CL_MASK)
+
void enetc4_dev_hw_init(struct rte_eth_dev *eth_dev);
void enetc_print_ethaddr(const char *name, const struct rte_ether_addr *eth_addr);
diff --git a/drivers/net/enetc/enetc4_ethdev.c b/drivers/net/enetc/enetc4_ethdev.c
index d54051f..04dc306 100644
--- a/drivers/net/enetc/enetc4_ethdev.c
+++ b/drivers/net/enetc/enetc4_ethdev.c
@@ -281,12 +281,14 @@ enetc4_alloc_txbdr(struct enetc_bdr *txr, uint16_t nb_desc)
int size;
size = nb_desc * sizeof(struct enetc_swbd);
- txr->q_swbd = rte_malloc(NULL, size, ENETC_BD_RING_ALIGN);
+ /* Zero q_swbd so buffer_addr is NULL for all uninitialized slots. */
+ txr->q_swbd = rte_zmalloc(NULL, size, ENETC_BD_RING_ALIGN);
if (txr->q_swbd == NULL)
return -ENOMEM;
- size = nb_desc * sizeof(struct enetc_bdr);
- txr->bd_base = rte_malloc(NULL, size, ENETC_BD_RING_ALIGN);
+ /* Allocate the TX BD ring: each BD is struct enetc_tx_bd (16 bytes). */
+ size = nb_desc * sizeof(struct enetc_tx_bd);
+ txr->bd_base = rte_zmalloc(NULL, size, ENETC_BD_RING_ALIGN);
if (txr->bd_base == NULL) {
rte_free(txr->q_swbd);
txr->q_swbd = NULL;
@@ -441,12 +443,14 @@ enetc4_alloc_rxbdr(struct enetc_bdr *rxr, uint16_t nb_desc)
int size;
size = nb_desc * sizeof(struct enetc_swbd);
- rxr->q_swbd = rte_malloc(NULL, size, ENETC_BD_RING_ALIGN);
+ /* Zero q_swbd so buffer_addr is NULL for all uninitialized slots. */
+ rxr->q_swbd = rte_zmalloc(NULL, size, ENETC_BD_RING_ALIGN);
if (rxr->q_swbd == NULL)
return -ENOMEM;
- size = nb_desc * sizeof(struct enetc_bdr);
- rxr->bd_base = rte_malloc(NULL, size, ENETC_BD_RING_ALIGN);
+ /* Allocate the RX BD ring: each BD is union enetc_rx_bd (16 bytes). */
+ size = nb_desc * sizeof(union enetc_rx_bd);
+ rxr->bd_base = rte_zmalloc(NULL, size, ENETC_BD_RING_ALIGN);
if (rxr->bd_base == NULL) {
rte_free(rxr->q_swbd);
rxr->q_swbd = NULL;
@@ -481,7 +485,7 @@ enetc4_setup_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring,
rx_ring->mb_pool = mb_pool;
rx_ring->rcir = (void *)((size_t)hw->reg +
ENETC_BDR(RX, idx, ENETC_RBCIR));
- enetc_refill_rx_ring(rx_ring, (enetc_bd_unused(rx_ring)));
+ enetc_refill_rx_ring(rx_ring, ENETC_BD_ALIGN_DOWN(enetc_bd_unused(rx_ring)));
buf_size = (uint16_t)(rte_pktmbuf_data_room_size(rx_ring->mb_pool) -
RTE_PKTMBUF_HEADROOM);
enetc4_rxbdr_wr(hw, idx, ENETC_RBBSR, buf_size);
@@ -743,12 +747,17 @@ enetc4_dev_configure(struct rte_eth_dev *dev)
PMD_INIT_FUNC_TRACE();
- max_len = dev->data->dev_conf.rxmode.mtu + RTE_ETHER_HDR_LEN +
- RTE_ETHER_CRC_LEN;
- enetc4_port_wr(enetc_hw, ENETC4_PM_MAXFRM(0), ENETC_SET_MAXFRM(max_len));
+ /* Port-level register writes are PF-only; skip for VF devices */
+ if (hw->device_id != ENETC4_DEV_ID_VF) {
+ max_len = dev->data->dev_conf.rxmode.mtu + RTE_ETHER_HDR_LEN +
+ RTE_ETHER_CRC_LEN;
+ enetc4_port_wr(enetc_hw, ENETC4_PM_MAXFRM(0),
+ ENETC_SET_MAXFRM(max_len));
- val = ENETC4_MAC_MAXFRM_SIZE | SDU_TYPE_MPDU;
- enetc4_port_wr(enetc_hw, ENETC4_PTCTMSDUR(0), val | SDU_TYPE_MPDU);
+ val = ENETC4_MAC_MAXFRM_SIZE | SDU_TYPE_MPDU;
+ enetc4_port_wr(enetc_hw, ENETC4_PTCTMSDUR(0),
+ val | SDU_TYPE_MPDU);
+ }
/* Rx offloads which are enabled by default */
if (dev_rx_offloads_sup & ~rx_offloads) {
@@ -770,7 +779,8 @@ enetc4_dev_configure(struct rte_eth_dev *dev)
if (rx_offloads & (RTE_ETH_RX_OFFLOAD_UDP_CKSUM | RTE_ETH_RX_OFFLOAD_TCP_CKSUM))
checksum &= ~L4_CKSUM;
- enetc4_port_wr(enetc_hw, ENETC4_PARCSCR, checksum);
+ if (hw->device_id != ENETC4_DEV_ID_VF)
+ enetc4_port_wr(enetc_hw, ENETC4_PARCSCR, checksum);
/* Enable interrupts */
if (hw->device_id == ENETC4_DEV_ID_VF) {
@@ -1033,8 +1043,8 @@ enetc4_dev_hw_init(struct rte_eth_dev *eth_dev)
ENETC_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
struct rte_pci_device *pci_dev = RTE_CLASS_TO_BUS_DEVICE(eth_dev, *pci_dev);
- eth_dev->rx_pkt_burst = &enetc_recv_pkts_nc;
- eth_dev->tx_pkt_burst = &enetc_xmit_pkts_nc;
+ eth_dev->rx_pkt_burst = &enetc_recv_pkts_cacheable;
+ eth_dev->tx_pkt_burst = &enetc_xmit_pkts_cacheable;
/* Retrieving and storing the HW base address of device */
hw->hw.reg = (void *)pci_dev->mem_resource[0].addr;
diff --git a/drivers/net/enetc/enetc_rxtx.c b/drivers/net/enetc/enetc_rxtx.c
index a37c835..c737b22 100644
--- a/drivers/net/enetc/enetc_rxtx.c
+++ b/drivers/net/enetc/enetc_rxtx.c
@@ -26,6 +26,7 @@ enetc_clean_tx_ring(struct enetc_bdr *tx_ring)
struct enetc_swbd *tx_swbd, *tx_swbd_base;
int i, hwci, bd_count;
struct rte_mbuf *m[ENETC_RXBD_BUNDLE];
+ struct enetc_tx_bd *txbd;
/* we don't need barriers here, we just want a relatively current value
* from HW.
@@ -51,6 +52,13 @@ enetc_clean_tx_ring(struct enetc_bdr *tx_ring)
/* It seems calling rte_pktmbuf_free is wasting a lot of cycles,
* make a list and call _free when it's done.
*/
+ /* Clear flags on the reclaimed BD so that dcbf in the
+ * cacheable TX path never flushes a stale flags_F to memory
+ * before the new BD fields are fully written.
+ */
+ txbd = ENETC_TXBD(*tx_ring, i);
+ txbd->flags = 0;
+
if (tx_frm_cnt == ENETC_RXBD_BUNDLE) {
rte_pktmbuf_free_bulk(m, tx_frm_cnt);
tx_frm_cnt = 0;
@@ -217,6 +225,7 @@ enetc_refill_rx_ring(struct enetc_bdr *rx_ring, const int buff_cnt)
{
struct enetc_swbd *rx_swbd;
union enetc_rx_bd *rxbd;
+ union enetc_rx_bd *grp_start_rxbd;
int i, j, k = ENETC_RXBD_BUNDLE;
struct rte_mbuf *m[ENETC_RXBD_BUNDLE];
struct rte_mempool *mb_pool;
@@ -225,6 +234,7 @@ enetc_refill_rx_ring(struct enetc_bdr *rx_ring, const int buff_cnt)
mb_pool = rx_ring->mb_pool;
rx_swbd = &rx_ring->q_swbd[i];
rxbd = ENETC_RXBD(*rx_ring, i);
+ grp_start_rxbd = rxbd;
for (j = 0; j < buff_cnt; j++) {
/* bulk alloc for the next up to 8 BDs */
if (k == ENETC_RXBD_BUNDLE) {
@@ -246,12 +256,29 @@ enetc_refill_rx_ring(struct enetc_bdr *rx_ring, const int buff_cnt)
i++;
k++;
if (unlikely(i == rx_ring->bd_count)) {
+ /*
+ * Ring wrap: flush the current partial or full group
+ * before resetting the pointer to index 0.
+ */
+ dcbf((void *)grp_start_rxbd);
i = 0;
rxbd = ENETC_RXBD(*rx_ring, i);
rx_swbd = &rx_ring->q_swbd[i];
+ grp_start_rxbd = rxbd;
+ } else if ((i & ENETC_BD_PER_CL_MASK) == 0) {
+ /*
+ * Completed a full 4-BD group (one cache line).
+ * Flush it to PoC so HW sees the updated descriptors.
+ */
+ dcbf((void *)grp_start_rxbd);
+ grp_start_rxbd = rxbd;
}
}
+ /* Flush any remaining partial group at the end of the fill. */
+ if (j && (i & ENETC_BD_PER_CL_MASK) != 0)
+ dcbf((void *)grp_start_rxbd);
+
if (likely(j)) {
rx_ring->next_to_alloc = i;
rx_ring->next_to_use = i;
@@ -597,3 +624,250 @@ enetc_recv_pkts(void *rxq, struct rte_mbuf **rx_pkts,
return enetc_clean_rx_ring(rx_ring, rx_pkts, nb_pkts);
}
+
+/* --- Cacheable BD ring TX path with SW cache maintenance (dcbf) --- */
+
+uint16_t
+enetc_xmit_pkts_cacheable(void *tx_queue,
+ struct rte_mbuf **tx_pkts,
+ uint16_t nb_pkts)
+{
+ int i, start, bds_to_use;
+ struct enetc_tx_bd *txbd;
+ struct enetc_bdr *tx_ring = (struct enetc_bdr *)tx_queue;
+ unsigned int j;
+ uint8_t *data;
+ struct rte_mbuf *seg;
+ uint16_t seg_len, segs_per_pkt;
+ bool is_first_seg;
+ int first_bd_idx, bd_count;
+
+ i = tx_ring->next_to_use;
+ bds_to_use = enetc_bd_unused(tx_ring);
+ bd_count = tx_ring->bd_count;
+ start = 0;
+
+ /*
+ * Remember the first BD index of this batch so we can flush the
+ * BD cache lines to PoC after all descriptors are written.
+ */
+ first_bd_idx = i;
+
+ while (start < nb_pkts) {
+ seg = tx_pkts[start];
+ segs_per_pkt = seg->nb_segs;
+
+ if (bds_to_use < segs_per_pkt)
+ break;
+
+ is_first_seg = true;
+ while (seg) {
+ tx_ring->q_swbd[i].buffer_addr = NULL;
+ seg_len = rte_pktmbuf_data_len(seg);
+ data = rte_pktmbuf_mtod(seg, void *);
+
+ /*
+ * Flush packet data cache lines to PoC so HW DMA
+ * reads the correct payload from memory.
+ */
+ for (j = 0; j < seg_len; j += RTE_CACHE_LINE_SIZE)
+ dcbf(data + j);
+
+ /*
+ * Cover the last byte of an unaligned buffer to
+ * ensure the full payload is clean to the Point of
+ * Coherency.
+ */
+ dcbf(data + (seg_len - 1));
+ txbd = ENETC_TXBD(*tx_ring, i);
+ txbd->flags = 0;
+ if (is_first_seg) {
+ tx_ring->q_swbd[i].buffer_addr = seg;
+ txbd->frm_len = rte_pktmbuf_pkt_len(seg);
+ if (seg->ol_flags & ENETC4_TX_CKSUM_OFFLOAD_MASK)
+ enetc4_tx_offload_checksum(seg, txbd);
+ is_first_seg = false;
+ }
+
+ txbd->buf_len = rte_cpu_to_le_16(seg_len);
+ txbd->addr = rte_cpu_to_le_64(rte_mbuf_data_iova(seg));
+ seg = seg->next;
+ i++;
+ bds_to_use--;
+
+ if (unlikely(i == bd_count))
+ i = 0;
+ }
+
+ /*
+ * Set the frame-last flag on the final BD of this packet.
+ * This is the last write to the BD group; the cache flush
+ * below will push all BDs to memory afterwards.
+ */
+ txbd->flags |= rte_cpu_to_le_16(ENETC4_TXBD_FLAGS_F);
+ start++;
+ }
+
+ /*
+ * Flush TX BDs to PoC so HW (non-cache-coherent i.MX95) can read
+ * the descriptors from memory. TX BDs are 16 B each; 4 BDs share
+ * one 64-byte cache line. Walk from the cache-line-aligned start
+ * of first_bd_idx to just past the last written BD, one dcbf per
+ * cache line.
+ *
+ * The flush must happen AFTER all BD fields (including flags_F) are
+ * written, so HW never sees a partial descriptor.
+ */
+ if (likely(start > 0)) {
+ int n = first_bd_idx & ~ENETC_BD_PER_CL_MASK;
+ int written = (i - n + bd_count) % bd_count;
+
+ if (written == 0)
+ written = bd_count;
+ written = (written + ENETC_BD_PER_CL_MASK) & ~ENETC_BD_PER_CL_MASK;
+
+ while (written > 0) {
+ dcbf((void *)ENETC_TXBD(*tx_ring, n));
+ n = (n + ENETC_BD_PER_CL) % bd_count;
+ written -= ENETC_BD_PER_CL;
+ }
+ }
+
+ enetc_clean_tx_ring(tx_ring);
+ tx_ring->next_to_use = i;
+ enetc_wr_reg(tx_ring->tcir, i);
+
+ return start;
+}
+
+/* --- Cacheable BD ring RX path with SW cache maintenance (dccivac) --- */
+
+static int
+enetc_clean_rx_ring_cacheable(struct enetc_bdr *rx_ring,
+ struct rte_mbuf **rx_pkts,
+ int work_limit)
+{
+ int rx_frm_cnt = 0;
+ int cleaned_cnt, i;
+ struct enetc_swbd *rx_swbd;
+ union enetc_rx_bd *rxbd, rxbd_temp;
+ struct rte_mbuf *first_seg = NULL, *cur_seg = NULL;
+ uint32_t bd_status;
+ uint8_t *data;
+ uint32_t j;
+ struct rte_mbuf *seg;
+ uint16_t data_len;
+
+ i = rx_ring->next_to_clean;
+ rxbd = ENETC_RXBD(*rx_ring, i);
+ cleaned_cnt = enetc_bd_unused(rx_ring);
+ rx_swbd = &rx_ring->q_swbd[i];
+
+ /*
+ * On i.MX95 the BD ring is in cacheable hugepage memory but the
+ * platform is non-cache-coherent. HW writes RX BDs to DDR
+ * without snooping the CPU cache, so stale cached copies of BD
+ * status fields must be discarded before the CPU reads them.
+ *
+ * Ideal instruction: DC IVAC (invalidate only, no writeback).
+ * ARM64 constraint: DC IVAC requires EL1 privilege; executing it
+ * from EL0 (DPDK userspace) raises a fault. The only EL0-safe
+ * cache maintenance instruction that invalidates is DC CIVAC
+ * (clean + invalidate, dccivac).
+ *
+ * Safety of using dccivac here:
+ * enetc_refill_rx_ring() issues dcbf() on every BD group before
+ * returning ownership to HW. After dcbf the CPU cache lines are
+ * marked clean (no dirty data). When dccivac runs, the "clean"
+ * phase finds nothing dirty to write back, so it behaves as a
+ * pure invalidate - exactly what we need.
+ *
+ * Granularity: BD = 16 B, cache line = 64 B, so one dccivac
+ * covers exactly 4 BDs. Invalidate at each 4-BD boundary.
+ */
+ dccivac((void *)ENETC_RXBD(*rx_ring,
+ (i & ~(int)ENETC_BD_PER_CL_MASK)));
+
+ while (likely(rx_frm_cnt < work_limit)) {
+#ifdef RTE_ARCH_32
+ rte_memcpy(&rxbd_temp, rxbd, 16);
+#else
+ __uint128_t *dst128 = (__uint128_t *)&rxbd_temp;
+ const __uint128_t *src128 = (const __uint128_t *)rxbd;
+ *dst128 = *src128;
+#endif
+ bd_status = rte_le_to_cpu_32(rxbd_temp.r.lstatus);
+
+ if (!(bd_status & ENETC_RXBD_LSTATUS_R))
+ break;
+ if (rxbd_temp.r.error)
+ rx_ring->ierrors++;
+
+ seg = rx_swbd->buffer_addr;
+ data_len = rte_le_to_cpu_16(rxbd_temp.r.buf_len);
+ seg->data_len = data_len;
+ if (!first_seg) {
+ first_seg = seg;
+ cur_seg = seg;
+ first_seg->pkt_len = data_len;
+ enetc_dev_rx_parse(first_seg,
+ rxbd_temp.r.parse_summary);
+ first_seg->hash.rss = rxbd_temp.r.rss_hash;
+ } else {
+ first_seg->pkt_len += data_len;
+ first_seg->nb_segs++;
+ cur_seg->next = seg;
+ cur_seg = seg;
+ }
+
+ /*
+ * Invalidate packet data cache lines so the CPU reads the
+ * payload that HW DMA'd into memory, not stale cached bytes.
+ */
+ data = rte_pktmbuf_mtod(seg, void *);
+ for (j = 0; j < data_len; j += RTE_CACHE_LINE_SIZE)
+ dccivac(data + j);
+ /* Cover the last byte of an unaligned buffer. */
+ dccivac(data + (data_len - 1));
+
+ if (bd_status & ENETC_RXBD_LSTATUS_F) {
+ seg->next = NULL;
+ first_seg->pkt_len -= rx_ring->crc_len;
+ rx_pkts[rx_frm_cnt] = first_seg;
+ rx_frm_cnt++;
+ first_seg = NULL;
+ }
+
+ cleaned_cnt++;
+ rx_swbd++;
+ i++;
+ if (unlikely(i == rx_ring->bd_count)) {
+ i = 0;
+ rx_swbd = &rx_ring->q_swbd[i];
+ }
+ rxbd = ENETC_RXBD(*rx_ring, i);
+
+ /*
+ * Crossed a 4-BD (cache-line) boundary: invalidate the new
+ * group so the next four status reads fetch fresh DDR data
+ * written by HW.
+ */
+ if ((i & ENETC_BD_PER_CL_MASK) == 0 &&
+ likely(rx_frm_cnt < work_limit))
+ dccivac((void *)rxbd);
+ }
+
+ rx_ring->next_to_clean = i;
+ enetc_refill_rx_ring(rx_ring, ENETC_BD_ALIGN_DOWN(cleaned_cnt));
+
+ return rx_frm_cnt;
+}
+
+uint16_t
+enetc_recv_pkts_cacheable(void *rxq, struct rte_mbuf **rx_pkts,
+ uint16_t nb_pkts)
+{
+ struct enetc_bdr *rx_ring = (struct enetc_bdr *)rxq;
+
+ return enetc_clean_rx_ring_cacheable(rx_ring, rx_pkts, nb_pkts);
+}
--
2.25.1
^ permalink raw reply related
* [PATCH 09/10] net/enetc: set user configurable priority to TX rings
From: Gagandeep Singh @ 2026-06-19 18:44 UTC (permalink / raw)
To: dev; +Cc: hemant.agrawal, Vanshika Shukla
In-Reply-To: <20260619184427.522518-1-g.singh@nxp.com>
From: Vanshika Shukla <vanshika.shukla@nxp.com>
Add devarg 'enetc4_txq_prior' to allow per-queue TX ring priority
configuration. The value is a '|'-separated list of TBMR priority
bits, one per TX queue (e.g. 'enetc4_txq_prior=1|2|3').
Store the parsed priorities in hw->txq_prior and apply them in
enetc4_tx_queue_setup() when enabling the ring.
Signed-off-by: Vanshika Shukla <vanshika.shukla@nxp.com>
---
drivers/net/enetc/enetc.h | 1 +
drivers/net/enetc/enetc4_ethdev.c | 71 ++++++++++++++++++++++++++++++-
2 files changed, 71 insertions(+), 1 deletion(-)
diff --git a/drivers/net/enetc/enetc.h b/drivers/net/enetc/enetc.h
index 2cdb3c7..99b1e91 100644
--- a/drivers/net/enetc/enetc.h
+++ b/drivers/net/enetc/enetc.h
@@ -111,6 +111,7 @@ struct enetc_eth_hw {
uint32_t max_tx_queues;
uint32_t vsi_timeout; /* VSI-PSI message wait timeout (iterations) */
uint32_t vsi_delay; /* VSI-PSI message wait delay (us) */
+ uint32_t *txq_prior; /* per-queue TX priority (TBMR priority bits) */
};
/*
diff --git a/drivers/net/enetc/enetc4_ethdev.c b/drivers/net/enetc/enetc4_ethdev.c
index 154fc09..d54051f 100644
--- a/drivers/net/enetc/enetc4_ethdev.c
+++ b/drivers/net/enetc/enetc4_ethdev.c
@@ -3,6 +3,7 @@
*/
#include <stdbool.h>
+#include <rte_kvargs.h>
#include <rte_random.h>
#include <dpaax_iova_table.h>
@@ -10,6 +11,65 @@
#include "enetc_logs.h"
#include "enetc.h"
+#define ENETC4_TXQ_PRIORITIES "enetc4_txq_prior"
+
+static int
+parse_txq_prior(const char *key __rte_unused, const char *value, void *opaque)
+{
+ struct rte_eth_dev *dev = (struct rte_eth_dev *)opaque;
+ struct enetc_eth_hw *hw =
+ ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ char *input_str = strdup(value);
+ char *str;
+ uint32_t i = 0;
+
+ hw->txq_prior = rte_zmalloc(NULL,
+ hw->max_tx_queues * sizeof(uint32_t), 0);
+ if (!hw->txq_prior) {
+ free(input_str);
+ return -1;
+ }
+
+ str = strtok(input_str, "|");
+ while (str != NULL && i < hw->max_tx_queues) {
+ hw->txq_prior[i++] = (uint32_t)atoi(str);
+ str = strtok(NULL, "|");
+ }
+
+ free(input_str);
+ return 0;
+}
+
+static int
+enetc4_get_devargs(struct rte_eth_dev *dev, const char *key)
+{
+ struct rte_devargs *devargs = dev->device->devargs;
+ struct rte_kvargs *kvlist;
+
+ if (!devargs)
+ return 0;
+
+ kvlist = rte_kvargs_parse(devargs->args, NULL);
+ if (!kvlist)
+ return 0;
+
+ if (!rte_kvargs_count(kvlist, key)) {
+ rte_kvargs_free(kvlist);
+ return 0;
+ }
+
+ if (!strcmp(key, ENETC4_TXQ_PRIORITIES)) {
+ if (rte_kvargs_process(kvlist, key,
+ parse_txq_prior, (void *)dev) < 0) {
+ rte_kvargs_free(kvlist);
+ return 0;
+ }
+ }
+
+ rte_kvargs_free(kvlist);
+ return 0;
+}
+
/* Supported Rx offloads */
static uint64_t dev_rx_offloads_sup =
RTE_ETH_RX_OFFLOAD_IPV4_CKSUM |
@@ -310,9 +370,14 @@ enetc4_tx_queue_setup(struct rte_eth_dev *dev,
data->tx_queues[queue_idx] = tx_ring;
tx_ring->tx_deferred_start = tx_conf->tx_deferred_start;
if (!tx_conf->tx_deferred_start) {
+ uint32_t tx_en = ENETC_TBMR_EN;
+
+ /* apply TX queue priority if configured */
+ if (priv->hw.txq_prior)
+ tx_en |= priv->hw.txq_prior[tx_ring->index];
/* enable ring */
enetc4_txbdr_wr(&priv->hw.hw, tx_ring->index,
- ENETC_TBMR, ENETC_TBMR_EN);
+ ENETC_TBMR, tx_en);
dev->data->tx_queue_state[tx_ring->index] =
RTE_ETH_QUEUE_STATE_STARTED;
} else {
@@ -1009,6 +1074,8 @@ enetc4_dev_init(struct rte_eth_dev *eth_dev)
hw->max_tx_queues = si_cap & ENETC_SICAPR0_BDR_MASK;
hw->max_rx_queues = (si_cap >> 16) & ENETC_SICAPR0_BDR_MASK;
+ enetc4_get_devargs(eth_dev, ENETC4_TXQ_PRIORITIES);
+
ENETC_PMD_DEBUG("Max RX queues = %d Max TX queues = %d",
hw->max_rx_queues, hw->max_tx_queues);
error = enetc4_mac_init(hw, eth_dev);
@@ -1065,4 +1132,6 @@ static struct rte_pci_driver rte_enetc4_pmd = {
RTE_PMD_REGISTER_PCI(net_enetc4, rte_enetc4_pmd);
RTE_PMD_REGISTER_PCI_TABLE(net_enetc4, pci_id_enetc4_map);
RTE_PMD_REGISTER_KMOD_DEP(net_enetc4, "* vfio-pci");
+RTE_PMD_REGISTER_PARAM_STRING(net_enetc4,
+ ENETC4_TXQ_PRIORITIES "=<string>");
RTE_LOG_REGISTER_DEFAULT(enetc4_logtype_pmd, NOTICE);
--
2.25.1
^ permalink raw reply related
* [PATCH 08/10] net/enetc: add devargs to control VSI-PSI timeout and delay
From: Gagandeep Singh @ 2026-06-19 18:44 UTC (permalink / raw)
To: dev; +Cc: hemant.agrawal
In-Reply-To: <20260619184427.522518-1-g.singh@nxp.com>
Add two new devargs for ENETC4 VF:
- enetc4_vsi_timeout: VSI-PSI message wait timeout (iteration count)
- enetc4_vsi_delay: VSI-PSI message wait delay in microseconds
Store the values in struct enetc_eth_hw and use them in
enetc4_msg_vsi_send() instead of the hardcoded defaults.
Fall back to ENETC4_DEF_VSI_WAIT_TIMEOUT_UPDATE /
ENETC4_DEF_VSI_WAIT_DELAY_UPDATE when not set.
Signed-off-by: Gagandeep Singh <g.singh@nxp.com>
---
drivers/net/enetc/enetc.h | 2 ++
drivers/net/enetc/enetc4_vf.c | 54 ++++++++++++++++++++++++-----------
2 files changed, 39 insertions(+), 17 deletions(-)
diff --git a/drivers/net/enetc/enetc.h b/drivers/net/enetc/enetc.h
index 439d2d6..2cdb3c7 100644
--- a/drivers/net/enetc/enetc.h
+++ b/drivers/net/enetc/enetc.h
@@ -109,6 +109,8 @@ struct enetc_eth_hw {
uint32_t num_rss;
uint32_t max_rx_queues;
uint32_t max_tx_queues;
+ uint32_t vsi_timeout; /* VSI-PSI message wait timeout (iterations) */
+ uint32_t vsi_delay; /* VSI-PSI message wait delay (us) */
};
/*
diff --git a/drivers/net/enetc/enetc4_vf.c b/drivers/net/enetc/enetc4_vf.c
index 44c0dc0..79a08b3 100644
--- a/drivers/net/enetc/enetc4_vf.c
+++ b/drivers/net/enetc/enetc4_vf.c
@@ -10,6 +10,8 @@
#include "enetc.h"
#define ENETC4_VSI_DISABLE "enetc4_vsi_disable"
+#define ENETC4_VSI_TIMEOUT "enetc4_vsi_timeout"
+#define ENETC4_VSI_DELAY "enetc4_vsi_delay"
#define ENETC_CRC_TABLE_SIZE 256
#define ENETC_POLY 0x1021
@@ -262,10 +264,13 @@ enetc4_process_psi_msg(struct rte_eth_dev *eth_dev, struct enetc_hw *enetc_hw)
}
static int
-enetc4_msg_vsi_send(struct enetc_hw *enetc_hw, struct enetc_msg_swbd *msg)
+enetc4_msg_vsi_send(struct enetc_eth_hw *hw, struct enetc_msg_swbd *msg)
{
- int timeout = ENETC4_DEF_VSI_WAIT_TIMEOUT_UPDATE;
- int delay_us = ENETC4_DEF_VSI_WAIT_DELAY_UPDATE;
+ struct enetc_hw *enetc_hw = &hw->hw;
+ int timeout = hw->vsi_timeout ? (int)hw->vsi_timeout :
+ ENETC4_DEF_VSI_WAIT_TIMEOUT_UPDATE;
+ int delay_us = hw->vsi_delay ? (int)hw->vsi_delay :
+ ENETC4_DEF_VSI_WAIT_DELAY_UPDATE;
uint8_t class_id = 0;
int err = 0;
int vsimsgsr;
@@ -382,7 +387,7 @@ enetc4_vf_set_mac_addr(struct rte_eth_dev *dev, struct rte_ether_addr *addr)
ENETC_CMD_ID_SET_PRIMARY_MAC, 0, 0, 0);
/* send the command and wait */
- err = enetc4_msg_vsi_send(enetc_hw, msg);
+ err = enetc4_msg_vsi_send(hw, msg);
if (err) {
ENETC_PMD_ERR("VSI message send error");
goto end;
@@ -426,7 +431,6 @@ static int
enetc4_vf_promisc_send_message(struct rte_eth_dev *dev, bool promisc_en)
{
struct enetc_eth_hw *hw = ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
- struct enetc_hw *enetc_hw = &hw->hw;
struct enetc_msg_cmd_set_promisc *cmd;
struct enetc_msg_swbd *msg;
uint32_t msg_size;
@@ -466,7 +470,7 @@ enetc4_vf_promisc_send_message(struct rte_eth_dev *dev, bool promisc_en)
ENETC_CMD_ID_SET_MAC_PROMISCUOUS, 0, 0, 0);
/* send the command and wait */
- err = enetc4_msg_vsi_send(enetc_hw, msg);
+ err = enetc4_msg_vsi_send(hw, msg);
if (err) {
ENETC_PMD_ERR("VSI message send error");
goto end;
@@ -483,7 +487,6 @@ static int
enetc4_vf_allmulti_send_message(struct rte_eth_dev *dev, bool mc_promisc)
{
struct enetc_eth_hw *hw = ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
- struct enetc_hw *enetc_hw = &hw->hw;
struct enetc_msg_cmd_set_promisc *cmd;
struct enetc_msg_swbd *msg;
uint32_t msg_size;
@@ -524,7 +527,7 @@ enetc4_vf_allmulti_send_message(struct rte_eth_dev *dev, bool mc_promisc)
ENETC_CMD_ID_SET_MAC_PROMISCUOUS, 0, 0, 0);
/* send the command and wait */
- err = enetc4_msg_vsi_send(enetc_hw, msg);
+ err = enetc4_msg_vsi_send(hw, msg);
if (err) {
ENETC_PMD_ERR("VSI message send error");
goto end;
@@ -630,7 +633,7 @@ enetc4_vf_get_link_status(struct rte_eth_dev *dev, struct enetc_psi_reply_msg *r
ENETC_CMD_ID_GET_LINK_STATUS, 0, 0, 0);
/* send the command and wait */
- err = enetc4_msg_vsi_send(enetc_hw, msg);
+ err = enetc4_msg_vsi_send(hw, msg);
if (err) {
ENETC_PMD_ERR("VSI message send error");
goto end;
@@ -676,7 +679,7 @@ enetc4_vf_get_link_speed(struct rte_eth_dev *dev, struct enetc_psi_reply_msg *re
ENETC_CMD_ID_GET_LINK_SPEED, 0, 0, 0);
/* send the command and wait */
- err = enetc4_msg_vsi_send(enetc_hw, msg);
+ err = enetc4_msg_vsi_send(hw, msg);
if (err) {
ENETC_PMD_ERR("VSI message send error");
goto end;
@@ -819,7 +822,6 @@ static int
enetc4_vf_vlan_promisc(struct rte_eth_dev *dev, bool promisc_en)
{
struct enetc_eth_hw *hw = ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
- struct enetc_hw *enetc_hw = &hw->hw;
struct enetc_msg_cmd_set_vlan_promisc *cmd;
struct enetc_msg_swbd *msg;
uint32_t msg_size;
@@ -858,7 +860,7 @@ enetc4_vf_vlan_promisc(struct rte_eth_dev *dev, bool promisc_en)
ENETC_CMD_ID_SET_VLAN_PROMISCUOUS, 0, 0, 0);
/* send the command and wait */
- err = enetc4_msg_vsi_send(enetc_hw, msg);
+ err = enetc4_msg_vsi_send(hw, msg);
if (err) {
ENETC_PMD_ERR("VSI message send error");
goto end;
@@ -921,7 +923,7 @@ enetc4_vf_mac_addr_add(struct rte_eth_dev *dev, struct rte_ether_addr *addr,
ENETC_MSG_ADD_EXACT_MAC_ENTRIES, 0, 0, 0);
/* send the command and wait */
- err = enetc4_msg_vsi_send(enetc_hw, msg);
+ err = enetc4_msg_vsi_send(hw, msg);
if (err) {
ENETC_PMD_ERR("VSI message send error");
goto end;
@@ -1021,7 +1023,7 @@ static int enetc4_vf_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id,
}
/* send the command and wait */
- err = enetc4_msg_vsi_send(enetc_hw, msg);
+ err = enetc4_msg_vsi_send(hw, msg);
if (err) {
ENETC_PMD_ERR("VSI message send error");
goto end;
@@ -1104,7 +1106,6 @@ static int
enetc4_vf_link_register_notif(struct rte_eth_dev *dev, bool enable)
{
struct enetc_eth_hw *hw = ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
- struct enetc_hw *enetc_hw = &hw->hw;
struct enetc_msg_swbd *msg;
struct rte_eth_link link;
uint32_t msg_size;
@@ -1138,7 +1139,7 @@ enetc4_vf_link_register_notif(struct rte_eth_dev *dev, bool enable)
cmd, 0, 0, 0);
/* send the command and wait */
- err = enetc4_msg_vsi_send(enetc_hw, msg);
+ err = enetc4_msg_vsi_send(hw, msg);
if (err)
ENETC_PMD_ERR("VSI msg error for link status notification");
@@ -1322,12 +1323,29 @@ enetc4_vf_dev_init(struct rte_eth_dev *eth_dev)
kvlist = rte_kvargs_parse(eth_dev->device->devargs->args,
NULL);
if (kvlist) {
+ const char *val;
+
if (rte_kvargs_count(kvlist, ENETC4_VSI_DISABLE) != 0) {
ENETC_PMD_NOTICE("VSI messaging disabled by devarg");
eth_dev->dev_ops = &enetc4_vf_ops_no_vsi_m;
} else {
eth_dev->dev_ops = &enetc4_vf_ops;
}
+
+ /* parse optional VSI-PSI timeout devarg */
+ val = rte_kvargs_get(kvlist, ENETC4_VSI_TIMEOUT);
+ if (val) {
+ hw->vsi_timeout = (uint32_t)strtoul(val, NULL, 0);
+ ENETC_PMD_NOTICE("VSI timeout set to %u", hw->vsi_timeout);
+ }
+
+ /* parse optional VSI-PSI delay devarg */
+ val = rte_kvargs_get(kvlist, ENETC4_VSI_DELAY);
+ if (val) {
+ hw->vsi_delay = (uint32_t)strtoul(val, NULL, 0);
+ ENETC_PMD_NOTICE("VSI delay set to %u us", hw->vsi_delay);
+ }
+
rte_kvargs_free(kvlist);
} else {
eth_dev->dev_ops = &enetc4_vf_ops;
@@ -1443,5 +1461,7 @@ RTE_PMD_REGISTER_PCI(net_enetc4_vf, rte_enetc4_vf_pmd);
RTE_PMD_REGISTER_PCI_TABLE(net_enetc4_vf, pci_vf_id_enetc4_map);
RTE_PMD_REGISTER_KMOD_DEP(net_enetc4_vf, "* igb_uio | uio_pci_generic");
RTE_PMD_REGISTER_PARAM_STRING(net_enetc4_vf,
- ENETC4_VSI_DISABLE "=<any>");
+ ENETC4_VSI_DISABLE "=<any> "
+ ENETC4_VSI_TIMEOUT "=<uint> "
+ ENETC4_VSI_DELAY "=<uint>");
RTE_LOG_REGISTER_DEFAULT(enetc4_vf_logtype_pmd, NOTICE);
--
2.25.1
^ permalink raw reply related
* [PATCH 06/10] net/enetc: support scatter-gather
From: Gagandeep Singh @ 2026-06-19 18:44 UTC (permalink / raw)
To: dev; +Cc: hemant.agrawal, Vanshika Shukla
In-Reply-To: <20260619184427.522518-1-g.singh@nxp.com>
From: Vanshika Shukla <vanshika.shukla@nxp.com>
Add scatter-gather support for ENETC4 PMD:
- Add ENETC_RXBD_LSTATUS_R/F bits for RX BD status
- Add ENETC4_MAX_SEGS (63) for max segments per TX packet
- Update enetc4_vf_dev_infos_get to fill nb_seg_max, offloads,
max queues and packet length
- Extend enetc_xmit_pkts_nc to handle multi-segment mbufs
- Extend enetc_clean_rx_ring_nc to chain scatter-gather segments
using LSTATUS_R/F bits
Signed-off-by: Vanshika Shukla <vanshika.shukla@nxp.com>
---
drivers/net/enetc/base/enetc_hw.h | 2 +
drivers/net/enetc/enetc.h | 4 +-
drivers/net/enetc/enetc4_vf.c | 46 ++++++++---
drivers/net/enetc/enetc_rxtx.c | 124 +++++++++++++++++++-----------
4 files changed, 119 insertions(+), 57 deletions(-)
diff --git a/drivers/net/enetc/base/enetc_hw.h b/drivers/net/enetc/base/enetc_hw.h
index f79c950..6e96562 100644
--- a/drivers/net/enetc/base/enetc_hw.h
+++ b/drivers/net/enetc/base/enetc_hw.h
@@ -230,6 +230,8 @@ enum enetc_bdr_type {TX, RX};
(0x0005 | ENETC_PKT_TYPE_IPV4)
#define ENETC_PKT_TYPE_IPV6_ESP \
(0x0005 | ENETC_PKT_TYPE_IPV6)
+#define ENETC_RXBD_LSTATUS_R BIT(30)
+#define ENETC_RXBD_LSTATUS_F BIT(31)
/* PCI device info */
struct enetc_hw {
diff --git a/drivers/net/enetc/enetc.h b/drivers/net/enetc/enetc.h
index 4d99b5b..439d2d6 100644
--- a/drivers/net/enetc/enetc.h
+++ b/drivers/net/enetc/enetc.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright 2018-2019,2024 NXP
+ * Copyright 2018-2019,2024-2026 NXP
*/
#ifndef _ENETC_H_
@@ -28,6 +28,8 @@
#define MIN_BD_COUNT 32
/* BD ALIGN */
#define BD_ALIGN 8
+/* Max segments per ENETC4 TX packet (scatter-gather) */
+#define ENETC4_MAX_SEGS 63
/* minimum frame size supported */
#define ENETC_MAC_MINFRM_SIZE 68
diff --git a/drivers/net/enetc/enetc4_vf.c b/drivers/net/enetc/enetc4_vf.c
index bec7128..9dc4e1d 100644
--- a/drivers/net/enetc/enetc4_vf.c
+++ b/drivers/net/enetc/enetc4_vf.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright 2024 NXP
+ * Copyright 2024-2026 NXP
*/
#include <stdbool.h>
@@ -18,8 +18,19 @@ uint16_t enetc_crc_table[ENETC_CRC_TABLE_SIZE];
bool enetc_crc_gen;
/* Supported Rx offloads */
-static uint64_t dev_vf_rx_offloads_sup =
- RTE_ETH_RX_OFFLOAD_VLAN_FILTER;
+static uint64_t dev_rx_offloads_sup =
+ RTE_ETH_RX_OFFLOAD_IPV4_CKSUM |
+ RTE_ETH_RX_OFFLOAD_UDP_CKSUM |
+ RTE_ETH_RX_OFFLOAD_TCP_CKSUM |
+ RTE_ETH_RX_OFFLOAD_VLAN_FILTER |
+ RTE_ETH_RX_OFFLOAD_SCATTER;
+
+/* Supported Tx offloads */
+static uint64_t dev_tx_offloads_sup =
+ RTE_ETH_TX_OFFLOAD_IPV4_CKSUM |
+ RTE_ETH_TX_OFFLOAD_UDP_CKSUM |
+ RTE_ETH_TX_OFFLOAD_TCP_CKSUM |
+ RTE_ETH_TX_OFFLOAD_MULTI_SEGS;
static void
enetc_gen_crc_table(void)
@@ -61,21 +72,38 @@ static int
enetc4_vf_dev_infos_get(struct rte_eth_dev *dev,
struct rte_eth_dev_info *dev_info)
{
- int ret = 0;
+ struct enetc_eth_hw *hw =
+ ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
PMD_INIT_FUNC_TRACE();
- ret = enetc4_dev_infos_get(dev, dev_info);
- if (ret)
- return ret;
-
+ dev_info->rx_desc_lim = (struct rte_eth_desc_lim) {
+ .nb_max = MAX_BD_COUNT,
+ .nb_min = MIN_BD_COUNT,
+ .nb_align = BD_ALIGN,
+ .nb_seg_max = ENETC4_MAX_SEGS,
+ .nb_mtu_seg_max = ENETC4_MAX_SEGS,
+ };
+ dev_info->tx_desc_lim = (struct rte_eth_desc_lim) {
+ .nb_max = MAX_BD_COUNT,
+ .nb_min = MIN_BD_COUNT,
+ .nb_align = BD_ALIGN,
+ .nb_seg_max = ENETC4_MAX_SEGS,
+ .nb_mtu_seg_max = ENETC4_MAX_SEGS,
+ };
+ dev_info->max_rx_queues = hw->max_rx_queues;
+ dev_info->max_tx_queues = hw->max_tx_queues;
+ dev_info->max_rx_pktlen = ENETC4_MAC_MAXFRM_SIZE;
dev_info->max_mtu = dev_info->max_rx_pktlen - (RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN);
dev_info->max_mac_addrs = ENETC4_MAC_ENTRIES;
- dev_info->rx_offload_capa |= dev_vf_rx_offloads_sup;
+ dev_info->rx_offload_capa = dev_rx_offloads_sup;
+ dev_info->tx_offload_capa = dev_tx_offloads_sup;
+ dev_info->flow_type_rss_offloads = ENETC_RSS_OFFLOAD_ALL;
return 0;
}
+
int
enetc4_vf_dev_stop(struct rte_eth_dev *dev __rte_unused)
{
diff --git a/drivers/net/enetc/enetc_rxtx.c b/drivers/net/enetc/enetc_rxtx.c
index c87349f..a37c835 100644
--- a/drivers/net/enetc/enetc_rxtx.c
+++ b/drivers/net/enetc/enetc_rxtx.c
@@ -149,54 +149,64 @@ enetc_xmit_pkts_nc(void *tx_queue,
struct rte_mbuf **tx_pkts,
uint16_t nb_pkts)
{
- struct enetc_swbd *tx_swbd;
- int i, start, bds_to_use;
- struct enetc_tx_bd *txbd;
struct enetc_bdr *tx_ring = (struct enetc_bdr *)tx_queue;
- unsigned int buflen, j;
+ int i, start, bds_to_use, bd_count;
+ struct enetc_tx_bd *txbd;
+ struct rte_mbuf *seg;
+ uint16_t seg_len, segs_per_pkt;
+ bool is_first_seg;
+ unsigned int j;
uint8_t *data;
i = tx_ring->next_to_use;
-
bds_to_use = enetc_bd_unused(tx_ring);
- if (bds_to_use < nb_pkts)
- nb_pkts = bds_to_use;
-
+ bd_count = tx_ring->bd_count;
start = 0;
- while (nb_pkts--) {
- tx_ring->q_swbd[i].buffer_addr = tx_pkts[start];
- buflen = rte_pktmbuf_pkt_len(tx_ring->q_swbd[i].buffer_addr);
- data = rte_pktmbuf_mtod(tx_ring->q_swbd[i].buffer_addr, void *);
- for (j = 0; j <= buflen; j += RTE_CACHE_LINE_SIZE)
- dcbf(data + j);
+ while (start < nb_pkts) {
+ seg = tx_pkts[start];
+ segs_per_pkt = seg->nb_segs;
- txbd = ENETC_TXBD(*tx_ring, i);
- txbd->flags = 0;
- if (tx_ring->q_swbd[i].buffer_addr->ol_flags & ENETC4_TX_CKSUM_OFFLOAD_MASK)
- enetc4_tx_offload_checksum(tx_ring->q_swbd[i].buffer_addr, txbd);
+ if (bds_to_use < segs_per_pkt)
+ break;
- tx_swbd = &tx_ring->q_swbd[i];
- txbd->frm_len = buflen;
- txbd->buf_len = txbd->frm_len;
- txbd->addr = (uint64_t)(uintptr_t)
- rte_cpu_to_le_64((size_t)tx_swbd->buffer_addr->buf_iova +
- tx_swbd->buffer_addr->data_off);
+ is_first_seg = true;
+ while (seg) {
+ tx_ring->q_swbd[i].buffer_addr = NULL;
+ seg_len = rte_pktmbuf_data_len(seg);
+ data = rte_pktmbuf_mtod(seg, void *);
+
+ /* Flush payload to PoC so HW DMA reads the correct data. */
+ for (j = 0; j < seg_len; j += RTE_CACHE_LINE_SIZE)
+ dcbf(data + j);
+ /* Cover the last byte of an unaligned buffer. */
+ dcbf(data + (seg_len - 1));
+
+ txbd = ENETC_TXBD(*tx_ring, i);
+ txbd->flags = 0;
+ if (is_first_seg) {
+ tx_ring->q_swbd[i].buffer_addr = tx_pkts[start];
+ txbd->frm_len = rte_pktmbuf_pkt_len(seg);
+ if (seg->ol_flags & ENETC4_TX_CKSUM_OFFLOAD_MASK)
+ enetc4_tx_offload_checksum(seg, txbd);
+ is_first_seg = false;
+ }
+
+ txbd->buf_len = rte_cpu_to_le_16(seg_len);
+ txbd->addr = rte_cpu_to_le_64(rte_mbuf_data_iova(seg));
+ seg = seg->next;
+ i++;
+ bds_to_use--;
+ if (unlikely(i == bd_count))
+ i = 0;
+ }
+
+ /* Set the frame-last flag on the final BD of this packet. */
txbd->flags |= rte_cpu_to_le_16(ENETC4_TXBD_FLAGS_F);
- i++;
start++;
- if (unlikely(i == tx_ring->bd_count))
- i = 0;
}
- /* we're only cleaning up the Tx ring here, on the assumption that
- * software is slower than hardware and hardware completed sending
- * older frames out by now.
- * We're also cleaning up the ring before kicking off Tx for the new
- * batch to minimize chances of contention on the Tx ring
- */
enetc_clean_tx_ring(tx_ring);
-
tx_ring->next_to_use = i;
enetc_wr_reg(tx_ring->tcir, i);
return start;
@@ -501,38 +511,59 @@ enetc_clean_rx_ring_nc(struct enetc_bdr *rx_ring,
int cleaned_cnt, i;
struct enetc_swbd *rx_swbd;
union enetc_rx_bd *rxbd, rxbd_temp;
+ struct rte_mbuf *first_seg = NULL, *cur_seg = NULL;
uint32_t bd_status;
uint8_t *data;
uint32_t j;
+ struct rte_mbuf *seg;
+ uint16_t data_len;
/* next descriptor to process */
i = rx_ring->next_to_clean;
- /* next descriptor to process */
rxbd = ENETC_RXBD(*rx_ring, i);
-
cleaned_cnt = enetc_bd_unused(rx_ring);
rx_swbd = &rx_ring->q_swbd[i];
while (likely(rx_frm_cnt < work_limit)) {
rxbd_temp = *rxbd;
bd_status = rte_le_to_cpu_32(rxbd_temp.r.lstatus);
- if (!bd_status)
+ /* LSTATUS_R indicates this BD has been written by HW */
+ if (!(bd_status & ENETC_RXBD_LSTATUS_R))
break;
if (rxbd_temp.r.error)
rx_ring->ierrors++;
- rx_swbd->buffer_addr->pkt_len = rxbd_temp.r.buf_len -
- rx_ring->crc_len;
- rx_swbd->buffer_addr->data_len = rx_swbd->buffer_addr->pkt_len;
- rx_swbd->buffer_addr->hash.rss = rxbd_temp.r.rss_hash;
- enetc_dev_rx_parse(rx_swbd->buffer_addr,
- rxbd_temp.r.parse_summary);
+ seg = rx_swbd->buffer_addr;
+ data_len = rte_le_to_cpu_16(rxbd_temp.r.buf_len);
+ seg->data_len = data_len;
+
+ if (!first_seg) {
+ first_seg = seg;
+ cur_seg = seg;
+ first_seg->pkt_len = data_len;
+ enetc_dev_rx_parse(first_seg, rxbd_temp.r.parse_summary);
+ first_seg->hash.rss = rxbd_temp.r.rss_hash;
+ } else {
+ first_seg->pkt_len += data_len;
+ first_seg->nb_segs++;
+ cur_seg->next = seg;
+ cur_seg = seg;
+ }
- data = rte_pktmbuf_mtod(rx_swbd->buffer_addr, void *);
- for (j = 0; j <= rx_swbd->buffer_addr->pkt_len; j += RTE_CACHE_LINE_SIZE)
+ /* Invalidate packet data cache lines so CPU reads HW-written data. */
+ data = rte_pktmbuf_mtod(seg, void *);
+ for (j = 0; j < data_len; j += RTE_CACHE_LINE_SIZE)
dccivac(data + j);
+ dccivac(data + (data_len - 1));
+
+ if (bd_status & ENETC_RXBD_LSTATUS_F) {
+ seg->next = NULL;
+ first_seg->pkt_len -= rx_ring->crc_len;
+ rx_pkts[rx_frm_cnt] = first_seg;
+ rx_frm_cnt++;
+ first_seg = NULL;
+ }
- rx_pkts[rx_frm_cnt] = rx_swbd->buffer_addr;
cleaned_cnt++;
rx_swbd++;
i++;
@@ -541,7 +572,6 @@ enetc_clean_rx_ring_nc(struct enetc_bdr *rx_ring,
rx_swbd = &rx_ring->q_swbd[i];
}
rxbd = ENETC_RXBD(*rx_ring, i);
- rx_frm_cnt++;
}
rx_ring->next_to_clean = i;
--
2.25.1
^ permalink raw reply related
* [PATCH 07/10] net/enetc: add option to disable VSI messaging
From: Gagandeep Singh @ 2026-06-19 18:44 UTC (permalink / raw)
To: dev; +Cc: hemant.agrawal
In-Reply-To: <20260619184427.522518-1-g.singh@nxp.com>
Add devarg 'enetc4_vsi_disable' to allow disabling features
dependent on VSI-PSI messaging. This is useful for testing DPDK
with a PF driver that does not support VSI-PSI messages.
When the devarg is present, a reduced ops table
(enetc4_vf_ops_no_vsi_m) is used that replaces link_update with
a no-op stub and omits MAC/VLAN filter ops that require VSI msgs.
Signed-off-by: Gagandeep Singh <g.singh@nxp.com>
---
drivers/net/enetc/enetc4_vf.c | 61 +++++++++++++++++++++++++++++++++--
1 file changed, 58 insertions(+), 3 deletions(-)
diff --git a/drivers/net/enetc/enetc4_vf.c b/drivers/net/enetc/enetc4_vf.c
index 9dc4e1d..44c0dc0 100644
--- a/drivers/net/enetc/enetc4_vf.c
+++ b/drivers/net/enetc/enetc4_vf.c
@@ -3,11 +3,14 @@
*/
#include <stdbool.h>
+#include <rte_kvargs.h>
#include <rte_random.h>
#include <dpaax_iova_table.h>
#include "enetc_logs.h"
#include "enetc.h"
+#define ENETC4_VSI_DISABLE "enetc4_vsi_disable"
+
#define ENETC_CRC_TABLE_SIZE 256
#define ENETC_POLY 0x1021
#define ENETC_CRC_INIT 0xffff
@@ -687,6 +690,13 @@ enetc4_vf_get_link_speed(struct rte_eth_dev *dev, struct enetc_psi_reply_msg *re
return err;
}
+static int
+enetc4_vf_link_update_dummy(struct rte_eth_dev *dev __rte_unused,
+ int wait_to_complete __rte_unused)
+{
+ return 0;
+}
+
static int
enetc4_vf_link_update(struct rte_eth_dev *dev, int wait_to_complete __rte_unused)
{
@@ -1148,6 +1158,27 @@ static const struct rte_pci_id pci_vf_id_enetc4_map[] = {
};
/* Features supported by this driver */
+/* ops table used when VSI messaging is disabled */
+static const struct eth_dev_ops enetc4_vf_ops_no_vsi_m = {
+ .dev_configure = enetc4_dev_configure,
+ .dev_start = enetc4_vf_dev_start,
+ .dev_stop = enetc4_vf_dev_stop,
+ .dev_close = enetc4_dev_close,
+ .stats_get = enetc4_vf_stats_get,
+ .dev_infos_get = enetc4_vf_dev_infos_get,
+ .mtu_set = enetc4_vf_mtu_set,
+ .link_update = enetc4_vf_link_update_dummy,
+ .rx_queue_setup = enetc4_rx_queue_setup,
+ .rx_queue_start = enetc4_rx_queue_start,
+ .rx_queue_stop = enetc4_rx_queue_stop,
+ .rx_queue_release = enetc4_rx_queue_release,
+ .tx_queue_setup = enetc4_tx_queue_setup,
+ .tx_queue_start = enetc4_tx_queue_start,
+ .tx_queue_stop = enetc4_tx_queue_stop,
+ .tx_queue_release = enetc4_tx_queue_release,
+ .dev_supported_ptypes_get = enetc4_supported_ptypes_get,
+};
+
static const struct eth_dev_ops enetc4_vf_ops = {
.dev_configure = enetc4_dev_configure,
.dev_start = enetc4_vf_dev_start,
@@ -1283,7 +1314,28 @@ enetc4_vf_dev_init(struct rte_eth_dev *eth_dev)
struct enetc_hw *enetc_hw = &hw->hw;
PMD_INIT_FUNC_TRACE();
- eth_dev->dev_ops = &enetc4_vf_ops;
+
+ /* check if VSI messaging should be disabled via devarg */
+ if (eth_dev->device->devargs) {
+ struct rte_kvargs *kvlist;
+
+ kvlist = rte_kvargs_parse(eth_dev->device->devargs->args,
+ NULL);
+ if (kvlist) {
+ if (rte_kvargs_count(kvlist, ENETC4_VSI_DISABLE) != 0) {
+ ENETC_PMD_NOTICE("VSI messaging disabled by devarg");
+ eth_dev->dev_ops = &enetc4_vf_ops_no_vsi_m;
+ } else {
+ eth_dev->dev_ops = &enetc4_vf_ops;
+ }
+ rte_kvargs_free(kvlist);
+ } else {
+ eth_dev->dev_ops = &enetc4_vf_ops;
+ }
+ } else {
+ eth_dev->dev_ops = &enetc4_vf_ops;
+ }
+
enetc4_dev_hw_init(eth_dev);
si_cap = enetc_rd(enetc_hw, ENETC_SICAPR0);
@@ -1304,8 +1356,9 @@ enetc4_vf_dev_init(struct rte_eth_dev *eth_dev)
ENETC_PMD_DEBUG("port_id %d vendorID=0x%x deviceID=0x%x",
eth_dev->data->port_id, pci_dev->id.vendor_id,
pci_dev->id.device_id);
- /* update link */
- enetc4_vf_link_update(eth_dev, 0);
+ /* update link if VSI messaging is enabled */
+ if (eth_dev->dev_ops == &enetc4_vf_ops)
+ enetc4_vf_link_update(eth_dev, 0);
return 0;
}
@@ -1389,4 +1442,6 @@ static struct rte_pci_driver rte_enetc4_vf_pmd = {
RTE_PMD_REGISTER_PCI(net_enetc4_vf, rte_enetc4_vf_pmd);
RTE_PMD_REGISTER_PCI_TABLE(net_enetc4_vf, pci_vf_id_enetc4_map);
RTE_PMD_REGISTER_KMOD_DEP(net_enetc4_vf, "* igb_uio | uio_pci_generic");
+RTE_PMD_REGISTER_PARAM_STRING(net_enetc4_vf,
+ ENETC4_VSI_DISABLE "=<any>");
RTE_LOG_REGISTER_DEFAULT(enetc4_vf_logtype_pmd, NOTICE);
--
2.25.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox