* 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
* [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
* [PATCH 11/18] net/dpaa: remove redundant FQ shutdown from Rx queue setup
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>
Remove the redundant qman_shutdown_fq() call from
dpaa_eth_rx_queue_setup(). The FQ is shut down during device stop,
so calling it again at queue setup time is unnecessary and may
interfere with a clean queue initialization.
Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com>
---
drivers/net/dpaa/dpaa_ethdev.c | 3 ---
1 file changed, 3 deletions(-)
diff --git a/drivers/net/dpaa/dpaa_ethdev.c b/drivers/net/dpaa/dpaa_ethdev.c
index b427b1df13..3b66fbe18a 100644
--- a/drivers/net/dpaa/dpaa_ethdev.c
+++ b/drivers/net/dpaa/dpaa_ethdev.c
@@ -1157,9 +1157,6 @@ int dpaa_eth_rx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx,
DPAA_PMD_INFO("Rx queue setup for queue index: %d fq_id (0x%x)",
queue_idx, rxq->fqid);
- /* Shutdown FQ before configure */
- qman_shutdown_fq(rxq->fqid);
-
if (!fif->num_profiles) {
if (dpaa_intf->bp_info && dpaa_intf->bp_info->bp &&
dpaa_intf->bp_info->mp != mp) {
--
2.25.1
^ permalink raw reply related
* [PATCH 11/18] net/dpaa: remove redundant FQ shutdown from rx_queue_setup
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>
Remove the redundant qman_shutdown_fq() call from dpaa_eth_rx_queue_setup().
The FQ is shut down during device stop, so calling it again at queue setup
time is unnecessary and may interfere with a clean queue initialization.
Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com>
---
drivers/net/dpaa/dpaa_ethdev.c | 3 ---
1 file changed, 3 deletions(-)
diff --git a/drivers/net/dpaa/dpaa_ethdev.c b/drivers/net/dpaa/dpaa_ethdev.c
index b427b1df13..3b66fbe18a 100644
--- a/drivers/net/dpaa/dpaa_ethdev.c
+++ b/drivers/net/dpaa/dpaa_ethdev.c
@@ -1157,9 +1157,6 @@ int dpaa_eth_rx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx,
DPAA_PMD_INFO("Rx queue setup for queue index: %d fq_id (0x%x)",
queue_idx, rxq->fqid);
- /* Shutdown FQ before configure */
- qman_shutdown_fq(rxq->fqid);
-
if (!fif->num_profiles) {
if (dpaa_intf->bp_info && dpaa_intf->bp_info->bp &&
dpaa_intf->bp_info->mp != mp) {
--
2.25.1
^ permalink raw reply related
* [PATCH 10/18] net/dpaa: clean Tx confirmation FQ on device stop
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>
Ensure the Tx confirmation FQ is also cleaned up during device
stop, preventing stale FQ state on subsequent device restarts.
Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com>
---
drivers/net/dpaa/dpaa_ethdev.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/drivers/net/dpaa/dpaa_ethdev.c b/drivers/net/dpaa/dpaa_ethdev.c
index e1856580b9..b427b1df13 100644
--- a/drivers/net/dpaa/dpaa_ethdev.c
+++ b/drivers/net/dpaa/dpaa_ethdev.c
@@ -573,6 +573,7 @@ static int dpaa_eth_dev_close(struct rte_eth_dev *dev)
/* release configuration memory */
rte_free(dpaa_intf->fc_conf);
+ dpaa_intf->fc_conf = NULL;
/** Release congestion Groups after releasing FQIDs*/
/* Release RX congestion Groups */
@@ -642,6 +643,10 @@ static int dpaa_eth_dev_close(struct rte_eth_dev *dev)
rte_free(dpaa_intf->tx_queues);
dpaa_intf->tx_queues = NULL;
+
+ 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) {
@@ -2537,6 +2542,8 @@ dpaa_dev_init(struct rte_eth_dev *eth_dev)
return 0;
free_tx:
+ rte_free(dpaa_intf->tx_conf_queues);
+ dpaa_intf->tx_conf_queues= NULL;
rte_free(dpaa_intf->tx_queues);
dpaa_intf->tx_queues = NULL;
dpaa_intf->nb_tx_queues = 0;
--
2.25.1
^ permalink raw reply related
* [PATCH 10/18] net/dpaa: clean tx_conf_fq on device stop
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>
Ensure the Tx confirmation FQ is also cleaned up during device
stop, preventing stale FQ state on subsequent device restarts.
Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com>
---
drivers/net/dpaa/dpaa_ethdev.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/drivers/net/dpaa/dpaa_ethdev.c b/drivers/net/dpaa/dpaa_ethdev.c
index e1856580b9..b427b1df13 100644
--- a/drivers/net/dpaa/dpaa_ethdev.c
+++ b/drivers/net/dpaa/dpaa_ethdev.c
@@ -573,6 +573,7 @@ static int dpaa_eth_dev_close(struct rte_eth_dev *dev)
/* release configuration memory */
rte_free(dpaa_intf->fc_conf);
+ dpaa_intf->fc_conf = NULL;
/** Release congestion Groups after releasing FQIDs*/
/* Release RX congestion Groups */
@@ -642,6 +643,10 @@ static int dpaa_eth_dev_close(struct rte_eth_dev *dev)
rte_free(dpaa_intf->tx_queues);
dpaa_intf->tx_queues = NULL;
+
+ 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) {
@@ -2537,6 +2542,8 @@ dpaa_dev_init(struct rte_eth_dev *eth_dev)
return 0;
free_tx:
+ rte_free(dpaa_intf->tx_conf_queues);
+ dpaa_intf->tx_conf_queues= NULL;
rte_free(dpaa_intf->tx_queues);
dpaa_intf->tx_queues = NULL;
dpaa_intf->nb_tx_queues = 0;
--
2.25.1
^ permalink raw reply related
* [PATCH 09/18] drivers: add DPAA cgrid cleanup support
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>
Add qman_find_fq_by_cgid() to find frame queues associated with
a given CGID. This allows the driver to verify that all FQs
using a CGR are shut down before releasing the CGR ID, preventing
use-after-free of CGR resources.
Signed-off-by: Jun Yang <jun.yang@nxp.com>
Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com>
---
drivers/bus/dpaa/dpaa_bus_base_symbols.c | 1 +
drivers/bus/dpaa/include/fsl_qman.h | 3 +++
drivers/net/dpaa/dpaa_ethdev.c | 29 ++++++++++++++++++++++--
3 files changed, 31 insertions(+), 2 deletions(-)
diff --git a/drivers/bus/dpaa/dpaa_bus_base_symbols.c b/drivers/bus/dpaa/dpaa_bus_base_symbols.c
index 52abec2b4c..514ab7b1f1 100644
--- a/drivers/bus/dpaa/dpaa_bus_base_symbols.c
+++ b/drivers/bus/dpaa/dpaa_bus_base_symbols.c
@@ -56,6 +56,7 @@ RTE_EXPORT_INTERNAL_SYMBOL(qman_reserve_fqid_range)
RTE_EXPORT_INTERNAL_SYMBOL(qman_alloc_pool_range)
RTE_EXPORT_INTERNAL_SYMBOL(qman_alloc_cgrid_range)
RTE_EXPORT_INTERNAL_SYMBOL(qman_release_cgrid_range)
+RTE_EXPORT_INTERNAL_SYMBOL(qman_find_fq_by_cgrid)
RTE_EXPORT_INTERNAL_SYMBOL(dpaa_intr_enable)
RTE_EXPORT_INTERNAL_SYMBOL(dpaa_intr_disable)
RTE_EXPORT_INTERNAL_SYMBOL(dpaa_get_ioctl_version_number)
diff --git a/drivers/bus/dpaa/include/fsl_qman.h b/drivers/bus/dpaa/include/fsl_qman.h
index bd46207232..20321ed355 100644
--- a/drivers/bus/dpaa/include/fsl_qman.h
+++ b/drivers/bus/dpaa/include/fsl_qman.h
@@ -1907,6 +1907,9 @@ static inline int qman_shutdown_fq_by_fqid(u32 fqid)
return qman_shutdown_fq(&fq);
}
+__rte_internal
+int qman_find_fq_by_cgrid(u32 cgrid, u32 *fqid);
+
/**
* qman_reserve_fqid_range - Reserve the specified range of frame queue IDs
* @fqid: the base FQID of the range to deallocate
diff --git a/drivers/net/dpaa/dpaa_ethdev.c b/drivers/net/dpaa/dpaa_ethdev.c
index 1615cf3892..e1856580b9 100644
--- a/drivers/net/dpaa/dpaa_ethdev.c
+++ b/drivers/net/dpaa/dpaa_ethdev.c
@@ -511,7 +511,7 @@ static int dpaa_eth_dev_close(struct rte_eth_dev *dev)
struct rte_eth_link *link = &dev->data->dev_link;
struct dpaa_if *dpaa_intf = dev->data->dev_private;
struct qman_fq *fq;
- int loop;
+ uint32_t fqid, loop;
int ret;
PMD_INIT_FUNC_TRACE();
@@ -574,28 +574,53 @@ static int dpaa_eth_dev_close(struct rte_eth_dev *dev)
/* release configuration memory */
rte_free(dpaa_intf->fc_conf);
+ /** Release congestion Groups after releasing FQIDs*/
/* Release RX congestion Groups */
if (dpaa_intf->cgr_rx) {
for (loop = 0; loop < dpaa_intf->nb_rx_queues; loop++) {
+ ret = qman_find_fq_by_cgrid(dpaa_intf->cgr_rx[loop].cgrid, &fqid);
+ if (!ret) {
+ /** Should be FQ not cleaned in previous program.*/
+ DPAA_PMD_DEBUG("FQ(fqid=0x%x) with rx cgid=%d is still alive?",
+ fqid, dpaa_intf->cgr_rx[loop].cgrid);
+ ret = qman_shutdown_fq_by_fqid(fqid);
+ if (ret) {
+ DPAA_PMD_WARN("Failed(%d) to shutdown fq(fqid=0x%x)",
+ ret, fqid);
+ }
+ }
ret = qman_delete_cgr(&dpaa_intf->cgr_rx[loop]);
if (ret) {
DPAA_PMD_WARN("%s: delete rxq%d's cgr err(%d)",
dev->data->name, loop, ret);
}
}
+ qman_release_cgrid_range(dpaa_intf->cgr_rx[0].cgrid, dpaa_intf->nb_rx_queues);
rte_free(dpaa_intf->cgr_rx);
dpaa_intf->cgr_rx = NULL;
}
/* Release TX congestion Groups */
if (dpaa_intf->cgr_tx) {
- for (loop = 0; loop < MAX_DPAA_CORES; loop++) {
+ for (loop = 0; loop < dpaa_intf->nb_tx_queues; loop++) {
+ ret = qman_find_fq_by_cgrid(dpaa_intf->cgr_tx[loop].cgrid, &fqid);
+ if (!ret) {
+ /** Should be FQ not cleaned in previous program.*/
+ DPAA_PMD_DEBUG("FQ(fqid=0x%x) with tx cgid=%d is still alive?",
+ fqid, dpaa_intf->cgr_tx[loop].cgrid);
+ ret = qman_shutdown_fq_by_fqid(fqid);
+ if (ret) {
+ DPAA_PMD_WARN("Failed(%d) to shutdown fq(fqid=0x%x)",
+ ret, fqid);
+ }
+ }
ret = qman_delete_cgr(&dpaa_intf->cgr_tx[loop]);
if (ret) {
DPAA_PMD_WARN("%s: delete txq%d's cgr err(%d)",
dev->data->name, loop, ret);
}
}
+ qman_release_cgrid_range(dpaa_intf->cgr_tx[0].cgrid, dpaa_intf->nb_tx_queues);
rte_free(dpaa_intf->cgr_tx);
dpaa_intf->cgr_tx = NULL;
}
--
2.25.1
^ permalink raw reply related
* [PATCH 09/18] bus/dpaa: add cgrid cleanup support
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>
Add qman_find_fq_by_cgid() to find frame queues associated with
a given CGID. This allows the driver to verify that all FQs
using a CGR are shut down before releasing the CGR ID, preventing
use-after-free of CGR resources.
Signed-off-by: Jun Yang <jun.yang@nxp.com>
Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com>
---
drivers/bus/dpaa/dpaa_bus_base_symbols.c | 1 +
drivers/bus/dpaa/include/fsl_qman.h | 3 +++
drivers/net/dpaa/dpaa_ethdev.c | 29 ++++++++++++++++++++++--
3 files changed, 31 insertions(+), 2 deletions(-)
diff --git a/drivers/bus/dpaa/dpaa_bus_base_symbols.c b/drivers/bus/dpaa/dpaa_bus_base_symbols.c
index 52abec2b4c..514ab7b1f1 100644
--- a/drivers/bus/dpaa/dpaa_bus_base_symbols.c
+++ b/drivers/bus/dpaa/dpaa_bus_base_symbols.c
@@ -56,6 +56,7 @@ RTE_EXPORT_INTERNAL_SYMBOL(qman_reserve_fqid_range)
RTE_EXPORT_INTERNAL_SYMBOL(qman_alloc_pool_range)
RTE_EXPORT_INTERNAL_SYMBOL(qman_alloc_cgrid_range)
RTE_EXPORT_INTERNAL_SYMBOL(qman_release_cgrid_range)
+RTE_EXPORT_INTERNAL_SYMBOL(qman_find_fq_by_cgrid)
RTE_EXPORT_INTERNAL_SYMBOL(dpaa_intr_enable)
RTE_EXPORT_INTERNAL_SYMBOL(dpaa_intr_disable)
RTE_EXPORT_INTERNAL_SYMBOL(dpaa_get_ioctl_version_number)
diff --git a/drivers/bus/dpaa/include/fsl_qman.h b/drivers/bus/dpaa/include/fsl_qman.h
index bd46207232..20321ed355 100644
--- a/drivers/bus/dpaa/include/fsl_qman.h
+++ b/drivers/bus/dpaa/include/fsl_qman.h
@@ -1907,6 +1907,9 @@ static inline int qman_shutdown_fq_by_fqid(u32 fqid)
return qman_shutdown_fq(&fq);
}
+__rte_internal
+int qman_find_fq_by_cgrid(u32 cgrid, u32 *fqid);
+
/**
* qman_reserve_fqid_range - Reserve the specified range of frame queue IDs
* @fqid: the base FQID of the range to deallocate
diff --git a/drivers/net/dpaa/dpaa_ethdev.c b/drivers/net/dpaa/dpaa_ethdev.c
index 1615cf3892..e1856580b9 100644
--- a/drivers/net/dpaa/dpaa_ethdev.c
+++ b/drivers/net/dpaa/dpaa_ethdev.c
@@ -511,7 +511,7 @@ static int dpaa_eth_dev_close(struct rte_eth_dev *dev)
struct rte_eth_link *link = &dev->data->dev_link;
struct dpaa_if *dpaa_intf = dev->data->dev_private;
struct qman_fq *fq;
- int loop;
+ uint32_t fqid, loop;
int ret;
PMD_INIT_FUNC_TRACE();
@@ -574,28 +574,53 @@ static int dpaa_eth_dev_close(struct rte_eth_dev *dev)
/* release configuration memory */
rte_free(dpaa_intf->fc_conf);
+ /** Release congestion Groups after releasing FQIDs*/
/* Release RX congestion Groups */
if (dpaa_intf->cgr_rx) {
for (loop = 0; loop < dpaa_intf->nb_rx_queues; loop++) {
+ ret = qman_find_fq_by_cgrid(dpaa_intf->cgr_rx[loop].cgrid, &fqid);
+ if (!ret) {
+ /** Should be FQ not cleaned in previous program.*/
+ DPAA_PMD_DEBUG("FQ(fqid=0x%x) with rx cgid=%d is still alive?",
+ fqid, dpaa_intf->cgr_rx[loop].cgrid);
+ ret = qman_shutdown_fq_by_fqid(fqid);
+ if (ret) {
+ DPAA_PMD_WARN("Failed(%d) to shutdown fq(fqid=0x%x)",
+ ret, fqid);
+ }
+ }
ret = qman_delete_cgr(&dpaa_intf->cgr_rx[loop]);
if (ret) {
DPAA_PMD_WARN("%s: delete rxq%d's cgr err(%d)",
dev->data->name, loop, ret);
}
}
+ qman_release_cgrid_range(dpaa_intf->cgr_rx[0].cgrid, dpaa_intf->nb_rx_queues);
rte_free(dpaa_intf->cgr_rx);
dpaa_intf->cgr_rx = NULL;
}
/* Release TX congestion Groups */
if (dpaa_intf->cgr_tx) {
- for (loop = 0; loop < MAX_DPAA_CORES; loop++) {
+ for (loop = 0; loop < dpaa_intf->nb_tx_queues; loop++) {
+ ret = qman_find_fq_by_cgrid(dpaa_intf->cgr_tx[loop].cgrid, &fqid);
+ if (!ret) {
+ /** Should be FQ not cleaned in previous program.*/
+ DPAA_PMD_DEBUG("FQ(fqid=0x%x) with tx cgid=%d is still alive?",
+ fqid, dpaa_intf->cgr_tx[loop].cgrid);
+ ret = qman_shutdown_fq_by_fqid(fqid);
+ if (ret) {
+ DPAA_PMD_WARN("Failed(%d) to shutdown fq(fqid=0x%x)",
+ ret, fqid);
+ }
+ }
ret = qman_delete_cgr(&dpaa_intf->cgr_tx[loop]);
if (ret) {
DPAA_PMD_WARN("%s: delete txq%d's cgr err(%d)",
dev->data->name, loop, ret);
}
}
+ qman_release_cgrid_range(dpaa_intf->cgr_tx[0].cgrid, dpaa_intf->nb_tx_queues);
rte_free(dpaa_intf->cgr_tx);
dpaa_intf->cgr_tx = NULL;
}
--
2.25.1
^ permalink raw reply related
* [PATCH 08/18] bus/dpaa: enhance DPAA FQ shutdown
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>
Improve the FQ shutdown sequence to handle edge cases more
robustly, including better handling of ORL (Order Restoration
List) presence and improved error recovery paths.
Signed-off-by: Gagandeep Singh <g.singh@nxp.com>
---
drivers/bus/dpaa/base/qbman/qman.c | 79 ++++++++++++++++++++++--------
1 file changed, 59 insertions(+), 20 deletions(-)
diff --git a/drivers/bus/dpaa/base/qbman/qman.c b/drivers/bus/dpaa/base/qbman/qman.c
index 9d2ca25f0e..9832c0be24 100644
--- a/drivers/bus/dpaa/base/qbman/qman.c
+++ b/drivers/bus/dpaa/base/qbman/qman.c
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
*
* Copyright 2008-2016 Freescale Semiconductor Inc.
- * Copyright 2017,2019-2025 NXP
+ * Copyright 2017,2019-2026 NXP
*
*/
@@ -2843,9 +2843,10 @@ qman_shutdown_fq(struct qman_fq *fq)
}
res = mcr->result; /* Make a copy as we reuse MCR below */
- if (res == QM_MCR_RESULT_OK) {
+ if (res == QM_MCR_RESULT_OK)
drain_mr_fqrni(&p->p);
- } else if (res == QM_MCR_RESULT_PENDING) {
+
+ if (res == QM_MCR_RESULT_PENDING) {
/*
* Need to wait for the FQRN in the message ring, which
* will only occur once the FQ has been drained. In
@@ -2853,27 +2854,29 @@ qman_shutdown_fq(struct qman_fq *fq)
* to dequeue from the channel the FQ is scheduled on
*/
int found_fqrn = 0;
- const u16 pool_ch_start = dpaa_get_qm_channel_pool();
- const u16 pool_ch_end = pool_ch_start + dpaa_get_qm_channel_pool_num();
- u32 sdqcr = p->sdqcr;
/* Flag that we need to drain FQ */
drain = 1;
+ const u16 pool_ch_start = dpaa_get_qm_channel_pool();
+ const u16 pool_ch_end = pool_ch_start +
+ dpaa_get_qm_channel_pool_num();
if (channel >= pool_ch_start && channel < pool_ch_end) {
- /* Pool channel, enable the bit in the portal */
+ /* Pool channel - must use affine portal */
if (p->config->channel != channel) {
- DPAA_BUS_ERR("Portal affine channel(0x%04x) != wq channel(0x%04x)",
+ DPAA_BUS_ERR("Portal ch(0x%04x) != FQ ch(0x%04x)",
p->config->channel, channel);
ret = -EINVAL;
goto out;
}
} else if (channel < pool_ch_start) {
/* Dedicated channel */
- sdqcr = QM_SDQCR_TYPE_ACTIVE | QM_SDQCR_CHANNELS_DEDICATED;
- qm_dqrr_sdqcr_set(&p->p, sdqcr);
+ qm_dqrr_sdqcr_set(&p->p,
+ QM_SDQCR_TYPE_ACTIVE |
+ QM_SDQCR_CHANNELS_DEDICATED);
} else {
- DPAA_BUS_ERR("Can't recover FQ 0x%x, Invalid channel: 0x%x", fqid, channel);
+ DPAA_BUS_ERR("Invalid channel 0x%x for FQ 0x%x",
+ channel, fqid);
ret = -EBUSY;
goto out;
}
@@ -2881,15 +2884,16 @@ qman_shutdown_fq(struct qman_fq *fq)
/* Keep draining DQRR while checking the MR*/
qm_dqrr_drain_nomatch(&p->p);
/* Process message ring too */
- found_fqrn = qm_mr_drain(&p->p,
- FQRN);
+ found_fqrn = qm_mr_drain(&p->p, FQRN);
cpu_relax();
} while (!found_fqrn);
- /* Restore SDQCR */
- if (sdqcr != p->sdqcr)
- qm_dqrr_sdqcr_set(&p->p, p->sdqcr);
- } else {
- DPAA_BUS_ERR("retire_fq failed: FQ 0x%x, res=0x%x", fqid, res);
+ qm_dqrr_sdqcr_set(&p->p, p->sdqcr);
+
+ }
+ if (res != QM_MCR_RESULT_OK &&
+ res != QM_MCR_RESULT_PENDING) {
+ DPAA_BUS_ERR("retire_fq failed: FQ 0x%x, res=0x%x",
+ fqid, res);
ret = -EIO;
goto out;
}
@@ -2932,7 +2936,7 @@ qman_shutdown_fq(struct qman_fq *fq)
if (mcr->result != QM_MCR_RESULT_OK) {
DPAA_BUS_ERR("OOS after drain fail: FQ 0x%x (0x%x)",
- fqid, mcr->result);
+ fqid, mcr->result);
ret = -EIO;
goto out;
}
@@ -2951,7 +2955,7 @@ qman_shutdown_fq(struct qman_fq *fq)
if (mcr->result != QM_MCR_RESULT_OK) {
DPAA_BUS_ERR("OOS fail: FQ 0x%x (0x%x)",
- fqid, mcr->result);
+ fqid, mcr->result);
ret = -EIO;
goto out;
}
@@ -2968,3 +2972,38 @@ qman_shutdown_fq(struct qman_fq *fq)
out:
return ret;
}
+
+int qman_find_fq_by_cgrid(u32 cgrid, u32 *fqid)
+{
+ struct qman_fq fq = {
+ .fqid = 1
+ };
+ struct qm_mcr_queryfq_np np;
+ struct qm_fqd fqd;
+ int err;
+
+ do {
+ err = qman_query_fq_np(&fq, &np);
+ if (err == -ERANGE) {
+ DPAA_BUS_INFO("No FQ found with cgrid(0x%x)", cgrid);
+ return err;
+ } else if (err) {
+ DPAA_BUS_WARN("Failed(%d) to Query np FQ(fqid=0x%x)", err, fq.fqid);
+ return err;
+ }
+ if ((np.state & QM_MCR_NP_STATE_MASK) != QM_MCR_NP_STATE_OOS) {
+ err = qman_query_fq(&fq, &fqd);
+ if (err) {
+ DPAA_BUS_WARN("Failed(%d) to Query FQ(fqid=0x%x)", err, fq.fqid);
+ } else if ((fqd.fq_ctrl & QM_FQCTRL_CGE) && fqd.cgid == cgrid) {
+ if (fqid)
+ *fqid = fq.fqid;
+ return 0;
+ }
+ }
+ /* Move to the next FQID */
+ fq.fqid++;
+ } while (1);
+
+ return -ENODEV;
+}
--
2.25.1
^ permalink raw reply related
* [PATCH 07/18] bus/dpaa: improve FQ shutdown with channel validation
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>
Fix hardcoded channel range check by using DTS-derived pool
channel start/end values. Add validation that the portal's
affine channel matches the FQ's channel for pool-channel FQs,
and only restore SDQCR when it was actually changed.
Signed-off-by: Jun Yang <jun.yang@nxp.com>
---
drivers/bus/dpaa/base/qbman/qman.c | 55 ++++++++++-------------
drivers/bus/dpaa/base/qbman/qman_driver.c | 29 ++++++++++--
drivers/bus/dpaa/dpaa_bus_base_symbols.c | 2 +
drivers/bus/dpaa/include/fsl_qman.h | 8 ++--
4 files changed, 54 insertions(+), 40 deletions(-)
diff --git a/drivers/bus/dpaa/base/qbman/qman.c b/drivers/bus/dpaa/base/qbman/qman.c
index 2315b81065..9d2ca25f0e 100644
--- a/drivers/bus/dpaa/base/qbman/qman.c
+++ b/drivers/bus/dpaa/base/qbman/qman.c
@@ -2792,7 +2792,7 @@ qman_shutdown_fq(struct qman_fq *fq)
int orl_empty, drain = 0, ret = 0;
u32 res, fqid = fq->fqid;
u8 state;
- u32 channel, wq;
+ u16 channel;
DPAA_BUS_DEBUG("In shutdown for queue = %x", fqid);
if (!p)
@@ -2806,9 +2806,10 @@ qman_shutdown_fq(struct qman_fq *fq)
ret = -ETIMEDOUT;
goto out;
}
+
state = mcr->queryfq_np.state & QM_MCR_NP_STATE_MASK;
if (state == QM_MCR_NP_STATE_OOS) {
- DPAA_BUS_ERR("Already in OOS");
+ DPAA_BUS_DEBUG("fqid(0x%x) Already in OOS", fqid);
goto out; /* Already OOS, no need to do anymore checks */
}
@@ -2824,7 +2825,6 @@ qman_shutdown_fq(struct qman_fq *fq)
/* Need to store these since the MCR gets reused */
channel = qm_fqd_get_chan(&mcr->queryfq.fqd);
- wq = qm_fqd_get_wq(&mcr->queryfq.fqd);
switch (state) {
case QM_MCR_NP_STATE_TEN_SCHED:
@@ -2843,10 +2843,9 @@ qman_shutdown_fq(struct qman_fq *fq)
}
res = mcr->result; /* Make a copy as we reuse MCR below */
- if (res == QM_MCR_RESULT_OK)
+ if (res == QM_MCR_RESULT_OK) {
drain_mr_fqrni(&p->p);
-
- if (res == QM_MCR_RESULT_PENDING) {
+ } else if (res == QM_MCR_RESULT_PENDING) {
/*
* Need to wait for the FQRN in the message ring, which
* will only occur once the FQ has been drained. In
@@ -2854,35 +2853,30 @@ qman_shutdown_fq(struct qman_fq *fq)
* to dequeue from the channel the FQ is scheduled on
*/
int found_fqrn = 0;
+ const u16 pool_ch_start = dpaa_get_qm_channel_pool();
+ const u16 pool_ch_end = pool_ch_start + dpaa_get_qm_channel_pool_num();
+ u32 sdqcr = p->sdqcr;
/* Flag that we need to drain FQ */
drain = 1;
- __maybe_unused u16 dequeue_wq = 0;
- if (channel >= qm_channel_pool1 &&
- channel < (u16)(qm_channel_pool1 + 15)) {
+ if (channel >= pool_ch_start && channel < pool_ch_end) {
/* Pool channel, enable the bit in the portal */
- dequeue_wq = (channel -
- qm_channel_pool1 + 1) << 4 | wq;
- } else if (channel < qm_channel_pool1) {
+ if (p->config->channel != channel) {
+ DPAA_BUS_ERR("Portal affine channel(0x%04x) != wq channel(0x%04x)",
+ p->config->channel, channel);
+ ret = -EINVAL;
+ goto out;
+ }
+ } else if (channel < pool_ch_start) {
/* Dedicated channel */
- dequeue_wq = wq;
+ sdqcr = QM_SDQCR_TYPE_ACTIVE | QM_SDQCR_CHANNELS_DEDICATED;
+ qm_dqrr_sdqcr_set(&p->p, sdqcr);
} else {
- DPAA_BUS_ERR("Can't recover FQ 0x%x, ch: 0x%x",
- fqid, channel);
+ DPAA_BUS_ERR("Can't recover FQ 0x%x, Invalid channel: 0x%x", fqid, channel);
ret = -EBUSY;
goto out;
}
- /* Set the sdqcr to drain this channel */
- if (channel < qm_channel_pool1)
- qm_dqrr_sdqcr_set(&p->p,
- QM_SDQCR_TYPE_ACTIVE |
- QM_SDQCR_CHANNELS_DEDICATED);
- else
- qm_dqrr_sdqcr_set(&p->p,
- QM_SDQCR_TYPE_ACTIVE |
- QM_SDQCR_CHANNELS_POOL_CONV
- (channel));
do {
/* Keep draining DQRR while checking the MR*/
qm_dqrr_drain_nomatch(&p->p);
@@ -2892,13 +2886,10 @@ qman_shutdown_fq(struct qman_fq *fq)
cpu_relax();
} while (!found_fqrn);
/* Restore SDQCR */
- qm_dqrr_sdqcr_set(&p->p,
- p->sdqcr);
- }
- if (res != QM_MCR_RESULT_OK &&
- res != QM_MCR_RESULT_PENDING) {
- DPAA_BUS_ERR("retire_fq failed: FQ 0x%x, res=0x%x",
- fqid, res);
+ if (sdqcr != p->sdqcr)
+ qm_dqrr_sdqcr_set(&p->p, p->sdqcr);
+ } else {
+ DPAA_BUS_ERR("retire_fq failed: FQ 0x%x, res=0x%x", fqid, res);
ret = -EIO;
goto out;
}
diff --git a/drivers/bus/dpaa/base/qbman/qman_driver.c b/drivers/bus/dpaa/base/qbman/qman_driver.c
index 45b094e0c6..51a360d36e 100644
--- a/drivers/bus/dpaa/base/qbman/qman_driver.c
+++ b/drivers/bus/dpaa/base/qbman/qman_driver.c
@@ -17,9 +17,10 @@
* where CCSR isn't available).
*/
u16 qman_ip_rev;
-u16 qm_channel_pool1 = QMAN_CHANNEL_POOL1;
-u16 qm_channel_caam = QMAN_CHANNEL_CAAM;
-u16 qm_channel_pme = QMAN_CHANNEL_PME;
+static u16 qm_channel_pool1 = QMAN_CHANNEL_POOL1;
+static u16 qm_channel_caam = QMAN_CHANNEL_CAAM;
+static u16 qm_channel_pme = QMAN_CHANNEL_PME;
+static u16 qm_channel_pool_num;
/* Ccsr map address to access ccsrbased register */
static void *qman_ccsr_map;
@@ -65,6 +66,11 @@ u16 dpaa_get_qm_channel_pool(void)
return qm_channel_pool1;
}
+u16 dpaa_get_qm_channel_pool_num(void)
+{
+ return qm_channel_pool_num;
+}
+
static int fsl_qman_portal_init(uint32_t index, int is_shared)
{
struct qman_portal *portal;
@@ -275,7 +281,7 @@ int qman_global_init(void)
uint64_t phys_addr;
uint64_t regs_size;
const u32 *clk;
-
+ u16 pool_channel;
static int done;
if (done)
@@ -336,6 +342,21 @@ int qman_global_init(void)
return -EINVAL;
}
+ if (lenp != sizeof(rte_be32_t) * 2) {
+ pr_err("pool-channel-range should have 2 items.\n");
+ return -EINVAL;
+ }
+ pool_channel = rte_be_to_cpu_32(chanid[0]);
+ qm_channel_pool_num = rte_be_to_cpu_32(chanid[1]);
+
+ if (pool_channel != qm_channel_pool1) {
+ pr_warn("Pool channel(%04x) configured != default(0x%04x)\n",
+ pool_channel, qm_channel_pool1);
+ }
+ qm_channel_pool1 = pool_channel;
+ pr_debug("Pool channel starts from 0x%04x, number=%d, lenp:%ld\n",
+ qm_channel_pool1, qm_channel_pool_num, lenp);
+
/* get ccsr base */
dt_node = of_find_compatible_node(NULL, NULL, "fsl,qman");
if (!dt_node) {
diff --git a/drivers/bus/dpaa/dpaa_bus_base_symbols.c b/drivers/bus/dpaa/dpaa_bus_base_symbols.c
index 522cdca27e..52abec2b4c 100644
--- a/drivers/bus/dpaa/dpaa_bus_base_symbols.c
+++ b/drivers/bus/dpaa/dpaa_bus_base_symbols.c
@@ -1,5 +1,6 @@
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright (c) 2025 Red Hat, Inc.
+ * Copyright 2026 NXP
*/
#include <eal_export.h>
@@ -94,6 +95,7 @@ RTE_EXPORT_INTERNAL_SYMBOL(qman_create_cgr)
RTE_EXPORT_INTERNAL_SYMBOL(qman_delete_cgr)
RTE_EXPORT_INTERNAL_SYMBOL(dpaa_get_qm_channel_caam)
RTE_EXPORT_INTERNAL_SYMBOL(dpaa_get_qm_channel_pool)
+RTE_EXPORT_INTERNAL_SYMBOL(dpaa_get_qm_channel_pool_num)
RTE_EXPORT_INTERNAL_SYMBOL(qman_thread_fd)
RTE_EXPORT_INTERNAL_SYMBOL(qman_thread_irq)
RTE_EXPORT_INTERNAL_SYMBOL(qman_fq_portal_thread_irq)
diff --git a/drivers/bus/dpaa/include/fsl_qman.h b/drivers/bus/dpaa/include/fsl_qman.h
index 673859ed2e..bd46207232 100644
--- a/drivers/bus/dpaa/include/fsl_qman.h
+++ b/drivers/bus/dpaa/include/fsl_qman.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
*
* Copyright 2008-2012 Freescale Semiconductor, Inc.
- * Copyright 2019-2022 NXP
+ * Copyright 2019-2022, 2026 NXP
*
*/
@@ -35,9 +35,6 @@ extern "C" {
#define QMAN_CHANNEL_POOL1_REV3 0x401
#define QMAN_CHANNEL_CAAM_REV3 0x840
#define QMAN_CHANNEL_PME_REV3 0x860
-extern u16 qm_channel_pool1;
-extern u16 qm_channel_caam;
-extern u16 qm_channel_pme;
enum qm_dc_portal {
qm_dc_portal_fman0 = 0,
qm_dc_portal_fman1 = 1,
@@ -51,6 +48,9 @@ u16 dpaa_get_qm_channel_caam(void);
__rte_internal
u16 dpaa_get_qm_channel_pool(void);
+__rte_internal
+u16 dpaa_get_qm_channel_pool_num(void);
+
/* Portal processing (interrupt) sources */
#define QM_PIRQ_CCSCI 0x00200000 /* CEETM Congestion State Change */
#define QM_PIRQ_CSCI 0x00100000 /* Congestion State Change */
--
2.25.1
^ permalink raw reply related
* [PATCH 06/18] drivers: shutdown DPAA FQ by fq descriptor
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>
Pass the full FQ descriptor to qman_shutdown_fq() instead of
just the fqid, so that channel-affine portals can be correctly
accessed when shutting down push-mode Rx queues.
Signed-off-by: Jun Yang <jun.yang@nxp.com>
---
drivers/bus/dpaa/base/qbman/qman.c | 9 +++++----
drivers/bus/dpaa/include/fsl_qman.h | 11 ++++++++++-
drivers/net/dpaa/dpaa_ethdev.c | 7 +++++++
3 files changed, 22 insertions(+), 5 deletions(-)
diff --git a/drivers/bus/dpaa/base/qbman/qman.c b/drivers/bus/dpaa/base/qbman/qman.c
index 931d487de4..2315b81065 100644
--- a/drivers/bus/dpaa/base/qbman/qman.c
+++ b/drivers/bus/dpaa/base/qbman/qman.c
@@ -2784,18 +2784,19 @@ qm_mc_result_timeout(struct qm_portal *portal,
RTE_EXPORT_INTERNAL_SYMBOL(qman_shutdown_fq)
int
-qman_shutdown_fq(u32 fqid)
+qman_shutdown_fq(struct qman_fq *fq)
{
- struct qman_portal *p;
+ struct qman_portal *p = fq->qp;
struct qm_mc_command *mcc;
struct qm_mc_result *mcr;
int orl_empty, drain = 0, ret = 0;
- u32 res;
+ u32 res, fqid = fq->fqid;
u8 state;
u32 channel, wq;
DPAA_BUS_DEBUG("In shutdown for queue = %x", fqid);
- p = get_affine_portal();
+ if (!p)
+ p = get_affine_portal();
/* Determine the state of the FQID */
mcc = qm_mc_start(&p->p);
mcc->queryfq_np.fqid = cpu_to_be32(fqid);
diff --git a/drivers/bus/dpaa/include/fsl_qman.h b/drivers/bus/dpaa/include/fsl_qman.h
index 82269cdf99..673859ed2e 100644
--- a/drivers/bus/dpaa/include/fsl_qman.h
+++ b/drivers/bus/dpaa/include/fsl_qman.h
@@ -1896,7 +1896,16 @@ static inline void qman_release_fqid(u32 fqid)
void qman_seed_fqid_range(u32 fqid, unsigned int count);
__rte_internal
-int qman_shutdown_fq(u32 fqid);
+int qman_shutdown_fq(struct qman_fq *fq);
+
+static inline int qman_shutdown_fq_by_fqid(u32 fqid)
+{
+ struct qman_fq fq;
+
+ memset(&fq, 0, sizeof(struct qman_fq));
+ fq.fqid = fqid;
+ return qman_shutdown_fq(&fq);
+}
/**
* qman_reserve_fqid_range - Reserve the specified range of frame queue IDs
diff --git a/drivers/net/dpaa/dpaa_ethdev.c b/drivers/net/dpaa/dpaa_ethdev.c
index 70d1e9acc3..1615cf3892 100644
--- a/drivers/net/dpaa/dpaa_ethdev.c
+++ b/drivers/net/dpaa/dpaa_ethdev.c
@@ -2363,6 +2363,13 @@ dpaa_dev_init(struct rte_eth_dev *eth_dev)
vsp_id = dev_vspids[loop];
+ /* Shutdown FQ before configure to clean the queue */
+ ret = qman_shutdown_fq_by_fqid(fqid);
+ if (ret < 0) {
+ DPAA_PMD_ERR("Failed shutdown %s:rxq-%d-fqid = 0x%08x",
+ dpaa_intf->name, loop, fqid);
+ }
+
if (dpaa_intf->cgr_rx)
dpaa_intf->cgr_rx[loop].cgrid = cgrid[loop];
--
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