* [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
* [PATCH 05/10] net/enetc: update random MAC generation code
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>
Use rte_eth_random_addr() instead of manual rte_rand() based MAC
generation. Also handle VF path by writing to ENETC_SIPMAR0/1 instead
of ENETC_PSIPMAR0/1 when running as a VF.
Signed-off-by: Gagandeep Singh <g.singh@nxp.com>
---
drivers/net/enetc/enetc_ethdev.c | 22 ++++++++++------------
1 file changed, 10 insertions(+), 12 deletions(-)
diff --git a/drivers/net/enetc/enetc_ethdev.c b/drivers/net/enetc/enetc_ethdev.c
index 407179f..427da87 100644
--- a/drivers/net/enetc/enetc_ethdev.c
+++ b/drivers/net/enetc/enetc_ethdev.c
@@ -196,20 +196,18 @@ enetc_hardware_init(struct enetc_eth_hw *hw)
}
if ((high_mac | low_mac) == 0) {
- char *first_byte;
-
ENETC_PMD_NOTICE("MAC is not available for this SI, "
"set random MAC");
- mac = (uint32_t *)hw->mac.addr;
- *mac = (uint32_t)rte_rand();
- first_byte = (char *)mac;
- *first_byte &= 0xfe; /* clear multicast bit */
- *first_byte |= 0x02; /* set local assignment bit (IEEE802) */
-
- enetc_port_wr(enetc_hw, ENETC_PSIPMAR0(0), *mac);
- mac++;
- *mac = (uint16_t)rte_rand();
- enetc_port_wr(enetc_hw, ENETC_PSIPMAR1(0), *mac);
+ rte_eth_random_addr(hw->mac.addr);
+ high_mac = *(uint32_t *)hw->mac.addr;
+ low_mac = *(uint16_t *)(hw->mac.addr + 4);
+ if (hw->device_id == ENETC_DEV_ID_VF) {
+ enetc_wr(enetc_hw, ENETC_SIPMAR0, high_mac);
+ enetc_wr(enetc_hw, ENETC_SIPMAR1, low_mac);
+ } else {
+ enetc_port_wr(enetc_hw, ENETC_PSIPMAR0(0), high_mac);
+ enetc_port_wr(enetc_hw, ENETC_PSIPMAR1(0), low_mac);
+ }
enetc_print_ethaddr("New address: ",
(const struct rte_ether_addr *)hw->mac.addr);
}
--
2.25.1
^ permalink raw reply related
* [PATCH 04/10] net/enetc: support ESP packet type in packet parsing
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 ESP (Encapsulating Security Payload) packet type definitions and
handling to the RX packet parsing path. Also update the supported
ptypes array to advertise ESP tunnel type support.
Signed-off-by: Gagandeep Singh <g.singh@nxp.com>
---
drivers/net/enetc/base/enetc_hw.h | 4 ++++
drivers/net/enetc/enetc_ethdev.c | 4 +++-
drivers/net/enetc/enetc_rxtx.c | 10 ++++++++++
3 files changed, 17 insertions(+), 1 deletion(-)
diff --git a/drivers/net/enetc/base/enetc_hw.h b/drivers/net/enetc/base/enetc_hw.h
index 19efadd..f79c950 100644
--- a/drivers/net/enetc/base/enetc_hw.h
+++ b/drivers/net/enetc/base/enetc_hw.h
@@ -226,6 +226,10 @@ enum enetc_bdr_type {TX, RX};
(0x0003 | ENETC_PKT_TYPE_IPV4)
#define ENETC_PKT_TYPE_IPV6_ICMP \
(0x0003 | ENETC_PKT_TYPE_IPV6)
+#define ENETC_PKT_TYPE_IPV4_ESP \
+ (0x0005 | ENETC_PKT_TYPE_IPV4)
+#define ENETC_PKT_TYPE_IPV6_ESP \
+ (0x0005 | ENETC_PKT_TYPE_IPV6)
/* PCI device info */
struct enetc_hw {
diff --git a/drivers/net/enetc/enetc_ethdev.c b/drivers/net/enetc/enetc_ethdev.c
index f41f3c1..407179f 100644
--- a/drivers/net/enetc/enetc_ethdev.c
+++ b/drivers/net/enetc/enetc_ethdev.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright 2018-2024 NXP
+ * Copyright 2018-2026 NXP
*/
#include <stdbool.h>
@@ -95,6 +95,8 @@ enetc_supported_ptypes_get(struct rte_eth_dev *dev __rte_unused,
RTE_PTYPE_L4_UDP,
RTE_PTYPE_L4_SCTP,
RTE_PTYPE_L4_ICMP,
+ RTE_PTYPE_TUNNEL_ESP,
+ RTE_PTYPE_UNKNOWN,
};
*no_of_elements = RTE_DIM(ptypes);
diff --git a/drivers/net/enetc/enetc_rxtx.c b/drivers/net/enetc/enetc_rxtx.c
index b44e6f3..c87349f 100644
--- a/drivers/net/enetc/enetc_rxtx.c
+++ b/drivers/net/enetc/enetc_rxtx.c
@@ -370,6 +370,16 @@ enetc_dev_rx_parse(struct rte_mbuf *m, uint16_t parse_results)
RTE_PTYPE_L3_IPV6 |
RTE_PTYPE_L4_UDP;
return;
+ case ENETC_PKT_TYPE_IPV4_ESP:
+ m->packet_type = RTE_PTYPE_L2_ETHER |
+ RTE_PTYPE_L3_IPV4 |
+ RTE_PTYPE_TUNNEL_ESP;
+ return;
+ case ENETC_PKT_TYPE_IPV6_ESP:
+ m->packet_type = RTE_PTYPE_L2_ETHER |
+ RTE_PTYPE_L3_IPV6 |
+ RTE_PTYPE_TUNNEL_ESP;
+ return;
case ENETC_PKT_TYPE_IPV4_SCTP:
m->packet_type = RTE_PTYPE_L2_ETHER |
RTE_PTYPE_L3_IPV4 |
--
2.25.1
^ permalink raw reply related
* [PATCH 03/10] net/enetc: fix queue initialization
From: Gagandeep Singh @ 2026-06-19 18:44 UTC (permalink / raw)
To: dev; +Cc: hemant.agrawal, stable
In-Reply-To: <20260619184427.522518-1-g.singh@nxp.com>
Hardware can misbehave if the user tries to reset the consumer and
producer indexes without resetting the ring.
This patch adds the ring reset step before resetting the indexes.
Fixes: 6c9c5aadc0e0 ("net/enetc: support ENETC4 queue API")
Cc: stable@dpdk.org
Signed-off-by: Gagandeep Singh <g.singh@nxp.com>
---
drivers/net/enetc/enetc4_ethdev.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/drivers/net/enetc/enetc4_ethdev.c b/drivers/net/enetc/enetc4_ethdev.c
index 78eba70..154fc09 100644
--- a/drivers/net/enetc/enetc4_ethdev.c
+++ b/drivers/net/enetc/enetc4_ethdev.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright 2024 NXP
+ * Copyright 2024-2026 NXP
*/
#include <stdbool.h>
@@ -279,6 +279,7 @@ enetc4_tx_queue_setup(struct rte_eth_dev *dev,
const struct rte_eth_txconf *tx_conf)
{
int err;
+ uint32_t tx_data;
struct enetc_bdr *tx_ring;
struct rte_eth_dev_data *data = dev->data;
struct enetc_eth_adapter *priv =
@@ -301,6 +302,10 @@ enetc4_tx_queue_setup(struct rte_eth_dev *dev,
goto fail;
tx_ring->ndev = dev;
+ /* reset queue */
+ tx_data = enetc4_txbdr_rd(&priv->hw.hw, tx_ring->index, ENETC_TBMR);
+ tx_data &= ~ENETC_TBMR_EN;
+ enetc4_txbdr_wr(&priv->hw.hw, tx_ring->index, ENETC_TBMR, tx_data);
enetc4_setup_txbdr(&priv->hw.hw, tx_ring);
data->tx_queues[queue_idx] = tx_ring;
tx_ring->tx_deferred_start = tx_conf->tx_deferred_start;
@@ -427,6 +432,7 @@ enetc4_rx_queue_setup(struct rte_eth_dev *dev,
struct rte_mempool *mb_pool)
{
int err = 0;
+ uint32_t rx_enable;
struct enetc_bdr *rx_ring;
struct rte_eth_dev_data *data = dev->data;
struct enetc_eth_adapter *adapter =
@@ -450,6 +456,10 @@ enetc4_rx_queue_setup(struct rte_eth_dev *dev,
goto fail;
rx_ring->ndev = dev;
+ /* reset queue */
+ rx_enable = enetc4_rxbdr_rd(&adapter->hw.hw, rx_ring->index, ENETC_RBMR);
+ rx_enable &= ~ENETC_RBMR_EN;
+ enetc4_rxbdr_wr(&adapter->hw.hw, rx_ring->index, ENETC_RBMR, rx_enable);
enetc4_setup_rxbdr(&adapter->hw.hw, rx_ring, mb_pool);
data->rx_queues[rx_queue_id] = rx_ring;
rx_ring->rx_deferred_start = rx_conf->rx_deferred_start;
--
2.25.1
^ permalink raw reply related
* [PATCH 02/10] net/enetc: fix TX BDs flag overwrite issue
From: Gagandeep Singh @ 2026-06-19 18:44 UTC (permalink / raw)
To: dev; +Cc: hemant.agrawal, stable
In-Reply-To: <20260619184427.522518-1-g.singh@nxp.com>
Zero the flags field before setting offload bits and set the
frame-last flag (F) after all descriptor fields are written.
This prevents stale flag bits from a previous packet corrupting
the current descriptor.
Fixes: 72f491f1e53c ("net/enetc: optimize ENETC4 data path")
Cc: stable@dpdk.org
Signed-off-by: Gagandeep Singh <g.singh@nxp.com>
---
drivers/net/enetc/enetc_rxtx.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/net/enetc/enetc_rxtx.c b/drivers/net/enetc/enetc_rxtx.c
index a2b8153..b44e6f3 100644
--- a/drivers/net/enetc/enetc_rxtx.c
+++ b/drivers/net/enetc/enetc_rxtx.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright 2018-2024 NXP
+ * Copyright 2018-2026 NXP
*/
#include <stdbool.h>
@@ -172,7 +172,7 @@ enetc_xmit_pkts_nc(void *tx_queue,
dcbf(data + j);
txbd = ENETC_TXBD(*tx_ring, i);
- txbd->flags = rte_cpu_to_le_16(ENETC4_TXBD_FLAGS_F);
+ 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);
@@ -182,6 +182,7 @@ enetc_xmit_pkts_nc(void *tx_queue,
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);
+ txbd->flags |= rte_cpu_to_le_16(ENETC4_TXBD_FLAGS_F);
i++;
start++;
if (unlikely(i == tx_ring->bd_count))
--
2.25.1
^ permalink raw reply related
* [PATCH 01/10] net/enetc: fix TX BD structure
From: Gagandeep Singh @ 2026-06-19 18:44 UTC (permalink / raw)
To: dev; +Cc: hemant.agrawal, stable
In-Reply-To: <20260619184427.522518-1-g.singh@nxp.com>
The flags field in struct enetc_tx_bd was declared as uint16_t but
ENETC4 TX BDs only use an 8-bit flags byte. Fix the type to uint8_t
to match the hardware descriptor layout.
Fixes: 696fa399d797 ("net/enetc: add PMD with basic operations")
Cc: stable@dpdk.org
Signed-off-by: Gagandeep Singh <g.singh@nxp.com>
---
drivers/net/enetc/base/enetc_hw.h | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/drivers/net/enetc/base/enetc_hw.h b/drivers/net/enetc/base/enetc_hw.h
index 173d677..19efadd 100644
--- a/drivers/net/enetc/base/enetc_hw.h
+++ b/drivers/net/enetc/base/enetc_hw.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright 2018-2024 NXP
+ * Copyright 2018-2026 NXP
*/
#ifndef _ENETC_HW_H_
@@ -198,8 +198,7 @@ enum enetc_bdr_type {TX, RX};
#define ENETC_TX_ADDR(txq, addr) ((void *)((txq)->enetc_txbdr + (addr)))
-#define ENETC_TXBD_FLAGS_IE BIT(13)
-#define ENETC_TXBD_FLAGS_F BIT(15)
+#define ENETC_TXBD_FLAGS_F BIT(7)
/* ENETC Parsed values (Little Endian) */
#define ENETC_PARSE_ERROR 0x8000
@@ -262,7 +261,7 @@ struct enetc_tx_bd {
uint8_t l3t:1;
uint8_t resv:5;
uint8_t l4t:3;
- uint16_t flags;
+ uint8_t flags;
};/* default layout */
uint32_t txstart;
uint32_t lstatus;
--
2.25.1
^ permalink raw reply related
* [PATCH 00/10] NXP ENETC driver related changes
From: Gagandeep Singh @ 2026-06-19 18:44 UTC (permalink / raw)
To: dev; +Cc: hemant.agrawal
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(-)
--
2.25.1
^ permalink raw reply
* Re: [PATCH v4 00/23] et/sxe2: added Linkdata sxe2 ethernet driver
From: Stephen Hemminger @ 2026-06-19 17:31 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.).
>
> V19:
> - remove software statistics devargs
>
> Jie Liu (23):
> net/sxe2: remove software statistics devargs
> net/sxe2: support AVX512 vectorized path for Rx and Tx
> net/sxe2: add AVX2 vector data path for Rx and Tx
> net/sxe2: add supported packet types get callback
> net/sxe2: add link update callback
> net/sxe2: support L2 filtering and MAC config
> drivers: support RSS feature
> net/sxe2: support TM hierarchy and shaping
> net/sxe2: support IPsec inline protocol offload
> net/sxe2: support statistics and multi-process
> drivers: interrupt handling
> net/sxe2: add NEON vec Rx/Tx burst functions
> drivers: add support for VF representors
> net/sxe2: add support for custom UDP tunnel ports
> net/sxe2: support firmware version reading
> net/sxe2: implement get monitor address
> common/sxe2: add shared SFP module definitions
> net/sxe2: support SFP module info and EEPROM access
> net/sxe2: implement private dump info
> net/sxe2: add mbuf validation in Tx debug mode
> common/sxe2: add callback for memory event handling
> net/sxe2: add private devargs parsing
> net/sxe2: update sxe2 feature matrix docs
>
> doc/guides/nics/features/sxe2.ini | 56 +
> doc/guides/nics/sxe2.rst | 164 ++
> drivers/common/sxe2/sxe2_common.c | 156 ++
> drivers/common/sxe2/sxe2_common.h | 4 +
> drivers/common/sxe2/sxe2_flow_public.h | 633 +++++++
> drivers/common/sxe2/sxe2_ioctl_chnl.c | 178 +-
> drivers/common/sxe2/sxe2_ioctl_chnl_func.h | 18 +
> drivers/common/sxe2/sxe2_msg.h | 118 ++
> drivers/net/sxe2/meson.build | 52 +
> drivers/net/sxe2/sxe2_cmd_chnl.c | 1587 +++++++++++++++-
> drivers/net/sxe2/sxe2_cmd_chnl.h | 139 ++
> drivers/net/sxe2/sxe2_drv_cmd.h | 523 +++++-
> drivers/net/sxe2/sxe2_dump.c | 302 +++
> drivers/net/sxe2/sxe2_dump.h | 12 +
> drivers/net/sxe2/sxe2_ethdev.c | 1513 ++++++++++++++-
> drivers/net/sxe2/sxe2_ethdev.h | 112 +-
> drivers/net/sxe2/sxe2_ethdev_repr.c | 609 ++++++
> drivers/net/sxe2/sxe2_ethdev_repr.h | 32 +
> drivers/net/sxe2/sxe2_filter.c | 895 +++++++++
> drivers/net/sxe2/sxe2_filter.h | 100 +
> drivers/net/sxe2/sxe2_flow.c | 1394 ++++++++++++++
> drivers/net/sxe2/sxe2_flow.h | 30 +
> drivers/net/sxe2/sxe2_flow_define.h | 144 ++
> drivers/net/sxe2/sxe2_flow_parse_action.c | 1182 ++++++++++++
> drivers/net/sxe2/sxe2_flow_parse_action.h | 23 +
> drivers/net/sxe2/sxe2_flow_parse_engine.c | 106 ++
> drivers/net/sxe2/sxe2_flow_parse_engine.h | 13 +
> drivers/net/sxe2/sxe2_flow_parse_pattern.c | 1935 +++++++++++++++++++
> drivers/net/sxe2/sxe2_flow_parse_pattern.h | 46 +
> drivers/net/sxe2/sxe2_ipsec.c | 1565 ++++++++++++++++
> drivers/net/sxe2/sxe2_ipsec.h | 254 +++
> drivers/net/sxe2/sxe2_irq.c | 1026 ++++++++++
> drivers/net/sxe2/sxe2_irq.h | 25 +
> drivers/net/sxe2/sxe2_mac.c | 530 ++++++
> drivers/net/sxe2/sxe2_mac.h | 84 +
> drivers/net/sxe2/sxe2_mp.c | 414 ++++
> drivers/net/sxe2/sxe2_mp.h | 67 +
> drivers/net/sxe2/sxe2_queue.c | 17 +-
> drivers/net/sxe2/sxe2_queue.h | 15 +-
> drivers/net/sxe2/sxe2_rss.c | 584 ++++++
> drivers/net/sxe2/sxe2_rss.h | 81 +
> drivers/net/sxe2/sxe2_rx.c | 93 +-
> drivers/net/sxe2/sxe2_rx.h | 2 +
> drivers/net/sxe2/sxe2_security.c | 335 ++++
> drivers/net/sxe2/sxe2_security.h | 77 +
> drivers/net/sxe2/sxe2_stats.c | 586 ++++++
> drivers/net/sxe2/sxe2_stats.h | 39 +
> drivers/net/sxe2/sxe2_switchdev.c | 332 ++++
> drivers/net/sxe2/sxe2_switchdev.h | 33 +
> drivers/net/sxe2/sxe2_tm.c | 1151 ++++++++++++
> drivers/net/sxe2/sxe2_tm.h | 76 +
> drivers/net/sxe2/sxe2_tx.c | 7 +
> drivers/net/sxe2/sxe2_txrx.c | 1968 +++++++++++++++++++-
> drivers/net/sxe2/sxe2_txrx.h | 8 +
> drivers/net/sxe2/sxe2_txrx_check_mbuf.c | 595 ++++++
> drivers/net/sxe2/sxe2_txrx_check_mbuf.h | 38 +
> drivers/net/sxe2/sxe2_txrx_poll.c | 281 ++-
> drivers/net/sxe2/sxe2_txrx_vec.c | 46 +-
> drivers/net/sxe2/sxe2_txrx_vec.h | 38 +-
> drivers/net/sxe2/sxe2_txrx_vec_avx2.c | 748 ++++++++
> drivers/net/sxe2/sxe2_txrx_vec_avx512.c | 868 +++++++++
> drivers/net/sxe2/sxe2_txrx_vec_common.h | 53 +-
> drivers/net/sxe2/sxe2_txrx_vec_neon.c | 691 +++++++
> drivers/net/sxe2/sxe2_txrx_vec_sse.c | 29 +-
> drivers/net/sxe2/sxe2_vsi.c | 146 ++
> drivers/net/sxe2/sxe2_vsi.h | 12 +-
> drivers/net/sxe2/sxe2vf_regs.h | 85 +
> 67 files changed, 24809 insertions(+), 266 deletions(-)
> create mode 100644 drivers/common/sxe2/sxe2_flow_public.h
> create mode 100644 drivers/common/sxe2/sxe2_msg.h
> create mode 100644 drivers/net/sxe2/sxe2_dump.c
> create mode 100644 drivers/net/sxe2/sxe2_dump.h
> create mode 100644 drivers/net/sxe2/sxe2_ethdev_repr.c
> create mode 100644 drivers/net/sxe2/sxe2_ethdev_repr.h
> create mode 100644 drivers/net/sxe2/sxe2_filter.c
> create mode 100644 drivers/net/sxe2/sxe2_filter.h
> create mode 100644 drivers/net/sxe2/sxe2_flow.c
> create mode 100644 drivers/net/sxe2/sxe2_flow.h
> create mode 100644 drivers/net/sxe2/sxe2_flow_define.h
> create mode 100644 drivers/net/sxe2/sxe2_flow_parse_action.c
> create mode 100644 drivers/net/sxe2/sxe2_flow_parse_action.h
> create mode 100644 drivers/net/sxe2/sxe2_flow_parse_engine.c
> create mode 100644 drivers/net/sxe2/sxe2_flow_parse_engine.h
> create mode 100644 drivers/net/sxe2/sxe2_flow_parse_pattern.c
> create mode 100644 drivers/net/sxe2/sxe2_flow_parse_pattern.h
> create mode 100644 drivers/net/sxe2/sxe2_ipsec.c
> create mode 100644 drivers/net/sxe2/sxe2_ipsec.h
> create mode 100644 drivers/net/sxe2/sxe2_irq.c
> create mode 100644 drivers/net/sxe2/sxe2_mac.c
> create mode 100644 drivers/net/sxe2/sxe2_mac.h
> create mode 100644 drivers/net/sxe2/sxe2_mp.c
> create mode 100644 drivers/net/sxe2/sxe2_mp.h
> create mode 100644 drivers/net/sxe2/sxe2_rss.c
> create mode 100644 drivers/net/sxe2/sxe2_rss.h
> create mode 100644 drivers/net/sxe2/sxe2_security.c
> create mode 100644 drivers/net/sxe2/sxe2_security.h
> create mode 100644 drivers/net/sxe2/sxe2_stats.c
> create mode 100644 drivers/net/sxe2/sxe2_stats.h
> create mode 100644 drivers/net/sxe2/sxe2_switchdev.c
> create mode 100644 drivers/net/sxe2/sxe2_switchdev.h
> create mode 100644 drivers/net/sxe2/sxe2_tm.c
> create mode 100644 drivers/net/sxe2/sxe2_tm.h
> create mode 100644 drivers/net/sxe2/sxe2_txrx_check_mbuf.c
> create mode 100644 drivers/net/sxe2/sxe2_txrx_check_mbuf.h
> create mode 100644 drivers/net/sxe2/sxe2_txrx_vec_avx2.c
> create mode 100644 drivers/net/sxe2/sxe2_txrx_vec_avx512.c
> create mode 100644 drivers/net/sxe2/sxe2_txrx_vec_neon.c
> create mode 100644 drivers/net/sxe2/sxe2vf_regs.h
>
This is look much better, there are a few minor things that you probably
want to address before I merge it.
The (overly verbose) AI feedback is...
[PATCH v4 00/23] sxe2 driver feature additions
This is in good shape. Substantive structural progress on essentially
everything I raised against v3.
Verified across the assembled tree:
- All 23 commits build cleanly end-to-end. git bisect now works. This is
the first revision of the series where that's been true.
- No LLM citation placeholders remain in commit messages. The v3 19/20
message with "[citation:1][citation:3][citation:5]" markers and the
"approximately X%" placeholder are both gone.
- The atomic-sw-stats fix is properly placed. 01/23 is a clean standalone
cleanup commit that removes RTE_ATOMIC qualifiers from
sxe2_rxq_sw_stats, replaces the atomic load/store/fetch_add calls with
plain operations, removes the if(sw_stats_en) gating, removes the now-
unused #include <rte_stdatomic.h>, and renames high_performance_mode to
no_sched_mode to match the devargs string. Verified zero atomic
operations on sw_stats remain in the assembled tree.
- drv-sw-stats devarg removed entirely (defined, parsed, but unused in
v3 - now gone).
- All surviving devargs are documented in doc/guides/nics/sxe2.rst with
substantive explanations covering what each parameter does, valid
values, defaults, and trade-offs.
- The v3 19/20 patch is split into 21/23 (memseg-walk callback
infrastructure, common/sxe2 only) and 22/23 (devargs parsing,
net/sxe2). Both commit messages now describe one thing each.
- The 469-entry runtime ptype-table initialiser is now a file-scope
`static const alignas(RTE_CACHE_LINE_SIZE) uint32_t
sxe2_ptype_tbl[]` with C99 designated initialisers.
- Patch 02/23 (AVX512) scope is tightened - dropped from 13 files to 6,
and the files it touches are all AVX512-related now.
- The v3 03/20 patch is split into 04/23 ("supported packet types") and
05/23 ("link update callback"), addressing the scope-drift complaint.
Three remaining items, none blocking:
[PATCH v4 04/23] subject still does not match content
The commit message says the patch adds `dev_supported_ptypes_get`, and
the patch adds that callback - but it also creates the entire 1793-line
drivers/net/sxe2/sxe2_txrx.c with the Tx/Rx framework, packet-type
constant table, classification helpers, etc. The ptype callback is a
small piece of what this patch does. Either rename the subject to
something like "net/sxe2: add Rx/Tx framework and packet types callback"
(more honest) or split the txrx framework into a separate prior commit
with ptype-callback registration as a small follow-up.
[PATCH v4 04/23] ptype table refactor is incomplete
The static const table is correct, but adapter->ptype_tbl is still
declared in struct sxe2_adapter and sxe2_init_ptype_tbl() now just
memcpy's the const table into the per-adapter copy at init. The vec
paths in sxe2_txrx_vec_avx2.c, _avx512.c, _sse.c and the poll path all
read through rxq->vsi->adapter->ptype_tbl[] rather than the file-scope
const. To finish: remove the adapter field, remove sxe2_init_ptype_tbl,
and have all readers reference sxe2_ptype_tbl directly. The inner-loop
saves one indirection per packet, and per-port memory drops by
SXE2_MAX_PTYPE_NUM * 4 bytes.
[PATCH v4 22/23] flow-duplicate-pattern still defaults to 1
This devarg now has good documentation, but the documentation
clarifies the design objection rather than resolving it: a boolean
that toggles "duplicate rte_flow rules are rejected with EEXIST" vs
"duplicate rte_flow rules are accepted" is a per-boot toggle for
standard-API contract semantics. Standard APIs shouldn't behave
differently based on a vendor devarg. Pick one policy (rejecting
duplicates with EEXIST is what every other PMD does), apply it
unconditionally, and remove the devarg. The
switch_pattern_dup_allow rule metadata can stay if hardware needs it
internally - just don't expose the policy as a boot-time knob.
The other surviving devargs are acceptable as posted:
- no-sched-mode: kernel-coexistence rationale documented, defensible.
- rx-low-latency: ITR throttling threshold, well-documented trade-off,
precedent in other PMDs.
- function-flow-direct: DPDK/kernel flow-table coexistence policy with
no rte_flow analogue. The documentation explains this clearly.
- fnav-stat-type: hardware counter-mode selection. The cleaner long-
term shape would be separate xstats names, but the current form is
documented and reasonable for now.
- sched-layer-mode: hardware-imposed TM hierarchy cap. Should ideally
be exposed via rte_tm_capabilities_get and selected at hierarchy
build time rather than via devarg; worth raising as a future rte_tm
enhancement.
Minor cosmetic:
In sxe2_parse_no_sched_mode() (22/23) the local variable is still
named `high_performance_mode`. The struct field rename in 01/23
didn't propagate to this parser local. Cosmetic.
Once 22/23 drops flow-duplicate-pattern and 04/23's subject is
either renamed or split, I'd consider this ready.
^ permalink raw reply
* Re: [PATCH v3 00/18] net/dpaa: bug fixes for bus, net and fmlib drivers
From: Stephen Hemminger @ 2026-06-19 17:28 UTC (permalink / raw)
To: Hemant Agrawal; +Cc: david.marchand, dev
In-Reply-To: <20260619103901.2274740-1-hemant.agrawal@nxp.com>
On Fri, 19 Jun 2026 16:08:43 +0530
Hemant Agrawal <hemant.agrawal@nxp.com> wrote:
> This series contains bug fixes for the DPAA PMD (bus/dpaa, net/dpaa,
> net/dpaa/fmlib and dma/dpaa).
>
> v3 changes (AI code review feedback):
> - P05: Clarify commit message: p_dev == NULL is equivalent to h_scheme == NULL
> since p_dev = (t_device *)h_scheme; consistent with all sibling functions
> - P16: Add comment explaining the intentional loop continuation; clarify
> commit message about the loop design
> - P17: Add DPAA_DP_LOG(WARNING) before silent return on l3_len == 0 to
> aid debugging of corrupt/uninitialized mbufs
>
> v2 changes:
> - P05: Fix commit message API name
> - P08: Guard DPAA_PUSH_QUEUES_NUMBER env-var for LS1043A (errata)
> - P09: Document dpaa_finish() removal
> - P10: Fix wrong Fixes: tag
> - P11: Split into two patches with correct Fixes: tags
> - P13: Also fix rx_buf_diallocate -> rx_buf_deallocate
>
> All patches are bug fixes tagged with Fixes: and Cc: stable@dpdk.org.
>
> Gagandeep Singh (3):
> bus/dpaa: fix device probe issue
> net/dpaa: fix device remove
> net/dpaa: fix invalid check on interrupt unregister
>
> Hemant Agrawal (11):
> bus/dpaa: fix error handling of qman_create_fq
> bus/dpaa: fix fqid endianness
> bus/dpaa: fix error handling in qman_query
> net/dpaa: fix modify cgr to use index
> bus/dpaa: fix fd leak for ccsr mmap
> net/dpaa: fix xstat name for tx undersized counter
> net/dpaa: fix xstat string typos in BMI stats table
> net/dpaa: remove duplicate ptype entries
> net/dpaa: fix wrong buffer in xstats get by id
> net/dpaa: fix null l3_len check in checksum offload
> net/dpaa: fix mbuf leak in SG fd creation
>
> Jun Yang (1):
> bus/dpaa: fix BMI RX stats register offset
>
> Prashant Gupta (1):
> net/dpaa/fmlib: add null check in scheme delete
>
> Vanshika Shukla (2):
> net/dpaa: fix port_handle leak in fm_prev_cleanup
> dma/dpaa: fix out-of-bounds access in SG descriptor enqueue
>
> drivers/bus/dpaa/base/qbman/bman_driver.c | 3 ++-
> drivers/bus/dpaa/base/qbman/qman.c | 11 ++++++---
> drivers/bus/dpaa/base/qbman/qman_driver.c | 6 ++---
> drivers/bus/dpaa/dpaa_bus.c | 17 ++++++-------
> drivers/bus/dpaa/include/fman.h | 6 ++---
> drivers/dma/dpaa/dpaa_qdma.c | 7 +++++-
> drivers/net/dpaa/dpaa_ethdev.c | 30 +++++++++++------------
> drivers/net/dpaa/dpaa_flow.c | 4 +++
> drivers/net/dpaa/dpaa_rxtx.c | 5 ++++
> drivers/net/dpaa/fmlib/fm_lib.c | 3 +++
> 10 files changed, 56 insertions(+), 36 deletions(-)
>
Applied to next-net with some minor changes to commit message to fix capitalization complaints from check-git-log
^ permalink raw reply
* Re: [PATCH v2 0/4] net/bond: fixes and cleanup
From: Stephen Hemminger @ 2026-06-19 17:22 UTC (permalink / raw)
To: dev
In-Reply-To: <20260529000157.235931-1-stephen@networkplumber.org>
On Thu, 28 May 2026 16:59:12 -0700
Stephen Hemminger <stephen@networkplumber.org> wrote:
> Automated analysis of the bonding found a few minor things.
> The bug fix is in patch 3 for secondary process crash does rx/tx.
>
> The cleanups are in handling of 8023ad mode setting
> and the logging macros.
>
> v2 - feedback about the mode setting and log messages
>
> Stephen Hemminger (4):
> net/bonding: make 8023ad enable function void
> net/bonding: check mode before setting dedicated queues
> net/bonding: prevent crash on Rx/Tx from secondary process
> net/bonding: remove redundant function names from log
>
> drivers/net/bonding/eth_bond_8023ad_private.h | 17 +----
> drivers/net/bonding/rte_eth_bond_8023ad.c | 16 ++--
> drivers/net/bonding/rte_eth_bond_api.c | 4 +-
> drivers/net/bonding/rte_eth_bond_pmd.c | 73 ++++++++++++++-----
> 4 files changed, 67 insertions(+), 43 deletions(-)
>
Applied to net-next, took Bruce's suggestion to split the first patch.
^ permalink raw reply
* Re: [PATCH 2/6] ip_frag: discard datagrams with overlapping fragments
From: Stephen Hemminger @ 2026-06-19 17:01 UTC (permalink / raw)
To: Morten Brørup; +Cc: dev, stable, Konstantin Ananyev
In-Reply-To: <98CBD80474FA8B44BF855DF32C47DC35F6592A@smartserver.smartshare.dk>
On Fri, 19 Jun 2026 15:12:21 +0200
Morten Brørup <mb@smartsharesystems.com> wrote:
> > + /*
> > + * Overlap with an existing fragment. Per RFC 8200 section
> > 4.5
> > + * (and RFC 5722) the datagram must be discarded; the same
> > is
> > + * applied to IPv4. Free all collected fragments, drop this
> > one,
> > + * and invalidate the entry.
> > + */
> > + if (ofs < fp->frags[i].ofs + fp->frags[i].len &&
> > + fp->frags[i].ofs < ofs + len) {
>
> This only catches fragments that are smaller than existing fragments, i.e. fit within one of the existing fragments.
> It should be:
> if ((ofs >= fp->frags[i].ofs &&
> ofs < fp->frags[i].ofs + fp->frags[i].len) ||
> (ofs + len >= fp->frags[i].ofs &&
> ofs + len < fp->frags[i].ofs + fp->frags[i].len)) {
>
> > + ip_frag_free(fp, dr);
The code here is comparing an incoming fragment N against existing fragment E,
using half-open ranges [start, end).
The test in the patch is symmetric in N and E.
ofs < e.ofs + e.len && e.ofs < ofs + len
The one you propose tests that either endpoint of N lands inside E.
Take a fixed stored fragment E = [200, 400) and run several incoming fragments through both.
N0 = ofs, N1 = ofs+len.
N inside E: N = [250, 300)
E: |=========| (200..400)
N: |===| (250..300)
Patch: 250 < 400 && 200 < 300 → T && T → overlap.
Proposed: (250≥200 && 250<400) → T → overlap.
Both agree.
N encloses E: N = [100, 500)
E: |=========| (200..400)
N: |=============| (100..500)
Patch: 100 < 400 && 200 < 500 → T && T → overlap.
Proposed: (100≥200 && …) → F, (500≥200 && 500<400) → T && F → F, so F || F → no overlap, MISSED.
This is the case the new version version drops. Neither endpoint of N (100 or 500) sits inside [200,400),
because N straddles E completely, so new version endpoint-in-E check fails even though the ranges clearly overlap.
Patch version catches it because the interval test doesn't care which range is larger.
N partial on the left: N = [100, 300)
E: |=========| (200..400)
N: |======| (100..300)
Patch: 100 < 400 && 200 < 300 → T → overlap.
Proposed: (300≥200 && 300<400) → T → overlap.
Agree.
N partial on the right: N = [300, 500) — symmetric to the above, both catch it.
So on the four genuine-overlap geometries, your suggestion catches all four and his misses the enclosing one.
That is not right since the enclosing overlap is a legitimate attack shape (a big fragment overwriting a smaller stored one).
There is another issue.
The >= on the exclusive end produces a false positive on fragments that merely abut, which is the normal case.
Take E already stored as [1400, 2800) and an in-order-but-late fragment N = [0, 1400) arriving after it (ordinary out-of-order delivery):
N: |======| (0..1400)
E: |======| (1400..2800)
These share no bytes; byte 1400 belongs only to E.
Patch: 0 < 2800 && 1400 < 1400 → T && F → no overlap, correct.
Proposed: (1400≥1400 && 1400<2800) → T && T → overlap, wrong.
This test would discard a perfectly valid datagram whenever a left-abutting fragment arrives after its neighbor.
Adjacent fragments abutting is what fragmentation produces by design, so this would fire constantly under reordering.
Bottom line: the patch was correct as far as I can tell.
^ permalink raw reply
* [PATCH v2] net/bnxt: avoid link flap on flow control set
From: Mohammad Shuab Siddique @ 2026-06-19 16:31 UTC (permalink / raw)
To: dev; +Cc: kishore.padmanabha, stable, Chenna Arnoori,
Mohammad Shuab Siddique
In-Reply-To: <20260616232300.359253-1-mohammad-shuab.siddique@broadcom.com>
From: Chenna Arnoori <chenna.arnoori@broadcom.com>
When OVS-DPDK reconciles port state, it calls flow_ctrl_get followed
by flow_ctrl_set if the returned configuration differs from its
database. The driver was reporting autoneg=1 whenever the firmware
had auto_pause set (including the AUTONEG_PAUSE bit 0x4), even
though no pause autoneg was actually requested. This mismatch
caused OVS to repeatedly call flow_ctrl_set, which triggered a
full link reconfig with PHY reset, flapping the link every time
any interface change occurred on the system.
Two problems were fixed. First, flow_ctrl_set was clearing all
autoneg bits instead of only the flow-control autoneg bit,
which also wiped the speed autoneg state. Second, the pause
set path was abandoning its own HWRM request and calling the
full link config function, which built a separate request
without the pause fields that set_pause_common would have
computed.
Port the kernel bnxt_en driver's approach: add a
set_link_common helper that merges link and speed fields into
an existing HWRM request, and rework set_pause to build a
single combined request with both pause and link fields when
a full reconfig is needed. When only pause changes without an
auto-to-force transition, a pause-only PHY config is sent
without a full link reprogram.
Fixes: 8aaf473bbed6 ("net/bnxt: add flow control operations")
Cc: stable@dpdk.org
Signed-off-by: Chenna Arnoori <chenna.arnoori@broadcom.com>
Signed-off-by: Mohammad Shuab Siddique <mohammad-shuab.siddique@broadcom.com>
---
doc/guides/rel_notes/release_26_07.rst | 25 ++++
drivers/net/bnxt/bnxt.h | 10 ++
drivers/net/bnxt/bnxt_ethdev.c | 12 +-
drivers/net/bnxt/bnxt_hwrm.c | 151 +++++++++++++++++++++++++
drivers/net/bnxt/bnxt_hwrm.h | 1 +
5 files changed, 197 insertions(+), 2 deletions(-)
diff --git a/doc/guides/rel_notes/release_26_07.rst b/doc/guides/rel_notes/release_26_07.rst
index b5285af5fe..ee80a37055 100644
--- a/doc/guides/rel_notes/release_26_07.rst
+++ b/doc/guides/rel_notes/release_26_07.rst
@@ -209,6 +209,31 @@ ABI Changes
* No ABI change that would break compatibility with 25.11.
+Bug Fixes and Other Changes
+---------------------------
+
+.. This section should contain bug fixes added to the relevant
+ stable branch. Sample format:
+
+ * **code/area: Fixed issue in <component>.**
+
+ Fixed a specific issue with the following impact, caused by the following
+ action, and the resolution.
+
+ This section is a comment. Do not overwrite or remove it.
+ Also, make sure to start the actual text at the margin.
+ =======================================================
+
+* **net/bnxt: Fixed link flapping on flow control configuration.**
+
+ Fixed an issue where setting flow control parameters via
+ ``rte_eth_dev_flow_ctrl_set()`` triggered an unconditional PHY reset,
+ causing repeated link flaps in environments such as OVS-DPDK that
+ periodically reconcile port state. The fix ports the kernel bnxt_en
+ approach of building a combined pause+link HWRM request rather than
+ delegating to the full link reconfiguration path.
+
+
Known Issues
------------
diff --git a/drivers/net/bnxt/bnxt.h b/drivers/net/bnxt/bnxt.h
index 7515f0564f..0ea18fb134 100644
--- a/drivers/net/bnxt/bnxt.h
+++ b/drivers/net/bnxt/bnxt.h
@@ -88,6 +88,8 @@
#define HWRM_VERSION_1_9_1 0x10901
#define HWRM_VERSION_1_9_2 0x10903
#define HWRM_VERSION_1_10_2_13 0x10a020d
+/* Minimum spec version that supports AUTONEG_PAUSE bit in auto_pause field */
+#define HWRM_SPEC_CODE_AUTONEG_PAUSE 0x10201
#define BNXT_MAX_MTU 9574
#define BNXT_NUM_VLANS 2
@@ -333,6 +335,14 @@ struct bnxt_link_info {
uint8_t active_lanes;
uint8_t option_flags;
uint16_t pmd_speed_lanes;
+ /* Bitmask tracking which autoneg modes are active */
+ uint8_t autoneg;
+#define BNXT_AUTONEG_SPEED 1 /* speed autoneg enabled */
+#define BNXT_AUTONEG_FLOW_CTRL 2 /* pause/flow-ctrl autoneg enabled */
+ /* True after autoneg->forced FC transition; cleared once set_pause
+ * sends the combined pause+link HWRM request successfully.
+ */
+ bool link_reconfig_needed;
};
#define BNXT_COS_QUEUE_COUNT 8
diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c
index 1b8cf3a52a..467b551bd9 100644
--- a/drivers/net/bnxt/bnxt_ethdev.c
+++ b/drivers/net/bnxt/bnxt_ethdev.c
@@ -2565,7 +2565,7 @@ static int bnxt_flow_ctrl_get_op(struct rte_eth_dev *dev,
return rc;
memset(fc_conf, 0, sizeof(*fc_conf));
- if (bp->link_info->auto_pause)
+ if (bp->link_info->autoneg & BNXT_AUTONEG_FLOW_CTRL)
fc_conf->autoneg = 1;
switch (bp->link_info->pause) {
case 0:
@@ -2601,6 +2601,14 @@ static int bnxt_flow_ctrl_set_op(struct rte_eth_dev *dev,
return -ENOTSUP;
}
+ if (fc_conf->autoneg) {
+ bp->link_info->autoneg |= BNXT_AUTONEG_FLOW_CTRL;
+ } else {
+ if (bp->link_info->autoneg & BNXT_AUTONEG_FLOW_CTRL)
+ bp->link_info->link_reconfig_needed = true;
+ bp->link_info->autoneg &= ~BNXT_AUTONEG_FLOW_CTRL;
+ }
+
switch (fc_conf->mode) {
case RTE_ETH_FC_NONE:
bp->link_info->auto_pause = 0;
@@ -2642,7 +2650,7 @@ static int bnxt_flow_ctrl_set_op(struct rte_eth_dev *dev,
}
break;
}
- return bnxt_set_hwrm_link_config(bp, true);
+ return bnxt_hwrm_set_pause(bp);
}
/* Add UDP tunneling port */
diff --git a/drivers/net/bnxt/bnxt_hwrm.c b/drivers/net/bnxt/bnxt_hwrm.c
index 0c82935de9..a0983183c0 100644
--- a/drivers/net/bnxt/bnxt_hwrm.c
+++ b/drivers/net/bnxt/bnxt_hwrm.c
@@ -1876,6 +1876,22 @@ static int bnxt_hwrm_port_phy_qcfg(struct bnxt *bp,
link_info->auto_pause = resp->auto_pause;
link_info->force_pause = resp->force_pause;
link_info->auto_mode = resp->auto_mode;
+ link_info->autoneg = 0;
+
+ if (link_info->auto_mode != HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_MODE_NONE) {
+ link_info->autoneg = BNXT_AUTONEG_SPEED;
+ if (bp->hwrm_spec_code >= HWRM_SPEC_CODE_AUTONEG_PAUSE) {
+ if (link_info->auto_pause &
+ HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_AUTONEG_PAUSE)
+ link_info->autoneg |=
+ BNXT_AUTONEG_FLOW_CTRL;
+ } else {
+ link_info->autoneg |= BNXT_AUTONEG_FLOW_CTRL;
+ }
+ } else {
+ link_info->autoneg = 0;
+ }
+
link_info->phy_type = resp->phy_type;
link_info->media_type = resp->media_type;
@@ -4048,6 +4064,141 @@ static int bnxt_hwrm_port_phy_cfg_v2(struct bnxt *bp, struct bnxt_link_info *con
return rc;
}
+static void
+bnxt_hwrm_set_pause_common(struct bnxt *bp,
+ struct hwrm_port_phy_cfg_input *req)
+{
+ struct bnxt_link_info *link_info = bp->link_info;
+
+ if (link_info->autoneg & BNXT_AUTONEG_FLOW_CTRL) {
+ if (bp->hwrm_spec_code >= HWRM_SPEC_CODE_AUTONEG_PAUSE)
+ req->auto_pause =
+ HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_AUTONEG_PAUSE;
+ if (link_info->auto_pause &
+ HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_RX)
+ req->auto_pause |=
+ HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_RX;
+ if (link_info->auto_pause &
+ HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_TX)
+ req->auto_pause |=
+ HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_TX;
+ req->enables |=
+ rte_cpu_to_le_32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_PAUSE);
+ } else {
+ if (link_info->force_pause &
+ HWRM_PORT_PHY_CFG_INPUT_FORCE_PAUSE_RX)
+ req->force_pause |=
+ HWRM_PORT_PHY_CFG_INPUT_FORCE_PAUSE_RX;
+ if (link_info->force_pause &
+ HWRM_PORT_PHY_CFG_INPUT_FORCE_PAUSE_TX)
+ req->force_pause |=
+ HWRM_PORT_PHY_CFG_INPUT_FORCE_PAUSE_TX;
+ req->enables |=
+ rte_cpu_to_le_32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_FORCE_PAUSE);
+ if (bp->hwrm_spec_code >= HWRM_SPEC_CODE_AUTONEG_PAUSE) {
+ req->auto_pause = req->force_pause;
+ req->enables |=
+ rte_cpu_to_le_32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_PAUSE);
+ }
+ }
+}
+
+static void
+bnxt_hwrm_set_link_common(struct bnxt *bp, struct hwrm_port_phy_cfg_input *req)
+{
+ struct rte_eth_conf *dev_conf = &bp->eth_dev->data->dev_conf;
+ uint16_t autoneg, speed;
+
+ autoneg = bnxt_check_eth_link_autoneg(dev_conf->link_speeds);
+
+ if (BNXT_CHIP_P5(bp) &&
+ dev_conf->link_speeds & RTE_ETH_LINK_SPEED_40G)
+ autoneg = 0;
+
+ if (autoneg == 1 && BNXT_CHIP_P5(bp) &&
+ bp->link_info->auto_mode == 0 &&
+ bp->link_info->force_pam4_link_speed ==
+ HWRM_PORT_PHY_CFG_INPUT_FORCE_PAM4_LINK_SPEED_200GB)
+ autoneg = 0;
+
+ speed = bnxt_parse_eth_link_speed(bp, dev_conf->link_speeds,
+ bp->link_info);
+ req->flags |=
+ rte_cpu_to_le_32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_RESET_PHY);
+
+ if (autoneg == 1 &&
+ (bp->link_info->support_auto_speeds ||
+ bp->link_info->support_pam4_auto_speeds)) {
+ uint16_t spd_mask;
+ uint32_t en;
+
+ req->flags |=
+ rte_cpu_to_le_32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_RESTART_AUTONEG);
+ spd_mask = bnxt_parse_eth_link_speed_mask(bp,
+ dev_conf->link_speeds);
+ req->auto_link_speed_mask = rte_cpu_to_le_16(spd_mask);
+ req->auto_link_pam4_speed_mask =
+ rte_cpu_to_le_16(bp->link_info->auto_pam4_link_speed_mask);
+ en = HWRM_PORT_PHY_CFG_IN_EN_AUTO_LINK_SPEED_MASK |
+ HWRM_PORT_PHY_CFG_IN_EN_AUTO_PAM4_LINK_SPD_MASK |
+ HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_MODE;
+ req->enables |= rte_cpu_to_le_32(en);
+ req->auto_mode =
+ HWRM_PORT_PHY_CFG_INPUT_AUTO_MODE_SPEED_MASK;
+ } else {
+ uint32_t en;
+
+ req->flags |=
+ rte_cpu_to_le_32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_FORCE);
+ if (speed) {
+ if (bp->link_info->link_signal_mode) {
+ req->force_pam4_link_speed =
+ rte_cpu_to_le_16(speed);
+ en = HWRM_PORT_PHY_CFG_IN_EN_FORCE_PAM4_LINK_SPEED;
+ req->enables |= rte_cpu_to_le_32(en);
+ } else {
+ req->force_link_speed =
+ rte_cpu_to_le_16(speed);
+ }
+ }
+ }
+ req->auto_duplex =
+ bnxt_parse_eth_link_duplex(dev_conf->link_speeds);
+ req->enables |=
+ rte_cpu_to_le_32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_DUPLEX);
+}
+
+int bnxt_hwrm_set_pause(struct bnxt *bp)
+{
+ struct hwrm_port_phy_cfg_input req = {0};
+ struct hwrm_port_phy_cfg_output *resp = bp->hwrm_cmd_resp_addr;
+ struct bnxt_link_info *link_info = bp->link_info;
+ int rc;
+
+ HWRM_PREP(&req, HWRM_PORT_PHY_CFG, BNXT_USE_CHIMP_MB);
+
+ bnxt_hwrm_set_pause_common(bp, &req);
+
+ if ((link_info->autoneg & BNXT_AUTONEG_FLOW_CTRL) ||
+ link_info->link_reconfig_needed)
+ bnxt_hwrm_set_link_common(bp, &req);
+
+ rc = bnxt_hwrm_send_message(bp, &req, sizeof(req), BNXT_USE_CHIMP_MB);
+
+ HWRM_CHECK_RESULT();
+
+ if (!rc) {
+ if (!(link_info->autoneg & BNXT_AUTONEG_FLOW_CTRL)) {
+ link_info->pause = link_info->force_pause;
+ link_info->auto_pause = 0;
+ }
+ link_info->link_reconfig_needed = false;
+ }
+
+ HWRM_UNLOCK();
+ return rc;
+}
+
static int bnxt_set_hwrm_link_config_v2(struct bnxt *bp, bool link_up)
{
struct rte_eth_conf *dev_conf = &bp->eth_dev->data->dev_conf;
diff --git a/drivers/net/bnxt/bnxt_hwrm.h b/drivers/net/bnxt/bnxt_hwrm.h
index fc56223ab4..3034803023 100644
--- a/drivers/net/bnxt/bnxt_hwrm.h
+++ b/drivers/net/bnxt/bnxt_hwrm.h
@@ -261,6 +261,7 @@ void bnxt_free_hwrm_rx_ring(struct bnxt *bp, int queue_index);
int bnxt_alloc_hwrm_resources(struct bnxt *bp);
int bnxt_get_hwrm_link_config(struct bnxt *bp, struct rte_eth_link *link);
int bnxt_set_hwrm_link_config(struct bnxt *bp, bool link_up);
+int bnxt_hwrm_set_pause(struct bnxt *bp);
int bnxt_hwrm_func_qcfg(struct bnxt *bp, uint16_t *mtu);
int bnxt_hwrm_func_resc_qcaps(struct bnxt *bp);
int bnxt_hwrm_func_reserve_vf_resc(struct bnxt *bp, bool test);
--
2.47.3
^ permalink raw reply related
* Re: [PATCH v1 0/5] prefix lcore role enum values
From: Stephen Hemminger @ 2026-06-19 15:39 UTC (permalink / raw)
To: Morten Brørup
Cc: Thomas Monjalon, Huisong Li, andrew.rybchenko, dev, zhanjie9
In-Reply-To: <98CBD80474FA8B44BF855DF32C47DC35F65929@smartserver.smartshare.dk>
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/82235965090
It makes looking at patchwork dashboard difficult, all patches show up with red mark
^ permalink raw reply
* [v2] crypto/qat: require IPsec MB for HMAC precomputes
From: Emma Finn @ 2026-06-19 13:53 UTC (permalink / raw)
To: Kai Ji; +Cc: dev, Emma Finn
In-Reply-To: <20260611085237.1459286-1-emma.finn@intel.com>
IPsec MB library (v1.4.0+) is now required for HMAC precomputes as
OpenSSL 3.0 removed SHA*_Transform APIs. OpenSSL remains optional
for DOCSIS BPI cipher fallback via EVP API.
On x86: IPsec MB required, OpenSSL optional (DOCSIS fallback)
On ARM: IPsec MB required, OpenSSL required (DOCSIS support)
Signed-off-by: Emma Finn <emma.finn@intel.com>
---
v2:
* Fix resource leak in ossl_legacy_provider_load()
* Added release note
---
doc/guides/cryptodevs/qat.rst | 28 +-
doc/guides/rel_notes/release_26_07.rst | 8 +
drivers/common/qat/meson.build | 56 ++--
drivers/crypto/qat/qat_sym_session.c | 440 +++----------------------
4 files changed, 100 insertions(+), 432 deletions(-)
diff --git a/doc/guides/cryptodevs/qat.rst b/doc/guides/cryptodevs/qat.rst
index 0c2b85444e..4e60e8343c 100644
--- a/doc/guides/cryptodevs/qat.rst
+++ b/doc/guides/cryptodevs/qat.rst
@@ -352,15 +352,25 @@ To use this feature the user must set the devarg on process start as a device ad
-a 03:01.1,qat_sym_cipher_crc_enable=1
-Running QAT PMD with Intel IPsec MB library for symmetric precomputes function
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-The QAT PMD uses Intel IPsec MB library for partial hash calculation
-in symmetric precomputes function by default,
-the minimum required version of IPsec MB library is v1.4.
-If this version of IPsec is not met, it will fallback to use OpenSSL.
-ARM will always default to using OpenSSL
-as ARM IPsec MB does not support the necessary algorithms.
+Running QAT PMD with Intel IPsec MB library
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The QAT PMD requires IPsec MB library for HMAC partial hash calculation
+in symmetric precomputes function. OpenSSL 3.0+ removed the low-level SHA*_Transform APIs
+that were previously used for HMAC precomputes.
+
+**On x86 platforms:**
+
+* Intel IPsec MB library (v1.4.0+) is required for HMAC precomputes
+* OpenSSL (3.0+) is optional for DOCSIS BPI cipher fallback
+
+**On ARM platforms:**
+
+* ARM IPsec MB library from ``gitlab.arm.com/arm-reference-solutions/ipsec-mb``
+ is required for HMAC precomputes.
+* OpenSSL (3.0+) is required for DOCSIS BPI cipher algorithms. ARM IPsec MB does not
+ implement CFB-one-byte cipher modes needed for DOCSIS. Without OpenSSL, DOCSIS
+ algorithms will not be available on ARM.
Device and driver naming
diff --git a/doc/guides/rel_notes/release_26_07.rst b/doc/guides/rel_notes/release_26_07.rst
index 34809a4850..809ec19d66 100644
--- a/doc/guides/rel_notes/release_26_07.rst
+++ b/doc/guides/rel_notes/release_26_07.rst
@@ -155,6 +155,14 @@ New Features
Added AGENTS.md file for AI review
and supporting scripts to review patches and documentation.
+* **Updated QAT PMD dependency requirements.**
+
+ The QAT crypto PMD now requires IPsec MB library (v1.4.0+) for HMAC precomputes
+ on all platforms. OpenSSL 3.0+ is now optional and used only for DOCSIS BPI cipher
+ fallback. Previously, QAT could build with OpenSSL-only on x86.
+
+ On ARM, both IPsec MB and OpenSSL are required for full functionality.
+
Removed Items
-------------
diff --git a/drivers/common/qat/meson.build b/drivers/common/qat/meson.build
index 31e06f4376..969ff9e8ee 100644
--- a/drivers/common/qat/meson.build
+++ b/drivers/common/qat/meson.build
@@ -27,47 +27,61 @@ if disable_drivers.contains(qat_compress_path)
'Explicitly disabled via build config')
endif
-libcrypto = dependency('libcrypto', required: false, method: 'pkg-config')
+# IPsec MB is REQUIRED for HMAC precomputes (no OpenSSL 3.0 alternative)
+# OpenSSL is OPTIONAL for DOCSIS BPI cipher fallback
+IMB_required_ver = '1.4.0'
-if arch_subdir == 'arm'
- if libcrypto.found()
- ext_deps += libcrypto
- dpdk_conf.set('RTE_QAT_OPENSSL', true)
+# Only check IPsec MB if qat_crypto wasn't already disabled
+if qat_crypto
+ if arch_subdir == 'arm'
+ IMB_header = '#include<ipsec-mb.h>'
else
- qat_crypto = false
- dpdk_drvs_disabled += qat_crypto_path
- set_variable('drv_' + qat_crypto_path.underscorify() + '_disable_reason',
- 'missing dependency for Arm, libcrypto')
+ IMB_header = '#include<intel-ipsec-mb.h>'
endif
-else
- IMB_required_ver = '1.4.0'
- IMB_header = '#include<intel-ipsec-mb.h>'
+
+ # Check for IPsec MB library (required)
libipsecmb = cc.find_library('IPSec_MB', required: false)
if libipsecmb.found() and cc.links(
'int main(void) {return 0;}', dependencies: libipsecmb)
- # version comes with quotes, so we split based on " and take the middle
imb_ver = cc.get_define('IMB_VERSION_STR',
prefix : IMB_header).split('"')[1]
if (imb_ver.version_compare('>=' + IMB_required_ver))
ext_deps += libipsecmb
- elif libcrypto.found()
- ext_deps += libcrypto
- dpdk_conf.set('RTE_QAT_OPENSSL', true)
+ dpdk_conf.set('RTE_QAT_IPSECMB', true)
else
qat_crypto = false
dpdk_drvs_disabled += qat_crypto_path
set_variable('drv_' + qat_crypto_path.underscorify() + '_disable_reason',
- 'missing dependency, libipsecmb or libcrypto')
+ 'IPSec_MB version >= @0@ is required, found version @1@'.format(
+ IMB_required_ver, imb_ver))
endif
- elif libcrypto.found()
- ext_deps += libcrypto
- dpdk_conf.set('RTE_QAT_OPENSSL', true)
else
qat_crypto = false
dpdk_drvs_disabled += qat_crypto_path
set_variable('drv_' + qat_crypto_path.underscorify() + '_disable_reason',
- 'missing dependency, libipsecmb or libcrypto')
+ 'missing required dependency, libIPSec_MB >= @0@'.format(IMB_required_ver))
+ endif
+endif
+
+# Check for OpenSSL (optional, for DOCSIS BPI cipher fallback)
+openssl_required_ver = '3.0.0'
+if qat_crypto
+ libcrypto = dependency('libcrypto', required: false, method: 'pkg-config', version: '>= ' + openssl_required_ver)
+ if libcrypto.found()
+ ext_deps += libcrypto
+ dpdk_conf.set('RTE_QAT_OPENSSL', true)
+ if arch_subdir == 'arm'
+ message('QAT: Using OpenSSL @0@ for DOCSIS on ARM'.format(libcrypto.version()))
+ else
+ message('QAT: OpenSSL @0@ available for DOCSIS fallback'.format(libcrypto.version()))
+ endif
+ else
+ if arch_subdir == 'arm'
+ warning('QAT: OpenSSL >= @0@ not found - DOCSIS algorithms will not be available on ARM'.format(openssl_required_ver))
+ else
+ message('QAT: OpenSSL >= @0@ not found - DOCSIS will use IPsec MB only'.format(openssl_required_ver))
+ endif
endif
endif
diff --git a/drivers/crypto/qat/qat_sym_session.c b/drivers/crypto/qat/qat_sym_session.c
index ff01db4372..81f6bacff9 100644
--- a/drivers/crypto/qat/qat_sym_session.c
+++ b/drivers/crypto/qat/qat_sym_session.c
@@ -2,19 +2,18 @@
* Copyright(c) 2015-2022 Intel Corporation
*/
-#define OPENSSL_API_COMPAT 0x10100000L
-
-#ifdef RTE_QAT_OPENSSL
-#include <openssl/sha.h> /* Needed to calculate pre-compute values */
-#include <openssl/aes.h> /* Needed to calculate pre-compute values */
-#include <openssl/md5.h> /* Needed to calculate pre-compute values */
-#include <openssl/evp.h> /* Needed for bpi runt block processing */
-#endif
-
-#ifndef RTE_QAT_OPENSSL
-#ifndef RTE_ARCH_ARM
+/* IPsec MB is required for HMAC precomputes (OpenSSL 3.0 removed Transform APIs)
+ * OpenSSL is optional for DOCSIS BPI cipher fallback
+ */
+#ifdef RTE_ARCH_ARM
+#include <ipsec-mb.h>
+#else
#include <intel-ipsec-mb.h>
#endif
+
+#ifdef RTE_QAT_OPENSSL
+#define OPENSSL_API_COMPAT 0x30000000L
+#include <openssl/evp.h> /* For DOCSIS BPI cipher fallback */
#endif
#include <rte_memcpy.h>
@@ -38,9 +37,8 @@
static OSSL_PROVIDER * legacy_lib;
static OSSL_PROVIDER *default_lib;
-/* Some cryptographic algorithms such as MD and DES are now considered legacy
- * and not enabled by default in OpenSSL 3.0. Load up lagacy provider as MD5
- * DES are needed in QAT pre-computes and secure session creation.
+/* DES is considered legacy and not enabled by default in OpenSSL 3.0.
+ * Load legacy provider for DES-DOCSISBPI cipher fallback support.
*/
static int ossl_legacy_provider_load(void)
{
@@ -52,7 +50,8 @@ static int ossl_legacy_provider_load(void)
default_lib = OSSL_PROVIDER_load(NULL, "default");
if (default_lib == NULL) {
OSSL_PROVIDER_unload(legacy_lib);
- return -EINVAL;
+ legacy_lib = NULL;
+ return -EINVAL;
}
return 0;
@@ -60,8 +59,14 @@ static int ossl_legacy_provider_load(void)
static void ossl_legacy_provider_unload(void)
{
- OSSL_PROVIDER_unload(legacy_lib);
- OSSL_PROVIDER_unload(default_lib);
+ if (legacy_lib != NULL) {
+ OSSL_PROVIDER_unload(legacy_lib);
+ legacy_lib = NULL;
+ }
+ if (default_lib != NULL) {
+ OSSL_PROVIDER_unload(default_lib);
+ default_lib = NULL;
+ }
}
#endif
#endif
@@ -635,7 +640,9 @@ qat_sym_session_configure(struct rte_cryptodev *dev,
#ifdef RTE_QAT_OPENSSL
#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
- ossl_legacy_provider_load();
+ ret = ossl_legacy_provider_load();
+ if (ret != 0)
+ return ret;
#endif
#endif
ret = qat_sym_session_set_parameters(dev, xform,
@@ -644,7 +651,11 @@ qat_sym_session_configure(struct rte_cryptodev *dev,
if (ret != 0) {
QAT_LOG(ERR,
"Crypto QAT PMD: failed to configure session parameters");
-
+#ifdef RTE_QAT_OPENSSL
+#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
+ ossl_legacy_provider_unload();
+#endif
+#endif
return ret;
}
@@ -1412,339 +1423,9 @@ static int qat_hash_get_block_size(enum icp_qat_hw_auth_algo qat_hash_alg)
#define HMAC_OPAD_VALUE 0x5c
#define HASH_XCBC_PRECOMP_KEY_NUM 3
-#ifdef RTE_QAT_OPENSSL
-static int partial_hash_sha1(uint8_t *data_in, uint8_t *data_out)
-{
- SHA_CTX ctx;
-
- if (!SHA1_Init(&ctx))
- return -EFAULT;
- SHA1_Transform(&ctx, data_in);
- rte_memcpy(data_out, &ctx, SHA_DIGEST_LENGTH);
- return 0;
-}
-
-static int partial_hash_sha224(uint8_t *data_in, uint8_t *data_out)
-{
- SHA256_CTX ctx;
-
- if (!SHA224_Init(&ctx))
- return -EFAULT;
- SHA256_Transform(&ctx, data_in);
- rte_memcpy(data_out, &ctx, SHA256_DIGEST_LENGTH);
- return 0;
-}
-
-static int partial_hash_sha256(uint8_t *data_in, uint8_t *data_out)
-{
- SHA256_CTX ctx;
-
- if (!SHA256_Init(&ctx))
- return -EFAULT;
- SHA256_Transform(&ctx, data_in);
- rte_memcpy(data_out, &ctx, SHA256_DIGEST_LENGTH);
- return 0;
-}
-
-static int partial_hash_sha384(uint8_t *data_in, uint8_t *data_out)
-{
- SHA512_CTX ctx;
-
- if (!SHA384_Init(&ctx))
- return -EFAULT;
- SHA512_Transform(&ctx, data_in);
- rte_memcpy(data_out, &ctx, SHA512_DIGEST_LENGTH);
- return 0;
-}
-
-static int partial_hash_sha512(uint8_t *data_in, uint8_t *data_out)
-{
- SHA512_CTX ctx;
-
- if (!SHA512_Init(&ctx))
- return -EFAULT;
- SHA512_Transform(&ctx, data_in);
- rte_memcpy(data_out, &ctx, SHA512_DIGEST_LENGTH);
- return 0;
-}
-
-static int partial_hash_md5(uint8_t *data_in, uint8_t *data_out)
-{
- MD5_CTX ctx;
-
- if (!MD5_Init(&ctx))
- return -EFAULT;
- MD5_Transform(&ctx, data_in);
- rte_memcpy(data_out, &ctx, MD5_DIGEST_LENGTH);
-
- return 0;
-}
-
-static void aes_cmac_key_derive(uint8_t *base, uint8_t *derived)
-{
- int i;
-
- derived[0] = base[0] << 1;
- for (i = 1; i < ICP_QAT_HW_AES_BLK_SZ ; i++) {
- derived[i] = base[i] << 1;
- derived[i - 1] |= base[i] >> 7;
- }
-
- if (base[0] & 0x80)
- derived[ICP_QAT_HW_AES_BLK_SZ - 1] ^= QAT_AES_CMAC_CONST_RB;
-}
-
-static int
-partial_hash_compute(enum icp_qat_hw_auth_algo hash_alg,
- uint8_t *data_in, uint8_t *data_out)
-{
- int digest_size;
- uint8_t digest[qat_hash_get_digest_size(
- ICP_QAT_HW_AUTH_ALGO_DELIMITER)];
- uint32_t *hash_state_out_be32;
- uint64_t *hash_state_out_be64;
- int i;
-
- /* Initialize to avoid gcc warning */
- memset(digest, 0, sizeof(digest));
-
- digest_size = qat_hash_get_digest_size(hash_alg);
- if (digest_size <= 0)
- return -EFAULT;
-
- hash_state_out_be32 = (uint32_t *)data_out;
- hash_state_out_be64 = (uint64_t *)data_out;
-
- switch (hash_alg) {
- case ICP_QAT_HW_AUTH_ALGO_SHA1:
- if (partial_hash_sha1(data_in, digest))
- return -EFAULT;
- for (i = 0; i < digest_size >> 2; i++, hash_state_out_be32++)
- *hash_state_out_be32 =
- rte_bswap32(*(((uint32_t *)digest)+i));
- break;
- case ICP_QAT_HW_AUTH_ALGO_SHA224:
- if (partial_hash_sha224(data_in, digest))
- return -EFAULT;
- for (i = 0; i < digest_size >> 2; i++, hash_state_out_be32++)
- *hash_state_out_be32 =
- rte_bswap32(*(((uint32_t *)digest)+i));
- break;
- case ICP_QAT_HW_AUTH_ALGO_SHA256:
- if (partial_hash_sha256(data_in, digest))
- return -EFAULT;
- for (i = 0; i < digest_size >> 2; i++, hash_state_out_be32++)
- *hash_state_out_be32 =
- rte_bswap32(*(((uint32_t *)digest)+i));
- break;
- case ICP_QAT_HW_AUTH_ALGO_SHA384:
- if (partial_hash_sha384(data_in, digest))
- return -EFAULT;
- for (i = 0; i < digest_size >> 3; i++, hash_state_out_be64++)
- *hash_state_out_be64 =
- rte_bswap64(*(((uint64_t *)digest)+i));
- break;
- case ICP_QAT_HW_AUTH_ALGO_SHA512:
- if (partial_hash_sha512(data_in, digest))
- return -EFAULT;
- for (i = 0; i < digest_size >> 3; i++, hash_state_out_be64++)
- *hash_state_out_be64 =
- rte_bswap64(*(((uint64_t *)digest)+i));
- break;
- case ICP_QAT_HW_AUTH_ALGO_MD5:
- if (partial_hash_md5(data_in, data_out))
- return -EFAULT;
- break;
- default:
- QAT_LOG(ERR, "invalid hash alg %u", hash_alg);
- return -EFAULT;
- }
-
- return 0;
-}
-
-static const uint8_t AES_CMAC_SEED[ICP_QAT_HW_AES_128_KEY_SZ];
-
-static int qat_sym_do_precomputes(enum icp_qat_hw_auth_algo hash_alg,
- const uint8_t *auth_key,
- uint16_t auth_keylen,
- uint8_t *p_state_buf,
- uint16_t *p_state_len,
- uint8_t aes_cmac)
-{
- int block_size;
- uint8_t ipad[qat_hash_get_block_size(ICP_QAT_HW_AUTH_ALGO_DELIMITER)];
- uint8_t opad[qat_hash_get_block_size(ICP_QAT_HW_AUTH_ALGO_DELIMITER)];
- int i;
-
- if (hash_alg == ICP_QAT_HW_AUTH_ALGO_AES_XCBC_MAC) {
-
- /* CMAC */
- if (aes_cmac) {
- AES_KEY enc_key;
- uint8_t *in = NULL;
- uint8_t k0[ICP_QAT_HW_AES_128_KEY_SZ];
- uint8_t *k1, *k2;
-
- auth_keylen = ICP_QAT_HW_AES_128_KEY_SZ;
-
- in = rte_zmalloc("AES CMAC K1",
- ICP_QAT_HW_AES_128_KEY_SZ, 16);
-
- if (in == NULL) {
- QAT_LOG(ERR, "Failed to alloc memory");
- return -ENOMEM;
- }
-
- rte_memcpy(in, AES_CMAC_SEED,
- ICP_QAT_HW_AES_128_KEY_SZ);
- rte_memcpy(p_state_buf, auth_key, auth_keylen);
-
- if (AES_set_encrypt_key(auth_key, auth_keylen << 3,
- &enc_key) != 0) {
- rte_free_sensitive(in);
- return -EFAULT;
- }
-
- AES_encrypt(in, k0, &enc_key);
-
- k1 = p_state_buf + ICP_QAT_HW_AES_XCBC_MAC_STATE1_SZ;
- k2 = k1 + ICP_QAT_HW_AES_XCBC_MAC_STATE1_SZ;
-
- aes_cmac_key_derive(k0, k1);
- aes_cmac_key_derive(k1, k2);
-
- rte_memzero_explicit(k0, ICP_QAT_HW_AES_128_KEY_SZ);
- *p_state_len = ICP_QAT_HW_AES_XCBC_MAC_STATE2_SZ;
- rte_free_sensitive(in);
- goto out;
- } else {
- static uint8_t qat_aes_xcbc_key_seed[
- ICP_QAT_HW_AES_XCBC_MAC_STATE2_SZ] = {
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
- 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
- 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
- 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
- };
-
- uint8_t *in = NULL;
- uint8_t *out = p_state_buf;
- int x;
- AES_KEY enc_key;
-
- in = rte_zmalloc("working mem for key",
- ICP_QAT_HW_AES_XCBC_MAC_STATE2_SZ, 16);
- if (in == NULL) {
- QAT_LOG(ERR, "Failed to alloc memory");
- return -ENOMEM;
- }
-
- rte_memcpy(in, qat_aes_xcbc_key_seed,
- ICP_QAT_HW_AES_XCBC_MAC_STATE2_SZ);
- for (x = 0; x < HASH_XCBC_PRECOMP_KEY_NUM; x++) {
- if (AES_set_encrypt_key(auth_key,
- auth_keylen << 3,
- &enc_key) != 0) {
- rte_free_sensitive(in -
- (x * ICP_QAT_HW_AES_XCBC_MAC_KEY_SZ));
- rte_memzero_explicit(out -
- (x * ICP_QAT_HW_AES_XCBC_MAC_KEY_SZ),
- ICP_QAT_HW_AES_XCBC_MAC_STATE2_SZ);
- return -EFAULT;
- }
- AES_encrypt(in, out, &enc_key);
- in += ICP_QAT_HW_AES_XCBC_MAC_KEY_SZ;
- out += ICP_QAT_HW_AES_XCBC_MAC_KEY_SZ;
- }
- *p_state_len = ICP_QAT_HW_AES_XCBC_MAC_STATE2_SZ;
- rte_free_sensitive(in - x*ICP_QAT_HW_AES_XCBC_MAC_KEY_SZ);
- goto out;
- }
-
- } else if ((hash_alg == ICP_QAT_HW_AUTH_ALGO_GALOIS_128) ||
- (hash_alg == ICP_QAT_HW_AUTH_ALGO_GALOIS_64)) {
- uint8_t *in = NULL;
- uint8_t *out = p_state_buf;
- AES_KEY enc_key;
-
- memset(p_state_buf, 0, ICP_QAT_HW_GALOIS_H_SZ +
- ICP_QAT_HW_GALOIS_LEN_A_SZ +
- ICP_QAT_HW_GALOIS_E_CTR0_SZ);
- in = rte_zmalloc("working mem for key",
- ICP_QAT_HW_GALOIS_H_SZ, 16);
- if (in == NULL) {
- QAT_LOG(ERR, "Failed to alloc memory");
- return -ENOMEM;
- }
-
- rte_memzero_explicit(in, ICP_QAT_HW_GALOIS_H_SZ);
- if (AES_set_encrypt_key(auth_key, auth_keylen << 3,
- &enc_key) != 0) {
- return -EFAULT;
- }
- AES_encrypt(in, out, &enc_key);
- *p_state_len = ICP_QAT_HW_GALOIS_H_SZ +
- ICP_QAT_HW_GALOIS_LEN_A_SZ +
- ICP_QAT_HW_GALOIS_E_CTR0_SZ;
- rte_free_sensitive(in);
- return 0;
- }
-
- block_size = qat_hash_get_block_size(hash_alg);
- if (block_size < 0)
- return block_size;
- /* init ipad and opad from key and xor with fixed values */
- memset(ipad, 0, block_size);
- memset(opad, 0, block_size);
-
- if (auth_keylen > (unsigned int)block_size) {
- QAT_LOG(ERR, "invalid keylen %u", auth_keylen);
- return -EFAULT;
- }
-
- RTE_VERIFY(auth_keylen <= sizeof(ipad));
- RTE_VERIFY(auth_keylen <= sizeof(opad));
-
- rte_memcpy(ipad, auth_key, auth_keylen);
- rte_memcpy(opad, auth_key, auth_keylen);
-
- for (i = 0; i < block_size; i++) {
- uint8_t *ipad_ptr = ipad + i;
- uint8_t *opad_ptr = opad + i;
- *ipad_ptr ^= HMAC_IPAD_VALUE;
- *opad_ptr ^= HMAC_OPAD_VALUE;
- }
-
- /* do partial hash of ipad and copy to state1 */
- if (partial_hash_compute(hash_alg, ipad, p_state_buf)) {
- rte_memzero_explicit(ipad, block_size);
- rte_memzero_explicit(opad, block_size);
- QAT_LOG(ERR, "ipad precompute failed");
- return -EFAULT;
- }
-
- /*
- * State len is a multiple of 8, so may be larger than the digest.
- * Put the partial hash of opad state_len bytes after state1
- */
- *p_state_len = qat_hash_get_state1_size(hash_alg);
- if (partial_hash_compute(hash_alg, opad, p_state_buf + *p_state_len)) {
- rte_memzero_explicit(ipad, block_size);
- rte_memzero_explicit(opad, block_size);
- QAT_LOG(ERR, "opad precompute failed");
- return -EFAULT;
- }
-
- /* don't leave data lying around */
- rte_memzero_explicit(ipad, block_size);
- rte_memzero_explicit(opad, block_size);
-out:
- return 0;
-}
-
-#else
+/* HMAC precomputes always use IPsec MB (OpenSSL 3.0 removed SHA*_Transform APIs)
+ * OpenSSL is only used for DOCSIS BPI cipher fallback (via EVP API)
+ */
static int aes_ipsecmb_job(uint8_t *in, uint8_t *out, IMB_MGR *m,
const uint8_t *key, uint16_t auth_keylen)
@@ -1992,7 +1673,6 @@ static int qat_sym_do_precomputes_ipsec_mb(enum icp_qat_hw_auth_algo hash_alg,
free_mb_mgr(m);
return ret;
}
-#endif
static void
qat_sym_session_init_common_hdr(struct qat_sym_session *session)
@@ -2482,16 +2162,9 @@ static int qat_sym_cd_auth_set(struct qat_sym_session *cdesc,
break;
}
/* SHA-1 HMAC */
-#ifdef RTE_QAT_OPENSSL
- ret = qat_sym_do_precomputes(ICP_QAT_HW_AUTH_ALGO_SHA1, authkey,
- authkeylen, cdesc->cd_cur_ptr, &state1_size,
- cdesc->aes_cmac);
-
-#else
ret = qat_sym_do_precomputes_ipsec_mb(ICP_QAT_HW_AUTH_ALGO_SHA1,
authkey, authkeylen, cdesc->cd_cur_ptr, &state1_size,
cdesc->aes_cmac);
-#endif
if (ret) {
QAT_LOG(ERR, "(SHA)precompute failed");
@@ -2509,15 +2182,9 @@ static int qat_sym_cd_auth_set(struct qat_sym_session *cdesc,
break;
}
/* SHA-224 HMAC */
-#ifdef RTE_QAT_OPENSSL
- ret = qat_sym_do_precomputes(ICP_QAT_HW_AUTH_ALGO_SHA224, authkey,
- authkeylen, cdesc->cd_cur_ptr, &state1_size,
- cdesc->aes_cmac);
-#else
ret = qat_sym_do_precomputes_ipsec_mb(ICP_QAT_HW_AUTH_ALGO_SHA224,
authkey, authkeylen, cdesc->cd_cur_ptr, &state1_size,
cdesc->aes_cmac);
-#endif
if (ret) {
QAT_LOG(ERR, "(SHA)precompute failed");
return -EFAULT;
@@ -2534,15 +2201,9 @@ static int qat_sym_cd_auth_set(struct qat_sym_session *cdesc,
break;
}
/* SHA-256 HMAC */
-#ifdef RTE_QAT_OPENSSL
- ret = qat_sym_do_precomputes(ICP_QAT_HW_AUTH_ALGO_SHA256, authkey,
- authkeylen, cdesc->cd_cur_ptr, &state1_size,
- cdesc->aes_cmac);
-#else
ret = qat_sym_do_precomputes_ipsec_mb(ICP_QAT_HW_AUTH_ALGO_SHA256,
authkey, authkeylen, cdesc->cd_cur_ptr, &state1_size,
cdesc->aes_cmac);
-#endif
if (ret) {
QAT_LOG(ERR, "(SHA)precompute failed");
return -EFAULT;
@@ -2559,15 +2220,9 @@ static int qat_sym_cd_auth_set(struct qat_sym_session *cdesc,
break;
}
/* SHA-384 HMAC */
-#ifdef RTE_QAT_OPENSSL
- ret = qat_sym_do_precomputes(ICP_QAT_HW_AUTH_ALGO_SHA384, authkey,
- authkeylen, cdesc->cd_cur_ptr, &state1_size,
- cdesc->aes_cmac);
-#else
ret = qat_sym_do_precomputes_ipsec_mb(ICP_QAT_HW_AUTH_ALGO_SHA384,
authkey, authkeylen, cdesc->cd_cur_ptr, &state1_size,
cdesc->aes_cmac);
-#endif
if (ret) {
QAT_LOG(ERR, "(SHA)precompute failed");
return -EFAULT;
@@ -2584,15 +2239,9 @@ static int qat_sym_cd_auth_set(struct qat_sym_session *cdesc,
break;
}
/* SHA-512 HMAC */
-#ifdef RTE_QAT_OPENSSL
- ret = qat_sym_do_precomputes(ICP_QAT_HW_AUTH_ALGO_SHA512, authkey,
- authkeylen, cdesc->cd_cur_ptr, &state1_size,
- cdesc->aes_cmac);
-#else
ret = qat_sym_do_precomputes_ipsec_mb(ICP_QAT_HW_AUTH_ALGO_SHA512,
authkey, authkeylen, cdesc->cd_cur_ptr, &state1_size,
cdesc->aes_cmac);
-#endif
if (ret) {
QAT_LOG(ERR, "(SHA)precompute failed");
return -EFAULT;
@@ -2628,16 +2277,10 @@ static int qat_sym_cd_auth_set(struct qat_sym_session *cdesc,
if (cdesc->aes_cmac)
memset(cdesc->cd_cur_ptr, 0, state1_size);
-#ifdef RTE_QAT_OPENSSL
- ret = qat_sym_do_precomputes(ICP_QAT_HW_AUTH_ALGO_AES_XCBC_MAC,
- authkey, authkeylen, cdesc->cd_cur_ptr + state1_size,
- &state2_size, cdesc->aes_cmac);
-#else
ret = qat_sym_do_precomputes_ipsec_mb(
ICP_QAT_HW_AUTH_ALGO_AES_XCBC_MAC,
authkey, authkeylen, cdesc->cd_cur_ptr + state1_size,
&state2_size, cdesc->aes_cmac);
-#endif
if (ret) {
QAT_LOG(ERR, "(%s)precompute failed",
cdesc->aes_cmac ? "CMAC" : "XCBC");
@@ -2654,15 +2297,9 @@ static int qat_sym_cd_auth_set(struct qat_sym_session *cdesc,
case ICP_QAT_HW_AUTH_ALGO_GALOIS_64:
cdesc->qat_proto_flag = QAT_CRYPTO_PROTO_FLAG_GCM;
state1_size = ICP_QAT_HW_GALOIS_128_STATE1_SZ;
-#ifdef RTE_QAT_OPENSSL
- ret = qat_sym_do_precomputes(cdesc->qat_hash_alg, authkey,
- authkeylen, cdesc->cd_cur_ptr + state1_size,
- &state2_size, cdesc->aes_cmac);
-#else
ret = qat_sym_do_precomputes_ipsec_mb(cdesc->qat_hash_alg, authkey,
authkeylen, cdesc->cd_cur_ptr + state1_size,
&state2_size, cdesc->aes_cmac);
-#endif
if (ret) {
QAT_LOG(ERR, "(GCM)precompute failed");
return -EFAULT;
@@ -2734,15 +2371,9 @@ static int qat_sym_cd_auth_set(struct qat_sym_session *cdesc,
auth_param->hash_state_sz = ICP_QAT_HW_ZUC_256_IV_SZ >> 3;
break;
case ICP_QAT_HW_AUTH_ALGO_MD5:
-#ifdef RTE_QAT_OPENSSL
- ret = qat_sym_do_precomputes(ICP_QAT_HW_AUTH_ALGO_MD5, authkey,
- authkeylen, cdesc->cd_cur_ptr, &state1_size,
- cdesc->aes_cmac);
-#else
ret = qat_sym_do_precomputes_ipsec_mb(ICP_QAT_HW_AUTH_ALGO_MD5,
authkey, authkeylen, cdesc->cd_cur_ptr, &state1_size,
cdesc->aes_cmac);
-#endif
if (ret) {
QAT_LOG(ERR, "(MD5)precompute failed");
return -EFAULT;
@@ -3197,6 +2828,11 @@ qat_security_session_create(void *dev,
sess_private_data, SECURITY_GET_SESS_PRIV_IOVA(sess));
if (ret != 0) {
QAT_LOG(ERR, "Failed to configure session parameters");
+#ifdef RTE_QAT_OPENSSL
+#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
+ ossl_legacy_provider_unload();
+#endif
+#endif
return ret;
}
--
2.43.0
^ permalink raw reply related
* RE: [PATCH 0/6] ip_frag: fix reassembly defects and add test
From: Morten Brørup @ 2026-06-19 13:24 UTC (permalink / raw)
To: Stephen Hemminger, dev
In-Reply-To: <20260616210656.464062-1-stephen@networkplumber.org>
> From: Stephen Hemminger [mailto:stephen@networkplumber.org]
> Sent: Tuesday, 16 June 2026 23.06
>
> The IP reassembly library tracks only a running byte total and reserved
> slots for the first and last fragments, with no coverage map. As a
> result
> it mishandles duplicate, overlapping, oversized, and misheadered
> fragments, and the IPv4 key is missing a field RFC 791 requires. There
> was also no functional test to catch any of it.
>
> These came out of reviewing a duplicate-fragment report on the list.
>
> Patches 1 and 2 are interdependent: the overlap discard relies on the
> duplicate handling so an exact duplicate is dropped on its own rather
> than discarding the whole datagram. The rest are independent.
>
> Patch 6 adds a functional test modeled on the Linux selftest
> ip_defrag.c.
> It passes on this series; with any single fix reverted the matching
> case
> fails.
With patch 2/6 fixed,
Series-acked-by: Morten Brørup <mb@smartsharesystems.com>
^ permalink raw reply
* RE: [PATCH 2/6] ip_frag: discard datagrams with overlapping fragments
From: Morten Brørup @ 2026-06-19 13:12 UTC (permalink / raw)
To: Stephen Hemminger, dev; +Cc: stable, Konstantin Ananyev
In-Reply-To: <20260616210656.464062-3-stephen@networkplumber.org>
> From: Stephen Hemminger [mailto:stephen@networkplumber.org]
> Sent: Tuesday, 16 June 2026 23.06
>
> Existing code does not handle overlapping fragments.
>
> RFC 8200 (IPv6) requires that on overlap all reassembly is abandoned
> andall received fragments are dropped. RFC 791 (IPv4) originally called
> fortrimming and rewriting, but Linux discards for IPv4 as well, since
> overlap has no legitimate use and is a known attack vector.
>
> Depends on the duplicate-tolerance change so that an exact duplicate is
> dropped on its own rather than discarding the whole datagram.
>
> Fixes: cc8f4d020c0b ("examples/ip_reassembly: initial import")
> Cc: stable@dpdk.org
>
> Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
> ---
> lib/ip_frag/ip_frag_internal.c | 34 ++++++++++++++++++++++++++--------
> 1 file changed, 26 insertions(+), 8 deletions(-)
>
> diff --git a/lib/ip_frag/ip_frag_internal.c
> b/lib/ip_frag/ip_frag_internal.c
> index 9a03ef995a..2505314a29 100644
> --- a/lib/ip_frag/ip_frag_internal.c
> +++ b/lib/ip_frag/ip_frag_internal.c
> @@ -92,16 +92,34 @@ ip_frag_process(struct ip_frag_pkt *fp, struct
> rte_ip_frag_death_row *dr,
> uint32_t i, idx;
>
> /*
> - * Discard an exact duplicate fragment. If a previously stored
> fragment
> - * already covers the same offset and length, this fragment
> carries no
> - * new data. Reassembly is tolerant of duplicates (RFC 791), so
> drop
> - * only this mbuf and keep the reassembly entry intact rather
> than
> - * treating it as an error. Fragments overlapping an existing one
> with
> - * different bounds are not handled here.
> + * Scan the fragments already collected for this datagram before
> + * storing the new one. The stored set is kept free of duplicates
> and
> + * overlaps, so a single pass is sufficient.
> */
> for (i = 0; i != fp->last_idx; i++) {
> - if (fp->frags[i].mb != NULL && fp->frags[i].ofs == ofs &&
> - fp->frags[i].len == len) {
> + if (fp->frags[i].mb == NULL)
> + continue;
> +
> + /*
> + * Exact duplicate: carries no new data. Reassembly
> tolerates
> + * duplicates (RFC 791), so drop only this mbuf and keep
> the
> + * entry.
> + */
> + if (fp->frags[i].ofs == ofs && fp->frags[i].len == len) {
> + IP_FRAG_MBUF2DR(dr, mb);
> + return NULL;
> + }
> +
> + /*
> + * Overlap with an existing fragment. Per RFC 8200 section
> 4.5
> + * (and RFC 5722) the datagram must be discarded; the same
> is
> + * applied to IPv4. Free all collected fragments, drop this
> one,
> + * and invalidate the entry.
> + */
> + if (ofs < fp->frags[i].ofs + fp->frags[i].len &&
> + fp->frags[i].ofs < ofs + len) {
This only catches fragments that are smaller than existing fragments, i.e. fit within one of the existing fragments.
It should be:
if ((ofs >= fp->frags[i].ofs &&
ofs < fp->frags[i].ofs + fp->frags[i].len) ||
(ofs + len >= fp->frags[i].ofs &&
ofs + len < fp->frags[i].ofs + fp->frags[i].len)) {
> + ip_frag_free(fp, dr);
> + ip_frag_key_invalidate(&fp->key);
> IP_FRAG_MBUF2DR(dr, mb);
> return NULL;
> }
> --
> 2.53.0
^ permalink raw reply
* [PATCH 18/18] dma/dpaa: add SG data validation and ERR050757 fix
From: Hemant Agrawal @ 2026-06-19 12:29 UTC (permalink / raw)
To: stephen, david.marchand, dev; +Cc: Gagandeep Singh
In-Reply-To: <20260619122922.3774666-1-hemant.agrawal@nxp.com>
From: Gagandeep Singh <g.singh@nxp.com>
Add scatter-gather (SG) support to the QDMA driver, enabled by default
via the s_sg_enable flag. Add optional data validation mode controlled
by the s_data_validation flag for debugging transfer correctness.
Add a workaround for hardware errata ERR050757: when
RTE_DMA_DPAA_ERRATA_ERR050757 is defined, configure the source frame
descriptor with stride settings (sss/ssd = FSL_QDMA_CMD_SS_ERR050757_LEN)
to force PCI read transactions to stay within the errata-safe length
limit, preventing data corruption on affected silicon.
Signed-off-by: Gagandeep Singh <g.singh@nxp.com>
---
drivers/dma/dpaa/dpaa_qdma.c | 99 +++++++++++++++++++++++++++---------
1 file changed, 75 insertions(+), 24 deletions(-)
diff --git a/drivers/dma/dpaa/dpaa_qdma.c b/drivers/dma/dpaa/dpaa_qdma.c
index bf2a373d70..ca615f8d8b 100644
--- a/drivers/dma/dpaa/dpaa_qdma.c
+++ b/drivers/dma/dpaa/dpaa_qdma.c
@@ -9,9 +9,14 @@
#include "dpaa_qdma.h"
#include "dpaa_qdma_logs.h"
+static int s_data_validation;
+static int s_hw_err_check;
+static int s_sg_enable = 1;
static uint32_t s_sg_max_entry_sz = 2000;
-static bool s_hw_err_check;
+#ifdef RTE_DMA_DPAA_ERRATA_ERR050757
+static int s_pci_read = 1;
+#endif
#define DPAA_DMA_ERROR_CHECK "dpaa_dma_err_check"
static inline void
@@ -112,7 +117,8 @@ dma_pool_alloc(char *nm, int size, int aligned, dma_addr_t *phy_addr)
if (!virt_addr)
return NULL;
- *phy_addr = rte_mem_virt2iova(virt_addr);
+ if (phy_addr)
+ *phy_addr = rte_mem_virt2iova(virt_addr);
return virt_addr;
}
@@ -392,6 +398,8 @@ fsl_qdma_data_validation(struct fsl_qdma_desc *desc[],
char err_msg[512];
int offset;
+ if (likely(!s_data_validation))
+ return;
offset = sprintf(err_msg, "Fatal TC%d/queue%d: ",
fsl_queue->block_id,
@@ -716,19 +724,21 @@ fsl_qdma_enqueue_desc_single(struct fsl_qdma_queue *fsl_queue,
ft = fsl_queue->ft[fsl_queue->ci];
#ifdef RTE_DMA_DPAA_ERRATA_ERR050757
- sdf = &ft->df.sdf;
- sdf->srttype = FSL_QDMA_CMD_RWTTYPE;
+ if (s_pci_read) {
+ sdf = &ft->df.sdf;
+ sdf->srttype = FSL_QDMA_CMD_RWTTYPE;
#ifdef RTE_DMA_DPAA_ERRATA_ERR050265
- sdf->prefetch = 1;
+ sdf->prefetch = 1;
#endif
- if (len > FSL_QDMA_CMD_SS_ERR050757_LEN) {
- sdf->ssen = 1;
- sdf->sss = FSL_QDMA_CMD_SS_ERR050757_LEN;
- sdf->ssd = FSL_QDMA_CMD_SS_ERR050757_LEN;
- } else {
- sdf->ssen = 0;
- sdf->sss = 0;
- sdf->ssd = 0;
+ if (len > FSL_QDMA_CMD_SS_ERR050757_LEN) {
+ sdf->ssen = 1;
+ sdf->sss = FSL_QDMA_CMD_SS_ERR050757_LEN;
+ sdf->ssd = FSL_QDMA_CMD_SS_ERR050757_LEN;
+ } else {
+ sdf->ssen = 0;
+ sdf->sss = 0;
+ sdf->ssd = 0;
+ }
}
#endif
csgf_src = &ft->desc_sbuf;
@@ -837,19 +847,21 @@ fsl_qdma_enqueue_desc_sg(struct fsl_qdma_queue *fsl_queue)
csgf_src->length = total_len;
csgf_dest->length = total_len;
#ifdef RTE_DMA_DPAA_ERRATA_ERR050757
- sdf = &ft->df.sdf;
- sdf->srttype = FSL_QDMA_CMD_RWTTYPE;
+ if (s_pci_read) {
+ sdf = &ft->df.sdf;
+ sdf->srttype = FSL_QDMA_CMD_RWTTYPE;
#ifdef RTE_DMA_DPAA_ERRATA_ERR050265
- sdf->prefetch = 1;
+ sdf->prefetch = 1;
#endif
- if (total_len > FSL_QDMA_CMD_SS_ERR050757_LEN) {
- sdf->ssen = 1;
- sdf->sss = FSL_QDMA_CMD_SS_ERR050757_LEN;
- sdf->ssd = FSL_QDMA_CMD_SS_ERR050757_LEN;
- } else {
- sdf->ssen = 0;
- sdf->sss = 0;
- sdf->ssd = 0;
+ if (total_len > FSL_QDMA_CMD_SS_ERR050757_LEN) {
+ sdf->ssen = 1;
+ sdf->sss = FSL_QDMA_CMD_SS_ERR050757_LEN;
+ sdf->ssd = FSL_QDMA_CMD_SS_ERR050757_LEN;
+ } else {
+ sdf->ssen = 0;
+ sdf->sss = 0;
+ sdf->ssd = 0;
+ }
}
#endif
ret = fsl_qdma_enqueue_desc_to_ring(fsl_queue, num);
@@ -888,6 +900,25 @@ fsl_qdma_enqueue_desc(struct fsl_qdma_queue *fsl_queue)
fsl_queue->pending_num = 0;
}
return ret;
+ } else if (!s_sg_enable) {
+ while (fsl_queue->pending_num > 0) {
+ ret = fsl_qdma_enqueue_desc_single(fsl_queue,
+ fsl_queue->pending_desc[start].dst,
+ fsl_queue->pending_desc[start].src,
+ fsl_queue->pending_desc[start].len);
+ if (!ret) {
+ start = (start + 1) &
+ (fsl_queue->pending_max - 1);
+ fsl_queue->pending_start = start;
+ fsl_queue->pending_num--;
+ } else {
+ DPAA_QDMA_ERR("Eq pending desc failed(%d)",
+ ret);
+ return -EIO;
+ }
+ }
+
+ return 0;
}
return fsl_qdma_enqueue_desc_sg(fsl_queue);
@@ -1344,6 +1375,26 @@ dpaa_qdma_init(struct rte_dma_dev *dmadev)
DPAA_QDMA_INFO("Enable DMA error checks");
}
+ if (getenv("DPAA_QDMA_DATA_VALIDATION"))
+ s_data_validation = 1;
+
+ if (getenv("DPAA_QDMA_HW_ERR_CHECK"))
+ s_hw_err_check = 1;
+
+ penv = getenv("DPAA_QDMA_SG_ENABLE");
+ if (penv)
+ s_sg_enable = atoi(penv);
+
+ penv = getenv("DPAA_QDMA_SG_MAX_ENTRY_SIZE");
+ if (penv)
+ s_sg_max_entry_sz = atoi(penv);
+
+#ifdef RTE_DMA_DPAA_ERRATA_ERR050757
+ penv = getenv("DPAA_QDMA_PCI_READ");
+ if (penv)
+ s_pci_read = atoi(penv);
+#endif
+
fsl_qdma->n_queues = QDMA_QUEUES * QDMA_BLOCKS;
fsl_qdma->num_blocks = QDMA_BLOCKS;
fsl_qdma->block_offset = QDMA_BLOCK_OFFSET;
--
2.25.1
^ permalink raw reply related
* [PATCH 17/18] mempool/dpaa: release bpid on driver destructor
From: Hemant Agrawal @ 2026-06-19 12:29 UTC (permalink / raw)
To: stephen, david.marchand, dev; +Cc: Jun Yang
In-Reply-To: <20260619122922.3774666-1-hemant.agrawal@nxp.com>
From: Jun Yang <jun.yang@nxp.com>
Track allocated BPIDs in a static per-BPID flag table and register a
driver destructor that releases any BPIDs still marked as in use at
process exit. This prevents BPID leaks when an application exits without
calling rte_mempool_free(). Also tune the per-lcore mempool cache flush
threshold to match the hardware bulk release size (DPAA_MBUF_MAX_ACQ_REL)
so that buffers are returned to HW in optimal burst sizes.
Signed-off-by: Jun Yang <jun.yang@nxp.com>
---
drivers/bus/dpaa/base/qbman/bman.c | 8 +++
drivers/bus/dpaa/dpaa_bus_base_symbols.c | 1 +
drivers/bus/dpaa/include/fsl_bman.h | 3 ++
drivers/mempool/dpaa/dpaa_mempool.c | 67 ++++++++++++++++++++++--
drivers/mempool/dpaa/dpaa_mempool.h | 3 +-
5 files changed, 78 insertions(+), 4 deletions(-)
diff --git a/drivers/bus/dpaa/base/qbman/bman.c b/drivers/bus/dpaa/base/qbman/bman.c
index 889d657052..d09266fa5b 100644
--- a/drivers/bus/dpaa/base/qbman/bman.c
+++ b/drivers/bus/dpaa/base/qbman/bman.c
@@ -237,6 +237,14 @@ void bman_free_pool(struct bman_pool *pool)
kfree(pool);
}
+void bman_free_bpid(u8 bpid, u32 flags)
+{
+ if (flags & BMAN_POOL_FLAG_THRESH)
+ bm_pool_set(bpid, zero_thresholds);
+ if (flags & BMAN_POOL_FLAG_DYNAMIC_BPID)
+ bman_release_bpid(bpid);
+}
+
const struct bman_pool_params *bman_get_params(const struct bman_pool *pool)
{
return &pool->params;
diff --git a/drivers/bus/dpaa/dpaa_bus_base_symbols.c b/drivers/bus/dpaa/dpaa_bus_base_symbols.c
index 514ab7b1f1..8bd1a9bc6e 100644
--- a/drivers/bus/dpaa/dpaa_bus_base_symbols.c
+++ b/drivers/bus/dpaa/dpaa_bus_base_symbols.c
@@ -46,6 +46,7 @@ RTE_EXPORT_INTERNAL_SYMBOL(netcfg_acquire)
RTE_EXPORT_INTERNAL_SYMBOL(netcfg_release)
RTE_EXPORT_INTERNAL_SYMBOL(bman_new_pool)
RTE_EXPORT_INTERNAL_SYMBOL(bman_free_pool)
+RTE_EXPORT_INTERNAL_SYMBOL(bman_free_bpid)
RTE_EXPORT_INTERNAL_SYMBOL(bman_get_params)
RTE_EXPORT_INTERNAL_SYMBOL(bman_release)
RTE_EXPORT_INTERNAL_SYMBOL(bman_acquire)
diff --git a/drivers/bus/dpaa/include/fsl_bman.h b/drivers/bus/dpaa/include/fsl_bman.h
index 67a7a09618..6079eedff5 100644
--- a/drivers/bus/dpaa/include/fsl_bman.h
+++ b/drivers/bus/dpaa/include/fsl_bman.h
@@ -317,6 +317,9 @@ struct bman_pool *bman_new_pool(const struct bman_pool_params *params);
__rte_internal
void bman_free_pool(struct bman_pool *pool);
+__rte_internal
+void bman_free_bpid(u8 bpid, u32 flags);
+
/**
* bman_get_params - Returns a pool object's parameters.
* @pool: the pool object
diff --git a/drivers/mempool/dpaa/dpaa_mempool.c b/drivers/mempool/dpaa/dpaa_mempool.c
index 3fdbcba646..210ea3bcf9 100644
--- a/drivers/mempool/dpaa/dpaa_mempool.c
+++ b/drivers/mempool/dpaa/dpaa_mempool.c
@@ -25,10 +25,22 @@
#include <rte_eal.h>
#include <rte_malloc.h>
#include <rte_ring.h>
+#include <rte_common.h>
#include <dpaa_mempool.h>
#include <dpaax_iova_table.h>
+struct dpaa_bpid_flag {
+ uint32_t flags;
+ int used;
+};
+
+/** Be referenced in destructor to release bpid allocated.
+ * Destructor can't access bman_pool from eal mem,
+ * we release ID with flag directly.
+ */
+static struct dpaa_bpid_flag s_dpaa_bpid_allocated_flag[DPAA_MAX_BPOOLS];
+
#define FMAN_ERRATA_BOUNDARY ((uint64_t)4096)
#define FMAN_ERRATA_BOUNDARY_MASK (~(FMAN_ERRATA_BOUNDARY - 1))
@@ -58,6 +70,8 @@ dpaa_mbuf_create_pool(struct rte_mempool *mp)
struct bman_pool_params params = {
.flags = BMAN_POOL_FLAG_DYNAMIC_BPID
};
+ unsigned int lcore_id;
+ struct rte_mempool_cache *cache;
MEMPOOL_INIT_FUNC_TRACE();
@@ -115,7 +129,7 @@ dpaa_mbuf_create_pool(struct rte_mempool *mp)
rte_dpaa_bpid_info[bpid].ptov_off = 0;
rte_dpaa_bpid_info[bpid].flags = 0;
- bp_info = rte_malloc(NULL,
+ bp_info = rte_zmalloc(NULL,
sizeof(struct dpaa_bp_info),
RTE_CACHE_LINE_SIZE);
if (!bp_info) {
@@ -127,6 +141,20 @@ dpaa_mbuf_create_pool(struct rte_mempool *mp)
rte_memcpy(bp_info, (void *)&rte_dpaa_bpid_info[bpid],
sizeof(struct dpaa_bp_info));
mp->pool_data = (void *)bp_info;
+ s_dpaa_bpid_allocated_flag[bpid].flags = params.flags;
+ s_dpaa_bpid_allocated_flag[bpid].used = true;
+ /* Update per core mempool cache threshold to optimal value which is
+ * number of buffers that can be released to HW buffer pool in
+ * a single API call.
+ */
+ for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
+ cache = &mp->local_cache[lcore_id];
+ DPAA_MEMPOOL_DEBUG("lCore %d: cache->flushthresh %d -> %d",
+ lcore_id, cache->flushthresh,
+ (uint32_t)(cache->size + DPAA_MBUF_MAX_ACQ_REL));
+ if (cache->flushthresh)
+ cache->flushthresh = cache->size + DPAA_MBUF_MAX_ACQ_REL;
+ }
DPAA_MEMPOOL_INFO("BMAN pool created for bpid =%d", bpid);
return 0;
@@ -136,6 +164,7 @@ static void
dpaa_mbuf_free_pool(struct rte_mempool *mp)
{
struct dpaa_bp_info *bp_info = DPAA_MEMPOOL_TO_POOL_INFO(mp);
+ uint16_t i;
MEMPOOL_INIT_FUNC_TRACE();
@@ -143,10 +172,25 @@ dpaa_mbuf_free_pool(struct rte_mempool *mp)
bman_free_pool(bp_info->bp);
DPAA_MEMPOOL_INFO("BMAN pool freed for bpid =%d",
bp_info->bpid);
- rte_free(mp->pool_data);
- bp_info->bp = NULL;
+ rte_dpaa_bpid_info[bp_info->bpid].mp = NULL;
+ rte_dpaa_bpid_info[bp_info->bpid].bp = NULL;
+ s_dpaa_bpid_allocated_flag[bp_info->bpid].used = false;
+ rte_free(bp_info);
mp->pool_data = NULL;
}
+
+ if (!rte_dpaa_bpid_info)
+ return;
+
+ for (i = 0; i < DPAA_MAX_BPOOLS; i++) {
+ if (rte_dpaa_bpid_info[i].mp)
+ break;
+ }
+
+ if (i == DPAA_MAX_BPOOLS) {
+ rte_free(rte_dpaa_bpid_info);
+ rte_dpaa_bpid_info = NULL;
+ }
}
static int
@@ -481,4 +525,21 @@ static const struct rte_mempool_ops dpaa_mpool_ops = {
.populate = dpaa_populate,
};
+#define RTE_PRIORITY_104 104
+
+RTE_FINI_PRIO(dpaa_mpool_finish, 104)
+{
+ uint16_t bpid;
+
+ for (bpid = 0; bpid < DPAA_MAX_BPOOLS; bpid++) {
+ if (s_dpaa_bpid_allocated_flag[bpid].used) {
+ bman_free_bpid(bpid, s_dpaa_bpid_allocated_flag[bpid].flags);
+ s_dpaa_bpid_allocated_flag[bpid].used = false;
+ }
+ }
+ /** The rte_dpaa_bpid_info and bman_pool from EAL mem have been released
+ * with EAL mem pool being destroyed.
+ */
+}
+
RTE_MEMPOOL_REGISTER_OPS(dpaa_mpool_ops);
diff --git a/drivers/mempool/dpaa/dpaa_mempool.h b/drivers/mempool/dpaa/dpaa_mempool.h
index 865b533b8f..d7ee49b557 100644
--- a/drivers/mempool/dpaa/dpaa_mempool.h
+++ b/drivers/mempool/dpaa/dpaa_mempool.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: BSD-3-Clause
*
- * Copyright 2017,2019,2024 -2025 NXP
+ * Copyright 2017,2019,2024 -2026 NXP
*
*/
#ifndef __DPAA_MEMPOOL_H__
@@ -24,6 +24,7 @@
/* total number of bpools on SoC */
#define DPAA_MAX_BPOOLS 256
+#define DPAA_INVALID_BPID DPAA_MAX_BPOOLS
/* Maximum release/acquire from BMAN */
#define DPAA_MBUF_MAX_ACQ_REL FSL_BM_BURST_MAX
--
2.25.1
^ permalink raw reply related
* [PATCH 17/18] drivers: release DPAA bpid on driver destructor
From: Hemant Agrawal @ 2026-06-19 12:29 UTC (permalink / raw)
To: stephen, david.marchand, dev; +Cc: Jun Yang
In-Reply-To: <20260619122922.3774666-1-hemant.agrawal@nxp.com>
From: Jun Yang <jun.yang@nxp.com>
Track allocated BPIDs in a static per-BPID flag table and register a
driver destructor that releases any BPIDs still marked as in use at
process exit. This prevents BPID leaks when an application exits without
calling rte_mempool_free(). Also tune the per-lcore mempool cache flush
threshold to match the hardware bulk release size (DPAA_MBUF_MAX_ACQ_REL)
so that buffers are returned to HW in optimal burst sizes.
Signed-off-by: Jun Yang <jun.yang@nxp.com>
---
drivers/bus/dpaa/base/qbman/bman.c | 8 +++
drivers/bus/dpaa/dpaa_bus_base_symbols.c | 1 +
drivers/bus/dpaa/include/fsl_bman.h | 3 ++
drivers/mempool/dpaa/dpaa_mempool.c | 67 ++++++++++++++++++++++--
drivers/mempool/dpaa/dpaa_mempool.h | 3 +-
5 files changed, 78 insertions(+), 4 deletions(-)
diff --git a/drivers/bus/dpaa/base/qbman/bman.c b/drivers/bus/dpaa/base/qbman/bman.c
index 889d657052..d09266fa5b 100644
--- a/drivers/bus/dpaa/base/qbman/bman.c
+++ b/drivers/bus/dpaa/base/qbman/bman.c
@@ -237,6 +237,14 @@ void bman_free_pool(struct bman_pool *pool)
kfree(pool);
}
+void bman_free_bpid(u8 bpid, u32 flags)
+{
+ if (flags & BMAN_POOL_FLAG_THRESH)
+ bm_pool_set(bpid, zero_thresholds);
+ if (flags & BMAN_POOL_FLAG_DYNAMIC_BPID)
+ bman_release_bpid(bpid);
+}
+
const struct bman_pool_params *bman_get_params(const struct bman_pool *pool)
{
return &pool->params;
diff --git a/drivers/bus/dpaa/dpaa_bus_base_symbols.c b/drivers/bus/dpaa/dpaa_bus_base_symbols.c
index 514ab7b1f1..8bd1a9bc6e 100644
--- a/drivers/bus/dpaa/dpaa_bus_base_symbols.c
+++ b/drivers/bus/dpaa/dpaa_bus_base_symbols.c
@@ -46,6 +46,7 @@ RTE_EXPORT_INTERNAL_SYMBOL(netcfg_acquire)
RTE_EXPORT_INTERNAL_SYMBOL(netcfg_release)
RTE_EXPORT_INTERNAL_SYMBOL(bman_new_pool)
RTE_EXPORT_INTERNAL_SYMBOL(bman_free_pool)
+RTE_EXPORT_INTERNAL_SYMBOL(bman_free_bpid)
RTE_EXPORT_INTERNAL_SYMBOL(bman_get_params)
RTE_EXPORT_INTERNAL_SYMBOL(bman_release)
RTE_EXPORT_INTERNAL_SYMBOL(bman_acquire)
diff --git a/drivers/bus/dpaa/include/fsl_bman.h b/drivers/bus/dpaa/include/fsl_bman.h
index 67a7a09618..6079eedff5 100644
--- a/drivers/bus/dpaa/include/fsl_bman.h
+++ b/drivers/bus/dpaa/include/fsl_bman.h
@@ -317,6 +317,9 @@ struct bman_pool *bman_new_pool(const struct bman_pool_params *params);
__rte_internal
void bman_free_pool(struct bman_pool *pool);
+__rte_internal
+void bman_free_bpid(u8 bpid, u32 flags);
+
/**
* bman_get_params - Returns a pool object's parameters.
* @pool: the pool object
diff --git a/drivers/mempool/dpaa/dpaa_mempool.c b/drivers/mempool/dpaa/dpaa_mempool.c
index 3fdbcba646..210ea3bcf9 100644
--- a/drivers/mempool/dpaa/dpaa_mempool.c
+++ b/drivers/mempool/dpaa/dpaa_mempool.c
@@ -25,10 +25,22 @@
#include <rte_eal.h>
#include <rte_malloc.h>
#include <rte_ring.h>
+#include <rte_common.h>
#include <dpaa_mempool.h>
#include <dpaax_iova_table.h>
+struct dpaa_bpid_flag {
+ uint32_t flags;
+ int used;
+};
+
+/** Be referenced in destructor to release bpid allocated.
+ * Destructor can't access bman_pool from eal mem,
+ * we release ID with flag directly.
+ */
+static struct dpaa_bpid_flag s_dpaa_bpid_allocated_flag[DPAA_MAX_BPOOLS];
+
#define FMAN_ERRATA_BOUNDARY ((uint64_t)4096)
#define FMAN_ERRATA_BOUNDARY_MASK (~(FMAN_ERRATA_BOUNDARY - 1))
@@ -58,6 +70,8 @@ dpaa_mbuf_create_pool(struct rte_mempool *mp)
struct bman_pool_params params = {
.flags = BMAN_POOL_FLAG_DYNAMIC_BPID
};
+ unsigned int lcore_id;
+ struct rte_mempool_cache *cache;
MEMPOOL_INIT_FUNC_TRACE();
@@ -115,7 +129,7 @@ dpaa_mbuf_create_pool(struct rte_mempool *mp)
rte_dpaa_bpid_info[bpid].ptov_off = 0;
rte_dpaa_bpid_info[bpid].flags = 0;
- bp_info = rte_malloc(NULL,
+ bp_info = rte_zmalloc(NULL,
sizeof(struct dpaa_bp_info),
RTE_CACHE_LINE_SIZE);
if (!bp_info) {
@@ -127,6 +141,20 @@ dpaa_mbuf_create_pool(struct rte_mempool *mp)
rte_memcpy(bp_info, (void *)&rte_dpaa_bpid_info[bpid],
sizeof(struct dpaa_bp_info));
mp->pool_data = (void *)bp_info;
+ s_dpaa_bpid_allocated_flag[bpid].flags = params.flags;
+ s_dpaa_bpid_allocated_flag[bpid].used = true;
+ /* Update per core mempool cache threshold to optimal value which is
+ * number of buffers that can be released to HW buffer pool in
+ * a single API call.
+ */
+ for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
+ cache = &mp->local_cache[lcore_id];
+ DPAA_MEMPOOL_DEBUG("lCore %d: cache->flushthresh %d -> %d",
+ lcore_id, cache->flushthresh,
+ (uint32_t)(cache->size + DPAA_MBUF_MAX_ACQ_REL));
+ if (cache->flushthresh)
+ cache->flushthresh = cache->size + DPAA_MBUF_MAX_ACQ_REL;
+ }
DPAA_MEMPOOL_INFO("BMAN pool created for bpid =%d", bpid);
return 0;
@@ -136,6 +164,7 @@ static void
dpaa_mbuf_free_pool(struct rte_mempool *mp)
{
struct dpaa_bp_info *bp_info = DPAA_MEMPOOL_TO_POOL_INFO(mp);
+ uint16_t i;
MEMPOOL_INIT_FUNC_TRACE();
@@ -143,10 +172,25 @@ dpaa_mbuf_free_pool(struct rte_mempool *mp)
bman_free_pool(bp_info->bp);
DPAA_MEMPOOL_INFO("BMAN pool freed for bpid =%d",
bp_info->bpid);
- rte_free(mp->pool_data);
- bp_info->bp = NULL;
+ rte_dpaa_bpid_info[bp_info->bpid].mp = NULL;
+ rte_dpaa_bpid_info[bp_info->bpid].bp = NULL;
+ s_dpaa_bpid_allocated_flag[bp_info->bpid].used = false;
+ rte_free(bp_info);
mp->pool_data = NULL;
}
+
+ if (!rte_dpaa_bpid_info)
+ return;
+
+ for (i = 0; i < DPAA_MAX_BPOOLS; i++) {
+ if (rte_dpaa_bpid_info[i].mp)
+ break;
+ }
+
+ if (i == DPAA_MAX_BPOOLS) {
+ rte_free(rte_dpaa_bpid_info);
+ rte_dpaa_bpid_info = NULL;
+ }
}
static int
@@ -481,4 +525,21 @@ static const struct rte_mempool_ops dpaa_mpool_ops = {
.populate = dpaa_populate,
};
+#define RTE_PRIORITY_104 104
+
+RTE_FINI_PRIO(dpaa_mpool_finish, 104)
+{
+ uint16_t bpid;
+
+ for (bpid = 0; bpid < DPAA_MAX_BPOOLS; bpid++) {
+ if (s_dpaa_bpid_allocated_flag[bpid].used) {
+ bman_free_bpid(bpid, s_dpaa_bpid_allocated_flag[bpid].flags);
+ s_dpaa_bpid_allocated_flag[bpid].used = false;
+ }
+ }
+ /** The rte_dpaa_bpid_info and bman_pool from EAL mem have been released
+ * with EAL mem pool being destroyed.
+ */
+}
+
RTE_MEMPOOL_REGISTER_OPS(dpaa_mpool_ops);
diff --git a/drivers/mempool/dpaa/dpaa_mempool.h b/drivers/mempool/dpaa/dpaa_mempool.h
index 865b533b8f..d7ee49b557 100644
--- a/drivers/mempool/dpaa/dpaa_mempool.h
+++ b/drivers/mempool/dpaa/dpaa_mempool.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: BSD-3-Clause
*
- * Copyright 2017,2019,2024 -2025 NXP
+ * Copyright 2017,2019,2024 -2026 NXP
*
*/
#ifndef __DPAA_MEMPOOL_H__
@@ -24,6 +24,7 @@
/* total number of bpools on SoC */
#define DPAA_MAX_BPOOLS 256
+#define DPAA_INVALID_BPID DPAA_MAX_BPOOLS
/* Maximum release/acquire from BMAN */
#define DPAA_MBUF_MAX_ACQ_REL FSL_BM_BURST_MAX
--
2.25.1
^ permalink raw reply related
* [PATCH 16/18] mempool/dpaa: optimize multi-entry buffer pool operations
From: Hemant Agrawal @ 2026-06-19 12:29 UTC (permalink / raw)
To: stephen, david.marchand, dev; +Cc: Jun Yang
In-Reply-To: <20260619122922.3774666-1-hemant.agrawal@nxp.com>
From: Jun Yang <jun.yang@nxp.com>
Replace the hardcoded buffer acquire count of 8 with the FSL_BM_BURST_MAX
constant when acquiring buffers from the buffer pool. Use a single
bm_hw_buf_desc structure for HW initialization of the first entry and copy
it to remaining entries, ensuring consistent HW descriptor state across
all entries in the pool.
Signed-off-by: Jun Yang <jun.yang@nxp.com>
---
drivers/bus/dpaa/base/qbman/bman.c | 49 ++++++-----------------------
drivers/bus/dpaa/include/fsl_bman.h | 46 ++++++++++++++++++++++-----
drivers/mempool/dpaa/dpaa_mempool.c | 8 ++---
3 files changed, 52 insertions(+), 51 deletions(-)
diff --git a/drivers/bus/dpaa/base/qbman/bman.c b/drivers/bus/dpaa/base/qbman/bman.c
index ee4232d0a0..889d657052 100644
--- a/drivers/bus/dpaa/base/qbman/bman.c
+++ b/drivers/bus/dpaa/base/qbman/bman.c
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
*
* Copyright 2008-2016 Freescale Semiconductor Inc.
- * Copyright 2017, 2024 NXP
+ * Copyright 2017, 2024-2026 NXP
*
*/
#include <rte_memcpy.h>
@@ -17,20 +17,6 @@
#define IRQNAME "BMan portal %d"
#define MAX_IRQNAME 16 /* big enough for "BMan portal %d" */
-
-#define MAX_U16 UINT16_MAX
-#define MAX_U32 UINT32_MAX
-#ifndef BIT_SIZE
-#define BIT_SIZE(t) (sizeof(t) * 8)
-#endif
-#define MAX_U48 \
- ((((uint64_t)MAX_U16) << BIT_SIZE(uint32_t)) | MAX_U32)
-#define HI16_OF_U48(x) \
- (((x) >> BIT_SIZE(rte_be32_t)) & MAX_U16)
-#define LO32_OF_U48(x) ((x) & MAX_U32)
-#define U48_BY_HI16_LO32(hi, lo) \
- (((hi) << BIT_SIZE(uint32_t)) | (lo))
-
struct bman_portal {
struct bm_portal p;
/* 2-element array. pools[0] is mask, pools[1] is snapshot. */
@@ -273,7 +259,7 @@ bman_release_fast(struct bman_pool *pool, const uint64_t *bufs,
struct bm_rcr_entry *r;
uint8_t i, avail;
uint64_t bpid = pool->params.bpid;
- struct bm_hw_buf_desc bm_bufs[FSL_BM_BURST_MAX];
+ struct bm_buffer bm_bufs[FSL_BM_BURST_MAX];
#ifdef RTE_LIBRTE_DPAA_HWDEBUG
if (!num || (num > FSL_BM_BURST_MAX))
@@ -290,19 +276,15 @@ bman_release_fast(struct bman_pool *pool, const uint64_t *bufs,
if (unlikely(!r))
return -EBUSY;
+ bm_bufs[0].be_desc.bpid = bpid;
+ for (i = 0; i < num; i++)
+ bm_buffer_set64_to_be(&bm_bufs[i], bufs[i]);
/*
* we can copy all but the first entry, as this can trigger badness
* with the valid-bit
*/
- bm_bufs[0].bpid = bpid;
- bm_bufs[0].hi_addr = cpu_to_be16(HI16_OF_U48(bufs[0]));
- bm_bufs[0].lo_addr = cpu_to_be32(LO32_OF_U48(bufs[0]));
- for (i = 1; i < num; i++) {
- bm_bufs[i].hi_addr = cpu_to_be16(HI16_OF_U48(bufs[i]));
- bm_bufs[i].lo_addr = cpu_to_be32(LO32_OF_U48(bufs[i]));
- }
-
- memcpy(r->bufs, bm_bufs, sizeof(struct bm_buffer) * num);
+ r->bufs[0].opaque = bm_bufs[0].opaque;
+ rte_memcpy(&r->bufs[1], &bm_bufs[1], sizeof(struct bm_buffer) * (num - 1));
bm_rcr_pvb_commit(&p->p, BM_RCR_VERB_CMD_BPID_SINGLE |
(num & BM_RCR_VERB_BUFCOUNT_MASK));
@@ -360,16 +342,6 @@ __rte_unused bman_extract_addr(struct bm_buffer *buf)
return buf->addr;
}
-static inline uint64_t
-bman_hw_extract_addr(struct bm_hw_buf_desc *buf)
-{
- uint64_t hi, lo;
-
- hi = be16_to_cpu(buf->hi_addr);
- lo = be32_to_cpu(buf->lo_addr);
- return U48_BY_HI16_LO32(hi, lo);
-}
-
RTE_EXPORT_INTERNAL_SYMBOL(bman_acquire_fast)
int
bman_acquire_fast(struct bman_pool *pool, uint64_t *bufs, uint8_t num)
@@ -378,7 +350,7 @@ bman_acquire_fast(struct bman_pool *pool, uint64_t *bufs, uint8_t num)
struct bm_mc_command *mcc;
struct bm_mc_result *mcr;
uint8_t i, rst;
- struct bm_hw_buf_desc bm_bufs[FSL_BM_BURST_MAX];
+ struct bm_buffer bm_bufs[FSL_BM_BURST_MAX];
#ifdef RTE_LIBRTE_DPAA_HWDEBUG
if (!num || (num > FSL_BM_BURST_MAX))
@@ -397,11 +369,10 @@ bman_acquire_fast(struct bman_pool *pool, uint64_t *bufs, uint8_t num)
if (unlikely(rst < 1 || rst > FSL_BM_BURST_MAX))
return -EINVAL;
- rte_memcpy(bm_bufs, mcr->acquire.bufs,
- sizeof(struct bm_buffer) * rst);
+ rte_memcpy(bm_bufs, mcr->acquire.bufs, sizeof(struct bm_buffer) * rst);
for (i = 0; i < rst; i++)
- bufs[i] = bman_hw_extract_addr(&bm_bufs[i]);
+ bufs[i] = bm_buffer_get64_from_be(&bm_bufs[i]);
return rst;
}
diff --git a/drivers/bus/dpaa/include/fsl_bman.h b/drivers/bus/dpaa/include/fsl_bman.h
index 2d24b89889..67a7a09618 100644
--- a/drivers/bus/dpaa/include/fsl_bman.h
+++ b/drivers/bus/dpaa/include/fsl_bman.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
*
* Copyright 2008-2012 Freescale Semiconductor, Inc.
- * Copyright 2024 NXP
+ * Copyright 2024-2026 NXP
*
*/
@@ -42,6 +42,13 @@ struct bm_mc_result; /* MC result */
* pool id specific to this buffer is needed (BM_RCR_VERB_CMD_BPID_MULTI,
* BM_MCC_VERB_ACQUIRE), the 'bpid' field is used.
*/
+struct __rte_packed_begin bm_hw_buf_desc {
+ uint8_t rsv;
+ uint8_t bpid;
+ rte_be16_t hi; /* High 16-bits of 48-bit address */
+ rte_be32_t lo; /* Low 32-bits of 48-bit address */
+} __rte_packed_end;
+
struct __rte_aligned(8) bm_buffer {
union {
struct {
@@ -66,17 +73,11 @@ struct __rte_aligned(8) bm_buffer {
u64 __notaddress:16;
#endif
};
+ struct bm_hw_buf_desc be_desc;
u64 opaque;
};
};
-struct __rte_packed_begin bm_hw_buf_desc {
- uint8_t rsv;
- uint8_t bpid;
- rte_be16_t hi_addr; /* High 16-bits of 48-bit address */
- rte_be32_t lo_addr; /* Low 32-bits of 48-bit address */
-} __rte_packed_end;
-
static inline u64 bm_buffer_get64(const struct bm_buffer *buf)
{
return buf->addr;
@@ -87,6 +88,17 @@ static inline dma_addr_t bm_buf_addr(const struct bm_buffer *buf)
return (dma_addr_t)buf->addr;
}
+#ifndef BIT_SIZE
+#define BIT_SIZE(t) (sizeof(t) * 8)
+#endif
+#define MAX_U48 \
+ ((((uint64_t)UINT16_MAX) << BIT_SIZE(uint32_t)) | UINT32_MAX)
+#define HI16_OF_U48(x) \
+ (((x) >> BIT_SIZE(uint32_t)) & UINT16_MAX)
+#define LO32_OF_U48(x) ((x) & UINT32_MAX)
+#define U48_BY_HI16_LO32(hi, lo) \
+ (((hi) << BIT_SIZE(uint32_t)) | (lo))
+
#define bm_buffer_set64(buf, v) \
do { \
struct bm_buffer *__buf931 = (buf); \
@@ -94,6 +106,24 @@ static inline dma_addr_t bm_buf_addr(const struct bm_buffer *buf)
__buf931->lo = lower_32_bits(v); \
} while (0)
+#define bm_buffer_set64_to_be(buf, v) \
+ do { \
+ struct bm_buffer *__buf931 = (buf); \
+ \
+ __buf931->be_desc.hi = cpu_to_be16(HI16_OF_U48(v)); \
+ __buf931->be_desc.lo = cpu_to_be32(LO32_OF_U48(v)); \
+ } while (0)
+
+#define bm_buffer_get64_from_be(buf) \
+ ({ \
+ uint64_t hi, lo; \
+ struct bm_buffer *__buf931 = (buf); \
+ \
+ hi = be16_to_cpu(__buf931->be_desc.hi); \
+ lo = be32_to_cpu(__buf931->be_desc.lo); \
+ U48_BY_HI16_LO32(hi, lo); \
+ })
+
#define FSL_BM_BURST_MAX 8
/* See 1.5.3.5.4: "Release Command" */
diff --git a/drivers/mempool/dpaa/dpaa_mempool.c b/drivers/mempool/dpaa/dpaa_mempool.c
index 2f8555a026..3fdbcba646 100644
--- a/drivers/mempool/dpaa/dpaa_mempool.c
+++ b/drivers/mempool/dpaa/dpaa_mempool.c
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: BSD-3-Clause
*
- * Copyright 2017,2019,2023-2025 NXP
+ * Copyright 2017,2019,2023-2026 NXP
*
*/
@@ -50,7 +50,7 @@ static int
dpaa_mbuf_create_pool(struct rte_mempool *mp)
{
struct bman_pool *bp;
- struct bm_buffer bufs[8];
+ struct bm_buffer bufs[FSL_BM_BURST_MAX];
struct dpaa_bp_info *bp_info;
uint8_t bpid;
int num_bufs = 0, ret = 0;
@@ -83,8 +83,8 @@ dpaa_mbuf_create_pool(struct rte_mempool *mp)
* then in 1s for the remainder.
*/
if (ret != 1)
- ret = bman_acquire(bp, bufs, 8, 0);
- if (ret < 8)
+ ret = bman_acquire(bp, bufs, FSL_BM_BURST_MAX, 0);
+ if (ret < FSL_BM_BURST_MAX)
ret = bman_acquire(bp, bufs, 1, 0);
if (ret > 0)
num_bufs += ret;
--
2.25.1
^ permalink raw reply related
* [PATCH 16/18] drivers: optimize DPAA multi-entry buffer pool operations
From: Hemant Agrawal @ 2026-06-19 12:29 UTC (permalink / raw)
To: stephen, david.marchand, dev; +Cc: Jun Yang
In-Reply-To: <20260619122922.3774666-1-hemant.agrawal@nxp.com>
From: Jun Yang <jun.yang@nxp.com>
Replace the hardcoded buffer acquire count of 8 with the FSL_BM_BURST_MAX
constant when acquiring buffers from the buffer pool. Use a single
bm_hw_buf_desc structure for HW initialization of the first entry and copy
it to remaining entries, ensuring consistent HW descriptor state across
all entries in the pool.
Signed-off-by: Jun Yang <jun.yang@nxp.com>
---
drivers/bus/dpaa/base/qbman/bman.c | 49 ++++++-----------------------
drivers/bus/dpaa/include/fsl_bman.h | 46 ++++++++++++++++++++++-----
drivers/mempool/dpaa/dpaa_mempool.c | 8 ++---
3 files changed, 52 insertions(+), 51 deletions(-)
diff --git a/drivers/bus/dpaa/base/qbman/bman.c b/drivers/bus/dpaa/base/qbman/bman.c
index ee4232d0a0..889d657052 100644
--- a/drivers/bus/dpaa/base/qbman/bman.c
+++ b/drivers/bus/dpaa/base/qbman/bman.c
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
*
* Copyright 2008-2016 Freescale Semiconductor Inc.
- * Copyright 2017, 2024 NXP
+ * Copyright 2017, 2024-2026 NXP
*
*/
#include <rte_memcpy.h>
@@ -17,20 +17,6 @@
#define IRQNAME "BMan portal %d"
#define MAX_IRQNAME 16 /* big enough for "BMan portal %d" */
-
-#define MAX_U16 UINT16_MAX
-#define MAX_U32 UINT32_MAX
-#ifndef BIT_SIZE
-#define BIT_SIZE(t) (sizeof(t) * 8)
-#endif
-#define MAX_U48 \
- ((((uint64_t)MAX_U16) << BIT_SIZE(uint32_t)) | MAX_U32)
-#define HI16_OF_U48(x) \
- (((x) >> BIT_SIZE(rte_be32_t)) & MAX_U16)
-#define LO32_OF_U48(x) ((x) & MAX_U32)
-#define U48_BY_HI16_LO32(hi, lo) \
- (((hi) << BIT_SIZE(uint32_t)) | (lo))
-
struct bman_portal {
struct bm_portal p;
/* 2-element array. pools[0] is mask, pools[1] is snapshot. */
@@ -273,7 +259,7 @@ bman_release_fast(struct bman_pool *pool, const uint64_t *bufs,
struct bm_rcr_entry *r;
uint8_t i, avail;
uint64_t bpid = pool->params.bpid;
- struct bm_hw_buf_desc bm_bufs[FSL_BM_BURST_MAX];
+ struct bm_buffer bm_bufs[FSL_BM_BURST_MAX];
#ifdef RTE_LIBRTE_DPAA_HWDEBUG
if (!num || (num > FSL_BM_BURST_MAX))
@@ -290,19 +276,15 @@ bman_release_fast(struct bman_pool *pool, const uint64_t *bufs,
if (unlikely(!r))
return -EBUSY;
+ bm_bufs[0].be_desc.bpid = bpid;
+ for (i = 0; i < num; i++)
+ bm_buffer_set64_to_be(&bm_bufs[i], bufs[i]);
/*
* we can copy all but the first entry, as this can trigger badness
* with the valid-bit
*/
- bm_bufs[0].bpid = bpid;
- bm_bufs[0].hi_addr = cpu_to_be16(HI16_OF_U48(bufs[0]));
- bm_bufs[0].lo_addr = cpu_to_be32(LO32_OF_U48(bufs[0]));
- for (i = 1; i < num; i++) {
- bm_bufs[i].hi_addr = cpu_to_be16(HI16_OF_U48(bufs[i]));
- bm_bufs[i].lo_addr = cpu_to_be32(LO32_OF_U48(bufs[i]));
- }
-
- memcpy(r->bufs, bm_bufs, sizeof(struct bm_buffer) * num);
+ r->bufs[0].opaque = bm_bufs[0].opaque;
+ rte_memcpy(&r->bufs[1], &bm_bufs[1], sizeof(struct bm_buffer) * (num - 1));
bm_rcr_pvb_commit(&p->p, BM_RCR_VERB_CMD_BPID_SINGLE |
(num & BM_RCR_VERB_BUFCOUNT_MASK));
@@ -360,16 +342,6 @@ __rte_unused bman_extract_addr(struct bm_buffer *buf)
return buf->addr;
}
-static inline uint64_t
-bman_hw_extract_addr(struct bm_hw_buf_desc *buf)
-{
- uint64_t hi, lo;
-
- hi = be16_to_cpu(buf->hi_addr);
- lo = be32_to_cpu(buf->lo_addr);
- return U48_BY_HI16_LO32(hi, lo);
-}
-
RTE_EXPORT_INTERNAL_SYMBOL(bman_acquire_fast)
int
bman_acquire_fast(struct bman_pool *pool, uint64_t *bufs, uint8_t num)
@@ -378,7 +350,7 @@ bman_acquire_fast(struct bman_pool *pool, uint64_t *bufs, uint8_t num)
struct bm_mc_command *mcc;
struct bm_mc_result *mcr;
uint8_t i, rst;
- struct bm_hw_buf_desc bm_bufs[FSL_BM_BURST_MAX];
+ struct bm_buffer bm_bufs[FSL_BM_BURST_MAX];
#ifdef RTE_LIBRTE_DPAA_HWDEBUG
if (!num || (num > FSL_BM_BURST_MAX))
@@ -397,11 +369,10 @@ bman_acquire_fast(struct bman_pool *pool, uint64_t *bufs, uint8_t num)
if (unlikely(rst < 1 || rst > FSL_BM_BURST_MAX))
return -EINVAL;
- rte_memcpy(bm_bufs, mcr->acquire.bufs,
- sizeof(struct bm_buffer) * rst);
+ rte_memcpy(bm_bufs, mcr->acquire.bufs, sizeof(struct bm_buffer) * rst);
for (i = 0; i < rst; i++)
- bufs[i] = bman_hw_extract_addr(&bm_bufs[i]);
+ bufs[i] = bm_buffer_get64_from_be(&bm_bufs[i]);
return rst;
}
diff --git a/drivers/bus/dpaa/include/fsl_bman.h b/drivers/bus/dpaa/include/fsl_bman.h
index 2d24b89889..67a7a09618 100644
--- a/drivers/bus/dpaa/include/fsl_bman.h
+++ b/drivers/bus/dpaa/include/fsl_bman.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
*
* Copyright 2008-2012 Freescale Semiconductor, Inc.
- * Copyright 2024 NXP
+ * Copyright 2024-2026 NXP
*
*/
@@ -42,6 +42,13 @@ struct bm_mc_result; /* MC result */
* pool id specific to this buffer is needed (BM_RCR_VERB_CMD_BPID_MULTI,
* BM_MCC_VERB_ACQUIRE), the 'bpid' field is used.
*/
+struct __rte_packed_begin bm_hw_buf_desc {
+ uint8_t rsv;
+ uint8_t bpid;
+ rte_be16_t hi; /* High 16-bits of 48-bit address */
+ rte_be32_t lo; /* Low 32-bits of 48-bit address */
+} __rte_packed_end;
+
struct __rte_aligned(8) bm_buffer {
union {
struct {
@@ -66,17 +73,11 @@ struct __rte_aligned(8) bm_buffer {
u64 __notaddress:16;
#endif
};
+ struct bm_hw_buf_desc be_desc;
u64 opaque;
};
};
-struct __rte_packed_begin bm_hw_buf_desc {
- uint8_t rsv;
- uint8_t bpid;
- rte_be16_t hi_addr; /* High 16-bits of 48-bit address */
- rte_be32_t lo_addr; /* Low 32-bits of 48-bit address */
-} __rte_packed_end;
-
static inline u64 bm_buffer_get64(const struct bm_buffer *buf)
{
return buf->addr;
@@ -87,6 +88,17 @@ static inline dma_addr_t bm_buf_addr(const struct bm_buffer *buf)
return (dma_addr_t)buf->addr;
}
+#ifndef BIT_SIZE
+#define BIT_SIZE(t) (sizeof(t) * 8)
+#endif
+#define MAX_U48 \
+ ((((uint64_t)UINT16_MAX) << BIT_SIZE(uint32_t)) | UINT32_MAX)
+#define HI16_OF_U48(x) \
+ (((x) >> BIT_SIZE(uint32_t)) & UINT16_MAX)
+#define LO32_OF_U48(x) ((x) & UINT32_MAX)
+#define U48_BY_HI16_LO32(hi, lo) \
+ (((hi) << BIT_SIZE(uint32_t)) | (lo))
+
#define bm_buffer_set64(buf, v) \
do { \
struct bm_buffer *__buf931 = (buf); \
@@ -94,6 +106,24 @@ static inline dma_addr_t bm_buf_addr(const struct bm_buffer *buf)
__buf931->lo = lower_32_bits(v); \
} while (0)
+#define bm_buffer_set64_to_be(buf, v) \
+ do { \
+ struct bm_buffer *__buf931 = (buf); \
+ \
+ __buf931->be_desc.hi = cpu_to_be16(HI16_OF_U48(v)); \
+ __buf931->be_desc.lo = cpu_to_be32(LO32_OF_U48(v)); \
+ } while (0)
+
+#define bm_buffer_get64_from_be(buf) \
+ ({ \
+ uint64_t hi, lo; \
+ struct bm_buffer *__buf931 = (buf); \
+ \
+ hi = be16_to_cpu(__buf931->be_desc.hi); \
+ lo = be32_to_cpu(__buf931->be_desc.lo); \
+ U48_BY_HI16_LO32(hi, lo); \
+ })
+
#define FSL_BM_BURST_MAX 8
/* See 1.5.3.5.4: "Release Command" */
diff --git a/drivers/mempool/dpaa/dpaa_mempool.c b/drivers/mempool/dpaa/dpaa_mempool.c
index 2f8555a026..3fdbcba646 100644
--- a/drivers/mempool/dpaa/dpaa_mempool.c
+++ b/drivers/mempool/dpaa/dpaa_mempool.c
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: BSD-3-Clause
*
- * Copyright 2017,2019,2023-2025 NXP
+ * Copyright 2017,2019,2023-2026 NXP
*
*/
@@ -50,7 +50,7 @@ static int
dpaa_mbuf_create_pool(struct rte_mempool *mp)
{
struct bman_pool *bp;
- struct bm_buffer bufs[8];
+ struct bm_buffer bufs[FSL_BM_BURST_MAX];
struct dpaa_bp_info *bp_info;
uint8_t bpid;
int num_bufs = 0, ret = 0;
@@ -83,8 +83,8 @@ dpaa_mbuf_create_pool(struct rte_mempool *mp)
* then in 1s for the remainder.
*/
if (ret != 1)
- ret = bman_acquire(bp, bufs, 8, 0);
- if (ret < 8)
+ ret = bman_acquire(bp, bufs, FSL_BM_BURST_MAX, 0);
+ if (ret < FSL_BM_BURST_MAX)
ret = bman_acquire(bp, bufs, 1, 0);
if (ret > 0)
num_bufs += ret;
--
2.25.1
^ permalink raw reply related
* [PATCH 15/18] net/dpaa: report error on using deferred start
From: Hemant Agrawal @ 2026-06-19 12:29 UTC (permalink / raw)
To: stephen, david.marchand, dev
In-Reply-To: <20260619122922.3774666-1-hemant.agrawal@nxp.com>
This patch add support to report on error
for rx and tx deferred start config
Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com>
---
drivers/net/dpaa/dpaa_ethdev.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/drivers/net/dpaa/dpaa_ethdev.c b/drivers/net/dpaa/dpaa_ethdev.c
index a223703421..c884d7e5e4 100644
--- a/drivers/net/dpaa/dpaa_ethdev.c
+++ b/drivers/net/dpaa/dpaa_ethdev.c
@@ -1171,6 +1171,12 @@ int dpaa_eth_rx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx,
rxq->nb_desc = UINT16_MAX;
rxq->offloads = rx_conf->offloads;
+ /* Rx deferred start is not supported */
+ if (rx_conf->rx_deferred_start) {
+ DPAA_PMD_ERR("%p:Rx deferred start not supported", (void *)dev);
+ return -EINVAL;
+ }
+
DPAA_PMD_INFO("Rx queue setup for queue index: %d fq_id (0x%x)",
queue_idx, rxq->fqid);
@@ -1477,6 +1483,12 @@ int dpaa_eth_tx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx,
txq->nb_desc = UINT16_MAX;
txq->offloads = tx_conf->offloads;
+ /* Tx deferred start is not supported */
+ if (tx_conf->tx_deferred_start) {
+ DPAA_PMD_ERR("%p:Tx deferred start not supported", (void *)dev);
+ return -EINVAL;
+ }
+
if (queue_idx >= dev->data->nb_tx_queues) {
rte_errno = EOVERFLOW;
DPAA_PMD_ERR("%p: queue index out of range (%u >= %u)",
--
2.25.1
^ permalink raw reply related
* [PATCH 14/18] net/dpaa: optimize FMC MAC type parsing
From: Hemant Agrawal @ 2026-06-19 12:29 UTC (permalink / raw)
To: stephen, david.marchand, dev; +Cc: Jun Yang
In-Reply-To: <20260619122922.3774666-1-hemant.agrawal@nxp.com>
From: Jun Yang <jun.yang@nxp.com>
For ls104xa, MAC9 and MAC10's type could be either of 10G/2.5G/1G
up to serdes configuration, MAC index should be identified by
port name instead of parsing MAC type and port number.
Signed-off-by: Jun Yang <jun.yang@nxp.com>
---
drivers/net/dpaa/dpaa_fmc.c | 73 ++++++++++++++++++++++---------------
1 file changed, 44 insertions(+), 29 deletions(-)
diff --git a/drivers/net/dpaa/dpaa_fmc.c b/drivers/net/dpaa/dpaa_fmc.c
index 7dc42f6e23..3034f534a5 100644
--- a/drivers/net/dpaa/dpaa_fmc.c
+++ b/drivers/net/dpaa/dpaa_fmc.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright 2017-2023 NXP
+ * Copyright 2017-2026 NXP
*/
/* System headers */
@@ -204,6 +204,36 @@ struct fmc_model_t {
struct fmc_model_t *g_fmc_model;
+static int
+dpaa_port_fmc_get_idx_from_name(const char *name)
+{
+ const char *found;
+ int idx_str_start = -1, idx;
+
+#define FMC_PORT_NAME_MAC "MAC/"
+#define FMC_PORT_NAME_OFFLINE "OFFLINE/"
+
+ found = strstr(name, FMC_PORT_NAME_MAC);
+ if (!found) {
+ found = strstr(name, FMC_PORT_NAME_OFFLINE);
+ if (found)
+ idx_str_start = strlen(FMC_PORT_NAME_OFFLINE);
+ } else {
+ idx_str_start = strlen(FMC_PORT_NAME_MAC);
+ }
+
+ if (!found) {
+ DPAA_PMD_ERR("Invalid fmc port name: %s", name);
+ return -EINVAL;
+ }
+
+ idx = atoi(&found[idx_str_start]);
+
+ DPAA_PMD_INFO("MAC index of %s is %d", name, idx);
+
+ return idx;
+}
+
static int
dpaa_port_fmc_port_parse(struct fman_if *fif,
const struct fmc_model_t *fmc_model,
@@ -211,7 +241,10 @@ dpaa_port_fmc_port_parse(struct fman_if *fif,
{
int current_port = fmc_model->apply_order[apply_idx].index;
const fmc_port *pport = &fmc_model->port[current_port];
- uint32_t num;
+ int num = dpaa_port_fmc_get_idx_from_name(pport->name);
+
+ if (num < 0)
+ return num;
if (pport->type == e_FM_PORT_TYPE_OH_OFFLINE_PARSING &&
pport->number == fif->mac_idx &&
@@ -219,40 +252,22 @@ dpaa_port_fmc_port_parse(struct fman_if *fif,
fif->mac_type == fman_onic))
return current_port;
- if (fif->mac_type == fman_mac_1g) {
- if (pport->type != e_FM_PORT_TYPE_RX)
- return -ENODEV;
- num = pport->number + DPAA_1G_MAC_START_IDX;
- if (fif->mac_idx == num)
- return current_port;
-
+ if (fif->mac_type == fman_mac_1g &&
+ pport->type != e_FM_PORT_TYPE_RX)
return -ENODEV;
- }
-
- if (fif->mac_type == fman_mac_2_5g) {
- if (pport->type != e_FM_PORT_TYPE_RX_2_5G)
- return -ENODEV;
- num = pport->number + DPAA_2_5G_MAC_START_IDX;
- if (fif->mac_idx == num)
- return current_port;
+ if (fif->mac_type == fman_mac_2_5g &&
+ pport->type != e_FM_PORT_TYPE_RX_2_5G)
return -ENODEV;
- }
-
- if (fif->mac_type == fman_mac_10g) {
- if (pport->type != e_FM_PORT_TYPE_RX_10G)
- return -ENODEV;
- num = pport->number + DPAA_10G_MAC_START_IDX;
- if (fif->mac_idx == num)
- return current_port;
+ if (fif->mac_type == fman_mac_10g &&
+ pport->type != e_FM_PORT_TYPE_RX_10G)
return -ENODEV;
- }
- DPAA_PMD_ERR("Invalid MAC(mac_idx=%d) type(%d)",
- fif->mac_idx, fif->mac_type);
+ if (fif->mac_idx == num)
+ return current_port;
- return -EINVAL;
+ return -ENODEV;
}
static int
--
2.25.1
^ permalink raw reply related
* [PATCH 13/18] bus/dpaa: improve log macro and fix bus detection
From: Hemant Agrawal @ 2026-06-19 12:29 UTC (permalink / raw)
To: stephen, david.marchand, dev
In-Reply-To: <20260619122922.3774666-1-hemant.agrawal@nxp.com>
Replace DPAA_BUS_LOG(LEVEL, ...) calls with shorthand macros
(DPAA_BUS_INFO, DPAA_BUS_ERR, DPAA_BUS_WARN, DPAA_BUS_DEBUG) for
consistency across the driver.
Move bus detection (sysfs path check), portal key creation and
dpaa_bus.detected guard into dpaa_bus_dev_compare() so that bus
probe is properly gated on hardware presence.
Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com>
---
drivers/bus/dpaa/base/fman/fman.c | 9 ++++----
drivers/bus/dpaa/dpaa_bus.c | 35 ++++++++++++++++++++++++-------
2 files changed, 32 insertions(+), 12 deletions(-)
diff --git a/drivers/bus/dpaa/base/fman/fman.c b/drivers/bus/dpaa/base/fman/fman.c
index 55f466d751..67f77265ca 100644
--- a/drivers/bus/dpaa/base/fman/fman.c
+++ b/drivers/bus/dpaa/base/fman/fman.c
@@ -119,7 +119,7 @@ _fman_init(const struct device_node *fman_node, int fd)
ip_rev_1 = in_be32((uint8_t *)fman->ccsr_vir + FMAN_IP_REV_1);
fman->ip_rev = ip_rev_1 >> FMAN_IP_REV_1_MAJOR_SHIFT;
fman->ip_rev &= FMAN_IP_REV_1_MAJOR_MASK;
- DPAA_BUS_LOG(NOTICE, "FMan version is 0x%02x", fman->ip_rev);
+ DPAA_BUS_INFO("FMan version is 0x%02x", fman->ip_rev);
if (fman->ip_rev >= FMAN_V3) {
/*
@@ -795,8 +795,7 @@ fman_if_init(const struct device_node *dpa_node, int fd)
fman_if_vsp_init(__if);
/* Parsing of the network interface is complete, add it to the list */
- DPAA_BUS_LOG(DEBUG, "Found %s, Tx Channel = %x, FMAN = %x,"
- "Port ID = %x",
+ DPAA_BUS_DEBUG("Found %s, Tx Channel = %x, FMAN = %x, Port ID = %x",
dname, __if->__if.tx_channel_id, __if->__if.fman->idx,
__if->__if.mac_idx);
@@ -1109,14 +1108,14 @@ fman_init(void)
fd = open(FMAN_DEVICE_PATH, O_RDWR);
if (unlikely(fd < 0)) {
- DPAA_BUS_LOG(ERR, "Unable to open %s: %s", FMAN_DEVICE_PATH, strerror(errno));
+ DPAA_BUS_ERR("Unable to open %s: %s", FMAN_DEVICE_PATH, strerror(errno));
return fd;
}
fman_ccsr_map_fd = fd;
parent_node = of_find_compatible_node(NULL, NULL, "fsl,dpaa");
if (!parent_node) {
- DPAA_BUS_LOG(ERR, "Unable to find fsl,dpaa node");
+ DPAA_BUS_ERR("Unable to find fsl,dpaa node");
return -ENODEV;
}
diff --git a/drivers/bus/dpaa/dpaa_bus.c b/drivers/bus/dpaa/dpaa_bus.c
index 02a8c5882e..79d0b6311a 100644
--- a/drivers/bus/dpaa/dpaa_bus.c
+++ b/drivers/bus/dpaa/dpaa_bus.c
@@ -560,13 +560,37 @@ rte_dpaa_bus_parse(const char *name, void *out)
static int
dpaa_bus_dev_compare(const char *name1, const char *name2)
{
+ int ret = 0;
char devname1[32], devname2[32];
if (rte_dpaa_bus_parse(name1, devname1) != 0 ||
rte_dpaa_bus_parse(name2, devname2) != 0)
return 1;
- return strncmp(devname1, devname2, sizeof(devname1));
+#define DPAA_DEV_PATH1 "/sys/devices/platform/soc/soc:fsl,dpaa"
+#define DPAA_DEV_PATH2 "/sys/devices/platform/fsl,dpaa"
+ if ((access(DPAA_DEV_PATH1, F_OK) != 0) &&
+ (access(DPAA_DEV_PATH2, F_OK) != 0)) {
+ DPAA_BUS_DEBUG("DPAA Bus not present. Skipping.");
+ return 0;
+ }
+
+ if (dpaa_bus.detected)
+ return 0;
+
+ dpaa_bus.detected = 1;
+
+ /* create the key, supplying a function that'll be invoked
+ * when a portal affined thread will be deleted.
+ */
+ ret = pthread_key_create(&dpaa_portal_key, dpaa_portal_finish);
+ if (ret) {
+ DPAA_BUS_DEBUG("Unable to create pthread key. (%d)", ret);
+ dpaa_clean_device_list();
+ return ret;
+ }
+
+ return 0;
}
/* register a dpaa bus based dpaa driver */
@@ -667,8 +691,6 @@ static int rte_dpaa_setup_intr(struct rte_intr_handle *intr_handle)
return 0;
}
-#define DPAA_DEV_PATH1 "/sys/devices/platform/soc/soc:fsl,dpaa"
-#define DPAA_DEV_PATH2 "/sys/devices/platform/fsl,dpaa"
static int
rte_dpaa_bus_scan(void)
@@ -715,12 +737,11 @@ rte_dpaa_bus_scan(void)
dpaa_bus.svr_ver = 0;
}
if (dpaa_bus.svr_ver == SVR_LS1046A_FAMILY) {
- DPAA_BUS_LOG(INFO, "This is LS1046A family SoC.");
+ DPAA_BUS_INFO("This is LS1046A family SoC.");
} else if (dpaa_bus.svr_ver == SVR_LS1043A_FAMILY) {
- DPAA_BUS_LOG(INFO, "This is LS1043A family SoC.");
+ DPAA_BUS_INFO("This is LS1043A family SoC.");
} else {
- DPAA_BUS_LOG(WARNING,
- "This is Unknown(%08x) DPAA1 family SoC.",
+ DPAA_BUS_WARN("This is Unknown(%08x) DPAA1 family SoC.",
dpaa_bus.svr_ver);
}
--
2.25.1
^ permalink raw reply related
* [PATCH 12/18] net/dpaa: optimize FM deconfig
From: Hemant Agrawal @ 2026-06-19 12:29 UTC (permalink / raw)
To: stephen, david.marchand, dev
In-Reply-To: <20260619122922.3774666-1-hemant.agrawal@nxp.com>
Consolidate FM deconfiguration to avoid duplicate calls.
Move the fm_deconfig call to a single location and remove
redundant checks in the device close path.
Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com>
---
drivers/net/dpaa/dpaa_ethdev.c | 37 +++++++++++++++++++++++++---------
drivers/net/dpaa/dpaa_flow.c | 9 +++++----
2 files changed, 32 insertions(+), 14 deletions(-)
diff --git a/drivers/net/dpaa/dpaa_ethdev.c b/drivers/net/dpaa/dpaa_ethdev.c
index 3b66fbe18a..a223703421 100644
--- a/drivers/net/dpaa/dpaa_ethdev.c
+++ b/drivers/net/dpaa/dpaa_ethdev.c
@@ -526,10 +526,12 @@ static int dpaa_eth_dev_close(struct rte_eth_dev *dev)
/* DPAA FM deconfig */
if (!(default_q || fmc_q)) {
- ret = dpaa_fm_deconfig(dpaa_intf, dev->process_private);
- if (ret) {
- DPAA_PMD_WARN("%s: FM deconfig failed(%d)",
- dev->data->name, ret);
+ if (dpaa_intf->port_handle) {
+ ret = dpaa_fm_deconfig(dpaa_intf, dev->process_private);
+ if (ret) {
+ DPAA_PMD_WARN("%s: FM deconfig failed(%d)",
+ dev->data->name, ret);
+ }
}
}
@@ -575,6 +577,23 @@ static int dpaa_eth_dev_close(struct rte_eth_dev *dev)
rte_free(dpaa_intf->fc_conf);
dpaa_intf->fc_conf = NULL;
+ /** For FMCLESS mode of share MAC, deconfig FM to direct
+ * ingress traffic to kernel before fq shutdown.
+ */
+ if (!(default_q || fmc_q)) {
+ ret = dpaa_fm_deconfig(dpaa_intf, dev->process_private);
+ if (ret) {
+ DPAA_PMD_WARN("%s: FM deconfig failed(%d)",
+ dev->data->name, ret);
+ }
+ }
+ if (fif->num_profiles) {
+ ret = dpaa_port_vsp_cleanup(dpaa_intf, fif);
+ if (ret) {
+ DPAA_PMD_WARN("%s: cleanup VSP failed(%d)",
+ dev->data->name, ret);
+ }
+ }
/** Release congestion Groups after releasing FQIDs*/
/* Release RX congestion Groups */
if (dpaa_intf->cgr_rx) {
@@ -647,12 +666,10 @@ static int dpaa_eth_dev_close(struct rte_eth_dev *dev)
rte_free(dpaa_intf->tx_conf_queues);
dpaa_intf->tx_conf_queues = NULL;
- if (dpaa_intf->port_handle) {
- ret = dpaa_fm_deconfig(dpaa_intf, fif);
- if (ret) {
- DPAA_PMD_WARN("%s: FM deconfig failed(%d)",
- dev->data->name, ret);
- }
+ ret = dpaa_fm_deconfig(dpaa_intf, fif);
+ if (ret) {
+ DPAA_PMD_WARN("%s: FM deconfig failed(%d)",
+ dev->data->name, ret);
}
if (fif->num_profiles) {
ret = dpaa_port_vsp_cleanup(dpaa_intf, fif);
diff --git a/drivers/net/dpaa/dpaa_flow.c b/drivers/net/dpaa/dpaa_flow.c
index f21950f64d..bfe294d21d 100644
--- a/drivers/net/dpaa/dpaa_flow.c
+++ b/drivers/net/dpaa/dpaa_flow.c
@@ -728,6 +728,9 @@ int dpaa_fm_deconfig(struct dpaa_if *dpaa_intf,
PMD_INIT_FUNC_TRACE();
+ if (!dpaa_intf->port_handle)
+ return 0;
+
/* FM PORT Disable */
ret = fm_port_disable(dpaa_intf->port_handle);
if (ret != E_OK) {
@@ -787,10 +790,8 @@ int dpaa_fm_config(struct rte_eth_dev *dev, uint64_t req_dist_set)
unsigned int i = 0;
PMD_INIT_FUNC_TRACE();
- if (dpaa_intf->port_handle) {
- if (dpaa_fm_deconfig(dpaa_intf, fif))
- DPAA_PMD_ERR("DPAA FM deconfig failed");
- }
+ if (dpaa_fm_deconfig(dpaa_intf, fif))
+ DPAA_PMD_ERR("DPAA FM deconfig failed");
if (!dev->data->nb_rx_queues)
return 0;
--
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